Access to back buffer

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Access to back buffer

Post by saigo »

Hello,

I'm actually using irrlicht 1.5 and I need to access the back buffer in read-only, impossible to find how to do it ?

Could someone help about it please ?
Thank you very much
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Render to texture, lock the texture.
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

OK so in this case, how to create a ITexture instance having the underlying surface with MULTISAMPLE property set to something different than "no multisampling" ?

Actually I need to apply a post-effect (post-processing) on a render, but I need this render to be antialiased. I have a bloom (glow) effect, but when I create the IrrlichtDevice using createDeviceEx, no problem for my effect if the AntiAlias member of the SIrrlichtCreationParameters is set to false, but if I set to true, the application behaves like if there is no depth buffer anymore.

Code: Select all

SIrrlichtCreationParameters param;

...
param.AntiAlias = false; // <- if set to true, depth buffer get broken
...

IrrlichtDevice* device = createDeviceEx(param);
IVideoDriver* driver = device->getVideoDriver();
...
Basically the way to proceed to do this :

1) create device with multisampling
2) render to default back buffer / depth buffer (multisampled)
3) copy only default back buffer to a non-multisampling surface
4) use the non-multisampling surface as input texture of pixel shader
(a multisampling render target can't be mapped as a texture)

It seems when I create arender target with irrlicht, I have no choice but to create a normal render target and can't decide the if I want or not an attached depth buffer neither if it is multisampled or not...
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The rendertexture is not multisampled. There's no way to create a multisampled RTT, yet. If you need to render multisampled you have to make a screenshot of your app (which grabs the backbuffer) and create a texture from it.
For better multisampling control you should switch to SVN/trunk version of Irrlicht where you can define the multisampling level (instead of just yes/no) and you can disable multisampling per node. Moreover, depth buffer handling was improved.
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

Thank you for your proposition but unfortunatly I'm helping a professional project and the version of all libraries and tools is fixed. We must use Irrlicht 1.5, so I'll just patch irrlicht engine locally and add what I need.

Performing a screenshot could be fine, I don't need to tweak the parameters, just keeping the default one is fine, however I wonder about performance, do you think I can perform it at 60 fps with post-effects and high polygons scene render ?

Thank you very much.

PS : If it can be helpful, I can provide my patch once it's done though I unfortunatly have no time for all implementations but just DirectX 9 driver patch. Just tell me.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The screenshot feature is not really that expensive. However, getting the framebuffer, making a texture from it, uploading again and doing the post-processing might be rather limiting. Maybe you should check if you can accomplish your feature in one or two shader passes (e.g. by doing the multisampling in the shader instead of relying on the FSAA buffer). Maybe Blindside or some other shader guru can say a word about this.
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

Thank you for your answer.

Unfortunatly the screenshot is really too slow for my need, even with a small resolution on a fast PC. I modified irrlicht engine to add a fucntion which copies the content of the back buffer to a ITexture (implementation available only fro DX9) and others have a default implementation.

Hereafter is what I did :

CD3D9Driver.h

Code: Select all

virtual bool copyBackBufferTo(ITexture* dest);
CD3D9Driver.cpp

Code: Select all

bool CD3D9Driver::copyBackBufferTo(ITexture* dest)
{
	// see implementation at end of this post
}
IVideoDriver.h

Code: Select all

virtual bool copyBackBufferTo(ITexture* dest) { return (false); }
With that modification, irrlicht builds fine, my application builds fine too but when I run the application, it fails when calling [driver]->getExposedVideoData().

It looks like if I have a modified/rebuild lib with original dll or something like addresses inconsistency, but I checked and seems not lib/dll/header problem...

Could you please tell me what I did wrong ?
Thank you very much for your help.

Code: Select all

//----------------------------------------------------
// implementation of the copyBackBufferTo function
//----------------------------------------------------
bool CD3D9Driver::copyBackBufferTo(ITexture* dest)
{
	if (dest->getDriverType() != EDT_DIRECT3D9)
		return (false);

	CD3D9Texture* tex = (CD3D9Texture*)dest;
	IDirect3DSurface9* destSurface = tex->getRenderTargetSurface();
	if (destSurface == NULL)
		return (false);

	IDirect3DSurface9* backBuffer;
	if (pID3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer) != D3D_OK)
		return (false);

	if (pID3DDevice->StretchRect(backBuffer, NULL, destSurface, NULL, D3DTEXF_LINEAR) != D3D_OK)
		return (false);

	return (true);
}
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

Just to make sure there is no confusion on the problem I encounter, even if I let just the virtual method in the IVideoDriver.h (with default implementation returning false) and remove the other modifications (DirectX9 implementation) still I encounter the same problem.

Is there a kind of specific other lib or module to rebuild afterward, or is there some kind of specific action to perform to ensure library consistency ?

If I remove the modification to the IVideoDriver class, no problem everything build and run fine but just can't perform post-processing to antialiased buffer.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

I have been thinking about solving this issue too. At the moment, when I want to anti-aliase an RTT I just do FSAA manually by rendering twice the screen size and downsampling. Performance is fine on most machines as long as the rest of the application is efficient enough, however, I would like to have a better solution like the one you suggest.

Rather than messing around with the screenshot feature, if you're going to modify Irrlicht anyway then you might as well look into enabling MSAA for RTT, which really is a much cleaner (And probably easier to accomplish, in the long run) method. I am going to look into this myself and report back if I accomplish anything.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Direct copy of textures and RTTs is also on my TODO list. Does this code accomplish this task purely on the GPU, though?
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

well I think this code is accomplished purely on the GPU without moving the pixel data from/to GPU-mem/Sys-mem because actually that's the way I do in my DirectX applications (render to AA RT, copy to non-AA RT, apply effect passes using non-AA RT as texture) and it does it at 4000+ (four thousands) FPS on a very basic scene and a standard PC with immediate back buffer swap.

About my previous question (runtime address error) do you have any idea hybrid ?

Thanks a lot for any help.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You probably just have to recompile from scratch, old class layuts will immediately lead to crashes.
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

What do you mean by "recompile from scratch" ? If you just mean "rebuild" the irrlicht solution, I did already but still there is problem.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You must recompile the library and your app. Besides that there's almost no way to make this thing fail, unless your implementation of the method fails. But your debugger would show this problem.
saigo
Posts: 25
Joined: Tue Apr 14, 2009 6:48 am
Contact:

Post by saigo »

OK I'm sorry for misexplaining my problem, I explain again.

I modified irrlicht engine, for testing and to ensure there is no relationship with my DirectX implementation, I just added a virtual method with a default implementation to the IVideoDriver class and didn't add my DirectX implementation.

So the only difference between the official version (1.5) and mine is that there is this in the IVideoDriver.h file :

Code: Select all

virtual bool copyBackBufferTo(ITexture* dest)
{
    return (false);
}
That's it. After I rebuilt (full rebuild) the irrlicht library, I rebuilt all other libraries I have which uses irrlicht, then I rebuilt my application.

Then in my application, at the very first use of the IVideoDriver instance, the application fails, almost any method I call from the IVideoDriver instance, the application fails.

Code: Select all

int APIENTRY _tWinMain( [...] )
{
    [...]
    IrrlichtDevice* pDevice = NULL;

    SIrrlichtCreationParameters param;
    param.DriverType = EDT_DIRECT3D9;
    param.[...]

    pDevice = createDeviceEx(param);
    if (pDevice == 0)
        return false;

    pDevice->setResizeAble(false);

    [...]

    IVideoDriver* driver = pDevice->getVideoDriver();
    ISceneManager* smgr = pDevice->getSceneManager();

    // until here everything is fine, all instances are properly set (not NULL)

    // any of the following calls (dereferencing a member from IVideoDriver instance) cause the application to fail
    driver->checkDriverReset();
    driver->getFPS();
    driver->getName();
    driver->getScreenSize();
The address of 'driver' variable (typed IVideoDriver*) is not NULL and its address seems to be correct (I mean not like 0x1, or any other strange non-null value).

Here are the following different errors with different members accessed:

driver->getExposedVideoData()
Access violation (segmentation fault for the Linuxians) when trying to read address 0x0000000C.

driver->checkDriverReset()
when calling this function, the application enter the function setTransform of the CD3D9Driver and fails at the first pID3DDevice->SetTransform (in the ETS_VIEW case of the switch) with segfault at address 0x0BB2F9F4.

driver->getFPS()
Run-time Check Failure #0 - The value of ESP was not properly saved across a function call. [...]

driver->getName()
Same as driver->getFPS()

driver->getScreenSize()
Pass successfully and return the proper dimensions.

driver->copyBackBufferTo(NULL)
Pass successfully but returns true though the only implementation always returns false.

This clearly indicates address shiftings, like if I were using a library with the copyBackBufferTo function and a header with no copyBackBufferTo prototype, that would result in other methods not at the proper location in the library, because of a wrong description of the header file compared to the library addresses table.

Any help would be very appreciated.
Thanks a lot.
Post Reply