Проблемы производительности WebGL с сеткой вершин>65k на MacBook Pro
Следующая модель имеет хорошую производительность на нескольких бюджетных машинах:
http://examples.x3dom.org/example/x3dom_sofaGirl.html
Однако на MacBook Pro с Nvidia GT 650m частота кадров очень низкая. Я думал, что это потому, что MacBook не имеет OES_element_index_uint
расширение, но расширение появляется, если я делаю:
document.createElement("canvas").getContext("experimental-webgl").getSupportedExtensions();
Реструктуризация сетки ниже 65К решает проблему. Есть ли способ добиться хорошей производительности без реструктуризации?
Я установил приложение (gfxCardStatus), которое отключило GT 650m и принудительно использовало только встроенную графику. Теперь все работает отлично. Это ошибка драйвера?
Я нашел еще одну 3d-сцену, которая работает на выделенном графическом процессоре быстрее, чем на встроенном:
http://examples.x3dom.org/binaryGeo/oilrig_demo/index.html
Я думаю, это потому, что он состоит из множества маленьких ячеек. Также, когда я запускаю эту сцену, я слышу, как вентилятор GPU раскручивается Это не было со сценой GirlGirl.
1 ответ
Во-первых, WebGL не ограничивается 65 тыс. Вершин на вызов. gl.drawElements
имеет ограничение в 64 КБ, хотя есть расширения, которые удаляют это ограничение. gl.drawArrays
не имеет такого ограничения, хотя.
Я не знаю, почему это медленно, но глядя на фрейм в WebGL Inspector X3DOM использует gl.drawArrays
Я вырыл немного больше. Я попытался использовать Web Tracing Framework, а также профилировщик Chrome. Это показало много времени, проведенного в gl.readPixels
,
Чтобы увидеть, была ли это проблема, я открыл консоль JavaScript и заменил gl.readPixels
с такой операцией
В консоли JavaScript:
// find the canvas
c = document.getElementsByTagName("canvas")[0]
// get the webgl context for that canvas
gl = c.getContext("webgl")
// replace readPixels with a no-op
gl.readPixels = function(x, y, w, h, f, t, b) {
var s = w * h * 4;
for (var ii = 0; ii < s; ++ii) {
b[ii] = 0;
}
};
Что убрано readPixels
от появления в профилировщике
но образец не работал быстрее.
Далее я попробовал взлом drawArrays
рисовать меньше.
В консоли JavaScript:
// save off the original drawArrays so we can call it
window.origDrawArrays = gl.drawArrays.bind(gl)
// patch in our own that draws less
gl.drawArrays = function(t, o, c) { window.origDrawArrays(t, o, 50000); }
Что вы знаете, теперь он работает очень быстро. Хм. Может быть, это ошибка драйвера. Его просили нарисовать 1070706 вершин, но вряд ли это большое количество для NVidia GT 650m
Итак, я не знаю почему, но мне хотелось изучить этот вопрос. Я написал собственное приложение для отображения тех же данных. Он работает со скоростью 60 кадров в секунду легко. Я проверил интегрированную графику в WebGL, как сказал OP. Также 60fps легко. NVidia 650GT находится на скорости около 1 кадра в секунду.
Я также проверил Safari и Firefox. Они тоже бегают медленно. Общее дело там - УГОЛ. Все они используют ANGLE для переписывания шейдеров. Возможно, есть проблема, так как тот же шейдер работал нормально на моем родном тесте. Конечно, тест Native не выполняет те же функции, что и WebGL, но он не только рисует 1M polys.
Поэтому я подал ошибку: https://code.google.com/p/chromium/issues/detail?id=437150