Skip to main content
GameDev.net gamedev.net
🔒 Locked

IDirect3DSurface::LockRect efficient?

Started by rk Dec 24, 2001 at 7:17 AM 5 replies 3.6k views
Original Post
rk
rk
Given I needed something to draw my graphics with in fullscreen mode, would LockRect be an efficient solution? Somehow I think it might not but as I have no certain information, I ask for your opinion. Should you think LockRect is not the Right Way, then what is? rk
S1CA
S1CA
LockRect on the frame buffer *is not* the most efficient way to draw at all because you throw away any hardware graphics acceleration the graphics chip would have done, also you make more work for the CPU - thus you throw away any progress made in graphics technology in the last 7 or so years!.

Textured polygons are what hardware manufacturers have been concentrating on all this time - using them gets the best performance!... Even drawing polygons then calling LockRect kills the 3D performance - for example if you had a scene made of 10000 polygons, you could expect to easily get 60fps on most hardware - now say you wanted to draw a single pixel in the middle of the screen. If you locked the frame buffer to draw that pixel, its quite feasible your frame rate would drop to say 50fps. If instead you used a tiny polygon, your frame rate would stay at 60fps.

The only place you should need a Lock in a game nowadays:

1. When loading textures/buffers for the first time.
2. For procedural texture and buffer updates.

--
Simon O''''Connor
Creative Asylum Ltd
www.creative-asylum.com
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
rk
rk
quote:
Original post by S1CA
LockRect on the frame buffer *is not* the most efficient way to draw at all because you throw away any hardware graphics acceleration the graphics chip would have done, also you make more work for the CPU - thus you throw away any progress made in graphics technology in the last 7 or so years!.



Then I find it very strange that The Zen of Direct3D programming delves quite deep into rendering the graphics using LockRect. It even shows how to create a sprite class whose drawing code is through LockRect''ing.

Maybe being a Zen guru isn''t that much of a great deal after all... Makes me wonder if all the other examples are as inefficient as the ones for 2D then...


rk

a person
a person
just because you see one person who is a "guru" saying that using LockRect() is THE way to do 2d, does not mean its efficent. The facts are here, make up your own mind:

1. LockRect() stalls the pipeline if ANY previous calls would have used that surface, reducing parrallism with the cpu and card.

2. Reading from VRAM is slow, especially in the scenario or trying to do alpha blits or any compartive blits passed on destination. you should use the hardware for that.

3. LockRect() while not slow if used correctly, can like anything else when overused will slow yoru app down quite easily. just like improperly used vertex buffers. good uses include dynamic textures. (btw to update sprite frames you can just change the texture coordinates, but then the whole vertex buffer thing might become an issue)

4. the author of the book is merely calling himself a Zen Guru for marketing. i highly doubt he knows dx8 as well as you believe he does.

5. i can almost garuntee, that the actual frames drawn to the screen are done using textured quads. dx8 was not designed for directdraw style 2d.

6. LockRect() just like locking your frame buffer in dx7 is NOT the MOST effiecent way for drawing sprites. if you need alpha blend in directdraw you would use lock() but on local surfaces. in dx8, you let the video card handle unless you want the cpu to do all the work, thus mooting the point of using dx8 for 2d graphics.

please rk, enlighten use. how does mr "Zen Guru" draw 2d sprites in dx? show some psudeo code and explain the process. what type of framerates do you get by drawing directly to the backbuffer via lockrect() at 1024x768 in 32bit color?

i am not be a guru, but even i know using lockRect() for all your drawing code is just plain ignorent.
S1CA
S1CA
I haven''t seen or read that book so I can''t comment, but it does seem a tad silly and strange that a book with "Direct3D" in the title should (seemingly) tell you to totally ignore what makes D3D good and do all the work manually using the CPU.

Locking is a valid (albeit slower if you have 3d hardware) way to get effects such as alpha blending when the API doesn''t support it. A common example of this was in DirectDraw where the only way to get alpha sprites was to lock and do it with the CPU or use Direct3D.

To quote the nVidia GDC2001 "D3D Optimisation" slides:
quote:

Software TnL Principles II:
- Don’t Lock() anything that’s not a VB
- Don’t use GDI to display anything
- Especially your frame rate
- Most especially when trying to make it all go fast!
- Watch out for this from your framework



and

quote:

Summary:
- Use VBs and IBs for everything
- Never Lock anything
- FB and ZB locks cost you CPU time
- Batch like crazy
- Don’t do anything you don’t need to
- And certainly don’t do them twice…
- Batch, batch, batch



You''ll find similar advice from other IHVs

The Lock() call itself does carry a performance hit since it flushes the pipeline, but the larger problems are:

- the graphics card is sat idle while you have the surface locked (i.e. you lose all CPU<->HW parallelism benefits).

- the CPU is tied up - while it''s doing per pixel work in your surface it can''t be used for other things.

- any read operations from textures or surfaces in AGP or video memory aren''t cached so have terrible CPU performance implications (something daft like 30cycles per DWORD). Most useful things you can do with a lock involve some sort of reading...

- for a surface in video memory, the memory for that surface isn''t local - its sat on the other side of the AGP (or worse, PCI) bus - the maximum throughput to that surface is far less than from the CPU to main memory.

Manually colouring in a 256x256 area of a 32bit screen would involve a lot of writes over the slower bus (i.e. 256K), alpha blending that with what''s already on the screen would involve plenty of uncached reads. Now compare that to a D3D call to draw two textured triangles - all it has to send to the card is 4 vertices averaging about 32 bytes each. 128bytes for the CPU to transfer versus 262144bytes...


--
Simon O''''Connor
Creative Asylum Ltd
www.creative-asylum.com
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
S1CA
S1CA
Doh - "a person" beat me to it...


Simplest way to proove this kind of thing to yourself is to try both and profile them. Learning from your mistakes is an important thing to do..

--
Simon O''''Connor
Creative Asylum Ltd
www.creative-asylum.com
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
rk
rk
Regardless of being a little amazed of a person''s apparent sour mood, in the new light provided by the facts you have all presented I see that indeed LockRect is not the best way for doing things. I think I''m going to look into textured quads.

Thank you all for the replies! And a person, merry Christmas to you too.


rk

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.