void SSAO::Run()

in PCSamples/Raytracing/RaytracingAO_PC12/SSAO.cpp [1035:1517]


void SSAO::Run(ID3D12Resource* pSceneConstantResource)
{
    auto commandList = m_deviceResources->GetCommandList();
    auto renderTarget = m_deviceResources->GetRenderTarget();

    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"SSAO");

    // Clear DSV.
    commandList->ClearDepthStencilView(
        m_dsvDescriptors->GetCpuHandle(SSAODSVDesc::DSVGBuffer),
        D3D12_CLEAR_FLAG_DEPTH,
        1.f,
        0,
        0,
        nullptr);

    // Setup screenspace.
    auto viewport = m_deviceResources->GetScreenViewport();
    viewport.Width *= m_screenWidthScale;

    commandList->RSSetViewports(1, &viewport);
    D3D12_RECT sissorRect = m_deviceResources->GetScissorRect();
    commandList->RSSetScissorRects(1, &sissorRect);

    commandList->SetGraphicsRootSignature(m_rootSignature.Get());
    commandList->SetComputeRootSignature(m_rootSignature.Get());

    ID3D12DescriptorHeap* ppHeaps[] = { m_csuDescriptors->Heap(), m_samplerDescriptors->Heap() };
    commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

    // Set graphics tables.
    {
        commandList->SetGraphicsRootConstantBufferView(
            SSAORootSig::RootSceneConstSlot,
            pSceneConstantResource->GetGPUVirtualAddress());
    }

    // Set compute tables.
    {
        commandList->SetComputeRootConstantBufferView(
            SSAORootSig::RootSceneConstSlot,
            pSceneConstantResource->GetGPUVirtualAddress());
        commandList->SetComputeRootDescriptorTable(
            SSAORootSig::RootSamplerSlot,
            m_samplerDescriptors->GetGpuHandle(SSAOSamplerDesc::SamplerLinearWrap));
    }

    // Phase 1: Render GBuffer.
    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render GBuffer");
    {
        D3D12_RESOURCE_BARRIER startBarrier[] = 
        {
            CD3DX12_RESOURCE_BARRIER::Transition(m_gBufferResource.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)
        };

        commandList->ResourceBarrier(_countof(startBarrier), startBarrier);
        commandList->SetPipelineState(m_gBufferResourcePipelineState.Get());

        D3D12_CPU_DESCRIPTOR_HANDLE rtvDescHandle = m_rtvDescriptors->GetCpuHandle(SSAORTVDesc::RTVGBuffer);
        D3D12_CPU_DESCRIPTOR_HANDLE dsvDescHandle = m_dsvDescriptors->GetCpuHandle(SSAODSVDesc::DSVGBuffer);
        commandList->OMSetRenderTargets(1, &rtvDescHandle, FALSE, &dsvDescHandle);

        // Record commands.
        unsigned int offset = 0;
        for (auto el : *m_mesh)
        {
            D3D12_VERTEX_BUFFER_VIEW vbv;
            vbv.BufferLocation = el.vertexResource->GetGPUVirtualAddress();
            vbv.StrideInBytes = el.stride;
            vbv.SizeInBytes = static_cast<unsigned int>(el.numVertices * sizeof(Vertex));
            commandList->IASetVertexBuffers(0, 1, &vbv);

            D3D12_INDEX_BUFFER_VIEW ibv;
            ibv.BufferLocation = el.indexResource->GetGPUVirtualAddress();
            ibv.SizeInBytes = static_cast<unsigned int>(el.numIndices * sizeof(unsigned int));
            ibv.Format = DXGI_FORMAT_R32_UINT;
            commandList->IASetIndexBuffer(&ibv);

            commandList->SetGraphicsRootConstantBufferView(
                SSAORootSig::RootMaterialConstSlot,
                m_materialListCB[offset / SSAOPerObjectCSUDesc::CSUCount]->GetGPUVirtualAddress());

            D3D12_GPU_DESCRIPTOR_HANDLE handleSRV[] = {
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVPerObjectStart + SSAOPerObjectCSUDesc::SRVDiffuse + offset),
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVPerObjectStart + SSAOPerObjectCSUDesc::SRVSpecular + offset),
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVPerObjectStart + SSAOPerObjectCSUDesc::SRVNormal + offset)
            };
            BindSRVGraphics(handleSRV, _countof(handleSRV));

            commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
            commandList->DrawIndexedInstanced(el.numIndices, 2, 0, 0, 0);

            offset += SSAOPerObjectCSUDesc::CSUCount;
        }

        // Convert RTV and DBV to shader readable resources.
        D3D12_RESOURCE_BARRIER RTVToGBufferBarrier[] = {
            CD3DX12_RESOURCE_BARRIER::Transition(m_gBufferResource.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
            CD3DX12_RESOURCE_BARRIER::Transition(m_dBufferResource.Get(), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
        };
        commandList->ResourceBarrier(_countof(RTVToGBufferBarrier), RTVToGBufferBarrier);
    }
    PIXEndEvent(commandList);

    // Phase 2: Decompress, linearize, downsample, and deinterleave the depth buffer.
    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Decompress and Downsample.");
    {
        {
            // Setup SRV and UAV
            {
                D3D12_GPU_DESCRIPTOR_HANDLE handleSRV[] = {
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepth),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVGBuffer)
                };
                BindSRVCompute(handleSRV, _countof(handleSRV));

                D3D12_GPU_DESCRIPTOR_HANDLE handleUAV[] = {
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVLinearDepth),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthDownsizeStart),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthTiledStart),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthDownsizeStart + 1),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthTiledStart + 1),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalDownsizeStart),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalTiledStart),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalDownsizeStart + 1),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalTiledStart + 1)
                };
                BindUAVCompute(handleUAV, _countof(handleUAV));
            }

            commandList->SetPipelineState(m_SSAOPrepareDepthBuffers1PipelineState.Get());

            auto desc = m_depthTiledResource[1]->GetDesc();
            commandList->Dispatch(GetNumGrps(unsigned int(desc.Width) * 8, 8), GetNumGrps(desc.Height * 8, 8), 1);
        }

        {
            // Setup SRV and UAV
            {
                D3D12_RESOURCE_BARRIER startBarrier[] = {
                    CD3DX12_RESOURCE_BARRIER::Transition(m_depthDownsizeResource[1].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                    CD3DX12_RESOURCE_BARRIER::Transition(m_normalDownsizeResource[1].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                };
                commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

                D3D12_GPU_DESCRIPTOR_HANDLE handleSRV[] = {
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + 1),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVNormalDownsizeStart + 1)
                };
                BindSRVCompute(handleSRV, _countof(handleSRV));

                D3D12_GPU_DESCRIPTOR_HANDLE handleUAV[] = {
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthDownsizeStart + 2),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthTiledStart + 2),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthDownsizeStart + 3),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVDepthTiledStart + 3),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalDownsizeStart + 2),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalTiledStart + 2),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalDownsizeStart + 3),
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVNormalTiledStart + 3)
                };
                BindUAVCompute(handleUAV, _countof(handleUAV));

                D3D12_RESOURCE_BARRIER endBarrier[] = {
                    CD3DX12_RESOURCE_BARRIER::Transition(m_depthDownsizeResource[1].Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS),
                    CD3DX12_RESOURCE_BARRIER::Transition(m_normalDownsizeResource[1].Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                };
                commandList->ResourceBarrier(_countof(endBarrier), endBarrier);
            }

            commandList->SetPipelineState(m_SSAOPrepareDepthBuffers2PipelineState.Get());

            auto desc = m_depthTiledResource[3]->GetDesc();
            commandList->Dispatch(GetNumGrps(unsigned int(desc.Width) * 8, 8), GetNumGrps(desc.Height * 8, 8), 1);
        }
    }
    PIXEndEvent(commandList);

    // Phase 3: Render SSAO for each sub-tile.
    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render SSAO.");
    {
        PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Depth Tiled.");
        {
            commandList->SetPipelineState(m_SSAOPRender1PipelineState.Get());

            for (unsigned int i = 0; i < _countof(m_depthTiledResource); i++)
            {
                D3D12_RESOURCE_BARRIER startBarrier[] = {
                    CD3DX12_RESOURCE_BARRIER::Transition(m_depthTiledResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                    CD3DX12_RESOURCE_BARRIER::Transition(m_normalTiledResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                };

                commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

                {
                    auto desc = m_depthTiledResource[i]->GetDesc();
                    DispatchSSAO(
                        m_mappedDepthTiledSSAORenderConstantResource[i]->GetGPUVirtualAddress(),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVMergedStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthTiledStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVNormalTiledStart + i),
                        unsigned int(desc.Width),
                        desc.Height,
                        desc.DepthOrArraySize
                    );
                }
            }
        }
        PIXEndEvent(commandList);

        PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Depth Downsize.");
        {
            commandList->SetPipelineState(m_SSAOPRender2PipelineState.Get());

            for (unsigned int i = 0; i < _countof(m_depthDownsizeResource); i++)
            {
                D3D12_RESOURCE_BARRIER startBarrier[] = {
                    CD3DX12_RESOURCE_BARRIER::Transition(m_depthDownsizeResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                    CD3DX12_RESOURCE_BARRIER::Transition(m_normalDownsizeResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                };
                commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

                {
                    auto desc = m_highQualityResource[i]->GetDesc();
                    DispatchSSAO(
                        m_mappedHighQualitySSAORenderConstantResource[i]->GetGPUVirtualAddress(),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVHighQualityStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVNormalDownsizeStart + i),
                        unsigned int(desc.Width),
                        unsigned int(desc.Height),
                        desc.DepthOrArraySize
                    );
                }
            }
        }
        PIXEndEvent(commandList);
    }
    PIXEndEvent(commandList);

    // Phase 4: Iteratively blur and upsample, combining each result.
    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Blur and Upsample.");
    {
        commandList->SetPipelineState(m_SSAOBlurUpsamplePreMinBlendOutPipelineState.Get());

        // Every iteration is twice larger in every dimension.
        for (unsigned int i = _countof(m_depthDownsizeResource) - 1; i != std::numeric_limits<unsigned int>::max(); i--)
        {
            // Edge cases (first and last) are taken into account.
            {
                if (i == _countof(m_depthDownsizeResource) - 1)
                {
                    D3D12_RESOURCE_BARRIER startBarrier[] = {
                        CD3DX12_RESOURCE_BARRIER::Transition(m_mergedResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                        CD3DX12_RESOURCE_BARRIER::Transition(m_mergedResource[i - 1].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                        CD3DX12_RESOURCE_BARRIER::Transition(m_highQualityResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                    };
                    commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

                    auto desc = m_depthDownsizeResource[i - 1]->GetDesc();
                    DispatchBlurAndUpsample(
                        m_mappedBlurAndUpscaleConstantResource[i]->GetGPUVirtualAddress(),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVSmoothStart + i - 1),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + i - 1),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVMergedStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVMergedStart + i - 1),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVHighQualityStart + i),
                        unsigned int(desc.Width),
                        unsigned int(desc.Height)
                    );
                }
                else if (i == 0)
                {
                    // Since this is the last index of the loop, setting a new pipeline does not effect any other cases.
                    commandList->SetPipelineState(m_SSAOBlurUpsamplePreMinPipelineState.Get());

                    D3D12_RESOURCE_BARRIER startBarrier[] = {
                        CD3DX12_RESOURCE_BARRIER::Transition(m_smoothResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                        CD3DX12_RESOURCE_BARRIER::Transition(m_linearDepthResource.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                        CD3DX12_RESOURCE_BARRIER::Transition(m_highQualityResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                    };
                    commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

                    auto desc = m_linearDepthResource->GetDesc();
                    DispatchBlurAndUpsample(
                        m_mappedBlurAndUpscaleConstantResource[i]->GetGPUVirtualAddress(),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVSSAO),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVLinearDepth),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVSmoothStart + i),
                        { reinterpret_cast<D3D12_GPU_VIRTUAL_ADDRESS>(nullptr) },
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVHighQualityStart + i),
                        unsigned int(desc.Width),
                        unsigned int(desc.Height)
                    );
                }
                else
                {
                    D3D12_RESOURCE_BARRIER startBarrier[] = {
                        CD3DX12_RESOURCE_BARRIER::Transition(m_smoothResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                        CD3DX12_RESOURCE_BARRIER::Transition(m_mergedResource[i - 1].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE),
                        CD3DX12_RESOURCE_BARRIER::Transition(m_highQualityResource[i].Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                    };
                    commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

                    auto desc = m_depthDownsizeResource[i - 1]->GetDesc();
                    DispatchBlurAndUpsample(
                        m_mappedBlurAndUpscaleConstantResource[i]->GetGPUVirtualAddress(),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVSmoothStart + i - 1),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepthDownsizeStart + i - 1),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVSmoothStart + i),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVMergedStart + i - 1),
                        m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVHighQualityStart + i),
                        unsigned int(desc.Width),
                        unsigned int(desc.Height)
                    );
                }
            }
        }
    }
    PIXEndEvent(commandList);

    // Phase 5: Render.
    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Render.");
    {
        // Setup SRV and UAV
        {
            {
                D3D12_RESOURCE_BARRIER startBarrier[] = {
                    CD3DX12_RESOURCE_BARRIER::Transition(m_ssaoResources.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)
                };
                commandList->ResourceBarrier(_countof(startBarrier), startBarrier);
            }

            D3D12_GPU_DESCRIPTOR_HANDLE handleSRV[] = {
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVSSAO),
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVGBuffer),
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVDepth),
            };
            BindSRVCompute(handleSRV, _countof(handleSRV));

            D3D12_GPU_DESCRIPTOR_HANDLE handleUAV[] = {
                m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::UAVOutFrame)
            };
            BindUAVCompute(handleUAV, _countof(handleUAV));
        }

        commandList->SetPipelineState(m_SSAOGBufferRenderPipelineState.Get());

        commandList->Dispatch(GetNumGrps(bufferWidth[1] * 8, 8), GetNumGrps(bufferHeight[1] * 8, 8), 1);
    }
    PIXEndEvent(commandList);

    // Phase 6: Copy to BackBuffer.
    PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Copy to Back Buffer.");
    {
        if (m_screenWidthScale == 1.f)
        {
            D3D12_RESOURCE_BARRIER startBarrier[] = {
                CD3DX12_RESOURCE_BARRIER::Transition(renderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_DEST),
                CD3DX12_RESOURCE_BARRIER::Transition(m_outFrameResources.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)
            };
            commandList->ResourceBarrier(_countof(startBarrier), startBarrier);

            commandList->CopyResource(renderTarget, m_outFrameResources.Get());

            D3D12_RESOURCE_BARRIER endBarrier[] = {
                CD3DX12_RESOURCE_BARRIER::Transition(renderTarget, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_RENDER_TARGET),
                CD3DX12_RESOURCE_BARRIER::Transition(m_outFrameResources.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
            };
            commandList->ResourceBarrier(_countof(endBarrier), endBarrier);
        }
        else
        {
            D3D12_RESOURCE_BARRIER startBarrier[] = {
                CD3DX12_RESOURCE_BARRIER::Transition(m_outFrameResources.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)
            };
            commandList->ResourceBarrier(_countof(startBarrier), startBarrier);
            CD3DX12_CPU_DESCRIPTOR_HANDLE renderTargetView = m_deviceResources->GetRenderTargetView();
            commandList->OMSetRenderTargets(
                1,
                &renderTargetView,
                FALSE,
                nullptr
            );

            D3D12_VIEWPORT screenViewport = m_deviceResources->GetScreenViewport();
            commandList->RSSetViewports(1, &screenViewport);

            {
                m_basicEffect->SetTexture(
                    m_csuDescriptors->GetGpuHandle(SSAOCSUDesc::SRVOutFrame),
                    m_samplerDescriptors->GetGpuHandle(SSAOSamplerDesc::SamplerLinearClamp)
                );
                m_basicEffect->Apply(commandList);
                m_primitiveBatch->Begin(commandList);
                {
                    // Left Quad.
                    {
                        m_primitiveBatch->DrawQuad(
                            { XMFLOAT3(0.f, 0.f, 0.f),{ 0.f, 0.f } },
                            { XMFLOAT3(m_screenWidthScale, 0.f, 0.f),{ 1.f, 0.f } },
                            { XMFLOAT3(m_screenWidthScale, 1.f, 0.f),{ 1.f, 1.f } },
                            { XMFLOAT3(0.f, 1.f, 0.f),{ 0.f, 1.f } }
                        );
                    }
                }
                m_primitiveBatch->End();
            }

            D3D12_RESOURCE_BARRIER endBarrier[] = {
                CD3DX12_RESOURCE_BARRIER::Transition(m_outFrameResources.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
            };
            commandList->ResourceBarrier(_countof(endBarrier), endBarrier);
        }
    }
    PIXEndEvent(commandList);

    // Restore original state.
    {
        std::vector<D3D12_RESOURCE_BARRIER> restoreBufferBarrier = {
            CD3DX12_RESOURCE_BARRIER::Transition(m_dBufferResource.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE),
            CD3DX12_RESOURCE_BARRIER::Transition(m_linearDepthResource.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS),
            CD3DX12_RESOURCE_BARRIER::Transition(m_ssaoResources.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
        };
        {
            for (auto& el : m_depthDownsizeResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }

            for (auto& el : m_depthTiledResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }

            for (auto& el : m_normalDownsizeResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }

            for (auto& el : m_normalTiledResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }

            for (auto& el : m_highQualityResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }

            for (auto& el : m_mergedResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }

            for (auto& el : m_smoothResource)
            {
                restoreBufferBarrier.push_back(
                    CD3DX12_RESOURCE_BARRIER::Transition(el.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)
                );
            }
        }

        commandList->ResourceBarrier(unsigned int(restoreBufferBarrier.size()), restoreBufferBarrier.data());
    }

    PIXEndEvent(commandList);
}