Фактична вартість будь-якої конкретної зміни стану залежить від такої кількості факторів, що загальна відповідь майже неможлива.
По-перше, кожна зміна стану потенційно може мати як сторону CPU, так і вартість GPU. Вартість CPU може залежно від вашого драйвера та графічного API виплачуватися повністю на головному потоці або частково на фоновому потоці.
По-друге, вартість GPU може залежати від обсягу роботи в польоті. Сучасні GPU дуже конвеєрні і люблять отримувати багато роботи в польоті відразу, і найбільше уповільнення, яке ви можете отримати, - це від зупинки трубопроводу, щоб все, що зараз знаходиться в польоті, повинне піти на пенсію до зміни штату. Що може спричинити застій трубопроводу? Ну, це залежить від вашого GPU!
Те, що ви насправді потрібно знати, щоб зрозуміти ефективність тут: це що потрібно зробити драйверу та графічному процесору, щоб обробити ваш стан змін? Це, звичайно, залежить від вашого GPU, а також від деталей, якими ISV часто не публікують публічно. Однак існують деякі загальні принципи .
Графічні процесори, як правило, розділені на передній та резервний. Frontend обробляє потік команд, згенерований драйвером, тоді як бекенд виконує всю реальну роботу. Як я вже говорив раніше, сервіс любить багато працювати в польоті, але йому потрібна певна інформація для зберігання інформації про цю роботу (можливо, заповнена за кордоном). Якщо ви б'єте достатньо невеликими партіями і використовуєте весь кремній, відслідковуючи роботу, тоді передній край повинен буде зупинитися, навіть якщо навколо буде сидіти багато невикористаних кінських сил. Отож принцип тут: чим більше змін у стані (і невеликих нічиїх), тим більше шансів на те, що ти поголодуєш на вихідний процесор .
Хоча малюнок насправді обробляється, ви в основному просто запускаєте шейдерні програми, які роблять доступ до пам’яті для отримання форменого одягу, даних вашого буфера вершин, текстур, а також структур управління, які повідомляють одиницям шейдера, де буфери вершин і ваші текстури. І GPU має кеш-пам'ять перед цими пам'яттю. Тому щоразу, коли ви будете кидати нові уніформи або нові прив'язки текстури / буфера до GPU, швидше за все, кеш пропустить перший раз, коли він має їх прочитати. Інший принцип: більшість змін стану призведе до пропуску кешу GPU. (Це найбільш змістовно, коли ви керуєте постійними буферами самостійно: якщо ви зберігаєте постійні буфери однакові між малюнками, вони, швидше за все, залишаться в кеші на графічному процесорі.)
Значну частину витрат на державні зміни для шайдерських ресурсів становить сторона ЦП. Щоразу, коли ви встановлюєте новий постійний буфер, драйвер, швидше за все, копіює вміст цього постійного буфера в командний потік для GPU. Якщо ви встановите єдину форму, драйвер, швидше за все, перетворює її у великий постійний буфер за вашою спиною, тому він повинен шукати зміщення цієї рівномірної форми в постійному буфері, скопіюйте значення в, а потім позначте постійний буфер як брудний, тому він може бути скопійований у командний потік до наступного дзвінка розіграшу. Якщо ви прив'язуєте новий буфер текстури або вершини, драйвер, ймовірно, копіює структуру управління для цього ресурсу навколо. Крім того, якщо ви використовуєте дискретний графічний процесор на багатозадачній ОС, драйвер повинен відстежувати кожен ресурс, який ви використовуєте, і коли ви починаєте використовувати його, щоб ядро " s Менеджер пам'яті GPU може гарантувати, що пам'ять для цього ресурсу знаходиться у VRAM GPU, коли трапляється розіграш. Принцип:Зміни стану змушують драйвер переміщати пам'ять навколо, щоб генерувати мінімальний потік команд для GPU.
Коли ви змінюєте поточний шейдер, ви, ймовірно, викликаєте пропущення кеш-пам'яті GPU (у них є кеш інструкцій!). В принципі, робота процесора повинна обмежуватися введенням в командний потік нової команди, що говорить "використовувати шейдер". Насправді, однак, існує цілий безлад у складанні шейдерів. Драйвери GPU дуже часто ліниво збирають шейдери, навіть якщо ви створили шейдер достроково. Більш актуальною для цієї теми, однак, деякі стани не підтримуються апаратним забезпеченням GPU, а замість цього компілюються в програму шейдера. Один популярний приклад - формати вершин: вони можуть бути складені в вершинний шейдер, а не в окремому стані на чіпі. Тож якщо ви використовуєте вершинні формати, які раніше не використовували з певним вершинним шейдером, тепер ви можете заплатити купу витрат на процесор, щоб наклеїти шейдер і скопіювати програму шейдера до GPU. Крім того, компілятор драйверів і шейдерів може робити змову робити всілякі речі для оптимізації виконання програми шейдерів. Це може означати оптимізацію плану пам’яті вашої форми та структур управління ресурсами, щоб вони були добре упаковані в сусідні регістри пам'яті або шейдери. Тож коли ви змінюєте шейдери, це може призвести до того, що драйвер перегляне все, що ви вже прив'язали до конвеєра, і перепакує його у абсолютно інший формат для нового шейдера, а потім скопіює його в командний потік. Принцип: Це може означати оптимізацію плану пам’яті вашої форми та структур управління ресурсами, щоб вони були добре упаковані в сусідні регістри пам'яті або шейдери. Тож коли ви змінюєте шейдери, це може призвести до того, що драйвер перегляне все, що ви вже прив'язали до конвеєра, і перепакує його у абсолютно інший формат для нового шейдера, а потім скопіює його в командний потік. Принцип: Це може означати оптимізацію плану пам’яті вашої форми та структур управління ресурсами, щоб вони були добре упаковані в сусідні регістри пам'яті або шейдери. Тож коли ви змінюєте шейдери, це може призвести до того, що драйвер перегляне все, що ви вже прив'язали до конвеєра, і перепакує його у абсолютно інший формат для нового шейдера, а потім скопіює його в командний потік. Принцип:зміна шейдерів може спричинити багато переміщення пам'яті процесора.
Зміни буфера кадрів, мабуть, залежать від впровадження, але вони, як правило, досить дорогі на GPU. Ваш GPU може не в змозі одночасно обробляти кілька дзвінків дзвінків до різних цілей рендерінгу, тому може знадобитися затримка трубопроводу між цими двома дзвінками. Можливо, доведеться очистити кеші, щоб ціль візуалізації була прочитана пізніше. Може знадобитися вирішити роботу, яку вона відклала під час малювання. (Дуже часто буває накопичення окремої структури даних разом із буферами глибини, цілями відображення MSAA тощо). Можливо, це доведеться доопрацювати, коли ви переходите від цієї цілі візуалізації. Якщо ви користуєтесь графічним процесором, заснованим на плитці як і багато мобільних графічних процесорів, при переключенні з буфера кадру може бути потрібна досить велика кількість фактичного затінення.) Принцип:зміна цілей візуалізації дорога для GPU.
Я впевнений, що це все дуже заплутано, і, на жаль, важко отримати занадто конкретні, тому що деталі часто не є загальнодоступними, але я сподіваюся, що це напівпристойний огляд деяких речей, які насправді відбуваються, коли ви називаєте якусь державу зміна функції у вашому улюбленому графічному API.