Variable Rate Shading: настройка и ограничения
Карта плотности, текущая кодировка KHR, обновление Viewport и проверка компромисса качества.
VRS уменьшает число вычислений фрагментного шейдера в выбранных областях 3D-кадра. Разрешение геометрии при этом не обязано уменьшаться. Это оптимизация с возможной потерей деталей материалов, а не способ улучшить графику.
Используйте VRS, когда измерения показывают высокую стоимость fragment shading. Он не устраняет упор в CPU, сложную геометрию или большое число draw calls. Для демонстрационных кадров сначала добейтесь нужного качества без VRS, затем сравнивайте результат при одинаковой камере и освещении.
Что требуется
- Forward+ или Mobile и поддержка выбранного VRS-пути устройством и драйвером. Compatibility не использует описанный здесь RD-путь.
- Режим Texture и карта плотности для нужного Viewport.
- Обновление карты: Once для неизменяемой карты, Always для карты, содержимое которой меняется.
Само значение VrsMode=Texture не доказывает поддержку GPU или фактическое снижение стоимости кадра. Запустите проект с --verbose и проверьте сообщения драйвера о fragment shading rate или fragment density map. В проверенном Windows/Vulkan журнал содержал Attachment fragment shading rate. Один лишь pipeline fragment shading rate не равен поддержке attachment-карты.
Не выбирайте поддержку по старому списку видеокарт. Реальный путь зависит от устройства, драйвера и backend. XR может предоставлять карту через активный XRInterface; режим XR сам по себе не включает eye tracking и не гарантирует наличие такой карты.
Включение на главном Viewport
В Project Settings задайте точные ключи:
| Ключ | Значение |
|---|---|
rendering/vrs/mode | 1 — Texture; 0 отключает VRS, 2 выбирает XR |
rendering/vrs/texture | Путь к карте, например asset://vrs_map.png |
При старте дерева главный Viewport получает эти параметры. В режиме Texture движок читает изображение по указанному пути и создаёт ImageTexture. Пустой путь или отсутствие карты не создаёт полезную карту автоматически; неверный файл даёт ошибку загрузки. Изменение ProjectSettings во время игры не заменяет настройку уже существующего Viewport — меняйте его свойства напрямую.
Для SubViewport задавайте VrsMode, VrsTexture и VrsUpdateMode у самого SubViewport. Настройки главного окна не являются автоматической настройкой всех вложенных Viewport.
Минимальный пример на C#
Помощник создаёт карту 16×16 без mipmaps: чёрный центр и периферию с R=G≈0.5. Он запрашивает VRS у переданного Viewport. Это диагностическая карта, не готовый пресет качества для игры.
using System;
using Reckfell;
public static class VrsMap
{
// A small diagnostic map, not an optimal production quality preset.
// The caller owns the returned resource.
public static ImageTexture Create()
{
using var image = Image.CreateEmpty(16, 16, false, Image.Format.Rgb8);
image.Fill(new Color(0.5f, 0.5f, 0));
for (int y = 4; y < 12; y++)
for (int x = 4; x < 12; x++)
image.SetPixel(x, y, Colors.Black);
return ImageTexture.CreateFromImage(image);
}
// Requests VRS; property readback does not prove hardware support or a speedup.
public static void Apply(Viewport viewport, Texture2D map)
{
ArgumentNullException.ThrowIfNull(viewport);
ArgumentNullException.ThrowIfNull(map);
viewport.VrsTexture = map;
viewport.VrsMode = Viewport.VrsModeEnum.Texture;
viewport.VrsUpdateMode = Viewport.VrsUpdateModeEnum.Always;
}
}Создайте карту через VrsMap.Create(), затем вызовите VrsMap.Apply(GetViewport(), map). Сохраняйте ссылку на ресурс, пока он нужен. Для неизменяемой карты после назначения можно выбрать VrsUpdateMode.Once. При отключении установите VrsMode.Disabled и уберите VrsTexture; освобождайте созданный вами ресурс после прекращения его использования. Заимствованный GetViewport() освобождать нельзя.
Как читать каналы карты
R управляет горизонтальной, G — вертикальной плотностью; B не участвует в текущем преобразовании. Чёрный сохраняет максимальную плотность. Избегайте JPEG и других потерь, меняющих числовые значения каналов.
Кодирование зависит от VRS-метода. В текущем KHR fragment shading rate пути применяется floor(channel * 2 + 0.1) с ограничением 0…2, затем ограничивается соотношение осей. Для нормализованных каналов карты:
| R, G в 8-битном изображении | Кодируемый размер фрагмента в KHR-пути |
|---|---|
| 0, 0 | 1×1 |
| 0, 128 | 1×2 |
| 128, 0 | 2×1 |
| 128, 128 | 2×2 |
| 128, 255 | 2×4 |
| 255, 128 | 4×2 |
| 255, 255 | 4×4 |
Это описание текущего шейдера, а не обещание одинаковых режимов на каждом GPU. Старая таблица с уровнями 0/85/170/255 сюда не подходит: например, 85 не повышает показатель оси с 0 до 1 при указанной формуле. Текущий KHR-конвертер не кодирует 8×8. Для fragment density map используется другой путь — инверсия R/G с нижним пределом 1/255; переносить на него таблицу KHR нельзя.
Не делайте карту размером с экран без причины. Внутренняя attachment-карта имеет размер, округлённый вверх от внутреннего разрешения Viewport, делённого на размер VRS texel устройства. Маленькая входная карта покрывает весь Viewport; её размер не равен размеру пикселя экрана.
Обновление и проверка результата
Disabled у VrsUpdateMode останавливает обновление карты, но это отдельная настройка от VrsMode.Disabled. Once копирует карту однократно; после изменения содержимого снова запросите Once либо используйте Always. Для динамической карты учитывайте стоимость её генерации и копирования.
Порядок сравнения:
- Зафиксируйте разрешение, камеру, освещение, AA и масштаб рендеринга. Прогрейте shader cache.
- Измерьте GPU-время кадра при VrsMode.Disabled.
- Включите ту же сцену с картой. Проверьте мелкие текстуры, блики, тонкие детали и движение камеры.
- Оставляйте VRS только при полезном выигрыше и приемлемом изображении. Сохранение чётких краёв геометрии не гарантирует сохранение деталей материалов.
Если эффекта нет: проверьте renderer, сообщения поддержки, саму карту, VrsMode и VrsUpdateMode. Если FPS не вырос: проверьте GPU-время и реальное узкое место, ограничитель FPS и стоимость динамической карты. Не используйте чужие замеры как обещание для своего проекта.
Проверенный пример выполнен в текущем Windows/Vulkan на Forward+ и Mobile: карта, свойства Viewport, выделенный VRS attachment и отключение. Журнал также содержит предупреждение Vulkan loader о поиске layer manifest в реестре Windows; прогон не считается полностью чистым. Байты attachment, фактическая частота вызовов shader, выигрыш FPS, качество изображения, XR и другие GPU этим тестом не подтверждены.