Metal 中的多个渲染目标

coo*_*t29 5 cocoa core-animation objective-c render-to-texture metal

我正在尝试实现两个不同的,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];
}
Run Code Online (Sandbox Code Playgroud)

但是,场景仅渲染到其中一个图层,结果证明该图层与第一个颜色附件的纹理相关联。另一层用指定的清除颜色清除,但没有绘制任何内容。

在尝试将同一场景渲染到多个屏幕(即CAMetalLayers)时,该方法是否有任何成功的机会,或者使用渲染通道描述符的颜色附件完全没有意义?如果是这样,是否有任何其他可以想象的方法来实现这一结果?

小智 2

据我读到有关此问题的信息,您可以尝试仅渲染到一个 MTLTexture (不是可绘制层),然后尝试使用 MTLTexture 方法 getBytes 和 ReplaceRegion 将纹理数据复制到两个可绘制层中。

目前我正在努力渲染到普通纹理,但我遇到了一些伪影,目前它对我不起作用,也许你会找到解决这个问题的方法。