1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
|
<!--
Copyright 2023 The Khronos Group Inc.
Copyright 2023 Valve Corporation
Copyright 2023 LunarG, Inc.
SPDX-License-Identifier: Apache-2.0
-->
[![Khronos Vulkan][1]][2]
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Layers Configuration
[![Creative Commons][3]][4]
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
Vulkan supports intercepting or hooking API entry points via a layer framework. A layer can intercept all or any subset of Vulkan API entry points. Multiple layers can be chained together to cascade their functionality in the appearance of a single, larger layer.
Vulkan layers allow application developers to add functionality to Vulkan applications without modifying the application itself, e.g., validating API usages, dumping API entry points or generating screenshots of specified frames.
A *layers configuration* consists in two operations:
- Selecting and ordering layers.
- Configuring each layer themselves using layer settings.
Vulkan layers can be configured using three different methods to match specific Vulkan developers' workflows:
- Using Environment variables: [Loader environment variables](https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md) and [per-layer settings environment variables](https://github.com/KhronosGroup/Vulkan-Utility-Libraries/blob/main/docs/layer_configuration.md#layer-settings-environment-variables).
- Using dedicated Vulkan system files: [`vk_loader_settings.json`](https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderSettingsFile.md) and [`vk_layer_settings.txt`](https://github.com/KhronosGroup/Vulkan-Utility-Libraries/blob/main/docs/layer_configuration.md#configuring-the-layers-using-the-settings-file-vk_layer_settingstxt).
- Using the Vulkan API, programmably in the Vulkan application: [`vkCreateInstance`](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateInstance.html) and [`VK_EXT_layer_settings`](https://github.com/KhronosGroup/Vulkan-Utility-Libraries/blob/main/docs/layer_configuration.md#configuring-the-layer-settings-using-vk_ext_layer_settings) extension.
Since three methods exist and can be used simultanously, here is the priority order:
1. Environment variables.
2. Using dedicated Vulkan system files.
3. Using the Vulkan API, programmably in the Vulkan application.
[*Vulkan Configurator*](https://github.com/LunarG/VulkanTools/blob/main/vkconfig_gui/README.md) simplifies the usage of these three methods. Using the graphical user interface, we can create *layers configuration*. The tool automatically create and locate the `vk_loader_settings.json` and `vk_layer_settings.txt` files. It can also be used to generate environment variables scripts and a C++ header library that can be directly included within the Vulkan application code.
These three methods are implemented by the **Vulkan Layer Settings** library part of the *[Vulkan-Utility-Libraries](https://github.com/KhronosGroup/Vulkan-Utility-Libraries)* repository.
Any layer project that uses this library will provide these three methods to control layer settings bringing consistency and easy of use of layers to the Vulkan community.
For each of these methods, it's possible for Vulkan application developers to generate environment variables scripts and C++ code from Vulkan Configurator, using either the GUI (using the context menu of each layers configuration) or the command line (using `vkconfig settings`). This generated files can either implement the default layer setting values of the values selected in the Vulkan Configurator GUI.
For more information, read the [Vulkan Layers whitepaper](https://github.com/KhronosGroup/Vulkan-Profiles/tree/main/doc/Configuring-Vulkan-Layers-Whitepaper.pdf).
Guideline: Settings which are unknown by the layer will be ignored independently of the method. It's the responsibility of the layer developer to ensure backward compatibility with previous versions of the layer. This is to ensure the list of layer settings remain stable across versions and that the responsibility of handling layer backward compatibility doesn't fall on Vulkan application developers as this could quickly become untrackable..
## Configuring Vulkan Layers using the *Vulkan API*
### Enabling and ordering the layer using `vkCreateInstance()`
Applications may programmatically activate layers via the `vkCreateInstance()` entry point. This is done by setting `enabledLayerCount` and `ppEnabledLayerNames` in the `VkInstanceCreateInfo` structure.
The layer names order in `ppEnabledLayerNames` specifies the layers execution ordering from closer to the Vulkan application to closer to the Vulkan driver.
Layer properties can be queried from an application with [vkEnumerateInstanceLayerProperties](https://docs.vulkan.org/spec/latest/chapters/extensions.html#vkEnumerateInstanceLayerProperties[vkEnumerateInstanceLayerProperties).
#### Code example to enable and order the validation and the profiles layers programmatically
```cpp
const VkApplicationInfo app_info = initAppInfo();
const char* layers[] = {"VK_LAYER_KHRONOS_validation", "VK_LAYER_KHRONOS_profiles"};
const VkInstanceCreateInfo inst_create_info = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0,
&app_info,
static_cast<uint32_t>(std::size(layers)), layers,
0, nullptr
};
VkInstance instance = VK_NULL_HANDLE;
VkResult result = vkCreateInstance(&inst_create_info, nullptr, &instance);
```
In this example, the Khronos validation layer will be called _before_ the Khronos profiles layer.
### Configuring the layer settings using `VK_EXT_layer_settings`
Introduced with Vulkan `1.3.272`, layer settings may be configured using the `VK_EXT_layer_settings` extension by initializing the `VkLayerSettingsCreateInfoEXT` structure and chaining it to the `pNext` of `VkInstanceCreateInfo` when creating a Vulkan instance.
#### Code example to configure the validation layer programmatically
```cpp
const char* layer_name = "VK_LAYER_KHRONOS_validation";
const VkBool32 setting_validate_core = VK_TRUE;
const VkBool32 setting_validate_sync = VK_TRUE;
const VkBool32 setting_thread_safety = VK_TRUE;
const char* setting_debug_action[] = {"VK_DBG_LAYER_ACTION_LOG_MSG"};
const char* setting_report_flags[] = {"info", "warn", "perf", "error", "debug"};
const VkBool32 setting_enable_message_limit = VK_TRUE;
const int32_t setting_duplicate_message_limit = 3;
const VkLayerSettingEXT settings[] = {
{layer_name, "validate_core", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_validate_core},
{layer_name, "validate_sync", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_validate_sync},
{layer_name, "thread_safety", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_thread_safety},
{layer_name, "debug_action", VK_LAYER_SETTING_TYPE_STRING_EXT, 1, setting_debug_action},
{layer_name, "report_flags", VK_LAYER_SETTING_TYPE_STRING_EXT, static_cast<uint32_t>(std::size(setting_report_flags)), setting_report_flags},
{layer_name, "enable_message_limit", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_enable_message_limit},
{layer_name, "duplicate_message_limit", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &setting_duplicate_message_limit}};
const VkLayerSettingsCreateInfoEXT layer_settings_create_info = {
VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr,
static_cast<uint32_t>(std::size(settings)), settings};
const VkApplicationInfo app_info = initAppInfo();
const char* layers[] = {layer_name};
const VkInstanceCreateInfo inst_create_info = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, &layer_settings_create_info, 0,
&app_info,
static_cast<uint32_t>(std::size(layers)), layers,
0, nullptr
};
VkInstance instance = VK_NULL_HANDLE;
VkResult result = vkCreateInstance(&inst_create_info, nullptr, &instance);
```
### Configuring the layer settings using `VK_EXT_layer_settings` C++ helper library
In Vulkan Configurator UI, using the context menu of each layers configuration, it's possible to generate a C++ helper library ("vulkan_layer_settings.hpp") matching the layer settings of the selected layers configuration.
```cpp
#include "vulkan_layer_settings.hpp"
...
// Create an object with all the settigns initialized
LayerSettings layer_settings;
// We can modify the setting values:
layer_settings.validation.report_flags = {"error", "warn"};
const VkLayerSettingsCreateInfoEXT layer_settings_create_info = {
VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr,
static_cast<uint32_t>(layer_settings.info().size()), &layer_settings.info()[0]};
const VkApplicationInfo app_info = initAppInfo();
const char* layers[] = {layer_name};
const VkInstanceCreateInfo inst_create_info = {
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, &layer_settings_create_info, 0,
&app_info,
static_cast<uint32_t>(std::size(layers)), layers,
0, nullptr
};
VkInstance instance = VK_NULL_HANDLE;
VkResult result = vkCreateInstance(&inst_create_info, nullptr, &instance);
```
## Configuring Vulkan Layers using *Vulkan Configurator*
Developers can configure layers through a graphical user interface. *Vulkan Configurator* allows full user control of Vulkan layers, including enabling or disabling specific layers, controlling layer order, changing layer settings, etc.
*Vulkan Configurator* configures the layers by applying a global system configuration of the Vulkan loader and creating a vk_layer_settings.txt file that will be find by any layer.
*Vulkan Configurator* can be used using command line to setup the system environment. Use the command `vkconfig --help` for more information in this case.
We recommend using *Vulkan Configurator* GUI approach for Vulkan application developers. It's the most effective approach to switch between multiple layer configurations and quickly iterate during development.
Additionally, *Vulkan Configurator* presents to the Vulkan application developers the layers found on the system and the settings of each layer, allowing Vulkan application developers to discover new functionality from the GUI without having to dig into each layer documentation.
### Enabling and ordering the layer with the Vulkan Loader settings file (`vk_loader_settings.json`)
Introduced with Vulkan Configurator 3 and Vulkan Loader 1.4.304, to control the enabled layers and the layer order, *Vulkan Configurator 3* generates the `vk_loader_settings.json` file, which is consumed by the Vulkan loader to enable Vulkan layers and control the order of the layers. This file also stores the user-defined paths specified in *Vulkan Configurator 3* to find additional layers.
#### The Vulkan Loader settings file on Linux and macOS
Unix systems store override layer file in the following paths:
- `$HOME/.local/share/vulkan/loader_settings.d/vk_loader_settings.json`
#### The Vulkan Loader settings file on Windows
Windows systems store the override layer file in the following path:
- `%HOME%\AppData\Local\LunarG\vulkan\vk_loader_settings.json`
### Enabling and ordering the layer with the override layer file (`VkLayer_override.json`)
To control the enabled layers and the layer order, *Vulkan Configurator 2* generates the `VkLayer_override.json` file, which is consumed by the Vulkan loader to enable Vulkan layers and control the order of the layers. This file also stores the user-defined paths specified in *Vulkan Configurator 2* to find additional layers.
The `VkLayer_override.json` file is no longer generated or used by *Vulkan Configurator 3*
#### The override layer file on Linux and macOS
Unix systems store override layer file in the following paths:
- `$HOME/.local/share/vulkan/implicit_layer.d/VkLayer_override.json`
#### The override layer file on Windows
Windows systems store the override layer file in the following path:
- `%HOME%\AppData\Local\LunarG\vkconfig\override\VkLayerOverride.json`
### Configuring the layers using the settings file (`vk_layer_settings.txt`)
To control the layer settings, *Vulkan Configurator* is generating the `vk_layer_settings.txt` file which is consumed by the Vulkan layers and set the setting values defined by the Vulkan developers using the UI.
By default, the **Vulkan Layer Settings** library requires the settings file to be named `vk_layer_settings.txt` and it will search it in the working directory of the targeted application. Hence, if a file is found in the working directory of the targeted application, the **Vulkan Layer Settings** library will bypass the layer settings created by *Vulkan Configurator*.
If `VK_LAYER_SETTINGS_PATH` is set and is a directory, then the settings file must be a file called `vk_layer_settings.txt` in the directory given by `VK_LAYER_SETTINGS_PATH`.
If `VK_LAYER_SETTINGS_PATH` is set and is not a directory, then it must point to a file (with any name) which is the layer settings file.
The settings file can be modified or fully hand-written by the Vulkan application developers or third party tools. The settings file consists of comment lines and settings lines. Comment lines begin with the `#` character. Settings lines have the following format:
`<`*`LayerName`*`>.<`*`setting_name`*`> = <`*`setting_value`*`>`
The list of available settings is available in the layer manifest.
#### Example Usage of `vk_layer_settings.txt`:
```txt
# The main, heavy-duty validation checks. This may be valuable early in the
# development cycle to reduce validation output while correcting
# parameter/object usage errors.
khronos_validation.validate_core = true
# Enable synchronization validation during command buffers recording. This
# feature reports resource access conflicts due to missing or incorrect
# synchronization operations between actions (Draw, Copy, Dispatch, Blit)
# reading or writing the same regions of memory.
khronos_validation.validate_sync = true
# Thread checks. In order to not degrade performance, it might be best to run
# your program with thread-checking disabled most of the time, enabling it
# occasionally for a quick sanity check or when debugging difficult application
# behaviors.
khronos_validation.thread_safety = true
# Specifies what action is to be taken when a layer reports information
khronos_validation.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG
# Comma-delineated list of options specifying the types of messages to be reported
khronos_validation.report_flags = debug,error,perf,info,warn
# Enable limiting of duplicate messages.
khronos_validation.enable_message_limit = true
# Maximum number of times any single validation message should be reported.
khronos_validation.duplicate_message_limit = 3
```
#### Layer Settings File location on Linux and macOS
Unix systems store the layer setting file in the following path:
- `$HOME/.local/share/vulkan/settings.d/vk_layer_settings.txt`
#### Layer Settings File location on Windows
Windows systems store the layer setting file in the following path:
- `%HOME%\AppData\Local\LunarG\vkconfig\override\vk_layer_settings.txt`
## Configuring Vulkan Layers using Environment Variables
### Finding Vulkan Layers
In order to enable a Vulkan layer from the command-line, you must first make sure:
1. The layer's Manifest JSON file is found by the Vulkan Desktop Loader because it is in:
* One of the standard operating system install paths
* It was added using one of the layer path environment variables (`VK_LAYER_PATH` or `VK_ADD_LAYER_PATH`).
* See the `Layer Discovery` section of the Vulkan Loader's [Layer Interface doc](https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderLayerInterface.md).
2. The layer's library file is able to be loaded by the Vulkan Desktop Loader because it is in:
* A standard library path for the operating system
* The library path has been updated using an operating system-specific mechanism such as:
* Linux: adding the path to the layer's library .so with `LD_LIBRARY_PATH`
* MacOS: adding the path to the layer's library .dylib with `DYLD_LIBRARY_PATH`
3. The layer's library file is compiled for the same target and bitdepth (32 vs 64) as the application
#### Activating Specific SDK Layers
To activate layers located in a particular SDK installation, or layers built locally from source, specify the layer JSON
manifest file directory using either `VK_LAYER_PATH` or `VK_ADD_LAYER_PATH`.
The difference between `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` is that `VK_LAYER_PATH` overrides the system layer paths
so that no system layers are loaded by default unless their path is added to the environment variable.
`VK_ADD_LAYER_PATH` on the otherhand, causes the loader to search the additional layer paths listed in the
environment variable first, and then the standard system paths will be searched.
#### Example Usage On Windows:
For example, if a Vulkan SDK is installed in `C:\VulkanSDK\1.3.261.0`, execute the following in a Command Window:
```
C:\> set VK_LAYER_PATH=C:\VulkanSDK\1.3.261.0\Bin
```
#### Example Usage on Linux
For Linux, if Vulkan SDK 1.3.261.0 was locally installed in `/sdk` and `VULKAN_SDK=/sdk/1.3.261.0/x86_64`:
```
$ export VK_LAYER_PATH=$VULKAN_SDK/lib/vulkan/layers
$ export LD_LIBRARY_PATH=$VULKAN_SDK/lib:$VULKAN_SDK/lib/vulkan/layers
```
#### Example Usage on MacOS
For macOS, if Vulkan SDK 1.3.261.0 was locally installed in `/sdk` and `VULKAN_SDK=/sdk/1.3.261/macOS`:
```
$ export VK_LAYER_PATH=$VULKAN_SDK/share/vulkan/explicit_layers.d
$ export DYLD_LIBRARY_PATH=$VULKAN_SDK/lib
```
### Enabling and ordering Vulkan Layers
Originally, the Vulkan Desktop Loader provided `VK_INSTANCE_LAYERS` to enable layers from the command-line.
However, starting with the Vulkan Loader built against the 1.3.234 Vulkan headers, the `VK_LOADER_LAYERS_ENABLE` environment
variable was added to allow for more easily enabling Vulkan layers.
The newer Loaders will continue to accept the original `VK_INSTANCE_LAYERS` environment variable for some time, but it is
considered deprecated.
#### Vulkan 1.3.234 Loader and Newer (`VK_LOADER_LAYERS_ENABLE`)
The easiest way to enable a layer with a more recent drop of the Vulkan Loader is using the `VK_LOADER_LAYERS_ENABLE`
environment variable.
This environment variable accepts a case-insensitive, comma-delimited list of globs which can be used to define
the layers to load.
For example, previously if you wanted to enable the Profiles layer and the Validation layer, you would have to set
`VK_INSTANCE_LAYERS` equal to the full name of each layer:
```
VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation;VK_LAYER_KHRONOS_profiles
```
Now, with `VK_LOADER_LAYERS_ENABLE`, you simply can use stars where you don't want to fill in the full name:
```
VK_LOADER_LAYERS_ENABLE=*validation,*profiles
```
Note that order is relevant, with the initial layer being the closest to the application, and the final layer being closest to the driver.
In this example, the Khronos validation layer will be called _before_ the Khronos profiles layer.
##### Example Usage On Windows:
```
C:\> set VK_LOADER_LAYERS_ENABLE=*validation,*profiles
```
##### Example Usage On Linux/macOS:
```
$ export VK_LOADER_LAYERS_ENABLE=*validation,*profiles
```
More info about the new layer filtering environment variables can be found in the `Layer Filtering` section of the
of the [Loader Layer Documentation](https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderLayerInterface.md).
#### Older Vulkan Loaders
Older Vulkan Desktop loaders will not accept the filtering environment variable, and so must continue using the original
`VK_INSTANCE_LAYERS` environment variable.
##### Example Usage On Windows:
The variable should include a semicolon-separated list of layer names to activate.
Note that order is relevant, with the initial layer being the closest to the application, and the final layer being closest to the driver.
```
C:\> set VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation;VK_LAYER_KHRONOS_profiles
```
In this example, the Khronos validation layer will be called _before_ the Khronos profiles layer.
`VK_INSTANCE_LAYERS` may also be set in the system environment variables.
##### Example Usage On Linux/macOS:
The variable should include a colon-separated list of layer names to activate.
Note that order is relevant, with the initial layer being the closest to the application, and the final layer being closest to the driver.
```
$ export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:VK_LAYER_KHRONOS_profiles
```
In this example, the Khronos validation layer will be called _before_ the Khronos profiles layer.
### Layer Settings Environment Variables
Some settings from the settings file can also be set using environment variables. The settings that can be set using environment variables are listed in the documentation for each supported layer. If an environment variable is set, its value takes precedence over the value in the settings file.
The environment variable names for the layer settings have multiple variants that follows the format:
- `VK_<`*`LayerVendor`*`>_<`*`LayerName`*`>_<`*`setting_name`*`>` which take precedent over:
- `VK_<`*`LayerName`*`>_<`*`setting_name`*`>` which take precedent over:
- `VK_<`*`setting_name`*`>`
A few settings may be available under the deprecated format `VK_LAYER_<`*`setting_name`*`>`, which is discouraged from further being used.
This approach allows to share the same setting name for potentially multiple layers but still use different values for the same setting name if
this is what is required for the Vulkan developer use case.
#### Example of environment variable variants for a single setting:
`VK_KHRONOS_VALIDATION_DEBUG_ACTION`
`VK_VALIDATION_DEBUG_ACTION`
`VK_DEBUG_ACTION`
#### Example Usage on Windows:
```
C:\> set VK_VALIDATION_VALIDATE_CORE=true
C:\> set VK_VALIDATION_VALIDATE_SYNC=true
C:\> set VK_VALIDATION_THREAD_SAFETY=true
C:\> set VK_VALIDATION_DEBUG_ACTION=VK_DBG_LAYER_ACTION_LOG_MSG
C:\> set VK_VALIDATION_REPORT_FLAGS=debug;error;perf;info;warn
C:\> set VK_VALIDATION_ENABLE_MESSAGE_LIMIT=true
C:\> set VK_VALIDATION_DUPLICATE_MESSAGE_LIMIT=3
```
#### Example Usage on Linux/macOS:
```
$ export VK_VALIDATION_VALIDATE_CORE=true
$ export VK_VALIDATION_VALIDATE_SYNC=true
$ export VK_VALIDATION_THREAD_SAFETY=true
$ export VK_VALIDATION_DEBUG_ACTION=VK_DBG_LAYER_ACTION_LOG_MSG
$ export VK_VALIDATION_REPORT_FLAGS=debug:error:perf:info:warn
$ export VK_VALIDATION_ENABLE_MESSAGE_LIMIT=true
$ export VK_VALIDATION_DUPLICATE_MESSAGE_LIMIT=3
```
#### Example Usage on Android:
```
$ adb setprop debug.vvl.validation_core true
$ adb setprop debug.vulkan.validation.validation_sync true
$ adb setprop debug.vulkan.validation.thread_safety true
$ adb setprop debug.vulkan.validation.enable_message_limit true
$ adb setprop debug.vulkan.validation.duplicate_message_limit 3
```
|