2015-11-29 3 views
2

Я пытаюсь реализовать два отличных CAMetalLayers и использовать один MTLRenderCommandEncoder для рендеринга той же сцены на оба слоя (металл для OS X).Несколько целей рендеринга в металле

Для этой цели я попытался создать один MTLRenderPassDescriptor и прикреплять текстуры двух слоев к своим цветным вложениям. Мой метод отрисовки выглядит следующим образом:

- (void)render { 
    dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER); 

    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer]; 
    __block dispatch_semaphore_t block_sema = _inflight_semaphore; 
    [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) { 
     dispatch_semaphore_signal(block_sema); 
    }]; 

    MTLRenderPassDescriptor *renderPass = [MTLRenderPassDescriptor renderPassDescriptor]; 

    for (int i = 0; i < [_metalLayers count]; i++) { 
     _metalDrawables[i] = [_metalLayers[i] nextDrawable]; 
     renderPass.colorAttachments[i].texture = _metalDrawables[[_metalDrawables count] - 1].texture; 
     renderPass.colorAttachments[i].clearColor = MTLClearColorMake(0.5, 0.5, (float)i/(float)[_metalLayers count], 1); 
     renderPass.colorAttachments[i].storeAction = MTLStoreActionStore; 
     renderPass.colorAttachments[i].loadAction = MTLLoadActionClear; 
    } 

    id<MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPass]; 
    [commandEncoder setRenderPipelineState:_pipeline]; 
    [commandEncoder setVertexBuffer:_positionBuffer offset:0 atIndex:0 ]; 
    [commandEncoder setVertexBuffer:_colorBuffer offset:0 atIndex:1 ]; 
    [commandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3 instanceCount:1]; 
    [commandEncoder endEncoding]; 

    for (int i = 0; i < [_metalDrawables count]; i++) { 
     [commandBuffer presentDrawable:_metalDrawables[i]]; 
    } 
    [commandBuffer commit]; 
} 

Однако сцена визуализируется лишь на один из слоев, оказывается, чтобы быть один, связанный с текстурой первого прикрепленного управления цветом. Другой слой очищается с указанным четким цветом, но ничего не рисуется.

Имеет ли подход какой-либо шанс преуспеть или использует цветные вложения дескриптора передачи визуализации, совершенно бессмысленные при попытке отобразить одну и ту же сцену на несколько экранов (то есть CAMetalLayers)? Если да, есть ли другой возможный подход для достижения этого результата?

+1

ли ваш фрагмент шейдера запись в более чем одном приложении цвета? Я бы посмотрел раздел ['Квалификаторы атрибутов для вывода функции фрагмента'] (https://developer.apple.com/library/ios/documentation/Metal/Reference/MetalShadingLanguageGuide/func-var-qual/func- var-qual.html # // apple_ref/doc/uid/TP40014364-CH4-SW12) и спецификатор '[[color (m)]]'. – lock

+0

Вышеуказанный ответ правильный и что вам нужно. Если ваш шейдер не записывает несколько целей рендеринга, вы не увидите эти записи в ваших прикрепленных текстурах. – m3v3rik

ответ

1

Насколько я читал об этой проблеме, вы можете попробовать отобразить только одну MTLTexture (не нарисованный слой), а затем попытаться использовать методы MTLTexture getBytes и replaceRegion, чтобы скопировать данные текстуры в два слоя.

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

1

Чтобы написать несколько целей рендеринга, вам нужно будет явно записать эту цель рендеринга в вашем шейдере фрагмента. @lock уже указал на это.

struct MyFragmentOutput { 
    // color attachment 0 
    float4 clr_f [[ color(0) ]]; 

    // color attachment 1 
    int4 clr_i [[ color(1) ]]; 

    // color attachment 2 
    uint4 clr_ui [[ color(2) ]]; 
}; 

fragment MyFragmentOutput 
my_frag_shader(...) 
{ 
    MyFragmentOutput f; 
    .... 
    f.clr_f = ...; 
    f.clr_i = ...; 
    ... 
    return f;
 } 

Однако, это излишний, поскольку вам не нужен графический процессор для визуализации сцены дважды. Таким образом, ответ выше @Kacper более точен для вашего дела. Однако, чтобы добавить к его ответу, я бы рекомендовал использовать BlitEncoder, который может копировать данные между двумя текстурами на графическом процессоре, которые, как я полагаю, должны быть намного быстрее, чем у процессора.

https://developer.apple.com/library/mac/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/Blit-Ctx/Blit-Ctx.html#//apple_ref/doc/uid/TP40014221-CH9-SW4

 Смежные вопросы

  • Нет связанных вопросов^_^