iOS/Metal: как читать из буфера глубины в точке?

Я хотел бы прочитать из буфера глубины. В GL на OS X я мог бы сделать:

float depth[2][2]; // get 2x2 for bilinear interpolation
glReadPixels(s.x, s.y, /*width*/2, /*height*/2, GL_DEPTH_COMPONENT, GL_FLOAT, depth);

(Обратите внимание, что с OpenGL ES на iOS вы не можете читать из буфера глубины)

Что эквивалентно металлу?

Похоже, мне нужно сделать:

_renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionStore;

А потом как-то читать из буфера через ЦП?

Хотя, возможно, есть лучший способ, так как мне нужна только одна точка (там, где касание). Может ли фрагментный шейдер сохранить глубину только для этой точки (или 2x2 для билинейной интерполяции), что позволит мне оставить storeAction как MTLStoreActionDontCare?


person Taylor    schedule 10.02.2015    source источник


Ответы (1)


Я установил действие хранилища глубины на MTLStoreActionStore, а затем сделал следующее в методе рендеринга:

[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {

    // We're done! So read from the depth texture.        

    // Just read the center pixel for now.
    MTLRegion region = MTLRegionMake2D(_depthTex.width/2, _depthTex.height/2, 1, 1);

    float depth;
    [_depthTex getBytes:&depth bytesPerRow:_depthTex.width*4 fromRegion:region mipmapLevel:0];

    NSLog(@"read depth: %f", depth);

    dispatch_semaphore_signal(block_sema);

}];

Это сработало и было подтверждено разработчиком Apple на форумах как «правильный способ».

Обратите внимание, что чтение из буфера глубины невозможно с OpenGL ES на iOS. Металл ФТВ!

person Taylor    schedule 10.02.2015
comment
Я не верю, что вы можете использовать getBytes: больше. С сайта разработчиков Apple: apple.co/1IG3jpw Текстуры с форматом пикселей глубины, трафарета или глубины/трафарета могут выделяться только в режиме частного хранилища. Чтобы загрузить или сохранить содержимое этих текстур, вы должны выполнить операцию blit. - person datboi; 10.12.2015
comment
@datboi интересно. Я собираюсь пересмотреть это и обновить код. - person Taylor; 03.01.2016
comment
Извините, полное объяснение: если вы используете iOS, текстуры по умолчанию имеют значение MTLStorageModeShared, что не требует синхронизации через кодировщик команд blit. Однако текстуры глубины и трафарета являются исключением и должны выделяться с помощью MTLStorageModePrivate. Из-за этого требования к режиму хранения единственным вариантом будет перенос из этой частной текстуры глубины/трафарета (в VRAM) в доступную ЦП память, поскольку этот метод (getBytes) не поддерживается для текстур с частным режимом хранения. – Apple, apple.co/1OGM7h7 - person datboi; 21.01.2016