/*
===========================================================================
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/>.
===========================================================================
*/
// Gameplay Rendering Pipeline - vertex and index buffer management


#include "grp_local.h"


void VertexBuffers::Create(const char* name, MemoryUsage::Id memoryUsage, uint32_t vertexCount)
{
	totalCount = vertexCount;

	BufferDesc desc = {};
	desc.committedResource = true;
	desc.initialState = ResourceStates::VertexBufferBit;
	desc.memoryUsage = memoryUsage;

	desc.name = va("%s position vertex", name);
	desc.byteCount = vertexCount * sizeof(vec3_t);
	buffers[BasePosition] = CreateBuffer(desc);
	strides[BasePosition] = sizeof(vec3_t);

	desc.name = va("%s normal vertex", name);
	desc.byteCount = vertexCount * sizeof(vec3_t);
	buffers[BaseNormal] = CreateBuffer(desc);
	strides[BaseNormal] = sizeof(vec3_t);

	for(uint32_t s = 0; s < MAX_SHADER_STAGES; ++s)
	{
		desc.name = va("%s tex coords #%d vertex", name, (int)s + 1);
		desc.byteCount = vertexCount * sizeof(vec2_t);
		buffers[BaseCount + s * StageCount + StageTexCoords] = CreateBuffer(desc);
		strides[BaseCount + s * StageCount + StageTexCoords] = sizeof(vec2_t);

		desc.name = va("%s color #%d vertex", name, (int)s + 1);
		desc.byteCount = vertexCount * sizeof(color4ub_t);
		buffers[BaseCount + s * StageCount + StageColors] = CreateBuffer(desc);
		strides[BaseCount + s * StageCount + StageColors] = sizeof(color4ub_t);
	}
}

void VertexBuffers::BeginUpload()
{
	for(uint32_t b = 0; b < BufferCount; ++b)
	{
		mapped[b] = BeginBufferUpload(buffers[b]);
	}
}

void VertexBuffers::EndUpload()
{
	for(uint32_t b = 0; b < BufferCount; ++b)
	{
		EndBufferUpload(buffers[b]);
		mapped[b] = NULL;
	}
}

void VertexBuffers::Upload(uint32_t firstStage, uint32_t stageCount)
{
	Q_assert(mapped[0] != NULL);

	const uint32_t batchOffset = batchFirst + batchCount;

	float* pos = (float*)mapped[BasePosition] + 3 * batchOffset;
	for(int v = 0; v < tess.numVertexes; ++v)
	{
		pos[0] = tess.xyz[v][0];
		pos[1] = tess.xyz[v][1];
		pos[2] = tess.xyz[v][2];
		pos += 3;
	}

	float* nor = (float*)mapped[BaseNormal] + 3 * batchOffset;
	for(int v = 0; v < tess.numVertexes; ++v)
	{
		nor[0] = tess.normal[v][0];
		nor[1] = tess.normal[v][1];
		nor[2] = tess.normal[v][2];
		nor += 3;
	}

	for(uint32_t s = 0; s < stageCount; ++s)
	{
		const stageVars_t& sv = tess.svars[s + firstStage];

		uint8_t* const tcBuffer = mapped[BaseCount + s * StageCount + StageTexCoords];
		float* tc = (float*)tcBuffer + 2 * batchOffset;
		memcpy(tc, &sv.texcoords[0], tess.numVertexes * sizeof(vec2_t));

		uint8_t* const colBuffer = mapped[BaseCount + s * StageCount + StageColors];
		uint32_t* col = (uint32_t*)colBuffer + batchOffset;
		memcpy(col, &sv.colors[0], tess.numVertexes * sizeof(color4ub_t));
	}
}
