Using Vulkan C API
This commit is contained in:
parent
b3e6d84807
commit
e642e9dc3a
83 changed files with 8015 additions and 8163 deletions
|
|
@ -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.
|
||||
|
||||

|
||||
|
||||
|
||||
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, ®ions[0], ®ions[1], ®ions[2], ®ions[3], m_size.width, m_size.height, 1);
|
||||
~~~~
|
||||
|
||||
## Calling the Callable Shaders
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue