123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- #include "pch.h"
- #include "Direct3DBase.h"
- using namespace Microsoft::WRL;
- using namespace Windows::UI::Core;
- using namespace Windows::Foundation;
- // Constructor.
- Direct3DBase::Direct3DBase()
- {
- }
- // Initialize the Direct3D resources required to run.
- void Direct3DBase::Initialize(CoreWindow^ window)
- {
- m_window = window;
-
- CreateDeviceResources();
- CreateWindowSizeDependentResources();
- }
- // These are the resources that depend on the device.
- void Direct3DBase::CreateDeviceResources()
- {
- // This flag adds support for surfaces with a different color channel ordering than the API default.
- // It is recommended usage, and is required for compatibility with Direct2D.
- UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
- #if defined(_DEBUG)
- // 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 DX11 API device object, and get a corresponding context.
- ComPtr<ID3D11Device> device;
- ComPtr<ID3D11DeviceContext> context;
- DX::ThrowIfFailed(
- D3D11CreateDevice(
- nullptr, // specify null to use the default adapter
- D3D_DRIVER_TYPE_HARDWARE,
- nullptr, // leave as nullptr unless software device
- creationFlags, // optionally set debug and Direct2D compatibility flags
- featureLevels, // list of feature levels this app can support
- ARRAYSIZE(featureLevels), // number of entries in above list
- D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION
- &device, // returns the Direct3D device created
- &m_featureLevel, // returns feature level of device created
- &context // returns the device immediate context
- )
- );
- // Get the DirectX11.1 device by QI off the DirectX11 one.
- DX::ThrowIfFailed(
- device.As(&m_d3dDevice)
- );
- // And get the corresponding device context in the same way.
- DX::ThrowIfFailed(
- context.As(&m_d3dContext)
- );
- }
- // Allocate all memory resources that change on a window SizeChanged event.
- void Direct3DBase::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;
- // If the swap chain already exists, resize it.
- if(m_swapChain != nullptr)
- {
- DX::ThrowIfFailed(
- m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
- );
- }
- // Otherwise, create a new one.
- else
- {
- // Create a descriptor for the swap chain.
- 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 swapchain 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 two buffers to enable flip effect
- swapChainDesc.Scaling = DXGI_SCALING_NONE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // we recommend using this swap effect for all applications
- swapChainDesc.Flags = 0;
- // Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
- // First, retrieve the underlying DXGI Device from the D3D Device
- ComPtr<IDXGIDevice1> dxgiDevice;
- DX::ThrowIfFailed(
- m_d3dDevice.As(&dxgiDevice)
- );
- // Identify the physical adapter (GPU or card) this device is running on.
- ComPtr<IDXGIAdapter> dxgiAdapter;
- DX::ThrowIfFailed(
- dxgiDevice->GetAdapter(&dxgiAdapter)
- );
- // And obtain the factory object that created it.
- ComPtr<IDXGIFactory2> dxgiFactory;
- DX::ThrowIfFailed(
- dxgiAdapter->GetParent(
- __uuidof(IDXGIFactory2),
- &dxgiFactory
- )
- );
- Windows::UI::Core::CoreWindow^ p = m_window.Get();
- // Create a swap chain for this window from the DXGI factory.
- DX::ThrowIfFailed(
- dxgiFactory->CreateSwapChainForCoreWindow(
- m_d3dDevice.Get(),
- reinterpret_cast<IUnknown*>(p),
- &swapChainDesc,
- nullptr, // allow on all displays
- &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)
- );
- }
-
- // Obtain the backbuffer for this window which will be the final 3D rendertarget.
- ComPtr<ID3D11Texture2D> backBuffer;
- DX::ThrowIfFailed(
- m_swapChain->GetBuffer(
- 0,
- __uuidof(ID3D11Texture2D),
- &backBuffer
- )
- );
- // Create a view interface on the rendertarget to use on bind.
- DX::ThrowIfFailed(
- m_d3dDevice->CreateRenderTargetView(
- backBuffer.Get(),
- nullptr,
- &m_renderTargetView
- )
- );
- // Cache the rendertarget dimensions in our helper class for convenient use.
- D3D11_TEXTURE2D_DESC backBufferDesc;
- backBuffer->GetDesc(&backBufferDesc);
- m_renderTargetSize.Width = static_cast<float>(backBufferDesc.Width);
- m_renderTargetSize.Height = static_cast<float>(backBufferDesc.Height);
- // Create a descriptor for the depth/stencil buffer.
- CD3D11_TEXTURE2D_DESC depthStencilDesc(
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- backBufferDesc.Width,
- backBufferDesc.Height,
- 1,
- 1,
- D3D11_BIND_DEPTH_STENCIL);
- // Allocate a 2-D surface as the depth/stencil buffer.
- ComPtr<ID3D11Texture2D> depthStencil;
- DX::ThrowIfFailed(
- m_d3dDevice->CreateTexture2D(
- &depthStencilDesc,
- nullptr,
- &depthStencil
- )
- );
- // Create a DepthStencil view on this surface to use on bind.
- DX::ThrowIfFailed(
- m_d3dDevice->CreateDepthStencilView(
- depthStencil.Get(),
- &CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D),
- &m_depthStencilView
- )
- );
- // Create a viewport descriptor of the full window size.
- CD3D11_VIEWPORT viewPort(
- 0.0f,
- 0.0f,
- static_cast<float>(backBufferDesc.Width),
- static_cast<float>(backBufferDesc.Height)
- );
-
- // Set the current viewport using the descriptor.
- m_d3dContext->RSSetViewports(1, &viewPort);
- }
- void Direct3DBase::UpdateForWindowSizeChange()
- {
- if (m_window->Bounds.Width != m_windowBounds.Width ||
- m_window->Bounds.Height != m_windowBounds.Height)
- {
- m_renderTargetView = nullptr;
- m_depthStencilView = nullptr;
- CreateWindowSizeDependentResources();
- }
- }
- void Direct3DBase::Present()
- {
- // 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->Present(1, 0);
- // If the device was removed either by a disconnect or a driver upgrade, we
- // must completely reinitialize the renderer.
- if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
- {
- Initialize(m_window.Get());
- }
- else
- {
- DX::ThrowIfFailed(hr);
- }
- }
|