#pragma once

#include "GLExtensions.h"
#include "ShaderTypes.h"

#include <map>
#include <string>
#include <vector>

class ShaderFeedbackBuffers
{
public:
	struct Slot
	{
		GLuint texture = 0;
		GLuint framebuffer = 0;
	};

	struct Surface
	{
		Slot slots[2];
		unsigned width = 0;
		unsigned height = 0;
		unsigned readIndex = 0;
		bool hasData = false;
		bool pendingWrite = false;
	};

	bool EnsureResources(const std::vector<RuntimeRenderState>& layerStates, unsigned frameWidth, unsigned frameHeight, std::string& error);
	void DestroyResources();
	void ResetState();
	GLuint ResolveReadTexture(const RuntimeRenderState& state) const;
	bool FeedbackAvailable(const RuntimeRenderState& state) const;
	void CaptureFeedbackFramebuffer(const std::string& layerId, GLuint sourceFramebuffer, unsigned frameWidth, unsigned frameHeight);
	void FinalizeFrame();

private:
	bool EnsureZeroTexture();
	bool CreateSurface(Surface& surface, unsigned frameWidth, unsigned frameHeight, std::string& error);
	void DestroySurface(Surface& surface);
	void ClearSurfaceState(Surface& surface);

private:
	std::map<std::string, Surface> mSurfacesByLayerId;
	GLuint mZeroTexture = 0;
};
