Оптимизированы ли мои шейдерные программы GLSL браузером или драйвером? - PullRequest
0 голосов
/ 25 июня 2018

В моем недавнем проекте я процедурно создаю фрагментные шейдеры, которые выглядят так (но, возможно, больше), которые я отображаю с помощью WebGL:

precision mediump float;
uniform vec2 u_windowSize;
void main() {
  float s = 2.0 / min(u_windowSize.x, u_windowSize.y);
  vec2 pos0 = s * (gl_FragCoord.xy - 0.5 * u_windowSize);
  if (length(pos0) > 1.0) { gl_FragColor = vec4(0,0,0,0); return; }
  vec2 pos1 = pos0/0.8;
  vec2 pos2 = ((1.0-length(pos1))/length(pos1)) * pos1;
  vec3 col2 = vec3(1.0,1.0,1.0);
  vec2 pos3 = pos2;
  vec3 col3 = vec3(1.0,0.0,0.0);
  vec2 tmp2 = 6.0*(1.0/sqrt(2.0)) * mat2(1.0,1.0,-1.0,1.0) * pos2;
  vec3 col4;
  if (mod(tmp2.x, 2.0) < 1.0 != mod(tmp2.y, 2.0) < 1.0) {
     col4 = col2;
  } else {
     col4 = col3;
  };      
  vec2 pos5 = pos0;
  vec3 col5 = vec3(0.0,1.0,1.0);
  vec3 col6;
  if (length(pos0) < 0.8) {
     col6 = col4;
  } else {
     col6 = col5;
  };
  gl_FragColor = vec4(col6, 1.0);
}

Очевидно, что здесь есть некоторая избыточность, которую вы бы не писали от руки - копирование pos2 в pos3, например, бессмысленно. Но так как я генерирую этот код, это удобно.

Прежде чем я преждевременно начну оптимизацию и заставлю мой генератор создавать, как мы надеемся, более эффективный код, я хотел бы знать:

Браузеры и / или графические драйверы уже оптимизируют такие вещи (так что мне не нужно)?

1 Ответ

0 голосов
/ 25 июня 2018

Для браузера не требуется никакой оптимизации.Вы можете увидеть, что браузер отправляет драйверу, используя расширение WEBGL_debug_shaders.

Пример:

const gl = document.createElement('canvas').getContext('webgl');
const ext = gl.getExtension('WEBGL_debug_shaders');
const vs = `
attribute vec4 position;
uniform mat4 matrix;

void main() {
  float a = 1. + 2. * 3.;  // does this get optimized to 7?
  float b = a;             // does this get discarded?
  gl_Position = matrix * position * vec4(b, a, b, a);
}
`;

const s = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(s, vs);
gl.compileShader(s);
console.log(ext.getTranslatedShaderSource(s));

На моей машине / драйвере / браузере, который возвращает этот результат

#version 410
in vec4 webgl_74509a83309904df;
uniform mat4 webgl_5746d1f3d2c2394;
void main(){
(gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
float webgl_2420662cd003acfa = 7.0;
float webgl_44a9acbe7629930d = webgl_2420662cd003acfa;
(gl_Position = ((webgl_5746d1f3d2c2394 * webgl_74509a83309904df) * vec4(webgl_44a9acbe7629930d, webgl_2420662cd003acfa, webgl_44a9acbe7629930d, webgl_2420662cd003acfa)));
}

Мы можем видеть, что в этом случае простая константа математика была оптимизирована, но фактчто a и b одинаковы не были.Тем не менее, нет никакой гарантии, что другие браузеры выполнят эту оптимизацию.

Независимо от того, оптимизировать драйверы или нет, зависит от драйвера.Большинство драйверов хотя бы немного оптимизируют, но полная оптимизация требует времени.DirectX может занять> 5 минут для оптимизации одного сложного шейдера с полной оптимизацией, так что оптимизацию, вероятно, следует выполнить в автономном режиме .В случае DirectX ожидается, что вы сохраните результат бинарного шейдера, чтобы избежать следующих 5 минут, когда шейдер понадобится в следующий раз, но для WebGL это невозможно, поскольку бинарные шейдеры будут и не переносимыми, и проблемой безопасности.Также недопустимо длительное зависание браузера в ожидании компиляции, поэтому браузеры не могут запросить DirectX для полной оптимизации.Тем не менее, некоторые бинарные шейдеры кеша в браузере закулисны.

...