Skip to content

Enabling shader keywords

Matt Ellis edited this page Nov 23, 2023 · 2 revisions

Working with shader files often requires using #if preprocessor directives to generate different shader variants. These branches can be used to introduce conditional behaviour for different platforms, such as mobile or desktop, different graphics APIs such as Vulkan or DirectX, or even different user features, enabled at runtime with shader keywords.

Rider will parse your shader source code, while you type. It builds a semantic model and can use this to provide rich functionality such as syntax highlighting, ctrl+click navigation, finding usages and smart rename and other refactorings. However, it is not feasible for Rider to build a semantic model of the content of all preprocessor directives simultaneously; an inactive branch might contain alternative conflicting declarations of existing fields or functions, or broken code, or could even contain unexpected syntax to close one function and declare another one (e.g. by including a close brace and a new function declaration). So Rider will only analyse the preprocessor branches based on the currently defined symbols while editing. This leads to "inactive", grey-out preprocessor branches, with no syntax highlighting or inspections.

Example preprocessor branches with greyed out inactive code

Rider 2023.3 introduces a way to choose which shader keywords are enabled, and which Unity shader preprocessor symbols are defined.

Clicking the "Variants" widget in the breadcrumb bar at the bottom of the editor will show a popup that tells Rider to treat different symbols as defined while editing. For example, it's possible to select the graphics API - selecting "DirectX 11" will tell Rider to consider the SHADER_API_D3D11 symbol to be defined, and anything inside #if SHADER_API_D3D11 would be parsed as active code, with syntax highlighting and inspections and so on. Switching to "Vulkan" would mean that SHADER_API_D3D11 is no longer active, and the preprocessor branch would be considered inactive, but anything inside #if SHADER_API_VULKAN would be active instead.

Selecting the DirectX platform activates the SHADER_API_D3D11 symbol

Similarly, Rider can switch between desktop and mobile to activate the SHADER_API_DESKTOP or SHADER_API_MOBILE symbols.

Note that Rider will provide completion for known SHADER_ symbols.

Completion of SHADER define symbols

Rider also allows enabling shader keywords. The following #pragma directive will declare the BLUE, RED and GREEN shader keywords. These keywords can be enabled at runtime with the Shader.EnableKeyword API, amongst others (see the docs for shader keywords for more details).

#pragma shader_feature _ BLUE RED GREEN

These keywords are also preprocessor define symbols, and Rider can enable these through the shader variants widget, and will then process the appropriate preprocessor branch. When a keyword is enabled, it is highlighted as bold and underlined.

The preprocessor branch for an enabled keyword is shown as active

The keyword in the #pragma is also highlighted. It's also possible to enable and disable keywords through the alt+enter context menu, either in the #pragma or wherever the symbol is used.

The pragma directive with enabled keyword highlighted as bold and underlined

One thing to note: Unity allows multiple keywords to be enabled, but only the first in a pragma directive is considered to be active. All other keywords are suppressed, and will not be active. Rider marks suppressed keywords with a strikethrough, and the symbol is not defined. Rider does not automatically disable other keywords in the pragma because it is possible to enable multiple conflicting keywords in code, and it is also possible to define the same keyword in multiple pragmas. The alt+enter menu can be used on a suppressed keyword to disable the keyword(s) that cause it to be suppressed.

Alt+Enter menu showing disabling of conflicting keywords

The shader variants widget is a great way of providing context to Rider's code analysis, so you can choose which shader variant you're editing, and make use of Rider's analysis and other rich functionality.

Clone this wiki locally