2009-08-10 8 views
18

OpenGL ESレンダリングループは、私のiPhoneアプリケーションの別のスレッドに配置されています。 EAGLContextのpresentRenderbufferメソッドが失敗することを除いて、すべてがうまくいっています。結果は白い空白の画面になります。 メインスレッドで同じコードを実行すると、presentRenderbufferは成功し、グラフィックスが正しく表示されます。 別のスレッドでOpenGLを実行する正しい方法は何ですか?iphoneの別のスレッドでOpenGL ESを使用するには?

答えて

14

EAGLSharegroupを作成する必要があります。

スレッド間のOpenGLコンテキストの共有については、this threadを参照してください。 iOS5を前へ

UPDATE
私は、ディスクからのテクスチャの非同期ロードを許可するようにスレッド間のOpenGLコンテキストを共有しました。しかし、iOS5のCVOpenGLESTextureCachesは基本的にテクスチャのアップロードを無料にするので、shareGroupsはもう必要なく、私のコードはより簡単で高速になります。

+1

「テクスチャアップロードを無料にする」とはどういう意味ですか?私はCVPixelBufferCreateWithBytes()からの結果でCVOpenGLESTextureCacheCreateTextureFromImage()を呼び出してみました。glTexImage2D()でテクスチャをアップロードするのと同じくらい時間がかかりました。 – MoDJ

+0

glTexImage2Dはmemcpyと同じ機能をテクスチャに、TextureFromImageは画像のテクスチャをポイントします。コピーは必要ありません。多くのメモリ帯域幅を節約できます。 GLの多くが非同期であるため、タイミングだけでは明らかにならないでしょう。 GPU/CPU使用率とフレームレートを調べる必要があります。 –

+0

http://stackoverflow.com/questions/12813442/cvopenglestexturecache-vs-gltexsubimage2d-on-iosを参照してください。ユーザーがバッファを渡したときに記述したようには動作しません。実際、この実行パスでは、glTexImage2Dで費やされるCPU時間が非常に多くなりました。 – MoDJ

2

別のスレッドでコンテキストをレンダリングしないでください。代わりに、すべての計算を別のスレッドで行い、レンダリングがメインの表示スレッドで行われるようにします。

+0

あなたは本当に簡単にGCDを使用していることを行うことができます。ここでは

は、定型的なコードです。 – Cthutu

13

ありがとう、Fistman。私はそれを動作させ、別のスレッドを使用して期待したパフォーマンスの向上を得ました。 EAGLSharegroupは問題を解決しました。

hereのように、2番目のスレッドのコンテキストを作成しました。


#import <UIKit/UIKit.h> 
#import <OpenGLES/EAGL.h> 
#import <OpenGLES/ES1/gl.h> 
#import <OpenGLES/ES1/glext.h> 
#import <QuartzCore/QuartzCore.h> 
#import <OpenGLES/EAGLDrawable.h> 


struct OpenGLContext 
{ 
    GLint Width; 
    GLint Height; 

    GLuint RenderBuffer; 
    GLuint FrameBuffer; 
    GLuint DepthBuffer; 

    UIView* View; 
    EAGLContext* MainContext; 
    EAGLContext* WorkingContext; 
    EAGLSharegroup* Sharegroup; 

    // Trivial constructor. 
    OpenGLContext(); 

    // Call on the main thread before use. 
    // I call it in layoutSubviews. 
    // view must not be nil. 
    void MainInit(UIView* view); 

    // Call on the rendering thread before use, but 
    // after MainInit(); 
    void InitOnSecondaryThread(); 

    // Call before any OpenGL ES calls, at the 
    // beginning of each frame. 
    void PrepareBuffers(); 

    // Present frame. Call at the end of each 
    // frame. 
    void SwapBuffers(); 
}; 

OpenGLContext::OpenGLContext() 
{ 
    Width = 0; 
    Height = 0; 

    RenderBuffer = 0; 
    FrameBuffer = 0; 
    DepthBuffer = 0; 

    View = 0; 
    MainContext = 0; 
    WorkingContext = 0; 
    Sharegroup = 0; 
} 

void OpenGLContext::InitOnSecondaryThread() 
{ 
    EAGLSharegroup* group = MainContext.sharegroup; 
    if (!group) 
    { 
     NSLog(@"Could not get sharegroup from the main context"); 
    } 
    WorkingContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:group]; 
    if (!WorkingContext || ![EAGLContext setCurrentContext:WorkingContext]) { 
     NSLog(@"Could not create WorkingContext"); 
    } 
} 

void OpenGLContext::MainInit(UIView* view) 
{ 
    View = view; 
    MainContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; 

    if (!MainContext || ![EAGLContext setCurrentContext:MainContext]) { 
     NSLog(@"Could not create EAGLContext"); 
     return; 
    } 
    NSLog(@"Main EAGLContext created");  

    glGenFramebuffersOES(1, &FrameBuffer); 
    glGenRenderbuffersOES(1, &RenderBuffer); 
    glGenRenderbuffersOES(1, &DepthBuffer); 

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, RenderBuffer); 

    if (![MainContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)View.layer]) 
    { 
     NSLog(@"error calling MainContext renderbufferStorage"); 
     return; 
    } 

    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, RenderBuffer); 

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &Width); 
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &Height); 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, DepthBuffer); 
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, Width, Height); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, DepthBuffer); 

    glFlush(); 

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { 
     NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); 
    } 

    WorkingContext = MainContext; 
} 

void OpenGLContext::PrepareBuffers() 
{ 
    if (!WorkingContext || [EAGLContext setCurrentContext:WorkingContext] == NO) 
    { 
     NSLog(@"PrepareBuffers: [EAGLContext setCurrentContext:WorkingContext] failed"); 
     return; 
    } 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer); 
} 

void OpenGLContext::SwapBuffers() 
{ 
    if (!WorkingContext || [EAGLContext setCurrentContext:WorkingContext] == NO) 
    { 
     NSLog(@"SwapBuffers: [EAGLContext setCurrentContext:WorkingContext] failed"); 
     return; 
    } 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, RenderBuffer); 

    if([WorkingContext presentRenderbuffer:GL_RENDERBUFFER_OES] == NO) 
    { 
     NSLog(@"SwapBuffers: [WorkingContext presentRenderbuffer:GL_RENDERBUFFER_OES] failed"); 
    } 
} 


関連する問題