Advertisement
Guest User

Untitled

a guest
Nov 15th, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.84 KB | None | 0 0
  1. #include "glsl.hpp"
  2. #include <glslang/Public/ShaderLang.h>
  3.  
  4. using namespace std;
  5.  
  6. namespace shader_manager
  7. {
  8.     namespace glsl
  9.     {
  10.         // utils
  11.  
  12.         template<typename T>
  13.         vector<T> create_reserved_vec(size_t size)
  14.         {
  15.             vector<T> result;
  16.             result.reserve(size);
  17.             return result;
  18.         }
  19.  
  20.         // converting
  21.  
  22.         glslang::EShSource to_glslang_source_language(source_language language)
  23.         {
  24.             switch (language)
  25.             {
  26.             case source_language::glsl_450:
  27.                 return ::glslang::EShSourceGlsl;
  28.  
  29.             case source_language::glsl_400:
  30.                 return ::glslang::EShSourceGlsl;
  31.  
  32.             case source_language::glsl_330:
  33.                 return ::glslang::EShSourceGlsl;
  34.  
  35.             case source_language::hlsl_500:
  36.                 return ::glslang::EShSourceHlsl;
  37.  
  38.             case source_language::hlsl_400:
  39.                 return ::glslang::EShSourceHlsl;
  40.  
  41.             case source_language::hlsl_300:
  42.                 return ::glslang::EShSourceHlsl;
  43.  
  44.             default:
  45.                 throw runtime_error("undefined enum value");
  46.             }
  47.         }
  48.  
  49.         unsigned to_glslang_graphic_api_version(source_language language)
  50.         {
  51.             switch (language)
  52.             {
  53.             case source_language::glsl_450:
  54.                 return 450;
  55.  
  56.             case source_language::glsl_400:
  57.                 return 400;
  58.  
  59.             case source_language::glsl_330:
  60.                 return 330;
  61.  
  62.             case source_language::hlsl_500:
  63.                 return 500;
  64.  
  65.             case source_language::hlsl_400:
  66.                 return 400;
  67.  
  68.             case source_language::hlsl_300:
  69.                 return 300;
  70.  
  71.             default:
  72.                 throw std::runtime_error("undefined enum value");
  73.             }
  74.         }
  75.  
  76.         glslang::EShTargetLanguage to_glslang_target_language(target_language language)
  77.         {
  78.             switch (language)
  79.             {
  80.             case target_language::spv_1_0:
  81.                 return ::glslang::EShTargetSpv;
  82.  
  83.             case target_language::spv_1_1:
  84.                 return ::glslang::EShTargetSpv;
  85.  
  86.             case target_language::spv_1_2:
  87.                 return ::glslang::EShTargetSpv;
  88.  
  89.             case target_language::spv_1_3:
  90.                 return ::glslang::EShTargetSpv;
  91.  
  92.             case target_language::spv_1_4:
  93.                 return ::glslang::EShTargetSpv;
  94.  
  95.             default:
  96.                 throw std::runtime_error("undefined enum value");
  97.             }
  98.         }
  99.  
  100.         glslang::EShTargetLanguageVersion to_glslang_target_language_version(target_language language)
  101.         {
  102.             switch (language)
  103.             {
  104.             case target_language::spv_1_0:
  105.                 return ::glslang::EShTargetSpv_1_0;
  106.  
  107.             case target_language::spv_1_1:
  108.                 return ::glslang::EShTargetSpv_1_1;
  109.  
  110.             case target_language::spv_1_2:
  111.                 return ::glslang::EShTargetSpv_1_2;
  112.  
  113.             case target_language::spv_1_3:
  114.                 return ::glslang::EShTargetSpv_1_3;
  115.  
  116.             case target_language::spv_1_4:
  117.                 return ::glslang::EShTargetSpv_1_4;
  118.  
  119.             default:
  120.                 throw std::runtime_error("undefined enum value");
  121.             }
  122.         }
  123.  
  124.         glslang::EShClient to_glslang_graphic_api(graphic_api api)
  125.         {
  126.             switch (api)
  127.             {
  128.             case graphic_api::openGL_450:
  129.                 return ::glslang::EShClientOpenGL;
  130.  
  131.             case graphic_api::vulkan_1_0:
  132.                 return ::glslang::EShClientVulkan;
  133.  
  134.             case graphic_api::vulkan_1_1:
  135.                 return ::glslang::EShClientVulkan;
  136.  
  137.             default:
  138.                 throw std::runtime_error("undefined enum value");
  139.             }
  140.         }
  141.  
  142.         glslang::EShTargetClientVersion to_glslang_graphic_api_version(graphic_api api)
  143.         {
  144.             switch (api)
  145.             {
  146.             case graphic_api::openGL_450:
  147.                 return ::glslang::EShTargetOpenGL_450;
  148.  
  149.             case graphic_api::vulkan_1_0:
  150.                 return ::glslang::EShTargetVulkan_1_0;
  151.  
  152.             case graphic_api::vulkan_1_1:
  153.                 return ::glslang::EShTargetVulkan_1_1;
  154.  
  155.             default:
  156.                 throw std::runtime_error("undefined enum value");
  157.             }
  158.         }
  159.  
  160.         EShLanguage to_glslang_shader_stage(shader_stage stage)
  161.         {
  162.             switch (stage)
  163.             {
  164.             case shader_stage::compute:
  165.                 return EShLangCompute;
  166.  
  167.             case shader_stage::fragment:
  168.                 return EShLangFragment;
  169.  
  170.             case shader_stage::geometry:
  171.                 return EShLangGeometry;
  172.  
  173.             case shader_stage::tessellation_control:
  174.                 return EShLangTessControl;
  175.  
  176.             case shader_stage::tessellation_evaluation:
  177.                 return EShLangTessEvaluation;
  178.  
  179.             case shader_stage::vertex:
  180.                 return EShLangVertex;
  181.  
  182.             default:
  183.                 throw std::runtime_error("undefined enum value");
  184.             }
  185.         }
  186.  
  187.         vector<char const*> to_cstr_vec(vector<string> const& vec)
  188.         {
  189.             std::vector<char const*> result;
  190.             for (auto const& str : vec)
  191.             {
  192.                 result.push_back(str.c_str());
  193.             }
  194.             return result;
  195.         }
  196.  
  197.         // initialization of program
  198.  
  199.         void set_shader_options(glslang::TShader& shader, shader_options options)
  200.         {
  201.             switch (options)
  202.             {
  203.             case shader_options::auto_map_bindings:
  204.                 shader.setAutoMapBindings(true);
  205.                 break;
  206.             case shader_options::auto_map_locations:
  207.                 shader.setAutoMapLocations(true);
  208.                 break;
  209.             case shader_options::invert_y:
  210.                 shader.setInvertY(true);
  211.                 break;
  212.             case shader_options::hlsl_io_mapping:
  213.                 shader.setHlslIoMapping(true);
  214.                 break;
  215.             case shader_options::flatten_uniform_arrays:
  216.                 shader.setFlattenUniformArrays(true);
  217.                 break;
  218.             case shader_options::no_storage_format:
  219.                 shader.setNoStorageFormat(true);
  220.                 break;
  221.             default:
  222.                 throw std::runtime_error("undefined enum value");
  223.             }
  224.         }
  225.  
  226.         void configurate_shader(glslang::TShader& gl_shader, shader shader)
  227.         {
  228.             gl_shader.setEntryPoint(shader.entry_point.data());
  229.             gl_shader.setEnvClient(
  230.                 to_glslang_graphic_api(shader.graphic_api),
  231.                 to_glslang_graphic_api_version(shader.graphic_api)
  232.             );
  233.             gl_shader.setEnvInput(
  234.                 to_glslang_source_language(shader.source_language),
  235.                 to_glslang_shader_stage(shader.stage),
  236.                 to_glslang_graphic_api(shader.graphic_api),
  237.                 to_glslang_graphic_api_version(shader.graphic_api)
  238.             );
  239.         }
  240.  
  241.         void prepare_shader(glslang::TShader& glang_shader, vector<char const*> const& code,
  242.             shader const& shader)
  243.         {
  244.             static TBuiltInResource resource;
  245.  
  246.             glang_shader.setStrings(code.data(), static_cast<int>(code.size()));
  247.             configurate_shader(glang_shader, shader);
  248.             glang_shader.parse(&resource, 0, false, EShMessages::EShMsgDefault);
  249.         }
  250.  
  251.         void init_program(glslang::TProgram& program, std::vector<shader> const& shaders)
  252.         {
  253.             auto glang_shaders = create_reserved_vec<glslang::TShader>(shaders.size());
  254.             auto shaders_code = create_reserved_vec<vector<char const*>>(shaders.size());
  255.  
  256.             for (auto const& shader : shaders)
  257.             {
  258.                 shaders_code.push_back(to_cstr_vec(shader.source));
  259.  
  260.                 glslang::TShader glang_shader(to_glslang_shader_stage(shader.stage));
  261.                 prepare_shader(glang_shader, shaders_code.back(), shader);
  262.                 glang_shaders.push_back(glang_shader);
  263.  
  264.                 program.addShader(&glang_shader);
  265.             }
  266.  
  267.             if (!program.link(EShMsgDefault))
  268.             {
  269.                 throw std::runtime_error("fail to link shaders");
  270.             }
  271.             if (!program.mapIO())
  272.             {
  273.                 throw std::runtime_error("fail to map IO");
  274.             }
  275.             if (!program.buildReflection())
  276.             {
  277.                 throw std::runtime_error("fail to build_reflection");
  278.             }
  279.         }
  280.  
  281.         // variable factory
  282.  
  283.         class glslang_variable : public variable, public opengl_fundamental_variable_impl
  284.         {
  285.         public:
  286.             glslang_variable(glslang::TObjectReflection const& var_info) :
  287.                 opengl_fundamental_variable_impl(
  288.                     static_cast<opengl_fundamental_type>(var_info.glDefineType)), name_(var_info.name)
  289.             {
  290.             }
  291.  
  292.             std::string get_name() const override
  293.             {
  294.                 return name_;
  295.             }
  296.  
  297.         private:
  298.             std::string name_;
  299.         };
  300.        
  301.         shared_ptr<variable> create_variable(glslang::TProgram const& program,
  302.             glslang::TObjectReflection const& var_info, bool in_struct);
  303.  
  304.         vector<shared_ptr<variable>> create_variables(glslang::TProgram const& program,
  305.             glslang::TObjectReflection const& var_info)
  306.         {
  307.             vector<shared_ptr<variable>> variables;
  308.             for (utils::index_t i = var_info.arrayStride; i != var_info.topLevelArrayStride; ++i)
  309.             {
  310.                 variables.push_back(create_variable(program, program.getBufferVariable(static_cast<int>(i)), true));
  311.             }
  312.             return variables;
  313.         }
  314.  
  315.         class struct_glslang_variable : public variable, public variable_impl, public struct_variable_impl
  316.         {
  317.         public:
  318.             struct_glslang_variable(glslang::TProgram const& program, glslang::TObjectReflection const& var_info) :
  319.                 variable_impl(var_info.name, "struct"),
  320.                 struct_variable_impl(create_variables(program, var_info))
  321.             {
  322.             }
  323.         };
  324.  
  325.         shared_ptr<variable> create_array_in_struct_variable(glslang::TObjectReflection const& var_info)
  326.         {
  327.             struct var : variable, glslang_variable, in_struct_variable_impl, array_variable_impl
  328.             {
  329.                 var(glslang::TObjectReflection const& var_info) :
  330.                     glslang_variable(var_info),
  331.                     in_struct_variable_impl(var_info.offset),
  332.                     array_variable_impl(var_info.size)
  333.                 {
  334.                 }
  335.             };
  336.  
  337.             return make_shared<var>(var_info);
  338.         }
  339.  
  340.         shared_ptr<variable> create_array_variable(glslang::TObjectReflection const& var_info)
  341.         {
  342.             struct var : variable, glslang_variable, array_variable_impl
  343.             {
  344.                 var(glslang::TObjectReflection const& var_info) :
  345.                     glslang_variable(var_info),
  346.                     array_variable_impl(var_info.size)
  347.                 {
  348.                 }
  349.             };
  350.  
  351.             return make_shared<var>(var_info);
  352.         }
  353.  
  354.         shared_ptr<variable> create_in_struct_variable(glslang::TObjectReflection const& var_info)
  355.         {
  356.             struct var : variable, glslang_variable, in_struct_variable_impl
  357.             {
  358.                 var(glslang::TObjectReflection const& var_info) :
  359.                     glslang_variable(var_info),
  360.                     in_struct_variable_impl(var_info.offset)
  361.                 {
  362.                 }
  363.             };
  364.  
  365.             return make_shared<var>(var_info);
  366.         }
  367.  
  368.         shared_ptr<variable> create_struct_array_in_struct_variable(glslang::TProgram const& program,
  369.             glslang::TObjectReflection const& var_info)
  370.         {
  371.             struct var : variable, struct_glslang_variable, in_struct_variable_impl, array_variable_impl
  372.             {
  373.                 var(glslang::TProgram& program, glslang::TObjectReflection const& var_info) :
  374.                     struct_glslang_variable(program, var_info),
  375.                     in_struct_variable_impl(var_info.offset),
  376.                     array_variable_impl(var_info.size)
  377.                 {
  378.                 }
  379.             };
  380.  
  381.             return make_shared<var>(program, var_info);
  382.         }
  383.  
  384.         shared_ptr<variable> create_struct_array_variable(glslang::TProgram const& program,
  385.             glslang::TObjectReflection const& var_info)
  386.         {
  387.             struct var : variable, struct_glslang_variable, array_variable_impl
  388.             {
  389.                 var(glslang::TProgram& program, glslang::TObjectReflection const& var_info) :
  390.                     struct_glslang_variable(program, var_info),
  391.                     array_variable_impl(var_info.size)
  392.                 {
  393.                 }
  394.             };
  395.  
  396.             return make_shared<var>(program, var_info);
  397.         }
  398.  
  399.         shared_ptr<variable> create_struct_in_struct_variable(glslang::TProgram const& program,
  400.             glslang::TObjectReflection const& var_info)
  401.         {
  402.             struct var : variable, struct_glslang_variable, in_struct_variable_impl
  403.             {
  404.                 var(glslang::TProgram& program, glslang::TObjectReflection const& var_info) :
  405.                     struct_glslang_variable(program, var_info),
  406.                     in_struct_variable_impl(var_info.offset)
  407.                 {
  408.                 }
  409.             };
  410.  
  411.             return make_shared<var>(program, var_info);
  412.         }
  413.  
  414.         // shader reflection
  415.  
  416.         shared_ptr<variable> create_variable(glslang::TProgram const& program,
  417.             glslang::TObjectReflection const& var_info, bool in_struct)
  418.         {
  419.             if (var_info.numMembers)
  420.             {
  421.                 if (var_info.size && in_struct)
  422.                 {
  423.                     return create_struct_array_in_struct_variable(program, var_info);
  424.                 }
  425.                 else if (var_info.size)
  426.                 {
  427.                     return create_struct_array_variable(program, var_info);
  428.                 }
  429.                 else if (in_struct)
  430.                 {
  431.                     return create_struct_in_struct_variable(program, var_info);
  432.                 }
  433.                 else
  434.                 {
  435.                     return make_shared<struct_glslang_variable>(program, var_info);
  436.                 }
  437.             }
  438.             else
  439.             {
  440.                 if (var_info.size && in_struct)
  441.                 {
  442.                     return create_array_in_struct_variable(var_info);
  443.                 }
  444.                 else if (var_info.size)
  445.                 {
  446.                     return create_array_variable(var_info);
  447.                 }
  448.                 else if (in_struct)
  449.                 {
  450.                     return create_in_struct_variable(var_info);
  451.                 }
  452.                 else
  453.                 {
  454.                     return make_shared<glslang_variable>(var_info);
  455.                 }
  456.             }
  457.         }
  458.  
  459.         void get_uniform_variables(glslang::TProgram const& program, vector<shared_ptr<resource>>& resources)
  460.         {
  461.             for (utils::index_t i = 0; i != program.getNumUniformVariables(); ++i)
  462.             {
  463.                 auto const& var_info = program.getUniform(static_cast<int>(i));
  464.                 resources.push_back(make_shared<uniform_resource_impl>(
  465.                     create_variable(program, var_info, false), "uniform", var_info.getBinding()));
  466.             }
  467.  
  468.             for (utils::index_t i = 0; i != program.getNumUniformBlocks(); ++i)
  469.             {
  470.                 auto const& var_info = program.getUniformBlock(static_cast<int>(i));
  471.                 resources.push_back(make_shared<uniform_resource_impl>(
  472.                     create_variable(program, var_info, false), "uniform", var_info.getBinding()));
  473.             }
  474.         }
  475.  
  476.         void get_input_variables(glslang::TProgram const& program, vector<shared_ptr<resource>>& resources)
  477.         {
  478.             for (utils::index_t i = 0; i != program.getNumPipeInputs(); ++i)
  479.             {
  480.                 auto const& var_info = program.getPipeInput(static_cast<int>(i));
  481.                 resources.push_back(make_shared<input_resource_impl>(
  482.                     create_variable(program, var_info, false), "input", var_info.getBinding()));
  483.             }
  484.         }
  485.  
  486.         void get_output_variables(glslang::TProgram const& program, vector<shared_ptr<resource>>& resources)
  487.         {
  488.             for (utils::index_t i = 0; i != program.getNumPipeInputs(); ++i)
  489.             {
  490.                 auto const& var_info = program.getPipeOutput(static_cast<int>(i));
  491.                 resources.push_back(make_shared<output_resource_impl>(
  492.                     create_variable(program, var_info, false), "output", var_info.getBinding()));
  493.             }
  494.         }
  495.  
  496.         vector<shared_ptr<resource>> build_resources(glslang::TProgram const& program)
  497.         {
  498.             vector<shared_ptr<resource>> result;
  499.             get_uniform_variables(program, result);
  500.             get_input_variables(program, result);
  501.             get_output_variables(program, result);
  502.  
  503.             return result;
  504.         }
  505.  
  506.         // analizer ---------------------------------------------------------------------------------------------
  507.  
  508.         std::vector<std::shared_ptr<resource>> analize_shaders(std::vector<shader> const& shaders)
  509.         {
  510.             glslang::InitializeProcess();
  511.             glslang::TProgram program;
  512.             init_program(program, shaders);
  513.             auto resources = build_resources(program);
  514.             glslang::FinalizeProcess();
  515.             return resources;
  516.         }
  517.     }
  518. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement