47char *MSLGeneratorInterface::msl_patch_default =
nullptr;
50#define FRAGMENT_OUT_STRUCT_NAME "FragmentOut"
51#define FRAGMENT_TILE_IN_STRUCT_NAME "FragmentTileIn"
53#define ATOMIC_DEFINE_STR "#define MTL_SUPPORTS_TEXTURE_ATOMICS 1\n"
90 case Type::VEC3_101010I2:
137 char *current_str_begin = &*
str.begin();
138 char *current_str_end = &*
str.end();
140 bool is_inside_comment =
false;
141 for (
char *c = current_str_begin; c < current_str_end; c++) {
142 if (is_inside_comment) {
143 if ((*c ==
'*') && (c < current_str_end - 1) && (*(c + 1) ==
'/')) {
144 is_inside_comment =
false;
153 if ((*c ==
'/') && (c < current_str_end - 1) && (*(c + 1) ==
'*')) {
154 is_inside_comment =
true;
163 char *current_str_begin = &*
str.begin();
164 char *current_str_end = &*
str.end();
166 bool is_inside_comment =
false;
167 for (
char *c = current_str_begin; c < current_str_end; c++) {
168 if (is_inside_comment) {
170 is_inside_comment =
false;
177 if ((*c ==
'/') && (c < current_str_end - 1) && (*(c + 1) ==
'/')) {
178 is_inside_comment =
true;
188 for (
const char *c = chr; *c !=
'\0'; c++) {
191 if ((ch >=
'a' && ch <=
'z') || (ch >=
'A' && ch <=
'Z') ||
192 (numchars > 0 && ch >=
'0' && ch <=
'9') || ch ==
'_' || ch ==
'#')
198 return (numchars > 0);
208 char last_char =
' ';
210 for (start = array_loc - 1; (start >=
min) && (*start !=
'\0'); start--) {
212 if ((ch >=
'a' && ch <=
'z') || (ch >=
'A' && ch <=
'Z') || (ch >=
'0' && ch <=
'9') ||
213 ch ==
'_' || ch ==
'#')
225 if ((last_char >=
'0' && last_char <=
'9')) {
241 for (
char *c = current_str_begin + 2; c < current_str_end - 18; c++) {
242 char *base_search = strstr(c,
"gl_ClipDistance[");
243 if (base_search ==
nullptr) {
247 c = base_search + 16;
250 if (*(c + 1) !=
']') {
255 if ((*c >=
'0') && (*c <=
'9')) {
256 char clip_distance_id = ((*c) -
'0');
257 auto found = std::find(
264 *(base_search + 15) =
'_';
265 *(base_search + 17) =
' ';
278 char *current_str_begin = &*
str.begin();
279 char *current_str_end = &*
str.end();
281 for (
char *c = current_str_begin + 2; c < current_str_end - 6; c++) {
282 char *start = strstr(c,
"out ");
283 if (start ==
nullptr) {
288 if (strncmp(c - 2,
"in", 2) == 0) {
294 char *word_base1 = c + 4;
295 char *word_base2 = word_base1;
297 if (
is_program_word(word_base1, &len1) && (*(word_base1 + len1) ==
' ')) {
298 word_base2 = word_base1 + len1 + 1;
301 bool is_array = (*(word_base2 + len2) ==
'[');
307 char *array_end = strchr(word_base2 + len2,
']');
308 if (array_end !=
nullptr) {
316 *(word_base2 - 1) =
',';
317 *(word_base2 + len2) =
',';
330 *(word_base2 - 1) =
'&';
346 char *current_str_begin = &*
str.begin();
347 char *current_str_end = &*
str.end();
349 for (
char *c = current_str_begin; c < current_str_end - 10; c++) {
350 char *base_scan = strstr(c,
"mat");
351 if (base_scan ==
nullptr) {
355 char *constructor_end =
nullptr;
359 if (!(*c ==
'2' || *c ==
'3' || *c ==
'4')) {
368 if (*c ==
'2' || *c ==
'3' || *c ==
'4') {
387 if (constructor_end !=
nullptr) {
396 char *current_str_begin = &*
str.begin();
397 char *current_str_end = &*
str.end();
399 for (
char *c = current_str_begin; c < current_str_end - 6; c++) {
405 char *array_scan = strchr(c,
'[');
406 if (array_scan ==
nullptr) {
410 char *base_type_name = array_scan - 1 - typelen;
416 char *closing_square_brace = strchr(c,
']');
417 if (closing_square_brace !=
nullptr) {
418 c = closing_square_brace;
419 char *first_bracket = c + 1;
420 if (*first_bracket ==
'(') {
422 char *semi_colon = strchr(c,
';');
423 if (semi_colon !=
nullptr && *(semi_colon - 1) ==
')') {
424 char *closing_bracket = semi_colon - 1;
427 *first_bracket =
'{';
428 *closing_bracket =
'}';
429 for (
char *
clear = base_type_name;
clear <= closing_square_brace;
clear++) {
451 int nested_bracket_depth = 0;
452 for (
char *c = current_str_begin; c < current_str_end; c++) {
454 if (*c ==
'{' || *c ==
'[' || *c ==
'(') {
455 nested_bracket_depth++;
458 if (*c ==
'}' || *c ==
']' || *c ==
')') {
459 nested_bracket_depth--;
463 return (nested_bracket_depth == 0);
476 std::stringstream & )
478 char *current_str_begin = &*
str.begin();
479 char *current_str_end = &*
str.end();
481 int nested_bracket_depth = 0;
482 for (
char *c = current_str_begin; c < current_str_end - 6; c++) {
484 if (*c ==
'{' || *c ==
'[' || *c ==
'(') {
485 nested_bracket_depth++;
488 if (*c ==
'}' || *c ==
']' || *c ==
')') {
489 nested_bracket_depth--;
495 if (nested_bracket_depth == 0 && strncmp(c,
"const ", 6) == 0 &&
496 strncmp(c,
"const constant ", 15) != 0)
498 char *c_expr_end = strchr(c,
';');
501 "[PERFORMANCE WARNING] Global scope constant expression found - These get allocated "
502 "per-thread in METAL - Best to use Macro's or uniforms to avoid overhead: '%.*s'",
503 (
int)(c_expr_end + 1 - c),
517 const std::string &in_vertex_src,
518 MTLPrimitiveType &out_prim_tye,
522 static std::regex use_ssbo_fetch_mode_find(
524 "USE_SSBO_VERTEX_FETCH\\(\\s*(TriangleList|LineList|TriangleStrip|\\w+)\\s*,\\s*([0-9]+)\\s*"
528 std::smatch vertex_shader_ssbo_flags;
529 bool uses_ssbo_fetch =
false;
530 if (in_vertex_src.find(
"#pragma USE_SSBO_VERTEX_FETCH") != std::string::npos) {
531 uses_ssbo_fetch = std::regex_search(
532 in_vertex_src, vertex_shader_ssbo_flags, use_ssbo_fetch_mode_find);
534 if (uses_ssbo_fetch) {
545 std::string str_output_primitive_type = vertex_shader_ssbo_flags[1].str();
546 std::string str_output_prim_count_per_vertex = vertex_shader_ssbo_flags[2].str();
549 if (str_output_primitive_type ==
"TriangleList") {
550 out_prim_tye = MTLPrimitiveTypeTriangle;
552 else if (str_output_primitive_type ==
"LineList") {
553 out_prim_tye = MTLPrimitiveTypeLine;
555 else if (str_output_primitive_type ==
"TriangleStrip") {
556 out_prim_tye = MTLPrimitiveTypeTriangleStrip;
559 MTL_LOG_ERROR(
"Unsupported output primitive type for SSBO VERTEX FETCH MODE. Shader: %s",
565 out_num_output_verts = std::stoi(
583 std::string &glsl_compute_source)
586 char *current_str_begin = &*glsl_compute_source.begin();
587 char *current_str_end = &*glsl_compute_source.end();
589 for (
char *c = current_str_begin; c < current_str_end - 6; c++) {
591 char *c_expr_start = strstr(c,
"shared ");
592 if (c_expr_start ==
nullptr) {
603 char *c_expr_end = strstr(c,
";");
604 if (c_expr_end ==
nullptr) {
621 if (c_next_space ==
nullptr) {
625 int len = c_next_space - c;
628 new_shared_block.
type_name = std::string(buf);
634 c = c_next_space + 1;
644 char *varname_end =
nullptr;
645 if (c_array_begin !=
nullptr) {
647 if (c_next_space !=
nullptr) {
648 varname_end = (c_next_space < c_array_begin) ? c_next_space : c_array_begin;
651 varname_end = c_array_begin;
657 if (c_next_space !=
nullptr) {
658 varname_end = (c_next_space < c_expr_end) ? c_next_space : c_expr_end;
661 varname_end = c_expr_end;
665 len = varname_end - c;
668 new_shared_block.
varname = std::string(buf);
672 int len = c_expr_end - c_array_begin;
674 new_shared_block.
array_decl = std::string(buf);
684 for (
char *c = c_expr_start; c <= c_expr_end; c++) {
687 std::string out_str =
"TG ";
689 out_str += (new_shared_block.
is_array) ?
"(&" :
"&";
690 out_str += new_shared_block.
varname;
695 memcpy(c_expr_start, out_str.c_str(), (out_str.length() - 1) *
sizeof(
char));
713 case ShaderCreateInfo::Resource::BindType::SAMPLER:
715 case ShaderCreateInfo::Resource::BindType::IMAGE:
717 case ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER: {
719 if (array_offset == -1) {
733 os <<
"constant " << res.
uniformbuf.type_name <<
" *" << name_no_array <<
";\n";
737 case ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER: {
741 const char *memory_scope = ((writeable) ?
"device " :
"constant ");
742 if (array_offset == -1) {
757 os << memory_scope << res.
storagebuf.type_name <<
" *" << name_no_array <<
";\n";
772 std::stringstream ss;
775 ss <<
"\n/* Pass Resources. */\n";
779 ss <<
"\n/* Batch Resources. */\n";
783 ss <<
"\n/* Geometry Resources. */\n";
801 std::stringstream ss;
802 ss <<
"\n/* Vertex Inputs. */\n";
804 ss <<
to_string(attr.type) <<
" " << attr.name <<
";\n";
819 std::stringstream ss;
820 ss <<
"\n/* Fragment Outputs. */\n";
822 ss <<
to_string(output.type) <<
" " << output.name <<
";\n";
826 ss <<
"\n/* Fragment Tile inputs. */\n";
828 ss <<
to_string(input.type) <<
" " << input.name <<
";\n";
835std::string MTLShader::MTLShader::geometry_interface_declare(
864 if (msl_patch_default !=
nullptr) {
865 return msl_patch_default;
868 std::stringstream ss_patch;
871 size_t len = strlen(ss_patch.str().c_str()) + 1;
873 msl_patch_default = (
char *)malloc(
len *
sizeof(
char));
874 memcpy(msl_patch_default, ss_patch.str().c_str(),
len *
sizeof(
char));
875 return msl_patch_default;
880 std::stringstream &ss)
885 ss <<
"constant " << sc.type <<
" " << sc.name <<
" [[function_constant(" << index <<
")]];\n";
896 bool uses_create_info = info !=
nullptr;
897 if (!uses_create_info) {
898 MTL_LOG_WARNING(
"Unable to compile shader %p '%s' as no create-info was provided!",
907 return this->generate_msl_from_glsl_compute(info);
919 msl_iface.prepare_from_createinfo(info);
923 if (!msl_iface.uses_transform_feedback) {
930 msl_iface.uses_transform_feedback =
true;
936 std::string msl_defines_string =
"#define GPU_ARB_shader_draw_parameters 1\n";
942 msl_defines_string +=
"#define GPU_ARB_texture_gather 1\n";
946 if (!msl_iface.uses_transform_feedback) {
957 MTLPrimitiveType vertex_fetch_ssbo_output_prim_type = MTLPrimitiveTypeTriangle;
958 uint32_t vertex_fetch_ssbo_num_output_verts = 0;
963 vertex_fetch_ssbo_output_prim_type,
964 vertex_fetch_ssbo_num_output_verts);
966 if (msl_iface.uses_ssbo_vertex_fetch_mode) {
968 "[Shader] SSBO VERTEX FETCH Enabled for Shader '%s' With Output primitive type: %s, "
969 "vertex count: %u\n",
971 output_primitive_type.c_str(),
972 vertex_fetch_ssbo_num_output_verts);
979 if (!msl_iface.uses_transform_feedback) {
992 msl_iface.uses_gl_VertexID = bool(info->
builtins_ & BuiltinBits::VERTEX_ID) ||
995 msl_iface.uses_gl_InstanceID = bool(info->
builtins_ & BuiltinBits::INSTANCE_ID) ||
1000 msl_iface.uses_ssbo_vertex_fetch_mode;
1006 msl_iface.uses_gl_BaseInstanceARB = msl_iface.uses_gl_InstanceID ||
1008 "gl_BaseInstanceARB") != std::string::npos ||
1015 msl_iface.uses_gpu_layer = bool(info->
builtins_ & BuiltinBits::LAYER);
1016 msl_iface.uses_gpu_viewport_index = bool(info->
builtins_ & BuiltinBits::VIEWPORT_INDEX);
1019 if (!msl_iface.uses_transform_feedback) {
1020 std::smatch gl_special_cases;
1021 msl_iface.uses_gl_PointCoord = bool(info->
builtins_ & BuiltinBits::POINT_COORD) ||
1024 msl_iface.uses_barycentrics = bool(info->
builtins_ & BuiltinBits::BARYCENTRIC_COORD);
1025 msl_iface.uses_gl_FrontFacing = bool(info->
builtins_ & BuiltinBits::FRONT_FACING) ||
1028 msl_iface.uses_gl_PrimitiveID = bool(info->
builtins_ & BuiltinBits::PRIMITIVE_ID) ||
1039 msl_iface.uses_gl_FragDepth = (info->
depth_write_ != DepthWrite::UNCHANGED) &&
1045 "gl_FragStencilRefARB") != std::string::npos;
1054 if (msl_iface.uses_ssbo_vertex_fetch_mode) {
1055 msl_iface.prepare_ssbo_vertex_fetch_uniforms();
1063 if (!msl_iface.uses_transform_feedback) {
1069 std::stringstream ss_vertex;
1070 std::stringstream ss_fragment;
1071 ss_vertex <<
"#line 1 \"msl_wrapper_code\"\n";
1072 ss_fragment <<
"#line 1 \"msl_wrapper_code\"\n";
1074 if (
bool(info->
builtins_ & BuiltinBits::TEXTURE_ATOMIC) &&
1087 if (msl_iface.use_argument_buffer_for_samplers()) {
1088 ss_vertex <<
"#define USE_ARGUMENT_BUFFER_FOR_SAMPLERS 1" << std::endl;
1089 ss_vertex <<
"#define ARGUMENT_BUFFER_NUM_SAMPLERS "
1092 if (msl_iface.uses_ssbo_vertex_fetch_mode) {
1093 ss_vertex <<
"#define MTL_SSBO_VERTEX_FETCH 1" << std::endl;
1095 ss_vertex <<
"#define SSBO_ATTR_TYPE_" << attr.name <<
" " << attr.type << std::endl;
1099 ss_vertex <<
"#define "
1122 ss_vertex << msl_iface.msl_patch_default_get() << std::endl << std::endl;
1137 if (!iface->instance_name.is_empty()) {
1138 ss_vertex <<
"struct " << iface->name <<
" {" << std::endl;
1140 ss_vertex <<
to_string(inout.type) <<
" " << inout.name <<
" "
1143 ss_vertex <<
"};" << std::endl;
1151 ss_vertex <<
"public:" << std::endl;
1156 bool is_inside_struct =
false;
1157 if (!iface->instance_name.is_empty()) {
1161 ss_vertex << iface->name <<
" " << iface->instance_name <<
";" << std::endl;
1162 is_inside_struct =
true;
1169 if (!is_inside_struct) {
1170 ss_vertex <<
to_string(inout.type) <<
" " << inout.name <<
";" << std::endl;
1173 const char *arraystart = strchr(inout.name.c_str(),
'[');
1174 bool is_array = (arraystart !=
nullptr);
1175 int array_len = (is_array) ? std::stoi(std::regex_replace(
1180 std::string out_name = inout.name.c_str();
1181 std::size_t
pos = out_name.find(
'[');
1182 if (is_array &&
pos != std::string::npos) {
1183 out_name.resize(
pos);
1187 msl_iface.vertex_output_varyings.append(
1190 ((is_inside_struct) ? iface->instance_name.c_str() :
""),
1196 msl_iface.fragment_input_varyings.append(
1199 ((is_inside_struct) ? iface->instance_name.c_str() :
""),
1208 if (!msl_iface.uses_ssbo_vertex_fetch_mode) {
1209 ss_vertex << msl_iface.generate_msl_vertex_in_struct();
1215 if (msl_iface.uses_gl_Position) {
1216 ss_vertex <<
"float4 gl_Position;" << std::endl;
1218 if (msl_iface.uses_gl_PointSize) {
1219 ss_vertex <<
"float gl_PointSize = 1.0;" << std::endl;
1221 if (msl_iface.uses_gl_VertexID) {
1222 ss_vertex <<
"int gl_VertexID;" << std::endl;
1224 if (msl_iface.uses_gl_InstanceID) {
1225 ss_vertex <<
"int gl_InstanceID;" << std::endl;
1227 if (msl_iface.uses_gl_BaseInstanceARB) {
1228 ss_vertex <<
"int gl_BaseInstanceARB;" << std::endl;
1230 for (
const int cd :
IndexRange(msl_iface.clip_distances.size())) {
1231 ss_vertex <<
"float gl_ClipDistance_" << cd <<
";" << std::endl;
1235 if (msl_iface.uses_gpu_layer) {
1236 ss_vertex <<
"int gpu_Layer = 0;" << std::endl;
1238 if (msl_iface.uses_gpu_viewport_index) {
1239 ss_vertex <<
"int gpu_ViewportIndex = 0;" << std::endl;
1246 if (msl_iface.uses_ssbo_vertex_fetch_mode) {
1247 ss_vertex <<
"constant uchar** MTL_VERTEX_DATA;" << std::endl;
1248 ss_vertex <<
"constant ushort* MTL_INDEX_DATA_U16 = nullptr;" << std::endl;
1249 ss_vertex <<
"constant uint32_t* MTL_INDEX_DATA_U32 = nullptr;" << std::endl;
1259 ss_vertex <<
"\tthread " <<
tex.get_msl_typestring_wrapper(
false) <<
";" << std::endl;
1262 ss_vertex << std::endl;
1269 if (msl_iface.uses_transform_feedback) {
1270 ss_vertex << msl_iface.generate_msl_vertex_transform_feedback_out_struct(
ShaderStage::VERTEX);
1274 ss_vertex <<
"};" << std::endl;
1277 ss_vertex << msl_iface.generate_msl_vertex_entry_stub();
1280 if (!msl_iface.uses_transform_feedback) {
1283 if (msl_iface.use_argument_buffer_for_samplers()) {
1284 ss_fragment <<
"#define USE_ARGUMENT_BUFFER_FOR_SAMPLERS 1" << std::endl;
1285 ss_fragment <<
"#define ARGUMENT_BUFFER_NUM_SAMPLERS "
1290 ss_fragment << msl_iface.msl_patch_default_get() << std::endl << std::endl;
1305 if (!iface->instance_name.is_empty()) {
1306 ss_fragment <<
"struct " << iface->name <<
" {" << std::endl;
1308 ss_fragment <<
to_string(inout.type) <<
" " << inout.name <<
""
1311 ss_fragment <<
"};" << std::endl;
1318 ss_fragment <<
"public:" << std::endl;
1323 bool is_inside_struct =
false;
1324 if (!iface->instance_name.is_empty()) {
1326 ss_fragment << iface->name <<
" " << iface->instance_name <<
";" << std::endl;
1327 is_inside_struct =
true;
1334 if (!is_inside_struct) {
1335 ss_fragment <<
to_string(inout.type) <<
" " << inout.name <<
";" << std::endl;
1342 if (msl_iface.fragment_tile_inputs.size() > 0) {
1343 ss_fragment << msl_iface.generate_msl_fragment_struct(
true);
1345 ss_fragment << msl_iface.generate_msl_fragment_struct(
false);
1350 ss_fragment <<
"float4 gl_FragCoord;" << std::endl;
1351 if (msl_iface.uses_gl_FragColor) {
1352 ss_fragment <<
"float4 gl_FragColor;" << std::endl;
1354 if (msl_iface.uses_gl_FragDepth) {
1355 ss_fragment <<
"float gl_FragDepth;" << std::endl;
1357 if (msl_iface.uses_gl_FragStencilRefARB) {
1358 ss_fragment <<
"int gl_FragStencilRefARB;" << std::endl;
1360 if (msl_iface.uses_gl_PointCoord) {
1361 ss_fragment <<
"float2 gl_PointCoord;" << std::endl;
1363 if (msl_iface.uses_gl_FrontFacing) {
1364 ss_fragment <<
"bool gl_FrontFacing;" << std::endl;
1366 if (msl_iface.uses_gl_PrimitiveID) {
1367 ss_fragment <<
"uint gl_PrimitiveID;" << std::endl;
1371 if (msl_iface.uses_barycentrics) {
1372 ss_fragment <<
"vec3 gpu_BaryCoord;\n";
1376 if (msl_iface.uses_gpu_layer) {
1377 ss_fragment <<
"int gpu_Layer = 0;" << std::endl;
1379 if (msl_iface.uses_gpu_viewport_index) {
1380 ss_fragment <<
"int gpu_ViewportIndex = 0;" << std::endl;
1386 ss_fragment <<
"\tthread " <<
tex.get_msl_typestring_wrapper(
false) <<
";" << std::endl;
1394 ss_fragment <<
"};" << std::endl;
1397 ss_fragment << msl_iface.generate_msl_fragment_entry_stub();
1401#if MTL_SHADER_DEBUG_EXPORT_SOURCE
1402 NSFileManager *sharedFM = [NSFileManager defaultManager];
1403 NSURL *app_bundle_url = [[NSBundle mainBundle] bundleURL];
1404 NSURL *shader_dir = [[app_bundle_url URLByDeletingLastPathComponent]
1405 URLByAppendingPathComponent:
@"Shaders/"
1407 [sharedFM createDirectoryAtURL:shader_dir
1408 withIntermediateDirectories:YES
1411 const char *path_cstr = [shader_dir fileSystemRepresentation];
1413 std::ofstream vertex_fs;
1415 (std::string(path_cstr) +
"/" + std::string(this->name) +
"_GeneratedVertexShader.msl")
1417 vertex_fs << ss_vertex.str();
1420 if (!msl_iface.uses_transform_feedback) {
1421 std::ofstream fragment_fs;
1423 (std::string(path_cstr) +
"/" + std::string(this->name) +
"_GeneratedFragmentShader.msl")
1425 fragment_fs << ss_fragment.str();
1426 fragment_fs.close();
1430 "Vertex Shader Saved to: %s\n",
1431 (std::string(path_cstr) + std::string(this->name) +
"_GeneratedFragmentShader.msl").c_str());
1435 NSString *msl_final_vert = [NSString stringWithUTF8String:ss_vertex.str().c_str()];
1436 NSString *msl_final_frag = (msl_iface.uses_transform_feedback) ?
1438 ([NSString stringWithUTF8String:ss_fragment.str().c_str()]);
1446 [[NSString stringWithFormat:
@"vertex_function_entry_%s", this->name] retain]);
1448 [[NSString stringWithFormat:
@"fragment_function_entry_%s", this->name] retain]);
1455 this->
set_interface(msl_iface.bake_shader_interface(this->name, info));
1458 uses_gpu_layer = msl_iface.uses_gpu_layer;
1459 uses_gpu_viewport_index = msl_iface.uses_gpu_viewport_index;
1460 use_ssbo_vertex_fetch_mode_ = msl_iface.uses_ssbo_vertex_fetch_mode;
1461 if (msl_iface.uses_ssbo_vertex_fetch_mode) {
1462 ssbo_vertex_fetch_output_prim_type_ = vertex_fetch_ssbo_output_prim_type;
1463 ssbo_vertex_fetch_output_num_verts_ = vertex_fetch_ssbo_num_output_verts;
1482 msl_iface.prepare_from_createinfo(info);
1499 msl_iface.uses_gl_GlobalInvocationID =
1500 bool(info->
builtins_ & BuiltinBits::GLOBAL_INVOCATION_ID) ||
1503 msl_iface.uses_gl_WorkGroupSize = bool(info->
builtins_ & BuiltinBits::WORK_GROUP_SIZE) ||
1507 msl_iface.uses_gl_WorkGroupID = bool(info->
builtins_ & BuiltinBits::WORK_GROUP_ID) ||
1511 msl_iface.uses_gl_NumWorkGroups = bool(info->
builtins_ & BuiltinBits::NUM_WORK_GROUP) ||
1515 msl_iface.uses_gl_LocalInvocationIndex =
1516 bool(info->
builtins_ & BuiltinBits::LOCAL_INVOCATION_INDEX) ||
1519 msl_iface.uses_gl_LocalInvocationID = bool(info->
builtins_ & BuiltinBits::LOCAL_INVOCATION_ID) ||
1521 "gl_LocalInvocationID") != std::string::npos;
1543 std::stringstream ss_compute;
1544 ss_compute <<
"#line 1 \"msl_wrapper_code\"\n";
1546 ss_compute <<
"#define GPU_ARB_shader_draw_parameters 1\n";
1547 if (
bool(info->
builtins_ & BuiltinBits::TEXTURE_ATOMIC) &&
1560 if (msl_iface.use_argument_buffer_for_samplers()) {
1561 ss_compute <<
"#define USE_ARGUMENT_BUFFER_FOR_SAMPLERS 1" << std::endl;
1562 ss_compute <<
"#define ARGUMENT_BUFFER_NUM_SAMPLERS "
1567 if (msl_iface.uses_gl_WorkGroupSize) {
1571 if (msl_iface.uses_gl_WorkGroupSize) {
1572 ss_compute <<
"#define MTL_USE_WORKGROUP_SIZE 1" << std::endl;
1575 ss_compute <<
"#define MTL_WORKGROUP_SIZE_Y "
1580 ss_compute <<
"#define MTL_WORKGROUP_SIZE_Z "
1588 ss_compute << msl_iface.msl_patch_default_get() << std::endl << std::endl;
1594 ss_compute <<
"public:" << std::endl;
1606 ss_compute <<
"\tthread " <<
tex.get_msl_typestring_wrapper(
false) <<
";" << std::endl;
1609 ss_compute << std::endl;
1612 if (msl_iface.uses_gl_GlobalInvocationID) {
1613 ss_compute <<
"uint3 gl_GlobalInvocationID;" << std::endl;
1615 if (msl_iface.uses_gl_WorkGroupID) {
1616 ss_compute <<
"uint3 gl_WorkGroupID;" << std::endl;
1618 if (msl_iface.uses_gl_NumWorkGroups) {
1619 ss_compute <<
"uint3 gl_NumWorkGroups;" << std::endl;
1621 if (msl_iface.uses_gl_LocalInvocationIndex) {
1622 ss_compute <<
"uint gl_LocalInvocationIndex;" << std::endl;
1624 if (msl_iface.uses_gl_LocalInvocationID) {
1625 ss_compute <<
"uint3 gl_LocalInvocationID;" << std::endl;
1636 if (msl_iface.shared_memory_blocks.size() > 0) {
1641 if (block.is_array) {
1642 ss_compute <<
"TG " << block.type_name <<
" (&_" << block.varname <<
")"
1643 << block.array_decl;
1646 ss_compute <<
"TG " << block.type_name <<
" &_" << block.varname;
1648 ss_compute << std::endl;
1651 ss_compute <<
") : ";
1657 ss_compute << block.varname <<
"(_" << block.varname <<
")";
1664 ss_compute <<
"{ }" << std::endl;
1667 ss_compute <<
"};" << std::endl;
1670 ss_compute << msl_iface.generate_msl_compute_entry_stub();
1676 [[NSString stringWithFormat:
@"compute_function_entry_%s", this->name] retain]);
1682#if MTL_SHADER_DEBUG_EXPORT_SOURCE
1683 NSFileManager *sharedFM = [NSFileManager defaultManager];
1684 NSURL *app_bundle_url = [[NSBundle mainBundle] bundleURL];
1685 NSURL *shader_dir = [[app_bundle_url URLByDeletingLastPathComponent]
1686 URLByAppendingPathComponent:
@"Shaders/"
1688 [sharedFM createDirectoryAtURL:shader_dir
1689 withIntermediateDirectories:YES
1692 const char *path_cstr = [shader_dir fileSystemRepresentation];
1694 std::ofstream compute_fs;
1696 (std::string(path_cstr) +
"/" + std::string(this->name) +
"_GeneratedComputeShader.msl")
1698 compute_fs << ss_compute.str();
1702 "Compute Shader Saved to: %s\n",
1703 (std::string(path_cstr) + std::string(this->name) +
"_GeneratedComputeShader.msl").c_str());
1706 NSString *msl_final_compute = [NSString stringWithUTF8String:ss_compute.str().c_str()];
1710 this->
set_interface(msl_iface.bake_shader_interface(this->name, info));
1746 inp_uses_indexed_rendering->
location :
1749 inp_uses_index_mode_u16->
location :
1753 "uni_ssbo_input_prim_type_loc uniform location invalid!");
1755 "uni_ssbo_input_vert_count_loc uniform location invalid!");
1757 "uni_ssbo_uses_indexed_rendering uniform location invalid!");
1759 "uni_ssbo_uses_index_mode_u16 uniform location invalid!");
1761 "uni_ssbo_index_base_loc uniform location invalid!");
1771 ShaderSSBOAttributeBinding &cached_ssbo_attr = cached_ssbo_attribute_bindings_[i];
1772 cached_ssbo_attr.attribute_index = i;
1814 cached_ssbo_attr.uniform_stride = (inp_unf_stride !=
nullptr) ? inp_unf_stride->
location : -1;
1815 cached_ssbo_attr.uniform_offset = (inp_unf_offset !=
nullptr) ? inp_unf_offset->
location : -1;
1816 cached_ssbo_attr.uniform_fetchmode = (inp_unf_fetchmode !=
nullptr) ?
1819 cached_ssbo_attr.uniform_vbo_id = (inp_unf_vbo_id !=
nullptr) ? inp_unf_vbo_id->
location : -1;
1820 cached_ssbo_attr.uniform_attr_type = (inp_unf_attr_type !=
nullptr) ?
1824 BLI_assert(cached_ssbo_attr.uniform_offset != -1);
1825 BLI_assert(cached_ssbo_attr.uniform_stride != -1);
1826 BLI_assert(cached_ssbo_attr.uniform_fetchmode != -1);
1827 BLI_assert(cached_ssbo_attr.uniform_vbo_id != -1);
1828 BLI_assert(cached_ssbo_attr.uniform_attr_type != -1);
1835 create_info_ = info;
1859 int texture_slot_id = 0;
1860 int ubo_buffer_slot_id_ = 0;
1861 int storage_buffer_slot_id_ = 0;
1863 uint max_storage_buffer_location = 0;
1869 int max_sampler_slot = 0;
1873 max_sampler_slot =
max_ii(res.slot, max_sampler_slot);
1881 switch (res.bind_type) {
1887 if (res.sampler.type == ImageType::FLOAT_BUFFER ||
1888 res.sampler.type == ImageType::INT_BUFFER ||
1889 res.sampler.type == ImageType::UINT_BUFFER)
1896 msl_tex.
type = res.sampler.type;
1897 msl_tex.
name = res.sampler.name;
1899 msl_tex.
slot = texture_slot_id++;
1911 if ((res.image.qualifiers & Qualifier::READ_WRITE) == Qualifier::READ_WRITE) {
1914 else if (
bool(res.image.qualifiers & Qualifier::WRITE)) {
1924 msl_image.
type = res.image.type;
1925 msl_image.
name = res.image.name;
1926 msl_image.
access = access;
1927 msl_image.
slot = texture_slot_id++;
1938 BLI_assert(res.uniformbuf.type_name.size() > 0);
1940 int64_t array_offset = res.uniformbuf.name.find_first_of(
"[");
1947 ubo.
slot = 1 + (ubo_buffer_slot_id_++);
1953 ubo.
type_name = res.uniformbuf.type_name;
1955 ubo.
is_array = (array_offset > -1);
1959 ubo.
name = name_no_array;
1962 ubo.
name = res.uniformbuf.name;
1970 BLI_assert(res.storagebuf.type_name.size() > 0);
1972 int64_t array_offset = res.storagebuf.name.find_first_of(
"[");
1977 ssbo.
slot = storage_buffer_slot_id_++;
1980 max_storage_buffer_location =
max_uu(max_storage_buffer_location, ssbo.
location);
1985 ssbo.
type_name = res.storagebuf.type_name;
1987 ssbo.
is_array = (array_offset > -1);
1991 ssbo.
name = name_no_array;
1994 ssbo.
name = res.storagebuf.name;
2005 uint atomic_fallback_buffer_count = 0;
2008 ImageType::UINT_2D_ATOMIC,
2009 ImageType::UINT_2D_ARRAY_ATOMIC,
2010 ImageType::UINT_3D_ATOMIC,
2011 ImageType::INT_2D_ATOMIC,
2012 ImageType::INT_2D_ARRAY_ATOMIC,
2013 ImageType::INT_3D_ATOMIC))
2023 ssbo.
slot = storage_buffer_slot_id_++;
2024 ssbo.
location = max_storage_buffer_location + 1 + atomic_fallback_buffer_count;
2037 ssbo.
name =
tex.name +
"_storagebuf";
2046 atomic_fallback_buffer_count++;
2055 bool all_attr_location_assigned =
true;
2064 bool attr_location_assigned = (attr.index >= 0);
2065 all_attr_location_assigned = all_attr_location_assigned && attr_location_assigned;
2067 msl_attr.
type = attr.type;
2068 msl_attr.
name = attr.name;
2073 if (!all_attr_location_assigned) {
2087 mtl_frag_out.
layout_index = (frag_out.blend != DualBlend::NONE) ?
2088 ((frag_out.blend == DualBlend::SRC_0) ? 0 : 1) :
2090 mtl_frag_out.
type = frag_out.type;
2091 mtl_frag_out.
name = frag_out.name;
2099 if (is_tile_based_arch) {
2117 mtl_frag_in.
layout_index = (frag_tile_in.blend != DualBlend::NONE) ?
2118 ((frag_tile_in.blend == DualBlend::SRC_0) ? 0 : 1) :
2120 mtl_frag_in.
type = frag_tile_in.type;
2121 mtl_frag_in.
name = frag_tile_in.name;
2129 bool is_layered_fb = bool(create_info_->
builtins_ & BuiltinBits::LAYER);
2131 ImageType image_type = ImageType::FLOAT_BUFFER;
2132 switch (frag_tile_in.type) {
2134 image_type = is_layered_fb ? ImageType::FLOAT_2D_ARRAY : ImageType::FLOAT_2D;
2137 image_type = is_layered_fb ? ImageType::INT_2D_ARRAY : ImageType::INT_2D;
2140 image_type = is_layered_fb ? ImageType::UINT_2D_ARRAY : ImageType::UINT_2D;
2145 BLI_assert(image_type != ImageType::FLOAT_BUFFER);
2150 msl_image.
type = image_type;
2151 msl_image.
name = frag_tile_in.name +
"_subpass_img";
2153 msl_image.
slot = texture_slot_id++;
2157 msl_image.
location = frag_tile_in.index;
2192 "Compiled Shader '%s' is falling back to bindless via argument buffers due to having a "
2193 "texture sampler of Index: %u Which exceeds the limit of 15+1. However shader only uses "
2194 "%d textures. Consider optimising bind points with .auto_resource_location(true).",
2201 return use_argument_buffer;
2245 const std::string &uname = attr.name;
2258 std::stringstream out;
2259 out << std::endl <<
"/*** AUTO-GENERATED MSL VERETX SHADER STUB. ***/" << std::endl;
2262 out <<
"#undef texture" << std::endl;
2263 out <<
"#undef textureLod" << std::endl;
2266 out <<
"#undef bool" << std::endl;
2280 out <<
"vertex_function_entry_" << parent_shader_.
name_get() <<
"(\n\t";
2282 out <<
"vertex_function_entry(\n\t";
2286 out <<
") {" << std::endl << std::endl;
2293 out << shader_stage_inst_name <<
".gl_VertexID = gl_VertexID;" << std::endl;
2296 out << shader_stage_inst_name <<
".gl_InstanceID = gl_InstanceID-gl_BaseInstanceARB;"
2300 out << shader_stage_inst_name <<
".gl_BaseInstanceARB = gl_BaseInstanceARB;" << std::endl;
2312 out <<
"\t/* Execute Vertex main function */\t" << std::endl
2313 <<
"\t" << shader_stage_inst_name <<
".main();" << std::endl
2323 out <<
"if(is_function_constant_defined(MTL_global_pointsize)){ output.pointsize = "
2324 "(MTL_global_pointsize > 0.0)?MTL_global_pointsize:output.pointsize; }"
2332 out <<
"\treturn output;" << std::endl;
2342 std::stringstream out;
2343 out << std::endl <<
"/*** AUTO-GENERATED MSL FRAGMENT SHADER STUB. ***/" << std::endl;
2346 out <<
"#undef texture" << std::endl;
2347 out <<
"#undef textureLod" << std::endl;
2350 out <<
"#undef bool" << std::endl;
2357 out <<
"[[early_fragment_tests]]" << std::endl;
2370 out <<
") {" << std::endl << std::endl;
2374 <<
";" << std::endl;
2378 out << shader_stage_inst_name <<
".gl_PointCoord = gl_PointCoord;" << std::endl;
2381 out << shader_stage_inst_name <<
".gl_FrontFacing = gl_FrontFacing;" << std::endl;
2384 out <<
"fragment_shader_instance.gl_PrimitiveID = gl_PrimitiveID;" << std::endl;
2392 out << shader_stage_inst_name <<
".gpu_BaryCoord = mtl_barycentric_coord.xyz;" << std::endl;
2406 out <<
"\t/* Execute Fragment main function */\t" << std::endl
2407 <<
"\t" << shader_stage_inst_name <<
".main();" << std::endl
2412 out <<
" return output;" << std::endl <<
"}";
2420 std::stringstream out;
2421 out << std::endl <<
"/*** AUTO-GENERATED MSL COMPUTE SHADER STUB. ***/" << std::endl;
2424 out <<
"#undef texture" << std::endl;
2425 out <<
"#undef textureLod" << std::endl;
2428 out <<
"#undef bool" << std::endl;
2434 out <<
"kernel void ";
2436 out <<
"compute_function_entry_" << parent_shader_.
name_get() <<
"(\n\t";
2438 out <<
"compute_function_entry(\n\t";
2442 out <<
") {" << std::endl << std::endl;
2445 std::string stage_instance_constructor =
"";
2448 stage_instance_constructor +=
"(";
2450 if (block.is_array) {
2451 out <<
"TG " << block.type_name <<
" " << block.varname << block.array_decl <<
";";
2454 out <<
"TG " << block.type_name <<
" " << block.varname <<
";";
2456 stage_instance_constructor += ((!first) ?
"," :
"") + block.varname;
2461 stage_instance_constructor +=
")";
2464 << stage_instance_constructor <<
";" << std::endl;
2469 out << shader_stage_inst_name <<
".gl_GlobalInvocationID = gl_GlobalInvocationID;"
2473 out << shader_stage_inst_name <<
".gl_WorkGroupID = gl_WorkGroupID;" << std::endl;
2476 out << shader_stage_inst_name <<
".gl_NumWorkGroups = gl_NumWorkGroups;" << std::endl;
2479 out << shader_stage_inst_name <<
".gl_LocalInvocationIndex = gl_LocalInvocationIndex;"
2483 out << shader_stage_inst_name <<
".gl_LocalInvocationID = gl_LocalInvocationID;" << std::endl;
2492 out <<
"\t/* Execute Compute main function */\t" << std::endl
2493 <<
"\t" << shader_stage_inst_name <<
".main();" << std::endl
2504 if (is_first_parameter) {
2505 is_first_parameter =
false;
2513 bool &is_first_parameter)
2522 if (
bool(
tex.stage & stage)) {
2524 <<
" [[texture(" <<
tex.slot <<
")]]";
2535 <<
"\n\tconstant SStruct& samplers [[buffer(MTL_uniform_buffer_base_index+"
2543 if (
bool(
tex.stage & stage)) {
2545 <<
"_sampler [[sampler(" <<
tex.slot <<
")]]";
2552 "[Metal] Warning: Shader exceeds limit of %u samplers on current hardware\n",
2560 bool &is_first_parameter)
2563 if (
bool(ubo.stage &
stage)) {
2573 out << ubo.type_name <<
"* " << ubo.name <<
"[[buffer(MTL_uniform_buffer_base_index+"
2574 << ubo.slot <<
")]]";
2580 if (
bool(ssbo.stage &
stage)) {
2583 const char *memory_scope = ((writeable) ?
"device " :
"constant ");
2593 out << ssbo.type_name <<
"* " << ssbo.name <<
"[[buffer(MTL_storage_buffer_base_index+"
2594 << (ssbo.slot) <<
")]]";
2601 std::stringstream out;
2602 bool is_first_parameter =
true;
2607 out <<
parameter_delimiter(is_first_parameter) <<
"\tconstant uchar* MTL_VERTEX_DATA_" << i
2608 <<
" [[buffer(" << i <<
")]]\n";
2611 <<
"\tconstant ushort* MTL_INDEX_DATA[[buffer(MTL_SSBO_VERTEX_FETCH_IBO_INDEX)]]";
2617 is_first_parameter =
false;
2624 <<
"::PushConstantBlock* uniforms[[buffer(MTL_uniform_buffer_base_index)]]";
2625 is_first_parameter =
false;
2634 <<
"::VertexOut_TF* "
2635 "transform_feedback_results[[buffer(MTL_transform_feedback_buffer_index)]]";
2644 <<
"\n\tconst uint32_t gl_VertexID [[vertex_id]]";
2648 <<
"\n\tconst uint32_t gl_InstanceID [[instance_id]]";
2652 <<
"\n\tconst uint32_t gl_BaseInstanceARB [[base_instance]]";
2659 bool is_first_parameter =
true;
2660 std::stringstream out;
2662 <<
"::VertexOut v_in [[stage_in]]";
2667 <<
"::PushConstantBlock* uniforms[[buffer(MTL_uniform_buffer_base_index)]]";
2677 <<
"\n\tconst float2 gl_PointCoord [[point_coord]]";
2681 <<
"\n\tconst bool gl_FrontFacing [[front_facing]]";
2685 <<
"\n\tconst uint gl_PrimitiveID [[primitive_id]]";
2691 <<
"\n\tconst float3 mtl_barycentric_coord [[barycentric_coord]]";
2705 bool is_first_parameter =
true;
2706 std::stringstream out;
2710 <<
"::PushConstantBlock* uniforms[[buffer(MTL_uniform_buffer_base_index)]]";
2721 <<
"\n\tconst uint3 gl_GlobalInvocationID [[thread_position_in_grid]]";
2725 <<
"\n\tconst uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]";
2729 <<
"\n\tconst uint3 gl_NumWorkGroups [[threadgroups_per_grid]]";
2733 <<
"\n\tconst uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]]";
2737 <<
"\n\tconst uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]";
2751 std::stringstream out;
2754 out <<
"typedef struct {" << std::endl;
2757 if (uniform.is_array) {
2758 out <<
"\t" <<
to_string(uniform.type) <<
" " << uniform.name <<
"[" << uniform.array_elems
2759 <<
"];" << std::endl;
2762 out <<
"\t" <<
to_string(uniform.type) <<
" " << uniform.name <<
";" << std::endl;
2765 out <<
"} PushConstantBlock;\n\n";
2768 out << std::endl <<
"const constant PushConstantBlock *global_uniforms;" << std::endl;
2774 out <<
"#define " << uniform.name <<
" global_uniforms->" << uniform.name << std::endl;
2783 std::stringstream out;
2787 out <<
"#undef " << uniform.name << std::endl;
2791 out <<
"#undef " << ubo.name << std::endl;
2795 out <<
"#undef " << ssbo.name << std::endl;
2802 std::stringstream out;
2810 out <<
"typedef struct {" << std::endl;
2825 out <<
"\t" <<
get_matrix_subtype(in_attr.type) <<
" __internal_" << in_attr.name << elem
2826 <<
" [[attribute(" << (in_attr.layout_location + elem) <<
")]];" << std::endl;
2830 out <<
"\t" << in_attr.type <<
" " << in_attr.name <<
" [[attribute("
2831 << in_attr.layout_location <<
")]];" << std::endl;
2835 out <<
"} VertexIn;" << std::endl << std::endl;
2843 std::stringstream out;
2846 out <<
"typedef struct {" << std::endl;
2852 bool first_attr_is_position =
false;
2858 out <<
"\tfloat4 _default_position_ [[position]]";
2859 out <<
" [[invariant]]";
2860 out <<
";" << std::endl;
2870 out <<
" [[invariant]]";
2871 out <<
";" << std::endl;
2872 first_attr_is_position =
true;
2877 bool skip_first_index = first_attr_is_position;
2881 if (skip_first_index) {
2882 skip_first_index =
false;
2886 if (v_out.is_array) {
2893 for (
int i = 0; i < v_out.array_elems; i++) {
2894 out <<
"\t" << v_out.type <<
" " << v_out.instance_name <<
"_" << v_out.name << i
2895 << v_out.get_mtl_interpolation_qualifier() <<
";" << std::endl;
2901 BLI_assert(v_out.get_mtl_interpolation_qualifier() ==
" [[flat]]" &&
2902 "Matrix varying types must have [[flat]] interpolation");
2905 out <<
"\t" << subtype << v_out.instance_name <<
" __matrix_" << v_out.name << elem
2906 << v_out.get_mtl_interpolation_qualifier() <<
";" << std::endl;
2910 out <<
"\t" << v_out.type <<
" " << v_out.instance_name <<
"_" << v_out.name
2911 << v_out.get_mtl_interpolation_qualifier() <<
";" << std::endl;
2923 out <<
"\tfloat pointsize [[point_size]];" << std::endl;
2930 out <<
"\tfloat pointsize [[point_size, function_constant(MTL_global_pointsize)]];"
2937 out <<
"#if defined(USE_CLIP_PLANES) || defined(USE_WORLD_CLIP_PLANES)" << std::endl;
2940 out <<
"\tfloat clipdistance [[clip_distance, "
2941 "function_constant(MTL_clip_distances_enabled)]] ["
2945 out <<
"\tfloat clipdistance [[clip_distance, "
2946 "function_constant(MTL_clip_distances_enabled)]];"
2949 out <<
"#endif" << std::endl;
2954 out <<
"\tuint gpu_Layer [[render_target_array_index]];" << std::endl;
2959 out <<
"\tuint gpu_ViewportIndex [[viewport_array_index]];" << std::endl;
2962 out <<
"} VertexOut;" << std::endl << std::endl;
2972 std::stringstream out;
2975 out <<
"typedef struct {" << std::endl;
2980 bool first_attr_is_position =
false;
2984 out <<
"\tfloat4 pos [[position]];" << std::endl;
2986 .name =
"gl_Position",
2987 .interpolation_qualifier =
"",
2997 first_attr_is_position =
true;
3002 bool skip_first_index = first_attr_is_position;
3006 if (skip_first_index) {
3007 skip_first_index =
false;
3016 if (v_out.is_array) {
3018 for (
int i = 0; i < v_out.array_elems; i++) {
3019 out <<
"\t" << v_out.type <<
" " << v_out.name << i
3020 << v_out.get_mtl_interpolation_qualifier() <<
";" << std::endl;
3026 BLI_assert(v_out.get_mtl_interpolation_qualifier() ==
" [[flat]]" &&
3027 "Matrix varying types must have [[flat]] interpolation");
3030 out <<
"\t" << subtype <<
" __matrix_" << v_out.name << elem
3031 << v_out.get_mtl_interpolation_qualifier() <<
";" << std::endl;
3035 out <<
"\t" << v_out.type <<
" " << v_out.name << v_out.get_mtl_interpolation_qualifier()
3036 <<
";" << std::endl;
3041 out <<
"} VertexOut_TF;" << std::endl << std::endl;
3048 std::stringstream out;
3053 out <<
"typedef struct {" << std::endl;
3054 for (
int f_output = 0; f_output < fragment_interface_src.size(); f_output++) {
3055 out <<
"\t" <<
to_string(fragment_interface_src[f_output].type) <<
" "
3056 << fragment_interface_src[f_output].name <<
" [[color("
3057 << fragment_interface_src[f_output].layout_location <<
")";
3058 if (fragment_interface_src[f_output].layout_index >= 0) {
3059 out <<
", index(" << fragment_interface_src[f_output].layout_index <<
")";
3061 if (fragment_interface_src[f_output].raster_order_group >= 0) {
3062 out <<
", raster_order_group(" << fragment_interface_src[f_output].raster_order_group <<
")";
3065 <<
";" << std::endl;
3069 std::string out_depth_argument = ((this->
depth_write == DepthWrite::GREATER) ?
3071 ((this->
depth_write == DepthWrite::LESS) ?
"less" :
3073 out <<
"\tfloat fragdepth [[depth(" << out_depth_argument <<
")]];" << std::endl;
3077 out <<
"\tuint fragstencil [[stencil]];" << std::endl;
3095 std::stringstream out;
3098 out <<
"\t/* Copy Uniform block member reference */" << std::endl;
3100 <<
"global_uniforms = uniforms;" << std::endl;
3107 std::stringstream out;
3113 << tile_input.name <<
" = "
3114 <<
"fragment_tile_in." << tile_input.name <<
";" << std::endl;
3120 char swizzle[] =
"xyzw";
3123 bool is_layered_fb = bool(create_info_->
builtins_ & BuiltinBits::LAYER);
3124 std::string texel_co = (is_layered_fb) ?
3125 "ivec3(ivec2(v_in._default_position_.xy), int(v_in.gpu_Layer))" :
3126 "ivec2(v_in._default_position_.xy)";
3129 << tile_input.name <<
" = texelFetch("
3131 <<
"_subpass_img, " << texel_co <<
", 0)." << swizzle <<
";\n";
3140 std::stringstream out;
3141 out <<
"\t/* Copy UBO block references into local class variables */" << std::endl;
3145 if (
bool(ubo.stage &
stage)) {
3152 if (!ubo.is_array) {
3155 out <<
" = " << ubo.name <<
";" << std::endl;
3160 out <<
"\t/* Copy SSBO block references into local class variables */" << std::endl;
3164 if (
bool(ssbo.stage &
stage) && !ssbo.is_texture_buffer) {
3171 if (!ssbo.is_array) {
3174 out <<
" = " << ssbo.name <<
";" << std::endl;
3190 std::stringstream out;
3191 out <<
"const constant uchar* GLOBAL_MTL_VERTEX_DATA[MTL_SSBO_VERTEX_FETCH_MAX_VBOS] = {"
3195 out <<
"\t\tMTL_VERTEX_DATA_" << i << delimiter << std::endl;
3197 out <<
"};" << std::endl;
3198 out <<
"\t" << shader_stage_inst_name <<
".MTL_VERTEX_DATA = GLOBAL_MTL_VERTEX_DATA;"
3200 out <<
"\t" << shader_stage_inst_name <<
".MTL_INDEX_DATA_U16 = MTL_INDEX_DATA;" << std::endl;
3201 out <<
"\t" << shader_stage_inst_name
3202 <<
".MTL_INDEX_DATA_U32 = reinterpret_cast<constant "
3203 "uint32_t*>(MTL_INDEX_DATA);"
3209 std::stringstream out;
3210 out <<
"\t/* Copy Vertex Stage-in attributes into local variables */" << std::endl;
3247 bool do_attribute_conversion_on_read =
false;
3251 if (do_attribute_conversion_on_read) {
3253 out <<
"\t" << attribute_conversion_func_name <<
"(MTL_AttributeConvert"
3259 out <<
"\t" << shader_stage_inst_name <<
"."
3273 std::stringstream out;
3274 out <<
"\t/* Copy Vertex Outputs into output struct */" << std::endl;
3278 out <<
"\toutput._default_position_ = " << shader_stage_inst_name <<
".gl_Position;"
3283 out <<
"\toutput._default_position_.y = -output._default_position_.y;" << std::endl;
3284 out <<
"\toutput._default_position_.z = "
3285 "(output._default_position_.z+output._default_position_.w)/2.0;"
3291 out <<
"\toutput.pointsize = " << shader_stage_inst_name <<
".gl_PointSize;" << std::endl;
3296 out <<
"\toutput.gpu_Layer = " << shader_stage_inst_name <<
".gpu_Layer;" << std::endl;
3301 out <<
"\toutput.gpu_ViewportIndex = " << shader_stage_inst_name <<
".gpu_ViewportIndex;"
3309 out <<
"#if defined(USE_CLIP_PLANES) || defined(USE_WORLD_CLIP_PLANES)" << std::endl
3310 <<
"if(MTL_clip_distances_enabled) {" << std::endl;
3314 out <<
"\toutput.clipdistance[" << cd
3315 <<
"] = (is_function_constant_defined(MTL_clip_distance_enabled" << cd <<
"))?"
3316 << shader_stage_inst_name <<
".gl_ClipDistance_" << cd <<
":1.0;" << std::endl;
3320 out <<
"\toutput.clipdistance = " << shader_stage_inst_name <<
".gl_ClipDistance_0;"
3323 out <<
"}" << std::endl <<
"#endif" << std::endl;
3328 if (v_out.is_array) {
3330 for (
int i = 0; i < v_out.array_elems; i++) {
3331 out <<
"\toutput." << v_out.instance_name <<
"_" << v_out.name << i <<
" = "
3332 << shader_stage_inst_name <<
".";
3334 if (v_out.instance_name !=
"") {
3335 out << v_out.instance_name <<
".";
3338 out << v_out.name <<
"[" << i <<
"]"
3339 <<
";" << std::endl;
3346 out <<
"\toutput." << v_out.instance_name <<
"__matrix_" << v_out.name << elem <<
" = "
3347 << shader_stage_inst_name <<
".";
3349 if (v_out.instance_name !=
"") {
3350 out << v_out.instance_name <<
".";
3353 out << v_out.name <<
"[" << elem <<
"];" << std::endl;
3361 out <<
"\toutput." << v_out.instance_name <<
"_" << v_out.name <<
" = to_vec4("
3362 << shader_stage_inst_name <<
"." << v_out.name <<
");" << std::endl;
3365 out <<
"\toutput." << v_out.instance_name <<
"_" << v_out.name <<
".y = -output."
3366 << v_out.name <<
".y;" << std::endl;
3371 out <<
"\toutput." << v_out.instance_name <<
"_" << v_out.name <<
" = "
3372 << shader_stage_inst_name <<
".";
3374 if (v_out.instance_name !=
"") {
3375 out << v_out.instance_name <<
".";
3378 out << v_out.name <<
";" << std::endl;
3392 std::stringstream out;
3393 out <<
"\t/* Copy Vertex TF Outputs into transform feedback buffer */" << std::endl;
3399 out <<
"transform_feedback_results[gl_VertexID]."
3413 std::stringstream out;
3414 out <<
"\t/* Copy Fragment input into local variables. */" << std::endl;
3418 out <<
"\t" << shader_stage_inst_name <<
".gl_FragCoord = v_in._default_position_;"
3423 out <<
"\t" << shader_stage_inst_name <<
".gl_FragCoord = v_in."
3431 out <<
"\t" << shader_stage_inst_name <<
".gl_FragDepth = " << shader_stage_inst_name
3432 <<
".gl_FragCoord.z;" << std::endl;
3437 out <<
"\t" << shader_stage_inst_name <<
".gpu_Layer = v_in.gpu_Layer;" << std::endl;
3442 out <<
"\t" << shader_stage_inst_name <<
".gpu_ViewportIndex = v_in.gpu_ViewportIndex;"
3458 bool exists_in_vertex_output =
false;
3462 exists_in_vertex_output =
true;
3465 if (!exists_in_vertex_output) {
3467 "[Warning] Fragment shader expects varying input '%s', but this is not passed from "
3475 out <<
"\t" << shader_stage_inst_name <<
".";
3489 out <<
"\t" << shader_stage_inst_name <<
".";
3498 for (
int elem = 0; elem <
count; elem++) {
3499 out << ((elem == 0) ?
"(" :
"") <<
"v_in."
3502 << ((elem <
count - 1) ?
",\n" :
"");
3504 out <<
");" << std::endl;
3507 out <<
"\t" << shader_stage_inst_name <<
".";
3529 std::stringstream out;
3530 out <<
"\t/* Copy Fragment Outputs into output struct. */" << std::endl;
3534 out <<
"\toutput.fragdepth = " << shader_stage_inst_name <<
".gl_FragDepth;" << std::endl;
3539 out <<
"\toutput.fragstencil = uint(" << shader_stage_inst_name <<
".gl_FragStencilRefARB);"
3544 for (
int f_output = 0; f_output < this->
fragment_outputs.size(); f_output++) {
3546 out <<
"\toutput." << this->
fragment_outputs[f_output].name <<
" = " << shader_stage_inst_name
3560 std::stringstream out;
3561 out <<
"\t/* Populate local texture and sampler members */" << std::endl;
3568 <<
";" << std::endl;
3579 <<
"_sampler;" << std::endl;
3584 if (tex_buf_id != -1) {
3595 ImageType::UINT_2D_ARRAY_ATOMIC,
3596 ImageType::UINT_3D_ATOMIC,
3597 ImageType::INT_2D_ARRAY_ATOMIC,
3598 ImageType::INT_3D_ATOMIC))
3616 if (attr.layout_location >= 0) {
3619 for (
uint32_t i = 1; i <= location_element_count; i++) {
3621 uint32_t location_mask = (i << attr.layout_location);
3622 BLI_assert((used_locations & location_mask) == 0);
3623 used_locations = used_locations | location_mask;
3630 if (attr.layout_location == -1) {
3640 uint32_t location_mask = (1 << loc);
3646 uint32_t location_slot_mask = (1 << required_attr_slot_count) - 1;
3647 uint32_t sliding_location_slot_mask = location_slot_mask << location_mask;
3648 if ((used_locations & sliding_location_slot_mask) == 0) {
3650 attr.layout_location = loc;
3651 used_locations = used_locations | location_slot_mask;
3657 MTL_LOG_ERROR(
"Could not assign attribute location to attribute %s for shader %s",
3659 this->parent_shader_.name_get());
3666 int running_location_ind = 0;
3672 ((running_location_ind > 0) ? (this->
fragment_outputs[i].layout_location == -1) :
true),
3673 "Error: Mismatched input attributes, some with location specified, some without");
3676 running_location_ind++;
3686 const char *str_to_copy,
3694 uint32_t ret_len = strlen(str_to_copy);
3698 if (name_buffer_offset + ret_len + 1 > name_buffer_size) {
3699 name_buffer_size = name_buffer_offset +
max_ii(128, ret_len + 1);
3700 *name_buffer_ptr = (
char *)
MEM_reallocN(*name_buffer_ptr, name_buffer_size);
3704 uint32_t insert_offset = name_buffer_offset;
3705 char *current_offset = (*name_buffer_ptr) + insert_offset;
3706 memcpy(current_offset, str_to_copy, (ret_len + 1) *
sizeof(
char));
3709 name_buffer_offset += ret_len + 1;
3712 return insert_offset;
3725 interface->name_buffer_ = (
char *)
MEM_mallocN(name_buffer_size,
"name_buffer");
3744 std::string _internal_name = (elem == 0) ?
3748 std::to_string(elem);
3754 interface->add_input_attribute(
3756 _internal_name.c_str(),
3758 name_buffer_offset),
3759 this->vertex_input_attributes[attribute].layout_location + elem,
3771 "[Note] Matrix Type '%s' added to shader interface as vertex attribute. (Elem Count: "
3781 interface->add_input_attribute(
3783 this->vertex_input_attributes[attribute].name.c_str(),
3785 name_buffer_offset),
3786 this->vertex_input_attributes[attribute].layout_location,
3801 &interface->name_buffer_,
"PushConstantBlock", name_buffer_size, name_buffer_offset));
3803 for (
int uniform = 0; uniform < this->
uniforms.size(); uniform++) {
3804 interface->add_uniform(
3806 this->uniforms[uniform].name.c_str(),
3808 name_buffer_offset),
3810 (this->
uniforms[uniform].is_array) ? this->
uniforms[uniform].array_elems : 1);
3814 for (
int uniform_block = 0; uniform_block < this->
uniform_blocks.size(); uniform_block++) {
3815 interface->add_uniform_block(
3817 this->uniform_blocks[uniform_block].name.c_str(),
3819 name_buffer_offset),
3827 for (
int storage_block = 0; storage_block < this->
storage_blocks.size(); storage_block++) {
3828 interface->add_storage_block(
3830 this->storage_blocks[storage_block].name.c_str(),
3832 name_buffer_offset),
3842 uint tex_buf_ssbo_location = -1;
3843 uint tex_buf_ssbo_id = input_texture.atomic_fallback_buffer_ssbo_id;
3844 if (tex_buf_ssbo_id != -1) {
3845 tex_buf_ssbo_location = this->
storage_blocks[tex_buf_ssbo_id].location;
3849 input_texture.name.c_str(),
3851 name_buffer_offset),
3853 input_texture.location,
3854 input_texture.get_texture_binding_type(),
3855 input_texture.get_sampler_format(),
3856 input_texture.is_texture_sampler,
3857 input_texture.stage,
3858 tex_buf_ssbo_location);
3864 &interface->name_buffer_, constant.name.c_str(), name_buffer_size, name_buffer_offset));
3868 interface->set_sampler_properties(
3875 interface->prepare_common_shader_inputs(info);
3878 if (name_buffer_offset < name_buffer_size) {
3879 interface->name_buffer_ = (
char *)
MEM_reallocN(interface->name_buffer_, name_buffer_offset);
3889 switch (this->type) {
3890 case ImageType::FLOAT_1D: {
3893 case ImageType::FLOAT_2D: {
3896 case ImageType::FLOAT_3D: {
3899 case ImageType::FLOAT_CUBE: {
3900 return "texturecube";
3902 case ImageType::FLOAT_1D_ARRAY: {
3903 return "texture1d_array";
3905 case ImageType::FLOAT_2D_ARRAY: {
3906 return "texture2d_array";
3908 case ImageType::FLOAT_CUBE_ARRAY: {
3909 return "texturecube_array";
3911 case ImageType::FLOAT_BUFFER: {
3912 return "texture_buffer";
3914 case ImageType::DEPTH_2D: {
3917 case ImageType::SHADOW_2D: {
3920 case ImageType::DEPTH_2D_ARRAY: {
3921 return "depth2d_array";
3923 case ImageType::SHADOW_2D_ARRAY: {
3924 return "depth2d_array";
3926 case ImageType::DEPTH_CUBE: {
3929 case ImageType::SHADOW_CUBE: {
3932 case ImageType::DEPTH_CUBE_ARRAY: {
3933 return "depthcube_array";
3935 case ImageType::SHADOW_CUBE_ARRAY: {
3936 return "depthcube_array";
3938 case ImageType::INT_1D: {
3941 case ImageType::INT_2D: {
3944 case ImageType::INT_3D: {
3947 case ImageType::INT_CUBE: {
3948 return "texturecube";
3950 case ImageType::INT_1D_ARRAY: {
3951 return "texture1d_array";
3953 case ImageType::INT_2D_ARRAY: {
3954 return "texture2d_array";
3956 case ImageType::INT_CUBE_ARRAY: {
3957 return "texturecube_array";
3959 case ImageType::INT_BUFFER: {
3960 return "texture_buffer";
3962 case ImageType::UINT_1D: {
3965 case ImageType::UINT_2D: {
3968 case ImageType::UINT_3D: {
3971 case ImageType::UINT_CUBE: {
3972 return "texturecube";
3974 case ImageType::UINT_1D_ARRAY: {
3975 return "texture1d_array";
3977 case ImageType::UINT_2D_ARRAY: {
3978 return "texture2d_array";
3980 case ImageType::UINT_CUBE_ARRAY: {
3981 return "texturecube_array";
3983 case ImageType::UINT_BUFFER: {
3984 return "texture_buffer";
3988 case ImageType::INT_2D_ATOMIC:
3989 case ImageType::UINT_2D_ATOMIC: {
3992 case ImageType::INT_2D_ARRAY_ATOMIC:
3993 case ImageType::UINT_2D_ARRAY_ATOMIC: {
3994 if (supports_native_atomics) {
3995 return "texture2d_array";
4001 case ImageType::INT_3D_ATOMIC:
4002 case ImageType::UINT_3D_ATOMIC: {
4003 if (supports_native_atomics) {
4023 switch (this->type) {
4024 case ImageType::FLOAT_1D: {
4025 return "_mtl_combined_image_sampler_1d";
4027 case ImageType::FLOAT_2D: {
4028 return "_mtl_combined_image_sampler_2d";
4030 case ImageType::FLOAT_3D: {
4031 return "_mtl_combined_image_sampler_3d";
4033 case ImageType::FLOAT_CUBE: {
4034 return "_mtl_combined_image_sampler_cube";
4036 case ImageType::FLOAT_1D_ARRAY: {
4037 return "_mtl_combined_image_sampler_1d_array";
4039 case ImageType::FLOAT_2D_ARRAY: {
4040 return "_mtl_combined_image_sampler_2d_array";
4042 case ImageType::FLOAT_CUBE_ARRAY: {
4043 return "_mtl_combined_image_sampler_cube_array";
4045 case ImageType::FLOAT_BUFFER: {
4046 return "_mtl_combined_image_sampler_buffer";
4048 case ImageType::DEPTH_2D: {
4049 return "_mtl_combined_image_sampler_depth_2d";
4051 case ImageType::SHADOW_2D: {
4052 return "_mtl_combined_image_sampler_depth_2d";
4054 case ImageType::DEPTH_2D_ARRAY: {
4055 return "_mtl_combined_image_sampler_depth_2d_array";
4057 case ImageType::SHADOW_2D_ARRAY: {
4058 return "_mtl_combined_image_sampler_depth_2d_array";
4060 case ImageType::DEPTH_CUBE: {
4061 return "_mtl_combined_image_sampler_depth_cube";
4063 case ImageType::SHADOW_CUBE: {
4064 return "_mtl_combined_image_sampler_depth_cube";
4066 case ImageType::DEPTH_CUBE_ARRAY: {
4067 return "_mtl_combined_image_sampler_depth_cube_array";
4069 case ImageType::SHADOW_CUBE_ARRAY: {
4070 return "_mtl_combined_image_sampler_depth_cube_array";
4072 case ImageType::INT_1D: {
4073 return "_mtl_combined_image_sampler_1d";
4075 case ImageType::INT_2D: {
4076 return "_mtl_combined_image_sampler_2d";
4078 case ImageType::INT_3D: {
4079 return "_mtl_combined_image_sampler_3d";
4081 case ImageType::INT_CUBE: {
4082 return "_mtl_combined_image_sampler_cube";
4084 case ImageType::INT_1D_ARRAY: {
4085 return "_mtl_combined_image_sampler_1d_array";
4087 case ImageType::INT_2D_ARRAY: {
4088 return "_mtl_combined_image_sampler_2d_array";
4090 case ImageType::INT_CUBE_ARRAY: {
4091 return "_mtl_combined_image_sampler_cube_array";
4093 case ImageType::INT_BUFFER: {
4094 return "_mtl_combined_image_sampler_buffer";
4096 case ImageType::UINT_1D: {
4097 return "_mtl_combined_image_sampler_1d";
4099 case ImageType::UINT_2D: {
4100 return "_mtl_combined_image_sampler_2d";
4102 case ImageType::UINT_3D: {
4103 return "_mtl_combined_image_sampler_3d";
4105 case ImageType::UINT_CUBE: {
4106 return "_mtl_combined_image_sampler_cube";
4108 case ImageType::UINT_1D_ARRAY: {
4109 return "_mtl_combined_image_sampler_1d_array";
4111 case ImageType::UINT_2D_ARRAY: {
4112 return "_mtl_combined_image_sampler_2d_array";
4114 case ImageType::UINT_CUBE_ARRAY: {
4115 return "_mtl_combined_image_sampler_cube_array";
4117 case ImageType::UINT_BUFFER: {
4118 return "_mtl_combined_image_sampler_buffer";
4122 case ImageType::INT_2D_ATOMIC:
4123 case ImageType::UINT_2D_ATOMIC: {
4124 if (supports_native_atomics) {
4125 return "_mtl_combined_image_sampler_2d";
4128 return "_mtl_combined_image_sampler_2d_atomic_fallback";
4131 case ImageType::INT_3D_ATOMIC:
4132 case ImageType::UINT_3D_ATOMIC: {
4133 if (supports_native_atomics) {
4134 return "_mtl_combined_image_sampler_3d";
4137 return "_mtl_combined_image_sampler_3d_atomic_fallback";
4140 case ImageType::INT_2D_ARRAY_ATOMIC:
4141 case ImageType::UINT_2D_ARRAY_ATOMIC: {
4142 if (supports_native_atomics) {
4143 return "_mtl_combined_image_sampler_2d_array";
4146 return "_mtl_combined_image_sampler_2d_array_atomic_fallback";
4160 switch (this->type) {
4162 case ImageType::FLOAT_1D:
4163 case ImageType::FLOAT_2D:
4164 case ImageType::FLOAT_3D:
4165 case ImageType::FLOAT_CUBE:
4166 case ImageType::FLOAT_1D_ARRAY:
4167 case ImageType::FLOAT_2D_ARRAY:
4168 case ImageType::FLOAT_CUBE_ARRAY:
4169 case ImageType::FLOAT_BUFFER:
4170 case ImageType::DEPTH_2D:
4171 case ImageType::SHADOW_2D:
4172 case ImageType::DEPTH_2D_ARRAY:
4173 case ImageType::SHADOW_2D_ARRAY:
4174 case ImageType::DEPTH_CUBE:
4175 case ImageType::SHADOW_CUBE:
4176 case ImageType::DEPTH_CUBE_ARRAY:
4177 case ImageType::SHADOW_CUBE_ARRAY: {
4181 case ImageType::INT_1D:
4182 case ImageType::INT_2D:
4183 case ImageType::INT_3D:
4184 case ImageType::INT_CUBE:
4185 case ImageType::INT_1D_ARRAY:
4186 case ImageType::INT_2D_ARRAY:
4187 case ImageType::INT_CUBE_ARRAY:
4188 case ImageType::INT_BUFFER:
4189 case ImageType::INT_2D_ATOMIC:
4190 case ImageType::INT_2D_ARRAY_ATOMIC:
4191 case ImageType::INT_3D_ATOMIC: {
4196 case ImageType::UINT_1D:
4197 case ImageType::UINT_2D:
4198 case ImageType::UINT_3D:
4199 case ImageType::UINT_CUBE:
4200 case ImageType::UINT_1D_ARRAY:
4201 case ImageType::UINT_2D_ARRAY:
4202 case ImageType::UINT_CUBE_ARRAY:
4203 case ImageType::UINT_BUFFER:
4204 case ImageType::UINT_2D_ATOMIC:
4205 case ImageType::UINT_2D_ARRAY_ATOMIC:
4206 case ImageType::UINT_3D_ATOMIC: {
4221 switch (this->type) {
4222 case ImageType::FLOAT_1D: {
4225 case ImageType::FLOAT_2D: {
4228 case ImageType::FLOAT_3D: {
4231 case ImageType::FLOAT_CUBE: {
4234 case ImageType::FLOAT_1D_ARRAY: {
4237 case ImageType::FLOAT_2D_ARRAY: {
4240 case ImageType::FLOAT_CUBE_ARRAY: {
4243 case ImageType::FLOAT_BUFFER: {
4246 case ImageType::DEPTH_2D: {
4249 case ImageType::SHADOW_2D: {
4252 case ImageType::DEPTH_2D_ARRAY: {
4255 case ImageType::SHADOW_2D_ARRAY: {
4258 case ImageType::DEPTH_CUBE: {
4261 case ImageType::SHADOW_CUBE: {
4264 case ImageType::DEPTH_CUBE_ARRAY: {
4267 case ImageType::SHADOW_CUBE_ARRAY: {
4270 case ImageType::INT_1D: {
4273 case ImageType::INT_2D: {
4276 case ImageType::INT_3D: {
4279 case ImageType::INT_CUBE: {
4282 case ImageType::INT_1D_ARRAY: {
4285 case ImageType::INT_2D_ARRAY: {
4288 case ImageType::INT_CUBE_ARRAY: {
4291 case ImageType::INT_BUFFER: {
4294 case ImageType::UINT_1D: {
4297 case ImageType::UINT_2D:
4298 case ImageType::UINT_2D_ATOMIC:
4299 case ImageType::INT_2D_ATOMIC: {
4302 case ImageType::UINT_3D:
4303 case ImageType::UINT_3D_ATOMIC:
4304 case ImageType::INT_3D_ATOMIC: {
4307 case ImageType::UINT_CUBE: {
4310 case ImageType::UINT_1D_ARRAY: {
4313 case ImageType::UINT_2D_ARRAY:
4314 case ImageType::UINT_2D_ARRAY_ATOMIC:
4315 case ImageType::INT_2D_ARRAY_ATOMIC: {
4318 case ImageType::UINT_CUBE_ARRAY: {
4321 case ImageType::UINT_BUFFER: {
4333 switch (this->type) {
4334 case ImageType::FLOAT_BUFFER:
4335 case ImageType::FLOAT_1D:
4336 case ImageType::FLOAT_1D_ARRAY:
4337 case ImageType::FLOAT_2D:
4338 case ImageType::FLOAT_2D_ARRAY:
4339 case ImageType::FLOAT_3D:
4340 case ImageType::FLOAT_CUBE:
4341 case ImageType::FLOAT_CUBE_ARRAY:
4343 case ImageType::INT_BUFFER:
4344 case ImageType::INT_1D:
4345 case ImageType::INT_1D_ARRAY:
4346 case ImageType::INT_2D:
4347 case ImageType::INT_2D_ARRAY:
4348 case ImageType::INT_3D:
4349 case ImageType::INT_CUBE:
4350 case ImageType::INT_CUBE_ARRAY:
4351 case ImageType::INT_2D_ATOMIC:
4352 case ImageType::INT_3D_ATOMIC:
4353 case ImageType::INT_2D_ARRAY_ATOMIC:
4355 case ImageType::UINT_BUFFER:
4356 case ImageType::UINT_1D:
4357 case ImageType::UINT_1D_ARRAY:
4358 case ImageType::UINT_2D:
4359 case ImageType::UINT_2D_ARRAY:
4360 case ImageType::UINT_3D:
4361 case ImageType::UINT_CUBE:
4362 case ImageType::UINT_CUBE_ARRAY:
4363 case ImageType::UINT_2D_ATOMIC:
4364 case ImageType::UINT_3D_ATOMIC:
4365 case ImageType::UINT_2D_ARRAY_ATOMIC:
4367 case ImageType::SHADOW_2D:
4368 case ImageType::SHADOW_2D_ARRAY:
4369 case ImageType::SHADOW_CUBE:
4370 case ImageType::SHADOW_CUBE_ARRAY:
4371 case ImageType::DEPTH_2D:
4372 case ImageType::DEPTH_2D_ARRAY:
4373 case ImageType::DEPTH_CUBE:
4374 case ImageType::DEPTH_CUBE_ARRAY:
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
MINLINE uint max_uu(uint a, uint b)
MINLINE int max_ii(int a, int b)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define ARRAY_SET_ITEMS(...)
#define UNUSED_VARS_NDEBUG(...)
int GPU_max_textures_vert()
#define MEM_reallocN(vmemh, len)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
vertex_source("basic_depth_pointcloud_vert.glsl") .additional_info("draw_pointcloud")
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void append(const T &value)
std::string generate_msl_texture_vars(ShaderStage shader_stage)
std::string generate_msl_uniform_structs(ShaderStage shader_stage)
std::string generate_msl_global_uniform_population(ShaderStage stage)
void resolve_input_attribute_locations()
std::string generate_msl_vertex_entry_stub()
blender::Vector< MSLBufferBlock > uniform_blocks
void prepare_ssbo_vertex_fetch_uniforms()
bool uses_gpu_viewport_index
blender::Vector< MSLBufferBlock > storage_blocks
std::string generate_msl_vertex_output_population()
shader::DepthWrite depth_write
bool uses_transform_feedback
std::string generate_msl_vertex_in_struct()
std::string generate_msl_uniform_block_population(ShaderStage stage)
bool uses_gl_GlobalInvocationID
void resolve_fragment_output_locations()
blender::Vector< MSLFragmentTileInputAttribute > fragment_tile_inputs
std::string generate_msl_compute_entry_stub()
bool use_argument_buffer_for_samplers() const
bool uses_gl_NumWorkGroups
std::string generate_msl_vertex_transform_feedback_out_struct(ShaderStage shader_stage)
blender::Vector< MSLVertexOutputAttribute > fragment_input_varyings
bool uses_ssbo_vertex_fetch_mode
std::string generate_msl_fragment_input_population()
blender::Vector< MSLVertexOutputAttribute > vertex_output_varyings
uint32_t get_sampler_argument_buffer_bind_index(ShaderStage stage)
std::string generate_msl_vertex_output_tf_population()
bool uses_gl_LocalInvocationID
std::string generate_msl_fragment_inputs_string()
blender::Vector< MSLTextureResource > texture_samplers
bool uses_early_fragment_test
blender::Vector< MSLVertexInputAttribute > vertex_input_attributes
std::string generate_msl_fragment_struct(bool is_input)
std::string generate_msl_uniform_undefs(ShaderStage stage)
std::string generate_msl_compute_inputs_string()
std::string generate_msl_fragment_tile_input_population()
void prepare_from_createinfo(const shader::ShaderCreateInfo *info)
std::string generate_msl_fragment_output_population()
uint32_t max_sampler_index_for_stage(ShaderStage stage) const
blender::Vector< MSLConstant > constants
std::string generate_msl_vertex_out_struct(ShaderStage shader_stage)
uint32_t num_samplers_for_stage(ShaderStage stage) const
std::string generate_msl_fragment_entry_stub()
void generate_msl_uniforms_input_string(std::stringstream &out, ShaderStage stage, bool &is_first_parameter)
blender::Vector< char > clip_distances
blender::Vector< MSLFragmentOutputAttribute > fragment_outputs
blender::Vector< MSLVertexOutputAttribute > vertex_output_varyings_tf
MTLShaderInterface * bake_shader_interface(const char *name, const shader::ShaderCreateInfo *info=nullptr)
void generate_msl_textures_input_string(std::stringstream &out, ShaderStage stage, bool &is_first_parameter)
std::string generate_msl_vertex_inputs_string()
blender::Vector< MSLSharedMemoryBlock > shared_memory_blocks
bool uses_gl_BaseInstanceARB
int sampler_argument_buffer_bind_index[3]
bool uses_gl_FragStencilRefARB
blender::Vector< MSLUniform > uniforms
std::string generate_msl_vertex_attribute_input_population()
bool uses_gl_LocalInvocationIndex
char * msl_patch_default_get()
bool supports_native_tile_inputs
static MTLCapabilities & get_capabilities()
uint32_t get_total_attributes() const
const char * get_name_at_offset(uint32_t offset) const
const MTLShaderInputAttribute & get_attribute(uint index) const
void set_fragment_function_name(NSString *fragment_function_name)
int uni_ssbo_input_prim_type_loc
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
void shader_compute_source_from_msl(NSString *input_compute_source)
int uni_ssbo_index_base_loc
int uni_ssbo_uses_index_mode_u16
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override
int uni_ssbo_input_vert_count_loc
int uni_ssbo_uses_indexed_rendering
std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override
bool has_transform_feedback_varying(std::string str)
void set_vertex_function_name(NSString *vetex_function_name)
void shader_source_from_msl(NSString *input_vertex_source, NSString *input_fragment_source)
MTLShaderInterface * get_interface()
void prepare_ssbo_vertex_fetch_metadata()
std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
void set_interface(MTLShaderInterface *interface)
void set_compute_function_name(NSString *compute_function_name)
const ShaderInput * uniform_get(const char *name) const
ShaderInterface * interface
const char *const name_get() const
output_img push_constant(Type::FLOAT, "subtrahend") .define("TYPE"
void *(* MEM_mallocN)(size_t len, const char *str)
static void error(const char *str)
static void clear(Message &msg)
#define MTL_MAX_BUFFER_BINDINGS
#define MTL_MAX_TEXTURE_SLOTS
#define MTL_MAX_DEFAULT_SAMPLERS
#define MTL_LOG_INFO(info,...)
#define MTL_LOG_WARNING(info,...)
#define MTL_LOG_ERROR(info,...)
#define shader_debug_printf(...)
#define MTL_SHADER_SPECIALIZATION_CONSTANT_BASE_ID
#define UNIFORM_SSBO_VBO_ID_STR
#define UNIFORM_SSBO_OFFSET_STR
#define UNIFORM_SSBO_INPUT_VERT_COUNT_STR
#define UNIFORM_SSBO_INPUT_PRIM_TYPE_STR
#define UNIFORM_SSBO_STRIDE_STR
#define UNIFORM_SSBO_USES_INDEXED_RENDERING_STR
#define UNIFORM_SSBO_INDEX_MODE_U16_STR
#define UNIFORM_SSBO_FETCHMODE_STR
#define UNIFORM_SSBO_TYPE_STR
#define UNIFORM_SSBO_INDEX_BASE_STR
#define FRAGMENT_TILE_IN_STRUCT_NAME
char datatoc_mtl_shader_defines_msl[]
#define ATOMIC_DEFINE_STR
#define FRAGMENT_OUT_STRUCT_NAME
char datatoc_mtl_shader_shared_h[]
@ MTL_DATATYPE_INT1010102_NORM
uint mtl_get_data_type_size(eMTLDataType type)
#define MTL_SSBO_VERTEX_FETCH_MAX_VBOS
BLI_INLINE int to_component_count(const Type &type)
@ TEXTURE_ACCESS_READWRITE
static void replace_array_initializers_func(std::string &str)
uint get_shader_stage_index(ShaderStage stage)
char * next_word_in_range(char *begin, char *end)
const char * to_string(ShaderStage stage)
bool is_matrix_type(const std::string &type)
static void replace_matrix_constructors(std::string &str)
static uint32_t name_buffer_copystr(char **name_buffer_ptr, const char *str_to_copy, uint32_t &name_buffer_size, uint32_t &name_buffer_offset)
constexpr size_t const_strlen(const char *str)
static bool is_program_word(const char *chr, int *len)
static void extract_and_replace_clipping_distances(std::string &vertex_source, MSLGeneratorInterface &msl_iface)
static void remove_multiline_comments_func(std::string &str)
static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &res)
const char * get_shader_stage_instance_name(ShaderStage stage)
static bool extract_ssbo_pragma_info(const MTLShader *shader, const MSLGeneratorInterface &, const std::string &in_vertex_src, MTLPrimitiveType &out_prim_tye, uint32_t &out_num_output_verts)
static void replace_outvars(std::string &str)
const char * to_string_msl(const shader::Interpolation &interp)
static char parameter_delimiter(bool &is_first_parameter)
const char * get_stage_class_name(ShaderStage stage)
static std::regex remove_non_numeric_characters("[^0-9]")
int get_matrix_location_count(const std::string &type)
static MTLSamplerAddressMode to_mtl_type(GPUSamplerExtendMode wrap_mode)
static void extract_global_scope_constants(std::string &str, std::stringstream &)
std::string get_matrix_subtype(const std::string &type)
static int backwards_program_word_scan(const char *array_loc, const char *min)
static void remove_singleline_comments_func(std::string &str)
std::string get_attribute_conversion_function(bool *uses_conversion, const shader::Type &type)
bool is_builtin_type(std::string type)
char * next_symbol_in_range(char *begin, char *end, char symbol)
static bool balanced_braces(char *current_str_begin, char *current_str_end)
static void generate_specialization_constant_declarations(const shader::ShaderCreateInfo *info, std::stringstream &ss)
void extract_shared_memory_blocks(MSLGeneratorInterface &msl_iface, std::string &glsl_compute_source)
MTLVertexFormat mtl_datatype_to_vertex_type(eMTLDataType type)
shader::Qualifier qualifiers
eGPUSamplerFormat get_sampler_format() const
std::string get_msl_return_type_str() const
MSLTextureSamplerAccess access
std::string get_msl_texture_type_str() const
eGPUTextureType get_texture_binding_type() const
std::string get_msl_wrapper_type_str() const
bool supports_texture_atomics
void set_compute_workgroup_size(int workgroup_size_x, int workgroup_size_y, int workgroup_size_z)
std::string glsl_compute_source_
std::string glsl_fragment_source_
std::string glsl_vertex_source_
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Vector< SubpassIn > subpass_inputs_
Vector< Resource > geometry_resources_
Vector< const char * > tf_names_
Vector< VertIn > vertex_inputs_
bool early_fragment_test_
bool auto_resource_location_
Vector< Resource > batch_resources_
Vector< Resource > pass_resources_
Vector< Resource > resources_get_all_() const
ComputeStageLayout compute_layout_
eGPUShaderTFBType tf_type_
Vector< SpecializationConstant > specialization_constants_
Vector< PushConst > push_constants_
Vector< FragOut > fragment_outputs_