RRRella

D3D12Core implementation

Jan 27th, 2021 (edited)
70
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "hzpch.h"
  2. #include "DirectX12Core.h"
  3. namespace Hazel
  4. {
  5.     D3D12Core* D3D12Core::s_Instance = nullptr;
  6.     D3D12Core::D3D12Core()
  7.     {
  8. #ifdef HZ_DEBUG
  9.         ComPtr<ID3D12Debug> debugInterface;
  10.         D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface));
  11.         debugInterface->EnableDebugLayer();
  12. #endif
  13.         m_Device = CreateDevice(m_UseWarp);
  14.         m_DirectCommandQueue = CreateRef<CommandQueue>(m_Device, D3D12_COMMAND_LIST_TYPE_DIRECT);
  15.         m_ComputeCommandQueue = CreateRef<CommandQueue>(m_Device, D3D12_COMMAND_LIST_TYPE_COMPUTE);
  16.         m_CopyCommandQueue = CreateRef<CommandQueue>(m_Device, D3D12_COMMAND_LIST_TYPE_COPY);
  17.     }
  18.     Ref<CommandQueue> D3D12Core::GetCommandQueue(D3D12_COMMAND_LIST_TYPE type)
  19.     {
  20.         Ref<CommandQueue> commandQueue;
  21.         switch (type)
  22.         {
  23.         case D3D12_COMMAND_LIST_TYPE_DIRECT:
  24.             commandQueue = m_DirectCommandQueue;
  25.             break;
  26.         case D3D12_COMMAND_LIST_TYPE_COMPUTE:
  27.             commandQueue = m_ComputeCommandQueue;
  28.             break;
  29.         case D3D12_COMMAND_LIST_TYPE_COPY:
  30.             commandQueue = m_CopyCommandQueue;
  31.             break;
  32.         default:
  33.             assert(false && "Invalid command queue type.");
  34.         }
  35.         return commandQueue;
  36.     }
  37.     ComPtr<ID3D12Device2> D3D12Core::CreateDevice(bool bUseWarp)
  38.     {
  39.         ComPtr<IDXGIFactory4> dxgiFactory;
  40.         UINT createFactoryFlags = 0;
  41. #if defined(_DEBUG)
  42.         createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG;
  43. #endif
  44.         CreateDXGIFactory2(createFactoryFlags, IID_PPV_ARGS(&dxgiFactory));
  45.         ComPtr<IDXGIAdapter1> dxgiAdapter1;
  46.         ComPtr<IDXGIAdapter4> dxgiAdapter4;
  47.         if (bUseWarp)
  48.         {
  49.             dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&dxgiAdapter1));
  50.             dxgiAdapter1.As(&dxgiAdapter4);
  51.         }
  52.         else
  53.         {
  54.             SIZE_T maxDedicatedVideoMemory = 0;
  55.             for (UINT i = 0; dxgiFactory->EnumAdapters1(i, &dxgiAdapter1) != DXGI_ERROR_NOT_FOUND; ++i)
  56.             {
  57.                 DXGI_ADAPTER_DESC1 dxgiAdapterDesc1;
  58.                 dxgiAdapter1->GetDesc1(&dxgiAdapterDesc1);
  59.                 if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 &&
  60.                     SUCCEEDED(D3D12CreateDevice(dxgiAdapter1.Get(),
  61.                         D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr)) &&
  62.                     dxgiAdapterDesc1.DedicatedVideoMemory > maxDedicatedVideoMemory)
  63.                 {
  64.                     maxDedicatedVideoMemory = dxgiAdapterDesc1.DedicatedVideoMemory;
  65.                     dxgiAdapter1.As(&dxgiAdapter4);
  66.                 }
  67.             }
  68.         }
  69.         ComPtr<ID3D12Device2> D3DDevice;
  70.         D3D12CreateDevice(dxgiAdapter4.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&D3DDevice));
  71.         #if defined(_DEBUG)
  72.         ComPtr<ID3D12InfoQueue> pInfoQueue;
  73.         if (SUCCEEDED(D3DDevice.As(&pInfoQueue)))
  74.         {
  75.             pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
  76.             pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
  77.             pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
  78.             D3D12_MESSAGE_SEVERITY Severities[] =
  79.             {
  80.                 D3D12_MESSAGE_SEVERITY_INFO
  81.             };
  82.             D3D12_MESSAGE_ID DenyIds[] = {
  83.                 D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,   // I'm really not sure how to avoid this message.
  84.                 D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE,                         // This warning occurs when using capture frame while graphics debugging.
  85.                 D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE,                       // This warning occurs when using capture frame while graphics debugging.
  86.             };
  87.             D3D12_INFO_QUEUE_FILTER NewFilter = {};
  88.             NewFilter.DenyList.NumSeverities = _countof(Severities);
  89.             NewFilter.DenyList.pSeverityList = Severities;
  90.             NewFilter.DenyList.NumIDs = _countof(DenyIds);
  91.             NewFilter.DenyList.pIDList = DenyIds;
  92.             pInfoQueue->PushStorageFilter(&NewFilter);
  93.         }
  94. #endif
  95.         return D3DDevice;
  96.     }
  97.     ComPtr<ID3D12DescriptorHeap> D3D12Core::CreateDescriptorHeap(UINT numDescriptors, D3D12_DESCRIPTOR_HEAP_TYPE type)
  98.     {
  99.         D3D12_DESCRIPTOR_HEAP_DESC desc = {};
  100.         desc.Type = type;
  101.         desc.NumDescriptors = numDescriptors;
  102.         desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  103.         desc.NodeMask = 0;
  104.         ComPtr<ID3D12DescriptorHeap> descriptorHeap;
  105.         m_Device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&descriptorHeap));
  106.         return descriptorHeap;
  107.     }
  108.     ComPtr<IDXGISwapChain4> D3D12Core::CreateSwapChain(HWND windowHandle,ComPtr<ID3D12CommandQueue> commandqueue, uint32_t width, uint32_t height)
  109.     {
  110.         ComPtr<IDXGISwapChain4> dxgiSwapChain4;
  111.         ComPtr<IDXGIFactory4> dxgiFactory4;
  112.         UINT createFactoryFlags = 0;
  113. #if defined(_DEBUG)
  114.         createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG;
  115. #endif
  116.         CreateDXGIFactory2(createFactoryFlags, IID_PPV_ARGS(&dxgiFactory4));
  117.         DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
  118.         swapChainDesc.Width = width;
  119.         swapChainDesc.Height = height;
  120.         swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  121.         swapChainDesc.Stereo = FALSE;
  122.         swapChainDesc.SampleDesc = { 1, 0 };
  123.         swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  124.         swapChainDesc.BufferCount = m_BufferCount;
  125.         swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
  126.         swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
  127.         swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
  128.         swapChainDesc.Flags = CheckTearingSupport() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
  129.         ComPtr<IDXGISwapChain1> swapChain1;
  130.         dxgiFactory4->CreateSwapChainForHwnd(commandqueue.Get(), windowHandle, &swapChainDesc, nullptr, nullptr, &swapChain1);
  131.         dxgiFactory4->MakeWindowAssociation(windowHandle, DXGI_MWA_NO_ALT_ENTER);
  132.         swapChain1.As(&dxgiSwapChain4);
  133.         return dxgiSwapChain4;
  134.     }
  135.     void D3D12Core::UpdateRenderTargetViews(ComPtr<IDXGISwapChain4> swapChain, ComPtr<ID3D12DescriptorHeap> descriptorHeap)
  136.     {
  137.         auto rtvDescriptorSize = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
  138.  
  139.         CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(descriptorHeap->GetCPUDescriptorHandleForHeapStart());
  140.  
  141.         for (int i = 0; i < m_BufferCount; ++i)
  142.         {
  143.             ComPtr<ID3D12Resource> BackBuffer;
  144.             swapChain->GetBuffer(i, IID_PPV_ARGS(&BackBuffer));
  145.  
  146.             m_Device->CreateRenderTargetView(BackBuffer.Get(), nullptr, rtvHandle);
  147.  
  148.             m_BackBuffers[i] = BackBuffer;
  149.  
  150.             rtvHandle.Offset(rtvDescriptorSize);
  151.         }
  152.     }
  153.     bool D3D12Core::CheckTearingSupport()
  154.     {
  155.         BOOL allowTearing = FALSE;
  156.         ComPtr<IDXGIFactory4> factory4;
  157.         if (SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory4))))
  158.         {
  159.             ComPtr<IDXGIFactory5> factory5;
  160.             if (SUCCEEDED(factory4.As(&factory5)))
  161.             {
  162.                 if (FAILED(factory5->CheckFeatureSupport(
  163.                     DXGI_FEATURE_PRESENT_ALLOW_TEARING,
  164.                     &allowTearing, sizeof(allowTearing))))
  165.                 {
  166.                     allowTearing = FALSE;
  167.                 }
  168.             }
  169.         }
  170.         return allowTearing == TRUE;
  171.     }
  172.     void D3D12Core::ParseCommandLineArguments()
  173.     {
  174.         int argc;
  175.         wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
  176.         for (size_t i = 0; i < argc; ++i)
  177.         {
  178.             if (::wcscmp(argv[i], L"-w") == 0 || ::wcscmp(argv[i], L"--width") == 0)
  179.             {
  180.                 m_ClientWidth = ::wcstol(argv[++i], nullptr, 10);
  181.             }
  182.             if (::wcscmp(argv[i], L"-h") == 0 || ::wcscmp(argv[i], L"--height") == 0)
  183.             {
  184.                 m_ClientHeight = ::wcstol(argv[++i], nullptr, 10);
  185.             }
  186.             if (::wcscmp(argv[i], L"-warp") == 0 || ::wcscmp(argv[i], L"--warp") == 0)
  187.             {
  188.                 m_UseWarp = true;
  189.             }
  190.         }
  191.         ::LocalFree(argv);
  192.     }
RAW Paste Data