BannerLeft BannerLeft

 

D3D Resources

When creating and manipulating resources Direct3D provides a number of flags that you can set to indicate how you intend to use the resource. By telling Direct3D this it can work with the video card driver and place resources in the best place for optimised rendering. There are three main sets of flags described on this page:

  • Memory pool - which memory pool to place a resource in
  • Usage - how you intend to use the resource
  • Lock flags - how you intend to work with the data when you lock it

Memory Pool

When creating vertex buffers, index buffers, textures etc. Direct3D requires you indicate a memory class into which to place the new resource. This is known as a pool and Direct3D defines the following:

  1. D3DPOOL_DEFAULT
  2. D3DPOOL_MANAGED
  3. D3DPOOL_SYSTEMMEM
  4. D3DPOOL_SCRATCH

Each of these is described below:

1. D3DPOOL_DEFAULT

Places the resource in the best place for speed given the usage hints you provide at creation. Normally this will place the resource in video memory or the fast AGP memory. If the resource is a texture it cannot be locked unless it is marked as a dynamic texture. Other resources like back buffers, render targets, vertex buffers and index buffers can be locked but there will be a performance penalty. If the Direct3D device is lost (due to mode change etc.) then resources declared as default must be released (prior to a reset) and recreated when the device is gained again. Make sure you always indicate that this resource is write only as well (see write only usage).

Note: when a default resource is created managed resources may be removed from video card memory to allow room for the default resource. For this reason it is best to always allocated default resources before managed ones or call EvictManagedResources before allocating non managed resources. Try never to create any non managed resources after creating managed ones e.g. create them at game start or level load but not during game play. If you have to create them then call EvictManagedResources first but be prepared for a speed hit.

2. D3DPOOL_MANAGED

This is the preferred memory pool. Direct3D maintains a system copy of the resource (in system RAM) and makes a copy into video ram or AGP memory as needed. One advantage of this is that these resources do not need to be freed and recreated when the device is lost. Another advantage is that all resources created in managed memory can be locked. Direct 3D will lock the system memory copy and then update the one in device memory as required. Managed memory is the preferred method as Direct3D can work directly with the video card for optimum resource positioning. The advice is to use managed for everything and then later on, if you want, go back and make changes to tweak performance.

3. D3DPOOL_SYSTEMMEM

Normally places resources in system RAM or at least non device assessable RAM. This will be for resources that you do not directly wish to render. These resources can be locked and do not need recreating on a lost device. One use of this resource pool is as a source to copy into a D3DPOOL_DEFAULT allocated surface or texture using UpdateSurface or UpdateTexture

4. D3DPOOL_SCRATCH

Places resources in system RAM. These resources can be locked and do not need recreating on a lost device. The great advantage of this resource type is that it is not restricted by the video card e.g. many video cards require texture dimensions to be power of 2 only so if you wish to load a non power of 2 texture this is the only pool into which you can load it. The disadvantage of course is that resources in this pool cannot be accessed by the device and so cannot be used during rendering. This pool is generally used for pre-processing of data e.g. you could load a large texture into a scratch memory surface and then slice it into smaller pieces and create normal device textures with it.

Summary

Use managed D3DPOOL_MANAGED most often, a copy will be placed in the optimal place by Direct3D in conjunction with the video card and they can be locked and manipulated and do not need recreating. If you need to use D3DPOOL_DEFAULT resources make sure you allocate them before any managed ones or use EvictManagedResources first. D3DPOOL_SYSTEMMEM resources are useful for data that will be used to update surfaces or textures. The D3DPOOL_SCRATCH pool is a place where you can manipulate date without any restrictions from the graphics device.

Resource Usage Hints

When creating resources Direct3D provides a flag where you can indicate how you will using the resource. Note that this is only a hint to Direct3D and there is no guarantee of what Direct3D will do however it is a very useful mechanism for getting optimal performance from your rendering. Direct3D provides the following usage flags:

  • D3DUSAGE_AUTOGENMIPMAP
  • D3DUSAGE_DEPTHSTENCIL
  • D3DUSAGE_DMAP
  • D3DUSAGE_DONOTCLIP
  • D3DUSAGE_DYNAMIC
  • D3DUSAGE_NPATCHES
  • D3DUSAGE_POINTS
  • D3DUSAGE_RTPATCHES
  • D3DUSAGE_RENDERTARGET
  • D3DUSAGE_SOFTWAREPROCESSING
  • D3DUSAGE_WRITEONLY

Rather than go through these in order I will look first at the most commonly used ones:

D3DUSAGE_DYNAMIC

Can be provided for any resource other than a surface. You use this flag to indicate that the resource is going to be manipulated regularly e.g. written over every frame. Direct3D will generally place this resource in AGP memory. If you do not use this flag Direct3D assumes a resource is static i.e. you are never going to manipulate it. Note that you cannot indicate dynamic usage for D3DPOOL_MANAGED created resources, instead you should use D3DPOOL_DEFAULT. Doing this means that Direct3D and the video card will decide which is the best place to put the resource. In general this will be AGP memory for vertex buffers and either AGP memory or video memory for index buffers. For best results combine with the D3DUSAGE_WRITEONLY flag if possible. The bottom line is that if you ever lock, say a vertex buffer, more than once you should indicate it is dynamic rather than static.

D3DUSAGE_WRITEONLY

Can be specified only for vertex and index buffers. Indicates to Direct3D that you are only going to ever write to this resource and never read from it. If you are never going to read from the resource this flag can give great speed increases as the device can place the resource in the best place for rendering. If you use this flag and attempt to read from the resource it will fail. Resources created in the D3DPOOL_DEFAULT should always be marked as write only or you will lose a lot of performance.

D3DUSAGE_SOFTWAREPROCESSING

Indicates that vertex processing should be done in software as opposed to hardware. Use when you create a device with software processing but avoid when using hardware processing.

D3DUSAGE_AUTOGENMIPMAP

Causes an automatic generation of mipmaps for texture resources. Note that this cannot be used with resources in system memory (D3DPOOL_SYSTEMMEM).

D3DUSAGE_DEPTHSTENCIL

Indicated that this resource will be a depth stencil buffer. Can only be used with D3DPOOL_DEFAULT resources.

D3DUSAGE_DMAP

Indicates that this texture resource will be a displacement map.

D3DUSAGE_DONOTCLIP

Indicates that the vertex buffer will never require clipping. This is useful for buffers with already transformed vertices (D3DFVF_XYZRHW) as normally a vertex buffer will require extra data for clipping flags. Clipping flags are used when rendering outside or partially outside the viewing area so if you use this flag you must be sure you will never render off screen. Note that the D3DRS_CLIPPING render state must also be set to false.

D3DUSAGE_NPATCHES

Indicates that the vertex buffer will be used to draw N-patches.

D3DUSAGE_POINTS

Indicates that the vertex or index buffer will be used to draw point sprites. Note that if the device cannot handle hardware point sprites this will cause the resource to be loaded into system memory.

D3DUSAGE_RTPATCHES

Indicates that the vertex buffer is used for drawing higher order primitives.

D3DUSAGE_RENDERTARGET

The resource will be a render target i.e. you are going to render a scene into it (useful for things like mirrors etc.). This can only be specified for textures and surfaces and can only be used for resources in the D3DPOOL_DEFAULT memory pool.

Locking and reading / writing flags

When locking resources and reading or writing them you can provide flags to Direct3D to help optimise performance. The flags are shown below:

  1. D3DLOCK_DISCARD
  2. D3DLOCK_NO_DIRTY_UPDATE
  3. D3DLOCK_NOSYSLOCK
  4. D3DLOCK_READONLY
  5. D3DLOCK_NOOVERWRITE

1. D3DLOCK_DISCARD

Can be specified for texture, vertex and index buffers. Indicates that your application will overwrite every location in the locked resource with a write only operation. Should only be used with resources indicated as dynamic. Note that you must update the whole of the resource and not just a part of it. This flag can lead to big speed improvements. For vertex and index buffers Direct3D discards the previous contents and provide a new resource while still rendering from the old one - hence no stall occurs (the old one is thrown away once finished with). However be aware that if you do a lot of discards per frame the AGP memory usage will climb as you are always getting a new resource created.

2. D3DLOCK_NO_DIRTY_UPDATE

By default when you lock a resource it is marked as 'dirty' which means it may need updating in card memory for example.

3. D3DLOCK_NOSYSLOCK

Note that this is only relevant for 16 bit Windows (95/98/ME). When a lock occurs normally a critical section is entered forcing no display mode changes to occur during the time of the lock. This can be time consuming but does give other processes time to run.

4. D3DLOCK_READONLY

Indicates that your program will never write to the resource

5. D3DLOCK_NOOVERWRITE

Indicates that during this lock you will not overwrite any data in the index or vertex buffer. This allows the driver to keep rendering with the buffer, otherwise the driver would need to finish rendering before the lock process can be completed. You use this flag if you are going to lock a buffer several times a frame to append to it. This is often used for techniques like text rendering or sprites where you add to a buffer in a loop e.g. you maintain where you are in the buffer and append items until you reach the end. When the end is reached you then do a D3DLOCK_DISCARD and start again.



© 2004-2014 Keith Ditchburn