LPDIRECT3DTEXTURE9 pd3dTex; //Holds the texture, previously initialized
D3DLOCKED_RECT d3dlr;
HRESULT hr = pd3dTex->LockRect(0, &d3dlr, NULL, 0);
COLOR *colors = (COLOR *)d3dlr.pBits;
//alter colors
pd3dTex->UnlockRect(0);
Avoid locking DirectX texture?
Hi,
Is there a way to get access to the color bits part of a LPDIRECT3DTEXTURE9 and alter them without the need to lock and unlock the texture?
Currently I'm doing this:
I'd like to avoid the locking part and just constantly have access to the pBits in memory (while still being able to draw the texture in the graphics device)
You can't directly modify a texture's contents without locking it, no way around that. If your modifications are something you can do in a pixel shader, then you might want to consider using render targets. Each time you need to make modifications you could sample the source texture and render results to another. Then next time you just switch the textures.
Quote:Original post by CarlMLNope, there's no way. If there was, then the GPU would have to lock the texture every frame, and you'd get a horrific frame rate. You need to lock resources so that the GPU and CPU don't fight over it.
Hi,
Is there a way to get access to the color bits part of a LPDIRECT3DTEXTURE9 and alter them without the need to lock and unlock the texture?
Currently I'm doing this:
*** Source Snippet Removed ***
I'd like to avoid the locking part and just constantly have access to the pBits in memory (while still being able to draw the texture in the graphics device)
So long as you create the texture as D3DUSAGE_DYNAMIC and use the appropriate locking flags, performance shouldn't be much of a problem though so long as you lock, fill and unlock no more than once per frame.
See The Documentation for more details.
Ok thanks for the info, that is too bad. Currently I'm doing the lock/unlock twice per code cycle. Once to alter the pixels, then the texture is rendered and then I lock/unlock again to reset the texture. The locking part for a 4096x4096 texture takes around 50 milliseconds in my tests so doing it twice takes 0.1 seconds, which is quite a lot for something that is supposed to be interactive. I think I will need to redesign some parts so I can skip the second lock/unlock.
Quote:Original post by CarlML1. Never read from a resource, keep a copy of the data in system memory and read from that instead.
Ok thanks for the info, that is too bad. Currently I'm doing the lock/unlock twice per code cycle. Once to alter the pixels, then the texture is rendered and then I lock/unlock again to reset the texture. The locking part for a 4096x4096 texture takes around 50 milliseconds in my tests so doing it twice takes 0.1 seconds, which is quite a lot for something that is supposed to be interactive. I think I will need to redesign some parts so I can skip the second lock/unlock.
2. Never ever lock a texture more than once per frame - you can only render once per frame, so why do you need to lock more than once?
3. Always use dynamic textures if you're locking them every frame. If you don't, you'll be severely hurting the GPU/driver.
4. If you can avoid locking the entire texture, do so. If you're only updating a few pixels in the texture, record the min and max X and Y coordinates, and only lock the rectangle between min and max. That way there's less data to transfer on Unlock()
5. Do you really need a 4096x4096 texture? A lot of cards don't support that (2 of the 3 cards I have don't).
In addition to Steve's comments:
1. If you must write to the pixels to start, consider two options:
a. A single 'master' texture that you write once at start and then render from texture->texture each frame with no locking.
b. If you must have dynamic/different pixels each frame consider a ring buffer where you have a 4-5 staging textures of the same size and whilst you render one you can lock the others
(1a) requires a render-target which can restrict your texture formats
(1b) requires much more memory and some tolerance to latency
In the case of (1a) you can use IDirect3DDevice9::Clear() for lightning fast reset operations (provided you're not doing HDRI).
When considering algorithmic alternatives you need to realise two things about performance. Firstly, the latency between physical hardware over the PCI-E is an obvious and trivial consideration; secondly, by having two processing units depend on the same resource you risk forcing synchronisation. The latter is less obvious but often the main problem - GPU rendering tends to be at its peak when it can operate independently of the CPU, so the more 'involved' the CPU and main app is with resources (and general pipeline control) the less room the GPU has to just run away and do its own thing.
hth
Jack
1. If you must write to the pixels to start, consider two options:
a. A single 'master' texture that you write once at start and then render from texture->texture each frame with no locking.
b. If you must have dynamic/different pixels each frame consider a ring buffer where you have a 4-5 staging textures of the same size and whilst you render one you can lock the others
(1a) requires a render-target which can restrict your texture formats
(1b) requires much more memory and some tolerance to latency
In the case of (1a) you can use IDirect3DDevice9::Clear() for lightning fast reset operations (provided you're not doing HDRI).
When considering algorithmic alternatives you need to realise two things about performance. Firstly, the latency between physical hardware over the PCI-E is an obvious and trivial consideration; secondly, by having two processing units depend on the same resource you risk forcing synchronisation. The latter is less obvious but often the main problem - GPU rendering tends to be at its peak when it can operate independently of the CPU, so the more 'involved' the CPU and main app is with resources (and general pipeline control) the less room the GPU has to just run away and do its own thing.
Quote:. Do you really need a 4096x4096 texture? A lot of cards don't support that (2 of the 3 cards I have don't)True, but just think how pathetic they'll seem with the D3D11 generation requiring 16,384x16,384 textures at a minimum [razz]
hth
Jack
Quote:Original post by jollyjeffersI still want my 65536x? textures for 16-bit lookups [sad]Quote:. Do you really need a 4096x4096 texture? A lot of cards don't support that (2 of the 3 cards I have don't)True, but just think how pathetic they'll seem with the D3D11 generation requiring 16,384x16,384 textures at a minimum [razz]
Thanks for the feedback.
I was able to redesign away the need to have the second lock/unlock so that is good.
I'm testing with a 4096x4096 texture since that is in the upper range of what might be used. The texture size is choosen by the user of the program (a painting application, as a plugin for a 3d program). Anyway things are working ok now, I can live with one lock/unlock.:)
I was able to redesign away the need to have the second lock/unlock so that is good.
I'm testing with a 4096x4096 texture since that is in the upper range of what might be used. The texture size is choosen by the user of the program (a painting application, as a plugin for a 3d program). Anyway things are working ok now, I can live with one lock/unlock.:)
A question though... what happens if you lock the texture, alter pixel data and then display the texture without unlocking? Then unlock after displaying. In my test there doesn't seem to be any issue with doing that and the texture is displayed ok. Could it lead to issues?
Quote:Original post by CarlMLRendering will probably fail, or may display corrupt. If it works on your card, then that's just luck. If the texture is locked, it means that the CPU is accessing it. Because the GPU can be up to 2.5 frames behind the CPU, the GPU might not read the texture at the time you render, but might try to read it at some other point, after you've modified the texture again, or even in the middle of a memcpy() operation.
A question though... what happens if you lock the texture, alter pixel data and then display the texture without unlocking? Then unlock after displaying. In my test there doesn't seem to be any issue with doing that and the texture is displayed ok. Could it lead to issues?
The Debug Runtimes will probably shout at you for doing that, and I suppose it's technically possible to crash the video card driver and bring down the whole system in an absolute worst case scenario.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement