BradLarson / GPUImage2

GPUImage 2 is a BSD-licensed Swift framework for GPU-accelerated video and image processing.
BSD 3-Clause "New" or "Revised" License
4.88k stars 611 forks source link

UIView.layer must be used from main thread only #226

Open chengkaizone opened 6 years ago

chengkaizone commented 6 years ago

I am having a headline warning when I record my video using GPUImage2

chengkaizone commented 6 years ago

Code: sharedImageProcessingContext.context.renderbufferStorage(Int(GL_RENDERBUFFER), from:self.layer as! CAEAGLLayer)

jwoodrow commented 6 years ago

I have/had the same issue.

as a monkeypatch I changed the following lines (starts at line 62) in the RenderView.swift file:

sharedImageProcessingContext.context.renderbufferStorage(Int(GL_RENDERBUFFER), from:self.layer as! CAEAGLLayer)

var backingWidth:GLint = 0
var backingHeight:GLint = 0
glGetRenderbufferParameteriv(GLenum(GL_RENDERBUFFER), GLenum(GL_RENDERBUFFER_WIDTH), &backingWidth)
glGetRenderbufferParameteriv(GLenum(GL_RENDERBUFFER), GLenum(GL_RENDERBUFFER_HEIGHT), &backingHeight)

by this:

let group = DispatchGroup()
group.enter()

DispatchQueue.main.async {
    sharedImageProcessingContext.context.renderbufferStorage(Int(GL_RENDERBUFFER), from:self.layer as! CAEAGLLayer)
    group.leave()
}
group.wait()

var backingWidth:GLint = 0
var backingHeight:GLint = 0
glGetRenderbufferParameteriv(GLenum(GL_RENDERBUFFER), GLenum(GL_RENDERBUFFER_WIDTH), &backingWidth)
glGetRenderbufferParameteriv(GLenum(GL_RENDERBUFFER), GLenum(GL_RENDERBUFFER_HEIGHT), &backingHeight)

I know this will block the thread but since it's a very negligible time for my use case I consider it enough.

The reason is that

sharedImageProcessingContext.context.renderbufferStorage(Int(GL_RENDERBUFFER), from:self.layer as! CAEAGLLayer)

is the reason the warning is raised, but if you only put that line on the main thread then backingWidth and backingHeight are still equal to zero, because the renderbufferStorage hasn't had time to finish on the main thread. so making the rendering thread wait for the renderbufferStorage seems the simplest solution for me.

jvk75 commented 6 years ago

Thanks @jwoodrow! Your fix removed a crash that I was having in iPhoneX (crash that was only in happening in iPhoneX)

jwoodrow commented 6 years ago

@jvk75 glad I could help, although as I said this is a quick and dirty fix.

I don't have any deep knowledge of how this library works (I'd love to try and make an equivalent of this using Metal too instead of openGL because it would probably gain in performance and stability even though it would limit device compatibility) so I don't know if this will affect performance or stability for apps since technically it does pause the gpuimage thread concerned (no idea if there are multiple threads but seeing how it performs I'd wager there are).

anyway I'd use any fix/patch not confirmed by @BradLarson with caution just in case it could break something else and then you'd end up with even more issues and less possibility of assistance (it would be complicated to help on an issue in your project in 2-3 months if your code ends up being different from everyone else's if ever this became a source of a problem).

jvk75 commented 6 years ago

In my use case the performance is not an issue as I only do still images. Trying anyway to move out of the GPUImage as there has not been much/any activity lately so future scares me.

jwoodrow commented 6 years ago

From what I gathered, Brad has other project he's focused on and when it comes to gpuimage2 his priority was to fix the linux compatibility. I'm using this library over the objective-C one because I didn't want to have to deal with bridging headers and all, but I don't feel like gpuimage2 is not production ready since it isn't updated a lot not even issue wise.

I have the same concerns as you when it comes to lack of activity which is why I'd love to work on a Metal library similar to this but there are so many things to do in order to recreate a Metal gpuimage especially with all the image operations already available on it (plus dealing with Metal textures isn't exactly a piece of cake either)

AndrewChan2022 commented 4 years ago

I change it to pull mode and it works fine: 1) filter chain push render result to GPUImageView, and GPUImageView save it. 2) in view's draw method: call renderbufferStorage, then render the result to canvas.

liuqiaohong0515 commented 3 years ago

In RenderView-UIKit.swift file, line 62

runOnMainQueue {
            sharedImageProcessingContext.context.renderbufferStorage(Int(GL_RENDERBUFFER), from:self.layer as! CAEAGLLayer)
}