[fixed]OpenGL FBO size larger than screen on ATI

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

[fixed]OpenGL FBO size larger than screen on ATI

Post by Nadro »

I fixed problem with FBO textures larger than window size on ATI Radeon cards. This is problem:

Orginal Irrlicht FBO code, Windows resolution 640x480 RTT texture 1024x1024:
Image
Draw is only part 640x480 on the texture

Fixed Irrlicht FBO code, Windows resolution 640x480 RTT texture 1024x1024:
Image
Draw is full texture

With this code OpenGL RTTs also support alpha values.

This is fixed code:

Code: Select all

                                      *** Irrlicht Source ***

--------------------------------- COpenGLTexture.cpp --------------------------------
//! ColorFrameBuffer constructor
COpenGLTexture::COpenGLTexture(const core::dimension2d<s32>& size,
                                bool extPackedDepthStencilSupported,
                                const char* name,
                                COpenGLDriver* driver)
 : ITexture(name), ImageSize(size), Driver(driver), Image(0),
  TextureName(0), InternalFormat(GL_RGB8), PixelFormat(GL_RGBA),
  PixelType(GL_UNSIGNED_BYTE), HasMipMaps(false), IsRenderTarget(true),
  ColorFrameBuffer(0), DepthRenderBuffer(0), StencilRenderBuffer(0), Locks(0)
{
	#ifdef _DEBUG
	setDebugName("COpenGLTexture_FBO");
	#endif

	// generate color texture
	Driver->extGlGenFramebuffers(1, &ColorFrameBuffer);
	Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);

	GLuint depthbuffer;
	Driver->extGlGenRenderbuffers(1, &depthbuffer);
	Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, depthbuffer);
	Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, ImageSize.Width, ImageSize.Height);

	Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthbuffer);

	glGenTextures(1, &TextureName);
	glBindTexture(GL_TEXTURE_2D, TextureName);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ImageSize.Width, ImageSize.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, TextureName, 0);
	GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
}
------------------------------------------------------------------------------------------
********************************************************************
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Alpha values are already supported for OpenGL RTTs.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Yes in SVN version ;) but in 1.4 not.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You might do everyone a favor and post the diffs instead of pastes of the new code. That way it is easier to see what you've changed and it could be used as a patch by those who care to give it a whirl.

Travis
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I think this version uses a completely different FBO approach. I did not have the time, yet, to look up the extension registry, but I guess it would have to be put into another ifdef in case the other FBO extension is not supported.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

I use Irrlicht FBO code from SVN and this is difference:

Code: Select all

//! ColorFrameBuffer constructor
COpenGLTexture::COpenGLTexture(const core::dimension2d<s32>& size,
                                bool extPackedDepthStencilSupported,
                                const char* name,
                                COpenGLDriver* driver)
 : ITexture(name), ImageSize(size), Driver(driver), Image(0),
  TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA),
  PixelType(GL_UNSIGNED_BYTE), HasMipMaps(false), IsRenderTarget(true),
  ColorFrameBuffer(0), DepthRenderBuffer(0), StencilRenderBuffer(0), Locks(0)
{
	#ifdef _DEBUG
	setDebugName("COpenGLTexture_FBO");
	#endif

	// generate color texture
	glGenTextures(1, &TextureName);
	glBindTexture(GL_TEXTURE_2D, TextureName);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width,
		ImageSize.Height, 0, PixelFormat, PixelType, 0);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

/* I remove this tips with create depth texture and stencil texture
#ifdef GL_EXT_packed_depth_stencil
	if (extPackedDepthStencilSupported)
	{
		// generate packed depth stencil texture
		glGenTextures(1, &DepthRenderBuffer);
		glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width,
			ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth
	}
	else // generate separate stencil and depth textures
#endif
	{
		// generate depth texture
		glGenTextures(1, &DepthRenderBuffer);
		glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, ImageSize.Width,
			ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // we 're in trouble! the code below does not complete the FBO currently...
        // stencil buffer is only supported with EXT_packed_depth_stencil extension (above)

//        // generate stencil texture
//        glGenTextures(1, &StencilRenderBuffer);
//        glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer);
//        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//        glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width,
//                        ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0);
//        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}
*/
#ifdef GL_EXT_framebuffer_object
	// generate frame buffer
	Driver->extGlGenFramebuffers(1, &ColorFrameBuffer);
	Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);

// I generate render buffer, standard operations for generate FBO but not use in Irrlicht
   GLuint depthbuffer;
   Driver->extGlGenRenderbuffers(1, &depthbuffer);
   Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, depthbuffer);
   Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, ImageSize.Width, ImageSize.Height);
// and split randerbuffer with framebuffer
   Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthbuffer);

	// attach color texture to frame buffer
	Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
						GL_COLOR_ATTACHMENT0_EXT,
						GL_TEXTURE_2D,
						TextureName,
						0);
// I not use tips with create separate texture for depth and stencil, so I remove this
/*
	// attach depth texture to depth buffer
	Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
						GL_DEPTH_ATTACHMENT_EXT,
						GL_TEXTURE_2D,
						DepthRenderBuffer,
						0);
	// attach stencil texture to stencil buffer
	Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
						GL_STENCIL_ATTACHMENT_EXT,
						GL_TEXTURE_2D,
						StencilRenderBuffer,
						0);
*/
	glGetError();
/* I remove it and I use "GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);" but We can use standard Irrlicht test for Color texture*/
	// check the status
/*	if (!checkFBOStatus(Driver))
	{
		printf("FBO=%u, Color=%u, Depth=%u, Stencil=%u\n",
			ColorFrameBuffer, TextureName, DepthRenderBuffer, StencilRenderBuffer);
		if (ColorFrameBuffer)
			Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer);
		if (DepthRenderBuffer)
			glDeleteTextures(1, &DepthRenderBuffer);
		if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer)
			glDeleteTextures(1, &StencilRenderBuffer);
		ColorFrameBuffer = 0;
		DepthRenderBuffer = 0;
		StencilRenderBuffer = 0;
	}*/
	Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
#endif
}
That's all :)
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

A short note first: Since you use SVN you can create diffs against the latest HEAD revisions. No need to document your changes, simply post the patch (already contains information about addition and removal of code from your side).
So what you're actually doing is replacing the one or two textures for depth and stencil by a renderbuffer. It took me quite a while to understand from your code, but now I think it's useful. Since we do not offer access to depth or stencil textures, yet, this will be better than the existing version (and probably also faster). I'll try to come up with a version which combines all three ways.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

I create patch for the latest Irrlicht SVN version. This is link:
http://chernobylstudio.com/download/nad ... GFIX.patch
Info for this patch: Replace Depth and Stencil Textures by a RenderBuffer. Patch fixed problem with FBO textures larger than screen on ATI cards.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Radeon 2xxx and 3xxx series has got support for depth textures and stencil textures, but 1xxx series and older hasn't got support this textures, so I think renderbuffer is the best solve this problem for older cards :wink:
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, I'll add it the next days. I simply did not yet find enough time to add it.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

I do test with standard Irrlicht FBO and my, fixed FBO on 13.RenderToTexture and texture size 1024x1024 (I use vi-wer patch for large DirectX textures). This is the result:

Direct3D9: 400 FPS
OpenGL (standard Irrlicht FBO): 220 FPS
OpenGL (my fixed FBO): 400 FPS

For test I use Radeon 2600 PRO with Catalyst 8.5

This results are show, than currently Irrlicht FBO need replace for faster fixed FBO structure. This is patch for Irrlicht Rev 1361:
http://nadro.byethost16.com/Patches/ATI ... GFIX.patch
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Steel Style
Posts: 168
Joined: Sun Feb 04, 2007 3:30 pm
Location: France

Post by Steel Style »

Thanks Nadro good work.
Yoran
Site Admin
Posts: 96
Joined: Fri Oct 07, 2005 8:55 am
Location: The Netherlands
Contact:

Post by Yoran »

Nadro i found a small bug, with large consequences.
void CD3D9Texture::updateDepthBuffer( )

Code: Select all

// replace old ZBuffer
       if( newZBuf )
            {
                Driver->setDepthBuffer( newZBuf );
                newZBuf->Release();
                //db->Release(); FIX by Yoran, texture->drop() fails if db is released twice! therefore resetting d3d9 device fails
            }
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yoran, that was the wrong thread...
Anyway, this patch has been commited to SVN/trunk.
Post Reply