// Fill the command list with all the render commands and dependent state.
void D3D12Fullscreen::PopulateCommandList()
{
	// Command list allocators can only be reset when the associated 
	// command lists have finished execution on the GPU; apps should use 
	// fences to determine GPU execution progress.
	ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset());

	// However, when ExecuteCommandList() is called on a particular command 
	// list, that command list can then be reset at any time and must be before 
	// re-recording.
	ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));

	if (m_resizeResources)
	{
		// Reload resources that depend on the size of the swap chain.
		LoadSizeDependentResources();
	}

	// Set necessary state.
	m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());

	ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
	m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

	CD3DX12_GPU_DESCRIPTOR_HANDLE cbvHandle(m_cbvHeap->GetGPUDescriptorHandleForHeapStart(), m_frameIndex, m_cbvDescriptorSize);
	m_commandList->SetGraphicsRootDescriptorTable(0, cbvHandle);
	m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	m_commandList->RSSetViewports(1, &m_viewport);
	m_commandList->RSSetScissorRects(1, &m_scissorRect);

	// Indicate that the back buffer will be used as a render target.
	m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));

	CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
	m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);

	// Record commands.
	const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
	m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
	m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);

	PIXBeginEvent(m_commandList.Get(), 0, L"Draw a thin rectangle");
	m_commandList->DrawInstanced(4, 1, 0, 0);
	PIXEndEvent(m_commandList.Get());

	// Indicate that the back buffer will now be used to present.
	m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));

	ThrowIfFailed(m_commandList->Close());
}
void VolumetricAnimation::PopulateComputeCommandList()
{
	HRESULT hr;
	V( m_computeCmdAllocator->Reset() );
	V( m_computeCmdList->Reset( m_computeCmdAllocator.Get(), m_computeState.Get() ) );
	m_computeCmdList->SetPipelineState( m_computeState.Get() );
	m_computeCmdList->SetComputeRootSignature( m_computeRootSignature.Get() );
	ID3D12DescriptorHeap* ppHeaps[] = { m_cbvsrvuavHeap.Get() };
	m_computeCmdList->SetDescriptorHeaps( _countof( ppHeaps ), ppHeaps );
	CD3DX12_GPU_DESCRIPTOR_HANDLE cbvHandle( m_cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(), RootParameterCBV, m_cbvsrvuavDescriptorSize );
	CD3DX12_GPU_DESCRIPTOR_HANDLE uavHandle( m_cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(), RootParameterUAV, m_cbvsrvuavDescriptorSize );

	m_computeCmdList->SetComputeRootDescriptorTable( RootParameterCBV, cbvHandle );
	m_computeCmdList->SetComputeRootDescriptorTable( RootParameterUAV, uavHandle );
	m_computeCmdList->Dispatch( m_volumeWidth / 8, m_volumeHeight/ 8, m_volumeDepth/ 8);
	m_computeCmdList->Close();
}
// Fill the command list with all the render commands and dependent state.
void D3D12Fullscreen::PopulateCommandLists()
{
	// Command list allocators can only be reset when the associated 
	// command lists have finished execution on the GPU; apps should use 
	// fences to determine GPU execution progress.
	ThrowIfFailed(m_sceneCommandAllocators[m_frameIndex]->Reset());
	ThrowIfFailed(m_postCommandAllocators[m_frameIndex]->Reset());

	// However, when ExecuteCommandList() is called on a particular command 
	// list, that command list can then be reset at any time and must be before 
	// re-recording.
	ThrowIfFailed(m_sceneCommandList->Reset(m_sceneCommandAllocators[m_frameIndex].Get(), m_scenePipelineState.Get()));
	ThrowIfFailed(m_postCommandList->Reset(m_postCommandAllocators[m_frameIndex].Get(), m_postPipelineState.Get()));

	// Populate m_sceneCommandList to render scene to intermediate render target.
	{
		// Set necessary state.
		m_sceneCommandList->SetGraphicsRootSignature(m_sceneRootSignature.Get());

		ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvHeap.Get() };
		m_sceneCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

		CD3DX12_GPU_DESCRIPTOR_HANDLE cbvHandle(m_cbvSrvHeap->GetGPUDescriptorHandleForHeapStart(), m_frameIndex + 1, m_cbvSrvDescriptorSize);
		m_sceneCommandList->SetGraphicsRootDescriptorTable(0, cbvHandle);
		m_sceneCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		m_sceneCommandList->RSSetViewports(1, &m_sceneViewport);
		m_sceneCommandList->RSSetScissorRects(1, &m_sceneScissorRect);

		CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), FrameCount, m_rtvDescriptorSize);
		m_sceneCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);

		// Record commands.
		m_sceneCommandList->ClearRenderTargetView(rtvHandle, ClearColor, 0, nullptr);
		m_sceneCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
		m_sceneCommandList->IASetVertexBuffers(0, 1, &m_sceneVertexBufferView);

		PIXBeginEvent(m_sceneCommandList.Get(), 0, L"Draw a thin rectangle");
		m_sceneCommandList->DrawInstanced(4, 1, 0, 0);
		PIXEndEvent(m_sceneCommandList.Get());
	}

	ThrowIfFailed(m_sceneCommandList->Close());

	// Populate m_postCommandList to scale intermediate render target to screen.
	{
		// Set necessary state.
		m_postCommandList->SetGraphicsRootSignature(m_postRootSignature.Get());

		ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvHeap.Get() };
		m_postCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

		// Indicate that the back buffer will be used as a render target and the
		// intermediate render target will be used as a SRV.
		D3D12_RESOURCE_BARRIER barriers[] = {
			CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET),
			CD3DX12_RESOURCE_BARRIER::Transition(m_intermediateRenderTarget.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
		};

		m_postCommandList->ResourceBarrier(_countof(barriers), barriers);

		m_postCommandList->SetGraphicsRootDescriptorTable(0, m_cbvSrvHeap->GetGPUDescriptorHandleForHeapStart());
		m_postCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
		m_postCommandList->RSSetViewports(1, &m_postViewport);
		m_postCommandList->RSSetScissorRects(1, &m_postScissorRect);

		CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
		m_postCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);

		// Record commands.
		m_postCommandList->ClearRenderTargetView(rtvHandle, LetterboxColor, 0, nullptr);
		m_postCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
		m_postCommandList->IASetVertexBuffers(0, 1, &m_postVertexBufferView);

		PIXBeginEvent(m_postCommandList.Get(), 0, L"Draw texture to screen.");
		m_postCommandList->DrawInstanced(4, 1, 0, 0);
		PIXEndEvent(m_postCommandList.Get());

		// Revert resource states back to original values.
		barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
		barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
		barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
		barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;

		m_postCommandList->ResourceBarrier(_countof(barriers), barriers);
	}

	ThrowIfFailed(m_postCommandList->Close());
}
void VolumetricAnimation::PopulateGraphicsCommandList()
{
	HRESULT hr;
	// Command list allocators can only be reset when the associated 
	// command lists have finished execution on the GPU; apps should use 
	// fences to determine GPU execution progress.
	V( m_graphicCmdAllocator->Reset() );

	// However, when ExecuteCommandList() is called on a particular command 
	// list, that command list can then be reset at any time and must be before 
	// re-recording.
	V( m_graphicCmdList->Reset( m_graphicCmdAllocator.Get(), m_pipelineState.Get() ) );

	XMMATRIX view = m_camera.GetViewMatrix();
	XMMATRIX proj = m_camera.GetProjMatrix();

	XMMATRIX world = XMMatrixRotationY( static_cast< float >( m_timer.GetTotalSeconds() ) );
	m_constantBufferData.wvp = XMMatrixMultiply( view, proj );
	//m_constantBufferData.wvp = XMMatrixMultiply( XMMatrixMultiply( world, view ), proj );
	XMStoreFloat4( &m_constantBufferData.viewPos, m_camera.GetEyePt() );
	
	memcpy( m_pCbvDataBegin, &m_constantBufferData, sizeof( m_constantBufferData ) );

	// Set necessary state.
	m_graphicCmdList->SetGraphicsRootSignature( m_graphicsRootSignature.Get() );

	ID3D12DescriptorHeap* ppHeaps[] = { m_cbvsrvuavHeap.Get() };
	m_graphicCmdList->SetDescriptorHeaps( _countof( ppHeaps ), ppHeaps );

	CD3DX12_GPU_DESCRIPTOR_HANDLE cbvHandle( m_cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(), RootParameterCBV, m_cbvsrvuavDescriptorSize );
	CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle( m_cbvsrvuavHeap->GetGPUDescriptorHandleForHeapStart(), RootParameterSRV, m_cbvsrvuavDescriptorSize );

	m_graphicCmdList->SetGraphicsRootDescriptorTable( RootParameterCBV, cbvHandle );
	m_graphicCmdList->SetGraphicsRootDescriptorTable( RootParameterSRV, srvHandle );

	m_graphicCmdList->RSSetViewports( 1, &m_viewport );
	m_graphicCmdList->RSSetScissorRects( 1, &m_scissorRect );

	// Indicate that the back buffer will be used as a render target.
	D3D12_RESOURCE_BARRIER resourceBarriersBefore[] = {
		CD3DX12_RESOURCE_BARRIER::Transition( m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET ),
		CD3DX12_RESOURCE_BARRIER::Transition( m_volumeBuffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE )
	};
	m_graphicCmdList->ResourceBarrier( 2, resourceBarriersBefore );

	CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle( m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize );
	m_graphicCmdList->OMSetRenderTargets( 1, &rtvHandle, FALSE, &m_dsvHeap->GetCPUDescriptorHandleForHeapStart() );

	// Record commands.
	const float clearColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
	m_graphicCmdList->ClearRenderTargetView( rtvHandle, clearColor, 0, nullptr );
	m_graphicCmdList->ClearDepthStencilView( m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr );
	m_graphicCmdList->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
	m_graphicCmdList->IASetVertexBuffers( 0, 1, &m_vertexBufferView );
	m_graphicCmdList->IASetIndexBuffer( &m_indexBufferView );
	m_graphicCmdList->DrawIndexedInstanced( 36, 1, 0, 0, 0 );

	// Indicate that the back buffer will now be used to present.
	D3D12_RESOURCE_BARRIER resourceBarriersAfter[] = {
		CD3DX12_RESOURCE_BARRIER::Transition( m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT ),
		CD3DX12_RESOURCE_BARRIER::Transition( m_volumeBuffer.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS )
	};
	m_graphicCmdList->ResourceBarrier( 2, resourceBarriersAfter );
	V( m_graphicCmdList->Close() );
}