Skip to main content
gamedev.net
🔒 Locked

Device Enumeration

Started by Wargrave Apr 10, 2006 at 6:27 PM 6 replies 1.3k views
Original Post
Wargrave
Wargrave
Hi folks! I'm having some serious compiling troubles. The code so far:

#include <iostream>
#include <windows.h>
#include <vector>
#include "d3d9.h"
#include "d3dx9.h"
using namespace std;

struct ScreenMode
{
   D3DDISPLAYMODE theMode;
   D3DFORMAT      fmt;
   int            nBits;
};

int main()
{
LPDIRECT3D9 g_pD3D = NULL; 
if( NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) 
return E_FAIL; 

UINT iAmountDevices = g_pD3D->GetAdapterCount();
D3DADAPTER_IDENTIFIER9* psAdapterIdentifier=new(D3DADAPTER_IDENTIFIER9[iAmountDevices]);

for(UINT n=0;n++<iAmountDevices;)
{
	g_pD3D->GetAdapterIdentifier(n, 0, &psAdapterIdentifier[n]);
	cout << psAdapterIdentifier[n].DeviceName;
}
delete []psAdapterIdentifier;

system("PAUSE");
return 0;
}

void GetModes(std::vector& vModes, IDirect3D9* pD3D)
{
   const D3DFORMAT fmts[] = 
   {
      D3DFMT_A1R5G5B5,
      D3DFMT_A2R10G10B10,
      D3DFMT_A8R8G8B8,
      D3DFMT_R5G6B5,
      D3DFMT_X1R5G5B5,
      D3DFMT_X8R8G8B8,
   };
   const int nBits[] = {16, 32, 32, 16, 16, 32};
   const int nNumFormats = 6;
   ScreenMode theMode;

   vModes.clear();
   for(int i=0; i<nNumFormats; ++i)
   {
      UINT nCount = pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT,fmts);
      for(UINT j=0; j<nCount; ++j)
      {
         if(SUCCEEDED(pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT,fmts,j,&theMode.theMode)))
         {
            theMode.fmt = fmts;
            theMode.nBits = nBits;
            vModes.push_back(theMode)
         }
      }
   }
}
When I compile the "Break" window keeps popping up. I'd also like to be able to enumerate the graphics cards, screen resolutions and screen update frequencies. The user should be able to pick and the picked options should be saved in a file. Maybe this is too much to ask but I've been trying to manage this myself for so long now that I'm becoming a bit desperate. Thanks Wargrave
jflanglois
jflanglois
Indeed, the problem is with you for loop. n is incremented at the begining of the loop, as opposed to the end. Write it like the OP suggested (although you preferably use the prefix increment operator).

Detailed explanation:
For the sake of simplicity, let's say you have only one device, so iAmountDevices = 1. You new an array of size 1 and you enter your for loop. At the first iteration, n == 1 (since you increment n right after the comparison), so you do GetDeviceIdentifier with an index of 1, and ask that the result is sent to &psAdapterIdentifier[1], which is out of bounds.
Quote:
From DXSDK, GetDeviceIdentifier
pIdentifier
[out] Pointer to a D3DADAPTER_IDENTIFIER9 structure to be filled with information describing this adapter. If Adapter is greater than or equal to the number of adapters in the system, this structure will be zeroed.

So you are writing zeros beyond the end of your array, thusly corrupting the heap. Boom.


jfl.
Wargrave
Wargrave
Thank you both for your answers. It worked.

How can I enumerate the graphics cards, screen resolutions and screen update frequencies in an efficient way? Actual code would be greatly appreciated.

Thanks
Wargrave
Evil Steve
Evil Steve
You'll need to edit your GetModes() function to allow you to enumerate modes for different cards:
void GetModes(std::vector<ScreenMode>& vModes, IDirect3D9* pD3D, int nAdapter){   const D3DFORMAT fmts[] =    {      D3DFMT_A1R5G5B5,      D3DFMT_A2R10G10B10,      D3DFMT_A8R8G8B8,      D3DFMT_R5G6B5,      D3DFMT_X1R5G5B5,      D3DFMT_X8R8G8B8,   };   const int nBits[] = {16, 32, 32, 16, 16, 32};   const int nNumFormats = 6;   ScreenMode theMode;   vModes.clear();   for(int i=0; i<nNumFormats; ++i)   {      UINT nCount = pD3D->GetAdapterModeCount(nAdapter, fmts);      for(UINT j=0; j<nCount; ++j)      {         if(SUCCEEDED(pD3D->EnumAdapterModes(nAdapter, fmts, j, &theMode.theMode)))         {            theMode.fmt = fmts;            theMode.nBits = nBits;            vModes.push_back(theMode)         }      }   }}

You'll need to enumerate cards, and for each cards you find, enumerate the modes for it:
struct Adapter{   D3DADAPTER_IDENTIFIER9  theAdapter;   std::vector<ScreenMode> vModes;}void EnumAdapters(IDirect3D9* pD3D, std::vector<Adapter>& vAdapters){Adapter theAdapter;UINT nCount;   nCount = g_pD3D->GetAdapterCount();   for(UINT i=0; i<nCount; ++i)   {      theAdapter.vModes.clear();      pD3D->GetAdapterIdentifier(i, 0, &theAdapter.theAdapter);      EnumModes(theAdapter.vModes, pD3D, i);      vAdapters.push_bach(theAdapter);   }}

That should work fine. Your test app would look something like:
#include <iostream>#include <windows.h>#include <vector>#include "d3d9.h"#include "d3dx9.h"using namespace std;int main(){std::vector<Adapter> vAdapters;   // Create a D3D interface   LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);   if(!pD3D)      return -1;   // Enumerate everything   EnumAdapters(pD3D, vAdapters);   // Display info   for(size_t nAdapter=0; nAdapter<vAdapters.size(); ++nAdapter)   {      cout << vAdapters[nAdapter].theAdapter.DeviceName << endl      for(size_t nMode=0; nMode<vAdapters[nAdapter].vModes.size(); ++nMode)      {         const ScreenMode& rMode = vAdapters[nAdapter].vModes[nMode];         cout << "   " << rMode.theMode.Width << "x" << rMode.theMode.Height << "x" << rMode.nBits << " @ " << rMode.theMode.RefreshRate << "Hz" << endl;      }   }}

All that code is untested though, so there may well be problems with it.

EDIT: Actually, what might be neater is to make Adapter derive from D3DADAPTER_IDENTIFIER9, then you can pass it a pointer to an Adapter where a D3DADAPTER_IDENTIFIER9 is needed. Likewise for the screen mode.
However, it might end up a little messy.
Wargrave
Wargrave
Hi!

It works perfectly! I greatly appreciate your help Evil Steve. Here is the code so far:

//Device Enumeration - Projektarbete - 2006-03-15#include <iostream>#include <windows.h>#include <vector>#include "d3d9.h"#include "d3dx9.h"using namespace std;struct ScreenMode{   D3DDISPLAYMODE theMode;   D3DFORMAT      fmt;   int            nBits;};struct Adapter{   D3DADAPTER_IDENTIFIER9  theAdapter;   std::vector<ScreenMode> vModes;};void EnumModes(std::vector<ScreenMode>& vModes, IDirect3D9* pD3D, int nAdapter);void EnumAdapters(IDirect3D9* pD3D, std::vector<Adapter>& vAdapters);int main(){std::vector<Adapter> vAdapters;   // Create a D3D interface   LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);   if(!pD3D)      return -1;   // Enumerate everything   EnumAdapters(pD3D, vAdapters);   // Display info   for(size_t nAdapter=0; nAdapter<vAdapters.size(); ++nAdapter)   {      cout << vAdapters[nAdapter].theAdapter.DeviceName << endl;      for(size_t nMode=0; nMode<vAdapters[nAdapter].vModes.size(); ++nMode)      {         const ScreenMode& rMode = vAdapters[nAdapter].vModes[nMode];         cout << "   " << rMode.theMode.Width << "x" << rMode.theMode.Height << "x" << rMode.nBits << " @ " << rMode.theMode.RefreshRate << "Hz" << endl;      }   }   system("PAUSE");   return 0;}void EnumModes(std::vector<ScreenMode>& vModes, IDirect3D9* pD3D, int nAdapter){   const D3DFORMAT fmts[] =    {      D3DFMT_A1R5G5B5,      D3DFMT_A2R10G10B10,      D3DFMT_A8R8G8B8,      D3DFMT_R5G6B5,      D3DFMT_X1R5G5B5,      D3DFMT_X8R8G8B8,   };   const int nBits[] = {16, 32, 32, 16, 16, 32};   const int nNumFormats = 6;   ScreenMode theMode;   vModes.clear();   for(int i=0; i<nNumFormats; ++i)   {      UINT nCount = pD3D->GetAdapterModeCount(nAdapter, fmts);      for(UINT j=0; j<nCount; ++j)      {         if(SUCCEEDED(pD3D->EnumAdapterModes(nAdapter, fmts, j, &theMode.theMode)))         {            theMode.fmt = fmts;            theMode.nBits = nBits;            vModes.push_back(theMode);         }      }   }}void EnumAdapters(IDirect3D9* pD3D, std::vector<Adapter>& vAdapters){Adapter theAdapter;UINT nCount;   nCount = pD3D->GetAdapterCount();   for(UINT i=0; i<nCount; ++i)   {      theAdapter.vModes.clear();      pD3D->GetAdapterIdentifier(i, 0, &theAdapter.theAdapter);      EnumModes(theAdapter.vModes, pD3D, i);      vAdapters.push_back(theAdapter);   }}


How do I list the bit formats (I think they're called that)? I also want the user to be able to choose a bit format, a graphics card and a resolution, and that this information is shown in a text file. What code and how should I add it to maintain the fine structure of the program above?

These are the last things I'm going to ask for, then I won't be a burden anymore.

Thanks
Wargrave
IlyaZ
IlyaZ
just add this line for the formats.

"Hz" <<" with "<<rMode.fmt<< endl;
jflanglois
jflanglois
Your main would look something like so (no error handling, sorry), plagiarized from Evil Steve and Iliza:

int main(){	std::vector<Adapter> vAdapters;	// Create a D3D interface	LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);	if(!pD3D)		return -1;	// Enumerate everything	EnumAdapters(pD3D, vAdapters);	// Display info	size_t nAdapter = 0;	for( ; nAdapter < vAdapters.size(); ++nAdapter ) {		std::cout << nAdapter << ": " << vAdapters[nAdapter].theAdapter.DeviceName << std::endl;	}	std::cout << "Please select an adapter: ";	std::cin >> nAdapter;	size_t nMode = 0;	for( ; nMode<vAdapters[nAdapter].vModes.size(); ++nMode ) {		const ScreenMode& rMode = vAdapters[nAdapter].vModes[nMode];		std::cout << nMode << ": "			<< rMode.theMode.Width << "x"			<< rMode.theMode.Height << "x"			<< rMode.nBits << " @ "			<< rMode.theMode.RefreshRate << "Hz"			<<" with "<< rMode.fmt << std::endl;	}	std::cout << "Please select a mode: ";	std::cin >> nMode;	// use nAdapter and nMode	system("PAUSE");	return 0;}

jfl.

Topic Locked

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

Sign in to reply to this topic.