Производительность вершинного шейдера GLSL с ранним возвратом и ветвлением - PullRequest
0 голосов
/ 03 мая 2018

У меня есть вершинный шейдер как таковой

void main (){

    vec4 wPos = modelMatrix * vec4( position , 1. );

    vWorldPosition = wPos.xyz;

    float mask = step(
        0.,
        dot(
            cameraDir, 
            normalize(normalMatrix * aNormal)
        )
    );

    gl_PointSize = mask * uPointSize;

    gl_Position = projectionMatrix * viewMatrix * wPos;

}

Я не совсем уверен, как проверить работоспособность шейдера, и исключить другие факторы, такие как overdraw. Я думаю, что точка размера 1, расположенная в сетке в пространстве экрана без какого-либо наложения, будет работать?

В противном случае мне любопытны эти твики:

(удаляет step, удаляет умножение, вводит if else)

void main (){

    if(dot(
         cameraDir, 
         normalize(normalMatrix * aNormal) //remove step
    ) < 0.) {
        gl_Position = vec4(0.,.0,-2.,.1); 
        gl_PointSize = 0.;
    } else {

        gl_PointSize = uPointSize; //remove a multiplication

        vec4 wPos = modelMatrix * vec4( position , 1. );

        vWorldPosition = wPos.xyz;
        gl_Position = projectionMatrix * viewMatrix * wPos;
    }

}

против чего-то подобного:

void main (){

    if(dot(
         cameraDir, 
         normalize(normalMatrix * aNormal) 
    ) < 0.) {
        gl_Position = vec4(0.,.0,-2.,.1); 
        return;
    }

    gl_PointSize = uPointSize; 

    vec4 wPos = modelMatrix * vec4( position , 1. );

    vWorldPosition = wPos.xyz;

    gl_Position = projectionMatrix * viewMatrix * wPos;

}

Будут ли эти шейдеры вести себя по-разному и почему / как?

Мне интересно, есть ли что-то, чтобы измерить разницу в производительности.

  • Есть ли какое-то значение, например, число MAD или что-то еще, что, очевидно, даст другой код?
  • Различают ли графические процессоры разных поколений эти различия по-разному?
  • Если пошаговая версия гарантированно будет самой быстрой, существует ли известный список шаблонов того, как можно избежать ветвления, и какие операции предпочитать? (Также возможно использование floor вместо step?) :

.

float condition = clamp(floor(myDot + 1.),0.,1.); //is it slower?

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Переменных слишком много, поэтому ответ "это зависит". Некоторые графические процессоры могут обрабатывать ветви. Некоторые не могут, и код расширяется компилятором, так что нет ветвей, только математика, умноженная на 0, и другая математика, которой нет. Тогда есть такие вещи, как мозаичные графические процессоры, которые пытаются агрессивно избежать оверлея. Я уверен, что есть и другие факторы.

Теоретически вы можете запустить миллион или несколько миллионов итераций вашего шейдера и рассчитать время с помощью

gl.readPixels(one pixel);
const start = performance.now();
...draw a bunch..
gl.readPixels(one pixel);
const end = performance.now();
const elapsedTime = end - start;

gl.readPixels - синхронная операция, поэтому она останавливает конвейер графического процессора. Сам по себе elapsedTime не является реальным временем, поскольку он включает в себя запуск графического процессора и остановку его среди прочего, но кажется, что вы можете сравнить elapsedTime с одного шейдера с другим, чтобы увидеть, что быстрее.

Другими словами, если elapsedTime равен 10 секундам, это не значит, что ваш шейдер занял десять секунд. Это означает, что для запуска графического процессора, запуска шейдера и остановки графического процессора потребовалось 10 секунд. Сколько из этих секунд начало, сколько остановка и сколько ваш шейдер недоступен. Но если elaspedTime для одного шейдера равно 10 секундам и 11 для другого, то, вероятно, можно с уверенностью сказать, что один шейдер быстрее другого. Обратите внимание, что вы, вероятно, хотите сделать тест достаточно длинным, чтобы получить разницу в секундах, а не в микросекундах. Вам также необходимо протестировать несколько графических процессоров, чтобы убедиться, что разница в скорости всегда сохраняется.

Обратите внимание, что вызов return в вершинном шейдере не препятствует генерации вершины. На самом деле то, что gl_Position в этом случае не определено.

0 голосов
/ 03 мая 2018

Условные ветки стоят дорого на графических процессорах - как правило, значительно дороже, чем умножения, поэтому ваши пересмотренные шейдеры, вероятно, медленнее.

...