DirectX Graphics:
Enumeration
Author
: Jack Hoxley
Written : 2nd December 2000
Contact : [Email]
Download : Graph_02.Zip
[11 Kb]
Contents
of this lesson:
1. Introduction
2. Display Device, Adapter and resolution
enumeration
3. Hardware Capability enumeration
1.
Introduction
Enumeration
is a fairly basic idea once you get used to it
- and it's something that you're going to have
to use if you intend to make a distributable application
using DirectX. Enumeration is the process of capability
detection - you ask it questions (about what it
can do) and it will tell you if it can or cant
do what you want it to do. As far as tutorials
go it's fairly safe to hardcode the settings such
as resolution and renderer - no ones really going
to miss out if it wont work, but if you're writing
a real-world application that lots of people will
be using (such as a published game) you want to
make your application as solid as a rock.
Enumeration
is what games use to display a list of resolutions
that you can play the game at, but it's also used
in ways you may not notice. For example, a program
can query your hardware for the possibility of
using bump-mapping; if the enumeration returns
true then you get in-game bump-mapping. If it
returns false the game can either decide to not
use bump-mapping or it can do something else (such
as use software bump-mapping).
This
lesson will introduce you to both of the main
types of enumeration - display mode/renderer and
hardware capabilities. But as there are so many
possible hardware capabilites to check only the
structure will be discussed here - enumeration
will be used in later tutorials, and any relevent
details will be discussed then. But if you happen
to have the DirectX8 SDK help file you can examine
their descriptions/information on all of the possible
enumerations.
2.
Display Device, Adapter and resolution enumeration
First
up we want to know what modes we can initialise
our application in. In windowed mode this doesn't
matter a great deal, but in fullscreen mode you
must prepare a correct display mode setup that
the hardware supports - or you'll get an error
when trying to create the device. There is a basic
hierachy that you need to remember when enumerating
for display modes and formats:
ADAPTER
=> DEVICE => RESOLUTIONS & CAPABILITIES
First
we must query the adapters available, then selecting
one of these adapters we query what device's it
supports (HAL or REFERENCE) then we must query
the adapter-device combination for the resolutions
it supports and the hardware capabilities. So,
first off I'll show you how to enumerate the adapters:
'//D3D should be a valid reference to a Direct3D8 object.
'//AdapterInfo should be a defined D3DADAPTER_IDENTIFIER8 variable
Private Sub EnumerateAdapters()
Dim I As Integer, sTemp As String, J As Integer
'//This'll either be 1 or 2
nAdapters = D3D.GetAdapterCount
For I = 0 To nAdapters - 1
'Get the relevent Details
D3D.GetAdapterIdentifier I, 0, AdapterInfo
'Get the name of the current adapter - it's stored as a long
'list of character codes that we need to parse into a string
' - Dont ask me why they did it like this; seems silly really :)
sTemp = "" 'Reset the string ready for our use
For J = 0 To 511
sTemp = sTemp & Chr$(AdapterInfo.Description(J))
Next J
sTemp = Replace(sTemp, Chr$(0), " ")
cmbAdapters.AddItem sTemp
Next I
End Sub
|
|
|
|
You
may well want to change the output control - currently
it just dumps all the relevent information into
the "cmbAdapters" combobox. The code
above basically counts the number of available
adapters (almost always 1) then it loops through
them and collects the information on them (in
the AdapterInfo variable). Should you want more
than the name of the adapter you can also get
the following (Useful) information:
Description
: A brief description of the adapter, intended
to be displayed to the user.
Driver : What driver the hardware is using
- again, to be displayed to the user. (This is
usually going to be the DLL name)
DeviceID : A number representing the chip-set
type; could be 0 if unknown.
DeviceIdentifier : A set of 4 variables
determining the hardware in use. This is the best
variable to use should you want to identify a
piece of hardware.
Now
that we can identify the adapter we can look at
what devices it'll support. Software renderers
are an advanced topic and are unlikely to be relevent
yet so we'll ignore them for now. Instead we'll
check if the hardware supports HAL (Hardware Accelaration).
The reference rasterizer should always be present
so we'll just assume that we can access it.
Private Sub EnumerateDevices()
On Local Error Resume Next '//We want to handle the errors...
Dim Caps As D3DCAPS8
D3D.GetDeviceCaps cmbAdapters.ListIndex, D3DDEVTYPE_HAL, Caps
If Err.Number = D3DERR_NOTAVAILABLE Then
'There is no hardware acceleration
cmbDevice.AddItem "Reference Rasterizer (REF)" 'Reference device will always be available
Else
cmbDevice.AddItem "Hardware Acceleration (HAL)"
cmbDevice.AddItem "Reference Rasterizer (REF)" 'Reference device will always be available
End If
End Sub
|
|
|
|
Above
is a slightly sloppy way of detecting hardware
support - but it works and is very simple. If
we attempt to read stuff from a HAL device and
it doesn't exist then we'll get the error code
"D3DERR_NOTAVAILABLE", at which point
we know that only the REF device is okay to use.
The code outputs the results to a combobox, which
you can change if you want...
The
last thing that we want to be able to check is
what display modes are supported. This can only
be done when we've selected an adapter and a device.
Private Sub EnumerateDispModes(Renderer As Long)
cmbRes.Clear '//Remove any existing entries...
Dim I As Integer, ModeTemp As D3DDISPLAYMODE
nModes = D3D.GetAdapterModeCount(cmbAdapters.ListIndex)
For I = 0 To nModes - 1 '//Cycle through them and collect the data...
Call D3D.EnumAdapterModes(cmbAdapters.ListIndex, I, ModeTemp)
'First we parse the modes into two catergories - 16bit and 32bit
If ModeTemp.Format = D3DFMT_R8G8B8 Or ModeTemp.Format = D3DFMT_X8R8G8B8 Or ModeTemp.Format = D3DFMT_A8R8G8B8 Then
'Check that the device is acceptable and valid...
If D3D.CheckDeviceType(cmbAdapters.ListIndex, Renderer, ModeTemp.Format, ModeTemp.Format, False) >= 0 Then
'then add it to the displayed list
cmbRes.AddItem ModeTemp.Width & "x" & ModeTemp.Height & " 32 bit" & " [FMT: " & ModeTemp.Format & "]"
End If
Else
If D3D.CheckDeviceType(cmbAdapters.ListIndex, Renderer, ModeTemp.Format, ModeTemp.Format, False) >= 0 Then
cmbRes.AddItem ModeTemp.Width & "x" & ModeTemp.Height & " 16 bit" & " [FMT: " & ModeTemp.Format & "]"
End If
End If
Next I
cmbRes.ListIndex = cmbRes.ListCount - 1
End Sub
|
|
|
|
Once
we have retrieved the number of display modes
we cycle through them and decide first what bit-depth
catergory they go in (16 bit or 32 bit) then we
check with Direct3D that the format is going to
work with the current device and adapter selection.
Once this is done it outputs it to a combo box
ready for the user to select which one he/she
wants to use. Note the "[FMT: ]" part
at the end; this shows you what precise format
it's in, 16/32 bit is not enough to base this
on, so I've included the information on exactly
what format it'll work in.
When
you look at the sample code included with this
tutorial you will notice that it recalculates
the resolutions and devices each time you change
the adapter, and it changes the display mode list
each time you select a new renderer.
3.
Hardware Capability enumeration
The
final useful part is to determine what features
the hardware supports. This is particularly useful
if you want to use a special feature that is hardware
dependant and not very common yet (ie, at the
cutting edge of technology). Capability enumeration
is very simple, but there are 100's (maybe 1000's)
or things you can check for.
The
first stage is to actually retrieve the information,
this is incredibly simple:
'This code assumes that D3D is a valid reference to a Direct3D8 object.
Dim Caps As D3DCAPS8 '//Holds all our information...
D3D.GetDeviceCaps cmbAdapters.ListIndex, Renderer, Caps
|
|
|
|
Now
that we have a structure holding all the information
("Caps") we can query it for what we
would like to know. There are lots of different
flags that you can look at, all of them listed
in VB's Object browser, but it's unlikely that
you can guess what they all mean. The DirectX
8 help file lists them all with descriptions if
you have it - otherwise you're just going to have
to wait until someone tells you (they will be
explained as you need them in later lessons) or
guess.
Following
are some example of how to get information on
the hardware capabilities:
If Caps.MaxActiveLights = -1 Then
List1.AddItem "Maximum Active Lights: Unlimited"
Else
List1.AddItem "Maximum Active Lights: " & Caps.MaxActiveLights
End If
List1.AddItem "Maximum Point Vertex size: " & Caps.MaxPointSize
List1.AddItem "Maximum Texture Size: " & Caps.MaxTextureWidth & "x" & Caps.MaxTextureHeight
List1.AddItem "Maximum Primatives in one call: " & Caps.MaxPrimitiveCount
If Caps.TextureCaps And D3DPTEXTURECAPS_SQUAREONLY Then
List1.AddItem "Textures must always be square"
End If
If Caps.TextureCaps And D3DPTEXTURECAPS_CUBEMAP Then
List1.AddItem "Device Supports Cube Mapping"
End If
If Caps.TextureCaps And D3DPTEXTURECAPS_VOLUMEMAP Then
List1.AddItem "Device Supports Volume Mapping"
End If
|
|
|
|
There
are more in the sample for this lesson; but the
above should be enough - they're all the same
apart from the specified flag.
It
is recommended that you download the sample code
for this lesson so that you can see how a working
example looks. The download is at the top of this
page.
Once
you've understood this part you can proceed onto
Lesson 03 : 2D Graphics
part 1 - The Basics
|