/*
	ZShaderParams.hpp
	Author: James Russell <jcrussell@762studios.com>
	Created: 7/1/2012

	Purpose: 

	Shader parameters class, to which uniform buffers and samplers are bound 
	and passed to draw calls.  The attached buffers and samplers will be used 
	to provide data to the shader.

	License:

	TODO

*/

#pragma once

#ifndef _ZSHADERPARAMS_HPP
#define _ZSHADERPARAMS_HPP

#include <ZRenderer/ZDrawParams.hpp>

#include <ZSTL/ZSTL.hpp>

#include <ZUtil/ZUtil.hpp>

#include <ZRenderer/ZDataBuffer.hpp>
#include <ZRenderer/ZTexture.hpp>
#include <ZRenderer/ZSampler.hpp>

#ifndef ZSP_MAX_UNIFORM_BLOCKS
#define ZSP_MAX_UNIFORM_BLOCKS (128)
#endif

#ifndef ZSP_MAX_SAMPLERS
#define ZSP_MAX_SAMPLERS (32)
#endif

//Shader Parameters Structure, used to hold shader parameters
class ZShaderParams : public ZDrawParams
{
private:
	DISABLE_COPY_AND_ASSIGN(ZShaderParams);

protected:    
	//A uniform block binding
	struct UniformBlockBinding
	{
		ZName Name;												//Name of the uniform block binding
		ZPtr<ZDataBuffer> Buffer;								//Parent buffer

		ZPair<ZDataBuffer*, const ZDataBufferBlock*> Binding;	//Pair Binding
	};

	//A sampler binding
	struct SamplerBinding
	{
		ZName Name;								//Name of the sampler binding
		ZPtr<ZSampler> Sampler;					//Sampler
		ZPtr<ZTexture> Texture;					//Texture

		ZPair<ZSampler*, ZTexture*> Binding;	//Pair binding 
	};

	//These are the buffer bindings and samplers that are provided to the shader program
	UniformBlockBinding UniformBlockBindings[ZSP_MAX_UNIFORM_BLOCKS];
	SamplerBinding	    SamplerBindings[ZSP_MAX_SAMPLERS];

	//Our current uniform block count and sampler count
	size_t UniformBlockBindingCount;
	size_t SamplerBindingCount;


public:

	/*
	Default Constructor.
	*/
	ZShaderParams();

	virtual ~ZShaderParams() { }

	/*
	public ZShaderParams::ClearUniformBufferBlocks
	
	Clears the current set of uniform buffer blocks.
	
	@return (void)
	@context (all)
	*/
	void ClearUniformBufferBlocks();

	/*
	public ZShaderParams::ClearSamplers
	
	Clears the current set of sampler bindings.
	
	@return (void)
	@context (all)
	*/
	void ClearSamplers();

	/*
	public ZShaderParams::SetUniformBufferBlock
	
	Sets the value of a uniform buffer block for a shader.  Set to NULL using overload 
	to remove binding.
	
	@param _name - the name of the uniform block in the shader
	@param _buffer - the buffer containing the values
	@param _block - the block definition for the buffer block
	@return (void)
	@context (all)
	*/
	void SetUniformBufferBlock(const ZName& _name, ZPtr<ZDataBuffer> _buffer, const ZDataBufferBlock* _block);

	/*
	public ZShaderParams::SetSampler
	
	Sets the value of a sampler for a shader. 

	@param _name - the name of the sampler in the shader
	@param _sampler - the sampler object to use
	@param _texture - the texture the sampler object is a view onto
	@return (void)
	@context (all)
	*/
	void SetSampler(const ZName& _name, ZPtr<ZSampler> _sampler, ZPtr<ZTexture> _texture);

	/*
	The following methods are used by the renderer to get the values needed when
	binding shader parameter values to pass to the shader program, to mark
	all bound resources as contended, and release contention.
	*/
	const ZPair<ZDataBuffer*, const ZDataBufferBlock*>* GetUniformBlockByName(const ZName& _name);
	const ZPair<ZSampler*, ZTexture*>* GetSamplerByName(const ZName& _name);

	//Subclass Override
	virtual void MarkResourcesContended();
	
	//Subclass Override
	virtual void ReleaseResourceContention();
};

#endif 
