Create 2 framebuffers, But introduced a new problem: splash screen, the screen keeps flickering

what I want to do is this:

  • Create 2 framebuffers, let’s call them fb1 and fb2.
  • Render the scene to fb2 normally.
  • Render fb2 to fb1 with one post-processing effect.
  • Render fb1 to the default framebuffer (we’ll call it fb0) with another post-processing effect.

This method really works. But introduced a new problem: splash screen, the screen keeps flickering.

After verification: changing glFinish to glReadPixels, the flickering phenomenon still exists.
But the image saved by glReadPixels is normal.

Ok, so overall you want:

  • SCENE → FB2 → FB1 → Default FB

and you’re getting screen flashing on the splash screen?

Also, this is a continuation of this thread, correct?

When starting a new thread, please provide context information. See:

for tips on this. Include information such as:

  • GPU and GPU driver version,
  • OS
  • what exactly you did when the problem started occurring,
  • what you’ve tried to resolve the problem yourself, and the results of those tests,
  • code snippets you believe may be relevant to your problem, etc.

You didn’t include anything about GPU, but based on this datasheet:

I’m going to assume you’re running on:

Also, this time you posted in an OpenGL forum instead of OpenGL ES. I’m going to assume you’re still dev/testing on OpenGL ES and move your thread there.

In any case, if my assumptions here are correct, key to your problem is probably that you’re running on an embedded tile-based GPU. Tile-based GPU is key here. Your flashing problem likely indicates that you are issuing a rendering command sequence that is causing a pipeline flush in the middle of the GPU rendering a render target (think default framebuffer or FBO). You should also be able to observe this in a decent profiling tool, and Imagination Tech (in my experience) has good profiling tools.

Do you know what a pipeline flush is? If so, I won’t spend much verbiage on this except to summarize that rasterization for a render target is being split. This can happen for a number of reasons. Obvious examples include issuing a glReadPixels(), glBlitFramebuffer(), glFinish(), or glFlush() in the middle of rendering a render target.

Where I’ve hit it on PowerVR before is with glClientWaitSync() using GL_SYNC_FLUSH_COMMANDS_BIT. This triggers a full pipeline flush. If you want to sync just on vertex work completion and not full-pipeline completion, there’s a trick to do that.

Also IIRC, reconfiguring an FBO can trigger a pipeline flush if there is outstanding rendering work on that FBO. So keep a small pool of FBOs and round-robin across them to avoid this. In the driver, the framebuffer is “the” resource with which all rasterization work is associated, so don’t reconfig those soon after queuing work on them unless you want a pipeline flush to occur. That said, there’s a finite GPU mem cost per FBO/framebuffer however, so you can’t go crazy and just create a bunch of them or you’ll exceed GPU memory.

You always have to keep in mind with a tile-based mobile GPU that (unlike a discrete desktop GPU) the whole architecture of the chip is geared toward rasterization occurring a frame or two late. If you do anything to thwart that, your performance will tank, and you may additionally get on-screen flashing effects as well.

Thank you very much for your prompt and detailed answer. Although there is some knowledge in it, I don’t understand it very well, but I am still very grateful.

background:
Use off-screen rendering on TDA4.
QNX system,
SDK version 7.3,
OpenGL ES
The same off-screen rendering is OK on TDA2 based on Linux system 3.7 and 3.8SDK.
I use it in the same thread.

See the following website for specific information:
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1033627/tda4vm-off-screen-rendering-problem-0x506-gl_invalid_framebuffer_operation?tisearch=e2e-sitesearch&keymatch=TDA4%20Offline#

But they didn’t solve it for me, and I was very anxious to solve the problem.
I really don’t know what to do now?

So ask specific questions. We don’t know what you don’t know. Ultimately, you’re going to need to figure this out yourself.

Did you look for some of the operations I mentioned above in your code (or similar calls which read the render targets)? Did you find any matches? Were any of those calls made in “in the middle” of submitting primitives to rasterize onto the same render target?

If you don’t see any of those, I’d suggest disabling massive sections of code in your program until your problem goes away. Then, incrementally re-enable code until the problem returns. Then, you’ll know what section of your code is triggering this problem. You can then binary search this section down to the root cause (or causes). And the results of this search will give you a specific question (or questions) to ask about on these forums.

Also, you did clear up all OpenGL errors being triggered in your code, correct? Including that GL_INVALID_FRAMEBUFFER_OPERATION?

There are a lot of differences between these systems, so this is an apples-vs-oranges comparison. TDA4 v. TDA2, QNX vs. Linux, SDK version 7.3 vs. version 3.7 / 3.8, … and those are just the differences you’ve listed here.

If you think one of these differences may be key, you need to get rid of the other differences to see if it specifically correlates with your problem.

By the way, at the end of the code you posted on that other thread:

glBindFramebuffer(GL_FRAMEBUFFER, m_nSvDefaultFbo);

GLenum eErrStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
...
if(eErrStatus != GL_FRAMEBUFFER_COMPLETE)
    ....

It may be clear to you, but here you are not checking the FBO completeness status for either of the 2 FBOs you just created and configured (m_nSvTopviewFbo or m_nSvPart3dFbo), but rather this other framebuffer (m_nSvDefaultFbo) that just happened to be bound before this section of code. Was this intentional?

Thank you for your reply.

  1. I use glGetError to check errors everywhere,
int nErrId = glGetError();
if (nErrId != GL_NO_ERROR)
printf("[AVM] Error: 0x%x... ...\n",nErrId);

There are no errors.

FBO also uses glCheckFramebufferStatus to check for errors.
No errors were reported.

  1. This error has been resolved: GL_INVALID_FRAMEBUFFER_OPERATION.

  2. I have annotated all glFinish functions (glReadPixels(), glBlitFramebuffer(), glFlush() are not used elsewhere),
    Still flickering.

  3. My code is roughly as follows:

  1. Initialize FBO
void SvEglRenderBase::InitFrameBufferOpt()
{
	GLenum eStatus;
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nSvDefaultFbo);
	printf("[AVM] Current FBO is %d ... ...\r\n", m_nSvDefaultFbo);
	//glActiveTexture(GL_TEXTURE0 + 15);
	glGenTextures(1, &m_nSvTopviewTexture);
	glBindTexture(GL_TEXTURE_2D, m_nSvTopviewTexture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SV_2D_LUT_WIDTH, SV_2D_LUT_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
	//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SV_2D_LUT_WIDTH, SV_2D_LUT_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, 0);

	//Depth buffer
	glGenRenderbuffers(1, &m_nSvTopviewDepth);
	glBindRenderbuffer(GL_RENDERBUFFER, m_nSvTopviewDepth);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, SV_2D_LUT_WIDTH, SV_2D_LUT_HEIGHT);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	//Framebuffer to link everything together
	glGenFramebuffers(1, &m_nSvTopviewFbo);
	glBindFramebuffer(GL_FRAMEBUFFER, m_nSvTopviewFbo);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_nSvTopviewTexture, 0);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_nSvTopviewDepth);

	printf("[AVM] m_nSvTopviewFbo = %d ... ...\n",m_nSvTopviewFbo);

	if ((eStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
		fprintf(stderr, "[AVM] Offscreen glCheckFramebufferStatus returned error 0x%x... ... \r\n", eStatus);
		m_nSvTopviewFbo = 0;
		return;
	}
	glBindFramebuffer(GL_FRAMEBUFFER, m_nSvDefaultFbo);

}
  1. Rendering and drawing
... ...
... ...
//Here TDA4 API, which creates the default FBO
appEglBindFrameBuffer(glAvmParams->eglWindowObj, &renderTexProp);		//TDA4 API, which creates the default FBO

//This is my own, and an another FBO is also created in it
reder_renderFrame(&glAvmParams->render3DSRVObj,glAvmParams->eglWindowObj,texYuv);
{
	//reder_renderFrame is roughly as follows:
	GLint nDefaultFbo;
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &nDefaultFbo);
	if(m_pRender->m_nSvTopviewFbo!=0)
	{
		glBindFramebuffer(GL_FRAMEBUFFER, m_pRender->m_nSvTopviewFbo);
		m_pRender->ShaderUse(SV_2D_RECT_SHADER);
		DrawOffline();
		glBindFramebuffer(GL_FRAMEBUFFER, nDefaultFbo);
		Draw(m_pRender->m_nSvTopviewTexture);
}

//The rest is TDA4's own API
//glFinish();//I commented it out here, but the screen still flashes
glBindFramebuffer(GL_FRAMEBUFFER, 0);
appEglSwap(glAvmParams->eglWindowObj);
cur_time = tivxPlatformGetTimeInUsecs() - cur_time;
appPerfStatsHwaUpdateLoad(APP_PERF_HWA_GPU,cur_time,output_desc->imagepatch_addr[0].dim_x*output_desc->imagepatch_addr[0].dim_y);
... ...
... ...

Possibly - We may have to create sync objects to synchronize rendering.
How to create a synchronization object to synchronize rendering, especially this synchronization double buffering?

Um… why? What are you trying to synchronize?

If you render to texture X, and then render to texture Y using X, you don’t need to do anything to make that work (so long as X isn’t attached to the FBO containing Y).

Create 2 framebuffers, But introduced a new problem: splash screen, the screen keeps flickering:

  • Create 2 framebuffers, let’s call them fb1 and fb2.
  • Render the scene to fb2 normally.
  • Render fb2 to fb1 with one post-processing effect.
  • Render fb1 to the default framebuffer (we’ll call it fb0) with another post-processing effect.

This method really works. But introduced a new problem: splash screen, the screen keeps flickering.

I feel that the crux of this problem lies in: how to synchronize double buffering?
Maybe I don’t have enough knowledge in this area, can you provide some demo reference?

Thanks~
Because I created two framebuffers which caused the splash screen, the details are as follows:
Create 2 framebuffers, But introduced a new problem: splash screen, the screen keeps flickering:

Create 2 framebuffers, let’s call them fb1 and fb2.
Render the scene to fb2 normally.
Render fb2 to fb1 with one post-processing effect.
Render fb1 to the default framebuffer (we’ll call it fb0) with another post-processing effect.
This method really works. But introduced a new problem: splash screen, the screen keeps flickering.

I suspect that it may be caused by the lack of synchronization of framebuffers, but I doubt it because I have no other direction to investigate and solve.

Do you have other solutions to help me solve this problem?

Repeating the same thing over and over is not helping anyone fix your problem.

Without having the entirety of your code, we can only guess at what the problem might be. I suggest doing what Dark Photon suggested and start ripping out pieces of code until you can make the problem go away, then put them back until it shows up again.

If you’re doing what you say you’re doing, then synchronization isn’t a problem.

My rendering function is as follows:

void render_renderFrame()
{
#if 1
		//Using off-screen rendering here will flash the screen
		//Using off-screen rendering here will flash the screen
		//Using off-screen rendering here will flash the screen
		GLint nDefaultFbo;
        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &nDefaultFbo);
		glBindFramebuffer(GL_FRAMEBUFFER, m_nSvFbo);
		DrawOffline(m_tagSvStartPoint);
		glBindFramebuffer(GL_FRAMEBUFFER, nDefaultFbo);
		float pVerLT[2] = { 0 , 0};
		float pVerRB[2] = { 480, 720};
		DrawSubtexture(pVerLT, pVerRB, m_nSvTexture);
		
#else
		//Off-screen rendering is not used here, and there will be no flickering screen if you draw directly
		//Off-screen rendering is not used here, and there will be no flickering screen if you draw directly
		//Off-screen rendering is not used here, and there will be no flickering screen if you draw directly
		TagSvIntPoint tagSvStartPoint;
		tagSvStartPoint.x = 0;
		tagSvStartPoint.y = 0;
		float fW = 480;
		float fH = 720;
		DrawView(tagSvStartPoint,fW,fH);
#endif
}

My FBO is initialized as follows:

void InitFBO()
{
	GLenum eStatus;
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_nSvDefaultFbo);

	glGenTextures(1, &m_nSvTexture);
	glBindTexture(GL_TEXTURE_2D, m_nSvTexture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 480, 720, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, 0);

	glGenRenderbuffers(1, &m_nSvDepth);
	glBindRenderbuffer(GL_RENDERBUFFER, m_nSvDepth);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 480, 720);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	glGenFramebuffers(1, &m_nSvFbo);
	glBindFramebuffer(GL_FRAMEBUFFER, m_nSvFbo);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_nSvTexture, 0);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_nSvDepth);


	if ((eStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
		fprintf(stderr, "Offscreen glCheckFramebufferStatus returned error 0x%x... ... \r\n", eStatus);
		m_nSvFbo = 0;
		return;
	}
	glBindFramebuffer(GL_FRAMEBUFFER, m_nSvDefaultFbo);

}

My entire rendering process is as follows:
The rendering process in TDA4:

... ...
1. texYuv[i] = appEglWindowGetTexYuv(pEglWindowObj, &texProp[i]);
... ...
2. appEglBindFrameBuffer(glSrvParams->eglWindowObj, &renderTexProp);
Default FBO is used in this function
glGenTextures(1, &tex_obj->tex);
glBindTexture(GL_TEXTURE_2D, tex_obj->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenFramebuffers(1, &tex_obj->fboId);
glBindFramebuffer(GL_FRAMEBUFFER, tex_obj->fboId);
GLuint rboDepthStencil;
glGenRenderbuffers(1, &rboDepthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, prop->width, prop->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, tex_obj->tex);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)tex_obj->img);
glBindFramebuffer(GL_FRAMEBUFFER, tex_obj->fboId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, tex_obj->tex, 0);
... ...
3. render_renderFrame();

Now the problem is here: if I use a new FBO in render_renderFrame (not the same as tex_obj->fboId in appEglBindFrameBuffer in step 2),
Here it will report 0x506 GL_INVALID_FRAMEBUFFER_OPERATION error, so nothing can be drawn.
The reason why I use a new FBO here is that I want to draw A first, then draw B, and finally display it as a new texture after processing.

4. glFinish();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
appEglSwap(glSrvParams->eglWindowObj);

Looking forward to your prompt reply, thank you~