WebGL можно эмулировать асинхронный вызов gl.finish()

WebGL хорош и асинхронен тем, что вы можете отправить длинный список команд рендеринга, не дожидаясь их завершения. Однако, если по какой-то причине вам нужно дождаться завершения рендеринга, вы должны сделать это синхронно с gl.finish(). Конечно, было бы лучше, если бы gl.finish принял обратный вызов и немедленно вернулся?

Вопрос: Есть ли способ подражать этому надежно?

Случай использования: Я передаю большое количество вершин большому затененному холсту, а затем используя drawImage, чтобы скопировать разделы этого большого холста на небольшие холсты на странице. Я фактически не использую gl.finish(), но drawImage(), похоже, имеет тот же эффект. В моем приложении повторная рендеринг запускается только тогда, когда пользователь выполняет действие (например, нажатие кнопки), и может занять несколько сотен миллисекунд. Было бы неплохо, если бы во время рендеринга браузер все еще реагировал, позволяя прокручивать и т.д. Я смотрю, в частности, на решение для Chrome, хотя что-то, что также работает в Firefox и Safari, было бы хорошо.

Возможный (плохой) ответ:. Вы можете попытаться оценить, как долго будет выполняться рендеринг, а затем установить тайм-аут, начинающийся с вызова gl.finish(). Однако надежно делать эту оценку для всех размеров буфера вершин и всех пользователей будет довольно сложно и неточно.

Возможный (не) ответ: requestAnimationFrame выполняет то, что я ищу... это не так, не так ли?

Ответ 1

Вы уже частично ответили на ваш ответ: drawImage() действительно имеет законченное поведение, поскольку он заставляет все выдающиеся команды рисования завершить, прежде чем он вернет данные изображения. Проблема в том, что даже если gl.finish() сделал то, что вы этого хотели, дождитесь завершения рендеринга, вы все равно будете иметь такое же поведение, как и сейчас. Основной поток будет заблокирован при завершении рендеринга, прерывая способность пользователя взаимодействовать со страницей.

В идеале то, что вы хотели бы в этом сценарии, - это своего рода обратный вызов, который указывает, когда набор команд рисования завершен без фактической блокировки, чтобы дождаться их. К сожалению, такой обратный вызов не существует (и было бы удивительно сложно обеспечить его, учитывая то, как работают внутренние браузеры!)

Пристойная среда в вашем случае может заключаться в том, чтобы сделать некоторые разумные оценки, когда вы чувствуете, что изображение может быть готово. Например, после того, как вы отправили вызов розыгрыша через 3 или 4 requestAnimationFrame, прежде чем вы вызовете drawImage. Если вы последовательно наблюдаете, что он занимает больше времени (10 кадров?), Тогда вращение дольше. Это позволит пользователям продолжать взаимодействие со страницей в обычном режиме и не производить никаких задержек при рисовании рисунка, потому что содержимое закончило рендеринг или значительно меньше задержки, потому что вы выполняете синхронный шаг в середине рендеринга. В зависимости от предполагаемого использования вашего сайта рендеринг в режиме реального времени, возможно, даже будет стоять, пока он не начнет показываться в течение секунды или секунды.

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