Using Vulkan C API

This commit is contained in:
mklefrancois 2021-06-07 14:02:45 +02:00
parent b3e6d84807
commit e642e9dc3a
83 changed files with 8015 additions and 8163 deletions

View file

@ -63,39 +63,50 @@ executeCallableEXT(pushC.lightType, 0);
In `HelloVulkan::createRtPipeline()`, immediately after adding the closest-hit shader, we will add
3 callable shaders, for each type of light.
First create the shader modules
~~~~ C++
enum StageIndices
{
eRaygen,
eMiss,
eMiss2,
eClosestHit,
eCall0,
eCall1,
eCall2,
eShaderGroupCount
};
...
// Call0
stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/light_point.rcall.spv", true, defaultSearchPaths, true));
stage.stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;
stages[eCall0] = stage;
// Call1
stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/light_spot.rcall.spv", true, defaultSearchPaths, true));
stage.stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;
stages[eCall1] = stage;
// Call2
stage.module = nvvk::createShaderModule(m_device, nvh::loadFile("spv/light_inf.rcall.spv", true, defaultSearchPaths, true));
stage.stage = VK_SHADER_STAGE_CALLABLE_BIT_KHR;
stages[eCall2] = stage;
~~~~
Then 3 groups of callable shaders and the stages that goes with it.
~~~~ C++
// Callable shaders
vk::RayTracingShaderGroupCreateInfoKHR callGroup{vk::RayTracingShaderGroupTypeKHR::eGeneral,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 =
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size()));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
m_rtShaderGroups.push_back(callGroup);
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size()));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call1, "main"});
m_rtShaderGroups.push_back(callGroup);
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size()));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call2, "main"});
m_rtShaderGroups.push_back(callGroup);
group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
group.closestHitShader = VK_SHADER_UNUSED_KHR;
group.generalShader = eCall0;
m_rtShaderGroups.push_back(group);
group.generalShader = eCall1;
m_rtShaderGroups.push_back(group);
group.generalShader = eCall2;
m_rtShaderGroups.push_back(group);
~~~~
And at the end of the function, delete the shaders.
~~~~ C++
m_device.destroy(call0);
m_device.destroy(call1);
m_device.destroy(call2);
~~~~
#### Shaders
@ -106,29 +117,44 @@ Here are the source of all shaders
* [light_inf.rcall](shaders/light_inf.rcall)
### Passing Callable to traceRaysKHR
### Shading Binding Table
In this example, we will use the `nvvk::SBTWrapper`. It is using the information to create the ray tracing pipeline, to
create the buffers for the shading binding table.
In the `hello_vulkan.h` header, include the wrapper and add a new member.
~~~~C
#include "nvvk/sbtwrapper_vk.hpp"
...
nvvk::SBTWrapper m_sbtWrapper;
~~~~
In `HelloVulkan::initRayTracing()`, initialize it the following way.
~~~~C
m_sbtWrapper.setup(m_device, m_graphicsQueueIndex, &m_alloc, m_rtProperties);
~~~~
In `HelloVulkan::createRtPipeline()`, immediately after creating the pipeline call to `vkCreateRayTracingPipelinesKHR()`,
create the SBT with the following command.
~~~~C
m_sbtWrapper.create(m_rtPipeline, rayPipelineInfo);
~~~~
In `HelloVulkan::raytrace()`, we have to tell where the callable shader starts. Since they were added after the hit shader, we have in the SBT the following.
![SBT](images/sbt.png)
Therefore, the callable starts at `4 * progSize`
The SBT wrapper class give back the information we need. So instead of computing the various offsets, we can get directly the
`VkStridedDeviceAddressRegionKHR` for each group type.
~~~~ C++
std::array<stride, 4> strideAddresses{
stride{sbtAddress + 0u * progSize, progSize, progSize * 1}, // raygen
stride{sbtAddress + 1u * progSize, progSize, progSize * 2}, // miss
stride{sbtAddress + 3u * progSize, progSize, progSize * 1}, // hit
stride{sbtAddress + 4u * progSize, progSize, progSize * 1}}; // callable
~~~~
Then we can call `traceRaysKHR`
~~~~ C++
cmdBuf.traceRaysKHR(&strideAddresses[0], &strideAddresses[1], &strideAddresses[2],
&strideAddresses[3], //
m_size.width, m_size.height, 1); //
auto& regions = m_sbtWrapper.getRegions();
vkCmdTraceRaysKHR(cmdBuf, &regions[0], &regions[1], &regions[2], &regions[3], m_size.width, m_size.height, 1);
~~~~
## Calling the Callable Shaders