//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007-2008)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: shader_reflection_d3d10.cpp
//      Краткое описание: Сборщик информации о шейдере для платформы DirectX 10
//

#ifdef GD_D3D10

#include <Darkstar/Graphic System/Effect/shader_reflection.hpp>
#include <Darkstar/Kernel/logh.hpp>

using namespace gs;
using ker::Log;

ShaderReflection::ShaderReflection(void* code, const unsigned int code_size)
{
	ID3D10ShaderReflection* reflector;
	if(FAILED(D3D10ReflectShader(code, code_size, &reflector)))
	{
		lwar << "Cannot reflect shader";
		return;
	};

	D3D10_SHADER_DESC shader_desc;
	if(FAILED(reflector->GetDesc(&shader_desc)))
	{
		lwar << "Cannot get description of shader";
		return;
	};
	constant_buffers.resize(shader_desc.ConstantBuffers);
	input_parameters.resize(shader_desc.InputParameters);
	for(unsigned int i = 0; i < shader_desc.ConstantBuffers; ++i)
	{
		ShaderConstantBuffer new_constant_buffer;
		D3D10_SHADER_BUFFER_DESC cbuffer_desc;
		ID3D10ShaderReflectionConstantBuffer* cb_reflector = reflector->GetConstantBufferByIndex(i);
		if(FAILED(cb_reflector->GetDesc(&cbuffer_desc)))
		{
			lwar << "Cannot get description of constant buffer with index = " << i;
			return;
		};
		new_constant_buffer.buffer_type = (ShaderConstantBufferType)cbuffer_desc.Type;
		new_constant_buffer.name = cbuffer_desc.Name;
		for(unsigned int j = 0; j < cbuffer_desc.Variables; ++j)
		{
			ShaderVariable new_variable;
			D3D10_SHADER_VARIABLE_DESC var_desc;
			ID3D10ShaderReflectionVariable* var_reflector = cb_reflector->GetVariableByIndex(j);
			if(FAILED(var_reflector->GetDesc(&var_desc)))
			{
				lwar << "Cannot get variable with index = " << j << " from constant buffer with index " << i;
				return;
			};
			if(var_desc.uFlags & D3D10_SVF_USED)
			{
				new_variable.name = var_desc.Name;
				// each register size is 16 bytes, so start offset must be shift right
				new_variable.register_index = var_desc.StartOffset;
				new_constant_buffer.variables.push_back(new_variable);
			};
		};
		constant_buffers[i] = new_constant_buffer;
	};
	for(unsigned int i = 0; i < shader_desc.BoundResources; ++i)
	{
		D3D10_SHADER_INPUT_BIND_DESC sib_desc;
		if(FAILED(reflector->GetResourceBindingDesc(i, &sib_desc)))
		{
			lwar << "Cannot get binding resource description with index: " << i;
			return;
		};
		if(sib_desc.Type == D3D10_SIT_TEXTURE || sib_desc.Type == D3D10_SIT_SAMPLER)
		{
			ShaderBoundResource new_bound_resource;
			new_bound_resource.name = sib_desc.Name;
			new_bound_resource.register_index = sib_desc.BindPoint;
			new_bound_resource.type = (ShaderBoundResourceType)sib_desc.Type;
			bound_resources.push_back(new_bound_resource);
		};
	};
	for(unsigned int i = 0; i < shader_desc.InputParameters; ++i)
	{
		ShaderInputParameter new_input_parameter;
		D3D10_SIGNATURE_PARAMETER_DESC sig_par_desc;
		if(FAILED(reflector->GetInputParameterDesc(i, &sig_par_desc)))
		{
			lwar << "Cannot get input parameter description for parameter with index = " << i;
			return;
		};
		new_input_parameter.name = sig_par_desc.SemanticName;
		new_input_parameter.semantic_index = sig_par_desc.SemanticIndex;
		new_input_parameter.sv_type = (ShaderSystemValuesType)sig_par_desc.SystemValueType;
		new_input_parameter.rc_type = (ShaderRegisterComponentType)sig_par_desc.ComponentType;
		new_input_parameter.register_index = sig_par_desc.Register;
		input_parameters[i] = new_input_parameter;
	};

	ID3D10Blob* tmp_input_signature;
	if(FAILED(D3D10GetInputSignatureBlob(code, code_size, &tmp_input_signature)))
	{
		lwar << "Cannot get input signature from vertex shader";
		return;
	};
	input_signature_data = tmp_input_signature->GetBufferPointer();
	input_signature_size = (unsigned int)tmp_input_signature->GetBufferSize();
};

ShaderReflection::~ShaderReflection()
{

};

#endif


		