   Beginning DirectX 10: Why my test program uses up 50% dual-core CPU?
  Anyone ever read "Beginning DirectX 10" book?I'm still on Chapter 2, where I get to make my first DirectX 10 program. The main problem is that the program I have created is sluggish and slow. All it was doing, was drawing 640x480 dark blue onto the screen, using the macro:void Render(){if (pD3DDevice != NULL){pD3DDevice->ClearRenderTargetView(pRenderTargetView, D3DXCOLOR(0.1f, 0.2f, 0.3f, 0.0f));//That's it. Nothing else here, move along folks. Don't feed the bears.//Display next item in swap chain. Making sure of that...pD3DSwapChain->Present(0, 0);}return;}Just this stuff running, and it "takes" away 50% of my Dual-Core CPU processing power. It lags when I drag it, resize the window, etc.So, I wanted to know what did I done wrong? Why is it slow? Thanks in advance.If you want the full code, look below:// BeginningDirectX10.cpp : Defines the entry point for the application.//#include "stdafx.h"#include "BeginningDirectX10.h"#include <D3D10.h>#include <D3DX10.h>#define MAX_LOADSTRING 100// Global Variables:HINSTANCE hInst;// current instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar textTCHAR szWindowClass[MAX_LOADSTRING];// the main window class name//Global DirectX variables:ID3D10Device*pD3DDevice = NULL;IDXGISwapChain*pD3DSwapChain = NULL;ID3D10RenderTargetView*pRenderTargetView = NULL;// Forward declarations of functions included in this code module:ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);bool InitDirect3D(HWND, int width, int height);void Render();void ShutdownDirect3D();int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR    lpCmdLine, int  nCmdShow){UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here.MSG msg = {0};HACCEL hAccelTable;// Initialize global stringsLoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_BEGINNINGDIRECTX10, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// Perform application initialization:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_BEGINNINGDIRECTX10));// Main message loop:while (msg.message != WM_QUIT){while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE){TranslateMessage(&msg);DispatchMessage(&msg);}Render();}return (int) msg.wParam;}////  FUNCTION: MyRegisterClass()////  PURPOSE: Registers the window class.////  COMMENTS:////    This function and its usage are only necessary if you want this code//    to be compatible with Win32 systems prior to the 'RegisterClassEx'//    function that was added to Windows 95. It is important to call this function//    so that the application will get 'well formed' small icons associated//    with it.//ATOM MyRegisterClass(HINSTANCE hInstance){WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX);wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc= WndProc;wcex.cbClsExtra= 0;wcex.cbWndExtra= 0;wcex.hInstance= hInstance;wcex.hIcon= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BEGINNINGDIRECTX10));wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= MAKEINTRESOURCE(IDC_BEGINNINGDIRECTX10);wcex.lpszClassName= szWindowClass;wcex.hIconSm= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);}////   FUNCTION: InitInstance(HINSTANCE, int)////   PURPOSE: Saves instance handle and creates main window////   COMMENTS:////   In this function, we save the instance handle in a global variable and//   create and display the main program window.//BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){   HWND hWnd;   int WINDOW_WIDTH = 640;   int WINDOW_HEIGHT = 480;   hInst = hInstance; // Store instance handle in our global variable   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);   if (!hWnd)   { return FALSE;   }   //DirectX 10 Initialization Call, just after creating the window. Not DirectX preset.   if (!InitDirect3D(hWnd, WINDOW_WIDTH, WINDOW_HEIGHT))   {   return 2;   }   ShowWindow(hWnd, nCmdShow);   UpdateWindow(hWnd);   return TRUE;}////  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)////  PURPOSE:  Processes messages for the main window.////  WM_COMMAND- process the application menu//  WM_PAINT- Paint the main window//  WM_DESTROY- post a quit message and return////LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;switch (message){case WM_COMMAND:wmId    = LOWORD(wParam);wmEvent = HIWORD(wParam);// Parse the menu selections:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO: Add any drawing code here...EndPaint(hWnd, &ps);break;case WM_DESTROY:PostQuitMessage(0);break;case WM_KEYDOWN:switch (wParam){case VK_ESCAPE:PostQuitMessage(1);break;}default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;}// Message handler for about box.INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){UNREFERENCED_PARAMETER(lParam);switch (message){case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL){EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;}//FUNCTION: InitDirect3D (HWND hWnd, int width, int height)////PURPOSE: Initialize Direct3D.////OUTPUT: True if successful, false if not.bool InitDirect3D(HWND hWnd, int width, int height){DXGI_SWAP_CHAIN_DESC SwapChainDesc;ZeroMemory(&SwapChainDesc, sizeof(SwapChainDesc));SwapChainDesc.BufferCount = 1;SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;SwapChainDesc.BufferDesc.Height = height;SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;SwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;SwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;SwapChainDesc.BufferDesc.Width = width;SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;//SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_NONPREROTATED;SwapChainDesc.OutputWindow = hWnd;SwapChainDesc.SampleDesc.Count = 1;SwapChainDesc.SampleDesc.Quality = 0;SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;SwapChainDesc.Windowed = true;HRESULT hResult = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL, 0, D3D10_SDK_VERSION, &SwapChainDesc, &pD3DSwapChain, &pD3DDevice);if (hResult != S_OK){return false;}//Getting back buffer from swap chain.ID3D10Texture2D* pBackBuffer;//Resource.hResult = pD3DSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*) &pBackBuffer);if (hResult != S_OK){return false;}//Create render target view.hResult = pD3DDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView);//Release the back buffer.pBackBuffer->Release();if (hResult != S_OK){return false;}//Set the render target.pD3DDevice->OMSetRenderTargets(1, &pRenderTargetView, NULL);//Create and set viewport.D3D10_VIEWPORT viewport;viewport.Height = height;viewport.Width = width;viewport.MinDepth = 0.0f;viewport.MaxDepth = 1.0f;viewport.TopLeftX = 0;viewport.TopLeftY = 0;pD3DDevice->RSSetViewports(1, &viewport);return true;}//FUNCTION: void Render()////PURPOSE: All drawing occurs here.void Render(){if (pD3DDevice != NULL){pD3DDevice->ClearRenderTargetView(pRenderTargetView, D3DXCOLOR(0.1f, 0.2f, 0.3f, 0.0f));//Nothing.//Display next item in swap chain. Note to Self.pD3DSwapChain->Present(0, 0);}return;}//FUNCTION: void ShutdownDirect3D()////PURPOSE: To shut down Direct3D.void ShutdownDirect3D(){//Release render target.if (pRenderTargetView != NULL){pRenderTargetView->Release();}//Release swap chain.if (pD3DSwapChain != NULL){pD3DSwapChain->Release();}//Release D3D Device.if (pD3DDevice != NULL){pD3DDevice->Release();}return;}
  how can you say it is "sluggish and slow" if all you get is a blue rectangle?;  50% of a dual core means 100% of a single core.This is basically because your program boils down to:while( true ) { doSomething(); }i.e. It's doing a simple task, over and over, as fast as it can.If you want it to relinquish some time back to the OS, the add Sleep(0); after you call Render().   ;  An application with only 1 thread will never have more than 50% usage on a dual core cpu, and 25% on a quad core. Unfortunately, if you want to use the totality of your processing speed, you have to multi-thread. DirectX11 actually made some nice improvement about multi threading.Still shouldn't be sluggish and slow­. Might be other problems.   ;  You are initializing the device object with the reference rasterizer driver. It is a software driver designed for verifying and debugging the API, not for lightning-fast performance.Real hardware can be orders of magnitude faster in rendering stuff.That said, I concur with what kunos says: if you're not effectively rendering anything but a solid color background, it shouldn't even matter how slow the rendering is [grin]   ;Quote:Original post by Hodgman50% of a dual core means 100% of a single core.But that's what it was saying when I used Task Manager to check on the Performance tab.Quote:Original post by Nik02You are initializing the device object with the reference rasterizer driver. It is a software driver designed for verifying and debugging the API, not for lightning-fast performance.Real hardware can be orders of magnitude faster in rendering stuff.So, it was because of D3D10_DRIVER_TYPE_REFERENCE? After I changed it to D3D10_DRIVER_TYPE_HARDWARE, the Task manager says my CPU is at 40%. And both of my CPUs are nearly the same.   ;  This is expected behavior, and you did not really do anything "wrong". As Hodgman already stated, you are telling the computer to fill your window with a single color as fast as it can, which effectively eats up all the power of a single core. This, in your case, is (about) 50% of the CPU power since you have two cores.Most games actually do this. They render the gfx on the screen as fast as they can. This is why the FPS on a faster computer is higher than on a slower one. However, the CPU usage for both the faster and slower computer is usually 100% of a single core in a single threaded game, and it might be more if the game is multi-threaded.   ;  Try using pD3DSwapChain->Present(1, 0) instead, with a hardware device. That should cause the screen to refresh only at the monitor refresh-rate, which can free up CPU-time.   ;Quote:Original post by tom_mai78101Quote:Original post by Hodgman50% of a dual core means 100% of a single core.But that's what it was saying when I used Task Manager to check on the Performance tab.Yes, that's correct. If a single threaded program is running as fast as it can on a dual-core processor, it will be using 50% of the total processing power (i.e. one out of two cores completely utilized), so task-manager will report 50% CPU usage...There isn't a problem here. The "problem" is that this is what you're telling the CPU to do. You're telling it to do this.   ;  Oh...Quote:Original post by Erik RufeltTry using pD3DSwapChain->Present(1, 0) instead, with a hardware device. That should cause the screen to refresh only at the monitor refresh-rate, which can free up CPU-time.What values are legal for the first parameter? Other than 0, and 1? And how does any single value (0, 1, 2, 3, etc.) control the syncing of the drawing?I know from here that I was able to control it, to some degree...:Quote:Original post by Beginning DirectX 10The first parameter to the Present function gives you the ability to control how drawing is synced. Sending a default value of 0 will present the next buffer in the swap chain to the screen immediately.