/*
===========================================================================
Copyright (C) 2023-2024 Gian 'myT' Schellenbaum

This file is part of Challenge Quake 3 (CNQ3).

Challenge Quake 3 is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.

Challenge Quake 3 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Challenge Quake 3. If not, see <https://www.gnu.org/licenses/>.
===========================================================================
*/
// Cinematic Rendering Pipeline - tone mapping


#include "crp_local.h"
#include "compshaders/crp/fullscreen.h"
#include "compshaders/crp/tone_map.h"
#include "compshaders/crp/tone_map_inverse.h"


#pragma pack(push, 4)

struct ToneMapRC
{
	uint32_t textureIndex;
	uint32_t samplerIndex;
	float invGamma;
	float brightness;
	float greyscale;
};

struct InverseToneMapRC
{
	uint32_t textureIndex;
	uint32_t samplerIndex;
	float gamma;
	float invBrightness;
};

#pragma pack(pop)


void ToneMap::Init()
{
	{
		GraphicsPipelineDesc desc("Tone Map");
		MakeFullScreenPipeline(desc, ShaderByteCode(g_tone_map_ps));
		desc.AddRenderTarget(0, crp.renderTargetFormat);
		pipeline = CreateGraphicsPipeline(desc);
	}

	{
		GraphicsPipelineDesc desc("Inverse Tone Map");
		MakeFullScreenPipeline(desc, ShaderByteCode(g_tone_map_inverse_ps));
		desc.AddRenderTarget(0, crp.renderTargetFormat);
		pipeline = CreateGraphicsPipeline(desc);
	}
}

void ToneMap::DrawToneMap()
{
	srp.renderMode = RenderMode::None;

	SCOPED_DEBUG_LABEL("Tone Map", 1.0f, 1.0f, 1.0f);

	CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);

	crp.SwapRenderTargets();

	CmdBeginBarrier();
	CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
	CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit);
	CmdEndBarrier();

	ToneMapRC rc = {};
	rc.textureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget());
	rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear);
	rc.invGamma = 1.0f / r_gamma->value;
	rc.brightness = r_brightness->value;
	rc.greyscale = r_greyscale->value;

	CmdBindRenderTargets(1, &crp.renderTarget, NULL);
	CmdBindPipeline(pipeline);
	CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
	CmdDraw(3, 0);
}

void ToneMap::DrawInverseToneMap()
{
	srp.renderMode = RenderMode::None;

	SCOPED_DEBUG_LABEL("Inverse Tone Map", 1.0f, 1.0f, 1.0f);

	CmdSetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);

	crp.SwapRenderTargets();

	CmdBeginBarrier();
	CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
	CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit);
	CmdEndBarrier();

	InverseToneMapRC rc = {};
	rc.textureIndex = GetTextureIndexSRV(crp.GetReadRenderTarget());
	rc.samplerIndex = GetSamplerIndex(TW_CLAMP_TO_EDGE, TextureFilter::Linear);
	rc.gamma = r_gamma->value;
	rc.invBrightness = 1.0f / r_brightness->value;

	CmdBindRenderTargets(1, &crp.renderTarget, NULL);
	CmdBindPipeline(inversePipeline);
	CmdSetGraphicsRootConstants(0, sizeof(rc), &rc);
	CmdDraw(3, 0);
}
