我有(多个)具有CAEAGLLayer类型的层的UIViews,并且能够在附加到这些层的renderbuffer上调用EAGLContext presentRenderBuffer,在辅助线程上,没有任何类型的图形故障。
我预计至少会看到一些撕裂,因为合成这些UIViews的其他UI是在主线程上更新的。CAEAGLLayer (我将kEAGLDrawablePropertyRetainedBacking设置为NO)是否在幕后执行一些双缓冲?
我只想知道为什么这是可行的。
示例:
BView是一个UIView子类,它在共享的EAGLContext中拥有一个帧缓冲区,并将渲染缓冲区存储分配给它的OpenGLES图层
@implementation BView
-(id) initWithFrame:(CGRect)frame context:(EAGLContext*)context
{
self = [super initWithFrame:frame];
// Configure layer
CAEAGLLayer* eaglLayer = (CAEAGLLayer*)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking : [NSNumber numberWithBool:NO], kEAGLDrawablePropertyColorFormat : kEAGLColorFormatSRGBA8 };
// Create framebuffer with renderbuffer attached to layer
[EAGLContext setCurrentContext:context];
glGenFramebuffers( 1, &FrameBuffer );
glBindFramebuffer( GL_FRAMEBUFFER, FrameBuffer );
glGenRenderbuffers( 1, &RenderBuffer );
glBindRenderbuffer( GL_RENDERBUFFER, RenderBuffer );
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer];
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer );
return self;
}
+(Class) layerClass
{
return [CAEAGLLayer class];
}`UIViewController在初始化时在主线程上添加一个BView实例:
BView* view = [[BView alloc] initWithFrame:(CGRect){ 0.0, 0.0, 75.0, 75.0 } context:Context];
[self.view addSubView:view];在辅助线程上,渲染到BView中的帧缓冲区并呈现它;在本例中,它在来自视频AVCaptureDevice的回调中,定期调用:
-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{
[EAGLContext setCurrentContext:bPipe->Context.GlContext];
// Render into framebuffer ...
// Present renderbuffer
glBindRenderbuffer( GL_RENDERBUFFER, BViewsRenderBuffer );
[Context presentRenderbuffer:GL_RENDERBUFFER];
}发布于 2016-01-21 20:59:25
它以前是不工作的。如果缓冲区出现在除主线程之外的任何线程上,更新视图通常会出现几个问题。这似乎已经工作了一段时间了,但是你自己去实现它是有风险的。较新的版本可能会有问题,一些较旧的版本可能仍然会有问题(并不是说您无论如何都需要支持一些旧的操作系统版本)。
苹果在内部如何工作的问题上总是有点封闭,但我们可能会猜到相当多的事情。由于iOS似乎是唯一一个使用你的主缓冲区作为FBO (帧缓冲区对象)的平台,所以我预计主帧缓冲区对于开发是不可访问的,并且当你呈现渲染缓冲区时,你的主FBO实际上会被重新绘制到主帧缓冲区。上一次我检查了呈现渲染缓冲区的方法,它会阻塞你当前的线程,而且似乎受到屏幕刷新率的限制(大多数情况下是60fps),这意味着仍然存在一些锁定机制。应该做一些额外的测试,但我希望有某种类型的缓冲池需要重新绘制到主缓冲池中,在该池中,此时只能存在一个唯一的缓冲区id,或者调用线程被阻塞。这将导致对当前渲染缓冲区的第一次调用根本不会被阻塞,但如果前一个缓冲区还没有被重新绘制,则每个顺序都会被阻塞。
如果这是真的,那么是的,双缓冲在某些时候是强制的,因为你可以立即继续绘制到你的缓冲区。因为渲染缓冲区在帧上具有相同的id,所以它可能不会被交换(据我所知),但它可以被重新绘制/复制到另一个缓冲区(最有可能是一个纹理),这可以在任何给定的时间动态完成。在此过程中,当您第一次呈现缓冲区时,您将把缓冲区复制到将被锁定的纹理。当屏幕刷新时,纹理将被收集并解锁。因此,如果这个纹理被锁定,你的演示调用将阻塞线程,否则它将顺利继续。很难说这是双缓冲。它有两个缓冲区,但它仍然使用锁定机制。
我真的希望你能理解为什么它是有效的。这与您在单独的共享上下文中加载大型数据结构时使用的过程基本相同,该上下文在单独的线程上运行。
不过,不幸的是,这大部分都只是猜测。
https://stackoverflow.com/questions/34922117
复制相似问题