GLSL - оголошення глобальних змінних за межами сфери основної функції


12

Чи допомагає це оголошувати змінні за межами основної сфери вашої функції в GLSL? Чи реально ці змінні використовувати повторно і чи ефективніше це?

Ось код, про який йдеться:

varying vec2 vposition;
uniform float seed;
uniform float top;
uniform float bottom;
uniform float phi;
uniform float theta;
uniform float scaledPI;
uniform float yn;
uniform float ym;
uniform float rx;
uniform float ry;
uniform float radius;

const float PI = 3.141592653589793238462643383;

float left;
float right;
float mscaled;
float xn;
float xm;
void main() {
    float t = vposition.y * yn + ym;

    if(t <= 0.0 || t >= PI){
        left = phi - PI;
        right = phi + PI;
    }else{
        mscaled = scaledPI / (1 - abs(Math.cos(theta)));
        mscaled = mscaled < PI ? mscaled : PI;
        left = phi - mscaled;
        right = phi + mscaled;
    }
    xn = (left - right) / ((-rx / 2.0) - (rx / 2.0));
    xm = left - ((-rx/2.0) * xn);
    float p = vposition.x * xn + xm;

    vec3 coords = vec3( sin(p) * sin(t), cos(t), cos(p) * sin(t) );
    float nv = surface( vec4( coords, seed ) );
    gl_FragColor = vec4( vec3( nv, nv, nv ), 1.0 );
}

3
Це питання бентежить. У GLSL немає основної петлі. Ви маєте на увазі main()функцію? Чи є ваші значення насправді глобальними змінними (обмундирування чи атрибути в мові GLSL) або постійними значеннями?
Шон Міддлічч

Чи можете ви розмістити якийсь код як приклад того, про що ви говорите?
Натан Рід

Я оновив питання кодом.
RodgerDodger

@ user1286792: Це не змінює факту, що в GLSL немає основного циклу . Не ясно, про що ти говориш. Що саме, на вашу думку, буде врятовано цим шляхом?
Нікол Болас

@NicolBolas Я оновив питання, щоб бути більш зрозумілим. Сподіваємось, це корисно зараз комусь у майбутньому.
RodgerDodger

Відповіді:


33

Я думаю, я отримую те, що ти намагаєшся запитати. Я припускаю, що ваша основна проблема - це неоднорідні змінні, визначені поза main():

float left;
float right;
float mscaled;
float xn;
float xm;

Давайте подивимось, як працюють GPU та GLSL. У GPU немає стека або записів активації виклику. Не існує способу імітувати область чи локальні змінні в GLSL, як це може зробити компілятор C для більшості процесорів. Все, що існує, - це регістри, які є або однорідними регістрами, входами, виходами на етапі шейдерів, і локальним файлом регістрів, унікальним для виклику шейдера.

Іншими словами, оскільки не існує такого поняття, як функція, стек чи купа, усі змінні, заявлені де-небудь, містяться в реєстрі. Незалежно від того, чи є вони локальними для певного обсягу в GLSL або глобальними для всього файлу, це не має ніякого значення. Вони просто регістри.

Однак розподільник регістра не є частиною стандарту GLSL. Різні реалізації OpenGL можуть мати різний рівень якості, що стосується перетворення високого рівня GLSL-коду в машинний код низького рівня, який розуміє GPU. Однією з найбільш складних частин компілятора (GLSL або іншим способом) є розподіл регістрів . Це та частина компілятора, яка визначає, які регістри займає дана змінна. У C це трохи складніше, оскільки, як правило, доводиться мати справу з дуже крихітними файлами реєстру (особливо на x86), і йому доводиться мати справу з розливом реєстру (переміщення змінних в стек) і згладжуванням (збереження змінних назад в ОЗУ перед викликом функцій) і непарні інструкції, які вимагають, щоб вихід був у певному реєстрі (x86)idivнаприклад). У графічних процесорах є великий реєстр-файл через відсутність стека чи купи, тож розподільник може бути простішим.

Однак файл реєстру не є нескінченним. Якщо у вас більше змінних, ніж регістри, що підтримуються вашим обладнанням, компілятору доведеться спробувати помістити всі ваші змінні в регістри. Зазвичай для цього потрібна певна форма перевірки діапазону життєдіяльності . Тобто, якщо ви використовуєте змінну xnдля одного обчислення, то ніколи не використовуйте її знову, компілятор може визначити це, а потім знати, що реєстр, зайнятий, xnможе бути використаний згодом іншою змінною, таким чином дозволяючи отримати більше змінних, ніж є регістри (так довго оскільки одразу не так вже й багато живих змінних).

Однак компілятор цього не може зробити. Цього не має. Або це може зробити це лише в деяких випадках. Області застосування спрощують компілятори набагато простіше вирішити проблему. Усі регістри, призначені місцевим змінним функцій, можна повторно використовувати після того, як ця функція вийде, оскільки вона знає, що змінні є мертвими. Глобальні змінні не мають такої легкої гарантії. Отже, деякі менш здібні компілятори можуть також не оптимізувати своє життя, і глобальні змінні завжди з'їдають реєстр. Це не зробить нічого повільніше, але на деяких драйверах це може обмежити розмір шейдера, який ви можете записати.

Загалом, я б дуже рекомендував зберігати всі змінні локалізованими. Тримайте визначення максимально наближеним до використання змінної, наскільки це має сенс. Це стосується всіх мов програмування, а не лише GLSL. Я також рекомендую робити кожен "змінний" const у кожному можливому випадку. Знову це може бути натяком на деякі менш здатні компілятори, що можливі певні оптимізації, і що ще важливіше, це робить ваш код більш самодокументованим та легким у обслуговуванні.

І звичайно, ось ваша обов'язкова порада "просто перевірити та дізнатися точно". Напишіть свій шейдер із і без глобалістів та профіліруйте його. Будь-які поради щодо ефективності роботи в Інтернеті повинні бути недовірливими та вважати, що вони можуть бути вичерпані у припущеннях або застарілих.


Саме це я і мав на увазі. Ви чудово відповіли на моє запитання, а також краще пояснили, що я просив.
RodgerDodger

1
Насправді іноді оголошення масивів як const замість non-const робить увесь шейдер повільнішим (A LOT повільніше). Я помітив цю проблему на моєму GTX 460.
Тара

Я просто позбувся дивної помилки і сильно підозрюю, що графічний процесор Adreno (OpenGL ES 3.1) не зміг скласти шейдер, оскільки змінні оголошувались поза основними.
comodoro

Один з найбільш ретельних відповідей на те, що я коли-небудь бачив - молодець!
duhaime

Сьогодні я знаю щось нове. Сьогодні я вчуся, я по-справжньому не знаю і не розумію glsl. Тільки тому, що я можу використовувати його, щоб зробити циліндричний простір, трансформований геометрією gif, не означає, що я розумію, як це працює.
cmarangu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.