New documentation

This commit is contained in:
mklefrancois 2020-08-31 16:57:10 +02:00
parent e1dff2a4e7
commit 3465e08c77
31 changed files with 2825 additions and 55 deletions

View file

@ -235,6 +235,174 @@ As mentioned earlier, for the effect to work, we need to accumulate frames over
* [Storing or Updating](vkrt_tuto_jitter_cam.md.htm#toc1.4)
* [Application Frame Update](vkrt_tuto_jitter_cam.md.htm#toc2)
# Fixing Pipeline
The above code works, but might not work in the future. The reason is, the shadow ray `traceRayEXT` call in the Closest Hit shader, uses payload 1
and when intersecting the object, the any hit shader will be executed using payload 0. In the time of writing those lines, the driver add
padding and there are no side effect, but this is not how thing should be done.
Each `traceRayEXT` invocation should have as many Hit Groups as there are trace calls with different payload. For the other examples, it is still fine,
because we are using the `gl_RayFlagsSkipClosestHitShaderNV` flag and the closest hit shader (payload 0) will not be called and there were not
any hit or intersection shaders in the Hit Group. But in this example, the closest hit will be skiped, but not the any hit.
**To fix this**, we need to add another hit group.
This is how the current SBT looks like.
![](Images/anyhit_0.png)
And we need to add the following to the ray tracing pipeline, a copy of the previous Hit Group, with a new AnyHit using the proper payload.
![](Images/anyhit_01.png)
## New shaders
Create two new files `raytrace_0.ahit` and `raytrace_1.ahit`, and rename `raytrace.ahit` to `raytrace_ahit.glsl`
!!! WARNING CMake
Cmake need to be re-run to add the new files to the project.
In `raytrace_0.ahit` add the following code
~~~~ C
#version 460
#extension GL_GOOGLE_include_directive : enable
#define PAYLOAD_0
#include "raytrace_rahit.glsl"
~~~~
and in `raytrace_1.ahit`, replace `PAYLOAD_0` by `PAYLOAD_1`
Then in `raytrace_ahit.glsl` remove the `#version 460` and add the following code, so that we have the right layout.
~~~~ C
#ifdef PAYLOAD_0
layout(location = 0) rayPayloadInNV hitPayload prd;
#elif defined(PAYLOAD_1)
layout(location = 1) rayPayloadInNV shadowPayload prd;
#endif
~~~~
## New Payload
We cannot simply have a bool for our shadow ray payload. We also need the `seed` for the random function.
In the `raycommon.glsl` file, add the following structure
~~~~ C
struct shadowPayload
{
bool isHit;
uint seed;
};
~~~~
The usage of the shadow payload is done in the closest hit and shadow miss shader. First, let's modify `raytraceShadow.rmiss` to look like this
~~~~ C
#version 460
#extension GL_NV_ray_tracing : require
#extension GL_GOOGLE_include_directive : enable
#include "raycommon.glsl"
layout(location = 1) rayPayloadInNV shadowPayload prd;
void main()
{
prd.isHit = false;
}
~~~~
The the change in the closest hit shader `raytrace.rchit`, need to change the usage of the payload, but also the call to `traceRayEXT`
Replace the payload to
~~~~ C
layout(location = 1) rayPayloadNV shadowPayload prdShadow;
~~~~
Then just before the call to `traceRayEXT`, initialize the values to
~~~~ C
prdShadow.isHit = true;
prdShadow.seed = prd.seed;
~~~~
and after the trace, set the seed value back to the main payload
~~~~ C
prd.seed = prdShadow.seed;
~~~~
And check if the trace shadow hit an object of not
~~~~ C
if(prdShadow.isHit)
~~~~
### traceRayEXT
When we call `traceRayEXT`, since we are using the payload 1 (last argument), we also
need the trace to hit the alternative hit group, the one using the payload 1.
To do this, we need to set the sbtRecordOffset to 1
~~~~ C
traceRayEXT(topLevelAS, // acceleration structure
flags, // rayFlags
0xFF, // cullMask
1, // sbtRecordOffset
0, // sbtRecordStride
1, // missIndex
origin, // ray origin
tMin, // ray min range
rayDir, // ray direction
tMax, // ray max range
1 // payload (location = 1)
);
~~~~
## Ray tracing Pipeline
The final step is to add the new Hit Group. This is a change in `HelloVulkan::createRtPipeline()`.
We need to load the new any hit shader and create a new Hit Group.
Replace the `"shaders/raytrace.rahit.spv"` for `"shaders/raytrace_0.rahit.spv"`
Then, after the creating of the first Hit Group, create a new one, where only the any hit using payload 1
is added. We are skipping the closest hit shader in the trace call, so we can ignore it in the Hit Group.
~~~~ C
// Payload 1
vk::ShaderModule ahit1SM =
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace_1.rahit.spv", true, paths));
hg.setClosestHitShader(VK_SHADER_UNUSED_NV); // Not used by shadow (skipped)
stages.push_back({{}, vk::ShaderStageFlagBits::eAnyHitNV, ahit1SM, "main"});
hg.setAnyHitShader(static_cast<uint32_t>(stages.size() - 1));
m_rtShaderGroups.push_back(hg);
~~~~
At the end of the function, delete the shader module `ahit1SM`.
!!! NOTE Re-Run
Everything should work as before, but now it does it right.
# Final Code
You can find the final code in the folder [ray_tracing_anyhit](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing_anyhit)