Page 1 of 1

[no bug]RTT's on D3D9 without drawing something first

Posted: Fri Sep 09, 2016 3:55 pm
by CuteAlien
When using rendertarget textures with the EDT_DIRECT3D9 driver I have to draw something (anything) first with the driver. If I try to use them before having drawn anything I get just black textures as result.

Problem is reproducible in Irrlicht trunk and Irrlicht 1.8. It works correct with OpenGL.
I stepped through my test-code below while having 2 Visual Studio versions parallel open - one with working and one with failing version. But I couldn't find any place where the runtime behaviour was different aside from the failing version returning a black texture.

If anyone has a clue what could be the problem I'd be glad to hear about it.

To enable the bug set the place with "#if 1" to "#if 0".

Code: Select all

 
// TEST to debug a problem with rtt and d3d9
 
#include <irrlicht.h>
 
using namespace irr;
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
// Create a rtt, draw something into it and copy resulting image to a newly created texture
irr::video::ITexture* drawIntoTexture(irr::video::IVideoDriver * driver)
{
    irr::core::dimension2d<irr::u32> texdim(64, 64);
 
    // set rt
    irr::video::ITexture * rtTex = driver->addRenderTargetTexture(texdim, "rtTxt", irr::video::ECF_A8R8G8B8);
    driver->setRenderTarget(rtTex, irr::video::ECBF_COLOR|irr::video::ECBF_DEPTH, irr::video::SColor(0,0,0,0));
 
    // draw some X into the texture
    driver->draw2DLine( irr::core::vector2di(0,0), irr::core::vector2di(texdim.Width,texdim.Height), irr::video::SColor(255,127,127,255));
    driver->draw2DLine( irr::core::vector2di(texdim.Width,0), irr::core::vector2di(0,texdim.Height), irr::video::SColor(255,127,127,255));
 
    // reset rt
    driver->setRenderTarget((irr::video::ITexture *)nullptr, irr::video::ECBF_COLOR|irr::video::ECBF_DEPTH);
 
    // Don't use rt directly as rtt's are reset on resize
    // But that part doesn't matter - the rtt is already getting a black texture (have debugged memory directly)
    irr::video::IImage * img = driver->createImage (rtTex, irr::core::position2di(0,0), rtTex->getSize());
    driver->removeTexture(rtTex);
    irr::video::ITexture*  result = driver->addTexture("texture", img);
 
    img->drop();
 
    return result;
}
 
int main()
{
    video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9; // works with opengl
    IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, false);
    if (device == 0)
        return 1; // could not create selected driver.
 
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
 
    // add camera
    scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
    cam->setPosition(core::vector3df(-50,50,-150));
 
    // create test cube
    scene::ISceneNode* test = smgr->addCubeSceneNode(60);
    test->setPosition(core::vector3df(-10,0,-10));
    test->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting
 
#if 1   // BUG: when set to 0 the rtt no longer works
    // We have to draw something once to get rtt working on D3D9 
    driver->beginScene(true, true, irr::video::SColor(0x00FFFFFF));
    driver->draw3DLine( core::vector3df(0,0,0), core::vector3df(1,1,1));    // 2d or 3d doesn't matter
    //driver->draw2DLine( irr::core::vector2di(0,0), irr::core::vector2di(10,10), irr::video::SColor(255,127,127,255));
    driver->endScene();
#endif
 
    // set cube texture to texture created from rtt
    test->setMaterialTexture(0, drawIntoTexture(driver));
 
    // just draw the cube
    while(device->run())
    {
        driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0));
        smgr->drawAll();
        driver->endScene();
        device->sleep(10);
    }
 
    device->drop(); // drop device
    return 0;
}
 

Re: Can't use RTT's on D3D9 without drawing something first

Posted: Fri Sep 09, 2016 5:30 pm
by hendu
RTT drawing, just like any drawing, must be inside beginScene and endScene, no? That GL happens to work without is just coincidence.

Re: Can't use RTT's on D3D9 without drawing something first

Posted: Sat Sep 10, 2016 10:39 am
by CuteAlien
Hm, probably you are right. It always seemed to work without beginScene/endScene, so I thought maybe setRenderTarget would replace it as it has similar parameters to beginScene(). Have to investigate this a little bit next week. If that's the case I'll have to check if beginScene()/endScene() can be nested, otherwise some of my code might become more complicated.

Re: Can't use RTT's on D3D9 without drawing something first

Posted: Sat Sep 10, 2016 12:55 pm
by hendu
I don't think they can be nested. Any wrappers just need to document that their draw calls must also be inside that.

Re: Can't use RTT's on D3D9 without drawing something first

Posted: Sat Sep 10, 2016 1:25 pm
by CuteAlien
Yeah, but sometimes not so nice. Maybe we need a function to tell if we are currently inside beginScene/endScene.

Re: [no bug]RTT's on D3D9 without drawing something first

Posted: Tue Sep 13, 2016 9:52 am
by CuteAlien
*sigh* - guess in the end caching stuff with rtt's while loading is simply a bad idea.
So yeah - beginScene/endScene pair should never be avoided. The reason it sometimes still worked... doesn't really matter, just shouldn't be done.

Re: [no bug]RTT's on D3D9 without drawing something first

Posted: Tue Sep 13, 2016 11:20 am
by Mel
But if for any obscure reason we wanted to lock the RTT to write them directly, would that still be possible? I am aware of the performance penalty, but just out of curiosity

Re: [no bug]RTT's on D3D9 without drawing something first

Posted: Tue Sep 13, 2016 12:34 pm
by CuteAlien
Sorry, I don't know details about locking - Nadro just rewrote that part, he would know more about it...
But I think beginScene/endScene is only for drawing.

Re: [no bug]RTT's on D3D9 without drawing something first

Posted: Tue Sep 20, 2016 10:03 am
by Nadro
AFAIK CuteAlien is right, begin/end scene is just for drawing, so you can still lock/unlock RT textures.
guess in the end caching stuff with rtt's while loading is simply a bad idea.
In OpenGL we use RTT (FBO) to download texture from GPU to CPU (in OpenGL ES 2.0 it's the only possible way), so this is similar situation.

Re: [no bug]RTT's on D3D9 without drawing something first

Posted: Tue Sep 20, 2016 10:15 am
by CuteAlien
@Nadro: So the new lock() on OpenGL has to be inside beginscene/endscene?

Re: [no bug]RTT's on D3D9 without drawing something first

Posted: Wed Sep 21, 2016 10:15 am
by Nadro
No, in OpenGL we don't need anything like a begin/end scene, thats why it works in all cases.