This topic is now archived and is closed to further replies.

Arek the Absolute

If locking a DDraw Surface is so slow...

Recommended Posts

How would one go about reading / writing the contents of a surface without locking it? It must be possible, as the Blt function doesn''t seem to lock any surfaces, but I''m afraid that''s probably much dirtier work than I''m capable of at the moment... Do any of you know of a way around locking?

Share this post

Link to post
Share on other sites
You could probably lock it once, and keep using that pointer over and over - but it''s not a safe thing to do.

If you lock buffer, be sure to use a triple buffer, and you should be fine. The performance issue comes into play if the buffer is locked, and Dx decides it''s time to flip.

Magmai Kai Holmlor
- Not For Rent

Share this post

Link to post
Share on other sites
The performance hit of locking a surface comes from having to copy the block of vram to system memory so it can be modified by your program. When the surface is unlocked the block of system memory is copied back to the video card, and the memory can then be reused, which invalidates the surface pointer.

The benefit of that is faster drawing of the surface, a very fast video->video copy, which is what Blt does if both surfaces are in vram.

Generally, if you create a surface in system memory you can keep reusing the same surface pointer, although in theory DirectX is free to move the data wherever it wants. The penalty for non-vram surfaces is slower draw speed, but if you''re locking a particular surface every frame (e.g. alpha blending) then it''s usually faster to keep it in system memory.

Share this post

Link to post
Share on other sites
Your best bet for handling this without fear of losing the VRAM pointer is to do one lock/unlock each frame, if needed. For example, you might structure your code something like this:

do background blits
lock surface
draw alpha blended sprites/lines/circles/etc...
unlock surface
do foreground blits

Of course, this is a general case. There may be instances where
you need to lock two or three times based on z-order. The idea is to keep locks down to a minimum.


Share this post

Link to post
Share on other sites
I would have thought that the most efficient way to access data in vram would be to copy it out and back in a chunk, otherwise you''d have to read/write pixels across the AGP bus, which is slower than main memory, and is also slower to read back than write.

Never mind the issues of mapping vram into the programs address space...

I could of course be utterly wrong, if anyone knows better please feel free

Share this post

Link to post
Share on other sites
I was under the impression that using Blt implicitly locks the surface. Unless I''m mistaken, you can''t access memory in a surface unless you lock it, and Blt does this automatically. Locking a surface has little overhead; it''s the grabbing of pixels from video memory that slows your system to a crawl, like Ruval said. I''ve tested this myself with a homemade alpha blending algorithm.

Keep your stuff in system memory if you want to manipulate your image data directly. Slower performance is the price you pay for having that much control over your graphics. And if you have a chance to use Visual Basic, check out the function GetLockedArray, which gives you read-write memory access as though it''s an array of raw pixel data.

Share this post

Link to post
Share on other sites
I thought some real numbers might clear things up, by measuring the lock/unlock overhead in cycles.

//This is the code I timed

if( dds->Lock(0, &ddsd, DDLOCK_SURFACEMEMORYPTR, 0) )
goto dderror;
if( dds->Unlock(ddsd.lpSurface) )
goto dderror;

The call overhead for lock/unlock is 150 cycles the rest is all taken up by directx.


For reference here is some code that runs in about the same amount of time.

800 cycles, for(int i=400; i; i--);
2200 cycles, for(int i=1100; i; i--);

So what does it all mean:

2. Only lock the surface once per frame
3. Lock only if you have to
4. Don't worry be happy, lock/unlock is pretty cheap

Edited by - burp on November 10, 2001 1:07:03 PM

Share this post

Link to post
Share on other sites
Oky.... guess i''ve to poke my nose into this.

I''ve found a way to skip that pesky lock/unlock.

In windowed mode.... itz as simple as anything cuz all u have to do is lock the backbuffer once while initializing DirectX and keep the pointer in some global varaible which may read like (g_pBackBufferPointer).

In fullscreen mode... things are a lil tricky. In FullScreen the surfaces are flipped, the address pointer of the backbuffer and frontbuffer are swapped rather than blitting ( Which is done by DirectX itself). So what i do is, I lock both frontbuffer and backbuffer once while DirectX loads and keep the pointer as global variables. Then whenever the surfaces are flipped , I swap the global variables as well. for example:

VOID * g_pBackBufferPointer;
VOID * g_pFrontBufferPointer;

HRESULT Present()

hr = g_pDDFrontBuffer->Flip(NULL,DDFLIP_WAIT);
if(FAILED(hr)) return hr;
VOID *pTempPointer;
pTempPointer = g_pBackBufferPointer;
g_pBackBufferPointer = g_pFrontBufferPointer;
g_pFrontBufferPointer = pTempPointer;


This makes your g_pBackBufferPointer always pointing towards the CURRENT BACKBUFFER !!! Hence you dont have to lock your
surfaces everytime you want to write someting on it . Simple huh ..
And tell you what.... it really works .

Share this post

Link to post
Share on other sites
Good idea, reminds me of the good old days, when programers were in total control of the graphics hardware.

Accessing video memory (read,write) is still slower than system memory, I say if you have to draw directly on the surface, use system memory.

One danger with that method would be if you lost the surface before drawing to it.

msdn quote: "Surfaces can be lost because the display mode was changed or because another application received exclusive access to the display card and freed all of the surface memory currently allocated on the card."

Share this post

Link to post
Share on other sites