Direct texture memory updating
Direct texture memory updating
Updating the pixel byte memory of a texture is uncomplicated with ITexture, however, there seems to be no method to mark the texture memory as changed, so any updates go unnoticed.
Under D3D9, there are calls to AddDirtyRect and UpdateTexture, i.e.
//upload mem-texture to render target on GPU
memtex->AddDirtyRect(NULL);
m_pDevice->UpdateTexture(memtex,m_pOutTexture);
Under opengl there must be other methods.
But how can Irrlich programmers perform byte ops on an ITexture and have them uploaded to the GPU without having to resort to using an intermediate ITexture and then using DrawImage, which can impact on rendering speed badly?
Is there a method I missed somewhere?
Under D3D9, there are calls to AddDirtyRect and UpdateTexture, i.e.
//upload mem-texture to render target on GPU
memtex->AddDirtyRect(NULL);
m_pDevice->UpdateTexture(memtex,m_pOutTexture);
Under opengl there must be other methods.
But how can Irrlich programmers perform byte ops on an ITexture and have them uploaded to the GPU without having to resort to using an intermediate ITexture and then using DrawImage, which can impact on rendering speed badly?
Is there a method I missed somewhere?
-
hybrid
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Direct texture memory updating
When unlocking the texture (which is required under all circumstances, so every lock has to have an unlock at some point after it), all updates are made on the GPU. Is that what you're looking for?
Re: Direct texture memory updating
I've been trying that using the following code, but the update never reaches the screen. I have to copy to an intermediate texture created with AddTexture (the target was created with AddRenderTarget), and then use the code at the end.
pBits = Buf->lock(); // Lock target ITexture
hRet = m_pDDSurfTarget->Lock( NULL, &m_ddsdIntermediateTarget, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ); // Lock sample surface
ASSERT( hRet == S_OK );
// Copy entire sample en block as source-target are now identical surface formats
void *pDst = memcpy( pBits, m_ddsdIntermediateTarget.lpSurface, uSizeBuf ); // Memcpy from surface memory to texture memory, uses "Fast" copy SSE2 at asm level
hRet = m_pDDSurfTarget->Unlock( m_ddsdIntermediateTarget.lpSurface );
Buf->unlock(); // So changes should now appear on screen but they don't...???
/// code at the end to get changes seen (duplicates a massive data transfer)
m_pDriver->setRenderTarget( Buf, false, false ); // Set render target to texture
SMaterial m; // Set material for this rendering (if not set, drawing may be related to other update's material, scaled or drawn to the screen backbuffer)
m.Lighting = 0;
m.Thickness = 1.f;
m_pDriver->setMaterial( m );
// Write frame to target texture (would be better if we could do this directly but need to mark texture as dirty, which needs d3d9 access or new method in library... todo)
m_pDriver->draw2DImage( m_pTex, irr::core::position2d<irr::s32>(0,0), irr::core::rect<irr::s32>(0, 0, dwWidth, dwHeight), 0, irr::video::SColor(255,255,255,255), false );
m_pDriver->setRenderTarget( 0, false, false ); // Return to previous render state
pBits = Buf->lock(); // Lock target ITexture
hRet = m_pDDSurfTarget->Lock( NULL, &m_ddsdIntermediateTarget, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ); // Lock sample surface
ASSERT( hRet == S_OK );
// Copy entire sample en block as source-target are now identical surface formats
void *pDst = memcpy( pBits, m_ddsdIntermediateTarget.lpSurface, uSizeBuf ); // Memcpy from surface memory to texture memory, uses "Fast" copy SSE2 at asm level
hRet = m_pDDSurfTarget->Unlock( m_ddsdIntermediateTarget.lpSurface );
Buf->unlock(); // So changes should now appear on screen but they don't...???
/// code at the end to get changes seen (duplicates a massive data transfer)
m_pDriver->setRenderTarget( Buf, false, false ); // Set render target to texture
SMaterial m; // Set material for this rendering (if not set, drawing may be related to other update's material, scaled or drawn to the screen backbuffer)
m.Lighting = 0;
m.Thickness = 1.f;
m_pDriver->setMaterial( m );
// Write frame to target texture (would be better if we could do this directly but need to mark texture as dirty, which needs d3d9 access or new method in library... todo)
m_pDriver->draw2DImage( m_pTex, irr::core::position2d<irr::s32>(0,0), irr::core::rect<irr::s32>(0, 0, dwWidth, dwHeight), 0, irr::video::SColor(255,255,255,255), false );
m_pDriver->setRenderTarget( 0, false, false ); // Return to previous render state
-
hybrid
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Direct texture memory updating
You're supposed to use Irrlicht API all over the place. Why do you bother with D3D structures? Just lock the Irrlicht texture, update the content, unlock. Works very nice.
Re: Direct texture memory updating
That is what I tried to do. It doesn't work! I posted the code above. Buf is the ptr to the ITexture created with AddRenderTexture. I Buf->lock() it, use the returned ptr to update the pixels, call Buf->unlock(), but the pixels never get updated. I checked the pixels were changed, but they never reach the screen!! I then created an intermediate ITexture using AddTexture, m_pTex. Copied the pixel data to this texture, then used draw2DImage to update Buf, withut using lock of course, and that works! So where is the problem? Is this a bug in Irrlicht?
Re: Direct texture memory updating
I just triple-checked my code, and locking, updating bytes on the ITexture of a cube surface, using the ptr returned by lock, and then unlocking does NOT cause the texture to be reloaded to the GPU.
Creating a texture with AddTexture, then performing the lock-update-byte-unlock on it, then using draw2DImage to copy to the in-use texture does update the target ITexture mapped to a cube, but its a big waste of CPU overhead to duplicate the copy process just to get around what looks like and Irrlicht bug... unless I missed something that I just can't see...
Why doesn't ths work:-
// Buf is a ITexture *
// pDDSurfTarget is a ptr to the memory surface in same ARGB format, identical byte order.
pBits = Buf->lock();
hRet = m_pDDSurfTarget->Lock( NULL, &m_ddsdIntermediateTarget, DDLOCK_WAIT, NULL );
void *pDst = memcpy( pBits, m_ddsdIntermediateTarget.lpSurface, uSizeBuf );
hRet = m_pDDSurfTarget->Unlock(0);
Buf->unlock(); // Should now update texture to GPU, but nothing happens!!
Creating a texture with AddTexture, then performing the lock-update-byte-unlock on it, then using draw2DImage to copy to the in-use texture does update the target ITexture mapped to a cube, but its a big waste of CPU overhead to duplicate the copy process just to get around what looks like and Irrlicht bug... unless I missed something that I just can't see...
Why doesn't ths work:-
// Buf is a ITexture *
// pDDSurfTarget is a ptr to the memory surface in same ARGB format, identical byte order.
pBits = Buf->lock();
hRet = m_pDDSurfTarget->Lock( NULL, &m_ddsdIntermediateTarget, DDLOCK_WAIT, NULL );
void *pDst = memcpy( pBits, m_ddsdIntermediateTarget.lpSurface, uSizeBuf );
hRet = m_pDDSurfTarget->Unlock(0);
Buf->unlock(); // Should now update texture to GPU, but nothing happens!!
-
hybrid
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Direct texture memory updating
I still don't get why you cannot use ITexture->lock()
Re: Direct texture memory updating
Hello, I do!!
Look at the code I posted, its is:-
Buf->unlock(); // Should now update texture to GPU, but nothing happens!!
// Buf is a ITexture *
It does not work on Irrlicht 1.7.2 , byte modification of ITextures created with addRenderTargetTexture:-
m_pDriver->addRenderTargetTexture( core::dimension2d<u32>( dx, dy ), (LPCTSTR)sz, ECF_A8R8G8B8 );
do not update the GPU after calling ITexture*->unlock!
Look at the code I posted, its is:-
Buf->unlock(); // Should now update texture to GPU, but nothing happens!!
// Buf is a ITexture *
It does not work on Irrlicht 1.7.2 , byte modification of ITextures created with addRenderTargetTexture:-
m_pDriver->addRenderTargetTexture( core::dimension2d<u32>( dx, dy ), (LPCTSTR)sz, ECF_A8R8G8B8 );
do not update the GPU after calling ITexture*->unlock!
Re: Direct texture memory updating
ITexture *m_pITexture = m_pDriver->addRenderTargetTexture( core::dimension2d<u32>( dx, dy ), (LPCTSTR)sz, ECF_A8R8G8B8 );
m_material.setTexture( 0, m_pITexture );
m_material.setTexture( 0, m_pITexture );
Re: Direct texture memory updating
Here's the code again:-
ITexture *m_pITexture = m_pDriver->addRenderTargetTexture( core::dimension2d<u32>( 256, 256 ), "MyTexture", ECF_A8R8G8B8 );
m_material.setTexture( 0, m_pITexture ); // Map texture to mesh
BYTE *pBits = m_pITexture->lock(); // Ptr to pixel memory
void *pDst = memcpy( pBits, m_ddsdIntermediateTarget.lpSurface, uSizeBuf ); // Memcpy from surface memory to texture memory, both in ARGB format
m_pITexture->unlock();
Please, why doesn't this work, when using draw2DImage function to Itexture works!!!
Its a bug?
ITexture *m_pITexture = m_pDriver->addRenderTargetTexture( core::dimension2d<u32>( 256, 256 ), "MyTexture", ECF_A8R8G8B8 );
m_material.setTexture( 0, m_pITexture ); // Map texture to mesh
BYTE *pBits = m_pITexture->lock(); // Ptr to pixel memory
void *pDst = memcpy( pBits, m_ddsdIntermediateTarget.lpSurface, uSizeBuf ); // Memcpy from surface memory to texture memory, both in ARGB format
m_pITexture->unlock();
Please, why doesn't this work, when using draw2DImage function to Itexture works!!!
Its a bug?
Re: Direct texture memory updating
and last but not least...
to conenct the material and its texture to the scenenode:-
m_pAnimatedMeshSceneNode->getMaterial(0) = m_material;
Drawing to the texture assigned works perfectly, if I use Irrlicht's drawing function, I just can't update the texture's surface pixels directly.., making updates slow
to conenct the material and its texture to the scenenode:-
m_pAnimatedMeshSceneNode->getMaterial(0) = m_material;
Drawing to the texture assigned works perfectly, if I use Irrlicht's drawing function, I just can't update the texture's surface pixels directly.., making updates slow
-
hybrid
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Direct texture memory updating
Ok, sorry. I always read the memcpy the wrong way - I thought you want to update your pDDSurfTarget. But I must also admit that Buf is not a typical name for a texture...
Anyway, your code should work as expected. Even with the changes for read only texture access both normal and RT textures will lock the main miplevel when calling lock() and giving access to the raw pixel data in return. And upon unlock, the UnlockRect call will update the whole texture region on the GPU. I didn't cross-check right now, but not too long ago all our text cases did reproduce the correct behavior when locking and unlocking textures. I have to see whether RTTs are also manipulated manually. But there's no big deal to use an ordinary texture instead here and update it from time to time. Locking and unlocking will definitely work there, you can even lock single mip levels and update those manually.
Anyway, your code should work as expected. Even with the changes for read only texture access both normal and RT textures will lock the main miplevel when calling lock() and giving access to the raw pixel data in return. And upon unlock, the UnlockRect call will update the whole texture region on the GPU. I didn't cross-check right now, but not too long ago all our text cases did reproduce the correct behavior when locking and unlocking textures. I have to see whether RTTs are also manipulated manually. But there's no big deal to use an ordinary texture instead here and update it from time to time. Locking and unlocking will definitely work there, you can even lock single mip levels and update those manually.