void GraphicsContext::SetRenderTargets( UINT NumRTVs, ITextureViewD3D12** ppRTVs, ITextureViewD3D12* pDSV ) { D3D12_CPU_DESCRIPTOR_HANDLE RTVHandles[8]; // Do not waste time initializing array to zero for (UINT i = 0; i < NumRTVs; ++i) { auto *pRTV = ppRTVs[i]; if( pRTV ) { auto *pTexture = ValidatedCast<TextureD3D12Impl>( pRTV->GetTexture() ); TransitionResource(pTexture, D3D12_RESOURCE_STATE_RENDER_TARGET); RTVHandles[i] = pRTV->GetCPUDescriptorHandle(); } } if (pDSV) { auto *pTexture = ValidatedCast<TextureD3D12Impl>( pDSV->GetTexture() ); //if (bReadOnlyDepth) //{ // TransitionResource(*pTexture, D3D12_RESOURCE_STATE_DEPTH_READ); // m_pCommandList->OMSetRenderTargets( NumRTVs, RTVHandles, FALSE, &DSV->GetDSV_DepthReadOnly() ); //} //else { TransitionResource(pTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE); auto DSVHandle = pDSV->GetCPUDescriptorHandle(); m_pCommandList->OMSetRenderTargets( NumRTVs, RTVHandles, FALSE, &DSVHandle ); } } else { m_pCommandList->OMSetRenderTargets( NumRTVs, RTVHandles, FALSE, nullptr ); } }
void CommandContext::BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate) { // If it's already transitioning, finish that transition if (Resource.m_TransitioningState != (D3D12_RESOURCE_STATES)-1) TransitionResource(Resource, Resource.m_TransitioningState); D3D12_RESOURCE_STATES OldState = Resource.m_UsageState; if (OldState != NewState) { ASSERT(m_NumBarriersToFlush < 16, "Exceeded arbitrary limit on buffered barriers"); D3D12_RESOURCE_BARRIER& BarrierDesc = m_ResourceBarrierBuffer[m_NumBarriersToFlush++]; BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; BarrierDesc.Transition.pResource = Resource.GetResource(); BarrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; BarrierDesc.Transition.StateBefore = OldState; BarrierDesc.Transition.StateAfter = NewState; BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY; Resource.m_TransitioningState = NewState; } if (FlushImmediate || m_NumBarriersToFlush == 16) { m_pCommandList->ResourceBarrier(m_NumBarriersToFlush, m_ResourceBarrierBuffer); m_NumBarriersToFlush = 0; } }
void CommandContext::ClearUAVFloat( ITextureViewD3D12 *pTexView, const float* Color ) { auto *pTexture = ValidatedCast<TextureD3D12Impl>( pTexView->GetTexture() ); TransitionResource(pTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true); // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs // a shader to set all of the values). UNSUPPORTED("Not yet implemented"); D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = {};//m_DynamicDescriptorHeap.UploadDirect(Target.GetUAV()); m_pCommandList->ClearUnorderedAccessViewFloat(GpuVisibleHandle, pTexView->GetCPUDescriptorHandle(), pTexture->GetD3D12Resource(), Color, 0, nullptr); }
//---------------------------------------------------------------------------// void RenderContextDX12::ApplyRenderTargets() { if (!myRenderTargetsDirty) return; myRenderTargetsDirty = false; D3D12_CPU_DESCRIPTOR_HANDLE rtDescriptors[Rendering::Constants::kMaxNumRenderTargets]; GpuResource* rtResources[Rendering::Constants::kMaxNumRenderTargets]; uint32 numRtsToSet = 0u; for (uint32 i = 0u; i < Rendering::Constants::kMaxNumRenderTargets; ++i) { Texture* rt = myRenderTargets[i]; if (rt != nullptr) { rtResources[numRtsToSet] = rt; rtDescriptors[numRtsToSet] = rt->GetRtv().myCpuHandle; ++numRtsToSet; } } for (uint32 i = 0u; i < numRtsToSet; ++i) { TransitionResource(rtResources[i], D3D12_RESOURCE_STATE_RENDER_TARGET); } if (myDepthStencilTarget) TransitionResource(myDepthStencilTarget, D3D12_RESOURCE_STATE_DEPTH_WRITE); KickoffResourceBarriers(); if (myDepthStencilTarget) myCommandList->OMSetRenderTargets(numRtsToSet, rtDescriptors, false, &myDepthStencilTarget->GetDsv().myCpuHandle); else myCommandList->OMSetRenderTargets(numRtsToSet, rtDescriptors, false, nullptr); }
void CommandContext::CopySubresource(GpuResource& Dest, UINT DestSubIndex, GpuResource& Src, UINT SrcSubIndex) { // TODO: Add a TransitionSubresource()? TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST); TransitionResource(Src, D3D12_RESOURCE_STATE_COPY_SOURCE); FlushResourceBarriers(); D3D12_TEXTURE_COPY_LOCATION DestLocation = { Dest.GetResource(), D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, DestSubIndex }; D3D12_TEXTURE_COPY_LOCATION SrcLocation = { Src.GetResource(), D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, SrcSubIndex }; m_pCommandList->CopyTextureRegion(&DestLocation, 0, 0, 0, &SrcLocation, nullptr); }
void CommandContext::ClearUAVUint( ITextureViewD3D12 *pTexView, const UINT *Color ) { auto *pTexture = ValidatedCast<TextureD3D12Impl>( pTexView->GetTexture() ); TransitionResource(pTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true); // After binding a UAV, we can get a GPU handle that is required to clear it as a UAV (because it essentially runs // a shader to set all of the values). UNSUPPORTED("Not yet implemented"); D3D12_GPU_DESCRIPTOR_HANDLE GpuVisibleHandle = {};//m_DynamicDescriptorHeap.UploadDirect(Target.GetUAV()); //CD3DX12_RECT ClearRect(0, 0, (LONG)Target.GetWidth(), (LONG)Target.GetHeight()); //TODO: My Nvidia card is not clearing UAVs with either Float or Uint variants. m_pCommandList->ClearUnorderedAccessViewUint(GpuVisibleHandle, pTexView->GetCPUDescriptorHandle(), pTexture->GetD3D12Resource(), Color, 0, nullptr/*1, &ClearRect*/); }
void CommandContext::TransitionResource(IBufferD3D12 *pBuffer, D3D12_RESOURCE_STATES NewState, bool FlushImmediate) { VERIFY_EXPR( pBuffer != nullptr ); auto *pBuffD3D12 = ValidatedCast<BufferD3D12Impl>(pBuffer); #ifdef _DEBUG // Dynamic buffers are suballocated in the upload heap when Map() is called // and must always be in D3D12_RESOURCE_STATE_GENERIC_READ state if(pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC) { VERIFY(pBuffD3D12->GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Dynamic buffers are expected to always be in D3D12_RESOURCE_STATE_GENERIC_READ state") VERIFY( (NewState & D3D12_RESOURCE_STATE_GENERIC_READ) == NewState, "Dynamic buffers can only transition to one of D3D12_RESOURCE_STATE_GENERIC_READ states") } #endif TransitionResource(*pBuffD3D12, *pBuffD3D12, NewState, FlushImmediate); #ifdef _DEBUG if(pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC) VERIFY(pBuffD3D12->GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Dynamic buffers are expected to never transition from D3D12_RESOURCE_STATE_GENERIC_READ state") #endif }
void CommandContext::TransitionResource(ITextureD3D12 *pTexture, D3D12_RESOURCE_STATES NewState, bool FlushImmediate) { VERIFY_EXPR( pTexture != nullptr ); auto *pTexD3D12 = ValidatedCast<TextureD3D12Impl>(pTexture); TransitionResource(*pTexD3D12, *pTexD3D12, NewState, FlushImmediate); }
void GraphicsContext::ClearDepthStencil( ITextureViewD3D12 *pDSV, D3D12_CLEAR_FLAGS ClearFlags, float Depth, UINT8 Stencil ) { auto *pTexture = ValidatedCast<TextureD3D12Impl>( pDSV->GetTexture() ); TransitionResource( pTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, true); m_pCommandList->ClearDepthStencilView(pDSV->GetCPUDescriptorHandle(), ClearFlags, Depth, Stencil, 0, nullptr); }
void GraphicsContext::ClearRenderTarget( ITextureViewD3D12 *pRTV, const float *Color ) { auto *pTexture = ValidatedCast<TextureD3D12Impl>( pRTV->GetTexture() ); TransitionResource(pTexture, D3D12_RESOURCE_STATE_RENDER_TARGET, true); m_pCommandList->ClearRenderTargetView(pRTV->GetCPUDescriptorHandle(), Color, 0, nullptr); }