Скопируйте текстуру буфера металлического каркаса для чтения

Я пытаюсь сделать снимок экрана представления MetalKit (MTKView), как в ответе Сделайте снимок текущего экрана с помощью Metal в быстром режиме, но для этого необходимо, чтобы MTKView установил для framebufferOnly значение false, что, согласно Apple, отключает некоторые оптимизации.

Есть ли способ скопировать текстуру MTKView (например, view.currentDrawable.texture), чтобы я мог читать пиксели? Мне не нужно часто делать скриншоты, поэтому было бы обидно отключать оптимизацию на весь жизненный цикл работающей программы.

Я пробовал использовать буферы MTLTexture.newTextureViewWithPixelFormat и blit, но все равно получаю то же исключение, что только буфер кадра является истинным.


person GenericPtr    schedule 11.07.2018    source источник


Ответы (1)


Когда запрашивается снимок экрана, вы можете переключить framebufferOnly, выполнить один проход рендеринга, а затем переключить его обратно.

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

person Ken Thomases    schedule 11.07.2018
comment
Я даже не думал о рендеринге для другой цели (я думаю, например, FBO в OpenGL), но это, вероятно, лучший подход. Это сделано путем установки текстуры во вложении цвета MTLRenderPassDescriptor? - person GenericPtr; 11.07.2018
comment
а также знаете ли вы, как принудительно выполнить проход рендеринга с помощью MetalKit? Сначала я попытался переключить framebufferOnly, но мне кажется, что мне нужно разрешить прохождение некоторого количества циклов событий, прежде чем оно будет зарегистрировано. Честно говоря, даже не ясно, когда делать снимок экрана в цикле рендеринга, так что, возможно, я тоже напортачил. - person GenericPtr; 11.07.2018
comment
Да, вы просто устанавливаете текстуру прикрепления цвета в дескрипторе прохода рендеринга. Кроме того, должен соответствовать формат пикселей прикрепления цвета в дескрипторе конвейера рендеринга. Вы можете вызвать draw на своем MTKView, чтобы принудительно выполнить проход рендеринга. Между прочим, вы не должны обращаться к содержимому текстуры до тех пор, пока буфер команд не будет завершен, и убедитесь, что кодировщик блит-команд также поместил туда команду synchronize в конце. - person Ken Thomases; 11.07.2018
comment
Я решил пойти с переключением frameBufferOnly. Как ни странно, для этого требуется вызвать MTKView.draw 3x после установки frameBufferOnly на false, иначе я получаю пустое изображение. - person GenericPtr; 12.07.2018