framework update 4/29/2020
This commit is contained in:
parent
21fc655237
commit
60103dd1ce
62 changed files with 2931 additions and 2743 deletions
|
|
@ -76,12 +76,15 @@ Next, we update the buffer that describes the scene, which is used by the raster
|
||||||
memcpy(gInst, m_objInstance.data(), bufferSize);
|
memcpy(gInst, m_objInstance.data(), bufferSize);
|
||||||
m_alloc.unmap(stagingBuffer);
|
m_alloc.unmap(stagingBuffer);
|
||||||
// Copy staging buffer to the Scene Description buffer
|
// Copy staging buffer to the Scene Description buffer
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
|
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
|
||||||
m_debug.endLabel(cmdBuf);
|
m_debug.endLabel(cmdBuf);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
m_alloc.destroy(stagingBuffer);
|
m_alloc.destroy(stagingBuffer);
|
||||||
|
|
||||||
|
m_rtBuilder.updateTlasMatrices(m_tlas);
|
||||||
|
m_rtBuilder.updateBlas(2);
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
<script type="preformatted">
|
<script type="preformatted">
|
||||||
|
|
@ -114,10 +117,10 @@ they will still be at their original positions in the ray traced version. We wil
|
||||||
|
|
||||||
Since we want to update the transformation matrices in the TLAS, we need to keep some of the objects used to create it.
|
Since we want to update the transformation matrices in the TLAS, we need to keep some of the objects used to create it.
|
||||||
|
|
||||||
First, move the vector of `nvvkpp::RaytracingBuilder::Instance` objects from `HelloVulkan::createTopLevelAS()` to the
|
First, move the vector of `nvvk::RaytracingBuilder::Instance` objects from `HelloVulkan::createTopLevelAS()` to the
|
||||||
`HelloVulkan` class.
|
`HelloVulkan` class.
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
std::vector<nvvkpp::RaytracingBuilder::Instance> m_tlas;
|
std::vector<nvvk::RaytracingBuilder::Instance> m_tlas;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
Make sure to rename it to `m_tlas`, instead of `tlas`.
|
Make sure to rename it to `m_tlas`, instead of `tlas`.
|
||||||
|
|
@ -131,12 +134,12 @@ void HelloVulkan::createTopLevelAS()
|
||||||
m_tlas.reserve(m_objInstance.size());
|
m_tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilder::Instance rayInst;
|
nvvk::RaytracingBuilder::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = m_objInstance[i].hitgroup;
|
rayInst.hitGroupId = m_objInstance[i].hitgroup;
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV;
|
||||||
m_tlas.emplace_back(rayInst);
|
m_tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
|
m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
|
||||||
|
|
@ -145,12 +148,12 @@ void HelloVulkan::createTopLevelAS()
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
Back in `HelloVulkan::animationInstances()`, we need to copy the new computed transformation
|
Back in `HelloVulkan::animationInstances()`, we need to copy the new computed transformation
|
||||||
matrices to the vector of `nvvkpp::RaytracingBuilder::Instance` objects.
|
matrices to the vector of `nvvk::RaytracingBuilder::Instance` objects.
|
||||||
|
|
||||||
In the `for` loop, add at the end
|
In the `for` loop, add at the end
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
nvvkpp::RaytracingBuilder::Instance& tinst = m_tlas[wusonIdx];
|
nvvk::RaytracingBuilder::Instance& tinst = m_tlas[wusonIdx];
|
||||||
tinst.transform = inst.transform;
|
tinst.transform = inst.transform;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
@ -162,12 +165,12 @@ m_rtBuilder.updateTlasMatrices(m_tlas);
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## nvvkpp::RaytracingBuilder::updateTlasMatrices (Implementation)
|
## nvvk::RaytracingBuilder::updateTlasMatrices (Implementation)
|
||||||
|
|
||||||
We currently use `nvvkpp::RaytracingBuilder` to update the matrices for convenience, but
|
We currently use `nvvk::RaytracingBuilder` to update the matrices for convenience, but
|
||||||
this could be done more efficiently if one kept some of the buffer and memory references. Using a
|
this could be done more efficiently if one kept some of the buffer and memory references. Using a
|
||||||
memory allocator, such as the one described in the [Many Objects Tutorial](vkrt_tuto_instances.md.htm),
|
memory allocator, such as the one described in the [Many Objects Tutorial](vkrt_tuto_instances.md.htm),
|
||||||
could also be an alternative for avoiding multiple reallocations. Here's the implementation of `nvvkpp::RaytracingBuilder::updateTlasMatrices`.
|
could also be an alternative for avoiding multiple reallocations. Here's the implementation of `nvvk::RaytracingBuilder::updateTlasMatrices`.
|
||||||
|
|
||||||
### Staging Buffer
|
### Staging Buffer
|
||||||
|
|
||||||
|
|
@ -177,18 +180,18 @@ building the TLAS.
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
void updateTlasMatrices(const std::vector<Instance>& instances)
|
void updateTlasMatrices(const std::vector<Instance>& instances)
|
||||||
{
|
{
|
||||||
VkDeviceSize bufferSize = instances.size() * sizeof(vk::AccelerationStructureInstanceKHR);
|
VkDeviceSize bufferSize = instances.size() * sizeof(VkAccelerationStructureInstanceKHR);
|
||||||
// Create a staging buffer on the host to upload the new instance data
|
// Create a staging buffer on the host to upload the new instance data
|
||||||
nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc,
|
nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
#if defined(ALLOC_VMA)
|
#if defined(ALLOC_VMA)
|
||||||
VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU
|
VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU
|
||||||
#else
|
#else
|
||||||
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
// Copy the instance data into the staging buffer
|
// Copy the instance data into the staging buffer
|
||||||
auto* gInst = reinterpret_cast<vk::AccelerationStructureInstanceKHR*>(m_alloc.map(stagingBuffer));
|
auto* gInst = reinterpret_cast<VkAccelerationStructureInstanceKHR*>(m_alloc.map(stagingBuffer));
|
||||||
for(int i = 0; i < instances.size(); i++)
|
for(int i = 0; i < instances.size(); i++)
|
||||||
{
|
{
|
||||||
gInst[i] = instanceToVkGeometryInstanceKHR(instances[i]);
|
gInst[i] = instanceToVkGeometryInstanceKHR(instances[i]);
|
||||||
|
|
@ -201,16 +204,23 @@ Building the TLAS always needs scratch memory, and so we need to request it. If
|
||||||
we hadn't set the `eAllowUpdate` flag, the returned size would be zero and the rest of the code
|
we hadn't set the `eAllowUpdate` flag, the returned size would be zero and the rest of the code
|
||||||
would fail.
|
would fail.
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// Compute the amount of scratch memory required by the AS builder to update the TLAS
|
// Compute the amount of scratch memory required by the AS builder to update
|
||||||
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
||||||
vk::AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch,
|
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
|
||||||
vk::AccelerationStructureBuildTypeKHR::eDevice, m_tlas.as.accel};
|
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR;
|
||||||
vk::DeviceSize scratchSize =
|
memoryRequirementsInfo.accelerationStructure = m_tlas.as.accel;
|
||||||
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
|
memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||||
// Allocate the scratch buffer
|
|
||||||
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR
|
VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
|
||||||
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
|
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
|
||||||
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer});
|
VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
|
||||||
|
|
||||||
|
// Allocate the scratch buffer
|
||||||
|
nvvkBuffer scratchBuffer =
|
||||||
|
m_alloc.createBuffer(scratchSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||||
|
VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||||
|
bufferInfo.buffer = scratchBuffer.buffer;
|
||||||
|
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
### Update the Buffer
|
### Update the Buffer
|
||||||
|
|
@ -218,19 +228,25 @@ In a new command buffer, we copy the staging buffer to the device buffer and
|
||||||
add a barrier to make sure the memory finishes copying before updating the TLAS.
|
add a barrier to make sure the memory finishes copying before updating the TLAS.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// Update the instance buffer on the device side and build the TLAS
|
// Update the instance buffer on the device side and build the TLAS
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
cmdBuf.copyBuffer(stagingBuffer.buffer, m_instBuffer.buffer, vk::BufferCopy(0, 0, bufferSize));
|
VkBufferCopy region{0, 0, bufferSize};
|
||||||
|
vkCmdCopyBuffer(cmdBuf, stagingBuffer.buffer, m_instBuffer.buffer, 1, ®ion);
|
||||||
|
|
||||||
vk::DeviceAddress instanceAddress = m_device.getBufferAddress(m_instBuffer.buffer);
|
//VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||||
|
bufferInfo.buffer = m_instBuffer.buffer;
|
||||||
|
VkDeviceAddress instanceAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
|
||||||
|
|
||||||
// Make sure the copy of the instance buffer are copied before triggering the
|
|
||||||
// acceleration structure build
|
// Make sure the copy of the instance buffer are copied before triggering the
|
||||||
vk::MemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eAccelerationStructureWriteKHR);
|
// acceleration structure build
|
||||||
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
|
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
|
||||||
vk::DependencyFlags(), {barrier}, {}, {});
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
|
||||||
|
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
||||||
|
0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
### Update Acceleration Structure
|
### Update Acceleration Structure
|
||||||
|
|
@ -239,30 +255,36 @@ We update the TLAS using the same acceleration structure for source and
|
||||||
destination to update it in place, and using the VK_TRUE parameter to trigger the update.
|
destination to update it in place, and using the VK_TRUE parameter to trigger the update.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances};
|
VkAccelerationStructureGeometryDataKHR geometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
|
||||||
topASGeometry.geometry.instances.arrayOfPointers = VK_FALSE;
|
geometry.instances.arrayOfPointers = VK_FALSE;
|
||||||
topASGeometry.geometry.instances.data = instanceAddress;
|
geometry.instances.data.deviceAddress = instanceAddress;
|
||||||
const vk::AccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
|
VkAccelerationStructureGeometryKHR topASGeometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
|
||||||
|
topASGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||||
|
topASGeometry.geometry = geometry;
|
||||||
|
|
||||||
|
const VkAccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
|
||||||
|
|
||||||
vk::AccelerationStructureBuildGeometryInfoKHR topASInfo;
|
VkAccelerationStructureBuildGeometryInfoKHR topASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
|
||||||
topASInfo.setFlags(m_tlas.flags);
|
topASInfo.flags = m_tlas.flags;
|
||||||
topASInfo.setUpdate(VK_TRUE);
|
topASInfo.update = VK_TRUE;
|
||||||
topASInfo.setSrcAccelerationStructure(m_tlas.as.accel);
|
topASInfo.srcAccelerationStructure = m_tlas.as.accel;
|
||||||
topASInfo.setDstAccelerationStructure(m_tlas.as.accel);
|
topASInfo.dstAccelerationStructure = m_tlas.as.accel;
|
||||||
topASInfo.setGeometryArrayOfPointers(VK_FALSE);
|
topASInfo.geometryArrayOfPointers = VK_FALSE;
|
||||||
topASInfo.setGeometryCount(1);
|
topASInfo.geometryCount = 1;
|
||||||
topASInfo.setPpGeometries(&pGeometry);
|
topASInfo.ppGeometries = &pGeometry;
|
||||||
topASInfo.setScratchData(scratchAddress);
|
topASInfo.scratchData.deviceAddress = scratchAddress;
|
||||||
|
|
||||||
uint32_t nbInstances = (uint32_t)instances.size();
|
uint32_t nbInstances = (uint32_t)instances.size();
|
||||||
vk::AccelerationStructureBuildOffsetInfoKHR buildOffsetInfo = {nbInstances, 0, 0, 0};
|
VkAccelerationStructureBuildOffsetInfoKHR buildOffsetInfo = {nbInstances, 0, 0, 0};
|
||||||
const vk::AccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
|
const VkAccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
|
||||||
|
|
||||||
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
|
// Build the TLAS
|
||||||
// and the existing TLAS being passed and updated in place
|
|
||||||
cmdBuf.buildAccelerationStructureKHR(1, &topASInfo, &pBuildOffsetInfo);
|
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
// and the existing TLAS being passed and updated in place
|
||||||
|
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &topASInfo, &pBuildOffsetInfo);
|
||||||
|
|
||||||
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
### Cleanup
|
### Cleanup
|
||||||
|
|
@ -310,12 +332,12 @@ Add all of the following members to the `HelloVulkan` class:
|
||||||
void updateCompDescriptors(nvvkBuffer& vertex);
|
void updateCompDescriptors(nvvkBuffer& vertex);
|
||||||
void createCompPipelines();
|
void createCompPipelines();
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_compDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_compDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_compDescPool;
|
vk::DescriptorPool m_compDescPool;
|
||||||
vk::DescriptorSetLayout m_compDescSetLayout;
|
vk::DescriptorSetLayout m_compDescSetLayout;
|
||||||
vk::DescriptorSet m_compDescSet;
|
vk::DescriptorSet m_compDescSet;
|
||||||
vk::Pipeline m_compPipeline;
|
vk::Pipeline m_compPipeline;
|
||||||
vk::PipelineLayout m_compPipelineLayout;
|
vk::PipelineLayout m_compPipelineLayout;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
The compute shader will work on a single `VertexObj` buffer.
|
The compute shader will work on a single `VertexObj` buffer.
|
||||||
|
|
@ -323,12 +345,12 @@ The compute shader will work on a single `VertexObj` buffer.
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
void HelloVulkan::createCompDescriptors()
|
void HelloVulkan::createCompDescriptors()
|
||||||
{
|
{
|
||||||
m_compDescSetLayoutBind.emplace_back(vk::DescriptorSetLayoutBinding(
|
m_compDescSetLayoutBind.addBinding(vk::DescriptorSetLayoutBinding(
|
||||||
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
|
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
|
||||||
|
|
||||||
m_compDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_compDescSetLayoutBind);
|
m_compDescSetLayout = m_compDescSetLayoutBind.createLayout(m_device);
|
||||||
m_compDescPool = nvvkpp::util::createDescriptorPool(m_device, m_compDescSetLayoutBind, 1);
|
m_compDescPool = m_compDescSetLayoutBind.createPool(m_device, 1);
|
||||||
m_compDescSet = nvvkpp::util::createDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
|
m_compDescSet = nvvk::allocateDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
@ -339,8 +361,7 @@ void HelloVulkan::updateCompDescriptors(nvvkBuffer& vertex)
|
||||||
{
|
{
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_compDescSetLayoutBind.makeWrite(m_compDescSet, 0, dbiUnif));
|
||||||
nvvkpp::util::createWrite(m_compDescSet, m_compDescSetLayoutBind[0], &dbiUnif));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
@ -358,10 +379,10 @@ void HelloVulkan::createCompPipelines()
|
||||||
vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout};
|
vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout};
|
||||||
|
|
||||||
computePipelineCreateInfo.stage =
|
computePipelineCreateInfo.stage =
|
||||||
nvvkpp::util::loadShader(m_device,
|
nvvk::createShaderStageInfo(m_device,
|
||||||
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
|
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
|
||||||
vk::ShaderStageFlagBits::eCompute);
|
VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
m_compPipeline = m_device.createComputePipelines({}, computePipelineCreateInfo, nullptr)[0];
|
m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
|
||||||
m_device.destroy(computePipelineCreateInfo.stage.module);
|
m_device.destroy(computePipelineCreateInfo.stage.module);
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
@ -445,8 +466,8 @@ void HelloVulkan::animationObject(float time)
|
||||||
|
|
||||||
updateCompDescriptors(model.vertexBuffer);
|
updateCompDescriptors(model.vertexBuffer);
|
||||||
|
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
|
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
|
||||||
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0,
|
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0,
|
||||||
|
|
@ -454,7 +475,7 @@ void HelloVulkan::animationObject(float time)
|
||||||
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
|
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
|
||||||
&time);
|
&time);
|
||||||
cmdBuf.dispatch(model.nbVertices, 1, 1);
|
cmdBuf.dispatch(model.nbVertices, 1, 1);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
@ -478,7 +499,7 @@ In the rendering loop, after the call to `animationInstances`, call the object a
|
||||||
|
|
||||||
## Update BLAS
|
## Update BLAS
|
||||||
|
|
||||||
In `nvvkpp::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to update a BLAS whose vertex buffer was previously updated. This function is very similar to the one used for instances, but in this case, there is no buffer transfer to do.
|
In `nvvk::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to update a BLAS whose vertex buffer was previously updated. This function is very similar to the one used for instances, but in this case, there is no buffer transfer to do.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -488,57 +509,63 @@ In `nvvkpp::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to
|
||||||
{
|
{
|
||||||
Blas& blas = m_blas[blasIdx];
|
Blas& blas = m_blas[blasIdx];
|
||||||
|
|
||||||
// Compute the amount of scratch memory required by the AS builder to update the TLAS
|
// Compute the amount of scratch memory required by the AS builder to update the BLAS
|
||||||
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
||||||
vk::AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch,
|
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
|
||||||
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel};
|
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR;
|
||||||
vk::DeviceSize scratchSize =
|
memoryRequirementsInfo.accelerationStructure = blas.as.accel;
|
||||||
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
|
memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||||
|
|
||||||
|
VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
|
||||||
|
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
|
||||||
|
VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
|
||||||
|
|
||||||
// Allocate the scratch buffer
|
// Allocate the scratch buffer
|
||||||
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR
|
nvvkBuffer scratchBuffer =
|
||||||
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
|
m_alloc.createBuffer(scratchSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||||
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer});
|
VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||||
|
bufferInfo.buffer = scratchBuffer.buffer;
|
||||||
|
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
|
||||||
|
|
||||||
|
|
||||||
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
|
const VkAccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
|
||||||
vk::AccelerationStructureBuildGeometryInfoKHR asInfo{vk::AccelerationStructureTypeKHR::eBottomLevel};
|
VkAccelerationStructureBuildGeometryInfoKHR asInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
|
||||||
asInfo.setFlags(blas.flags);
|
asInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||||
asInfo.setUpdate(VK_TRUE);
|
asInfo.flags = blas.flags;
|
||||||
asInfo.setSrcAccelerationStructure(blas.as.accel);
|
asInfo.update = VK_TRUE;
|
||||||
asInfo.setDstAccelerationStructure(blas.as.accel);
|
asInfo.srcAccelerationStructure = blas.as.accel;
|
||||||
asInfo.setGeometryArrayOfPointers(VK_FALSE);
|
asInfo.dstAccelerationStructure = blas.as.accel;
|
||||||
asInfo.setGeometryCount((uint32_t)blas.asGeometry.size());
|
asInfo.geometryArrayOfPointers = VK_FALSE;
|
||||||
asInfo.setPpGeometries(&pGeometry);
|
asInfo.geometryCount = (uint32_t)blas.asGeometry.size();
|
||||||
asInfo.setScratchData(scratchAddress);
|
asInfo.ppGeometries = &pGeometry;
|
||||||
|
asInfo.scratchData.deviceAddress = scratchAddress;
|
||||||
|
|
||||||
|
std::vector<const VkAccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
|
||||||
std::vector<const vk::AccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
|
|
||||||
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
|
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
|
||||||
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
|
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
|
||||||
|
|
||||||
|
|
||||||
// Update the instance buffer on the device side and build the TLAS
|
// Update the instance buffer on the device side and build the TLAS
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
|
|
||||||
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
|
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
|
||||||
// and the existing BLAS being passed and updated in place
|
// and the existing BLAS being passed and updated in place
|
||||||
cmdBuf.buildAccelerationStructureKHR(asInfo, pBuildOffset);
|
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &asInfo, pBuildOffset.data());
|
||||||
|
|
||||||
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
|
||||||
m_alloc.destroy(scratchBuffer);
|
m_alloc.destroy(scratchBuffer);
|
||||||
}
|
}
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
The previous function (`updateBlas`) uses geometry information stored in `m_blas`.
|
The previous function (`updateBlas`) uses geometry information stored in `m_blas`.
|
||||||
To be able to re-use this information, we need to keep the structure of `nvvkpp::RaytracingBuilderKHR::Blas` objects
|
To be able to re-use this information, we need to keep the structure of `nvvk::RaytracingBuilderKHR::Blas` objects
|
||||||
used for its creation.
|
used for its creation.
|
||||||
|
|
||||||
Move the `nvvkpp::RaytracingBuilderKHR::Blas` vector from `HelloVulkan::createBottomLevelAS()` to the `HelloVulkan` class, renaming it to `m_blas`.
|
Move the `nvvk::RaytracingBuilderKHR::Blas` vector from `HelloVulkan::createBottomLevelAS()` to the `HelloVulkan` class, renaming it to `m_blas`.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> m_blas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> m_blas;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
As with the TLAS, the BLAS needs to allow updates. We will also enable the
|
As with the TLAS, the BLAS needs to allow updates. We will also enable the
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,8 @@ In `createRtPipeline()`, after loading `raytrace.rchit.spv`, load `raytrace.rahi
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
vk::ShaderModule ahitSM =
|
vk::ShaderModule ahitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
add the any hit shader to the hit group
|
add the any hit shader to the hit group
|
||||||
|
|
|
||||||
|
|
@ -65,30 +65,29 @@ In `HelloVulkan::createRtPipeline()`, immediately after adding the closest-hit s
|
||||||
3 callable shaders, for each type of light.
|
3 callable shaders, for each type of light.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// Callable shaders
|
// Callable shaders
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR callGroup{vk::RayTracingShaderGroupTypeKHR::eGeneral,
|
vk::RayTracingShaderGroupCreateInfoKHR callGroup{vk::RayTracingShaderGroupTypeKHR::eGeneral,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
||||||
|
|
||||||
vk::ShaderModule call0 =
|
vk::ShaderModule call0 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device,
|
||||||
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
|
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
|
||||||
vk::ShaderModule call1 =
|
vk::ShaderModule call1 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device,
|
||||||
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
|
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
|
||||||
vk::ShaderModule call2 =
|
vk::ShaderModule call2 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
|
||||||
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
|
|
||||||
|
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
|
||||||
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
m_rtShaderGroups.push_back(callGroup);
|
m_rtShaderGroups.push_back(callGroup);
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call1, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call1, "main"});
|
||||||
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
m_rtShaderGroups.push_back(callGroup);
|
m_rtShaderGroups.push_back(callGroup);
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call2, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call2, "main"});
|
||||||
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
m_rtShaderGroups.push_back(callGroup);
|
m_rtShaderGroups.push_back(callGroup);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
And at the end of the function, delete the shaders.
|
And at the end of the function, delete the shaders.
|
||||||
|
|
|
||||||
|
|
@ -117,13 +117,13 @@ Replace the definition of buffers and textures and include the right allocator.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(ALLOC_DEDICATED)
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#include "nvvk/allocator_dedicated_vk.hpp"
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
using nvvkBuffer = nvvk::BufferDedicated;
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
using nvvkTexture = nvvk::TextureDedicated;
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(ALLOC_DMA)
|
||||||
#include "nvvkpp/allocator_dma_vkpp.hpp"
|
#include "nvvk/allocator_dma_vk.hpp"
|
||||||
using nvvkBuffer = nvvkpp::BufferDma;
|
using nvvkBuffer = nvvk::BufferDma;
|
||||||
using nvvkTexture = nvvkpp::TextureDma;
|
using nvvkTexture = nvvk::TextureDma;
|
||||||
#endif
|
#endif
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
@ -131,10 +131,11 @@ And do the same for the allocator
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(ALLOC_DEDICATED)
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(ALLOC_DMA)
|
||||||
nvvkpp::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvk::DeviceMemoryAllocator m_dmaAllocator;
|
nvvk::DeviceMemoryAllocator m_memAllocator;
|
||||||
|
nvvk::StagingMemoryManagerDma m_staging;
|
||||||
#endif
|
#endif
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
@ -148,34 +149,24 @@ DMA needs to be initialized, which will be done in the `setup()` function:
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(ALLOC_DEDICATED)
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(ALLOC_DMA)
|
||||||
m_dmaAllocator.init(device, physicalDevice);
|
m_memAllocator.init(device, physicalDevice);
|
||||||
m_alloc.init(device, &m_dmaAllocator);
|
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true);
|
||||||
|
m_staging.init(m_memAllocator);
|
||||||
|
m_alloc.init(device, m_memAllocator, m_staging);
|
||||||
#endif
|
#endif
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
When using DMA, memory buffer mapping is done through the DMA interface (instead of the VKDevice). Therefore, change the lines at the end of `updateUniformBuffer()` to
|
When using DMA, memory buffer mapping is done through the DMA interface (instead of the VKDevice).
|
||||||
|
Therefore, change the lines at the end of `updateUniformBuffer()` to use the common allocator interface.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
#if defined(ALLOC_DEDICATED)
|
void* data = m_alloc.map(m_cameraMat);
|
||||||
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
|
memcpy(data, &ubo, sizeof(ubo));
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
m_alloc.unmap(m_cameraMat);
|
||||||
m_device.unmapMemory(m_cameraMat.allocation);
|
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
void* data = m_dmaAllocator.map(m_cameraMat.allocation);
|
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
|
||||||
m_dmaAllocator.unmap(m_cameraMat.allocation);
|
|
||||||
#endif
|
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
The RaytracerBuilder was made to allow various allocators, but we still need to pass the right one in its setup function. Change the last line of `initRayTracing()` to
|
The RaytracerBuilder was made to allow various allocators, therefore nothing to change in the call to `m_rtBuilder.setup()`
|
||||||
|
|
||||||
~~~~ C++
|
|
||||||
#if defined(ALLOC_DEDICATED)
|
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
m_rtBuilder.setup(m_device, m_dmaAllocator, m_graphicsQueueIndex);
|
|
||||||
#endif
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
## Destruction
|
## Destruction
|
||||||
|
|
||||||
|
|
@ -204,7 +195,7 @@ We can also modify the code to use the [Vulkan Memory Allocator](https://github.
|
||||||
|
|
||||||
Download [vk_mem_alloc.h](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/src/vk_mem_alloc.h) from GitHub and add this to the `shared_sources` folder.
|
Download [vk_mem_alloc.h](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/src/vk_mem_alloc.h) from GitHub and add this to the `shared_sources` folder.
|
||||||
|
|
||||||
There is already a variation of the allocator for VMA, which is located under [nvpro-samples](https://github.com/nvpro-samples/shared_sources/tree/master/nvvkpp). This allocator has the same simple interface as the `AllocatorDedicated` class in `allocator_dedicated_vkpp.hpp`, but will use VMA for memory management.
|
There is already a variation of the allocator for VMA, which is located under [nvpro-samples](https://github.com/nvpro-samples/shared_sources/tree/master/nvvk). This allocator has the same simple interface as the `AllocatorDedicated` class in `allocator_dedicated_vkpp.hpp`, but will use VMA for memory management.
|
||||||
|
|
||||||
VMA might use dedicated memory, which we do, so you need to add the following extension to the
|
VMA might use dedicated memory, which we do, so you need to add the following extension to the
|
||||||
creation of the context in `main.cpp`.
|
creation of the context in `main.cpp`.
|
||||||
|
|
@ -223,15 +214,16 @@ Follow the changes done before and add the following
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(ALLOC_VMA)
|
||||||
#include "nvvkpp/allocator_vma_vkpp.hpp"
|
#include "nvvk/allocator_vma_vk.hpp"
|
||||||
using nvvkBuffer = nvvkpp::BufferVma;
|
using nvvkBuffer = nvvk::BufferVma;
|
||||||
using nvvkTexture = nvvkpp::TextureVma;
|
using nvvkTexture = nvvk::TextureVma;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(ALLOC_VMA)
|
||||||
nvvkpp::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
VmaAllocator m_vmaAllocator;
|
nvvk::StagingMemoryManagerVma m_staging;
|
||||||
|
VmaAllocator m_memAllocator;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -247,21 +239,13 @@ In `setup()`
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(ALLOC_VMA)
|
||||||
VmaAllocatorCreateInfo allocatorInfo = {};
|
VmaAllocatorCreateInfo allocatorInfo = {};
|
||||||
|
allocatorInfo.instance = instance;
|
||||||
allocatorInfo.physicalDevice = physicalDevice;
|
allocatorInfo.physicalDevice = physicalDevice;
|
||||||
allocatorInfo.device = device;
|
allocatorInfo.device = device;
|
||||||
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||||
vmaCreateAllocator(&allocatorInfo, &m_vmaAllocator);
|
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
|
||||||
m_alloc.init(device, m_vmaAllocator);
|
m_staging.init(device, physicalDevice, m_memAllocator);
|
||||||
~~~~
|
m_alloc.init(device, m_memAllocator, m_staging);
|
||||||
|
|
||||||
In `updateUniformBuffer()`
|
|
||||||
|
|
||||||
~~~~ C++
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
void* data;
|
|
||||||
vmaMapMemory(m_vmaAllocator, m_cameraMat.allocation, &data);
|
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
|
||||||
vmaUnmapMemory(m_vmaAllocator, m_cameraMat.allocation);
|
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
In `destroyResources()`
|
In `destroyResources()`
|
||||||
|
|
@ -271,25 +255,6 @@ In `destroyResources()`
|
||||||
vmaDestroyAllocator(m_vmaAllocator);
|
vmaDestroyAllocator(m_vmaAllocator);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
In `initRayTracing()`
|
|
||||||
|
|
||||||
~~~~ C++
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
m_rtBuilder.setup(m_device, m_vmaAllocator, m_graphicsQueueIndex);
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
Additionally, VMA has its own usage flags, so since `VMA_MEMORY_USAGE_CPU_TO_GPU` maps to `vkMP::eHostVisible` and `vkMP::eHostCoherent`, change the call to `m_alloc.createBuffer` in `HelloVulkan::createUniformBuffer()` to
|
|
||||||
|
|
||||||
~~~~ C++
|
|
||||||
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
|
|
||||||
#if defined(ALLOC_DEDICATED) || defined(ALLOC_DMA)
|
|
||||||
vkMP::eHostVisible | vkMP::eHostCoherent
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
VMA_MEMORY_USAGE_CPU_TO_GPU
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
|
|
||||||
# Final Code
|
# Final Code
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ All the information will need to be hold in buffers, which will be available to
|
||||||
Finally, there are two functions, one to create the spheres, and one that will create the intermediate structure for the BLAS.
|
Finally, there are two functions, one to create the spheres, and one that will create the intermediate structure for the BLAS.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
void createSpheres();
|
void createSpheres();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
|
nvvk::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
The following implementation will create 2.000.000 spheres at random positions and radius. It will create the Aabb from the sphere definition, two materials which will be assigned alternatively to each object. All the created information will be moved to Vulkan buffers to be accessed by the intersection and closest shaders.
|
The following implementation will create 2.000.000 spheres at random positions and radius. It will create the Aabb from the sphere definition, two materials which will be assigned alternatively to each object. All the created information will be moved to Vulkan buffers to be accessed by the intersection and closest shaders.
|
||||||
|
|
@ -120,13 +120,13 @@ void HelloVulkan::createSpheres()
|
||||||
|
|
||||||
// Creating all buffers
|
// Creating all buffers
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
|
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
|
||||||
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs);
|
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress);
|
||||||
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
|
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
|
||||||
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
|
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
// Debug information
|
// Debug information
|
||||||
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
|
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
|
||||||
|
|
@ -153,7 +153,7 @@ What is changing compare to triangle primitive is the Aabb data (see Aabb struct
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Returning the ray tracing geometry used for the BLAS, containing all spheres
|
// Returning the ray tracing geometry used for the BLAS, containing all spheres
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
|
||||||
{
|
{
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
|
||||||
|
|
@ -181,7 +181,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -217,7 +217,7 @@ The function `createBottomLevelAS()` is creating a BLAS per OBJ, the following m
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -248,7 +248,7 @@ Just before building the TLAS, we need to add the following
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// Add the blas containing all spheres
|
// Add the blas containing all spheres
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilder::Instance rayInst;
|
nvvk::RaytracingBuilder::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[0].transform; // Position of the instance
|
rayInst.transform = m_objInstance[0].transform; // Position of the instance
|
||||||
rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
|
rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
|
||||||
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
|
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
@ -301,7 +301,7 @@ Then write the buffer for the spheres
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &dbiSpheres));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, dbiSpheres));
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
## Intersection Shader
|
## Intersection Shader
|
||||||
|
|
@ -313,13 +313,13 @@ Here is how the two hit group looks like:
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// Hit Group0 - Closest Hit
|
// Hit Group0 - Closest Hit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
{
|
{
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chitSM, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chitSM, "main"});
|
||||||
hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1));
|
hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
m_rtShaderGroups.push_back(hg);
|
m_rtShaderGroups.push_back(hg);
|
||||||
|
|
@ -327,15 +327,15 @@ Here is how the two hit group looks like:
|
||||||
|
|
||||||
// Hit Group1 - Closest Hit + Intersection (procedural)
|
// Hit Group1 - Closest Hit + Intersection (procedural)
|
||||||
vk::ShaderModule chit2SM =
|
vk::ShaderModule chit2SM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
||||||
vk::ShaderModule rintSM =
|
vk::ShaderModule rintSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
|
||||||
{
|
{
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chit2SM, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chit2SM, "main"});
|
||||||
hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1));
|
hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eIntersectionKHR, rintSM, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eIntersectionKHR, rintSM, "main"});
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@ This new shader needs to be added to the raytracing pipeline. So, in `createRtPi
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
vk::ShaderModule chit2SM =
|
vk::ShaderModule chit2SM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
Then add a new hit group group immediately after adding the first hit group:
|
Then add a new hit group group immediately after adding the first hit group:
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ Remove most functions and members to keep only what is need to create the accele
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
## hello_vulkan (source)
|
## hello_vulkan (source)
|
||||||
|
|
@ -61,10 +61,11 @@ m_descSetLayoutBind.emplace_back( //
|
||||||
In `HelloVulkan::updateDescriptorSet`, write the value to the descriptor set.
|
In `HelloVulkan::updateDescriptorSet`, write the value to the descriptor set.
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &descASInfo));
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, descASInfo));
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,14 @@ methods and functions. The sections are organized by components, with subsection
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
!!! Note GitHub repository
|
||||||
|
https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
<script type="preformatted">
|
<script type="preformatted">
|
||||||
This tutorial highlights the steps to add ray tracing to an existing Vulkan application, and assumes a working knowledge
|
This tutorial highlights the steps to add ray tracing to an existing Vulkan application, and assumes a working knowledge
|
||||||
of Vulkan in general. The code verbosity of classical components such as swapchain management, render passes etc. is
|
of Vulkan in general. The code verbosity of classical components such as swapchain management, render passes etc. is
|
||||||
reduced using [C++ API helpers](https://github.com/nvpro-samples/shared_sources/tree/master/nvvkpp) and
|
reduced using [C++ API helpers](https://github.com/nvpro-samples/shared_sources/tree/master/nvvk) and
|
||||||
NVIDIA's [nvpro-samples](https://github.com/nvpro-samples/build_all) framework. This framework contains many advanced
|
NVIDIA's [nvpro-samples](https://github.com/nvpro-samples/build_all) framework. This framework contains many advanced
|
||||||
examples and best practices for Vulkan and OpenGL. We also use a helper for the creation of the ray tracing acceleration
|
examples and best practices for Vulkan and OpenGL. We also use a helper for the creation of the ray tracing acceleration
|
||||||
structures, but we will document its contents extensively in this tutorial. The code is further simplified by using the
|
structures, but we will document its contents extensively in this tutorial. The code is further simplified by using the
|
||||||
|
|
@ -36,17 +39,15 @@ verbosity and its potential for errors.
|
||||||
|
|
||||||
## Beta Installation
|
## Beta Installation
|
||||||
|
|
||||||
If you are in the Beta period, install and compile all of the following
|
The SDK 1.2.135 and up which can be found under https://vulkan.lunarg.com/sdk/home will work with this project.
|
||||||
|
|
||||||
|
Nevertheless, if you are in the Beta period, it is suggested to install and compile all of the following and replace
|
||||||
|
with the current environment.
|
||||||
|
|
||||||
* Latest driver: https://developer.nvidia.com/vulkan-driver
|
* Latest driver: https://developer.nvidia.com/vulkan-driver
|
||||||
* Latest Vulkan headers: https://github.com/KhronosGroup/Vulkan-Headers
|
* Latest Vulkan headers: https://github.com/KhronosGroup/Vulkan-Headers
|
||||||
* Latest glslangValidator: https://github.com/KhronosGroup/glslang
|
* Latest glslangValidator: https://github.com/KhronosGroup/glslang
|
||||||
|
|
||||||
!!! Warning Beta
|
|
||||||
Copy/replace `glslangValidator.exe` in the VulkanSDK bin directory.<br>
|
|
||||||
Ex: `C:\VulkanSDK\1.2.131.1\Bin`
|
|
||||||
|
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
This tutorial is a modification of [`ray_tracing__before`](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing__before), which loads are render OBJ scenes with Vulkan rasterizer.
|
This tutorial is a modification of [`ray_tracing__before`](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing__before), which loads are render OBJ scenes with Vulkan rasterizer.
|
||||||
|
|
@ -83,6 +84,10 @@ The directory structure should be looking like:
|
||||||
!!! Warning Beta
|
!!! Warning Beta
|
||||||
Modify `VULKAN > VULKAN_HEADERS_OVERRIDE_INCLUDE_DIR` to the path to beta vulkan headers.
|
Modify `VULKAN > VULKAN_HEADERS_OVERRIDE_INCLUDE_DIR` to the path to beta vulkan headers.
|
||||||
|
|
||||||
|
!!! Tip Visual Assist
|
||||||
|
To get auto-completion, edit vulkan.hpp and change two places from:<br>
|
||||||
|
`namespace VULKAN_HPP_NAMESPACE` to `namespace vk`
|
||||||
|
|
||||||
The starting project is a simple framework allowing us to load OBJ files and rasterize them
|
The starting project is a simple framework allowing us to load OBJ files and rasterize them
|
||||||
using Vulkan.
|
using Vulkan.
|
||||||
|
|
||||||
|
|
@ -93,7 +98,7 @@ using Vulkan.
|
||||||
# Ray Tracing Setup
|
# Ray Tracing Setup
|
||||||
|
|
||||||
Go to the `main` function of the `main.cpp` file, and find where we request Vulkan extensions with
|
Go to the `main` function of the `main.cpp` file, and find where we request Vulkan extensions with
|
||||||
`nvvkpp::ContextCreateInfo`.
|
`nvvk::ContextCreateInfo`.
|
||||||
To request ray tracing capabilities, we need to explicitly
|
To request ray tracing capabilities, we need to explicitly
|
||||||
add the
|
add the
|
||||||
[VK_KHR_ray_tracing](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_KHR_ray_tracing)
|
[VK_KHR_ray_tracing](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_KHR_ray_tracing)
|
||||||
|
|
@ -183,32 +188,32 @@ In the header file, include the`raytrace_vkpp` helper
|
||||||
```` C
|
```` C
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#define ALLOC_DEDICATED
|
||||||
#include "nvvkpp/raytrace_vkpp.hpp"
|
#include "nvvk/raytrace_vk.hpp"
|
||||||
````
|
````
|
||||||
|
|
||||||
so that we can add that helper as a member in the `HelloVulkan` class,
|
so that we can add that helper as a member in the `HelloVulkan` class,
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
nvvkpp::RaytracingBuilder m_rtBuilder;
|
nvvk::RaytracingBuilder m_rtBuilder;
|
||||||
````
|
````
|
||||||
|
|
||||||
and initialize it at the end of `initRaytracing()`:
|
and initialize it at the end of `initRaytracing()`:
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, m_alloc, m_graphicsQueueIndex);
|
||||||
````
|
````
|
||||||
|
|
||||||
## Bottom-Level Acceleration Structure
|
## Bottom-Level Acceleration Structure
|
||||||
|
|
||||||
The first step of building a BLAS object consists in converting the geometry data of an `ObjModel` into a
|
The first step of building a BLAS object consists in converting the geometry data of an `ObjModel` into a
|
||||||
multiple structures than can be used by the AS builder. We are holding all those structure under
|
multiple structures than can be used by the AS builder. We are holding all those structure under
|
||||||
`nvvkpp::RaytracingBuilderKHR::Blas`
|
`nvvk::RaytracingBuilderKHR::Blas`
|
||||||
|
|
||||||
Add a new method to the `HelloVulkan`
|
Add a new method to the `HelloVulkan`
|
||||||
class:
|
class:
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
````
|
````
|
||||||
|
|
||||||
Its implementation will fill three structures
|
Its implementation will fill three structures
|
||||||
|
|
@ -226,7 +231,7 @@ potential optimization.
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
// Setting up the creation info of acceleration structure
|
// Setting up the creation info of acceleration structure
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
|
|
@ -263,7 +268,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
// Our blas is only one geometry, but could be made of many geometries
|
// Our blas is only one geometry, but could be made of many geometries
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -273,13 +278,13 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
````
|
````
|
||||||
|
|
||||||
In the `HelloVulkan` class declaration, we can now add the `createBottomLevelAS()` method that will generate a
|
In the `HelloVulkan` class declaration, we can now add the `createBottomLevelAS()` method that will generate a
|
||||||
`nvvkpp::RaytracingBuilderKHR::Blas` for each object, and trigger a BLAS build:
|
`nvvk::RaytracingBuilderKHR::Blas` for each object, and trigger a BLAS build:
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
````
|
````
|
||||||
|
|
||||||
The implementation loops over all the loaded models and fills in an array of `nvvkpp::RaytracingBuilderKHR::Blas` before
|
The implementation loops over all the loaded models and fills in an array of `nvvk::RaytracingBuilderKHR::Blas` before
|
||||||
triggering a build of all BLAS's in a batch. The resulting acceleration structures will be stored
|
triggering a build of all BLAS's in a batch. The resulting acceleration structures will be stored
|
||||||
within the helper in the order of construction, so that they can be directly referenced by index later.
|
within the helper in the order of construction, so that they can be directly referenced by index later.
|
||||||
|
|
||||||
|
|
@ -287,7 +292,7 @@ within the helper in the order of construction, so that they can be directly ref
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -308,27 +313,34 @@ part of the set of helpers provided by the [nvpro-samples](https://github.com/nv
|
||||||
will generate one BLAS for each `RaytracingBuilderKHR::Blas`:
|
will generate one BLAS for each `RaytracingBuilderKHR::Blas`:
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
void buildBlas(const std::vector<RaytracingBuilderKHR::Blas>& blas_,
|
void buildBlas(const std::vector<RaytracingBuilderKHR::Blas>& blas_,
|
||||||
vk::BuildAccelerationStructureFlagsKHR flags = vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace)
|
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR)
|
||||||
{
|
|
||||||
m_blas = blas_; // Keeping a copy
|
|
||||||
|
|
||||||
vk::DeviceSize maxScratch{0};
|
|
||||||
|
|
||||||
// Iterate over the groups of geometries, creating one BLAS for each group
|
|
||||||
int idx{0};
|
|
||||||
for(auto& blas : m_blas)
|
|
||||||
{
|
{
|
||||||
|
m_blas = blas_; // Keeping a copy
|
||||||
|
|
||||||
|
VkDeviceSize maxScratch{0}; // Largest scratch buffer for our BLAS
|
||||||
|
|
||||||
|
// Is compaction requested?
|
||||||
|
bool doCompaction = (flags & VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR)
|
||||||
|
== VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
|
||||||
|
std::vector<VkDeviceSize> originalSizes;
|
||||||
|
originalSizes.resize(m_blas.size());
|
||||||
|
|
||||||
|
// Iterate over the groups of geometries, creating one BLAS for each group
|
||||||
|
int idx{0};
|
||||||
|
for(auto& blas : m_blas)
|
||||||
|
{
|
||||||
````
|
````
|
||||||
|
|
||||||
The creation of the acceleration structure needs all `vk::AccelerationStructureCreateGeometryTypeInfoKHR` previously set and
|
The creation of the acceleration structure needs all `vk::AccelerationStructureCreateGeometryTypeInfoKHR` previously set and
|
||||||
set into `vk::AccelerationStructureCreateInfoKHR`.
|
set into `vk::AccelerationStructureCreateInfoKHR`.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eBottomLevel};
|
VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
|
||||||
asCreateInfo.setFlags(flags);
|
asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||||
asCreateInfo.setMaxGeometryCount((uint32_t)blas.asCreateGeometryInfo.size());
|
asCreateInfo.flags = flags;
|
||||||
asCreateInfo.setPGeometryInfos(blas.asCreateGeometryInfo.data());
|
asCreateInfo.maxGeometryCount = (uint32_t)blas.asCreateGeometryInfo.size();
|
||||||
|
asCreateInfo.pGeometryInfos = blas.asCreateGeometryInfo.data();
|
||||||
````
|
````
|
||||||
|
|
||||||
The creation information is then passed to the allocator, that will internally create an acceleration structure handle.
|
The creation information is then passed to the allocator, that will internally create an acceleration structure handle.
|
||||||
|
|
@ -336,88 +348,186 @@ It will also query `vk::Device::getAccelerationStructureMemoryRequirementsKHR` t
|
||||||
and allocate memory accordingly.
|
and allocate memory accordingly.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Create an acceleration structure identifier and allocate memory to store the
|
// Create an acceleration structure identifier and allocate memory to
|
||||||
// resulting structure data
|
// store the resulting structure data
|
||||||
blas.as = m_alloc.createAcceleration(createinfo);
|
blas.as = m_alloc.createAcceleration(asCreateInfo);
|
||||||
m_debug.setObjectName(blas.as.accel, (std::string("Blas" + std::to_string(idx)).c_str()));
|
m_debug.setObjectName(blas.as.accel, (std::string("Blas" + std::to_string(idx)).c_str()));
|
||||||
````
|
````
|
||||||
|
|
||||||
The acceleration structure builder requires some scratch memory to generate the BLAS. Since we generate all the
|
The acceleration structure builder requires some scratch memory to generate the BLAS. Since we generate all the
|
||||||
BLAS's in a batch, we query the scratch memory requirements for each BLAS, and find the maximum such requirement.
|
BLAS's in a batch, we query the scratch memory requirements for each BLAS, and find the maximum such requirement.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Estimate the amount of scratch memory required to build the BLAS, and update the
|
// Estimate the amount of scratch memory required to build the BLAS, and
|
||||||
// size of the scratch buffer that will be allocated to sequentially build all BLASes
|
// update the size of the scratch buffer that will be allocated to
|
||||||
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
// sequentially build all BLASes
|
||||||
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch,
|
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
||||||
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel};
|
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
|
||||||
vk::DeviceSize scratchSize =
|
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
|
||||||
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
|
memoryRequirementsInfo.accelerationStructure = blas.as.accel;
|
||||||
|
memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||||
blas.flags = flags;
|
|
||||||
maxScratch = std::max(maxScratch, scratchSize);
|
VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
|
||||||
idx++;
|
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
|
||||||
}
|
VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
|
||||||
|
|
||||||
|
|
||||||
|
blas.flags = flags;
|
||||||
|
maxScratch = std::max(maxScratch, scratchSize);
|
||||||
|
|
||||||
|
// Original size
|
||||||
|
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
|
||||||
|
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
|
||||||
|
originalSizes[idx] = reqMem.memoryRequirements.size;
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
````
|
````
|
||||||
|
|
||||||
Once that maximum has been found, we allocate a scratch buffer.
|
Once that maximum has been found, we allocate a scratch buffer.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Allocate the scratch buffers holding the temporary data of the acceleration structure builder
|
// Allocate the scratch buffers holding the temporary data of the acceleration structure builder
|
||||||
nvvkBuffer scratchBuffer = m_alloc.createBuffer(maxScratch, vk::BufferUsageFlagBits::eRayTracingKHR
|
nvvkBuffer scratchBuffer =
|
||||||
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
|
m_alloc.createBuffer(maxScratch, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||||
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer});
|
VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||||
|
bufferInfo.buffer = scratchBuffer.buffer;
|
||||||
|
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
|
||||||
````
|
````
|
||||||
|
|
||||||
|
To know the size that the BLAS is really taking, we use queries.
|
||||||
|
|
||||||
|
```` C
|
||||||
|
// Query size of compact BLAS
|
||||||
|
VkQueryPoolCreateInfo qpci{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
|
||||||
|
qpci.queryCount = (uint32_t)m_blas.size();
|
||||||
|
qpci.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
|
||||||
|
VkQueryPool queryPool;
|
||||||
|
vkCreateQueryPool(m_device, &qpci, nullptr, &queryPool);
|
||||||
|
````
|
||||||
|
|
||||||
We then use a one-time command buffer to launch all the BLAS builds. Note the barrier after each
|
We then use a one-time command buffer to launch all the BLAS builds. Note the barrier after each
|
||||||
build call: this is required as we reuse the scratch space across builds, and hence need to ensure
|
build call: this is required as we reuse the scratch space across builds, and hence need to ensure
|
||||||
the previous build has completed before starting the next.
|
the previous build has completed before starting the next.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Create a command buffer containing all the BLAS builds
|
// Query size of compact BLAS
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
|
VkQueryPoolCreateInfo qpci{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
qpci.queryCount = (uint32_t)m_blas.size();
|
||||||
|
qpci.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
|
||||||
|
VkQueryPool queryPool;
|
||||||
|
vkCreateQueryPool(m_device, &qpci, nullptr, &queryPool);
|
||||||
|
|
||||||
|
|
||||||
|
// Create a command buffer containing all the BLAS builds
|
||||||
|
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
|
||||||
|
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
int ctr{0};
|
||||||
for(auto& blas : m_blas)
|
for(auto& blas : m_blas)
|
||||||
{
|
{
|
||||||
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
|
const VkAccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
|
||||||
vk::AccelerationStructureBuildGeometryInfoKHR bottomASInfo{vk::AccelerationStructureTypeKHR::eBottomLevel};
|
VkAccelerationStructureBuildGeometryInfoKHR bottomASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
|
||||||
bottomASInfo.setFlags(flags);
|
bottomASInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||||
bottomASInfo.setUpdate(VK_FALSE);
|
bottomASInfo.flags = flags;
|
||||||
bottomASInfo.setSrcAccelerationStructure({});
|
bottomASInfo.update = VK_FALSE;
|
||||||
bottomASInfo.setDstAccelerationStructure(blas.as.accel);
|
bottomASInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||||
bottomASInfo.setGeometryArrayOfPointers(VK_FALSE);
|
bottomASInfo.dstAccelerationStructure = blas.as.accel;
|
||||||
bottomASInfo.setGeometryCount((uint32_t)blas.asGeometry.size());
|
bottomASInfo.geometryArrayOfPointers = VK_FALSE;
|
||||||
bottomASInfo.setPpGeometries(&pGeometry);
|
bottomASInfo.geometryCount = (uint32_t)blas.asGeometry.size();
|
||||||
bottomASInfo.setScratchData(scratchAddress);
|
bottomASInfo.ppGeometries = &pGeometry;
|
||||||
|
bottomASInfo.scratchData.deviceAddress = scratchAddress;
|
||||||
|
|
||||||
// Pointers of offset
|
// Pointers of offset
|
||||||
std::vector<const vk::AccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
|
std::vector<const VkAccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
|
||||||
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
|
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
|
||||||
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
|
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
|
||||||
|
|
||||||
// Building the AS
|
// Building the AS
|
||||||
cmdBuf.buildAccelerationStructureKHR(bottomASInfo, pBuildOffset);
|
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &bottomASInfo, pBuildOffset.data());
|
||||||
|
|
||||||
// Since the scratch buffer is reused across builds, we need a barrier to ensure one build
|
// Since the scratch buffer is reused across builds, we need a barrier to ensure one build
|
||||||
// is finished before starting the next one
|
// is finished before starting the next one
|
||||||
vk::MemoryBarrier barrier(vk::AccessFlagBits::eAccelerationStructureWriteKHR, vk::AccessFlagBits::eAccelerationStructureWriteKHR);
|
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
|
||||||
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
|
barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
|
||||||
vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, {}, {barrier}, {}, {});
|
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
|
||||||
|
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
||||||
|
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||||
|
|
||||||
|
// Query the compact size
|
||||||
|
if(doCompaction)
|
||||||
|
{
|
||||||
|
vkCmdWriteAccelerationStructuresPropertiesKHR(cmdBuf, 1, &blas.as.accel,
|
||||||
|
VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryPool, ctr++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
````
|
||||||
|
|
||||||
|
While this approach has the advantage of keeping all BLAS's independent, building many BLAS's efficiently would
|
||||||
|
require allocating a larger scratch buffer, and launch several builds simultaneously. This tutorial also
|
||||||
|
does not use compaction, which could reduce significantly the memory footprint of the acceleration structures. Both
|
||||||
|
of those aspects will be part of a future advanced tutorial.
|
||||||
|
We finally execute the command buffer and clean up the allocator's scratch memory and staging buffer:
|
||||||
|
|
||||||
|
This part, which is optional, will compact the BLAS in the memory that it is really using. It needs to wait that all BLASes
|
||||||
|
are constructred, to make a copy in the more fitted memory space.
|
||||||
|
|
||||||
|
```` C
|
||||||
|
|
||||||
|
// Compacting all BLAS
|
||||||
|
if(doCompaction)
|
||||||
|
{
|
||||||
|
cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
|
// Get the size result back
|
||||||
|
std::vector<VkDeviceSize> compactSizes(m_blas.size());
|
||||||
|
vkGetQueryPoolResults(m_device, queryPool, 0, (uint32_t)compactSizes.size(), compactSizes.size() * sizeof(VkDeviceSize),
|
||||||
|
compactSizes.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT);
|
||||||
|
|
||||||
|
|
||||||
|
// Compacting
|
||||||
|
std::vector<nvvkAccel> cleanupAS(m_blas.size());
|
||||||
|
uint32_t totOriginalSize{0}, totCompactSize{0};
|
||||||
|
for(int i = 0; i < m_blas.size(); i++)
|
||||||
|
{
|
||||||
|
LOGI("Reducing %i, from %d to %d \n", i, originalSizes[i], compactSizes[i]);
|
||||||
|
totOriginalSize += (uint32_t)originalSizes[i];
|
||||||
|
totCompactSize += (uint32_t)compactSizes[i];
|
||||||
|
|
||||||
|
// Creating a compact version of the AS
|
||||||
|
VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
|
||||||
|
asCreateInfo.compactedSize = compactSizes[i];
|
||||||
|
asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||||
|
asCreateInfo.flags = flags;
|
||||||
|
auto as = m_alloc.createAcceleration(asCreateInfo);
|
||||||
|
|
||||||
|
// Copy the original BLAS to a compact version
|
||||||
|
VkCopyAccelerationStructureInfoKHR copyInfo{VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR};
|
||||||
|
copyInfo.src = m_blas[i].as.accel;
|
||||||
|
copyInfo.dst = as.accel;
|
||||||
|
copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR;
|
||||||
|
vkCmdCopyAccelerationStructureKHR(cmdBuf, ©Info);
|
||||||
|
cleanupAS[i] = m_blas[i].as;
|
||||||
|
m_blas[i].as = as;
|
||||||
|
}
|
||||||
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
|
// Destroying the previous version
|
||||||
|
for(auto as : cleanupAS)
|
||||||
|
m_alloc.destroy(as);
|
||||||
|
|
||||||
|
LOGI("------------------\n");
|
||||||
|
LOGI("Total: %d -> %d = %d (%2.2f%s smaller) \n", totOriginalSize, totCompactSize,
|
||||||
|
totOriginalSize - totCompactSize, (totOriginalSize - totCompactSize) / float(totOriginalSize) * 100.f, "%%");
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
|
|
||||||
While this approach has the advantage of keeping all BLAS's independent, building many BLAS's efficiently would
|
Finally, destroying what was allocated.
|
||||||
require allocating a larger scratch buffer, and launch several builds simultaneously. This tutorial also
|
|
||||||
does not use compaction, which could reduce significantly the memory footprint of the acceleration structures. Both
|
|
||||||
of those aspects will be part of a future advanced tutorial.
|
|
||||||
|
|
||||||
We finally execute the command buffer and clean up the allocator's scratch memory and staging buffer:
|
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
vkDestroyQueryPool(m_device, queryPool, nullptr);
|
||||||
m_alloc.destroy(scratchBuffer);
|
m_alloc.destroy(scratchBuffer);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
@ -430,7 +540,7 @@ to the `HelloVulkan` class:
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
````
|
````
|
||||||
|
|
||||||
An instance is represented by a `nvvkpp::RaytracingBuilder::Instance`, which stores its transform matrix (`transform`)
|
An instance is represented by a `nvvk::RaytracingBuilder::Instance`, which stores its transform matrix (`transform`)
|
||||||
and the identifier of its corresponding BLAS (`blasId`). It also contains an instance identifier that will be available
|
and the identifier of its corresponding BLAS (`blasId`). It also contains an instance identifier that will be available
|
||||||
during shading as `gl_InstanceCustomIndex`, as well as the index of the hit group that represents the shaders that will be
|
during shading as `gl_InstanceCustomIndex`, as well as the index of the hit group that represents the shaders that will be
|
||||||
invoked upon hitting the object (`hitGroupId`).
|
invoked upon hitting the object (`hitGroupId`).
|
||||||
|
|
@ -447,16 +557,16 @@ optimized for tracing performance (rather than AS size, for example).
|
||||||
```` C
|
```` C
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -480,21 +590,21 @@ the number of instances it will hold, and flags indicating preferences for the b
|
||||||
builds or better performance.
|
builds or better performance.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
void buildTlas(const std::vector<Instance>& instances,
|
void buildTlas(const std::vector<Instance>& instances,
|
||||||
vk::BuildAccelerationStructureFlagsKHR flags =
|
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR)
|
||||||
vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace)
|
|
||||||
{
|
|
||||||
m_tlas.flags = flags;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR geometryCreate{vk::GeometryTypeKHR::eInstances};
|
m_tlas.flags = flags;
|
||||||
geometryCreate.setMaxPrimitiveCount(static_cast<uint32_t>(instances.size()));
|
|
||||||
geometryCreate.setAllowsTransforms(VK_TRUE);
|
VkAccelerationStructureCreateGeometryTypeInfoKHR geometryCreate{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR};
|
||||||
|
geometryCreate.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||||
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eTopLevel};
|
geometryCreate.maxPrimitiveCount = (static_cast<uint32_t>(instances.size()));
|
||||||
asCreateInfo.setFlags(flags);
|
geometryCreate.allowsTransforms = (VK_TRUE);
|
||||||
asCreateInfo.setMaxGeometryCount(1);
|
|
||||||
asCreateInfo.setPGeometryInfos(&geometryCreate);
|
VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
|
||||||
|
asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||||
|
asCreateInfo.flags = flags;
|
||||||
|
asCreateInfo.maxGeometryCount = 1;
|
||||||
|
asCreateInfo.pGeometryInfos = &geometryCreate;
|
||||||
````
|
````
|
||||||
|
|
||||||
We then call the allocator, which will create an acceleration structure handle for the TLAS. It will also query the
|
We then call the allocator, which will create an acceleration structure handle for the TLAS. It will also query the
|
||||||
|
|
@ -502,10 +612,10 @@ resulting size of the TLAS using `vk::Device::getAccelerationStructureMemoryRequ
|
||||||
amount of memory:
|
amount of memory:
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Create the acceleration structure object and allocate the memory required to hold the TLAS data
|
// Create the acceleration structure object and allocate the memory
|
||||||
m_tlas.as = m_alloc.createAcceleration(asCreateInfo);
|
// required to hold the TLAS data
|
||||||
m_debug.setObjectName(m_tlas.as.accel, "Tlas");
|
m_tlas.as = m_alloc.createAcceleration(asCreateInfo);
|
||||||
}
|
m_debug.setObjectName(m_tlas.as.accel, "Tlas");
|
||||||
````
|
````
|
||||||
|
|
||||||
As with the BLAS, we also query the amount of scratch memory required by the builder to generate the TLAS,
|
As with the BLAS, we also query the amount of scratch memory required by the builder to generate the TLAS,
|
||||||
|
|
@ -514,18 +624,23 @@ one buffer and thus saved an allocation. However, for the purpose of this tutori
|
||||||
independent.
|
independent.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Compute the amount of scratch memory required by the acceleration structure builder
|
// Compute the amount of scratch memory required by the acceleration structure builder
|
||||||
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
|
||||||
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch,
|
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
|
||||||
vk::AccelerationStructureBuildTypeKHR::eDevice, m_tlas.as.accel};
|
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
|
||||||
vk::DeviceSize scratchSize =
|
memoryRequirementsInfo.accelerationStructure = m_tlas.as.accel;
|
||||||
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
|
memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
|
||||||
|
|
||||||
// Allocate the scratch memory
|
VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
|
||||||
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR
|
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
|
||||||
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
|
VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
|
||||||
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer});
|
|
||||||
|
// Allocate the scratch memory
|
||||||
|
nvvkBuffer scratchBuffer =
|
||||||
|
m_alloc.createBuffer(scratchSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||||
|
VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||||
|
bufferInfo.buffer = scratchBuffer.buffer;
|
||||||
|
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
|
||||||
````
|
````
|
||||||
|
|
||||||
An `Instance` object is nearly identical to a `VkGeometryInstanceKHR` object: the only difference is the transform
|
An `Instance` object is nearly identical to a `VkGeometryInstanceKHR` object: the only difference is the transform
|
||||||
|
|
@ -535,13 +650,13 @@ application side allows us to use the more intuitive $4\times4$ matrices, making
|
||||||
TLAS we then convert all the `Instance` objects to `VkGeometryInstanceKHR`:
|
TLAS we then convert all the `Instance` objects to `VkGeometryInstanceKHR`:
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// For each instance, build the corresponding instance descriptor
|
// For each instance, build the corresponding instance descriptor
|
||||||
std::vector<vk::AccelerationStructureInstanceKHR> geometryInstances;
|
std::vector<VkAccelerationStructureInstanceKHR> geometryInstances;
|
||||||
geometryInstances.reserve(instances.size());
|
geometryInstances.reserve(instances.size());
|
||||||
for(const auto& inst : instances)
|
for(const auto& inst : instances)
|
||||||
{
|
{
|
||||||
geometryInstances.push_back(instanceToVkGeometryInstanceKHR(inst));
|
geometryInstances.push_back(instanceToVkGeometryInstanceKHR(inst));
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
|
|
||||||
We then upload the instance descriptions to the device using a one-time command buffer. This command buffer will also be
|
We then upload the instance descriptions to the device using a one-time command buffer. This command buffer will also be
|
||||||
|
|
@ -549,54 +664,65 @@ used to generate the TLAS itself, and so we add a barrier after the copy to ensu
|
||||||
TLAS build.
|
TLAS build.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Building the TLAS
|
// Building the TLAS
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
// Create a buffer holding the actual instance data for use by the AS builder
|
// Create a buffer holding the actual instance data for use by the AS
|
||||||
VkDeviceSize instanceDescsSizeInBytes = instances.size() * sizeof(vk::AccelerationStructureInstanceKHR);
|
// builder
|
||||||
|
VkDeviceSize instanceDescsSizeInBytes = instances.size() * sizeof(VkAccelerationStructureInstanceKHR);
|
||||||
|
|
||||||
// Allocate the instance buffer and copy its contents from host to device memory
|
// Allocate the instance buffer and copy its contents from host to device
|
||||||
m_instBuffer = m_alloc.createBuffer(cmdBuf, geometryInstances,
|
// memory
|
||||||
vk::BufferUsageFlagBits::eRayTracingKHR | vk::BufferUsageFlagBits::eShaderDeviceAddress);
|
m_instBuffer = m_alloc.createBuffer(cmdBuf, geometryInstances,
|
||||||
m_debug.setObjectName(m_instBuffer.buffer, "TLASInstances");
|
VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||||
vk::DeviceAddress instanceAddress = m_device.getBufferAddress(m_instBuffer.buffer);
|
m_debug.setObjectName(m_instBuffer.buffer, "TLASInstances");
|
||||||
|
//VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||||
|
bufferInfo.buffer = m_instBuffer.buffer;
|
||||||
|
VkDeviceAddress instanceAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
|
||||||
|
|
||||||
// Make sure the copy of the instance buffer are copied before triggering the
|
// Make sure the copy of the instance buffer are copied before triggering the
|
||||||
// acceleration structure build
|
// acceleration structure build
|
||||||
vk::MemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eAccelerationStructureWriteKHR);
|
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
|
||||||
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
vk::DependencyFlags(), {barrier}, {}, {});
|
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
|
||||||
|
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
||||||
|
0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||||
````
|
````
|
||||||
|
|
||||||
The build is then triggered, and we execute the command buffer before destroying the temporary buffers.
|
The build is then triggered, and we execute the command buffer before destroying the temporary buffers.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Build the TLAS
|
// Build the TLAS
|
||||||
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances};
|
VkAccelerationStructureGeometryDataKHR geometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
|
||||||
topASGeometry.geometry.instances.setArrayOfPointers(VK_FALSE);
|
geometry.instances.arrayOfPointers = VK_FALSE;
|
||||||
topASGeometry.geometry.instances.setData(instanceAddress);
|
geometry.instances.data.deviceAddress = instanceAddress;
|
||||||
|
VkAccelerationStructureGeometryKHR topASGeometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
|
||||||
|
topASGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||||
|
topASGeometry.geometry = geometry;
|
||||||
|
|
||||||
const vk::AccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
|
|
||||||
vk::AccelerationStructureBuildGeometryInfoKHR topASInfo;
|
const VkAccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
|
||||||
topASInfo.setFlags(flags);
|
VkAccelerationStructureBuildGeometryInfoKHR topASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
|
||||||
topASInfo.setUpdate(VK_FALSE);
|
topASInfo.flags = flags;
|
||||||
topASInfo.setSrcAccelerationStructure({});
|
topASInfo.update = VK_FALSE;
|
||||||
topASInfo.setDstAccelerationStructure(m_tlas.as.accel);
|
topASInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||||
topASInfo.setGeometryArrayOfPointers(VK_FALSE);
|
topASInfo.dstAccelerationStructure = m_tlas.as.accel;
|
||||||
topASInfo.setGeometryCount(1);
|
topASInfo.geometryArrayOfPointers = VK_FALSE;
|
||||||
topASInfo.setPpGeometries(&pGeometry);
|
topASInfo.geometryCount = 1;
|
||||||
topASInfo.setScratchData(scratchAddress);
|
topASInfo.ppGeometries = &pGeometry;
|
||||||
|
topASInfo.scratchData.deviceAddress = scratchAddress;
|
||||||
|
|
||||||
// Build Offsets info: n instances
|
// Build Offsets info: n instances
|
||||||
vk::AccelerationStructureBuildOffsetInfoKHR buildOffsetInfo{static_cast<uint32_t>(instances.size()), 0, 0, 0};
|
VkAccelerationStructureBuildOffsetInfoKHR buildOffsetInfo{static_cast<uint32_t>(instances.size()), 0, 0, 0};
|
||||||
const vk::AccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
|
const VkAccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
|
||||||
|
|
||||||
// Build the TLAS
|
// Build the TLAS
|
||||||
cmdBuf.buildAccelerationStructureKHR(1, &topASInfo, &pBuildOffsetInfo);
|
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &topASInfo, &pBuildOffsetInfo);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
|
||||||
m_alloc.flushStaging();
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_alloc.destroy(scratchBuffer);
|
m_alloc.destroy(scratchBuffer);
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
|
|
@ -633,7 +759,7 @@ In the header, we declare the objects related to this additional descriptor set:
|
||||||
```` C
|
```` C
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
|
|
@ -654,25 +780,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, vkSS::eRaygenKHR )); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
|
|
@ -687,25 +813,25 @@ descriptor set as they semantically fit the Scene descriptor set.
|
||||||
|
|
||||||
```` C
|
```` C
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
@ -724,11 +850,10 @@ We set the actual contents of the descriptor set by adding those buffers in `upd
|
||||||
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
````
|
````
|
||||||
|
|
||||||
Originally the buffers containing the vertices and indices were only used by the rasterization pipeline. The ray tracing
|
Originally the buffers containing the vertices and indices were only used by the rasterization pipeline. The ray tracing
|
||||||
|
|
@ -922,11 +1047,11 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
||||||
|
|
@ -960,8 +1085,8 @@ shaders.
|
||||||
```` C
|
```` C
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -1137,19 +1262,19 @@ copy the handles into the SBT:
|
||||||
```` C
|
```` C
|
||||||
std::vector<uint8_t> shaderHandleStorage(sbtSize);
|
std::vector<uint8_t> shaderHandleStorage(sbtSize);
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
@ -1696,8 +1821,9 @@ In the body of `createRtPipeline`, we need to define the new miss shader right a
|
||||||
```` C
|
```` C
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,19 +30,22 @@
|
||||||
|
|
||||||
extern std::vector<std::string> defaultSearchPaths;
|
extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
|
#define VMA_IMPLEMENTATION
|
||||||
|
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "fileformats/stb_image.h"
|
#include "fileformats/stb_image.h"
|
||||||
#include "obj_loader.h"
|
#include "obj_loader.h"
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,31 +61,32 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(NVVK_ALLOC_DEDICATED)
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(NVVK_ALLOC_DMA)
|
||||||
m_memAllocator.init(device, physicalDevice);
|
m_memAllocator.init(device, physicalDevice);
|
||||||
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true);
|
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, true);
|
||||||
m_alloc.init(device, &m_memAllocator);
|
m_alloc.init(device, physicalDevice, &m_memAllocator);
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(NVVK_ALLOC_VMA)
|
||||||
VmaAllocatorCreateInfo allocatorInfo = {};
|
VmaAllocatorCreateInfo allocatorInfo = {};
|
||||||
allocatorInfo.physicalDevice = physicalDevice;
|
allocatorInfo.physicalDevice = physicalDevice;
|
||||||
|
allocatorInfo.instance = instance;
|
||||||
allocatorInfo.device = device;
|
allocatorInfo.device = device;
|
||||||
allocatorInfo.flags |=
|
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||||
VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
|
|
||||||
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
|
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
|
||||||
m_alloc.init(device, m_memAllocator);
|
m_alloc.init(device, physicalDevice, m_memAllocator);
|
||||||
#endif
|
#endif
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
|
|
||||||
|
|
||||||
m_offscreen.setup(device, m_memAllocator, queueFamily);
|
m_offscreen.setup(device, &m_alloc, queueFamily);
|
||||||
m_raytrace.setup(device, physicalDevice, m_memAllocator, queueFamily);
|
m_raytrace.setup(device, physicalDevice, &m_alloc, queueFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -100,15 +104,15 @@ void HelloVulkan::updateUniformBuffer()
|
||||||
// #VKRay
|
// #VKRay
|
||||||
ubo.projInverse = nvmath::invert(ubo.proj);
|
ubo.projInverse = nvmath::invert(ubo.proj);
|
||||||
|
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(NVVK_ALLOC_DEDICATED)
|
||||||
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
|
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
memcpy(data, &ubo, sizeof(ubo));
|
||||||
m_device.unmapMemory(m_cameraMat.allocation);
|
m_device.unmapMemory(m_cameraMat.allocation);
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(NVVK_ALLOC_DMA)
|
||||||
void* data = m_memAllocator.map(m_cameraMat.allocation);
|
void* data = m_memAllocator.map(m_cameraMat.allocation);
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
memcpy(data, &ubo, sizeof(ubo));
|
||||||
m_memAllocator.unmap(m_cameraMat.allocation);
|
m_memAllocator.unmap(m_cameraMat.allocation);
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(NVVK_ALLOC_VMA)
|
||||||
void* data;
|
void* data;
|
||||||
vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data);
|
vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data);
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
memcpy(data, &ubo, sizeof(ubo));
|
||||||
|
|
@ -128,37 +132,37 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj + 1, // Adding Implicit mat too
|
vkDS(1, vkDT::eStorageBuffer, nbObj + 1, // Adding Implicit mat too
|
||||||
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1,
|
vkDS(2, vkDT::eStorageBuffer, 1,
|
||||||
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(vkDS(4, vkDT::eStorageBuffer, nbObj,
|
m_descSetLayoutBind.addBinding(vkDS(4, vkDT::eStorageBuffer, nbObj,
|
||||||
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Storing implicit obj (binding = 7)
|
// Storing implicit obj (binding = 7)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(7, vkDT::eStorageBuffer, 1,
|
vkDS(7, vkDT::eStorageBuffer, 1,
|
||||||
vkSS::eClosestHitKHR | vkSS::eIntersectionKHR | vkSS::eAnyHitKHR));
|
vkSS::eClosestHitKHR | vkSS::eIntersectionKHR | vkSS::eAnyHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -170,9 +174,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -187,11 +191,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiIdx.emplace_back(model.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(model.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
dbiMat.emplace_back(m_implObjects.implMatBuf.buffer, 0, VK_WHOLE_SIZE); // Adding implicit mat
|
dbiMat.emplace_back(m_implObjects.implMatBuf.buffer, 0, VK_WHOLE_SIZE); // Adding implicit mat
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -199,10 +202,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
vk::DescriptorBufferInfo dbiImplDesc{m_implObjects.implBuf.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiImplDesc{m_implObjects.implBuf.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &dbiImplDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &dbiImplDesc));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -228,19 +231,19 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreen.renderPass());
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreen.renderPass());
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,8 +276,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -285,8 +288,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -308,7 +311,11 @@ void HelloVulkan::createUniformBuffer()
|
||||||
using vkMP = vk::MemoryPropertyFlagBits;
|
using vkMP = vk::MemoryPropertyFlagBits;
|
||||||
|
|
||||||
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
|
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
|
||||||
|
#ifndef NVVK_ALLOC_VMA
|
||||||
vkMP::eHostVisible | vkMP::eHostCoherent);
|
vkMP::eHostVisible | vkMP::eHostCoherent);
|
||||||
|
#else
|
||||||
|
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
||||||
|
#endif // _DEBUG
|
||||||
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,12 +328,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,21 +353,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
// Creating the VKImage
|
// Creating the VKImage
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
// Setting up the descriptor used by the shader
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
texture.descriptor =
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -387,16 +394,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -436,7 +442,12 @@ void HelloVulkan::destroyResources()
|
||||||
// #VKRay
|
// #VKRay
|
||||||
m_raytrace.destroy();
|
m_raytrace.destroy();
|
||||||
|
|
||||||
|
m_alloc.deinit();
|
||||||
|
#ifdef NVVK_ALLOC_DMA
|
||||||
m_memAllocator.deinit();
|
m_memAllocator.deinit();
|
||||||
|
#elif defined(NVVK_ALLOC_VMA)
|
||||||
|
vmaDestroyAllocator(m_memAllocator);
|
||||||
|
#endif // NVVK_ALLOC_DMA
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -465,7 +476,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstants>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstants>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstants);
|
m_pushConstants);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -574,7 +585,7 @@ void HelloVulkan::addImplMaterial(const MaterialObj& mat)
|
||||||
void HelloVulkan::createImplictBuffers()
|
void HelloVulkan::createImplictBuffers()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
// Not allowing empty buffers
|
// Not allowing empty buffers
|
||||||
if(m_implObjects.objImpl.empty())
|
if(m_implObjects.objImpl.empty())
|
||||||
|
|
@ -587,8 +598,8 @@ void HelloVulkan::createImplictBuffers()
|
||||||
vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
m_implObjects.implMatBuf =
|
m_implObjects.implMatBuf =
|
||||||
m_alloc.createBuffer(cmdBuf, m_implObjects.implMat, vkBU::eStorageBuffer);
|
m_alloc.createBuffer(cmdBuf, m_implObjects.implMat, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_implObjects.implBuf.buffer, "implicitObj");
|
m_debug.setObjectName(m_implObjects.implBuf.buffer, "implicitObj");
|
||||||
m_debug.setObjectName(m_implObjects.implMatBuf.buffer, "implicitMat");
|
m_debug.setObjectName(m_implObjects.implMatBuf.buffer, "implicitMat");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@
|
||||||
|
|
||||||
#include "vkalloc.hpp"
|
#include "vkalloc.hpp"
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#include "nvvk/allocator_dedicated_vk.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "offscreen.hpp"
|
#include "offscreen.hpp"
|
||||||
|
|
||||||
#include "obj.hpp"
|
#include "obj.hpp"
|
||||||
|
|
@ -46,10 +46,11 @@
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -76,26 +77,25 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
int m_maxFrames{10};
|
int m_maxFrames{10};
|
||||||
void resetFrame();
|
void resetFrame();
|
||||||
void updateFrame();
|
void updateFrame();
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures
|
|
||||||
nvvkMemAllocator m_memAllocator;
|
|
||||||
|
|
||||||
|
nvvk::Allocator m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
|
nvvk::MemAllocator m_memAllocator;
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
Offscreen m_offscreen;
|
Offscreen m_offscreen;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -157,7 +158,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -181,7 +182,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -196,7 +197,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -316,7 +318,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -368,7 +371,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -54,8 +54,8 @@ struct ImplInst
|
||||||
{
|
{
|
||||||
std::vector<ObjImplicit> objImpl; // All objects
|
std::vector<ObjImplicit> objImpl; // All objects
|
||||||
std::vector<MaterialObj> implMat; // All materials used by implicit obj
|
std::vector<MaterialObj> implMat; // All materials used by implicit obj
|
||||||
nvvkBuffer implBuf; // Buffer of objects
|
nvvk::Buffer implBuf; // Buffer of objects
|
||||||
nvvkBuffer implMatBuf; // Buffer of material
|
nvvk::Buffer implMatBuf; // Buffer of material
|
||||||
int blasId;
|
int blasId;
|
||||||
nvmath::mat4f transform{1};
|
nvmath::mat4f transform{1};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@
|
||||||
|
|
||||||
#include "offscreen.hpp"
|
#include "offscreen.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
|
|
||||||
extern std::vector<std::string> defaultSearchPaths;
|
extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
|
|
@ -39,10 +39,10 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
// Post-processing
|
// Post-processing
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void Offscreen::setup(const vk::Device& device, nvvkMemAllocator& memAlloc, uint32_t queueFamily)
|
void Offscreen::setup(const vk::Device& device, nvvk::Allocator* allocator, uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
m_device = device;
|
m_device = device;
|
||||||
m_alloc.init(device, &memAlloc);
|
m_alloc = allocator;
|
||||||
m_graphicsQueueIndex = queueFamily;
|
m_graphicsQueueIndex = queueFamily;
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -53,8 +53,8 @@ void Offscreen::destroy()
|
||||||
m_device.destroy(m_pipelineLayout);
|
m_device.destroy(m_pipelineLayout);
|
||||||
m_device.destroy(m_descPool);
|
m_device.destroy(m_descPool);
|
||||||
m_device.destroy(m_dsetLayout);
|
m_device.destroy(m_dsetLayout);
|
||||||
m_alloc.destroy(m_colorTexture);
|
m_alloc->destroy(m_colorTexture);
|
||||||
m_alloc.destroy(m_depthTexture);
|
m_alloc->destroy(m_depthTexture);
|
||||||
m_device.destroy(m_renderPass);
|
m_device.destroy(m_renderPass);
|
||||||
m_device.destroy(m_framebuffer);
|
m_device.destroy(m_framebuffer);
|
||||||
}
|
}
|
||||||
|
|
@ -64,52 +64,57 @@ void Offscreen::destroy()
|
||||||
//
|
//
|
||||||
void Offscreen::createFramebuffer(VkExtent2D& size)
|
void Offscreen::createFramebuffer(VkExtent2D& size)
|
||||||
{
|
{
|
||||||
m_alloc.destroy(m_colorTexture);
|
m_alloc->destroy(m_colorTexture);
|
||||||
m_alloc.destroy(m_depthTexture);
|
m_alloc->destroy(m_depthTexture);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(size, m_colorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(size, m_colorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_colorTexture = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
|
nvvk::Image image = m_alloc->createImage(colorCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_colorTexture = m_alloc->createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_colorTexture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
m_colorTexture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_colorTexture.image, vk::SamplerCreateInfo{},
|
|
||||||
m_colorFormat, vk::ImageLayout::eGeneral);
|
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
{
|
||||||
nvvkpp::image::create2DInfo(size, m_depthFormat,
|
auto depthCreateInfo =
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
nvvk::makeImage2DCreateInfo(size, m_depthFormat,
|
||||||
m_depthTexture = m_alloc.createImage(depthCreateInfo);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
|
nvvk::Image image = m_alloc->createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_depthFormat);
|
depthStencilView.setFormat(m_depthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_depthTexture.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_depthTexture.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_depthTexture = m_alloc->createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_colorTexture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_colorTexture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_depthTexture.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_depthTexture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_renderPass)
|
if(!m_renderPass)
|
||||||
{
|
{
|
||||||
m_renderPass =
|
m_renderPass = nvvk::createRenderPass(m_device, {m_colorFormat}, m_depthFormat, 1, true, true,
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_colorFormat}, m_depthFormat, 1, true, true,
|
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -147,13 +152,13 @@ void Offscreen::createPipeline(vk::RenderPass& renderPass)
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_pipelineLayout, renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_pipelineLayout, renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_pipeline = pipelineGenerator.create();
|
m_pipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_pipeline, "post");
|
m_debug.setObjectName(m_pipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,10 +172,10 @@ void Offscreen::createDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_dsetLayoutBinding.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_dsetLayoutBinding.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_dsetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_dsetLayoutBinding);
|
m_dsetLayout = m_dsetLayoutBinding.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_dsetLayoutBinding);
|
m_descPool = m_dsetLayoutBinding.createPool(m_device);
|
||||||
m_dset = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_dsetLayout);
|
m_dset = nvvk::allocateDescriptorSet(m_device, m_descPool, m_dsetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -179,7 +184,7 @@ void Offscreen::createDescriptor()
|
||||||
void Offscreen::updateDescriptorSet()
|
void Offscreen::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_dset, m_dsetLayoutBinding[0], &m_colorTexture.descriptor);
|
m_dsetLayoutBinding.makeWrite(m_dset, 0, &m_colorTexture.descriptor);
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@
|
||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "vkalloc.hpp"
|
#include "vkalloc.hpp"
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -39,7 +40,7 @@
|
||||||
class Offscreen
|
class Offscreen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device, nvvkMemAllocator& memAlloc, uint32_t queueFamily);
|
void setup(const vk::Device& device, nvvk::Allocator* allocator, uint32_t queueFamily);
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void createFramebuffer(VkExtent2D& size);
|
void createFramebuffer(VkExtent2D& size);
|
||||||
|
|
@ -50,25 +51,25 @@ public:
|
||||||
|
|
||||||
const vk::RenderPass& renderPass() { return m_renderPass; }
|
const vk::RenderPass& renderPass() { return m_renderPass; }
|
||||||
const vk::Framebuffer& frameBuffer() { return m_framebuffer; }
|
const vk::Framebuffer& frameBuffer() { return m_framebuffer; }
|
||||||
const nvvkTexture& colorTexture() { return m_colorTexture; }
|
const nvvk::Texture& colorTexture() { return m_colorTexture; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_dsetLayoutBinding;
|
nvvk::DescriptorSetBindings m_dsetLayoutBinding;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_dsetLayout;
|
vk::DescriptorSetLayout m_dsetLayout;
|
||||||
vk::DescriptorSet m_dset;
|
vk::DescriptorSet m_dset;
|
||||||
vk::Pipeline m_pipeline;
|
vk::Pipeline m_pipeline;
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::RenderPass m_renderPass;
|
vk::RenderPass m_renderPass;
|
||||||
vk::Framebuffer m_framebuffer;
|
vk::Framebuffer m_framebuffer;
|
||||||
|
|
||||||
nvvkTexture m_colorTexture;
|
nvvk::Texture m_colorTexture;
|
||||||
vk::Format m_colorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_colorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_depthTexture;
|
nvvk::Texture m_depthTexture;
|
||||||
vk::Format m_depthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_depthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::Allocator* m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
vk::Device m_device;
|
vk::Device m_device;
|
||||||
int m_graphicsQueueIndex{0};
|
int m_graphicsQueueIndex{0};
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@
|
||||||
|
|
||||||
#include "raytrace.hpp"
|
#include "raytrace.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
#include "nvvk/shaders_vk.hpp"
|
||||||
#include "obj_loader.h"
|
#include "obj_loader.h"
|
||||||
|
|
||||||
extern std::vector<std::string> defaultSearchPaths;
|
extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
@ -37,25 +38,19 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
void Raytracer::setup(const vk::Device& device,
|
void Raytracer::setup(const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
nvvkMemAllocator& memAlloc,
|
nvvk::Allocator* allocator,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
m_device = device;
|
m_device = device;
|
||||||
m_physicalDevice = physicalDevice;
|
m_physicalDevice = physicalDevice;
|
||||||
m_alloc.init(device, &memAlloc);
|
m_alloc = allocator;
|
||||||
m_graphicsQueueIndex = queueFamily;
|
m_graphicsQueueIndex = queueFamily;
|
||||||
|
|
||||||
// Requesting ray tracing properties
|
// Requesting ray tracing properties
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
#if defined(ALLOC_DEDICATED)
|
m_rtBuilder.setup(m_device, allocator, m_graphicsQueueIndex);
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
m_rtBuilder.setup(m_device, memAlloc, m_graphicsQueueIndex);
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
m_rtBuilder.setup(m_device, memAlloc, m_graphicsQueueIndex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_debug.setup(device);
|
m_debug.setup(device);
|
||||||
}
|
}
|
||||||
|
|
@ -68,13 +63,13 @@ void Raytracer::destroy()
|
||||||
m_device.destroy(m_rtDescSetLayout);
|
m_device.destroy(m_rtDescSetLayout);
|
||||||
m_device.destroy(m_rtPipeline);
|
m_device.destroy(m_rtPipeline);
|
||||||
m_device.destroy(m_rtPipelineLayout);
|
m_device.destroy(m_rtPipelineLayout);
|
||||||
m_alloc.destroy(m_rtSBTBuffer);
|
m_alloc->destroy(m_rtSBTBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
// Setting up the creation info of acceleration structure
|
// Setting up the creation info of acceleration structure
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
|
|
@ -110,7 +105,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjMod
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -121,7 +116,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjMod
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Returning the ray tracing geometry used for the BLAS, containing all spheres
|
// Returning the ray tracing geometry used for the BLAS, containing all spheres
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const ImplInst& implicitObj)
|
nvvk::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const ImplInst& implicitObj)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Setting up the creation info of acceleration structure
|
// Setting up the creation info of acceleration structure
|
||||||
|
|
@ -152,7 +147,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const Impl
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -163,7 +158,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const Impl
|
||||||
void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj)
|
void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj)
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(models.size());
|
allBlas.reserve(models.size());
|
||||||
for(const auto& obj : models)
|
for(const auto& obj : models)
|
||||||
{
|
{
|
||||||
|
|
@ -182,33 +177,34 @@ void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& imp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_rtBuilder.buildBlas(allBlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildBlas(allBlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
|
||||||
|
| vk::BuildAccelerationStructureFlagBitsKHR::eAllowCompaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raytracer::createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj)
|
void Raytracer::createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj)
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(instances.size());
|
tlas.reserve(instances.size());
|
||||||
for(int i = 0; i < static_cast<int>(instances.size()); i++)
|
for(int i = 0; i < static_cast<int>(instances.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = instances[i].transform; // Position of the instance
|
rayInst.transform = instances[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = instances[i].objIndex;
|
rayInst.blasId = instances[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the blas containing all implicit
|
// Add the blas containing all implicit
|
||||||
if(!implicitObj.objImpl.empty())
|
if(!implicitObj.objImpl.empty())
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = implicitObj.transform; // Position of the instance
|
rayInst.transform = implicitObj.transform; // Position of the instance
|
||||||
rayInst.instanceId = static_cast<uint32_t>(implicitObj.blasId); // Same for material index
|
rayInst.instanceId = static_cast<uint32_t>(implicitObj.blasId); // Same for material index
|
||||||
rayInst.blasId = static_cast<uint32_t>(implicitObj.blasId);
|
rayInst.blasId = static_cast<uint32_t>(implicitObj.blasId);
|
||||||
rayInst.hitGroupId = 1; // We will use the same hit group for all objects (the second one)
|
rayInst.hitGroupId = 1; // We will use the same hit group for all objects (the second one)
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,24 +220,24 @@ void Raytracer::createRtDescriptorSet(const vk::ImageView& outputImage)
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{{}, outputImage, vk::ImageLayout::eGeneral};
|
vk::DescriptorImageInfo imageInfo{{}, outputImage, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -269,16 +265,17 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -305,11 +302,11 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
|
||||||
|
|
||||||
// Hit Group0 - Closest Hit + AnyHit
|
// Hit Group0 - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
vk::ShaderModule ahitSM =
|
vk::ShaderModule ahitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -323,14 +320,14 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
|
||||||
|
|
||||||
// Hit Group1 - Closest Hit + Intersection (procedural)
|
// Hit Group1 - Closest Hit + Intersection (procedural)
|
||||||
vk::ShaderModule chit2SM =
|
vk::ShaderModule chit2SM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
||||||
vk::ShaderModule ahit2SM =
|
vk::ShaderModule ahit2SM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace2.rahit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace2.rahit.spv", true, paths));
|
||||||
vk::ShaderModule rintSM =
|
vk::ShaderModule rintSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
|
||||||
{
|
{
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -350,14 +347,13 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
||||||
|
|
||||||
vk::ShaderModule call0 =
|
vk::ShaderModule call0 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device,
|
||||||
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
|
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
|
||||||
vk::ShaderModule call1 =
|
vk::ShaderModule call1 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device,
|
||||||
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
|
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
|
||||||
vk::ShaderModule call2 =
|
vk::ShaderModule call2 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
|
||||||
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
|
|
||||||
|
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
|
||||||
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
|
|
@ -433,17 +429,17 @@ void Raytracer::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc->createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc->finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,11 @@
|
||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "vkalloc.hpp"
|
#include "vkalloc.hpp"
|
||||||
|
|
||||||
#include "nvmath/nvmath.h"
|
#include "nvmath/nvmath.h"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "obj.hpp"
|
#include "obj.hpp"
|
||||||
|
|
||||||
class Raytracer
|
class Raytracer
|
||||||
|
|
@ -38,12 +39,12 @@ class Raytracer
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
nvvkMemAllocator& memAlloc,
|
nvvk::Allocator* allocator,
|
||||||
uint32_t queueFamily);
|
uint32_t queueFamily);
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas implicitToVkGeometryKHR(const ImplInst& implicitObj);
|
nvvk::RaytracingBuilderKHR::Blas implicitToVkGeometryKHR(const ImplInst& implicitObj);
|
||||||
void createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj);
|
void createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj);
|
||||||
void createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj);
|
void createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj);
|
||||||
void createRtDescriptorSet(const vk::ImageView& outputImage);
|
void createRtDescriptorSet(const vk::ImageView& outputImage);
|
||||||
|
|
@ -57,23 +58,23 @@ public:
|
||||||
ObjPushConstants& sceneConstants);
|
ObjPushConstants& sceneConstants);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::Allocator* m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
vk::PhysicalDevice m_physicalDevice;
|
vk::PhysicalDevice m_physicalDevice;
|
||||||
vk::Device m_device;
|
vk::Device m_device;
|
||||||
int m_graphicsQueueIndex{0};
|
int m_graphicsQueueIndex{0};
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstants
|
struct RtPushConstants
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,6 @@
|
||||||
|
|
||||||
//#define ALLOC_DEDICATED
|
//#define NVVK_ALLOC_DEDICATED
|
||||||
#define ALLOC_DMA
|
#define NVVK_ALLOC_DMA
|
||||||
//#define ALLOC_VMA
|
//#define NVVK_ALLOC_VMA
|
||||||
|
|
||||||
#if defined(ALLOC_DEDICATED)
|
#include <nvvk/allocator_vk.hpp>
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
using nvvkAllocator = nvvkpp::AllocatorDedicated;
|
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
#include "nvvkpp/allocator_dma_vkpp.hpp"
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDma;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDma;
|
|
||||||
using nvvkAllocator = nvvkpp::AllocatorDma;
|
|
||||||
using nvvkMemAllocator = nvvk::DeviceMemoryAllocator;
|
|
||||||
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
#include "nvvkpp/allocator_vma_vkpp.hpp"
|
|
||||||
using nvvkBuffer = nvvkpp::BufferVma;
|
|
||||||
using nvvkTexture = nvvkpp::TextureVma;
|
|
||||||
using nvvkAllocator = nvvkpp::AllocatorVma;
|
|
||||||
using nvvkMemAllocator = VmaAllocator;
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,13 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -56,9 +56,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device, const vk::PhysicalDevice& physicalDevice, uint32_t queueFamily)
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -92,22 +95,23 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex));
|
m_descSetLayoutBind.addBinding(vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment));
|
m_descSetLayoutBind.addBinding(
|
||||||
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment));
|
m_descSetLayoutBind.addBinding(vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment));
|
||||||
|
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment));
|
m_descSetLayoutBind.addBinding(vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -119,9 +123,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -131,8 +135,8 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -140,7 +144,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(m_textures[i].descriptor);
|
diit.push_back(m_textures[i].descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -154,7 +158,8 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
{
|
{
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
vk::PushConstantRange pushConstantRanges = {vkSS::eVertex | vkSS::eFragment, 0, sizeof(ObjPushConstant)};
|
vk::PushConstantRange pushConstantRanges = {vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
|
sizeof(ObjPushConstant)};
|
||||||
|
|
||||||
// Creating the Pipeline Layout
|
// Creating the Pipeline Layout
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
|
||||||
|
|
@ -166,18 +171,19 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,16 +216,16 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, vkBU::eVertexBuffer);
|
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, vkBU::eVertexBuffer);
|
||||||
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, vkBU::eIndexBuffer);
|
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, vkBU::eIndexBuffer);
|
||||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, vkBU::eStorageBuffer);
|
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, vkBU::eStorageBuffer);
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -241,7 +247,8 @@ void HelloVulkan::createUniformBuffer()
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
using vkMP = vk::MemoryPropertyFlagBits;
|
using vkMP = vk::MemoryPropertyFlagBits;
|
||||||
|
|
||||||
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer, vkMP::eHostVisible | vkMP::eHostCoherent);
|
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
|
||||||
|
vkMP::eHostVisible | vkMP::eHostCoherent);
|
||||||
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,42 +261,46 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Creating all textures and samplers
|
// Creating all textures and samplers
|
||||||
//
|
//
|
||||||
void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std::vector<std::string>& textures)
|
void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
const std::vector<std::string>& textures)
|
||||||
{
|
{
|
||||||
using vkIU = vk::ImageUsageFlagBits;
|
using vkIU = vk::ImageUsageFlagBits;
|
||||||
|
|
||||||
vk::SamplerCreateInfo samplerCreateInfo{{}, vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear};
|
vk::SamplerCreateInfo samplerCreateInfo{
|
||||||
|
{}, vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear};
|
||||||
samplerCreateInfo.setMaxLod(FLT_MAX);
|
samplerCreateInfo.setMaxLod(FLT_MAX);
|
||||||
vk::Format format = vk::Format::eR8G8B8A8Srgb;
|
vk::Format format = vk::Format::eR8G8B8A8Srgb;
|
||||||
|
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor = nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal);
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -302,7 +313,8 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std
|
||||||
o << "media/textures/" << texture;
|
o << "media/textures/" << texture;
|
||||||
std::string txtFile = nvh::findFile(o.str(), defaultSearchPaths);
|
std::string txtFile = nvh::findFile(o.str(), defaultSearchPaths);
|
||||||
|
|
||||||
stbi_uc* pixels = stbi_load(txtFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
stbi_uc* pixels =
|
||||||
|
stbi_load(txtFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
||||||
|
|
||||||
// Handle failure
|
// Handle failure
|
||||||
if(!pixels)
|
if(!pixels)
|
||||||
|
|
@ -313,16 +325,18 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std
|
||||||
pixels = reinterpret_cast<stbi_uc*>(color.data());
|
pixels = reinterpret_cast<stbi_uc*>(color.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize, imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor = nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,9 +403,10 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
auto& inst = m_objInstance[i];
|
auto& inst = m_objInstance[i];
|
||||||
auto& model = m_objModel[inst.objIndex];
|
auto& model = m_objModel[inst.objIndex];
|
||||||
m_pushConstant.instanceId = i; // Telling which instance is drawn
|
m_pushConstant.instanceId = i; // Telling which instance is drawn
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, m_pushConstant);
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -422,48 +437,60 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eSampled
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
|
|
||||||
m_offscreenColor.descriptor = nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral);
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass = nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1,
|
m_offscreenRenderPass =
|
||||||
true, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
std::vector<vk::ImageView> attachments = {m_offscreenColor.descriptor.imageView, m_offscreenDepth.descriptor.imageView};
|
std::vector<vk::ImageView> attachments = {m_offscreenColor.descriptor.imageView,
|
||||||
|
m_offscreenDepth.descriptor.imageView};
|
||||||
|
|
||||||
m_device.destroy(m_offscreenFramebuffer);
|
m_device.destroy(m_offscreenFramebuffer);
|
||||||
vk::FramebufferCreateInfo info;
|
vk::FramebufferCreateInfo info;
|
||||||
|
|
@ -495,11 +522,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), vk::ShaderStageFlagBits::eVertex);
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), vk::ShaderStageFlagBits::eFragment);
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,10 +543,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -526,7 +556,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], &m_offscreenColor.descriptor);
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,9 +571,11 @@ void HelloVulkan::drawPost(vk::CommandBuffer cmdBuf)
|
||||||
cmdBuf.setScissor(0, {{{0, 0}, {m_size.width, m_size.height}}});
|
cmdBuf.setScissor(0, {{{0, 0}, {m_size.width, m_size.height}}});
|
||||||
|
|
||||||
auto aspectRatio = static_cast<float>(m_size.width) / static_cast<float>(m_size.height);
|
auto aspectRatio = static_cast<float>(m_size.width) / static_cast<float>(m_size.height);
|
||||||
cmdBuf.pushConstants<float>(m_postPipelineLayout, vk::ShaderStageFlagBits::eFragment, 0, aspectRatio);
|
cmdBuf.pushConstants<float>(m_postPipelineLayout, vk::ShaderStageFlagBits::eFragment, 0,
|
||||||
|
aspectRatio);
|
||||||
cmdBuf.bindPipeline(vk::PipelineBindPoint::eGraphics, m_postPipeline);
|
cmdBuf.bindPipeline(vk::PipelineBindPoint::eGraphics, m_postPipeline);
|
||||||
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, m_postPipelineLayout, 0, m_postDescSet, {});
|
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, m_postPipelineLayout, 0,
|
||||||
|
m_postDescSet, {});
|
||||||
cmdBuf.draw(3, 1, 0, 0);
|
cmdBuf.draw(3, 1, 0, 0);
|
||||||
|
|
||||||
m_debug.endLabel(cmdBuf);
|
m_debug.endLabel(cmdBuf);
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,11 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -41,17 +39,21 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device, const vk::PhysicalDevice& physicalDevice, uint32_t queueFamily) override;
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
void createGraphicsPipeline();
|
void createGraphicsPipeline();
|
||||||
void loadModel(const std::string& filename, nvmath::mat4f transform = nvmath::mat4f(1));
|
void loadModel(const std::string& filename, nvmath::mat4f transform = nvmath::mat4f(1));
|
||||||
void updateDescriptorSet();
|
void updateDescriptorSet();
|
||||||
void createUniformBuffer();
|
void createUniformBuffer();
|
||||||
void createSceneDescriptionBuffer();
|
void createSceneDescriptionBuffer();
|
||||||
void createTextureImages(const vk::CommandBuffer& cmdBuf, const std::vector<std::string>& textures);
|
void createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
const std::vector<std::string>& textures);
|
||||||
void updateUniformBuffer();
|
void updateUniformBuffer();
|
||||||
void onResize(int /*w*/, int /*h*/) override;
|
void onResize(int /*w*/, int /*h*/) override;
|
||||||
void destroyResources();
|
void destroyResources();
|
||||||
|
|
@ -62,10 +64,10 @@ public:
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -92,20 +94,20 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
|
|
@ -115,16 +117,16 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -97,12 +98,14 @@ int main(int argc, char** argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT, "NVIDIA Vulkan Raytracing Tutorial", nullptr, nullptr);
|
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT,
|
||||||
|
"NVIDIA Vulkan Raytracing Tutorial", nullptr, nullptr);
|
||||||
|
|
||||||
|
|
||||||
// Setup camera
|
// Setup camera
|
||||||
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
CameraManip.setLookat(nvmath::vec3f(2.0f, 2.0f, 2.0f), nvmath::vec3f(0, 0, 0), nvmath::vec3f(0, 1, 0));
|
CameraManip.setLookat(nvmath::vec3f(2.0f, 2.0f, 2.0f), nvmath::vec3f(0, 0, 0),
|
||||||
|
nvmath::vec3f(0, 1, 0));
|
||||||
|
|
||||||
// Setup Vulkan
|
// Setup Vulkan
|
||||||
if(!glfwVulkanSupported())
|
if(!glfwVulkanSupported())
|
||||||
|
|
@ -127,7 +130,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceScalarBlockLayoutFeaturesEXT scalarFeature;
|
vk::PhysicalDeviceScalarBlockLayoutFeaturesEXT scalarFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo;
|
nvvk::ContextCreateInfo contextInfo;
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
@ -144,7 +147,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, false, &scalarFeature);
|
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, false, &scalarFeature);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -159,7 +162,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -206,7 +210,8 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
ImGui::ColorEdit3("Clear color", reinterpret_cast<float*>(&clearColor));
|
ImGui::ColorEdit3("Clear color", reinterpret_cast<float*>(&clearColor));
|
||||||
renderUI(helloVk);
|
renderUI(helloVk);
|
||||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
|
||||||
|
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,7 +226,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -266,8 +272,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.getDevice().waitIdle();
|
helloVk.getDevice().waitIdle();
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
#include "obj_loader.h"
|
#include "obj_loader.h"
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +58,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,31 +100,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -135,27 +136,26 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMatIdx;
|
std::vector<vk::DescriptorBufferInfo> dbiMatIdx;
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiVert;
|
std::vector<vk::DescriptorBufferInfo> dbiVert;
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiIdx;
|
std::vector<vk::DescriptorBufferInfo> dbiIdx;
|
||||||
for(auto& obj : m_objModel)
|
for(size_t i = 0; i < m_objModel.size(); ++i)
|
||||||
{
|
{
|
||||||
dbiMat.emplace_back(obj.matColorBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiMatIdx.emplace_back(obj.matIndexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -163,7 +163,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -189,19 +189,19 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,13 +619,13 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
// Setting up the creation info of acceleration structure
|
// Setting up the creation info of acceleration structure
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
|
|
@ -657,7 +662,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
// Our blas is only one geometry, but could be made of many geometries
|
// Our blas is only one geometry, but could be made of many geometries
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -671,7 +676,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -685,16 +690,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -709,25 +714,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -756,16 +761,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -791,8 +797,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -857,17 +863,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,16 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +43,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +66,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +98,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,41 +119,41 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@
|
||||||
// at the top of imgui.cpp.
|
// at the top of imgui.cpp.
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -40,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -125,7 +125,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -148,7 +148,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -164,7 +164,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -174,8 +175,8 @@ int main(int argc, char** argv)
|
||||||
helloVk.initGUI(0); // Using sub-pass 0
|
helloVk.initGUI(0); // Using sub-pass 0
|
||||||
|
|
||||||
// Creation of the example
|
// Creation of the example
|
||||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
|
|
||||||
helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths));
|
helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths));
|
||||||
|
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
|
||||||
|
|
||||||
|
|
||||||
helloVk.createOffscreenRender();
|
helloVk.createOffscreenRender();
|
||||||
|
|
@ -242,7 +243,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -294,7 +296,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +59,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -441,7 +441,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -471,49 +471,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -550,13 +555,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -570,10 +576,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -582,8 +588,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -621,13 +626,13 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
|
|
@ -658,7 +663,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -685,12 +690,12 @@ void HelloVulkan::createTopLevelAS()
|
||||||
m_tlas.reserve(m_objInstance.size());
|
m_tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0;
|
rayInst.hitGroupId = 0;
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
m_tlas.emplace_back(rayInst);
|
m_tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
|
m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
|
||||||
|
|
@ -706,25 +711,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -753,16 +758,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -788,8 +794,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -853,17 +859,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -927,24 +933,24 @@ void HelloVulkan::animationInstances(float time)
|
||||||
* nvmath::translation_mat4(radius, 0.f, 0.f);
|
* nvmath::translation_mat4(radius, 0.f, 0.f);
|
||||||
inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform));
|
inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform));
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance& tinst = m_tlas[wusonIdx];
|
nvvk::RaytracingBuilderKHR::Instance& tinst = m_tlas[wusonIdx];
|
||||||
tinst.transform = inst.transform;
|
tinst.transform = inst.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the buffer
|
// Update the buffer
|
||||||
vk::DeviceSize bufferSize = m_objInstance.size() * sizeof(ObjInstance);
|
vk::DeviceSize bufferSize = m_objInstance.size() * sizeof(ObjInstance);
|
||||||
nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc,
|
nvvk::Buffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc,
|
||||||
vk::MemoryPropertyFlagBits::eHostVisible);
|
vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
// Copy data to staging buffer
|
// Copy data to staging buffer
|
||||||
auto* gInst = m_alloc.map(stagingBuffer);
|
auto* gInst = m_alloc.map(stagingBuffer);
|
||||||
memcpy(gInst, m_objInstance.data(), bufferSize);
|
memcpy(gInst, m_objInstance.data(), bufferSize);
|
||||||
m_alloc.unmap(stagingBuffer);
|
m_alloc.unmap(stagingBuffer);
|
||||||
// Copy staging buffer to the Scene Description buffer
|
// Copy staging buffer to the Scene Description buffer
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
|
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
|
||||||
m_debug.endLabel(cmdBuf);
|
m_debug.endLabel(cmdBuf);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
m_alloc.destroy(stagingBuffer);
|
m_alloc.destroy(stagingBuffer);
|
||||||
|
|
||||||
m_rtBuilder.updateTlasMatrices(m_tlas);
|
m_rtBuilder.updateTlasMatrices(m_tlas);
|
||||||
|
|
@ -957,8 +963,8 @@ void HelloVulkan::animationObject(float time)
|
||||||
|
|
||||||
updateCompDescriptors(model.vertexBuffer);
|
updateCompDescriptors(model.vertexBuffer);
|
||||||
|
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
|
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
|
||||||
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0,
|
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0,
|
||||||
|
|
@ -966,27 +972,26 @@ void HelloVulkan::animationObject(float time)
|
||||||
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
|
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
|
||||||
&time);
|
&time);
|
||||||
cmdBuf.dispatch(model.nbVertices, 1, 1);
|
cmdBuf.dispatch(model.nbVertices, 1, 1);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// #VK_compute
|
// #VK_compute
|
||||||
void HelloVulkan::createCompDescriptors()
|
void HelloVulkan::createCompDescriptors()
|
||||||
{
|
{
|
||||||
m_compDescSetLayoutBind.emplace_back(vk::DescriptorSetLayoutBinding(
|
m_compDescSetLayoutBind.addBinding(vk::DescriptorSetLayoutBinding(
|
||||||
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
|
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
|
||||||
|
|
||||||
m_compDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_compDescSetLayoutBind);
|
m_compDescSetLayout = m_compDescSetLayoutBind.createLayout(m_device);
|
||||||
m_compDescPool = nvvkpp::util::createDescriptorPool(m_device, m_compDescSetLayoutBind, 1);
|
m_compDescPool = m_compDescSetLayoutBind.createPool(m_device, 1);
|
||||||
m_compDescSet = nvvkpp::util::createDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
|
m_compDescSet = nvvk::allocateDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelloVulkan::updateCompDescriptors(nvvkBuffer& vertex)
|
void HelloVulkan::updateCompDescriptors(nvvk::Buffer& vertex)
|
||||||
{
|
{
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_compDescSetLayoutBind.makeWrite(m_compDescSet, 0, &dbiUnif));
|
||||||
nvvkpp::util::createWrite(m_compDescSet, m_compDescSetLayoutBind[0], &dbiUnif));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -999,9 +1004,9 @@ void HelloVulkan::createCompPipelines()
|
||||||
vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout};
|
vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout};
|
||||||
|
|
||||||
computePipelineCreateInfo.stage =
|
computePipelineCreateInfo.stage =
|
||||||
nvvkpp::util::loadShader(m_device,
|
nvvk::createShaderStageInfo(m_device,
|
||||||
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
|
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
|
||||||
vk::ShaderStageFlagBits::eCompute);
|
VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
|
m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
|
||||||
m_device.destroy(computePipelineCreateInfo.stage.module);
|
m_device.destroy(computePipelineCreateInfo.stage.module);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +97,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,44 +118,44 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> m_tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> m_tlas;
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> m_blas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> m_blas;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
@ -172,13 +171,13 @@ public:
|
||||||
|
|
||||||
// #VK_compute
|
// #VK_compute
|
||||||
void createCompDescriptors();
|
void createCompDescriptors();
|
||||||
void updateCompDescriptors(nvvkBuffer& vertex);
|
void updateCompDescriptors(nvvk::Buffer& vertex);
|
||||||
void createCompPipelines();
|
void createCompPipelines();
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_compDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_compDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_compDescPool;
|
vk::DescriptorPool m_compDescPool;
|
||||||
vk::DescriptorSetLayout m_compDescSetLayout;
|
vk::DescriptorSetLayout m_compDescSetLayout;
|
||||||
vk::DescriptorSet m_compDescSet;
|
vk::DescriptorSet m_compDescSet;
|
||||||
vk::Pipeline m_compPipeline;
|
vk::Pipeline m_compPipeline;
|
||||||
vk::PipelineLayout m_compPipelineLayout;
|
vk::PipelineLayout m_compPipelineLayout;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,12 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -124,7 +126,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -148,7 +150,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -163,7 +165,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -256,7 +259,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -308,7 +312,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +59,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,34 +101,34 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj,
|
vkDS(1, vkDT::eStorageBuffer, nbObj,
|
||||||
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1,
|
vkDS(2, vkDT::eStorageBuffer, 1,
|
||||||
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj,
|
vkDS(4, vkDT::eStorageBuffer, nbObj,
|
||||||
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -138,9 +140,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -154,11 +156,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -166,7 +167,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -192,19 +193,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,8 +237,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -249,8 +249,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -285,12 +285,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,21 +310,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -351,16 +351,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -437,7 +437,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -467,49 +467,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -546,13 +551,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -566,10 +572,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -578,8 +584,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -617,13 +622,13 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
|
|
@ -655,7 +660,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -665,7 +670,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -679,16 +684,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -703,25 +708,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -750,16 +755,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -785,11 +791,11 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
vk::ShaderModule ahitSM =
|
vk::ShaderModule ahitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
||||||
|
|
@ -855,17 +861,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +97,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,42 +118,42 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
void resetFrame();
|
void resetFrame();
|
||||||
void updateFrame();
|
void updateFrame();
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
int m_maxFrames{10000};
|
int m_maxFrames{10000};
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,11 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -124,7 +125,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -148,7 +149,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -163,7 +164,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -244,7 +246,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -296,7 +299,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +59,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
asCreate.setIndexType(vk::IndexType::eUint32);
|
asCreate.setIndexType(vk::IndexType::eUint32);
|
||||||
|
|
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -744,16 +749,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -779,8 +785,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -795,14 +801,13 @@ void HelloVulkan::createRtPipeline()
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
|
||||||
|
|
||||||
vk::ShaderModule call0 =
|
vk::ShaderModule call0 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device,
|
||||||
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
|
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
|
||||||
vk::ShaderModule call1 =
|
vk::ShaderModule call1 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device,
|
||||||
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
|
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
|
||||||
vk::ShaderModule call2 =
|
vk::ShaderModule call2 =
|
||||||
nvvkpp::util::createShaderModule(m_device,
|
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
|
||||||
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
|
|
||||||
|
|
||||||
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
|
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
|
||||||
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
|
||||||
|
|
@ -874,17 +879,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,15 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +43,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +66,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -101,19 +101,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -122,41 +122,41 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -141,7 +142,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -165,7 +166,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -180,7 +181,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -258,7 +260,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -310,7 +313,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -60,25 +61,26 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(NVVK_ALLOC_DEDICATED)
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(NVVK_ALLOC_DMA)
|
||||||
m_memAllocator.init(device, physicalDevice);
|
m_memAllocator.init(device, physicalDevice);
|
||||||
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true);
|
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, true);
|
||||||
m_alloc.init(device, &m_memAllocator);
|
m_alloc.init(device, physicalDevice, &m_memAllocator);
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(NVVK_ALLOC_VMA)
|
||||||
VmaAllocatorCreateInfo allocatorInfo = {};
|
VmaAllocatorCreateInfo allocatorInfo = {};
|
||||||
|
allocatorInfo.instance = instance;
|
||||||
allocatorInfo.physicalDevice = physicalDevice;
|
allocatorInfo.physicalDevice = physicalDevice;
|
||||||
allocatorInfo.device = device;
|
allocatorInfo.device = device;
|
||||||
allocatorInfo.flags |=
|
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||||
VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
|
|
||||||
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
|
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
|
||||||
m_alloc.init(device, m_memAllocator);
|
m_alloc.init(device, physicalDevice, m_memAllocator);
|
||||||
#endif
|
#endif
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -98,20 +100,9 @@ void HelloVulkan::updateUniformBuffer()
|
||||||
// #VKRay
|
// #VKRay
|
||||||
ubo.projInverse = nvmath::invert(ubo.proj);
|
ubo.projInverse = nvmath::invert(ubo.proj);
|
||||||
|
|
||||||
#if defined(ALLOC_DEDICATED)
|
void* data = m_alloc.map(m_cameraMat);
|
||||||
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
|
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
memcpy(data, &ubo, sizeof(ubo));
|
||||||
m_device.unmapMemory(m_cameraMat.allocation);
|
m_alloc.unmap(m_cameraMat);
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
void* data = m_memAllocator.map(m_cameraMat.allocation);
|
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
|
||||||
m_memAllocator.unmap(m_cameraMat.allocation);
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
void* data;
|
|
||||||
vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data);
|
|
||||||
memcpy(data, &ubo, sizeof(ubo));
|
|
||||||
vmaUnmapMemory(m_memAllocator, m_cameraMat.allocation);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -126,31 +117,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -162,9 +153,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -178,11 +169,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -190,7 +180,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -216,19 +206,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,8 +250,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -273,8 +262,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -296,12 +285,7 @@ void HelloVulkan::createUniformBuffer()
|
||||||
using vkMP = vk::MemoryPropertyFlagBits;
|
using vkMP = vk::MemoryPropertyFlagBits;
|
||||||
|
|
||||||
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
|
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
|
||||||
#if defined(ALLOC_DEDICATED) || defined(ALLOC_DMA)
|
vkMP::eHostVisible | vkMP::eHostCoherent);
|
||||||
vkMP::eHostVisible | vkMP::eHostCoherent
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
VMA_MEMORY_USAGE_CPU_TO_GPU
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,12 +298,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,21 +323,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -380,16 +364,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -439,9 +422,10 @@ void HelloVulkan::destroyResources()
|
||||||
m_device.destroy(m_rtPipelineLayout);
|
m_device.destroy(m_rtPipelineLayout);
|
||||||
m_alloc.destroy(m_rtSBTBuffer);
|
m_alloc.destroy(m_rtSBTBuffer);
|
||||||
|
|
||||||
#if defined(ALLOC_DMA)
|
m_alloc.deinit();
|
||||||
|
#if defined(NVVK_ALLOC_DMA)
|
||||||
m_memAllocator.deinit();
|
m_memAllocator.deinit();
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(NVVK_ALLOC_VMA)
|
||||||
vmaDestroyAllocator(m_memAllocator);
|
vmaDestroyAllocator(m_memAllocator);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -472,7 +456,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -502,49 +486,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -581,13 +570,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -601,10 +591,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -613,8 +603,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -652,21 +641,15 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
#if defined(ALLOC_DEDICATED)
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
m_rtBuilder.setup(m_device, m_memAllocator, m_graphicsQueueIndex);
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
m_rtBuilder.setup(m_device, m_memAllocator, m_graphicsQueueIndex);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
asCreate.setIndexType(vk::IndexType::eUint32);
|
asCreate.setIndexType(vk::IndexType::eUint32);
|
||||||
|
|
@ -703,7 +686,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -717,16 +700,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -741,25 +724,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -788,16 +771,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -823,8 +807,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -888,17 +872,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -27,29 +27,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
//#define ALLOC_DEDICATED
|
//#define NVVK_ALLOC_DEDICATED
|
||||||
#define ALLOC_DMA
|
#define NVVK_ALLOC_DMA
|
||||||
//#define ALLOC_VMA
|
//#define NVVK_ALLOC_VMA
|
||||||
|
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
|
|
||||||
#if defined(ALLOC_DEDICATED)
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
#elif defined(ALLOC_DMA)
|
|
||||||
#include "nvvkpp/allocator_dma_vkpp.hpp"
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDma;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDma;
|
|
||||||
#elif defined(ALLOC_VMA)
|
|
||||||
#include "nvvkpp/allocator_vma_vkpp.hpp"
|
|
||||||
using nvvkBuffer = nvvkpp::BufferVma;
|
|
||||||
using nvvkTexture = nvvkpp::TextureVma;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -58,10 +46,11 @@ using nvvkTexture = nvvkpp::TextureVma;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -80,12 +69,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -112,28 +101,28 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
#if defined(ALLOC_DEDICATED)
|
#if defined(NVVK_ALLOC_DEDICATED)
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
#elif defined(ALLOC_DMA)
|
#elif defined(NVVK_ALLOC_DMA)
|
||||||
nvvkpp::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvk::DeviceMemoryAllocator m_memAllocator;
|
nvvk::DeviceMemoryAllocator m_memAllocator;
|
||||||
#elif defined(ALLOC_VMA)
|
#elif defined(NVVK_ALLOC_VMA)
|
||||||
nvvkpp::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
VmaAllocator m_memAllocator;
|
VmaAllocator m_memAllocator;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -142,41 +131,41 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -40,10 +41,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -125,7 +126,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -149,7 +150,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -164,7 +165,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -258,7 +260,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -310,7 +313,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
#include "nvvk/shaders_vk.hpp"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
|
|
@ -59,11 +60,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -100,34 +102,34 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(vkDS(1, vkDT::eStorageBuffer, nbObj + 1,
|
m_descSetLayoutBind.addBinding(vkDS(1, vkDT::eStorageBuffer, nbObj + 1,
|
||||||
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials Index (binding = 4)
|
// Materials Index (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj + 1, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj + 1, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing spheres (binding = 7)
|
// Storing spheres (binding = 7)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(7, vkDT::eStorageBuffer, 1, vkSS::eClosestHitKHR | vkSS::eIntersectionKHR));
|
vkDS(7, vkDT::eStorageBuffer, 1, vkSS::eClosestHitKHR | vkSS::eIntersectionKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -139,9 +141,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -158,14 +160,13 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiMat.emplace_back(m_spheresMatColorBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiMat.emplace_back(m_spheresMatColorBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiMatIdx.emplace_back(m_spheresMatIndexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiMatIdx.emplace_back(m_spheresMatIndexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
|
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &dbiSpheres));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &dbiSpheres));
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -173,7 +174,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -199,19 +200,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,8 +244,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -256,8 +256,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -292,12 +292,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,21 +317,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -358,16 +358,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -449,7 +449,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -479,49 +479,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -558,13 +563,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -578,10 +584,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -590,8 +596,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -629,13 +634,13 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
|
|
@ -667,7 +672,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -677,7 +682,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Returning the ray tracing geometry used for the BLAS, containing all spheres
|
// Returning the ray tracing geometry used for the BLAS, containing all spheres
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
|
||||||
{
|
{
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
|
||||||
|
|
@ -705,7 +710,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
|
||||||
offset.setPrimitiveOffset(0);
|
offset.setPrimitiveOffset(0);
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -759,13 +764,13 @@ void HelloVulkan::createSpheres()
|
||||||
|
|
||||||
// Creating all buffers
|
// Creating all buffers
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
|
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
|
||||||
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress);
|
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress);
|
||||||
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
|
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
|
||||||
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
|
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
// Debug information
|
// Debug information
|
||||||
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
|
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
|
||||||
|
|
@ -777,7 +782,7 @@ void HelloVulkan::createSpheres()
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -798,27 +803,27 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the blas containing all spheres
|
// Add the blas containing all spheres
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[0].transform; // Position of the instance
|
rayInst.transform = m_objInstance[0].transform; // Position of the instance
|
||||||
rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
|
rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
|
||||||
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
|
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
|
||||||
rayInst.hitGroupId = 1; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 1; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -834,25 +839,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -881,16 +886,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -916,8 +922,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group0 - Closest Hit
|
// Hit Group0 - Closest Hit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
{
|
{
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
|
|
@ -930,11 +936,11 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group1 - Closest Hit + Intersection (procedural)
|
// Hit Group1 - Closest Hit + Intersection (procedural)
|
||||||
vk::ShaderModule chit2SM =
|
vk::ShaderModule chit2SM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
||||||
vk::ShaderModule rintSM =
|
vk::ShaderModule rintSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
|
||||||
{
|
{
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -1003,17 +1009,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +97,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,41 +118,41 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
@ -176,12 +175,12 @@ public:
|
||||||
nvmath::vec3f maximum;
|
nvmath::vec3f maximum;
|
||||||
};
|
};
|
||||||
|
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
|
nvvk::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
|
||||||
|
|
||||||
std::vector<Sphere> m_spheres; // All spheres
|
std::vector<Sphere> m_spheres; // All spheres
|
||||||
nvvkBuffer m_spheresBuffer; // Buffer holding the spheres
|
nvvk::Buffer m_spheresBuffer; // Buffer holding the spheres
|
||||||
nvvkBuffer m_spheresAabbBuffer; // Buffer of all Aabb
|
nvvk::Buffer m_spheresAabbBuffer; // Buffer of all Aabb
|
||||||
nvvkBuffer m_spheresMatColorBuffer; // Multiple materials
|
nvvk::Buffer m_spheresMatColorBuffer; // Multiple materials
|
||||||
nvvkBuffer m_spheresMatIndexBuffer; // Define which sphere uses which material
|
nvvk::Buffer m_spheresMatIndexBuffer; // Define which sphere uses which material
|
||||||
void createSpheres();
|
void createSpheres();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -124,7 +125,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -148,7 +149,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -163,7 +164,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -241,7 +243,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -293,7 +296,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +59,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
asCreate.setIndexType(vk::IndexType::eUint32);
|
asCreate.setIndexType(vk::IndexType::eUint32);
|
||||||
|
|
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -744,16 +749,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -779,8 +785,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -844,17 +850,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +97,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,42 +118,42 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
void resetFrame();
|
void resetFrame();
|
||||||
void updateFrame();
|
void updateFrame();
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
int m_maxFrames{100};
|
int m_maxFrames{100};
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -132,7 +133,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -156,7 +157,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -171,7 +172,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -254,7 +256,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -306,7 +309,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +59,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(m_textures[i].descriptor);
|
diit.push_back(m_textures[i].descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
asCreate.setIndexType(vk::IndexType::eUint32);
|
asCreate.setIndexType(vk::IndexType::eUint32);
|
||||||
|
|
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -673,17 +678,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.hitGroupId = m_objInstance[i].hitgroup; // Using the hit group set in main
|
||||||
rayInst.hitGroupId = m_objInstance[i].hitgroup;
|
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -698,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -745,16 +749,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -780,11 +785,11 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
vk::ShaderModule chit2SM =
|
vk::ShaderModule chit2SM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -893,17 +898,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
|
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -99,19 +98,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -120,41 +119,41 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,9 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -124,7 +124,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -148,7 +148,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -163,7 +163,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -251,7 +252,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -303,7 +305,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,13 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +58,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,33 +100,33 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// The top level acceleration structure
|
// The top level acceleration structure
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(7, vkDT::eAccelerationStructureKHR, 1, vkSS::eFragment));
|
vkDS(7, vkDT::eAccelerationStructureKHR, 1, vkSS::eFragment));
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -137,9 +138,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -153,11 +154,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -165,13 +165,13 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(texture.descriptor);
|
diit.push_back(texture.descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &descASInfo));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &descASInfo));
|
||||||
|
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
|
|
@ -198,19 +198,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,8 +242,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -255,8 +254,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -291,12 +290,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,21 +315,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
// Creating the VKImage
|
// Creating the VKImage
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
// Setting up the descriptor used by the shader
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
texture.descriptor =
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -357,16 +356,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -438,7 +436,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -467,49 +465,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -546,13 +549,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -566,10 +570,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -578,8 +582,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -617,13 +620,13 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
// Setting up the creation info of acceleration structure
|
// Setting up the creation info of acceleration structure
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
|
|
@ -660,7 +663,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
offset.setTransformOffset(0);
|
offset.setTransformOffset(0);
|
||||||
|
|
||||||
// Our blas is only one geometry, but could be made of many geometries
|
// Our blas is only one geometry, but could be made of many geometries
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
blas.asGeometry.emplace_back(asGeom);
|
blas.asGeometry.emplace_back(asGeom);
|
||||||
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
blas.asCreateGeometryInfo.emplace_back(asCreate);
|
||||||
blas.asBuildOffsetInfo.emplace_back(offset);
|
blas.asBuildOffsetInfo.emplace_back(offset);
|
||||||
|
|
@ -674,7 +677,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -688,16 +691,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +97,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,25 +118,25 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,10 @@
|
||||||
// at the top of imgui.cpp.
|
// at the top of imgui.cpp.
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -40,10 +42,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -125,7 +127,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -148,7 +150,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -164,7 +166,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -238,7 +241,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -297,7 +301,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
|
||||||
|
|
||||||
#include "hello_vulkan.h"
|
#include "hello_vulkan.h"
|
||||||
#include "nvh//cameramanipulator.hpp"
|
#include "nvh//cameramanipulator.hpp"
|
||||||
#include "nvvkpp/descriptorsets_vkpp.hpp"
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
#include "nvvkpp/pipeline_vkpp.hpp"
|
#include "nvvk/pipeline_vk.hpp"
|
||||||
|
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/renderpass_vkpp.hpp"
|
#include "nvvk/renderpasses_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
#include "nvvk/shaders_vk.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Holding the camera matrices
|
// Holding the camera matrices
|
||||||
struct CameraMatrices
|
struct CameraMatrices
|
||||||
|
|
@ -58,11 +59,12 @@ struct CameraMatrices
|
||||||
// Keep the handle on the device
|
// Keep the handle on the device
|
||||||
// Initialize the tool to do all our allocations: buffers, images
|
// Initialize the tool to do all our allocations: buffers, images
|
||||||
//
|
//
|
||||||
void HelloVulkan::setup(const vk::Device& device,
|
void HelloVulkan::setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily)
|
uint32_t queueFamily)
|
||||||
{
|
{
|
||||||
AppBase::setup(device, physicalDevice, queueFamily);
|
AppBase::setup(instance, device, physicalDevice, queueFamily);
|
||||||
m_alloc.init(device, physicalDevice);
|
m_alloc.init(device, physicalDevice);
|
||||||
m_debug.setup(m_device);
|
m_debug.setup(m_device);
|
||||||
}
|
}
|
||||||
|
|
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
|
||||||
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||||
|
|
||||||
// Camera matrices (binding = 0)
|
// Camera matrices (binding = 0)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
|
||||||
// Materials (binding = 1)
|
// Materials (binding = 1)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Scene description (binding = 2)
|
// Scene description (binding = 2)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Textures (binding = 3)
|
// Textures (binding = 3)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Materials (binding = 4)
|
// Materials (binding = 4)
|
||||||
m_descSetLayoutBind.emplace_back(
|
m_descSetLayoutBind.addBinding(
|
||||||
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
|
||||||
// Storing vertices (binding = 5)
|
// Storing vertices (binding = 5)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
// Storing indices (binding = 6)
|
// Storing indices (binding = 6)
|
||||||
m_descSetLayoutBind.emplace_back( //
|
m_descSetLayoutBind.addBinding( //
|
||||||
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
|
||||||
|
|
||||||
|
|
||||||
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
|
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||||
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
|
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||||
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
|
|
||||||
// Camera matrices and scene description
|
// Camera matrices and scene description
|
||||||
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||||
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc));
|
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||||
|
|
||||||
// All material buffers, 1 buffer per OBJ
|
// All material buffers, 1 buffer per OBJ
|
||||||
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
std::vector<vk::DescriptorBufferInfo> dbiMat;
|
||||||
|
|
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||||
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
|
|
||||||
|
|
||||||
// All texture samplers
|
// All texture samplers
|
||||||
std::vector<vk::DescriptorImageInfo> diit;
|
std::vector<vk::DescriptorImageInfo> diit;
|
||||||
|
|
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
|
||||||
{
|
{
|
||||||
diit.push_back(m_textures[i].descriptor);
|
diit.push_back(m_textures[i].descriptor);
|
||||||
}
|
}
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data()));
|
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||||
|
|
||||||
// Writing the information
|
// Writing the information
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
|
|
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
|
||||||
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
|
||||||
|
|
||||||
// Creating the Pipeline
|
// Creating the Pipeline
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
|
||||||
gpb.depthStencilState = {true};
|
gpb.depthStencilState.depthTestEnable = true;
|
||||||
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
|
||||||
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
|
||||||
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
|
gpb.addBindingDescription({0, sizeof(VertexObj)});
|
||||||
gpb.vertexInputState.attributeDescriptions = {
|
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
||||||
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
|
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
||||||
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
|
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
||||||
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
|
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
|
||||||
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
|
|
||||||
|
|
||||||
m_graphicsPipeline = gpb.create();
|
m_graphicsPipeline = gpb.createPipeline();
|
||||||
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
m_debug.setObjectName(m_graphicsPipeline, "Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||||
|
|
||||||
// Create the buffers on Device and copy vertices, indices and materials
|
// Create the buffers on Device and copy vertices, indices and materials
|
||||||
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||||
model.vertexBuffer =
|
model.vertexBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
|
||||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||||
|
|
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
||||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
|
||||||
// Creates all textures found
|
// Creates all textures found
|
||||||
createTextureImages(cmdBuf, loader.m_textures);
|
createTextureImages(cmdBuf, loader.m_textures);
|
||||||
cmdBufGet.flushCommandBuffer(cmdBuf);
|
cmdBufGet.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
|
|
||||||
std::string objNb = std::to_string(instance.objIndex);
|
std::string objNb = std::to_string(instance.objIndex);
|
||||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||||
|
|
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
|
||||||
void HelloVulkan::createSceneDescriptionBuffer()
|
void HelloVulkan::createSceneDescriptionBuffer()
|
||||||
{
|
{
|
||||||
using vkBU = vk::BufferUsageFlagBits;
|
using vkBU = vk::BufferUsageFlagBits;
|
||||||
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
|
||||||
|
|
||||||
auto cmdBuf = cmdGen.createCommandBuffer();
|
auto cmdBuf = cmdGen.createCommandBuffer();
|
||||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
|
||||||
cmdGen.flushCommandBuffer(cmdBuf);
|
cmdGen.submitAndWait(cmdBuf);
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
// If no textures are present, create a dummy one to accommodate the pipeline layout
|
||||||
if(textures.empty() && m_textures.empty())
|
if(textures.empty() && m_textures.empty())
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::Texture texture;
|
||||||
|
|
||||||
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
|
||||||
vk::DeviceSize bufferSize = sizeof(color);
|
vk::DeviceSize bufferSize = sizeof(color);
|
||||||
auto imgSize = vk::Extent2D(1, 1);
|
auto imgSize = vk::Extent2D(1, 1);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
|
||||||
|
|
||||||
|
// Creating the dummy texure
|
||||||
|
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
||||||
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
// Creating the VKImage
|
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
|
|
||||||
// Setting up the descriptor used by the shader
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eShaderReadOnlyOptimal);
|
vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
|
||||||
|
|
||||||
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
|
||||||
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
auto imgSize = vk::Extent2D(texWidth, texHeight);
|
||||||
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true);
|
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
nvvkTexture texture;
|
nvvk::ImageDedicated image =
|
||||||
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
|
||||||
|
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
|
||||||
|
vk::ImageViewCreateInfo ivInfo =
|
||||||
|
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
|
||||||
|
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
|
||||||
|
|
||||||
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
|
|
||||||
imageCreateInfo.mipLevels);
|
|
||||||
texture.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
|
|
||||||
m_textures.push_back(texture);
|
m_textures.push_back(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
|
||||||
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
|
||||||
m_pushConstant);
|
m_pushConstant);
|
||||||
|
|
||||||
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset);
|
cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
|
||||||
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
|
||||||
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
|
||||||
m_alloc.destroy(m_offscreenDepth);
|
m_alloc.destroy(m_offscreenDepth);
|
||||||
|
|
||||||
// Creating the color image
|
// Creating the color image
|
||||||
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
|
{
|
||||||
vk::ImageUsageFlagBits::eColorAttachment
|
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
|
||||||
| vk::ImageUsageFlagBits::eSampled
|
vk::ImageUsageFlagBits::eColorAttachment
|
||||||
| vk::ImageUsageFlagBits::eStorage);
|
| vk::ImageUsageFlagBits::eSampled
|
||||||
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
|
| vk::ImageUsageFlagBits::eStorage);
|
||||||
|
|
||||||
m_offscreenColor.descriptor =
|
|
||||||
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
|
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
|
||||||
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
|
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
|
||||||
|
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
|
||||||
|
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
// Creating the depth buffer
|
// Creating the depth buffer
|
||||||
auto depthCreateInfo =
|
auto depthCreateInfo =
|
||||||
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
|
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
vk::ImageUsageFlagBits::eDepthStencilAttachment);
|
||||||
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
|
{
|
||||||
|
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo depthStencilView;
|
vk::ImageViewCreateInfo depthStencilView;
|
||||||
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
depthStencilView.setViewType(vk::ImageViewType::e2D);
|
||||||
depthStencilView.setFormat(m_offscreenDepthFormat);
|
depthStencilView.setFormat(m_offscreenDepthFormat);
|
||||||
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
|
||||||
depthStencilView.setImage(m_offscreenDepth.image);
|
depthStencilView.setImage(image.image);
|
||||||
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
|
|
||||||
|
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting the image layout for both color and depth
|
// Setting the image layout for both color and depth
|
||||||
{
|
{
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
auto cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eGeneral);
|
vk::ImageLayout::eGeneral);
|
||||||
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
|
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
vk::ImageAspectFlagBits::eDepth);
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a renderpass for the offscreen
|
// Creating a renderpass for the offscreen
|
||||||
if(!m_offscreenRenderPass)
|
if(!m_offscreenRenderPass)
|
||||||
{
|
{
|
||||||
m_offscreenRenderPass =
|
m_offscreenRenderPass =
|
||||||
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
|
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
|
||||||
1, true, true, vk::ImageLayout::eGeneral,
|
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
|
||||||
vk::ImageLayout::eGeneral);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating the frame buffer for offscreen
|
// Creating the frame buffer for offscreen
|
||||||
|
|
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
|
||||||
// Pipeline: completely generic, no vertices
|
// Pipeline: completely generic, no vertices
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
|
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
|
||||||
|
m_renderPass);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eVertex);
|
vk::ShaderStageFlagBits::eVertex);
|
||||||
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
|
||||||
vk::ShaderStageFlagBits::eFragment);
|
vk::ShaderStageFlagBits::eFragment);
|
||||||
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
|
||||||
m_postPipeline = pipelineGenerator.create();
|
m_postPipeline = pipelineGenerator.createPipeline();
|
||||||
m_debug.setObjectName(m_postPipeline, "post");
|
m_debug.setObjectName(m_postPipeline, "post");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
|
||||||
using vkDT = vk::DescriptorType;
|
using vkDT = vk::DescriptorType;
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
|
|
||||||
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
|
||||||
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
|
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
|
||||||
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
|
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
|
||||||
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
|
||||||
void HelloVulkan::updatePostDescriptorSet()
|
void HelloVulkan::updatePostDescriptorSet()
|
||||||
{
|
{
|
||||||
vk::WriteDescriptorSet writeDescriptorSets =
|
vk::WriteDescriptorSet writeDescriptorSets =
|
||||||
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0],
|
m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
|
||||||
&m_offscreenColor.descriptor);
|
|
||||||
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
|
||||||
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
|
||||||
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
|
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
|
||||||
//
|
//
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas blas;
|
nvvk::RaytracingBuilderKHR::Blas blas;
|
||||||
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
|
||||||
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
|
||||||
asCreate.setIndexType(vk::IndexType::eUint32);
|
asCreate.setIndexType(vk::IndexType::eUint32);
|
||||||
|
|
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
|
||||||
void HelloVulkan::createBottomLevelAS()
|
void HelloVulkan::createBottomLevelAS()
|
||||||
{
|
{
|
||||||
// BLAS - Storing each primitive in a geometry
|
// BLAS - Storing each primitive in a geometry
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
|
||||||
allBlas.reserve(m_objModel.size());
|
allBlas.reserve(m_objModel.size());
|
||||||
for(const auto& obj : m_objModel)
|
for(const auto& obj : m_objModel)
|
||||||
{
|
{
|
||||||
|
|
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
|
||||||
|
|
||||||
void HelloVulkan::createTopLevelAS()
|
void HelloVulkan::createTopLevelAS()
|
||||||
{
|
{
|
||||||
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
|
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||||
tlas.reserve(m_objInstance.size());
|
tlas.reserve(m_objInstance.size());
|
||||||
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
|
||||||
{
|
{
|
||||||
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
|
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||||
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
rayInst.transform = m_objInstance[i].transform; // Position of the instance
|
||||||
rayInst.instanceId = i; // gl_InstanceID
|
rayInst.instanceId = i; // gl_InstanceID
|
||||||
rayInst.blasId = m_objInstance[i].objIndex;
|
rayInst.blasId = m_objInstance[i].objIndex;
|
||||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||||
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
|
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||||
tlas.emplace_back(rayInst);
|
tlas.emplace_back(rayInst);
|
||||||
}
|
}
|
||||||
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
|
||||||
|
|
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
|
||||||
using vkSS = vk::ShaderStageFlagBits;
|
using vkSS = vk::ShaderStageFlagBits;
|
||||||
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
using vkDSLB = vk::DescriptorSetLayoutBinding;
|
||||||
|
|
||||||
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
|
||||||
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
|
||||||
m_rtDescSetLayoutBind.emplace_back(
|
m_rtDescSetLayoutBind.addBinding(
|
||||||
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
|
||||||
|
|
||||||
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
|
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
|
||||||
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
|
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
|
||||||
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
|
||||||
|
|
||||||
|
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
|
||||||
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
|
||||||
descASInfo.setAccelerationStructureCount(1);
|
descASInfo.setAccelerationStructureCount(1);
|
||||||
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
|
descASInfo.setPAccelerationStructures(&tlas);
|
||||||
vk::DescriptorImageInfo imageInfo{
|
vk::DescriptorImageInfo imageInfo{
|
||||||
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writes;
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
writes.emplace_back(
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
|
||||||
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
|
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
|
||||||
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
|
|
||||||
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -744,16 +749,17 @@ void HelloVulkan::createRtPipeline()
|
||||||
std::vector<std::string> paths = defaultSearchPaths;
|
std::vector<std::string> paths = defaultSearchPaths;
|
||||||
|
|
||||||
vk::ShaderModule raygenSM =
|
vk::ShaderModule raygenSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
|
||||||
vk::ShaderModule missSM =
|
vk::ShaderModule missSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
|
||||||
|
|
||||||
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
// The second miss shader is invoked when a shadow ray misses the geometry. It
|
||||||
// simply indicates that no occlusion has been found
|
// simply indicates that no occlusion has been found
|
||||||
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
|
vk::ShaderModule shadowmissSM =
|
||||||
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
nvvk::createShaderModule(m_device,
|
||||||
|
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
|
||||||
|
|
||||||
|
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
std::vector<vk::PipelineShaderStageCreateInfo> stages;
|
||||||
|
|
@ -779,8 +785,8 @@ void HelloVulkan::createRtPipeline()
|
||||||
|
|
||||||
// Hit Group - Closest Hit + AnyHit
|
// Hit Group - Closest Hit + AnyHit
|
||||||
vk::ShaderModule chitSM =
|
vk::ShaderModule chitSM =
|
||||||
nvvkpp::util::createShaderModule(m_device, //
|
nvvk::createShaderModule(m_device, //
|
||||||
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
|
||||||
|
|
||||||
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
|
||||||
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
|
||||||
|
|
@ -844,17 +850,17 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
shaderHandleStorage.data());
|
||||||
// Write the handles in the SBT
|
// Write the handles in the SBT
|
||||||
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
|
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
||||||
|
|
||||||
m_rtSBTBuffer =
|
m_rtSBTBuffer =
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
||||||
|
|
||||||
|
|
||||||
genCmdBuf.flushCommandBuffer(cmdBuf);
|
genCmdBuf.submitAndWait(cmdBuf);
|
||||||
|
|
||||||
m_alloc.flushStaging();
|
m_alloc.finalizeAndReleaseStaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,14 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
|
#define NVVK_ALLOC_DEDICATED
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/allocator_vk.hpp"
|
||||||
#include "nvvkpp/debug_util_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
|
#include "nvvk/debug_util_vk.hpp"
|
||||||
|
#include "nvvk/descriptorsets_vk.hpp"
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
#define ALLOC_DEDICATED
|
#include "nvvk/raytraceKHR_vk.hpp"
|
||||||
#include "nvvkpp/raytraceKHR_vkpp.hpp"
|
|
||||||
|
|
||||||
using nvvkBuffer = nvvkpp::BufferDedicated;
|
|
||||||
using nvvkTexture = nvvkpp::TextureDedicated;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
// Simple rasterizer of OBJ objects
|
// Simple rasterizer of OBJ objects
|
||||||
|
|
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
|
||||||
// - Rendering is done in an offscreen framebuffer
|
// - Rendering is done in an offscreen framebuffer
|
||||||
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
// - The image of the framebuffer is displayed in post-process in a full-screen quad
|
||||||
//
|
//
|
||||||
class HelloVulkan : public nvvkpp::AppBase
|
class HelloVulkan : public nvvk::AppBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setup(const vk::Device& device,
|
void setup(const vk::Instance& instance,
|
||||||
|
const vk::Device& device,
|
||||||
const vk::PhysicalDevice& physicalDevice,
|
const vk::PhysicalDevice& physicalDevice,
|
||||||
uint32_t queueFamily) override;
|
uint32_t queueFamily) override;
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
|
|
@ -66,12 +65,12 @@ public:
|
||||||
// The OBJ model
|
// The OBJ model
|
||||||
struct ObjModel
|
struct ObjModel
|
||||||
{
|
{
|
||||||
uint32_t nbIndices{0};
|
uint32_t nbIndices{0};
|
||||||
uint32_t nbVertices{0};
|
uint32_t nbVertices{0};
|
||||||
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
|
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
|
||||||
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
|
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
|
||||||
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance of the OBJ
|
// Instance of the OBJ
|
||||||
|
|
@ -98,19 +97,19 @@ public:
|
||||||
std::vector<ObjInstance> m_objInstance;
|
std::vector<ObjInstance> m_objInstance;
|
||||||
|
|
||||||
// Graphic pipeline
|
// Graphic pipeline
|
||||||
vk::PipelineLayout m_pipelineLayout;
|
vk::PipelineLayout m_pipelineLayout;
|
||||||
vk::Pipeline m_graphicsPipeline;
|
vk::Pipeline m_graphicsPipeline;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
|
nvvk::DescriptorSetBindings m_descSetLayoutBind;
|
||||||
vk::DescriptorPool m_descPool;
|
vk::DescriptorPool m_descPool;
|
||||||
vk::DescriptorSetLayout m_descSetLayout;
|
vk::DescriptorSetLayout m_descSetLayout;
|
||||||
vk::DescriptorSet m_descSet;
|
vk::DescriptorSet m_descSet;
|
||||||
|
|
||||||
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
|
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||||
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
|
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||||
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
|
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||||
|
|
||||||
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
|
||||||
nvvkpp::DebugUtil m_debug; // Utility to name objects
|
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||||
|
|
||||||
// #Post
|
// #Post
|
||||||
void createOffscreenRender();
|
void createOffscreenRender();
|
||||||
|
|
@ -119,41 +118,41 @@ public:
|
||||||
void updatePostDescriptorSet();
|
void updatePostDescriptorSet();
|
||||||
void drawPost(vk::CommandBuffer cmdBuf);
|
void drawPost(vk::CommandBuffer cmdBuf);
|
||||||
|
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_postDescPool;
|
vk::DescriptorPool m_postDescPool;
|
||||||
vk::DescriptorSetLayout m_postDescSetLayout;
|
vk::DescriptorSetLayout m_postDescSetLayout;
|
||||||
vk::DescriptorSet m_postDescSet;
|
vk::DescriptorSet m_postDescSet;
|
||||||
vk::Pipeline m_postPipeline;
|
vk::Pipeline m_postPipeline;
|
||||||
vk::PipelineLayout m_postPipelineLayout;
|
vk::PipelineLayout m_postPipelineLayout;
|
||||||
vk::RenderPass m_offscreenRenderPass;
|
vk::RenderPass m_offscreenRenderPass;
|
||||||
vk::Framebuffer m_offscreenFramebuffer;
|
vk::Framebuffer m_offscreenFramebuffer;
|
||||||
nvvkTexture m_offscreenColor;
|
nvvk::Texture m_offscreenColor;
|
||||||
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
|
||||||
nvvkTexture m_offscreenDepth;
|
nvvk::Texture m_offscreenDepth;
|
||||||
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
|
||||||
|
|
||||||
// #VKRay
|
// #VKRay
|
||||||
void initRayTracing();
|
void initRayTracing();
|
||||||
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
|
||||||
void createBottomLevelAS();
|
void createBottomLevelAS();
|
||||||
void createTopLevelAS();
|
void createTopLevelAS();
|
||||||
void createRtDescriptorSet();
|
void createRtDescriptorSet();
|
||||||
void updateRtDescriptorSet();
|
void updateRtDescriptorSet();
|
||||||
void createRtPipeline();
|
void createRtPipeline();
|
||||||
void createRtShaderBindingTable();
|
void createRtShaderBindingTable();
|
||||||
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
|
||||||
|
|
||||||
|
|
||||||
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
|
||||||
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
|
nvvk::RaytracingBuilderKHR m_rtBuilder;
|
||||||
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
|
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
|
||||||
vk::DescriptorPool m_rtDescPool;
|
vk::DescriptorPool m_rtDescPool;
|
||||||
vk::DescriptorSetLayout m_rtDescSetLayout;
|
vk::DescriptorSetLayout m_rtDescSetLayout;
|
||||||
vk::DescriptorSet m_rtDescSet;
|
vk::DescriptorSet m_rtDescSet;
|
||||||
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
|
||||||
vk::PipelineLayout m_rtPipelineLayout;
|
vk::PipelineLayout m_rtPipelineLayout;
|
||||||
vk::Pipeline m_rtPipeline;
|
vk::Pipeline m_rtPipeline;
|
||||||
nvvkBuffer m_rtSBTBuffer;
|
nvvk::Buffer m_rtSBTBuffer;
|
||||||
|
|
||||||
struct RtPushConstant
|
struct RtPushConstant
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
|
|
@ -39,10 +40,10 @@
|
||||||
#include "nvh/cameramanipulator.hpp"
|
#include "nvh/cameramanipulator.hpp"
|
||||||
#include "nvh/fileoperations.hpp"
|
#include "nvh/fileoperations.hpp"
|
||||||
#include "nvpsystem.hpp"
|
#include "nvpsystem.hpp"
|
||||||
#include "nvvkpp/appbase_vkpp.hpp"
|
#include "nvvk/appbase_vkpp.hpp"
|
||||||
#include "nvvkpp/commands_vkpp.hpp"
|
#include "nvvk/commands_vk.hpp"
|
||||||
#include "nvvkpp/context_vkpp.hpp"
|
#include "nvvk/context_vk.hpp"
|
||||||
#include "nvvkpp/utilities_vkpp.hpp"
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
@ -125,7 +126,7 @@ int main(int argc, char** argv)
|
||||||
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
|
||||||
|
|
||||||
// Requesting Vulkan extensions and layers
|
// Requesting Vulkan extensions and layers
|
||||||
nvvkpp::ContextCreateInfo contextInfo(true);
|
nvvk::ContextCreateInfo contextInfo(true);
|
||||||
contextInfo.setVersion(1, 2);
|
contextInfo.setVersion(1, 2);
|
||||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
@ -149,7 +150,7 @@ int main(int argc, char** argv)
|
||||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||||
|
|
||||||
// Creating Vulkan base application
|
// Creating Vulkan base application
|
||||||
nvvkpp::Context vkctx{};
|
nvvk::Context vkctx{};
|
||||||
vkctx.initInstance(contextInfo);
|
vkctx.initInstance(contextInfo);
|
||||||
// Find all compatible devices
|
// Find all compatible devices
|
||||||
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
|
||||||
|
|
@ -164,7 +165,8 @@ int main(int argc, char** argv)
|
||||||
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
|
||||||
vkctx.setGCTQueueWithPresent(surface);
|
vkctx.setGCTQueueWithPresent(surface);
|
||||||
|
|
||||||
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex);
|
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
|
||||||
|
vkctx.m_queueGCT.familyIndex);
|
||||||
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||||
helloVk.createDepthBuffer();
|
helloVk.createDepthBuffer();
|
||||||
helloVk.createRenderPass();
|
helloVk.createRenderPass();
|
||||||
|
|
@ -250,7 +252,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Clearing screen
|
// Clearing screen
|
||||||
vk::ClearValue clearValues[2];
|
vk::ClearValue clearValues[2];
|
||||||
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor));
|
clearValues[0].setColor(
|
||||||
|
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
|
||||||
clearValues[1].setDepthStencil({1.0f, 0});
|
clearValues[1].setDepthStencil({1.0f, 0});
|
||||||
|
|
||||||
// Offscreen render pass
|
// Offscreen render pass
|
||||||
|
|
@ -302,7 +305,6 @@ int main(int argc, char** argv)
|
||||||
helloVk.destroyResources();
|
helloVk.destroyResources();
|
||||||
helloVk.destroy();
|
helloVk.destroy();
|
||||||
|
|
||||||
vkctx.m_instance.destroySurfaceKHR(surface);
|
|
||||||
vkctx.deinit();
|
vkctx.deinit();
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "raycommon.glsl"
|
#include "raycommon.glsl"
|
||||||
#include "wavefront.glsl"
|
#include "wavefront.glsl"
|
||||||
|
|
||||||
hitAttributeEXT vec3 attribs;
|
hitAttributeEXT vec2 attribs;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue