#include "glsl_to_spirv.h"
#include "zstd/table.h"
#include "meta/hash.h"
#include "yaml/yaml.h"
#include <shaderc/shaderc.hpp>
#include <vector>
namespace vulkanapi
{
	using std::vector;
	using zstd::hash_table;
	shaderc_shader_kind ConvertStageSC(vk::ShaderStageFlagBits stage)
	{
		static hash_table< vk::ShaderStageFlagBits, shaderc_shader_kind> conv
		{
			{ vk::ShaderStageFlagBits::eVertex				  ,shaderc_shader_kind::shaderc_vertex_shader },
			{ vk::ShaderStageFlagBits::eFragment              ,shaderc_shader_kind::shaderc_fragment_shader },
			{ vk::ShaderStageFlagBits::eGeometry              ,shaderc_shader_kind::shaderc_geometry_shader },
			{ vk::ShaderStageFlagBits::eTessellationControl   ,shaderc_shader_kind::shaderc_tess_control_shader },
			{ vk::ShaderStageFlagBits::eTessellationEvaluation,shaderc_shader_kind::shaderc_tess_evaluation_shader },
		};
		auto itr = conv.find(stage);
		return itr->second;
	}
	std::optional<std::vector<uint32_t>> GlslToSpirv::spirv(const string& glsl, vk::ShaderStageFlagBits v_stage, string_view code_id)
	{
		std::optional<std::vector<uint32_t>> spirv_out;
		{
			shaderc::Compiler compiler;
			shaderc::CompileOptions options;
			options.SetOptimizationLevel(shaderc_optimization_level_performance);
			options.SetTargetEnvironment(shaderc_target_env::shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3);
			auto result = compiler.CompileGlslToSpv(glsl, ConvertStageSC(v_stage), code_id.data(), options);
			if (result.GetCompilationStatus() != shaderc_compilation_status::shaderc_compilation_status_success)
				return spirv_out;
			spirv_out = vector<uint32_t>{ result.cbegin(),result.cend() };
		}
		return spirv_out;
	}

}
