diff --git a/README.md b/README.md index 9caf753..cfcac2b 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,4 @@ Following tutorials and documentation to learn the basics of the directX graphic ## Resources Used -[github.com/Microsoft/DirectXTK12](https://github.com/microsoft/DirectXTK12/wiki/The-basic-game-loop) - +[3dgep.com](https://www.3dgep.com/learning-directx-12-1/#Introduction) diff --git a/premake5.lua b/premake5.lua index ecc92a8..2e82f32 100644 --- a/premake5.lua +++ b/premake5.lua @@ -7,7 +7,7 @@ project "LearnDirectX" targetdir "bin/%{cfg.buildcfg}" architecture "x64" - links {"glfw3", "d3d9"} + links {"glfw3", "d3d12", "dxgi"} libdirs{ "vendor/GLFW/lib"} includedirs {"vendor/GLFW/include"} diff --git a/src/main.cpp b/src/main.cpp index 176edab..ac6f9ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,48 +1,158 @@ #include #include +#include + #define GLFW_EXPOSE_NATIVE_WIN32 #include "GLFW/glfw3.h" #include "GLFW/glfw3native.h" -#include -LPDIRECT3D9 d3d; // pointer to our Direct3D interface -LPDIRECT3DDEVICE9 d3ddev; // pointer to the device class -void initD3D(HWND hWnd) { - d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface +// DirectX headers +#include +#include +#include +#include +#include - D3DPRESENT_PARAMETERS d3dpp; // create the strcut to hold device info +using namespace Microsoft::WRL; - ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear the struct - d3dpp.Windowed = TRUE; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = hWnd; - - // create a device class using the information gathered - d3d->CreateDevice(D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - hWnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, - &d3dpp, - &d3ddev); +inline void ThrowIfFailed(HRESULT hr) { + if (FAILED(hr)) { + throw std::exception(); + } } +const uint8_t NumFrames = 3; +bool UseWarp = false; +bool IsInitialized = false; -void render_frame() { - d3ddev->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); - d3ddev->BeginScene(); - // do 3D rendering - d3ddev->EndScene(); +ComPtr Device; +ComPtr CommandQueue; +ComPtr SwapChain; +ComPtr backbuffer[NumFrames]; +ComPtr CommandList; +ComPtr CommandAllocator[NumFrames]; +// RTV stands for Render Target View +// A descriptor describes a resource +ComPtr RTVDescriptorHeap; +UINT RTVDescriptorSize; +UINT CurrentBackBufferIndex; - d3ddev->Present(NULL, NULL, NULL, NULL); +// Synchronization objects +ComPtr Fence; +uint64_t FenceValue; +uint64_t FrameFenceValues[NumFrames] = {}; +HANDLE FenceEvent; + +bool Vsync = true; +bool TearingSupported = false; + +bool fullscreen = false; + + +void EnableDebugLayer() { +#ifdef DEBUG + ComPtr debugInterface; + ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface))); + debugInterface->EnableDebugLayer(); +#endif } -void cleanD3D() { - d3ddev->Release(); - d3d->Release(); +// Query DirectX12 adapter +ComPtr GetAdapter(bool useWarp) { + ComPtr dxgiFactory; + + UINT createFactoryFlags = 0; +#ifdef DEBUG + createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG; +#endif + + ThrowIfFailed(CreateDXGIFactory2(createFactoryFlags, IID_PPV_ARGS(&dxgiFactory))); + + ComPtr dxgiAdapter1; + ComPtr dxgiAdapter4; + + if (useWarp) { + ThrowIfFailed(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&dxgiAdapter1))); + ThrowIfFailed(dxgiAdapter1.As(&dxgiAdapter4)); + } + else { + SIZE_T maxDedicatedVideoMemory = 0; + for (UINT i = 0; dxgiFactory->EnumAdapters1(i, &dxgiAdapter1) != DXGI_ERROR_NOT_FOUND; ++i) { + DXGI_ADAPTER_DESC1 dxgiAdapterDesc1; + dxgiAdapter1->GetDesc1(&dxgiAdapterDesc1); + + + // check if the device can create D3D12 device + // The Adapter with the largest video memory is favored + + if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 && SUCCEEDED(D3D12CreateDevice(dxgiAdapter1.Get(), + D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr)) && dxgiAdapterDesc1.DedicatedVideoMemory > maxDedicatedVideoMemory) { + maxDedicatedVideoMemory = dxgiAdapterDesc1.DedicatedVideoMemory; + ThrowIfFailed(dxgiAdapter1.As(&dxgiAdapter4)); + } + + } + } + + return dxgiAdapter4; } +ComPtr CreateDevice(ComPtr adapter) { + ComPtr d3d12Device2; + ThrowIfFailed(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12Device2))); +#ifdef DEBUG +// Enable Debug message + ComPtr InfoQueue; + if (SUCCEEDED(d3d12Device2.As(&InfoQueue))) { + InfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE); + InfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE); + InfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE); + + + // Suppress whole Categories and severities of messsage + D3D12_MESSAGE_SEVERITY Severities[] = { + D3D12_MESSAGE_SEVERITY_INFO + }; + + // Suppress message by their ID + D3D12_MESSAGE_ID DenyIds[] = { + D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE, + D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, + D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE + }; + + D3D12_INFO_QUEUE_FILTER newfilter = {}; + + newfilter.DenyList.NumSeverities = _countof(Severities); + newfilter.DenyList.pSeverityList = Severities; + newfilter.DenyList.NumIDs = _countof(DenyIds); + newfilter.DenyList.pIDList = DenyIds; + + ThrowIfFailed(InfoQueue->PushStorageFilter(&newfilter)); + + } +#endif + + return d3d12Device2; +} + +ComPtr CreateCommandQueue(ComPtr device, D3D12_COMMAND_LIST_TYPE type) { + ComPtr d3d12CommandQueue; + + D3D12_COMMAND_QUEUE_DESC desc = {}; + + desc.Type = type; + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.NodeMask = 0; + + ThrowIfFailed(device->CreateCommandQueue(&desc, IID_PPV_ARGS(&d3d12CommandQueue))); + + return d3d12CommandQueue; +} + void error_callback(int code , const char* description) { std::cerr << description << std::endl; } @@ -67,22 +177,22 @@ int main ( int argc , char** argv){ return -1; } - HWND NativeWindowHandle = glfwGetWin32Window(window); - - initD3D(NativeWindowHandle); + EnableDebugLayer(); + auto adapter = GetAdapter(UseWarp); + auto device = CreateDevice(adapter); + auto commandQueue = CreateCommandQueue(device, D3D12_COMMAND_LIST_TYPE_DIRECT); while (!glfwWindowShouldClose(window)) { - render_frame(); + glfwPollEvents(); } - cleanD3D(); glfwTerminate();