//--------------------------------------------------------------------------
void D3D12RenderWindow::Init(D3D12Renderer& kRenderer) noexcept
{
	if ((!m_kNode.is_attach()) && m_spTargetWindow)
	{
		D3D12_COMMAND_QUEUE_DESC kQueueDesc = {};
		kQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
		kQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
		VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandQueue(&kQueueDesc, IID_PPV_ARGS(&m_pkCommandQueue)), S_OK);
		DXGI_SWAP_CHAIN_DESC kSwapChainDesc = {};
		kSwapChainDesc.BufferCount = D3D12Renderer::FRAME_COUNT;
		kSwapChainDesc.BufferDesc.Width = m_spTargetWindow->GetWidth();
		kSwapChainDesc.BufferDesc.Height = m_spTargetWindow->GetHeight();
		kSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
		kSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
		kSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
		kSwapChainDesc.OutputWindow = (HWND)(m_spTargetWindow->GetNativeHandle());
		kSwapChainDesc.SampleDesc.Count = 1;
		kSwapChainDesc.Windowed = TRUE;
		IDXGISwapChain* pkSwapChain;
		VE_ASSERT_GE(kRenderer.m_pkDXGIFactory->CreateSwapChain(m_pkCommandQueue, &kSwapChainDesc, &pkSwapChain), S_OK);
		VE_ASSERT_GE(pkSwapChain->QueryInterface(IID_PPV_ARGS(&m_pkSwapChain)), S_OK);
		VE_SAFE_RELEASE(pkSwapChain);
		VE_ASSERT(m_pkCommandQueue && m_pkSwapChain);
		for (uint32_t i(0); i < D3D12Renderer::FRAME_COUNT; ++i)
		{
			FrameCache& kFrame = m_akFrameCache[i];
			VE_ASSERT_GE(m_pkSwapChain->GetBuffer(i, IID_PPV_ARGS(&kFrame.m_pkBufferResource)), S_OK);
			kFrame.m_hHandle.ptr = kRenderer.m_kRTVHeap.GetCPUStart().ptr + kRenderer.m_kRTVHeap.Alloc();
			kRenderer.m_pkDevice->CreateRenderTargetView(
				kFrame.m_pkBufferResource, nullptr, kFrame.m_hHandle);
			VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator(
				D3D12_COMMAND_LIST_TYPE_DIRECT,
				IID_PPV_ARGS(&kFrame.m_pkDirectAllocator)), S_OK);
			VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator(
				D3D12_COMMAND_LIST_TYPE_BUNDLE,
				IID_PPV_ARGS(&kFrame.m_pkBundleAllocator)), S_OK);
			kFrame.m_u64FenceValue = 0;

			VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
				kFrame.m_pkDirectAllocator, nullptr, IID_PPV_ARGS(&kFrame.m_pkTestList)), S_OK);
			VE_ASSERT_GE(kFrame.m_pkTestList->Close(), S_OK);
		}

		m_u64FenceValue = 0;
		VE_ASSERT_GE(kRenderer.m_pkDevice->CreateFence(m_u64FenceValue++,
			D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pkFence)), S_OK);
		m_kFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
		VE_ASSERT(m_kFenceEvent);
		const uint64_t u64FenceToWaitFor = m_u64FenceValue++;
		VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, u64FenceToWaitFor), S_OK);
		VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(u64FenceToWaitFor, m_kFenceEvent), S_OK);
		WaitForSingleObject(m_kFenceEvent, INFINITE);
		m_u32FramePtr = m_pkSwapChain->GetCurrentBackBufferIndex();
		m_u64FrameIndex = 0;

		m_spTargetWindow->Show();

		kRenderer.m_kRenderWindowList.attach_back(m_kNode);
	}
}
	std::shared_ptr<IDXGISwapChain3> CreateSwapChain( ID3D12Device * device, ID3D12CommandQueue * commandQueue, const HWND* hWnd, DXGI_SWAP_CHAIN_DESC* swapChainDesc)
	{
		IDXGISwapChain* swapChain;
		IDXGISwapChain3* swapChain3;

		DXGI_SWAP_CHAIN_DESC defaultDesc = {};
		if (!swapChainDesc)
		{
			defaultDesc.BufferCount = 2;
			defaultDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
			defaultDesc.BufferDesc.Width = 1200;
			defaultDesc.BufferDesc.Height = 900;
			defaultDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
			defaultDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
			defaultDesc.OutputWindow = *hWnd;
			defaultDesc.SampleDesc.Count = 1;
			defaultDesc.Windowed = TRUE;
			swapChainDesc = &defaultDesc;
		}

		DirectX::ThrowIfFailed(CreateFactory()->CreateSwapChain(
			commandQueue,
			swapChainDesc,
			&swapChain
			));
		swapChain->QueryInterface(IID_PPV_ARGS(&swapChain3));
		swapChain->Release();
		return std::shared_ptr<IDXGISwapChain3>(swapChain3, ReleaseIUnknown);
	}
void SwapChain::Initialize(HWND outputWindow)
{
    Shutdown();

    // We'll just use the first output for fullscreen
    DX12::Adapter->EnumOutputs(0, &output);

    if(format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
        noSRGBFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
    else if(format == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
        noSRGBFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
    else
        noSRGBFormat = format;

    DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
    swapChainDesc.BufferCount = uint32(NumBackBuffers);
    swapChainDesc.BufferDesc.Width = width;
    swapChainDesc.BufferDesc.Height = height;
    swapChainDesc.BufferDesc.Format = noSRGBFormat;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    swapChainDesc.OutputWindow = outputWindow;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.Windowed = TRUE;
    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH |
                          DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING |
                          DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;

    IDXGISwapChain* tempSwapChain = nullptr;
    DXCall(DX12::Factory->CreateSwapChain(DX12::GfxQueue, &swapChainDesc, &tempSwapChain));
    DXCall(tempSwapChain->QueryInterface(IID_PPV_ARGS(&swapChain)));
    DX12::Release(tempSwapChain);

    backBufferIdx = swapChain->GetCurrentBackBufferIndex();
    waitableObject = swapChain->GetFrameLatencyWaitableObject();

    AfterReset();
}
Beispiel #4
0
HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::QueryInterface(REFIID riid, void **ppvObj)
{
    return m_pSwapChain->QueryInterface(riid, ppvObj);
}
Beispiel #5
0
HRESULT DXManager::CreateSwapChain()
{
	HRESULT hr = S_FALSE;

	DXGI_SWAP_CHAIN_DESC swapChainDesc;
	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));

	// Set the swap chain to use double buffering.
	swapChainDesc.BufferCount = 2;
	// Set the height and width of the back buffers in the swap chain.
	swapChainDesc.BufferDesc.Height = m_WindowHeight;
	swapChainDesc.BufferDesc.Width = m_WindowWidth;
	// Set a regular 32-bit surface for the back buffers.
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	// Set the usage of the back buffers to be render target outputs.
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	// Set the swap effect to discard the previous buffer contents after swapping.
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
	// Set the handle for the window to render to.
	swapChainDesc.OutputWindow = m_hWnd;
	// Set to full screen or windowed mode.
	if (m_FullScreen)
		swapChainDesc.Windowed = false;
	else
		swapChainDesc.Windowed = true;
	// Set the refresh rate of the back buffer.
	if (m_VSYNC)
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = m_Numerator;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = m_Denominator;
	}
	else
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	}
	// Turn multisampling off.
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;
	// Set the scan line ordering and scaling to unspecified.
	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
	// Don't set the advanced flags.
	swapChainDesc.Flags = 0;

	IDXGISwapChain* swapChain;
	ZeroMemory(&swapChain, sizeof(IDXGISwapChain));

	hr = m_Factory->CreateSwapChain(m_CommandQueue, &swapChainDesc, &swapChain);
	if (FAILED(hr))
		return hr;

	hr = swapChain->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&m_SwapChain);
	if (FAILED(hr))
		return hr;

	D3D12_DESCRIPTOR_HEAP_DESC renderTargetViewHeapDesc;
	ZeroMemory(&renderTargetViewHeapDesc, sizeof(D3D12_DESCRIPTOR_HEAP_DESC));

	renderTargetViewHeapDesc.NumDescriptors = 2;
	renderTargetViewHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
	renderTargetViewHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

	hr = m_Device->CreateDescriptorHeap(&renderTargetViewHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&m_RenderTargetViewHeap);
	if (FAILED(hr))
		return hr;

	D3D12_CPU_DESCRIPTOR_HANDLE renderTargetViewHandle;
	ZeroMemory(&renderTargetViewHandle, sizeof(D3D12_CPU_DESCRIPTOR_HANDLE));
	renderTargetViewHandle = m_RenderTargetViewHeap->GetCPUDescriptorHandleForHeapStart();

	unsigned int renderTargetViewDescriptorSize = 0;
	renderTargetViewDescriptorSize = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

	hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D12Resource), (void**)&m_BackBufferRenderTarget[0]);
	if (FAILED(hr))
		return hr;

	m_Device->CreateRenderTargetView(m_BackBufferRenderTarget[0], NULL, renderTargetViewHandle);

	renderTargetViewHandle.ptr += renderTargetViewDescriptorSize;

	hr = m_SwapChain->GetBuffer(1, __uuidof(ID3D12Resource), (void**)&m_BackBufferRenderTarget[1]);
	if (FAILED(hr))
		return hr;

	m_Device->CreateRenderTargetView(m_BackBufferRenderTarget[1], NULL, renderTargetViewHandle);

	m_BufferIndex = m_SwapChain->GetCurrentBackBufferIndex();

	swapChain->Release();

	return hr;
}
Beispiel #6
0
void GraphicsDevice::Init(u32 screenWidth, u32 screenHeight)
{
#define GRAPHICSINIT_ON_FAILED(failCondition, errorMessage, ...) \
	do { \
		if(failCondition) \
		{ \
			Assertf(false, errorMessage, __VA_ARGS__); \
			return; \
		} \
	} while(0)

	HRESULT hr;

#if RECON_DEBUG
	ID3D12Debug* debugInterface;
	hr = D3D12GetDebugInterface(__uuidof(ID3D12Debug), (void**)&debugInterface);
	if(Verifyf(SUCCEEDED(hr), "Failed To Create Graphics Debug Interface! Error Code: '%d'", hr))
	{
		debugInterface->EnableDebugLayer();
	}
#endif // RECON_DEBUG

	hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&m_pDevice);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create D3D12 Device! Error Code: '%d'", hr);

	D3D12_COMMAND_QUEUE_DESC queueDesc = {};
	queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
	queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;

	hr = m_pDevice->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&m_pCommandQueue);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create D3D12 Command Queue! Error Code: '%d'", hr);

	// NOTE:	rasterTek does a bunch of extra stuff here before creating the swap chain
	//			to potentially help performance? But the Directx 12 Samples don't do this.
	//			may want to investigate in the future

	IDXGIFactory4* pFactory = nullptr;
	hr = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create DXGI Factory! Error Code: '%d'", hr);

	HWND hWnd = ((AppWindow_Windows*)AppEntryPoint::GetWindow())->GetWindowHandle();

	DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
	swapChainDesc.BufferCount = ms_FrameCount;
	swapChainDesc.BufferDesc.Width = screenWidth;
	swapChainDesc.BufferDesc.Height = screenHeight;
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
	swapChainDesc.OutputWindow = hWnd;
	swapChainDesc.Windowed = TRUE;

	// Multisampling
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;

	// Flags
	swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;

	IDXGISwapChain* pSwapChain = nullptr;
	hr = pFactory->CreateSwapChain(m_pCommandQueue, &swapChainDesc, &pSwapChain);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create Swap Chain! Error Code: '%d'", hr);

	hr = pSwapChain->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&m_pSwapChain);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create Swap Chain 3! Error Code: '%d'", hr);

	// We're done with the factory
	pFactory->Release();
	pFactory = nullptr;

	m_FrameIndex = m_pSwapChain->GetCurrentBackBufferIndex();


	D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
	rtvHeapDesc.NumDescriptors = ms_FrameCount;
	rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
	rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	hr = m_pDevice->CreateDescriptorHeap(&rtvHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&m_pRTVHeap);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create RTV Descriptor Heap! Error Code: '%d'", hr);

	D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_pRTVHeap->GetCPUDescriptorHandleForHeapStart();
	u32 rtvHeapIncSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

	for(int i = 0; i < ms_FrameCount; ++i)
	{
		hr = m_pSwapChain->GetBuffer(i, __uuidof(ID3D12Resource), (void**)&m_pRenderTargets[i]);
		GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Get RTV (%d) From Swap Chain! Error Code: '%d'", i, hr);

		m_pDevice->CreateRenderTargetView(m_pRenderTargets[i], nullptr, rtvHandle);
		rtvHandle.ptr += rtvHeapIncSize;

		hr = m_pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&m_pCommandAllocators[i]);
		GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create GPU Command Allocator! Error Code: '%d'", i, hr);
	}

	// Will want to move this to another class once multithreaded rendering is supported
	hr = m_pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_pCommandAllocators[0], nullptr, __uuidof(ID3D12GraphicsCommandList), (void**)&m_pGraphicsCommandList);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create GPU Command Allocator! Error Code: '%d'", hr);

	hr = m_pGraphicsCommandList->Close();
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Close Graphics Command List! Error Code: '%d'", hr);

	hr = m_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&m_pRenderFence);
	GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create Render Fence! Error Code: '%d'", hr);

	m_pRenderFenceEvent = CreateEvent(nullptr, false, false, nullptr);
	GRAPHICSINIT_ON_FAILED(m_pRenderFenceEvent == nullptr, "Failed To Create Render Fence Event! Error Code: '%d'", GetLastError());

#undef GRAPHICSINIT_ON_FAILED
}
Beispiel #7
0
bool D3DClass::Initialize(int screenHeight, int screenWidth, HWND hwnd, bool vsync, bool fullscreen)
{
	D3D_FEATURE_LEVEL featureLevel;
	HRESULT result;
	D3D12_COMMAND_QUEUE_DESC commandQueueDesc;
	IDXGIFactory4* factory;
	IDXGIAdapter* adapter;
	IDXGIOutput* adapterOutput;
	unsigned int numModes, i, numerator, denominator, renderTargetViewDescriptorSize;
	unsigned long long stringLength;
	DXGI_MODE_DESC* displayModeList;
	DXGI_ADAPTER_DESC adapterDesc;
	DXGI_SWAP_CHAIN_DESC swapChainDesc;
	IDXGISwapChain* swapChain;
	D3D12_DESCRIPTOR_HEAP_DESC renderTargetViewHeapDesc;
	D3D12_CPU_DESCRIPTOR_HANDLE renderTargetViewHandle;


	// Store the vsync setting.
	m_vsync_enabled = vsync;

	// Set the feature level to DirectX 12.1 to enable using all the DirectX 12 features.
	// Note: Not all cards support full DirectX 12, this feature level may need to be reduced on some cards to 12.0.
	featureLevel = D3D_FEATURE_LEVEL_11_0;

	// Create the Direct3D 12 device.
	result = D3D12CreateDevice(NULL, featureLevel, __uuidof(ID3D12Device), (void**)&m_device);
	if (FAILED(result))
	{
		MessageBox(hwnd, L"Could not create a DirectX 12.1 device.  The default video card does not support DirectX 12.1.", L"DirectX Device Failure", MB_OK);
		return false;
	}

	// Initialize the description of the command queue.
	ZeroMemory(&commandQueueDesc, sizeof(commandQueueDesc));

	// Set up the description of the command queue.
	commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
	commandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
	commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
	commandQueueDesc.NodeMask = 0;

	// Create the command queue.
	m_device->CreateCommandQueue(&commandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&m_commandQueue);

	// Create a DirectX graphics interface factory.
	CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&factory);

	// Use the factory to create an adapter for the primary graphics interface (video card).
	factory->EnumAdapters(0, &adapter);

	// Enumerate the primary adapter output (monitor).
	adapter->EnumOutputs(0, &adapterOutput);


	// Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor).
	adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);

	// Create a list to hold all the possible display modes for this monitor/video card combination.
	displayModeList = new DXGI_MODE_DESC[numModes];

	// Now fill the display mode list structures.
	adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);

	// Now go through all the display modes and find the one that matches the screen height and width.
	// When a match is found store the numerator and denominator of the refresh rate for that monitor.
	for (i = 0; i<numModes; i++)
	{
		if (displayModeList[i].Height == (unsigned int)screenHeight)
		{
			if (displayModeList[i].Width == (unsigned int)screenWidth)
			{
				numerator = displayModeList[i].RefreshRate.Numerator;
				denominator = displayModeList[i].RefreshRate.Denominator;
			}
		}
	}

	// Get the adapter (video card) description.
	adapter->GetDesc(&adapterDesc);

	// Store the dedicated video card memory in megabytes.
	m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024);

	// Convert the name of the video card to a character array and store it.
	wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);

	// Release the display mode list.
	delete[] displayModeList;
	displayModeList = nullptr;

	// Release the adapter output.
	adapterOutput->Release();
	adapterOutput = nullptr;

	// Release the adapter.
	adapter->Release();
	adapter = nullptr;

	// Initialize the swap chain description.
	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));

	// Set the swap chain to use double buffering.
	swapChainDesc.BufferCount = 2;

	// Set the height and width of the back buffers in the swap chain.
	swapChainDesc.BufferDesc.Height = screenHeight;
	swapChainDesc.BufferDesc.Width = screenWidth;

	// Set a regular 32-bit surface for the back buffers.
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

	// Set the usage of the back buffers to be render target outputs.
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

	// Set the swap effect to discard the previous buffer contents after swapping.
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;

	// Set the handle for the window to render to.
	swapChainDesc.OutputWindow = hwnd;

	// Set to full screen or windowed mode.
    swapChainDesc.Windowed = !fullscreen;

	// Set the refresh rate of the back buffer.
	if (m_vsync_enabled)
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;
	}
	else
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	}

	// Turn multisampling off.
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;

	// Set the scan line ordering and scaling to unspecified.
	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

	// Don't set the advanced flags.
	swapChainDesc.Flags = 0;

	// Finally create the swap chain using the swap chain description.	
	factory->CreateSwapChain(m_commandQueue, &swapChainDesc, &swapChain);

	// Next upgrade the IDXGISwapChain to a IDXGISwapChain3 interface and store it in a private member variable named m_swapChain.
	// This will allow us to use the newer functionality such as getting the current back buffer index.
	swapChain->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&m_swapChain);

	// Clear pointer to original swap chain interface since we are using version 3 instead (m_swapChain).
	swapChain = nullptr;

	// Release the factory now that the swap chain has been created.
	factory->Release();
	factory = nullptr;

	// Initialize the render target view heap description for the two back buffers.
	ZeroMemory(&renderTargetViewHeapDesc, sizeof(renderTargetViewHeapDesc));

	// Set the number of descriptors to two for our two back buffers.  Also set the heap tyupe to render target views.
	renderTargetViewHeapDesc.NumDescriptors = 2;
	renderTargetViewHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
	renderTargetViewHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

	// Create the render target view heap for the back buffers.
	m_device->CreateDescriptorHeap(&renderTargetViewHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&m_renderTargetViewHeap);

	// Get a handle to the starting memory location in the render target view heap to identify where the render target views will be located for the two back buffers.
	renderTargetViewHandle = m_renderTargetViewHeap->GetCPUDescriptorHandleForHeapStart();

	// Get the size of the memory location for the render target view descriptors.
	renderTargetViewDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

	// Get a pointer to the first back buffer from the swap chain.
	m_swapChain->GetBuffer(0, __uuidof(ID3D12Resource), (void**)&m_backBufferRenderTarget[0]);

	// Create a render target view for the first back buffer.
	m_device->CreateRenderTargetView(m_backBufferRenderTarget[0], NULL, renderTargetViewHandle);

	// Increment the view handle to the next descriptor location in the render target view heap.
	renderTargetViewHandle.ptr += renderTargetViewDescriptorSize;

	// Get a pointer to the second back buffer from the swap chain.
    m_swapChain->GetBuffer(1, __uuidof(ID3D12Resource), (void**)&m_backBufferRenderTarget[1]);

	// Create a render target view for the second back buffer.
	m_device->CreateRenderTargetView(m_backBufferRenderTarget[1], NULL, renderTargetViewHandle);

	// Finally get the initial index to which buffer is the current back buffer.
	m_bufferIndex = m_swapChain->GetCurrentBackBufferIndex();

	// Create a command allocator.
	m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&m_commandAllocator);

	// Create a fence for GPU synchronization.
	m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&m_fence);

	// Create an event object for the fence.
	m_fenceEvent = CreateEvent(nullptr, false, false, nullptr);

	// Initialize the starting fence value. 
	m_fenceValue = 1;

    CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
    rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

    ID3DBlob* signature;
    ID3DBlob* error;

    D3D12SerializeRootSignature(
        &rootSignatureDesc, 
        D3D_ROOT_SIGNATURE_VERSION_1, 
        &signature, 
        &error);
    m_device->CreateRootSignature(
        0, 
        signature->GetBufferPointer(), 
        signature->GetBufferSize(), 
        IID_PPV_ARGS(&m_rootSignature));

    //Create pipeline state, load and compiler shaders.
    
    //Note here to change D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION for debug
    UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;

    D3DReadFileToBlob(L"DefaultVS.cso", &m_vertexShader);
    D3DReadFileToBlob(L"DefaultHS.cso", &m_hullShader);
    D3DReadFileToBlob(L"DefaultDS.cso", &m_domainShader);
    D3DReadFileToBlob(L"DefaultPS.cso", &m_pixelShader);

    std::array<D3D12_INPUT_ELEMENT_DESC, 2> inputElementDescs = 
    {
        D3D12_INPUT_ELEMENT_DESC{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        D3D12_INPUT_ELEMENT_DESC{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
    };

    D3D12_GRAPHICS_PIPELINE_STATE_DESC pipelineDesc = {};
    pipelineDesc.InputLayout = { inputElementDescs.data() , (UINT)inputElementDescs.size() };
    pipelineDesc.pRootSignature = m_rootSignature;
    pipelineDesc.VS = { m_vertexShader->GetBufferPointer(), m_vertexShader->GetBufferSize() };
    pipelineDesc.PS = { m_pixelShader->GetBufferPointer(), m_pixelShader->GetBufferSize() };
    pipelineDesc.HS = { m_hullShader->GetBufferPointer(), m_hullShader->GetBufferSize() };
    pipelineDesc.DS = { m_domainShader->GetBufferPointer(), m_domainShader->GetBufferSize() };
    pipelineDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT_WIREFRAME);
    pipelineDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
    pipelineDesc.DepthStencilState.DepthEnable = false;
    pipelineDesc.DepthStencilState.StencilEnable = false;
    pipelineDesc.SampleMask = UINT_MAX;
    pipelineDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
    pipelineDesc.NumRenderTargets = 1;
    pipelineDesc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
    pipelineDesc.SampleDesc.Count = 1;
    m_device->CreateGraphicsPipelineState(&pipelineDesc, IID_PPV_ARGS(&m_pipelineState));

    // Create a basic command list.
    m_device->CreateCommandList(
        0, 
        D3D12_COMMAND_LIST_TYPE_DIRECT, 
        m_commandAllocator, 
        m_pipelineState, 
        IID_PPV_ARGS(&m_commandList));

    // Initially we need to close the command list during initialization as it is created in a recording state.
    m_commandList->Close();

    Vertex triangleVertices[] =
    {
        { { 0.0f, 0.5f, 0.f }, { 1.f, 0.f, 0.f, 1.f } },
        { { 0.5f, -0.5f, 0.f },{ 0.f, 1.f, 0.f, 1.f } },
        { { -0.5f, -0.5f, 0.f },{ 0.f, 0.f, 1.f, 1.f } },
    };

    const UINT vertexBufferSize = sizeof(triangleVertices);

    m_device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
        D3D12_HEAP_FLAG_NONE,
        &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(&m_vertexBuffer));

    UINT8* pVertexDataBegin;
    CD3DX12_RANGE readRange(0, 0);
    m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin));
    memcpy(pVertexDataBegin, triangleVertices, vertexBufferSize);
    m_vertexBuffer->Unmap(0, nullptr);

    m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
    m_vertexBufferView.StrideInBytes = sizeof(Vertex);
    m_vertexBufferView.SizeInBytes = vertexBufferSize;

    m_viewport.Height = screenHeight;
    m_viewport.Width = screenWidth;
    m_viewport.MaxDepth = 1000.f;
    m_viewport.MinDepth = 0.1f;
    m_viewport.TopLeftX = 0.f;
    m_viewport.TopLeftY = 0.f;

    m_scissorRect.left = 0;
    m_scissorRect.right = screenWidth;
    m_scissorRect.top = 0;
    m_scissorRect.bottom = screenHeight;

    unsigned long long fenceToWaitFor = m_fenceValue;
    m_commandQueue->Signal(m_fence, fenceToWaitFor);
    m_fenceValue++;

    // Wait until the GPU is done rendering.
    if (m_fence->GetCompletedValue() < fenceToWaitFor)
    {
        m_fence->SetEventOnCompletion(fenceToWaitFor, m_fenceEvent);
        WaitForSingleObject(m_fenceEvent, INFINITE);
    }

	return true;
}
//--------------------------------------------------------------------------
void VeRenderWindowD3D12::Init(VeRendererD3D12& kRenderer) noexcept
{
	if ((!m_kNode.is_attach()) && m_spTargetWindow)
	{
		D3D12_COMMAND_QUEUE_DESC kQueueDesc = {};
		kQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
		kQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
		if (FAILED(kRenderer.m_pkDevice->CreateCommandQueue(&kQueueDesc,
			IID_PPV_ARGS(&m_pkCommandQueue))))
		{
			VE_SAFE_RELEASE(m_pkCommandQueue);
			VE_SAFE_RELEASE(m_pkSwapChain);
			return;
		}
		DXGI_SWAP_CHAIN_DESC kSwapChainDesc = {};
		kSwapChainDesc.BufferCount = VeRendererD3D12::FRAME_COUNT;
		kSwapChainDesc.BufferDesc.Width = m_spTargetWindow->GetWidth();
		kSwapChainDesc.BufferDesc.Height = m_spTargetWindow->GetHeight();
		kSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;			
		kSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
		kSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
		kSwapChainDesc.OutputWindow = m_spTargetWindow->GetWMInfo().win.window;
		kSwapChainDesc.SampleDesc.Count = 1;
		kSwapChainDesc.Windowed = TRUE;
		IDXGISwapChain* pkSwapChain;
		if (FAILED(kRenderer.m_pkDXGIFactory->CreateSwapChain(m_pkCommandQueue,
			&kSwapChainDesc, &pkSwapChain)))
		{
			VE_SAFE_RELEASE(m_pkCommandQueue);
			VE_SAFE_RELEASE(pkSwapChain);
			return;
		}
		if (FAILED(pkSwapChain->QueryInterface(IID_PPV_ARGS(&m_pkSwapChain))))
		{
			VE_SAFE_RELEASE(m_pkCommandQueue);
			VE_SAFE_RELEASE(pkSwapChain);
			VE_SAFE_RELEASE(m_pkSwapChain);
			return;
		}
		else
		{
			VE_SAFE_RELEASE(pkSwapChain);
		}
		VE_ASSERT(m_pkCommandQueue && m_pkSwapChain);
		for (VeInt32 i(0); i < VeRendererD3D12::FRAME_COUNT; ++i)
		{
			FrameCache& kFrame = m_akFrameCache[i];
			VE_ASSERT_GE(m_pkSwapChain->GetBuffer(i, IID_PPV_ARGS(&kFrame.m_pkBufferResource)), S_OK);
			kFrame.m_hHandle.ptr = kRenderer.m_kRTVHeap.GetCPUStart().ptr + kRenderer.m_kRTVHeap.Alloc();
			kRenderer.m_pkDevice->CreateRenderTargetView(
				kFrame.m_pkBufferResource, nullptr, kFrame.m_hHandle);
			VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator(
				D3D12_COMMAND_LIST_TYPE_DIRECT,
				IID_PPV_ARGS(&kFrame.m_pkDirectAllocator)), S_OK);
			VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator(
				D3D12_COMMAND_LIST_TYPE_BUNDLE,
				IID_PPV_ARGS(&kFrame.m_pkBundleAllocator)), S_OK);
			kFrame.m_u64FenceValue = 0;
		}		

		m_u64FenceValue = 0;
		VE_ASSERT_GE(kRenderer.m_pkDevice->CreateFence(m_u64FenceValue++,
			D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pkFence)), S_OK);
		m_kFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
		VE_ASSERT(m_kFenceEvent);
		const VeUInt64 u64FenceToWaitFor = m_u64FenceValue++;
		VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, u64FenceToWaitFor), S_OK);
		VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(u64FenceToWaitFor, m_kFenceEvent), S_OK);
		WaitForSingleObject(m_kFenceEvent, INFINITE);
		m_u32FrameIndex = m_pkSwapChain->GetCurrentBackBufferIndex();
		kRenderer.m_kRenderWindowList.attach_back(m_kNode);
	}

	m_kViewport.TopLeftX = 0;
	m_kViewport.TopLeftY = 0;
	m_kViewport.Width = m_spTargetWindow->GetWidth();
	m_kViewport.Height = m_spTargetWindow->GetHeight();
	m_kViewport.MinDepth = 0.0f;
	m_kViewport.MaxDepth = 1.0f;

	m_kScissorRect.left = 0;
	m_kScissorRect.right = m_spTargetWindow->GetWidth();
	m_kScissorRect.top = 0;
	m_kScissorRect.bottom = m_spTargetWindow->GetHeight();

	{
		m_vertexBufferView.BufferLocation = kRenderer.m_kRenderBufferList.get_tail_node()->m_Content->m_pkResource->GetGPUVirtualAddress();
		m_vertexBufferView.StrideInBytes = sizeof(VE_FLOAT3);
		m_vertexBufferView.SizeInBytes = kRenderer.m_kRenderBufferList.get_head_node()->m_Content->GetSize();
	}
}