Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 金属中的多个渲染目标_Objective C_Cocoa_Core Animation_Render To Texture_Metal - Fatal编程技术网

Objective c 金属中的多个渲染目标

Objective c 金属中的多个渲染目标,objective-c,cocoa,core-animation,render-to-texture,metal,Objective C,Cocoa,Core Animation,Render To Texture,Metal,我正在尝试实现两个不同的camertallayer,并使用一个MTLRenderCommandEncoder将同一场景渲染到两个层(Metal for OS X) 为此,我尝试创建一个MTLRenderPassDescriptor,并将两个层的纹理附加到其颜色附件。我的渲染方法如下所示: - (void)render { dispatch_semaphore_wait(_inflight_semaphore, DISPATCH_TIME_FOREVER); id<MTLC

我正在尝试实现两个不同的
camertallayer
,并使用一个
MTLRenderCommandEncoder
将同一场景渲染到两个层(Metal for 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];
}
-(无效)渲染{
发送信号灯等待(发送中信号灯,发送时间永远);
id commandBuffer=[\u commandQueue commandBuffer];
__块调度信号量\u t块信号量=\u飞行中信号量;
[commandBuffer addCompletedHandler:^(id缓冲区){
调度信号量信号(块信号);
}];
MTLRenderPassDescriptor*renderPass=[MTLRenderPassDescriptor renderPassDescriptor];
对于(int i=0;i<[u金属层计数];i++){
_MetalDrawable[i]=[[u metalLayers[i]nextDrawable];
renderPass.colorAttachments[i]。纹理=\u metalDrawables[[u metalDrawables count]-1]。纹理;
renderPass.colorAttachments[i].clearColor=MTLClearColorMake(0.5,0.5,(float)i/(float)[[u金属层计数],1);
renderPass.colorAttachments[i].storeAction=MTLStoreActionStore;
renderPass.colorAttachments[i].loadAction=MTLLoadActionClear;
}
id commandEncoder=[commandBuffer renderCommandEncoderWithDescriptor:renderPass];
[commandEncoder setRenderPipelineState:_管道];
[commandEncoder setVertexBuffer:_positionBuffer偏移量:0索引:0];
[commandEncoder setVertexBuffer:_colorBuffer偏移量:0索引:1];
[commandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3 instanceCount:1];
[命令编码];
对于(int i=0;i<[u metaldawables count];i++){
[commandBuffer presentDrawable:_metalDrawables[i]];
}
[命令缓冲区提交];
}
但是,场景仅渲染到其中一个层,该层与第一个颜色附件的纹理关联。使用指定的“清除颜色”清除另一层,但不绘制任何内容


当尝试将同一场景渲染到多个屏幕(即
camertallayers
)时,该方法是否有成功的机会,或者使用渲染过程描述符的颜色附件完全没有意义?如果是这样的话,有没有其他可行的方法来实现此结果?

据我所知,您可以尝试仅渲染一个MTLTexture(非可绘制层),然后尝试使用MTLTexture方法getBytes和replaceRegion将纹理数据复制到两个可绘制层中


目前,我正在对普通纹理进行渲染,但我遇到了一些瑕疵,目前它对我不起作用,也许您会找到解决方法。

要写入多个渲染目标,您需要在片段着色器中显式写入该渲染目标@洛克已经指出了这一点

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;
    }
然而,这是一种过分的做法,因为您实际上不需要GPU来渲染场景两次。因此,@Kacper给出的上述答案对于您的案例更为准确。然而,为了补充他的答案,我建议使用BlitEncoder,它可以在GPU上的两个纹理之间复制数据,我认为这应该比CPU快得多


片段着色器是否写入多个颜色附件?我会看一看这个部分和
[[color(m)]
属性限定符。上面的答案是正确的,也是您需要的。除非您的着色器写入多个渲染目标,否则您将无法在附加的纹理中看到这些写入。我对Metal自己是新手,可能这没什么,但我发现奇怪的是,您初始化“\u metalDrawables[I]”,然后在同一循环中使用“\u metalDrawables[[u metalDrawables count]-1]”。这难道不意味着后者没有针对i=0到计数-2进行初始化吗?当CbCr纹理的分辨率比Y低两倍时,多个渲染目标对于RGB到YCbCr的转换非常有用