text: ﻿//
  // DeviceResources.h - A wrapper for the Direct3D 12 device and swapchain
  //
  
  #pragma once
  
  #include <dx12pch.h>
  #include <wrl/event.h>
  
  namespace DX
  {
      // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created.
      interface IDeviceNotify
      {
          virtual void OnDeviceLost() = 0;
          virtual void OnDeviceRestored() = 0;
  
      protected:
          ~IDeviceNotify() = default;
      };
  
      // Controls all the DirectX device resources.
      class DeviceResources
      {
      public:
          static const unsigned int c_AllowTearing = 0x1;
          static const unsigned int c_EnableHDR = 0x2;
  
          DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM,
              DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D32_FLOAT,
              UINT backBufferCount = 2,
              D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0,
              unsigned int flags = 0) noexcept(false);
          ~DeviceResources();
  
          void CreateDeviceResources();
          void CreateWindowSizeDependentResources();
          void SetWindow(HWND window, int width, int height);
          bool WindowSizeChanged(int width, int height);
          void HandleDeviceLost();
          void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; }
          void Prepare(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_PRESENT);
          void Present(D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET);
          void WaitForGpu() noexcept;
          void Clear(XMVECTORF32 backgroundColor);
  
          // Device Accessors.
          RECT GetOutputSize() const { return m_outputSize; }
  
          // Direct3D Accessors.
          ID3D12Device*                   GetD3DDevice() const            { return m_d3dDevice.Get(); }
          IDXGISwapChain3*                GetSwapChain() const            { return m_swapChain.Get(); }
          IDXGIFactory4*                  GetDXGIFactory() const          { return m_dxgiFactory.Get(); }
          D3D_FEATURE_LEVEL               GetDeviceFeatureLevel() const   { return m_d3dFeatureLevel; }
          ID3D12Resource*                 GetRenderTarget() const         { return m_renderTargets[m_backBufferIndex].Get(); }
          ID3D12Resource*                 GetDepthStencil() const         { return m_depthStencil.Get(); }
          ID3D12CommandQueue*             GetCommandQueue() const         { return m_commandQueue.Get(); }
          ID3D12CommandAllocator*         GetCommandAllocator() const     { return m_commandAllocators[m_backBufferIndex].Get(); }
          ID3D12GraphicsCommandList*      GetCommandList() const          { return m_commandList.Get(); }
          DXGI_FORMAT                     GetBackBufferFormat() const     { return m_backBufferFormat; }
          DXGI_FORMAT                     GetDepthBufferFormat() const    { return m_depthBufferFormat; }
          D3D12_VIEWPORT                  GetScreenViewport() const       { return m_screenViewport; }
          D3D12_RECT                      GetScissorRect() const          { return m_scissorRect; }
          UINT                            GetCurrentFrameIndex() const    { return m_backBufferIndex; }
          UINT                            GetBackBufferCount() const      { return m_backBufferCount; }
          DXGI_COLOR_SPACE_TYPE           GetColorSpace() const           { return m_colorSpace; }
          unsigned int                    GetDeviceOptions() const        { return m_options; }
          HWND                            GetWindow() const               { return m_window; }
          D3D12_FEATURE_DATA_SHADER_MODEL GetShaderModel() const    { return m_shaderModel; }
  
          CD3DX12_CPU_DESCRIPTOR_HANDLE GetRenderTargetView() const
          {
              return CD3DX12_CPU_DESCRIPTOR_HANDLE(
                  m_rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
                  static_cast<INT>(m_backBufferIndex), m_rtvDescriptorSize);
          }
          CD3DX12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const
          {
              return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
          }
  
      private:
          void MoveToNextFrame();
          void GetAdapter(IDXGIAdapter1** ppAdapter);
          void UpdateColorSpace();
  
          static const size_t MAX_BACK_BUFFER_COUNT = 3;
  
          UINT                                                m_backBufferIndex;
  
          // Direct3D objects.
          Microsoft::WRL::ComPtr<ID3D12Device>                m_d3dDevice;
          Microsoft::WRL::ComPtr<ID3D12CommandQueue>          m_commandQueue;
          Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList>   m_commandList;
          Microsoft::WRL::ComPtr<ID3D12CommandAllocator>      m_commandAllocators[MAX_BACK_BUFFER_COUNT];
  
          // Swap chain objects.
          Microsoft::WRL::ComPtr<IDXGIFactory4>               m_dxgiFactory;
          Microsoft::WRL::ComPtr<IDXGISwapChain3>             m_swapChain;
          Microsoft::WRL::ComPtr<ID3D12Resource>              m_renderTargets[MAX_BACK_BUFFER_COUNT];
          Microsoft::WRL::ComPtr<ID3D12Resource>              m_depthStencil;
  
          // Presentation fence objects.
          Microsoft::WRL::ComPtr<ID3D12Fence>                 m_fence;
          UINT64                                              m_fenceValues[MAX_BACK_BUFFER_COUNT];
          Microsoft::WRL::Wrappers::Event                     m_fenceEvent;
  
          // Direct3D rendering objects.
          Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>        m_rtvDescriptorHeap;
          Microsoft::WRL::ComPtr<ID3D12DescriptorHeap>        m_dsvDescriptorHeap;
          UINT                                                m_rtvDescriptorSize;
          D3D12_VIEWPORT                                      m_screenViewport;
          D3D12_RECT                                          m_scissorRect;
  
          // Direct3D properties.
          DXGI_FORMAT                                         m_backBufferFormat;
          DXGI_FORMAT                                         m_depthBufferFormat;
          UINT                                                m_backBufferCount;
          D3D_FEATURE_LEVEL                                   m_d3dMinFeatureLevel;
  
          // Cached device properties.
          HWND                                                m_window;
          D3D_FEATURE_LEVEL                                   m_d3dFeatureLevel;
          DWORD                                               m_dxgiFactoryFlags;
          RECT                                                m_outputSize;
  
          // HDR Support
          DXGI_COLOR_SPACE_TYPE                               m_colorSpace;
  
          // shader support
          D3D12_FEATURE_DATA_SHADER_MODEL                     m_shaderModel;
  
          // DeviceResources options (see flags above)
          unsigned int                                        m_options;
  
          // The IDeviceNotify can be held directly as it owns the DeviceResources.
          IDeviceNotify* m_deviceNotify;
      };
  }
  