| 1029 | } |
| 1030 | |
| 1031 | void define_entry_point(function &func) override |
| 1032 | { |
| 1033 | assert(!func.unique_name.empty() && func.unique_name[0] == 'F'); |
| 1034 | func.unique_name[0] = 'E'; |
| 1035 | |
| 1036 | // Modify entry point name so each thread configuration is made separate |
| 1037 | if (func.type == shader_type::compute) |
| 1038 | func.unique_name += |
| 1039 | '_' + std::to_string(func.num_threads[0]) + |
| 1040 | '_' + std::to_string(func.num_threads[1]) + |
| 1041 | '_' + std::to_string(func.num_threads[2]); |
| 1042 | |
| 1043 | if (std::find_if(_module.entry_points.begin(), _module.entry_points.end(), |
| 1044 | [&func](const std::pair<std::string, shader_type> &entry_point) { |
| 1045 | return entry_point.first == func.unique_name; |
| 1046 | }) != _module.entry_points.end()) |
| 1047 | return; |
| 1048 | |
| 1049 | _module.entry_points.emplace_back(func.unique_name, func.type); |
| 1050 | |
| 1051 | assert(_current_function_declaration.empty()); |
| 1052 | if (func.type == shader_type::compute) |
| 1053 | _current_function_declaration += |
| 1054 | "layout(local_size_x = " + std::to_string(func.num_threads[0]) + |
| 1055 | ", local_size_y = " + std::to_string(func.num_threads[1]) + |
| 1056 | ", local_size_z = " + std::to_string(func.num_threads[2]) + ") in;\n"; |
| 1057 | |
| 1058 | // Generate the glue entry point function |
| 1059 | function entry_point = func; |
| 1060 | entry_point.referenced_functions.push_back(func.id); |
| 1061 | |
| 1062 | // Change function signature to 'void main()' |
| 1063 | entry_point.return_type = { type::t_void }; |
| 1064 | entry_point.return_semantic.clear(); |
| 1065 | entry_point.parameter_list.clear(); |
| 1066 | |
| 1067 | std::unordered_map<std::string, std::string> semantic_to_varying_variable; |
| 1068 | |
| 1069 | const auto create_varying_variable = [this, stype = func.type, &semantic_to_varying_variable](type type, unsigned int extra_qualifiers, const std::string &name, const std::string &semantic) { |
| 1070 | // Skip built in variables |
| 1071 | if (!semantic_to_builtin(std::string(), semantic, stype).empty()) |
| 1072 | return; |
| 1073 | |
| 1074 | // Do not create multiple input/output variables for duplicate semantic usage (since every input/output location may only be defined once in GLSL) |
| 1075 | if ((extra_qualifiers & type::q_in) != 0 && |
| 1076 | !semantic_to_varying_variable.emplace(semantic, name).second) |
| 1077 | return; |
| 1078 | |
| 1079 | type.qualifiers |= extra_qualifiers; |
| 1080 | assert((type.has(type::q_in) || type.has(type::q_out)) && !type.has(type::q_inout)); |
| 1081 | |
| 1082 | // OpenGL does not allow varying of type boolean |
| 1083 | if (type.is_boolean()) |
| 1084 | type.base = type::t_float; |
| 1085 | |
| 1086 | const uint32_t location = semantic_to_location(semantic, std::max(1u, type.array_length)); |
| 1087 | |
| 1088 | for (unsigned int a = 0; a < std::max(1u, type.array_length); ++a) |
no test coverage detected