TempRenderTarget* PostProcessor::Bloom(ID3D11ShaderResourceView* input)
{
    PIXEvent pixEvent(L"Bloom");

    TempRenderTarget* downscale1 = GetTempRenderTarget(inputWidth / 2, inputHeight / 2, DXGI_FORMAT_R16G16B16A16_FLOAT);
    inputs.push_back(input);
    outputs.push_back(downscale1->RTView);
    PostProcess(bloom, L"Bloom Initial Pass");

    // Blur it
    for(uint64 i = 0; i < 2; ++i)
    {
        TempRenderTarget* blurTemp = GetTempRenderTarget(inputWidth / 2, inputHeight / 2, DXGI_FORMAT_R16G16B16A16_FLOAT);
        PostProcess(downscale1->SRView, blurTemp->RTView, blurH, L"Horizontal Bloom Blur");

        PostProcess(blurTemp->SRView, downscale1->RTView, blurV, L"Vertical Bloom Blur");
        blurTemp->InUse = false;
    }

    return downscale1;
}
void PostProcessor::Bloom(ID3D11ShaderResourceView* input, TempRenderTarget*& bloomTarget)
{
    // Downscale
    TempRenderTarget* bloomSrc = GetTempRenderTarget(inputWidth, inputHeight, DXGI_FORMAT_R11G11B10_FLOAT);

    inputs.push_back(input);
    inputs.push_back(adaptedLuminance[currLumTarget].SRView);
    outputs.push_back(bloomSrc->RTView);
    PostProcess(bloomThreshold, L"Bloom Threshold");

    TempRenderTarget* downscale1 = GetTempRenderTarget(inputWidth / 2, inputHeight / 2, DXGI_FORMAT_R11G11B10_FLOAT);
    PostProcess(bloomSrc->SRView, downscale1->RTView, scale, L"Bloom Downscale");
    bloomSrc->InUse = false;

    TempRenderTarget* downscale2 = GetTempRenderTarget(inputWidth / 4, inputHeight / 4, DXGI_FORMAT_R11G11B10_FLOAT);
    PostProcess(downscale1->SRView, downscale2->RTView, scale, L"Bloom Downscale");

    TempRenderTarget* downscale3 = GetTempRenderTarget(inputWidth / 8, inputHeight / 8, DXGI_FORMAT_R11G11B10_FLOAT);
    PostProcess(downscale2->SRView, downscale3->RTView, scale, L"Bloom Downscale");

    // Blur it
    for (uint64 i = 0; i < 4; ++i)
    {
        TempRenderTarget* blurTemp = GetTempRenderTarget(inputWidth / 8, inputHeight / 8, DXGI_FORMAT_R11G11B10_FLOAT);
        PostProcess(downscale3->SRView, blurTemp->RTView, bloomBlurH, L"Horizontal Bloom Blur");

        PostProcess(blurTemp->SRView, downscale3->RTView, bloomBlurV, L"Vertical Bloom Blur");
        blurTemp->InUse = false;
    }

    PostProcess(downscale3->SRView, downscale2->RTView, scale, L"Bloom Upscale");
    downscale3->InUse = false;

    PostProcess(downscale2->SRView, downscale1->RTView, scale, L"Bloom Upscale");
    downscale2->InUse = false;

    bloomTarget = downscale1;
}
void PostProcessor::CalcAvgLuminance(ID3D11ShaderResourceView* input)
{
    TempRenderTarget* initialLuminance = GetTempRenderTarget(LumMapSize, LumMapSize, DXGI_FORMAT_R32_FLOAT, 1, 0, 0, TRUE);

    // Luminance mapping
    PostProcess(input, initialLuminance->RTView, luminanceMap, L"Luminance Map Generation");

    // Generate the mip chain
    context->GenerateMips(initialLuminance->SRView);

    // Adaptation
    inputs.push_back(adaptedLuminance[!currLumTarget].SRView);
    inputs.push_back(initialLuminance->SRView);
    outputs.push_back(adaptedLuminance[currLumTarget].RTView);
    PostProcess(adaptLuminance, L"Luminance Adaptation");

    initialLuminance->InUse = FALSE;
}
void PostProcessor::ToneMap(ID3D11ShaderResourceView* input,
                            ID3D11ShaderResourceView* bloom,
                            ID3D11RenderTargetView* output)
{
    // Use an intermediate render target so that we can render do sRGB conversion ourselves in the shader
    TempRenderTarget* tmOutput = GetTempRenderTarget(inputWidth, inputHeight, DXGI_FORMAT_R8G8B8A8_UNORM);

    inputs.push_back(input);
    inputs.push_back(bloom);
    outputs.push_back(tmOutput->RTView);

    PostProcess(toneMap, L"Tone Mapping");

    ID3D11ResourcePtr outputResource;
    output->GetResource(&outputResource);

    context->CopyResource(outputResource, tmOutput->Texture);

    tmOutput->InUse = false;
}