Inline Ray Tracing Support in 2023.2

Greetings from the Graphics team!

We are glad to announce that as of the 2023.2 tech stream, the Unity Ray Tracing API has been extended to provide Inline Ray Tracing support across all shader stages, when targeting capable Windows and Console platforms.

Before sharing information on how to enable Inline Ray Tracing support for your shaders, along with platform support and code examples, let’s quickly review the concepts of the ray tracing pipeline and inline ray tracing.

Ray Tracing Pipeline

The High Definition Rendering Pipeline’s various Ray Tracing effects, such as shadows and reflections, are all implemented via the Unity Ray Tracing API and using the traditional “ray tracing pipeline”.

The ray tracing pipeline works by creating and building a Ray Tracing Acceleration Structure representing the scene’s geometry, to be traversed on the GPU using the Ray Generation shader. In cases where a ray is calculated to intersect with the bound acceleration structure, the appropriate “hit shader” is then invoked in order to perform the required shading. Alternatively, if geometry is not intersected by the ray generation shader at all, a “miss shader” may be invoked in order to perform background / environment shading.

To enable this, a dynamic shader table is created by the ray tracing pipeline, which defines and binds the various possible “hit” and “miss” shader programs to be potentially invoked by the ray generation shader. While this system is ideal for the ray tracing of complex pipelines and environments with high shader complexity, as in the case of the high-definition render pipeline, it does not permit the utilization of hardware accelerated ray tracing in general-purpose compute programs. Furthermore, dynamic ray tracing shader tables may introduce unnecessary complexity and overhead for simpler scenarios and use cases.

Inline Ray Tracing

DXR1.1 expands upon the DX12 Ray Tracing API by introducing the ability to issue inline ray queries directly within compute and rasterization shader stages. This provides developers with an alternative method of performing hardware accelerated ray tracing, and unlocks new and exciting possibilities for shader and custom pipeline effect authoring.

As of Unity 2023.2, this new functionality is now fully supported by the Ray Tracing API across all shader stages, when targeting DXR1.1 capable Windows Platforms, Xbox Series and Playstation 5.

Shader Support

The RayQuery object is defined in HLSL when using the DirectX Shader Compiler (DXC) whereas other shader compilers used by different platforms either don’t define the RayQuery object, or its name is different. Because of this, the recommended approach is to include the UnityRayQuery.cginc header and use the UnityRayQuery object instead of RayQuery:

#include <UnityRayQuery.cginc>

Enabling Inline Ray Tracing (RayQuery) support in shader code can be done using one of the 2 options:

#pragma require inlineraytracing
or
#pragma multi_compile _ UNITY_DEVICE_SUPPORTS_INLINE_RAY_TRACING

Declaring either pragma will force the shader to compile using the DXC (DirectX Shader Compiler), and will require Shader Model 6.5+ and Inline Ray Tracing support on the target device.

The latter approach (multi_compile) will generate and compile an additional inline ray tracing shader variant, to be loaded at runtime when targeting platforms with ray queries support. This allows you to define and maintain two (or more) variants for your shader - one that utilizes hardware ray queries, and one that relies on more traditional methods:

#include <UnityRayQuery.cginc>

#pragma vertex vert
#pragma fragment frag

#pragma multi_compile _ UNITY_DEVICE_SUPPORTS_INLINE_RAY_TRACING

#if UNITY_DEVICE_SUPPORTS_INLINE_RAY_TRACING

RaytracingAccelerationStructure g_AccelStruct;

#endif

float4 vert() : SV_POSITION { return float4(0, 0, 0, 1); }

float4 frag() : SV_Target

{
     float4 ret = float4(0, 0, 0, 0);

#if UNITY_DEVICE_SUPPORTS_INLINE_RAY_TRACING

    // Cast shadow rays using inline ray tracing
    UnityRayQuery<RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> query;

#else

    // Sample a shadow map

#endif

    return ret;
}

Please check DirectX specification for DXR 1.1 and RayQuery object for more information on using ray queries in shaders: https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html#rayquery

In C# you can use SystemInfo.supportsInlineRayTracing to check if the system supports Inline Ray Tracing in shader code. This check can be done before dispatching a compute shader that uses Inline Ray Tracing for example.

Once a Ray Tracing Acceleration Structure is created and built, you are required to bind the RTAS to a specific shader object. This can be done indirectly using the CommandBuffer API:

As well as directly using the Shader API:


Soft Shadows Example

The following example demonstrates the use of Inline Ray Tracing in compute shaders, in order to implement a custom shadow casting pass. Offsetting the ray direction enables a varying penumbra to control the softness of ray traced shadows:


Custom shadow pass with variable penumbra, implemented using Inline Ray Tracing

https://github.com/INedelcu/InlineRayTracingShadows/blob/main/Assets/RayTracingShadows/ComputeShaderRayQuery.compute

    RayDesc shadowRay;

    shadowRay.Origin = worldSpacePos + worldNormal * 0.01f;
    shadowRay.TMin = 0;
    shadowRay.TMax = 1e20f;

    UnityRayQuery<RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_CULL_BACK_FACING_TRIANGLES> shadowQuery;

    const uint sampleCount = g_TemporalAccumulationStep < 10 ? 8 : 2;

    // A value of 0 means that the pixel is not in shadow.
    float shadow = 0;

    for (uint i = 0; i < sampleCount; i++)
    {
        float3 localDir = normalize(float3(g_ShadowSpread, g_ShadowSpread, 1) * float3(2 * RandomFloat01(rngState) - 1, 2 * RandomFloat01(rngState) - 1, 1));

        shadowRay.Direction = mul(g_LightMatrix, localDir);

        // Assume everything is opaque. Cutout materials are not supported when using inline ray tracing.
        shadowQuery.TraceRayInline(g_AccelStruct, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_CULL_BACK_FACING_TRIANGLES, 0xff, shadowRay);

        shadowQuery.Proceed();

        shadow += shadowQuery.CommittedStatus() == COMMITTED_TRIANGLE_HIT;
    }

    float prevShadow = g_Output[id.xy];

    // Accumulate new samples into the previous frame's shadow map.
    float result = lerp(prevShadow, 1 - (shadow / sampleCount), 1 / float(g_TemporalAccumulationStep + 1));

    g_Output[id.xy] = result;

You can access the full sample project here: https://github.com/INedelcu/InlineRayTracingShadows

Reach out

Please give the new Inline Ray Tracing support a try and let us know what you think. We are also inviting you to share any interesting implementations and effects you may come up with when experimenting with ray queries.

Your feedback has been instrumental so far as it helps us prioritize the most meaningful solutions. Please check out our public roadmap to vote on the features that best suit your needs. If there are additional changes you’d like to see, feel free to submit a feature request, or contact the team directly in this thread or the graphics forum.

9 Likes

I really like these kind of developments, but I won’t be able to use them for a long time as I need to use URP for cross platform compatibility.

There is no obstacle to use this feature with URP. Just support of DXR need to be checked carefully on target hardware.

3 Likes

Interesting, so a PS5 And Switch console release could be made all in URP and support Ray Tracing on PS5 correct?

You can use Ray Queries in your custom shaders, as long as the target device supports this feature. You can query for support at runtime using SystemInfo.supportsInlineRayTracing.

When writing custom shaders, you can use the UNITY_DEVICE_SUPPORTS_INLINE_RAY_TRACING mutli_compile keyword, in order to implement shader variants using ray queries. This way, you can implement a more traditional approach for platforms without ray query support, and use ray queries on the supported platforms.

Support is currently limited to DXR1.1 capable Windows platforms, Xbox Series and Playstation 5. We are considering future mobile support via Vulkan and Metal as well, so if that is important to you please vote here:

4 Likes

Yes I added my vote the the board for both vulcan and metal, I think the hardware advances in the next year or so will allow for this to be able to run on the latest models.

Seems to be a core rendering feature like the ray tracing API itself, so you should be able to use it even on built-in.

– EDIT –
Took a look at the sample project source code, it’s actually using built-in.

1 Like

Good to hear this!