void KGraphicsDevice::Present()
{
	m_SwapChain->Present(0, 0);

	m_SwapIndex = (1 + m_SwapIndex) % 2;

	WaitForGPU();
}
示例#2
0
void AppTest::Destroy()
{
	WaitForGPU();
	SwapChain->SetFullscreenState(FALSE, nullptr);

	CloseHandle(HandleEvent);

#ifdef DEBUG
	novus::MallocTracker::GetInstance()->DumpTrackedMemory();
#endif
}
示例#3
0
IRenderer::Impl::Impl(HWND hwnd, U32 windowWidth, U32 windowHeight, IRenderer* pRenderer)
	: m_viewport(static_cast<F32>(windowWidth), static_cast<F32>(windowHeight))
	, m_scissorRect(windowWidth, windowHeight)
	, m_psoManager(&m_device, &m_resCache, &m_rootSignature)
	, m_pRenderer(pRenderer)
{
	// TEMP: Select the second(integrated card) adapter due to some problem with nvidia I can't pinpoint.
	auto pAdapter = m_hwCaps.GetDisplayAdapter(1).Get();
	m_device.Init(pAdapter.Get());
	m_hwCaps.CheckMSAASupport(m_device.Get());

	m_commandQueue.Init(m_device.Get());
	m_swapChain.Init(m_device.Get(), m_commandQueue.Get(), hwnd);
	m_commandAllocator.Init(m_device.Get());

	CreateRootSignature();

	// Create Resources
	ResourceConfig descCB(ResourceType::BUFFER, sizeof(XMFLOAT4X4));
	m_viewProjConstBuffer.CreateCommited(m_device.Get(), descCB, &m_pViewProjDataBegin);

	// Create Descriptor Heaps
	m_cbDescHeap.Init(m_device.Get(), DescHeapType::CB_SR_UA, MAX_RENDER_ITEMS, true);
	m_dsvDescHeap.Init(m_device.Get(), DescHeapType::DEPTH_STENCIL, 1);

	// Create Depth Buffer
	ClearValue clearValue(DXGI_FORMAT_D32_FLOAT, 1.0f);
	ResourceConfig dbConfig(ResourceType::TEXTURE2D, 800, 600, DXGI_FORMAT_R32_TYPELESS, TextureLayout::UNKNOWN, ResourceFlag::ALLOW_DEPTH_STENCIL);
	m_depthBuffer.CreateCommited(m_device.Get(), dbConfig, nullptr, nullptr, 0, D3D12_HEAP_TYPE_DEFAULT, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue);

	DepthStencilView dsvDesc;
	m_device.Get()->CreateDepthStencilView(m_depthBuffer.Get(), &dsvDesc, m_dsvDescHeap.GetCPUHandle(0));

	// Create a command list 
	m_commandList.Init(m_device.Get(), m_commandAllocator.Get());
	m_commandList.Close();

	// Create synchronization objects
	m_fence.Init(m_device.Get(), 0);
	m_currentFence = 1;
	m_handleEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);

	// Synchronize
	WaitForGPU();

	m_resCache.Init(m_device.Get());
}
示例#4
0
Direct3DManager::~Direct3DManager()
{
	WaitForGPU();

	ReleaseSwapChainDependentResources();

	mSwapChain->Release();
	mSwapChain = NULL;

	delete mContextManager;
	mContextManager = NULL;

	mDevice->Release();
	mDevice = NULL;

	mDXGIFactory->Release();
	mDXGIFactory = NULL;
}
示例#5
0
void AppTest::Render()
{
	PopulateCommandLists();

	//Execute command lists
	std::vector<ID3D12CommandList*> commandLists;
	commandLists.push_back(CommandList.Get());

	for (auto const& it : CommandListArray)
	{
		commandLists.push_back(it.Get());
	}

	CommandQueue->ExecuteCommandLists((UINT)commandLists.size(), &commandLists[0]);

	//Swap back and front buffers
	SwapChain->Present(1, 0);
	IndexLastSwapBuf = (1 + IndexLastSwapBuf) % NumSwapBufs;
	SwapChain->GetBuffer(IndexLastSwapBuf, IID_PPV_ARGS(RenderTarget.ReleaseAndGetAddressOf()));
	Device->CreateRenderTargetView(RenderTarget.Get(), nullptr, DescriptorHeap->GetCPUDescriptorHandleForHeapStart());

	WaitForGPU();
}
ResourceManager::~ResourceManager() {	
	if (m_pUpload) {
		WaitForGPU();
		
		m_pUpload->Release();
		m_pUpload = nullptr;
	}

	m_pDev = nullptr;

	CloseHandle(m_hdlFenceEvent);

	if (m_pFence) {
		m_pFence->Release();
		m_pFence = nullptr;
	}

	if (m_pCmdAllocator) {
		m_pCmdAllocator->Release();
		m_pCmdAllocator = nullptr;
	}

	if (m_pCmdList) {
		m_pCmdList->Release();
		m_pCmdList = nullptr;
	}

	while (!m_listFileData.empty()) {
		unsigned char* tmp = m_listFileData.back();

		if (tmp) delete[] tmp;

		m_listFileData.pop_back();
	}

	while (!m_listResources.empty()) {
		ID3D12Resource* tex = m_listResources.back();

		if (tex) tex->Release();

		m_listResources.pop_back();
	}

	if (m_pheapSampler) {
		m_pheapSampler->Release();
		m_pheapSampler = nullptr;
	}

	if (m_pheapCBVSRVUAV) {
		m_pheapCBVSRVUAV->Release();
		m_pheapCBVSRVUAV = nullptr;
	}

	if (m_pheapDSV) {
		m_pheapDSV->Release();
		m_pheapDSV = nullptr;
	}

	if (m_pheapRTV) {
		m_pheapRTV->Release();
		m_pheapRTV = nullptr;
	}
}
// Upload to the buffer stored at index i.
void ResourceManager::UploadToBuffer(unsigned int i, unsigned int numSubResources, D3D12_SUBRESOURCE_DATA* data, D3D12_RESOURCE_STATES initialState) {
	if (i < 0 || i >= m_listResources.size()) {
		std::string msg = "ResourceManager::UploadToBuffer failed due to index " + std::to_string(i) + " out of bounds.";
		throw GFX_Exception(msg.c_str());
	}

	if (FAILED(m_pCmdList->Reset(m_pCmdAllocator, NULL))) {
		throw GFX_Exception("ResourceManager::UploadToBuffer: CommandList Reset failed.");
	}

	m_pCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_listResources[i],
		initialState, D3D12_RESOURCE_STATE_COPY_DEST));

	auto size = GetRequiredIntermediateSize(m_listResources[i], 0, numSubResources);
	size = (UINT64)pow(2.0, ceil(log(size) / log(2))); // round size up to the next power of 2 to ensure good alignment in upload buffer.

	if (size > DEFAULT_UPLOAD_BUFFER_SIZE) {
		// then we're going to have to create a new temporary buffer.
		ID3D12Resource* tmpUpload;
		m_pDev->CreateCommittedResource(tmpUpload, &CD3DX12_RESOURCE_DESC::Buffer(size), &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
			D3D12_HEAP_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr);

		UpdateSubresources(m_pCmdList, m_listResources[i], tmpUpload, 0, 0, numSubResources, data);

		// set resource barriers to inform GPU that data is ready for use.
		m_pCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_listResources[i],
			initialState, D3D12_RESOURCE_STATE_COPY_DEST));

		// close the command list.
		if (FAILED(m_pCmdList->Close())) {
			throw GFX_Exception("ResourceManager::UploadToBuffer: CommandList Close failed.");
		}

		// load the command list.
		ID3D12CommandList* lCmds[] = { m_pCmdList };
		m_pDev->ExecuteCommandLists(lCmds, __crt_countof(lCmds));

		// add fence signal.
		++m_valFence;
		m_pDev->SetFence(m_pFence, m_valFence);

		WaitForGPU();
		tmpUpload->Release();
	} else {
		if (size > DEFAULT_UPLOAD_BUFFER_SIZE - m_iUpload) {
			// then we need to wait for the GPU to finish with whatever it is currently uploading.
			// check to see if it is already done.
			if (m_pFence->GetCompletedValue() < m_valFence) {
				// then we're not done, so wait.
				WaitForGPU();
				
			}
			m_iUpload = 0;
		}

		UpdateSubresources(m_pCmdList, m_listResources[i], m_pUpload, m_iUpload, 0, numSubResources, data);
		m_iUpload += size;

		// set resource barriers to inform GPU that data is ready for use.
		m_pCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_listResources[i],
			D3D12_RESOURCE_STATE_COPY_DEST, initialState));

		// close the command list.
		if (FAILED(m_pCmdList->Close())) {
			throw GFX_Exception("ResourceManager::UploadToBuffer: CommandList Close failed.");
		}

		// load the command list.
		ID3D12CommandList* lCmds[] = { m_pCmdList };
		m_pDev->ExecuteCommandLists(lCmds, __crt_countof(lCmds));

		// add fence signal.
		++m_valFence;
		m_pDev->SetFence(m_pFence, m_valFence);
	}
}
示例#8
0
void AppTest::LoadAssets()
{
	//Load and compile the shaders
	D3D12Shader vertShader = D3D12Shader(ShaderType::Vertex, L"TestShader.hlsl", "VS");
	D3D12Shader pixelShader = D3D12Shader(ShaderType::Pixel, L"TestShader.hlsl", "PS");

	std::vector<ShaderMacro> macros;
	macros.push_back({ "BOXCOLOR", "float4(1.0f, 1.0f, 1.0f, 1.0f)" });

	vertShader.Compile(&macros[0], static_cast<uint32_t>(macros.size()));
	pixelShader.Compile(&macros[0], static_cast<uint32_t>(macros.size()));

	D3D12_INPUT_ELEMENT_DESC layout[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
		{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0}
	};

	UINT numElements = ARRAYSIZE(layout);

	//Create root signiture with one root constant buffer view

	D3D12_ROOT_PARAMETER param;
	D3D12_DESCRIPTOR_RANGE descriptorRange = {};

	if (UseRootLevelCBV)
	{
		param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
		param.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
		param.Descriptor = { 0, 0 };
	}
	else
	{
		//Used for if you need non root level constant buffer views
		//This is somewhat slower than switching out a root level CBV
		descriptorRange.BaseShaderRegister = 0;
		descriptorRange.NumDescriptors = 1;
		descriptorRange.OffsetInDescriptorsFromTableStart = 0;
		descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
		descriptorRange.RegisterSpace = 0;

		param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
		param.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
		param.DescriptorTable.NumDescriptorRanges = 1;
		param.DescriptorTable.pDescriptorRanges = &descriptorRange;
	}

	ComPtr<ID3D10Blob> pOutBlob, pErrorBlob;
	D3D12_ROOT_SIGNATURE_DESC rootSigDesc;
	rootSigDesc.NumParameters = 1;
	rootSigDesc.pParameters = &param;
	rootSigDesc.NumStaticSamplers = 0;
	rootSigDesc.pStaticSamplers = nullptr;
	rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
	CHK(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf()));
	CHK(Device->CreateRootSignature(0, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_PPV_ARGS(RootSignature.GetAddressOf())));

	//Create the PSO

	D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
	ZeroMemory(&psoDesc, sizeof(psoDesc));
	psoDesc.InputLayout = { layout, numElements };
	psoDesc.pRootSignature = RootSignature.Get();
	psoDesc.VS = { reinterpret_cast<BYTE*>(vertShader.GetByteCodePtr()), vertShader.GetSize() };
	psoDesc.PS = { reinterpret_cast<BYTE*>(pixelShader.GetByteCodePtr()), pixelShader.GetSize() };
	psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);;
	psoDesc.RasterizerState.FrontCounterClockwise = true; //Using RH coordinate system
	psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
	psoDesc.DepthStencilState.DepthEnable = true;
	psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
	psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
	psoDesc.DepthStencilState.StencilEnable = false;
	psoDesc.SampleMask = UINT_MAX;
	psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
	psoDesc.NumRenderTargets = 1;
	psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
	psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
	psoDesc.SampleDesc.Count = 1;
	psoDesc.SampleDesc.Quality = 0;

	CHK(Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(PSO.GetAddressOf())));

	//Create descriptor heap
	D3D12_DESCRIPTOR_HEAP_DESC descHeapDesc = {};
	descHeapDesc.NumDescriptors = 1;
	descHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
	descHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

	CHK(Device->CreateDescriptorHeap(&descHeapDesc, IID_PPV_ARGS(DescriptorHeap.GetAddressOf())));

	D3D12_DESCRIPTOR_HEAP_DESC DSVDescHeapDesc = {};
	DSVDescHeapDesc.NumDescriptors = 1;
	DSVDescHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
	DSVDescHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

	CHK(Device->CreateDescriptorHeap(&DSVDescHeapDesc, IID_PPV_ARGS(DSVDescriptorHeap.GetAddressOf())));

	CHK(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocator.Get(), PSO.Get(), IID_PPV_ARGS(CommandList.GetAddressOf())));

	//Create the command lists for each thread
	for (unsigned int i = 0; i < ThreadCount; i++)
	{
		CHK(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocatorArray[i].Get(), PSO.Get(), IID_PPV_ARGS(CommandListArray[i].GetAddressOf())));
		CommandListArray[i].Get()->Close();
	}

	//Create back buffer and render target

	CHK(SwapChain->GetBuffer(0, IID_PPV_ARGS(RenderTarget.GetAddressOf())));
	Device->CreateRenderTargetView(RenderTarget.Get(), nullptr, DescriptorHeap->GetCPUDescriptorHandleForHeapStart());

	Viewport.TopLeftX = 0.0f;
	Viewport.TopLeftY = 0.0f;
	Viewport.Width = static_cast<float>(ViewportWidth);
	Viewport.Height = static_cast<float>(ViewportHeight);
	Viewport.MinDepth = 0.0f;
	Viewport.MaxDepth = 1.0f;

	RectScissor.left = 0;
	RectScissor.top = 0;
	RectScissor.right = ViewportWidth;
	RectScissor.bottom = ViewportHeight;

	//Create depth buffer
	D3D12_RESOURCE_DESC depthResDesc = CD3DX12_RESOURCE_DESC::Tex2D(
		DXGI_FORMAT_R32_TYPELESS,
		ViewportWidth,
		ViewportHeight,
		1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN);

	D3D12_CLEAR_VALUE dsvClearValue;
	dsvClearValue.Format = DXGI_FORMAT_D32_FLOAT;
	dsvClearValue.DepthStencil.Depth = 1.0f;
	dsvClearValue.DepthStencil.Stencil = 0;

	CHK(Device->CreateCommittedResource(
		&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
		D3D12_HEAP_FLAG_NONE,
		&depthResDesc,
		D3D12_RESOURCE_STATE_DEPTH_WRITE,
		&dsvClearValue,
		IID_PPV_ARGS(DepthBufferTexture.GetAddressOf())));
	DepthBufferTexture->SetName(L"Depth Buffer");

	D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
	dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
	dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
	dsvDesc.Texture2D.MipSlice = 0;
	dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
	Device->CreateDepthStencilView(DepthBufferTexture.Get(), &dsvDesc, DSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

	//Allocate buffer for all constant buffers
	PerObjectConstantBuffers.Init(BoxCount, sizeof(CBPerObject), Device.Get());

	//Create the constant buffer descriptor heap and populate it
	if (!UseRootLevelCBV)
	{
		ConstantBufferDescriptorHeap = std::make_unique<D3D12RHIDescriptorHeap>(BoxCount, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, true);

		HRESULT hr = ConstantBufferDescriptorHeap->Init(Device.Get());

		assert(SUCCEEDED(hr));

		D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDesc = {};
		constantBufferViewDesc.SizeInBytes = PerObjectConstantBuffers.GetAlignedStride();
		D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorHandle;

		for (unsigned int i = 0; i < BoxCount; i++)
		{
			cpuDescriptorHandle.ptr = reinterpret_cast<size_t>(ConstantBufferDescriptorHeap->GetDescriptorCPUPtr(i));
			constantBufferViewDesc.BufferLocation = PerObjectConstantBuffers.GetGPUHandle(i);
			Device->CreateConstantBufferView(&constantBufferViewDesc, cpuDescriptorHandle);
		}
	}

	//Generate mesh
	GeometryGenerator::SimpleMesh shapeMesh;
	
	GeometryGenerator::CreateBox(1.0f, 1.0f, 1.0f, shapeMesh);
	//GeometryGenerator::CreateSphere(1.0f, 10, 10, shapeMesh);

	IndexCount = static_cast<uint32_t>(shapeMesh.Indices.size());

	//Copy vertex data to buffer
	//This should be put into its own job system using the copy engine eventually
	Device->CreateCommittedResource(
		&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
		D3D12_HEAP_FLAG_NONE,
		&CD3DX12_RESOURCE_DESC::Buffer(sizeof(GeometryGenerator::SimpleVertex) * shapeMesh.Vertices.size()),
		D3D12_RESOURCE_STATE_GENERIC_READ,
		nullptr,
		IID_PPV_ARGS(VertBuffer.GetAddressOf()));

	Device->CreateCommittedResource(
		&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
		D3D12_HEAP_FLAG_NONE,
		&CD3DX12_RESOURCE_DESC::Buffer(sizeof(uint32_t) * shapeMesh.Indices.size()),
		D3D12_RESOURCE_STATE_GENERIC_READ,
		nullptr,
		IID_PPV_ARGS(IndexBuffer.GetAddressOf()));

	UINT8* dataBegin;
	VertBuffer->Map(0, nullptr, reinterpret_cast<void**>(&dataBegin));
	memcpy(dataBegin, &shapeMesh.Vertices[0], sizeof(GeometryGenerator::SimpleVertex) * shapeMesh.Vertices.size());
	VertBuffer->Unmap(0, nullptr);

	IndexBuffer->Map(0, nullptr, reinterpret_cast<void**>(&dataBegin));
	memcpy(dataBegin, &shapeMesh.Indices[0], sizeof(uint32_t) * shapeMesh.Indices.size());
	IndexBuffer->Unmap(0, nullptr);

	//Create vertex buffer view

	DescViewBufVert.BufferLocation = VertBuffer->GetGPUVirtualAddress();
	DescViewBufVert.StrideInBytes = sizeof(GeometryGenerator::SimpleVertex);
	DescViewBufVert.SizeInBytes = static_cast<UINT>(sizeof(GeometryGenerator::SimpleVertex) * shapeMesh.Vertices.size());

	DescViewBufIndex.BufferLocation = IndexBuffer->GetGPUVirtualAddress();
	DescViewBufIndex.Format = DXGI_FORMAT_R32_UINT;
	DescViewBufIndex.SizeInBytes = static_cast<UINT>(sizeof(uint32_t) * shapeMesh.Indices.size());

	//Create fencing object

	Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(Fence.GetAddressOf()));
	CurrentFence = 1;

	//Initialize bundles for drawing
	if (UseBundles)
	{
		InitBundles();
	}

	//Close the command list and use it to execute the GPU setup
	CommandList->Close();
	ID3D12CommandList* ppCommandLists[] = { CommandList.Get() };
	CommandQueue->ExecuteCommandLists(1, ppCommandLists);

	HandleEvent = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);

	WaitForGPU();
}
示例#9
0
void Direct3DManager::CreateWindowDependentResources(Vector2 screenSize, HWND windowHandle, bool vsync /*= false*/, bool fullScreen /*= false*/)
{
	// Wait until all previous GPU work is complete.
	WaitForGPU();

	mOutputSize = screenSize;
	mUseVsync = vsync;				//need to handle if vsync or fullscreen changes
	mIsFullScreen = fullScreen;

	// The width and height of the swap chain must be based on the window's
	// natively-oriented width and height. If the window is not in the native
	// orientation, the dimensions must be reversed.
	DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation();

	bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270;
	mOutputSize.X = swapDimensions ? screenSize.Y : screenSize.X;
	mOutputSize.Y = swapDimensions ? screenSize.X : screenSize.Y;

	if (mSwapChain != NULL)
	{
		ReleaseSwapChainDependentResources();
		// If the swap chain already exists, resize it.
		HRESULT hr = mSwapChain->ResizeBuffers(BACK_BUFFER_COUNT, lround(mOutputSize.X), lround(mOutputSize.Y), DXGI_FORMAT_R8G8B8A8_UNORM, 0);

		if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
		{
			// If the device was removed for any reason, a new device and swap chain will need to be created.
			mDeviceRemoved = true;

			// Do not continue execution of this method. DeviceResources will be destroyed and re-created.
			return;
		}
		else
		{
			Direct3DUtils::ThrowIfHRESULTFailed(hr);
		}
	}
	else
	{
		// Otherwise, create a new one using the same adapter as the existing Direct3D device.
		IDXGIAdapter* adapter = NULL;
		IDXGIOutput* adapterOutput = NULL;
		uint32 numDisplayModes = 0;

		Direct3DUtils::ThrowIfHRESULTFailed(mDXGIFactory->EnumAdapters(0, &adapter));
		Direct3DUtils::ThrowIfHRESULTFailed(adapter->EnumOutputs(0, &adapterOutput));
		Direct3DUtils::ThrowIfHRESULTFailed(adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numDisplayModes, NULL));
		DXGI_MODE_DESC *displayModeList = new DXGI_MODE_DESC[numDisplayModes];
		Direct3DUtils::ThrowIfHRESULTFailed(adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numDisplayModes, displayModeList));
		
		uint32 numerator = 0;
		uint32 denominator = 0;

		for (uint32 i = 0; i < numDisplayModes; i++)
		{
			if (displayModeList[i].Height == (uint32)mOutputSize.X)
			{
				if (displayModeList[i].Width == (uint32)mOutputSize.Y)
				{
					numerator = displayModeList[i].RefreshRate.Numerator;
					denominator = displayModeList[i].RefreshRate.Denominator;
				}
			}
		}

		/*
		DXGI_ADAPTER_DESC adapterDesc;
		// Get the adapter (video card) description.
		result = adapter->GetDesc(&adapterDesc);
		if(FAILED(result))
		{
			return false;
		}

		// 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.
		error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);
		if(error != 0)
		{
			return false;
		}
		*/
		delete[] displayModeList;
		displayModeList = NULL;
		adapterOutput->Release();
		adapterOutput = NULL;
		adapter->Release();
		adapter = NULL;

		DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
		ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
		swapChainDesc.Width = lround(mOutputSize.X);	// Match the size of the window.
		swapChainDesc.Height = lround(mOutputSize.Y);
		swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;			// This is the most common swap chain 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 = BACK_BUFFER_COUNT;					// Use triple-buffering to minimize latency.
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;	// All Windows Universal apps must use _FLIP_ SwapEffects
		swapChainDesc.Flags = 0;
		swapChainDesc.Scaling = DXGI_SCALING_NONE;
		swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;

		DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullScreenDesc = {};
		ZeroMemory(&swapChainFullScreenDesc, sizeof(swapChainFullScreenDesc));
		swapChainFullScreenDesc.Windowed = !mIsFullScreen;
		swapChainFullScreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
		swapChainFullScreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
		
		if (mUseVsync)
		{
			swapChainFullScreenDesc.RefreshRate.Numerator = numerator;
			swapChainFullScreenDesc.RefreshRate.Denominator = denominator;
		}
		else
		{
			swapChainFullScreenDesc.RefreshRate.Numerator = 0;
			swapChainFullScreenDesc.RefreshRate.Denominator = 1;
		}


		IDXGISwapChain1 *swapChain = NULL;
		Direct3DUtils::ThrowIfHRESULTFailed(
			mDXGIFactory->CreateSwapChainForHwnd(
				mContextManager->GetQueueManager()->GetGraphicsQueue()->GetCommandQueue(),
				windowHandle,
				&swapChainDesc,
				&swapChainFullScreenDesc,
				NULL,
				&swapChain
				)
			);
		
		Direct3DUtils::ThrowIfHRESULTFailed(swapChain->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&mSwapChain));
	}

	Direct3DUtils::ThrowIfHRESULTFailed(mSwapChain->SetRotation(displayRotation));

	BuildSwapChainDependentResources();

	// Set the 3D rendering viewport to target the entire window.
	mScreenViewport = { 0.0f, 0.0f, mOutputSize.X, mOutputSize.Y, 0.0f, 1.0f };

	WaitForGPU();
}