Reader small image

You're reading from  Mastering Graphics Programming with Vulkan

Product typeBook
Published inFeb 2023
PublisherPackt
ISBN-139781803244792
Edition1st Edition
Right arrow
Authors (2):
Marco Castorina
Marco Castorina
author image
Marco Castorina

Marco Castorina first got familiar with Vulkan while working as a driver developer at Samsung. Later he developed a 2D and 3D renderer in Vulkan from scratch for a leading media-server company. He recently joined the games graphics performance team at AMD. In his spare time, he keeps up to date with the latest techniques in real-time graphics.
Read more about Marco Castorina

Gabriel Sassone
Gabriel Sassone
author image
Gabriel Sassone

Gabriel Sassone is a rendering enthusiast currently working as a Principal Rendering Engineer at Multiplayer Group. Previously working for Avalanche Studios, where his first contact with Vulkan happened, where they developed the Vulkan layer for the proprietary Apex Engine and its Google Stadia Port. He previously worked at ReadyAtDawn, Codemasters, FrameStudios, and some non-gaming tech companies. His spare time is filled with music and rendering, gaming, and outdoor activities.
Read more about Gabriel Sassone

View More author details
Right arrow

Implementing Variable Rate Shading

In this chapter, we are going to implement a technique that has become quite popular recently: variable rate shading. This technique allows developers to specify at which rate to shade individual pixels while maintaining the same perceived visual quality. This approach allows us to reduce the time taken for some rendering passes, and the time savings can be used to implement more features or render at higher resolutions.

Vulkan provides multiple options to integrate this technique into an application, and we are going to provide an overview of all of them. This feature is provided through an extension that is supported only on recent hardware, but it’s possible to implement it manually using compute shaders. We won’t cover this option here, but we are going to point you to the relevant resources in the Further reading section.

In this chapter, we’ll cover the following main topics:

  • Introducing variable rate shading...

Technical requirements

Introducing variable rate shading

Variable rate shading (VRS) is a technique that allows developers to control the rate at which fragments are shaded. When this feature is disabled, all fragments are shaded using a 1x1 rate, meaning that the fragment shader will run for all fragments in the image.

With the introduction of virtual reality (VR) headsets, developers have started to investigate ways to reduce the amount of time it takes to render a frame. This is crucial, not only because VR requires rendering two frames (one for the right eye and one for the left) but also because VR is quite sensitive to frame latency, and higher frame rates are required to avoid users experiencing motion sickness.

One technique that was developed is called foveated rendering: the idea is to render the center of the image at full rate while lowering the quality outside the center. Developers have noticed that users are focused primarily on the central region of the image and don’t notice...

Integrating variable rate shading using Vulkan

As we mentioned in the previous section, the fragment shading rate functionality is provided through the VK_KHR_fragment_shading_rate extension. As with other option extensions, make sure the device you are using supports it before calling the related APIs.

Vulkan provides three methods to control the shading rate:

  • Per draw
  • Per primitive
  • Using an image attachment for a render pass

To use a custom shading rate per draw, there are two options. We can pass a VkPipelineFragmentShadingRateStateCreateInfoKHR structure when creating a pipeline, or we can call vkCmdSetFragmentShadingRateKHR at runtime.

This approach is useful when we know in advance that some draws can be performed at a lower rate without affecting quality. This could include the sky or objects we know are far away from the camera.

It’s also possible to provide a shading rate per primitive. This is accomplished by populating the PrimitiveShadingRateKHR...

Taking advantage of specialization constants

Specialization constants are a Vulkan feature that allows developers to define constant values when creating a pipeline. This is particularly useful when the same shader is needed for multiple use cases that differ only for some constant values, for example, materials. This is a more elegant solution compared to pre-processor definitions as they can be dynamically controlled at runtime without having to recompile the shaders.

In our case, we want to be able to control the workgroup size of compute shaders based on the hardware we are running to obtain the best performance:

  1. The first step in the implementation is to determine whether a shader uses specialization constants. We now identify any variables that have been decorated with the following type when parsing the shader SPIR-V:
    case ( SpvDecorationSpecId ):
    {
        id.binding = data[ word_index + 3 ];
        break;
    }
  2. When parsing all the variables...

Summary

In this chapter, we introduced the variable rate shading technique. We gave a brief overview of this approach and how it can be used to improve the performance of some rendering passes without a loss in perceived quality. We also explained the edge detection algorithm used to determine the shading rate for each fragment.

In the next section, we illustrated the changes necessary to enable and use this feature with the Vulkan API. We detailed the options available to change the shading rate at the draw, primitive, and render pass level. We then explained the implementation of the edge detection algorithm using a compute shader and how the result is used to generate the shading rate image.

In the last section, we introduced specialization constants, a mechanism provided by the Vulkan API to modify shader constant values at compile time. We illustrated how this feature can be used to control the group size of compute shaders for optimal performance based on the device our...

Further reading

We only gave a brief overview of the Vulkan APIs for variable rate shading. We recommend reading the specification for further details: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#primsrast-fragment-shading-rate.

Most of the resources available online seem to be focused on the DirectX API, but the same approach can be translated to Vulkan. This blog post provides some details on the benefits of VRS: https://devblogs.microsoft.com/directx/variable-rate-shading-a-scalpel-in-a-world-of-sledgehammers/.

These two videos provide in-depth details on integrating VRS into existing game engines. The section on how to implement VRS using compute shader is particularly interesting:

This article illustrates how VRS can also have other use cases, for instance, to accelerate raytracing: https://interplayoflight.wordpress.com/2022/05/29/accelerating...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Mastering Graphics Programming with Vulkan
Published in: Feb 2023Publisher: PacktISBN-13: 9781803244792
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Authors (2)

author image
Marco Castorina

Marco Castorina first got familiar with Vulkan while working as a driver developer at Samsung. Later he developed a 2D and 3D renderer in Vulkan from scratch for a leading media-server company. He recently joined the games graphics performance team at AMD. In his spare time, he keeps up to date with the latest techniques in real-time graphics.
Read more about Marco Castorina

author image
Gabriel Sassone

Gabriel Sassone is a rendering enthusiast currently working as a Principal Rendering Engineer at Multiplayer Group. Previously working for Avalanche Studios, where his first contact with Vulkan happened, where they developed the Vulkan layer for the proprietary Apex Engine and its Google Stadia Port. He previously worked at ReadyAtDawn, Codemasters, FrameStudios, and some non-gaming tech companies. His spare time is filled with music and rendering, gaming, and outdoor activities.
Read more about Gabriel Sassone