/*
===========================================================================
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 - OIT resolve pass


#include "crp_local.h"
#include "compshaders/crp/fullscreen.h"
#include "compshaders/crp/transp_resolve.h"


#pragma pack(push, 4)
struct TranspResolveRC
{
	uint32_t renderTargetTexture;
	uint32_t shaderIndexBuffer;
	uint32_t indexTexture;
	uint32_t fragmentBuffer;
	uint16_t centerPixelX;
	uint16_t centerPixelY;
	uint32_t depthTexture;
	float linearDepthA;
	float linearDepthB;
	float scissorMinX;
	float scissorMinY;
	float scissorMaxX;
	float scissorMaxY;
};
#pragma pack(pop)


void TranspResolve::Init()
{
	GraphicsPipelineDesc desc("OIT Resolve");
	MakeFullScreenPipeline(desc, ShaderByteCode(g_transp_resolve_ps));
	desc.AddRenderTarget(0, crp.renderTargetFormat);
	pipeline = CreateGraphicsPipeline(desc);
}

void TranspResolve::Draw(const drawSceneViewCommand_t& cmd)
{
	if(cmd.numTranspSurfs <= 0)
	{
		return;
	}

	srp.renderMode = RenderMode::World;

	SCOPED_RENDER_PASS("OIT Resolve", 1.0f, 0.5f, 0.5f);

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

	crp.SwapRenderTargets();

	CmdBeginBarrier();
	CmdTextureBarrier(crp.GetReadRenderTarget(), ResourceStates::PixelShaderAccessBit);
	CmdTextureBarrier(crp.GetWriteRenderTarget(), ResourceStates::RenderTargetBit);
	CmdTextureBarrier(crp.oitIndexTexture, ResourceStates::UnorderedAccessBit);
	CmdTextureBarrier(crp.depthTexture, ResourceStates::PixelShaderAccessBit);
	CmdBufferBarrier(crp.oitFragmentBuffer, ResourceStates::UnorderedAccessBit);
	CmdBufferBarrier(srp.traceRenderBuffer, ResourceStates::UnorderedAccessBit);
	CmdEndBarrier();

	TranspResolveRC rc = {};
	rc.fragmentBuffer = GetBufferIndexUAV(crp.oitFragmentBuffer);
	rc.indexTexture = GetTextureIndexUAV(crp.oitIndexTexture, 0);
	rc.renderTargetTexture = GetTextureIndexSRV(crp.GetReadRenderTarget());
	rc.shaderIndexBuffer = GetBufferIndexUAV(srp.traceRenderBuffer);
	rc.centerPixelX = glConfig.vidWidth / 2;
	rc.centerPixelY = glConfig.vidHeight / 2;
	rc.depthTexture = GetTextureIndexSRV(crp.depthTexture);
	RB_LinearDepthConstants(&rc.linearDepthA, &rc.linearDepthB);
	rc.scissorMinX = backEnd.viewParms.viewportX;
	rc.scissorMinY = backEnd.viewParms.viewportY;
	rc.scissorMaxX = rc.scissorMinX + backEnd.viewParms.viewportWidth - 1;
	rc.scissorMaxY = rc.scissorMinY + backEnd.viewParms.viewportHeight - 1;

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