**Render State — это набор настроек GPU-пайплайна (графического конвейера), которые определяют **как** отрисовывается примитив, тогда как сам шейдер определяет **чем** он отрисовывается.
Unity рассматривает эти настройки как часть «Pipeline State Object», поэтому каждый раз, когда любой из параметров меняется, движок вынужден выполнить `SetPass` и настроить пайплайн заново.
### Ключевые группы настроек render state
|Категория|Примеры свойств в Unity|Что управляет на GPU|Почему меняется SetPass|
|---|---|---|---|
|**Depth / Stencil**|`ZWrite`, `ZTest`, `Stencil { … }`|Буфер глубины и трафарет|Включение/выключение записи глубины или другие правила требуют нового PSO|
|**Blending (смешивание)**|`Blend SrcAlpha OneMinusSrcAlpha`, `AlphaToMask`|Режимы смешивания с цветовым буфером|Каждый уникальный набор факторов смешивания = новый пайплайн|
|**Rasterization**|`Cull Off/Front/Back`, `Wireframe`, `Offset`|Отсечение граней, полигональный режим|Другие комбинации куллинга → новая конфигурация растеризатора|
|**Render Target & Color Mask**|`ColorMask RGB`, MRT-настройки|В какие текстуры и каналы пишем|Изменение списка/маски целей рендеринга требует переподготовки|
|**Multisample / Antialiasing**|MSAA Sample Count, `AlphaToMask On`|Кол-во сэмплов, порядок resolve|Разные настройки MSAA несовместимы в одном PSO|
|**Dynamic States**(меняют реже)|`Viewport`, `Scissor`, `LineWidth`|Задают через _draw-time_ команды|Влияют меньше: можно менять без нового PSO, но Unity часто фиксирует их вместе|
> **Важно:** числовые uniform-свойства (`float`, `vector`, `texture`) _не_ относятся к render state. Их меняют через `MaterialPropertyBlock`, и SRP Batcher подменит буфер параметров без `SetPass`.
### Как это выражается в Unity
1. **Pass / SubShader**
Внутри `.shader` каждый `Pass` фиксирует свой набор render-state директив (`Blend`, `Cull`, …). Если два материала используют **один и тот же** pass (вариант), но отличаются только значениями uniform’ов, SRP Batcher оставит их в одном SetPass.
2. **Shader Keywords (shader_feature / multi_compile)**
Ключевик, который включает, например, `ZWrite Off` или `Blend Premultiply`, породит новый **shader variant**, а вместе с ним — уникальный render state. Поэтому Unity разорвёт батч и выполнит ещё один `SetPass`.
3. **Graphics Pipeline (URP/HDRP, Built-in)**
- В URP/HDRP Unity создаёт _RenderPass/RenderGraph_; для каждого PSO с уникальным (shader variant + render state) формируется собственный индекс в _SRP Batcher Cache_.
- В Built-in рендерере правила те же, просто без RenderGraph-абстракции.
### Практический итог для оптимизации
- Стремитесь иметь как можно меньше разных комбинаций **Blend / Depth / Cull / Stencil** между объектами, видимыми в одном кадре.
- Включайте флаги (`_ALPHATEST_ON`, `_NORMALMAP` …) только тем материалам, которым это действительно нужно.
- Для числовых параметров используйте `MaterialPropertyBlock` — он изменяет данные в существующем батче без разрыва.
- Проверяйте Frame Debugger: колонка **Batch cause** покажет «Objects use different render states» (или «different keywords») — именно эти отличия вызывают лишние SetPass Calls.
Таким образом, **render state** — это «паспорт» конфигурации GPU. Каждый раз, когда этот паспорт отличается, Unity обязана сделать новую команду `SetPass`, что увеличивает нагрузку на CPU и может разбивать SRP-Batcher-батчи, поэтому унификация render state критична для производительности.