Access to back buffer
You've changed the layout of the virtual table by adding another virutal function to the interface. This makes the new dll binary incompatible with the old dll.
The solution is to rebuild Irrlicht (the lib and the dll) and then link your application to the new lib. When you run your program, you need to be certain that the new Irrlicht.dll is the one that is found. You can be sure this happens by putting the right Irrlicht.dll into the same directory as your executable.
Travis
The solution is to rebuild Irrlicht (the lib and the dll) and then link your application to the new lib. When you run your program, you need to be certain that the new Irrlicht.dll is the one that is found. You can be sure this happens by putting the right Irrlicht.dll into the same directory as your executable.
Travis
Ok creating a usable IDirect3D9Texture with MSAA is indeed harder than I thought, it seems your method of copying from a multi sampled surface is the best solution.
I'm not convinced about copying from the back buffer though, I'll try to find a cleaner solution, here's what I have in mind:
- If the render target has multisampling support, create a multi sampled IDirect3D9Surface (Locking will be disabled in this case also.) AND a IDirect3D9Texture with RTT usage.
- When the render target is set, use the multi sampled surface.
- When another render target is set after that, perform a StretchRect copy straight to the texture surface.
This should work fine in most cases, with the slight memory overhead of having 2 copies, but it certainly beats rendering to texture twice the size of the original, this one only uses twice as much memory compared to quadruple.
Ok who am I kidding I think I'll just use your solution and call it a day.
I'll provide a patch for D3D and OGL implementations soon.
I'm not convinced about copying from the back buffer though, I'll try to find a cleaner solution, here's what I have in mind:
- If the render target has multisampling support, create a multi sampled IDirect3D9Surface (Locking will be disabled in this case also.) AND a IDirect3D9Texture with RTT usage.
- When the render target is set, use the multi sampled surface.
- When another render target is set after that, perform a StretchRect copy straight to the texture surface.
This should work fine in most cases, with the slight memory overhead of having 2 copies, but it certainly beats rendering to texture twice the size of the original, this one only uses twice as much memory compared to quadruple.
Ok who am I kidding I think I'll just use your solution and call it a day.
I'll provide a patch for D3D and OGL implementations soon.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Thank you vitek for your suggestion but of course I ensured both lib and dll are properly rebuilt. And yes this problem is due to change of virtual addresses table layout.
My question is "Why this $#%&*! table desyncs since all binaries and headers are OK ?"
To make sure, I prepared a clean environment on another machine, I deleted all the binaries of irrlicht engine, then rebuilt it, then rebuilt my libraries, then rebuilt my application. In this case everything built fine (no dll mistake, no debug/release mistake, etc...)
Moreover everything is versionned using SVN so I can see through CRC check that the binaries were properly modified (rebuilt).
Still the problem happens...
BlindSide your idea is good, I suggested to directly use the back buffer because if you create another AA render target for AA render purpose, in this case the back buffer originally created when device is created is kind of wasted. Moreover copying directly from the back buffer is nothing dangerous since it's just a normal surface.
Anyway I think your idea is better because like this the user can switch AA render / non-AA render on the fly if needed for particular cases.
My question is "Why this $#%&*! table desyncs since all binaries and headers are OK ?"
To make sure, I prepared a clean environment on another machine, I deleted all the binaries of irrlicht engine, then rebuilt it, then rebuilt my libraries, then rebuilt my application. In this case everything built fine (no dll mistake, no debug/release mistake, etc...)
Moreover everything is versionned using SVN so I can see through CRC check that the binaries were properly modified (rebuilt).
Still the problem happens...
BlindSide your idea is good, I suggested to directly use the back buffer because if you create another AA render target for AA render purpose, in this case the back buffer originally created when device is created is kind of wasted. Moreover copying directly from the back buffer is nothing dangerous since it's just a normal surface.
Anyway I think your idea is better because like this the user can switch AA render / non-AA render on the fly if needed for particular cases.
I had an attempt at making an OpenGL variant so this could get included into Irrlicht, but I'm not having much luck. I had to add the BlitFramebuffer extension to COpenGLExtensionHandler.
There seem to be a million and one ways of doing a straight copy from the backbuffer to an FBO but this is probably the best way for modern cards, albeit some ATI cards don't support it. Maybe hybrid or someone could have a look over this:
Here's a link to the blitextensions patch, with adds the extGlBlitFramebuffer function to COpenGLExtensionHandler: http://irrlichtirc.g0dsoft.com/BlindSid ... sion.patch
There seem to be a million and one ways of doing a straight copy from the backbuffer to an FBO but this is probably the best way for modern cards, albeit some ATI cards don't support it. Maybe hybrid or someone could have a look over this:
Code: Select all
bool COpenGLDriver::copyBackBufferTo(ITexture* dest)
{
if (dest->getDriverType() != EDT_OPENGL)
return false;
GLint oldFBO = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO);
COpenGLTexture* tex = (COpenGLTexture*)dest;
core::dimension2du bSize = this->getScreenSize();
this->extGlBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
this->extGlBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->getOpenGLTextureName());
glReadBuffer(GL_BACK);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
this->extGlBlitFramebuffer( 0, 0, bSize.Width, bSize.Height,
0, 0, bSize.Width, bSize.Height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
this->extGlBindFramebuffer(GL_FRAMEBUFFER, oldFBO);
return true;
}
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Sorry BlindSide I don't know that much about OpenGL so I'm afraid I can't be a help.
However something I added to my implementation that I forgot before and I would suggest you to add is a simple parameter check at begining of the function, such as :
If you encouter troubles with the DirectX9 implementation, just post here and I'll try to help.
However something I added to my implementation that I forgot before and I would suggest you to add is a simple parameter check at begining of the function, such as :
Code: Select all
bool COpenGLDriver::copyBackBufferTo(ITexture* dest)
{
if (dest == NULL || dest->getDriverType() != EDT_OPENGL)
return false;
[...]
arf, I encouter a new problem since I patched irrlicht by adding that copyBackBufferTo virtual method to IVideoDriver and CD3D9Driver.
I'm working on Windows XP with irrlicht 1.5 and DirectX9 implementation only.
Now when I minimize the application, no problem, but when I restore the window from the task bar, the application fails in the method CD3D9Driver::reset, and it's when trying to retrieve the surface description from the default surface :
So I tried this :
Any of the both last call fail with something like segfault reading address 0xC0000005.
The address of the surface retrieved (DepthBuffers[0]->Surface) is correct and match with the one originally created during device creation.
So tha surface seems to be corrupted, BlindSide do you have the same problem with your OpenGL implementation ? did you perform some tests with the DirectX9 implementation ?
PS: According to irrlicht 1.5 changelog:
- Lost devices (as found with D3D) are properly handled now. So the screen can be resized or minimized without crashing the app.
I'm working on Windows XP with irrlicht 1.5 and DirectX9 implementation only.
Now when I minimize the application, no problem, but when I restore the window from the task bar, the application fails in the method CD3D9Driver::reset, and it's when trying to retrieve the surface description from the default surface :
Code: Select all
// restore screen depthbuffer
pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface));
D3DSURFACE_DESC desc;
DepthBuffers[0]->Surface->GetDesc(&desc); // <== FAIL HERE
Code: Select all
// restore screen depthbuffer
pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface));
D3DSURFACE_DESC desc;
IDirect3DSurface9* surface = DepthBuffers[0]->Surface;
IDirect3DDevice9* tmp_device;
surface->GetDevice(&tmp_device); // <== FAIL HERE
surface->GetDesc(&desc); // <== FAIL HERE
The address of the surface retrieved (DepthBuffers[0]->Surface) is correct and match with the one originally created during device creation.
So tha surface seems to be corrupted, BlindSide do you have the same problem with your OpenGL implementation ? did you perform some tests with the DirectX9 implementation ?
PS: According to irrlicht 1.5 changelog:
- Lost devices (as found with D3D) are properly handled now. So the screen can be resized or minimized without crashing the app.
Actually I add my render target this way in my post-effect class constructor :
then delete it at the end of my application, in my post-process class destructor :
though in my case the destructor is not called because application fails (by minimizing the window and restoring it) before it ends.
The surface which fails in the reset method is not my render target but is the default surface, which is officially called the "implicit swapchain".
In my application I create several other render targets and until then I never got any problem when minimizing the application window.
Code: Select all
m_RenderTexture = driver->addRenderTargetTexture(dim, "PPINTERMEDIARYRTT");
Code: Select all
driver->removeTexture(m_RenderTexture);
The surface which fails in the reset method is not my render target but is the default surface, which is officially called the "implicit swapchain".
In my application I create several other render targets and until then I never got any problem when minimizing the application window.
OK today application fails at a different location... I reverted back my application code to previous version and it does not crash when minimizing, even with irrlicht modification I made.
In fact application crahes when minimizing if and only if I call driver->copyBackBufferTo(...) method.
I performed a test with exactly same code as when it crashes but commented out the call to copyBackBufferTo method and it works fine, well the main render displays graphic card memory garbage instead of proper render but over that garbage the UI and menus are properly rendered, which means the default surface is fine, and the application does not crash when minimizing.
So only that call to copyBackBufferTo makes the application to crash.
Any idea ? I don't use any thread in my application so is there a chance that irrlicht resets the device while in the middle of [DirectXDeviceInstance]->StretchRect (in the copyBackBufferTo method) ?
(I don't know about irrlicht actions perform timing)
Is there a way for me to protect the code from this problem ?
Thank you very much in advance for you precious help.
In fact application crahes when minimizing if and only if I call driver->copyBackBufferTo(...) method.
I performed a test with exactly same code as when it crashes but commented out the call to copyBackBufferTo method and it works fine, well the main render displays graphic card memory garbage instead of proper render but over that garbage the UI and menus are properly rendered, which means the default surface is fine, and the application does not crash when minimizing.
So only that call to copyBackBufferTo makes the application to crash.
Any idea ? I don't use any thread in my application so is there a chance that irrlicht resets the device while in the middle of [DirectXDeviceInstance]->StretchRect (in the copyBackBufferTo method) ?
(I don't know about irrlicht actions perform timing)
Is there a way for me to protect the code from this problem ?
Thank you very much in advance for you precious help.
Thank you very much everybody, I could fix the bug and now it works fine
So I post the DirectX 9 implementation again hoping it can help somebody else after me.
Please review and adjust accordingly to match irrlicht design, and then it could be good that admin/modo tag the topic as [resolved] or something.
Again, thank you very much to everybody for your help.
So I post the DirectX 9 implementation again hoping it can help somebody else after me.
Code: Select all
bool CD3D9Driver::copyBackBufferTo(ITexture* dest)
{
if (dest == NULL || 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)
{
// backBuffer->Release(); // <- not sure if this have to be done...
return (false);
}
backBuffer->Release();
return (true);
}
Again, thank you very much to everybody for your help.
I added this to CD3D9Driver and recompiled Irrlicht. However, it's giving me a linker error (the usual "unresolved external symbol"). Do I have to expose this function somehow?
Edit: After exposing this in IVideoDriver (which I'm aware is a bad practice since not all of the video drivers have this function, but I'm only using DX9 anyways), I got the function to return work.
Is there a better way to allow the linker access to the function?
Edit: After exposing this in IVideoDriver (which I'm aware is a bad practice since not all of the video drivers have this function, but I'm only using DX9 anyways), I got the function to return work.
Is there a better way to allow the linker access to the function?