Как определить количество активных контекстов WebGL? - PullRequest
0 голосов
/ 17 апреля 2020

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

Два вопроса:

  1. Есть ли способ определить, насколько вы близки к ограничениям, т.е. сколько активных контекстов WebGL существует и сколько доступно?
  2. Я нашел кусочки информации тут и там, но не смог точно определить, какие ограничения существуют для каждого браузера, оба домен и макс. Каковы ограничения для Chrome, Firefox, Safari, Edge и IE 11?

1 Ответ

1 голос
/ 17 апреля 2020

Не существует надежного способа узнать, сколько контекстов поддерживает браузер, и даже если вы знали, что он может измениться завтра или измениться в зависимости от различных условий машины, на которой работает браузер, или собственной эвристики браузера, например, возможно, если vram низкий, он позволяет меньше контекстов. Или, может быть, если новейший контекст использует слишком много ресурсов, он пытается освободить пространство, теряя другие контексты.

Мое личное правило заключается в том, что браузеры поддерживают по крайней мере 8 контекстов. Это то, что я построил мои сайты, чтобы предположить.

Вы, наверное, можете понять, почему существует предел. Приложения WebGL используют массу ресурсов. Может быть, не все из них, но в частности игры могут легко использовать концерты vram, и этот vram не так легко виртуализируется, как обычный ram, тем более что для отображения результатов в самом браузере каким-то образом все результаты должны быть одинаковыми обработать. Таким образом, поскольку они, вероятно, не виртуализированы, и поскольку они могут использовать столько ресурсов, браузеру необходимо ограничить количество одновременно создаваемых ресурсов, чтобы высвободить ресурсы для последней страницы, которую посещает пользователь.

Существует множество Вы можете использовать один контекст, чтобы отображать на веб-странице множество вещей, которые упоминаются или упоминаются в вопросах и ответах, на которые вы ссылаетесь.

Вы можете рассчитывать, например, так:

const canvases = [];
let done;

function createCanvas() {
  const canvas = document.createElement('canvas');
  canvas.addEventListener('webglcontextlost', () => {
    done = true;
    console.log('num contexts:', canvases.length - 1);
  });
  const gl = canvas.getContext('webgl');
  canvases.push(canvas);
}

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

async function main() {
  while (!done) {
    createCanvas();
    await wait();
  }
}

main();

На моем Macbook Pro Chrome 80, Firefox 75, Safari 13.1 и Safari на iPhone 11, все сообщили о 16 контекстах. Chrome 81 на Android на Pixel 2 XL сообщили 8, Firefox на том же устройстве сообщили 9. Но, как сказано выше, все эти цифры могут измениться завтра или даже сегодня при других условиях.


Follow Up

Независимо от того, какое ограничение браузера установлено для домена в Chrome, но для каждой страницы в Firefox и Safari. Вы можете проверить это здесь . Откройте 2 windows. Создайте 16 контекстов в одном окне, затем создайте еще один в другом. В Chrome вы увидите, что первое окно теряет контекст, как только еще один контекст создается во втором окне. В Firefox и Safari каждое окно имеет свой предел.

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

В Firefox с кодом, связанным выше, как только я создаю 17-й контекст в том же окне, он переходит в бесконечное число. oop. Он теряет первый контекст, тот регистр контекста, который должен быть восстановлен, firefox восстанавливает его немедленно, который теряет другой контекст, повтор. Кажется, что это делает невозможным использование в Firefox.

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

Очевидно, что это недостаточно определенная и недостаточно проверенная часть WebGL spe c.

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

const groups = [];
let done;

function createCanvas(parent, lostCallback) {
  const canvas = document.createElement('canvas');
  parent.appendChild(canvas);
  canvas.addEventListener('webglcontextlost', lostCallback);
  const gl = canvas.getContext('webgl');
  return {canvas, gl};
}

function createGroup() {
  const div = document.createElement('div');
  const group = {div};
  div.className = 'c';
  document.body.appendChild(div);
  
  function restore() {
    div.innerHTML = '';
    const {canvas, gl} = createCanvas(div, () => {
      done = true;
      group.gl = undefined;
      div.innerHTML = "context lost, click to restore";
      div.addEventListener('click', restore, {once: true});
    });
    group.gl = gl;
    group.canvas = canvas;
  }

  restore();  
  groups.push(group);
}

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

async function main() {
  while (!done) {
    createGroup();
    await wait();
  }
}

function render() {
  for (const {gl} of groups) {
    if (!gl) {
      continue;
    }
    gl.clearColor(Math.random() * 0.5 + 0.5, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
  }
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

main();
.c { 
  display: inline-block;
  border: 1px solid black;
  margin: 1px;
  font-size: xx-small;
}
canvas { 
  width: 100px;
  height: 10px;
  display: block;
}

Также обратите внимание, что исходная точка потери WebGL заключается в том, что WebGL не контролирует ОС. Например, в Windows, если какое-либо приложение делает что-то на GPU, что занимает слишком много времени, сама ОС сбрасывает GPU, который эффективно теряет контексты для всех приложений, а не только для вашего браузера. ВСЕ ПРИЛОЖЕНИЯ. Браузер ничего не может сделать, чтобы предотвратить это, поэтому браузер просто должен передать эту информацию на вашу веб-страницу. Также в Windows вы можете включать / отключать графические процессоры без перезагрузки. Это еще один случай, когда браузер не имеет контроля и просто должен сказать вам, что контекст был потерян.

...