INITIALIZING DIRECT3D

初始化Direct3D需要一下几个步骤:

1. Create the ID3D11Device and ID3D11DeviceContext interfaces using the D3D11CreateDevice function.
2. Check 4X MSAA quality level support using the ID3D11Device::CheckMultisampleQualityLevels method.
3. Describe the characteristics of the swap chain we are going to create by filling out an instance of the
DXGI_SWAP_CHAIN_DESC structure.
4. Query the IDXGIFactory instance that was used to create the device, and create an IDXGISwapChain instance.
5. Create a render target view to the swap chain’s back buffer.
6. Create the depth/stencil buffer and its associated depth/stencil view.
7. Bind the render target view and depth/stencil view to the output merger stage of the rendering pipeline so that they can be used by
Direct3D.
8. Set the viewport

 

创建d3d设备和上下文(Create the Device and Context)

1. The ID3D11Device interface is used to check feature support, and allocate resources.
2. The ID3D11DeviceContext interface is used to set render states, bind resources to the graphics pipeline, and issue rendering
commands.

HRESULT D3D11CreateDevice(
    IDXGIAdapter *pAdapter,
    D3D_DRIVER_TYPE DriverType,
    HMODULE Software,
    UINT Flags,
    CONST D3D_FEATURE_LEVEL *pFeatureLevels,
    UINT FeatureLevels,
    UINT SDKVersion,
    ID3D11Device **ppDevice,
    D3D_FEATURE_LEVEL *pFeatureLevel,
    ID3D11DeviceContext **ppImmediateContext
);

1. pAdapter: Specifies the display adapter we want the create device to represent. Specifying null for this parameter uses the
primary display adapter.

2. DriverType:

D3D_DRIVER_TYPE_HARDWARE

D3D_DRIVER_TYPE_SOFTWARE

D3D_DRIVER_TYPE_WARP: Creates a high performance Direct3D 10.1 software driver. WARP stands for Windows Advanced
Rasterization Platform. We are uninterested in this because it does not support Direct3D 11.

3. Software: This is used for supplying a software driver

4. Flags: Optional device creation flags (that can be bitwise ORed together). Two common flags are:

D3D11_CREATE_DEVICE_DEBUG: For debug mode builds, this flag should be set to enable the debug layer. When the debug flag is
specified, Direct3D will send debug messages to the VC++ output window

D3D11_CREATE_DEVICE_SINGLETHREADED: Improves performance if you can guarantee that Direct3D will not be called from
multiple threads. If this flag is enabled, then the ID3D11Device::CreateDeferredContext method will fail

5.pFeatureLevels: An array of D3D_FEATURE_LEVEL elements

Specifying null for this parameter indicates to choose the greatest feature level supported

6. FeatureLevels: The number of D3D_FEATURE_LEVELs in the array pFeatureLevels. Specify 0 if you specified null for the
previous parameter pFeatureLevels.

7. SDKVersion: Always specify D3D11_SDK_VERSION.
8. ppDevice: Returns the created device.
9. pFeatureLevel: Returns the first supported feature level in the pFeatureLevels array (or the greatest feature level supported, if
pFeatureLevels was null).
10. ppImmediateContext: Returns the created device context

UINT createDeviceFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

D3D_FEATURE_LEVEL featureLevel;
ID3D11Device* md3dDevice;
ID3D11DeviceContext* md3dImmediateContext;
    HRESULT hr = D3D11CreateDevice(
    0, // default adapter
    D3D_DRIVER_TYPE_HARDWARE,
    0, // no software device
    createDeviceFlags,
    0, 0, // default feature level array
    D3D11_SDK_VERSION,
    & md3dDevice,
    & featureLevel,
    & md3dImmediateContext); 

if( FAILED(hr) )
{
  MessageBox(0, L"D3D11CreateDevice Failed.", 0, 0);
  return false;
}

 

if( featureLevel != D3D_FEATURE_LEVEL_11_0 )
{
  MessageBox(0, L"Direct3D Feature Level 11 unsupported.", 0, 0);
  return false;
}

 

Check 4X MSAA Quality Support

UINT m4xMsaaQuality;
HR(md3dDevice->CheckMultisampleQualityLevels(
    DXGI_FORMAT_R8G8B8A8_UNORM, 4, & m4xMsaaQuality));
assert(m4xMsaaQuality > 0 );    

Describe the Swap Chain

typedef struct DXGI_SWAP_CHAIN_DESC {
    DXGI_MODE_DESC BufferDesc;
    DXGI_SAMPLE_DESC SampleDesc;
    DXGI_USAGE BufferUsage;
    UINT BufferCount;
    HWND OutputWindow;
    BOOL Windowed;
    DXGI_SWAP_EFFECT SwapEffect;
    UINT Flags;
} DXGI_SWAP_CHAIN_DESC;

typedef struct DXGI_MODE_DESC
{
  UINT Width; // desired back buffer width
  UINT Height; // desired back buffer height
  DXGI_RATIONAL RefreshRate; // display mode refresh rate
  DXGI_FORMAT Format; // back buffer pixel format
  DXGI_MODE_SCANLINE_ORDER ScanlineOrdering; // display scanline mode
  DXGI_MODE_SCALING Scaling; // display scaling mode
} DXGI_MODE_DESC;

 

1. BufferDesc: This structure describes the properties of the back buffer we want to create. The main properties we are concerned
with are the width and height, and pixel format; see the SDK documentation for further details on the other members.
2. SampleDesc: The number of multisamples and quality level; see §4.1.8.
3. BufferUsage: Specify DXGI_USAGE_RENDER_TARGET_OUTPUT because we are going to be rendering to the back buffer (i.e.,
use it as a render target).
4. BufferCount: The number of back buffers to use in the swap chain; we usually only use one back buffer for double buffering,
although you could use two for triple buffering.
5. OutputWindow: A handle to the window we are rendering into.
6. Windowed: Specify true to run in windowed mode or false for full-screen mode.
7. SwapEffect: Specify DXGI_SWAP_EFFECT_DISCARD in order to let the display driver select the most efficient presentation
method.
8. Flags: Optional flags. If you specify DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH, then when the application is
switching to full-screen mode, it will choose a display mode that best matches the current back buffer settings. If this flag is not
specified, then when the application is switching to full-screen mode, it will use the current desktop display mode. In our sample
framework, we do not specify this flag, as using the current desktop display mode in full-screen mode works fine for our demos
(most desktop displays are set to the optimal resolution of the monitor).

DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = mClientWidth; // use window's client area dims
sd.BufferDesc.Height = mClientHeight;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

// Use 4X MSAA?
if( mEnable4xMsaa )
{
  sd.SampleDesc.Count = 4;
// m4xMsaaQuality is returned via CheckMultisampleQualityLevels().
  sd.SampleDesc.Quality = m4xMsaaQuality-1;
}

else
{
  sd.SampleDesc.Count = 1;
  sd.SampleDesc.Quality = 0;
}

 

sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = mhMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;

Create the Swap Chain

HRESULT IDXGIFactory::CreateSwapChain(
    IUnknown *pDevice, // Pointer to ID3D11Device.
    DXGI_SWAP_CHAIN_DESC *pDesc, // Pointer to swap chain description.
    IDXGISwapChain **ppSwapChain); // Returns created swap chain interface.

我们如何获取IDXGIFactory指针来创建?然而要先查询这个instance

IDXGIDevice* dxgiDevice = 0;
HR(md3dDevice->QueryInterface(__uuidof(IDXGIDevice),
    (void**)&dxgiDevice));
IDXGIAdapter* dxgiAdapter = 0;
HR(dxgiDevice->GetParent(__uuidof(IDXGIAdapter),
    (void**))&dxgiAdapter));
// Finally got the IDXGIFactory interface.
IDXGIFactory* dxgiFactory = 0;
HR(dxgiAdapter->GetParent(__uuidof(IDXGIFactory),
    (void**))&dxgiFactory));
// Now, create the swap chain.
IDXGISwapChain* mSwapChain;
HR(dxgiFactory->CreateSwapChain(md3dDevice, )&sd, )&mSwapChain));
// Release our acquired COM interfaces (because we are done with them).
ReleaseCOM(dxgiDevice);
ReleaseCOM(dxgiAdapter);
ReleaseCOM(dxgiFactory);

DXGI (DirectX Graphics Infrastructure) is a separate API from Direct3D that handles graphics related things like
the swap chain, enumerating graphics hardware, and switching between windowed and full-screen mode

Create the Render Target View

ID3D11RenderTargetView* mRenderTargetView;
ID3D11Texture2D* backBuffer;
mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
  reinterpret_cast<void**>(&backBuffer));
md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView);
ReleaseCOM(backBuffer);

IDXGISwapChain::GetBuffer增加了back buffer COM引用计数,所以我们要ReleaseCOM

Create the Depth/Stencil Buffer and View

typedef struct D3D11_TEXTURE2D_DESC {
    UINT Width;
    UINT Height;
    UINT MipLevels;
    UINT ArraySize;
    DXGI_FORMAT Format;
    DXGI_SAMPLE_DESC SampleDesc;
    D3D11_USAGE Usage;
    UINT BindFlags;
    UINT CPUAccessFlags;
    UINT MiscFlags;
} D3D11_TEXTURE2D_DESC;

1. Width: The width of the texture in texels.
2. Height: The height of the texture in texels.
3. MipLevels: The number of mipmap levels. 
4. ArraySize: The number of textures in a texture array. For the depth/stencil buffer, we only need one texture.
5. Format: A member of the DXGI_FORMAT enumerated type specifying the format of the texels. For a depth/stencil buffer, this
needs to be one of the formats shown in §4.1.5.
6. SampleDesc: The number of multisamples and quality level; 
7. Usage: A member of the D3D11_USAGE enumerated type specifying how the texture will be used

D3D11_USAGE_DEFAULT:

Specify this usage if the GPU (graphics processing unit) will be reading and writing to the resource. The
CPU cannot read or write to a resource with this usage. For the depth/stencil buffer, we specify D3D11_USAGE_DEFAULT because
the GPU will be doing all the reading and writing to the depth/stencil buffer

D3D11_USAGE_IMMUTABLE:

Specify this usage if the contents of a resource does not ever change after creation. This allows for
some potential optimizations, as the resource will be read-only by the GPU. The CPU and GPU cannot write to an immutable
resource, except at creation time to initialize the resource.

D3D11_USAGE_DYNAMIC: Specify this usage if the application (CPU) needs to update the data contents of the resource frequently
(e.g., on a per frame basis). A resource with this usage can be read by the GPU and written to by the CPU. Updating a GPU
resource dynamically from the CPU incurs a performance hit, as the new data must be transferred over from CPU memory (i.e.,
system RAM) to GPU memory (i.e., video RAM); therefore, dynamic usage should be avoided unless necessary.

D3D11_USAGE_STAGING: Specify this usage if the application (CPU) needs to be able to read a copy of the resource (i.e., the
resource supports copying data from video memory to system memory). Copying from GPU to CPU memory is a slow operation and
should be avoided unless necessary.

8. BindFlags:

For a depth/stencil
buffer, this needs to be D3D11_BIND_DEPTH_STENCIL.

D3D11_BIND_RENDER_TARGET: The texture will be bound as a render target to the pipeline.
D3D11_BIND_SHADER_RESOURCE: The texture will be bound as a shader resource to the pipeline

9. CPUAccessFlags: Specifies how the CPU will access the resource. If the CPU needs to write to the resource, specify
D3D11_CPU_ACCESS_WRITE. A resource with write access must have usage D3D11_USAGE_DYNAMIC or
D3D11_USAGE_STAGING. If the CPU needs to read from the buffer, specify D3D11_CPU_ACCESS_READ. A buffer with read
access must have usage D3D11_USAGE_STAGING. For the depth/stencil buffer, only the GPU writes and reads to the
depth/buffer; therefore, we can specify zero for this value, as the CPU will not be reading or writing to the depth/stencil buffer.

10. MiscFlags: Optional flags, which do not apply to the depth/stencil buffer, so are set to zero.

D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Height = mClientHeight;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
// Use 4X MSAA? --must match swap chain MSAA values.
if( mEnable4xMsaa )
{
    depthStencilDesc.SampleDesc.Count = 4;
    depthStencilDesc.SampleDesc.Quality = m4xMsaaQuality-1;
}/
/ No MSAA
else
{
    depthStencilDesc.SampleDesc.Count = 1;
    depthStencilDesc.SampleDesc.Quality = 0;
}
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
ID3D11Texture2D* mDepthStencilBuffer;
ID3D11DepthStencilView* mDepthStencilView;
HR(md3dDevice->CreateTexture2D(
  &depthStencilDesc, // Description of texture to create.
  0,
  &mDepthStencilBuffer)); // Return pointer to depth/stencil buffer. HR(md3dDevice->CreateDepthStencilView(   mDepthStencilBuffer, // Resource we want to create a view to.   0,   &mDepthStencilView)); // Return depth/stencil view

Bind the Views to the Output Merger Stage

md3dImmediateContext->OMSetRenderTargets(
    1, &mRenderTargetView, mDepthStencilView);

参数1:number of render targets we are binding

参数2:pointer to the first element in an array of render target view pointers to bind to the pipeline

参数3:pointer to the depth/stencil view to bind to the pipeline

 

Set the Viewporttypedef struct D3D11_VIEWPORT {

typedef struct D3D11_VIEWPORT {
FLOAT TopLeftX; FLOAT TopLeftY; FLOAT Width; FLOAT Height; FLOAT MinDepth; FLOAT MaxDepth; } D3D11_VIEWPORT;


D3D11_VIEWPORT vp;
vp.TopLeftX = 0.0f;
vp.TopLeftY = 0.0f;
vp.Width = static_cast<float>(mClientWidth);
vp.Height = static_cast<float>(mClientHeight);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
md3dImmediateContext->RSSetViewports(1, &vp);

 

posted @ 2015-07-10 00:45  W.Heisenberg  阅读(447)  评论(0编辑  收藏  举报