代码和例子的下载路径:http://pan.baidu.com/s/1ntFPXhv
联系方式:[email protected]
这篇博文来介绍DX的初始化,并封装成MDxKernel模块。
MDxKernel模块非常简单,类似于一个工厂模式,其中MDxKernel和DX是对外导出的接口和类。
该模块中最重要的是MDxKernelImp类的实现
1)创建和设备无关的的资源:
创建DirectWrite,WIC,Direct2D相对应的工厂对象。
// These are the resources required independent of the device.
void MDxKernelImp::CreateDeviceIndependentResources()
{
D2D1_FACTORY_OPTIONS options;
ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
#if defined(_DEBUG)
// If the project is in a debug build, enable Direct2D debugging via SDK Layers.
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif
DX::ThrowIfFailed(
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
//D2D1_FACTORY_TYPE_MULTI_THREADED,
__uuidof(ID2D1Factory1),
&options,
&m_d2dFactory
)
);
DX::ThrowIfFailed(
DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory1),
&m_dwriteFactory
)
);
/*
DX::ThrowIfFailed(
CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_wicFactory)
)
);
*/
DX::ThrowIfFailed(
CoCreateInstance(
CLSID_WICImagingFactory,
NULL,CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(void **)&m_wicFactory
)
);
}
创建Direct3D和DXGI的设备
// These are the resources that depend on the device.
void MDxKernelImp::CreateDeviceResources()
{
// This flag adds support for surfaces with a different color channel ordering
// than the API default. It is required for compatibility with Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
ComPtr dxgiDevice;
#if defined(_DEBUG)
if (DX::SdkLayersAvailable())
{
// If the project is in a debug build, enable debugging via SDK Layers with this flag.
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
}
#endif
// This array defines the set of DirectX hardware feature levels this app will support.
// Note the ordering should be preserved.
// Don't forget to declare your application's minimum required feature level in its
// description. All applications are assumed to support 9.1 unless otherwise stated.
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
// Create the Direct3D 11 API device object and a corresponding context.
ComPtr device;
ComPtr context;
DX::ThrowIfFailed(
D3D11CreateDevice(
nullptr, // Specify nullptr to use the default adapter.
D3D_DRIVER_TYPE_HARDWARE,
0,
creationFlags, // Set debug and Direct2D compatibility flags.
featureLevels, // List of feature levels this app can support.
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
&device, // Returns the Direct3D device created.
&m_featureLevel, // Returns feature level of device created.
&context // Returns the device immediate context.
)
);
// Get the Direct3D 11.1 API device and context interfaces.
DX::ThrowIfFailed(
device.As(&m_d3dDevice)
);
DX::ThrowIfFailed(
context.As(&m_d3dContext)
);
// Get the underlying DXGI device of the Direct3D device.
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
// Create the Direct2D device object and a corresponding context.
DX::ThrowIfFailed(
m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
);
DX::ThrowIfFailed(
m_d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&m_d2dContext
)
);
}
创建交换链,
通过DXGI,将交换链和窗口句柄进行绑定。
// Allocate all memory resources that change on a window SizeChanged event.
void MDxKernelImp::CreateWindowSizeDependentResources()
{
// Store the window bounds so the next time we get a SizeChanged event we can
// avoid rebuilding everything if the size is identical.
//m_windowBounds = m_window->Bounds;
HRESULT hr=S_OK;
if (m_swapChain != nullptr)
{
// If the swap chain already exists, resize it.
HRESULT hr = m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0);
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
// If the device was removed for any reason, a new device and swapchain will need to be created.
HandleDeviceLost();
// Everything is set up now. Do not continue execution of this method.
return;
}
else
{
DX::ThrowIfFailed(hr);
}
}
else
{
// Otherwise, create a new one using the same adapter as the existing Direct3D device.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = 0; // Use automatic sizing.
swapChainDesc.Height = 0;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
//swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
//swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
//swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
swapChainDesc.Flags = 0;
ComPtr dxgiDevice;
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
ComPtr dxgiAdapter;
DX::ThrowIfFailed(
dxgiDevice->GetAdapter(&dxgiAdapter)
);
ComPtr dxgiFactory;
DX::ThrowIfFailed(
dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
);
// CoreWindow^ window = m_window.Get();
// DX::ThrowIfFailed(
// dxgiFactory->CreateSwapChainForCoreWindow(
// m_d3dDevice.Get(),
// reinterpret_cast(window),
// &swapChainDesc,
// nullptr,
// &m_swapChain
// )
// );
/*DX::ThrowIfFailed(*/
hr = dxgiFactory->CreateSwapChainForHwnd(
m_d3dDevice.Get(),
m_hWnd,
&swapChainDesc,
nullptr,
nullptr,
&m_swapChain
);
//);
// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
// ensures that the application will only render after each VSync, minimizing power consumption.
DX::ThrowIfFailed(
dxgiDevice->SetMaximumFrameLatency(1)
);
}
// Create a Direct3D render target view of the swap chain back buffer.
ComPtr backBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
);
DX::ThrowIfFailed(
m_d3dDevice->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&m_d3dRenderTargetView
)
);
// Cache the rendertarget dimensions in our helper class for convenient use.
D3D11_TEXTURE2D_DESC backBufferDesc = {0};
backBuffer->GetDesc(&backBufferDesc);
m_renderTargetSize.cx = backBufferDesc.Width;
m_renderTargetSize.cy = backBufferDesc.Height;
// Create a depth stencil view for use with 3D rendering if needed.
CD3D11_TEXTURE2D_DESC depthStencilDesc(
DXGI_FORMAT_D24_UNORM_S8_UINT,
backBufferDesc.Width,
backBufferDesc.Height,
1,
1,
D3D11_BIND_DEPTH_STENCIL
);
ComPtr depthStencil;
DX::ThrowIfFailed(
m_d3dDevice->CreateTexture2D(
&depthStencilDesc,
nullptr,
&depthStencil
)
);
auto viewDesc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D);
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilView(
depthStencil.Get(),
&viewDesc,
&m_d3dDepthStencilView
)
);
// Set the 3D rendering viewport to target the entire window.
CD3D11_VIEWPORT viewport(
0.0f,
0.0f,
static_cast(backBufferDesc.Width),
static_cast(backBufferDesc.Height)
);
m_d3dContext->RSSetViewports(1, &viewport);
// Create a Direct2D target bitmap associated with the
// swap chain back buffer and set it as the current target.
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
m_dpi,
m_dpi
);
ComPtr dxgiBackBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
);
DX::ThrowIfFailed(
m_d2dContext->CreateBitmapFromDxgiSurface(
dxgiBackBuffer.Get(),
&bitmapProperties,
&m_d2dTargetBitmap
)
);
m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
// Grayscale text anti-aliasing is recommended for all Windows Store apps.
m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
}
// Method to deliver the final image to the display.
void MDxKernelImp::Present(CRect *dtRect)
{
// The application may optionally specify "dirty" or "scroll" rects to improve efficiency
// in certain scenarios. In this sample, however, we do not utilize those features.
DXGI_PRESENT_PARAMETERS parameters = {0};
if(dtRect)
{
parameters.DirtyRectsCount = 1;
parameters.pDirtyRects = dtRect;
}
else
{
parameters.DirtyRectsCount = 0;
parameters.pDirtyRects = nullptr;
}
parameters.pScrollRect = nullptr;
parameters.pScrollOffset = nullptr;
// The first argument instructs DXGI to block until VSync, putting the application
// to sleep until the next VSync. This ensures we don't waste any cycles rendering
// frames that will never be displayed to the screen.
//HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
// Discard the contents of the render target.
// This is a valid operation only when the existing contents will be entirely
// overwritten. If dirty or scroll rects are used, this call should be removed.
// m_d3dContext->DiscardView(m_d3dRenderTargetView.Get());
// Discard the contents of the depth stencil.
// m_d3dContext->DiscardView(m_d3dDepthStencilView.Get());
// If the device was removed either by a disconnect or a driver upgrade, we
// must recreate all device resources.
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
HandleDeviceLost();
}
// else
// {
// DX::ThrowIfFailed(hr);
// }
if (m_windowSizeChangeInProgress)
{
// A window size change has been initiated and the app has just completed presenting
// the first frame with the new size. Notify the resize manager so we can short
// circuit any resize animation and prevent unnecessary delays.
//CoreWindowResizeManager::GetForCurrentView()->NotifyLayoutCompleted();
m_windowSizeChangeInProgress = false;
}
}
这个就不贴代码了。
以上列出了MDxKernel模块的五个重点,完整的封装请查看代码。
其中多处地方参考微软官网和MSDN,在此表示感谢。
代码和例子的下载路径:http://pan.baidu.com/s/1ntFPXhv
联系方式:[email protected]