Thread: CreateDevice returning D3DERR_NOTAVAILABLE

  1. #1
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709

    CreateDevice returning D3DERR_NOTAVAILABLE

    Could someone just take a look at this. I'm following Introduction to 3D Game Programming With Direct3D9 and I've whipped up this class to manage initialisation of Direct3D, but for some reason I'm getting D3DERR_NOTAVAILABLE returned from CreateDevice(). I've looked it up on MSDN but "This device does not support the queried technique." doesn't help much.

    I've tried using D3DDEVTYPE_REF and D3DCREATE_SOFTWARE_VERTEXPROCESSING but nothing seems to make it work. What the hell am I doing wrong?

    D3DManager.h
    Code:
    #pragma once
    
    /* D3DManager
     */
    #include <d3d9.h>
    #include <iostream>
    
    // TODO: Make this a singleton?
    class D3DManager {
    public:
        D3DManager();
        ~D3DManager();
    
        bool Initialise(HWND hWnd, D3DDEVTYPE deviceType, int bbWidth, int bbHeight, bool windowed);
    
    private:
        IDirect3D9*         d3d9;
        IDirect3DDevice9*   d3dDevice;
        DWORD               vertProcessing;
    
    };
    D3DManager.cpp
    Code:
    #include ".\d3dmanager.h"
    
    D3DManager::D3DManager()
    {
        d3d9 = 0;
        d3dDevice = 0;
        vertProcessing = 0;
    }
    
    D3DManager::~D3DManager()
    {
    }
    
    /* Initialise
     */
    bool D3DManager::Initialise(HWND hWnd, D3DDEVTYPE deviceType, int bbWidth, int bbHeight, bool windowed)
    {
        D3DCAPS9 caps;
        D3DPRESENT_PARAMETERS d3dpp;
        HRESULT hr = 0;
    
        d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
        if (! d3d9) return false;
    
        d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
    
        // Determine whether or not we can use hardware vertex processing (perferred)
        if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
            vertProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
        else
            vertProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    
        ZeroMemory(&caps, sizeof(D3DCAPS9));
    
        // Fill out the D3DPRESENT_PARAMETERS structure
        d3dpp.BackBufferCount = 1;                                  // Single backbuffer
        d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;                   // 8bits for ARGB
        d3dpp.BackBufferHeight = bbHeight;                          // back buffer height
        d3dpp.BackBufferWidth = bbWidth;                            // back buffer width
        d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;                // No AA. TODO: Make this a parameter
        d3dpp.MultiSampleQuality = 0;                               // Zero quality
        d3dpp.Flags = 0;                                            // Zero flags
        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // Use current refresh rate
        d3dpp.hDeviceWindow = hWnd;                                 // Window handle
        d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Immediate back buffer presentation
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;                   // Discard previous back buffer contents
        d3dpp.Windowed = windowed;                                  // Run windowed (or not)
    
        // Create the device
        hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, deviceType, hWnd, vertProcessing, &d3dpp, &d3dDevice);
        //if (FAILED(hr)) {
        //    char msg[256] = {0};
        //    sprintf(msg, "D3DManager::Initialise: CreateDevice() Failed (%d)", GetLastError());
        //    ::MessageBox(0, msg, "Error", MB_OK | MB_ICONERROR | MB_TASKMODAL);
        //    return false;
        //}
    
        switch (hr) {
            case D3DERR_DEVICELOST:
                ::MessageBox(0, "Device lost?!?", "Error", 0);
                return false;
            case D3DERR_INVALIDCALL:
                ::MessageBox(0, "Invalid call", "Error", 0);
                return false;
            case D3DERR_NOTAVAILABLE:
                ::MessageBox(0, "Not available", "Error", 0);
                return false;
            case D3DERR_OUTOFVIDEOMEMORY:
                ::MessageBox(0, "Out of video mem", "Error", 0);
                return false;
            default:
                return false;
        }
    
        return true;
    }
    I've decided to really knuckle down with Direct3D now I've got ~15 weeks with nothing to do.

    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  2. #2
    Yah. Morgul's Avatar
    Join Date
    Feb 2005
    Posts
    109
    I glanced at it and didn't see anything wrong. Maybe try a different back buffer format, that's the only thing I could think of at this point. I'll look it over again later.
    Sic vis pacum para bellum. If you want peace, prepare for war.

  3. #3
    >>"This device does not support the queried technique."

    Meaning, your Video Card doesnt support the feature(s) you requested of it. It could be anything; Your buffer format, your resolution, etc. Try decreasing every setting to its lowest possible value and try again.
    "There's always another way"
    -lightatdawn (lightatdawn.cprogramming.com)

  4. #4
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I'm with Mr. Wizard. You probably have some erroneous value in the D3DPRESENT_PARAMETETERS structure that is causing the issue.

    Always make it a practice to zero out the structures if you are not specifically intializing them with some known value PRIOR to passing it to Direct3D calls.

  6. #6
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Hmm I got it working and sort of did something cool but stupid at the same time. Observe:

    http://www.ahluka.co.uk/ooo_blood_money.jpg

    That, if I'm not mistaken, is the remains of the game of Hitman: blood money that I've just finished playing. Woot.

    But why?

    Code:
    /*
     * d3d
     */
    #include <windows.h>
    #include "GFXBase.h"
    //#include <d3d9.h>
    #include <d3dx9.h>
    #include "D3DManager.h"
    
    D3DManager* d3dm = 0;
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    void Render(float timeDelta);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        GFXBase* gfxBase = GFXBase::CreateInstance();
        MSG msg;
        HWND hWnd = 0;
        bool done = false;
        static float lastTime = (float) timeGetTime();
        float currTime;
        float timeDelta;
    
        d3dm = new D3DManager;
    
        hWnd = gfxBase->NewWindow(hInstance, WndProc, WS_OVERLAPPEDWINDOW, "d3d", "d3d", 0, 0, 640, 480);
        if (! hWnd) {
            ::MessageBox(0, "GFXBase::NewWindow failed", "Error", MB_OK | MB_ICONERROR | MB_TASKMODAL);
            gfxBase->DestroyWindow();
            GFXBase::FreeInstance();
            return 1;
        }
    
        if (! d3dm->Initialise(hWnd, D3DDEVTYPE_HAL, 640, 480, true)) {
            ::MessageBox(0, "D3DManager::Initialise failed", "Error", MB_OK | MB_ICONERROR | MB_TASKMODAL);
            return 1;
        }
    
        ShowWindow(hWnd, nCmdShow);
        SetFocus(hWnd);
        UpdateWindow(hWnd);
    
        ZeroMemory(&msg, sizeof(MSG));
        while (! done) {
            if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
                if (msg.message == WM_QUIT) done = true;
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            } else {
                currTime = (float) timeGetTime();
                timeDelta = (currTime - lastTime) * 0.001f;
    
                Render(timeDelta);
    
                lastTime = currTime;
            }
        }
    
        gfxBase->DestroyWindow();
        GFXBase::FreeInstance();
        delete d3dm;
        return msg.wParam;
    }
    
    void Render(float timeDelta)
    {
        if (d3dm->VerifyDevice()) {
            d3dm->GetDevice()->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
            d3dm->GetDevice()->Present(0, 0, 0, 0);
        }
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg) {
            case WM_CLOSE:
                DestroyWindow(hWnd);
                break;
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
            default:
                return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    
        return 0;
    }
    EDIT: Actually, I lie. I just realised that's my desktop wallpaper. Coincidence that I'd just stopped playing BM, but still, why?
    Last edited by cboard_member; 05-28-2006 at 10:14 AM.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Stop GUI Application returning when run
    By DaveHope in forum Windows Programming
    Replies: 7
    Last Post: 06-29-2009, 08:57 PM
  2. Help with struct... not returning correct results.
    By drty2 in forum C Programming
    Replies: 7
    Last Post: 01-18-2009, 11:25 PM
  3. Recursion: base case returning 1, function returning 0
    By yougene in forum C Programming
    Replies: 5
    Last Post: 09-07-2007, 05:38 PM
  4. Function returning incorrect value
    By CHurst in forum C Programming
    Replies: 3
    Last Post: 12-13-2005, 01:27 PM
  5. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM