56 return "Vertex Shader";
58 return "Fragment Shader";
60 return "Compute Shader";
64 return "Unknown Shader Stage";
82 char c = this->name[i];
83 if ((c >=
'A' && c <=
'Z') || (c >=
'a' && c <=
'z') || (c >=
'0' && c <=
'9')) {
96 NSString *input_vertex_source,
97 NSString *input_fragment_source,
98 NSString *vert_function_name,
99 NSString *frag_function_name)
117 if (push_constant_data_ !=
nullptr) {
119 push_constant_data_ =
nullptr;
128 if (pso_descriptor_ != nil) {
129 [pso_descriptor_ release];
130 pso_descriptor_ = nil;
134 pso_cache_lock_.lock();
138 [pso_inst->pso release];
141 if (pso_inst->vert) {
142 [pso_inst->vert release];
145 if (pso_inst->frag) {
146 [pso_inst->frag release];
156 [pso_inst->pso release];
159 if (pso_inst->compute) {
160 [pso_inst->compute release];
163 compute_pso_cache_.clear();
164 pso_cache_lock_.unlock();
167 if (shader_library_vert_ != nil) {
168 [shader_library_vert_ release];
169 shader_library_vert_ = nil;
171 if (shader_library_frag_ != nil) {
172 [shader_library_frag_ release];
173 shader_library_frag_ = nil;
175 if (shader_library_compute_ != nil) {
176 [shader_library_compute_ release];
177 shader_library_compute_ = nil;
184 if (shd_builder_ !=
nullptr) {
186 shd_builder_ =
nullptr;
192 async_compilation_ = is_batch_compilation;
211 std::stringstream ss;
212 for (
int i = 0; i < sources.
size(); i++) {
213 ss << sources[i] << std::endl;
220 MTL_LOG_ERROR(
"MTLShader::geometry_shader_from_glsl - Geometry shaders unsupported!");
233 std::stringstream ss;
235 for (i = 0; i < sources.
size(); i++) {
238 if (name.is_empty()) {
239 ss <<
"#line 1 \"generated_code_" << i <<
"\"\n";
242 ss <<
"#line 1 \"" << name <<
"\"\n";
245 ss << sources[i] <<
'\n';
247 ss <<
"#line 1 \"msl_wrapper_code\"\n";
261 std::stringstream ss;
262 for (
int i = 0; i < sources.
size(); i++) {
265 if (name.is_empty()) {
266 ss <<
"#line 1 \"generated_code_" << i <<
"\"\n";
269 ss <<
"#line 1 \"" << name <<
"\"\n";
271 ss << sources[i] << std::endl;
284 bool is_compute =
false;
286 BLI_assert_msg(info !=
nullptr,
"Compute shaders must use CreateInfo.\n");
294 bool success = generate_msl_from_glsl(info);
298 BLI_assert_msg(
false,
"Shader translation from GLSL to MSL has failed. \n");
306 shd_builder_ =
nullptr;
314 int threadgroup_tuning_param = info->mtl_max_threads_per_threadgroup_;
315 if (threadgroup_tuning_param > 0) {
316 maxTotalThreadsPerThreadgroup_Tuning_ = threadgroup_tuning_param;
326 id<MTLDevice> device = context_->
device;
333 BLI_assert([compute_function_name_ length] > 0);
338 BLI_assert([vertex_function_name_ length] > 0);
340 BLI_assert([fragment_function_name_ length] > 0);
346 MTLCompileOptions *
options = [[[MTLCompileOptions alloc]
init] autorelease];
347 options.languageVersion = MTLLanguageVersion2_2;
349 options.preserveInvariance = YES;
355 options.languageVersion = MTLLanguageVersion2_3;
357#if defined(MAC_OS_VERSION_14_0)
358 if (@available(macOS 14.00, *)) {
360 if (
bool(info->
builtins_ & BuiltinBits::TEXTURE_ATOMIC)) {
361 options.languageVersion = MTLLanguageVersion3_1;
372 uint8_t total_stages = (is_compute) ? 1 : 2;
374 for (
int stage_count = 0; stage_count < total_stages; stage_count++) {
385 shader_library_frag_ = nil;
391 NSString *source_with_header_a = [
str stringByAppendingString:source_to_compile];
395 NSString *source_with_header = source_with_header_a;
396 [source_with_header retain];
399 NSError *
error =
nullptr;
400 id<MTLLibrary> library = [device newLibraryWithSource:source_with_header
405 if ([[
error localizedDescription] rangeOfString:
@"Compilation succeeded"].location ==
408 const char *errors_c_str = [[
error localizedDescription] UTF8String];
421 shd_builder_ =
nullptr;
431 shader_library_vert_ = library;
432 shader_library_vert_.label = [NSString stringWithUTF8String:this->
name];
436 shader_library_frag_ = library;
437 shader_library_frag_.label = [NSString stringWithUTF8String:this->
name];
441 shader_library_compute_ = library;
442 shader_library_compute_.label = [NSString stringWithUTF8String:this->
name];
450 [source_with_header autorelease];
465 pso_descriptor_ = [[MTLRenderPipelineDescriptor alloc]
init];
466 pso_descriptor_.label = [NSString stringWithUTF8String:this->
name];
474 if (push_constant_block.
size > 0) {
479 push_constant_data_ =
nullptr;
494 shd_builder_ =
nullptr;
501 tf_output_name_list_.
clear();
502 for (
int i = 0; i < name_list.
size(); i++) {
503 tf_output_name_list_.
append(std::string(name_list[i]));
505 transform_feedback_type_ = geom_type;
512 transform_feedback_active_ =
true;
513 transform_feedback_vertbuf_ = buf;
521 transform_feedback_active_ =
false;
522 transform_feedback_vertbuf_ =
nullptr;
536 "MTLShader::bind - Shader '%s' has no valid implementation in Metal, draw calls will be "
575 source_per_element_size <= dest_per_element_size,
576 "source Per-array-element size must be smaller than destination storage capacity for "
579 if (source_per_element_size < dest_per_element_size) {
580 switch (uniform.
type) {
592 bool changed =
false;
593 for (
int i = 0; i < numvecs; i++) {
594 changed = changed || (memcmp((
void *)dest_ptr, (
void *)data_c,
sizeof(
float) * 3) != 0);
596 memcpy((
void *)dest_ptr, (
void *)data_c,
sizeof(
float) * 3);
598 data_c +=
sizeof(
float) * 3;
599 dest_ptr +=
sizeof(
float) * 4;
617 bool changed =
false;
618 for (
int i = 0; i < numvecs; i++) {
619 changed = changed || (memcmp((
void *)dest_ptr, (
void *)data_c,
sizeof(
float) * 3) != 0);
621 memcpy((
void *)dest_ptr, (
void *)data_c,
sizeof(
float) * 3);
623 data_c +=
sizeof(
float) * 3;
624 dest_ptr +=
sizeof(
float) * 4;
640 "Size of provided uniform data is greater than size specified in Shader interface\n");
644 bool data_changed = (memcmp((
void *)dest_ptr, (
void *)data, copy_size) != 0);
647 memcpy((
void *)dest_ptr, (
void *)data, copy_size);
665 "Texture uniform location re-mapping unsupported in Metal. (Possibly also bad uniform "
685 const char *data_to_copy = (
char *)data;
686 uint data_size_to_copy =
sizeof(
int) * comp_len * array_size;
696 data_to_copy = (
char *)&uc;
702 data_to_copy = (
char *)&us;
707 "When uniform inputs are provided as integers, the underlying type must adhere "
708 "to alignment per-component. If this test fails, the input data cannot be directly copied "
709 "to the buffer. e.g. Array of small types uchar/bool/ushort etc; are currently not "
717 bool data_changed = (memcmp((
void *)
ptr, (
void *)data_to_copy, data_size_to_copy) != 0);
720 memcpy((
void *)
ptr, (
void *)data_to_copy, data_size_to_copy);
726 return push_constant_modified_;
731 push_constant_modified_ = is_dirty;
746 parent_mtl->pso_cache_lock_.lock();
747 for (
const auto &pso_entry : parent_mtl->pso_cache_.items()) {
750 descriptors.
append(pso_descriptor);
753 parent_mtl->pso_cache_lock_.unlock();
757 limit = (limit > 0) ? limit : descriptors.
size();
760 const MTLPrimitiveTopologyClass &prim_class = prim_classes[i];
774 vertex_function_name_ = vert_function_name;
779 fragment_function_name_ = frag_function_name;
784 compute_function_name_ = compute_function_name;
788 NSString *input_fragment_source)
821 MTLFunctionConstantValues *values,
829 switch (shader_constants.
types[i]) {
831 [values setConstantValue:&value.i type:MTLDataTypeInt atIndex:index];
834 [values setConstantValue:&value.u type:MTLDataTypeUInt atIndex:index];
837 [values setConstantValue:&value.u type:MTLDataTypeBool atIndex:index];
840 [values setConstantValue:&value.f type:MTLDataTypeFloat atIndex:index];
867 MTLContext *ctx, MTLPrimitiveTopologyClass prim_type)
890 if (color_attachment.
used) {
896 mtl_format = MTLPixelFormatRGBA8Unorm;
911 MTLPixelFormatInvalid;
913 (stencil_attachment.
used) ?
915 MTLPixelFormatInvalid;
937 bool requires_specific_topology_class = uses_gpu_layer || uses_gpu_viewport_index ||
938 prim_type == MTLPrimitiveTopologyClassPoint;
940 (requires_specific_topology_class) ? prim_type : MTLPrimitiveTopologyClassUnspecified;
953 MTLPrimitiveTopologyClass prim_type,
962 pso_cache_lock_.lock();
965 pso_cache_lock_.unlock();
967 if (pipeline_state !=
nullptr) {
968 return pipeline_state;
984 MTLFunctionConstantValues *values = [[MTLFunctionConstantValues
new] autorelease];
991 MTLRenderPipelineDescriptor *desc = pso_descriptor_;
993 pso_descriptor_.label = [NSString stringWithUTF8String:this->
name];
1009 bool using_null_buffer =
false;
1014 desc.vertexDescriptor = nil;
1015 desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassUnspecified;
1041 if (attribute_desc.
format == MTLVertexFormatInvalid) {
1044 "MTLShader: baking pipeline state for '%s'- skipping input attribute at "
1045 "index '%d' but none was specified in the current vertex state",
1050 int MTL_attribute_conversion_mode = 0;
1051 [values setConstantValue:&MTL_attribute_conversion_mode
1053 withName:[NSString stringWithFormat:
@"MTL_AttributeConvert%d", i]];
1058 [values setConstantValue:&MTL_attribute_conversion_mode
1060 withName:[NSString stringWithFormat:
@"MTL_AttributeConvert%d", i]];
1065 "TODO(Metal): Shader %s needs to support internal format conversion\n",
1072 MTLVertexAttributeDescriptor *mtl_attribute = desc.vertexDescriptor.attributes[i];
1074 mtl_attribute.format = attribute_desc.
format;
1075 mtl_attribute.offset = attribute_desc.
offset;
1076 mtl_attribute.bufferIndex = attribute_desc.
buffer_index;
1086 MTLVertexBufferLayoutDescriptor *mtl_buf_layout = desc.vertexDescriptor.layouts[i];
1089 mtl_buf_layout.stepRate = buf_layout.
step_rate;
1090 mtl_buf_layout.stride = buf_layout.
stride;
1098 int MTL_attribute_conversion_mode = 0;
1099 [values setConstantValue:&MTL_attribute_conversion_mode
1101 withName:[NSString stringWithFormat:
@"MTL_AttributeConvert%d", i]];
1109 MTLVertexAttributeDescriptor *current_attribute =
1110 desc.vertexDescriptor.attributes[attribute.location];
1112 if (current_attribute.format == MTLVertexFormatInvalid) {
1113#if MTL_DEBUG_SHADER_ATTRIBUTES == 1
1114 printf(
"-> Filling in unbound attribute '%s' for shader PSO '%s' with location: %u\n",
1117 attribute.location);
1119 current_attribute.format = attribute.format;
1120 current_attribute.offset = 0;
1121 current_attribute.bufferIndex = null_buffer_index;
1124 if (!using_null_buffer) {
1125 MTLVertexBufferLayoutDescriptor *null_buf_layout =
1126 desc.vertexDescriptor.layouts[null_buffer_index];
1130 null_buf_layout.stepFunction = MTLVertexStepFunctionConstant;
1131 null_buf_layout.stepRate = 0;
1132 null_buf_layout.stride =
max_ii(null_buf_layout.stride, attribute.size);
1137 if (null_buffer_index >= MTL_uniform_buffer_base_index) {
1138 MTL_uniform_buffer_base_index = null_buffer_index + 1;
1140 using_null_buffer =
true;
1141#if MTL_DEBUG_SHADER_ATTRIBUTES == 1
1142 MTL_LOG_INFO(
"Setting up buffer binding for null attribute with buffer index %d",
1154 [values setConstantValue:&MTL_uniform_buffer_base_index
1156 withName:
@"MTL_uniform_buffer_base_index"];
1163 int MTL_storage_buffer_base_index = MTL_uniform_buffer_base_index + 1 +
1167 [values setConstantValue:&MTL_storage_buffer_base_index
1169 withName:
@"MTL_storage_buffer_base_index"];
1173 int MTL_transform_feedback_buffer_index = -1;
1177 MTL_transform_feedback_buffer_index =
1178 MTL_uniform_buffer_base_index +
1185 [values setConstantValue:&MTL_transform_feedback_buffer_index
1187 withName:
@"MTL_transform_feedback_buffer_index"];
1195 [values setConstantValue:&MTL_clip_distances_enabled
1197 withName:
@"MTL_clip_distances_enabled"];
1199 if (MTL_clip_distances_enabled > 0) {
1204 if (plane_enabled) {
1206 setConstantValue:&plane_enabled
1208 withName:[NSString stringWithFormat:
@"MTL_clip_distance_enabled%d", plane]];
1214 bool null_pointsize =
true;
1215 float MTL_pointsize = pipeline_descriptor.
point_size;
1217 MTLPrimitiveTopologyClassPoint)
1221 if (MTL_pointsize < 0.0) {
1222 MTL_pointsize =
fabsf(MTL_pointsize);
1223 [values setConstantValue:&MTL_pointsize
1224 type:MTLDataTypeFloat
1225 withName:
@"MTL_global_pointsize"];
1226 null_pointsize =
false;
1230 if (null_pointsize) {
1231 MTL_pointsize = 0.0f;
1232 [values setConstantValue:&MTL_pointsize
1233 type:MTLDataTypeFloat
1234 withName:
@"MTL_global_pointsize"];
1238 NSError *
error =
nullptr;
1239 desc.vertexFunction = [shader_library_vert_ newFunctionWithName:vertex_function_name_
1240 constantValues:values
1244 [[
error localizedDescription] rangeOfString:
@"Compilation succeeded"].location ==
1247 const char *errors_c_str = [[
error localizedDescription] UTF8String];
1252 Span<const char *>(&sources_c_str, 1), errors_c_str,
"VertShader", has_error, &parser);
1262 desc.fragmentFunction = [shader_library_frag_ newFunctionWithName:fragment_function_name_
1263 constantValues:values
1267 [[
error localizedDescription] rangeOfString:
@"Compilation succeeded"].location ==
1270 const char *errors_c_str = [[
error localizedDescription] UTF8String];
1275 Span<const char *>(&sources_c_str, 1), errors_c_str,
"FragShader", has_error, &parser);
1284 desc.fragmentFunction = nil;
1285 desc.rasterizationEnabled =
false;
1295 MTLRenderPipelineColorAttachmentDescriptor *col_attachment =
1296 desc.colorAttachments[color_attachment];
1298 col_attachment.pixelFormat = pixel_format;
1299 if (pixel_format != MTLPixelFormatInvalid) {
1304 format_supports_blending;
1306 col_attachment.alphaBlendOperation = pipeline_descriptor.
alpha_blend_op;
1307 col_attachment.rgbBlendOperation = pipeline_descriptor.
rgb_blend_op;
1316 "[Warning] Attempting to Bake PSO, but MTLPixelFormat %d does not support "
1318 *((
int *)&pixel_format));
1331 BLI_assert_msg((MTL_uniform_buffer_base_index + get_max_ubo_index() + 2) <
1333 "UBO and SSBO bindings exceed the fragment bind table limit.");
1338 "Transform feedback buffer binding exceeds the fragment bind table limit.");
1344 "Argument buffer binding exceeds the fragment bind table limit.");
1349 MTLAutoreleasedRenderPipelineReflection reflection_data;
1350 id<MTLRenderPipelineState> pso = [ctx->
device
1351 newRenderPipelineStateWithDescriptor:desc
1352 options:MTLPipelineOptionBufferTypeInfo
1353 reflection:&reflection_data
1356 NSLog(
@"Failed to create PSO for shader: %s error %@\n", this->name,
error);
1361 NSLog(
@"Failed to create PSO for shader: %s, but no error was provided!\n", this->name);
1367 NSLog(
@"Successfully compiled PSO for shader: %s (Metal Context: %p)\n", this->name, ctx);
1373 pso_inst->
vert = desc.vertexFunction;
1374 pso_inst->
frag = desc.fragmentFunction;
1375 pso_inst->
pso = pso;
1383 if (reflection_data != nil) {
1392 NSArray<MTLArgument *> *vert_args = [reflection_data vertexArguments];
1395 int buffer_binding_max_ind = 0;
1397 for (
int i = 0; i < [vert_args
count]; i++) {
1398 MTLArgument *arg = [vert_args objectAtIndex:i];
1399 if ([arg type] == MTLArgumentTypeBuffer) {
1400 int buf_index = [arg index] - MTL_uniform_buffer_base_index;
1401 if (buf_index >= 0) {
1402 buffer_binding_max_ind =
max_ii(buffer_binding_max_ind, buf_index);
1407 for (
int i = 0; i < buffer_binding_max_ind + 1; i++) {
1411 for (
int i = 0; i < [vert_args
count]; i++) {
1412 MTLArgument *arg = [vert_args objectAtIndex:i];
1413 if ([arg type] == MTLArgumentTypeBuffer) {
1414 int buf_index = [arg index] - MTL_uniform_buffer_base_index;
1416 if (buf_index >= 0) {
1421 ([arg
isActive] == YES) ?
true :
false};
1426 NSArray<MTLArgument *> *frag_args = [reflection_data fragmentArguments];
1429 buffer_binding_max_ind = 0;
1431 for (
int i = 0; i < [frag_args
count]; i++) {
1432 MTLArgument *arg = [frag_args objectAtIndex:i];
1433 if ([arg type] == MTLArgumentTypeBuffer) {
1434 int buf_index = [arg index] - MTL_uniform_buffer_base_index;
1435 if (buf_index >= 0) {
1436 buffer_binding_max_ind =
max_ii(buffer_binding_max_ind, buf_index);
1441 for (
int i = 0; i < buffer_binding_max_ind + 1; i++) {
1445 for (
int i = 0; i < [frag_args
count]; i++) {
1446 MTLArgument *arg = [frag_args objectAtIndex:i];
1447 if ([arg type] == MTLArgumentTypeBuffer) {
1448 int buf_index = [arg index] - MTL_uniform_buffer_base_index;
1450 if (buf_index >= 0) {
1455 ([arg
isActive] == YES) ?
true :
false};
1462 pso_cache_lock_.lock();
1464 pso_cache_.add(pipeline_descriptor, pso_inst);
1465 pso_cache_lock_.unlock();
1467 "PSO CACHE: Stored new variant in PSO cache for shader '%s' Hash: '%llu'\n",
1469 pipeline_descriptor.
hash());
1485 pso_cache_lock_.lock();
1487 compute_pipeline_descriptor);
1489 pso_cache_lock_.unlock();
1491 if (pipeline_state !=
nullptr) {
1494 return pipeline_state;
1501 MTLFunctionConstantValues *values = [[MTLFunctionConstantValues
new] autorelease];
1515 int MTL_uniform_buffer_base_index = 0;
1516 [values setConstantValue:&MTL_uniform_buffer_base_index
1518 withName:
@"MTL_uniform_buffer_base_index"];
1525 int MTL_storage_buffer_base_index = MTL_uniform_buffer_base_index + 1 +
1530 [values setConstantValue:&MTL_storage_buffer_base_index
1532 withName:
@"MTL_storage_buffer_base_index"];
1535 NSError *
error =
nullptr;
1536 id<MTLFunction> compute_function = [shader_library_compute_
1537 newFunctionWithName:compute_function_name_
1538 constantValues:values
1540 compute_function.label = [NSString stringWithUTF8String:this->
name];
1543 NSLog(
@"Compile Error - Metal Shader compute function, error %@",
error);
1546 if ([[
error localizedDescription] rangeOfString:
@"Compilation succeeded"].location ==
1555 MTLComputePipelineDescriptor *desc = [[MTLComputePipelineDescriptor alloc]
init];
1556 desc.label = [NSString stringWithUTF8String:this->
name];
1557 desc.computeFunction = compute_function;
1569 if (maxTotalThreadsPerThreadgroup_Tuning_ > 0) {
1570 desc.maxTotalThreadsPerThreadgroup = this->maxTotalThreadsPerThreadgroup_Tuning_;
1571 MTL_LOG_INFO(
"Using custom parameter for shader %s value %u\n",
1573 maxTotalThreadsPerThreadgroup_Tuning_);
1577 id<MTLComputePipelineState> pso = [ctx->
device
1578 newComputePipelineStateWithDescriptor:desc
1593 if (pso.maxTotalThreadsPerThreadgroup < num_required_threads_per_threadgroup) {
1595 "Shader '%s' requires %u threads per threadgroup, but PSO limit is: %lu. Recompiling "
1596 "with increased limit on descriptor.\n",
1598 num_required_threads_per_threadgroup,
1599 (
unsigned long)pso.maxTotalThreadsPerThreadgroup);
1602 desc.maxTotalThreadsPerThreadgroup = 1024;
1603 pso = [ctx->
device newComputePipelineStateWithDescriptor:desc
1611 NSLog(
@"Failed to create PSO for compute shader: %s error %@\n", this->name,
error);
1616 NSLog(
@"Failed to create PSO for compute shader: %s, but no error was provided!\n",
1623 NSLog(
@"Successfully compiled compute PSO for shader: %s (Metal Context: %p)\n",
1633 compute_pso_instance->
compute = compute_function;
1634 compute_pso_instance->
pso = pso;
1637 pso_cache_lock_.lock();
1639 compute_pso_cache_.add(compute_pipeline_descriptor, compute_pso_instance);
1640 pso_cache_lock_.unlock();
1642 return compute_pso_instance;
1653 switch (attribute_type) {
1654 case MTLVertexFormatFloat:
1656 case MTLVertexFormatInt:
1658 case MTLVertexFormatUInt:
1660 case MTLVertexFormatShort:
1662 case MTLVertexFormatUChar:
1664 case MTLVertexFormatUChar2:
1666 case MTLVertexFormatUChar3:
1668 case MTLVertexFormatUChar4:
1670 case MTLVertexFormatFloat2:
1672 case MTLVertexFormatFloat3:
1674 case MTLVertexFormatFloat4:
1676 case MTLVertexFormatUInt2:
1678 case MTLVertexFormatUInt3:
1680 case MTLVertexFormatUInt4:
1682 case MTLVertexFormatInt2:
1684 case MTLVertexFormatInt3:
1686 case MTLVertexFormatInt4:
1688 case MTLVertexFormatUCharNormalized:
1690 case MTLVertexFormatUChar2Normalized:
1692 case MTLVertexFormatUChar3Normalized:
1694 case MTLVertexFormatUChar4Normalized:
1696 case MTLVertexFormatInt1010102Normalized:
1698 case MTLVertexFormatShort3Normalized:
1702 "Not yet supported attribute type for SSBO vertex fetch -- Add entry "
1703 "GPU_SHADER_ATTR_TYPE_** to shader defines, and in this table");
1712 ssbo_vertex_attribute_bind_active_ =
true;
1717 ssbo_vbo_slot_used_[i] =
false;
1732 "Attribute has already been bound");
1736 ShaderSSBOAttributeBinding &cached_ssbo_attribute =
1738 BLI_assert(cached_ssbo_attribute.attribute_index >= 0);
1744 this->
uniform_int(cached_ssbo_attribute.uniform_fetchmode, 1, 1, &inst_val);
1745 this->
uniform_int(cached_ssbo_attribute.uniform_vbo_id, 1, 1, &ssbo_attr.
vbo_id);
1748 ssbo_vbo_slot_used_[ssbo_attr.
vbo_id] =
true;
1752 id<MTLRenderCommandEncoder> )
1754 ssbo_vertex_attribute_bind_active_ =
false;
1757 if (ssbo_vertex_attribute_bind_mask_ != 0) {
1762 int null_attr_buffer_slot = -1;
1764 if (!ssbo_vbo_slot_used_[i]) {
1765 null_attr_buffer_slot = i;
1770 "No suitable bind location for a NULL buffer was found");
1773 if (ssbo_vertex_attribute_bind_mask_ & (1 << i)) {
1775#if MTL_DEBUG_SHADER_ATTRIBUTES == 1
1777 "SSBO Vertex Fetch missing attribute with index: %d. Shader: %s, Attr "
1779 "%s - Null buffer bound",
1782 mtl_shader_attribute->name);
1789 "Unassigned Shader attribute: %s, Attr Name: %s -- Binding NULL BUFFER to "
1793 null_attr_buffer_slot);
1812 return transform_feedback_vertbuf_;
1821 return (std::find(tf_output_name_list_.
begin(), tf_output_name_list_.
end(),
str) !=
1822 tf_output_name_list_.
end());
1870 terminate_compile_threads =
false;
1876 terminate_compile_threads =
true;
1877 cond_var.notify_all();
1879 for (
auto &
thread : compile_threads) {
1885 if (!parallel_work_queue.empty()) {
1886 std::unique_lock<std::mutex>
lock(queue_mutex);
1887 while (!parallel_work_queue.empty()) {
1888 ParallelWork *work_item = parallel_work_queue.front();
1889 work_item->is_ready =
true;
1890 parallel_work_queue.pop_front();
1898 for (
Shader *shader : shaders) {
1909 std::unique_lock<std::mutex>
lock(queue_mutex);
1912 if (!compile_threads.empty()) {
1924 id<MTLDevice> metal_device = metal_context->
device;
1926#if defined(MAC_OS_VERSION_13_3)
1928 if (@available(macOS 13.3, *)) {
1930 BLI_assert(metal_device.shouldMaximizeConcurrentCompilation);
1931 max_mtlcompiler_threads =
MIN(
int([metal_device maximumConcurrentCompilationTaskCount]),
1932 max_mtlcompiler_threads);
1938 gpuSettings.
context_type = GHOST_kDrawingContextTypeMetal;
1947 for (
int i = 0; i < max_mtlcompiler_threads; i++) {
1950 GHOST_SystemHandle
ghost_system =
reinterpret_cast<GHOST_SystemHandle
>(
1965 compile_threads.push_back(std::thread([
this, per_thread_context] {
1966 this->parallel_compilation_thread_func(per_thread_context);
1971void MTLParallelShaderCompiler::parallel_compilation_thread_func(
GPUContext *blender_gpu_context)
1984 while (!terminate_compile_threads) {
1986 ParallelWork *work_item =
nullptr;
1988 std::unique_lock<std::mutex>
lock(queue_mutex);
1990 [&] {
return terminate_compile_threads || !parallel_work_queue.empty(); });
1991 if (terminate_compile_threads || parallel_work_queue.empty()) {
1994 work_item = parallel_work_queue.front();
1995 parallel_work_queue.pop_front();
1999 if (work_item->work_type == PARALLELWORKTYPE_COMPILE_SHADER) {
2003 work_item->shader =
static_cast<MTLShader *
>(
2004 work_item->shader_compiler->compile(*shader_info,
true));
2006 if (work_item->shader) {
2013 else if (work_item->work_type == PARALLELWORKTYPE_BAKE_PSO) {
2016 BLI_assert(shader && shader->has_compute_shader_lib());
2020 work_item->specialization_values);
2022 shader->bake_compute_pipeline_state(metal_context, compute_pipeline_descriptor);
2027 work_item->is_ready =
true;
2033BatchHandle MTLParallelShaderCompiler::create_batch(
size_t batch_size)
2035 std::scoped_lock
lock(batch_mutex);
2037 batches.
add(batch_handle, {});
2042 batch.is_ready =
false;
2044 return batch_handle;
2047void MTLParallelShaderCompiler::add_item_to_batch(ParallelWork *work_item,
2050 std::scoped_lock
lock(batch_mutex);
2055void MTLParallelShaderCompiler::add_parallel_item_to_queue(ParallelWork *work_item,
2059 if (!terminate_compile_threads) {
2062 if (compile_threads.empty()) {
2066 add_item_to_batch(work_item, batch_handle);
2067 std::lock_guard<std::mutex>
lock(queue_mutex);
2068 parallel_work_queue.push_back(work_item);
2069 cond_var.notify_one();
2089 ParallelWork *work_item =
new ParallelWork;
2090 work_item->info = info;
2091 work_item->shader_compiler = shader_compiler;
2092 work_item->is_ready =
false;
2093 work_item->shader =
nullptr;
2094 work_item->work_type = PARALLELWORKTYPE_COMPILE_SHADER;
2095 add_parallel_item_to_queue(work_item, batch_handle);
2098 return batch_handle;
2103 std::scoped_lock
lock(batch_mutex);
2105 if (
batch.is_ready) {
2109 for (ParallelWork *item :
batch.items) {
2110 if (item->is_ready) {
2118 batch.is_ready =
true;
2120 return batch.is_ready;
2128 std::scoped_lock
lock(batch_mutex);
2132 for (ParallelWork *item :
batch.items) {
2133 result.
append(item->shader);
2147 for (
auto &specialization : specializations) {
2163 if (!batch_handle) {
2164 batch_handle = create_batch(1);
2167 ParallelWork *work_item =
new ParallelWork;
2168 work_item->info =
nullptr;
2169 work_item->is_ready =
false;
2170 work_item->shader = sh;
2171 work_item->work_type = PARALLELWORKTYPE_BAKE_PSO;
2176 BLI_assert_msg(input !=
nullptr,
"The specialization constant doesn't exists");
2177 work_item->specialization_values[input->location].u = constant.value.u;
2181 add_parallel_item_to_queue(work_item, batch_handle);
2183 return batch_handle;
2193 std::scoped_lock
lock(batch_mutex);
2195 if (
batch.is_ready) {
2199 for (ParallelWork *item :
batch.items) {
2200 if (item->is_ready) {
2210 batch.is_ready =
true;
2212 return batch.is_ready;
2233 if (parallel_shader_compiler) {
2235 parallel_shader_compiler =
nullptr;
2242 return parallel_shader_compiler->
batch_compile(
this, infos);
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
Platform independent time functions.
void BLI_time_sleep_ms(int ms)
#define UNUSED_VARS_NDEBUG(...)
GHOST C-API function and type declarations.
GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle, GHOST_GPUSettings gpuSettings)
static GHOST_SystemCocoa * ghost_system
bool GPU_use_parallel_compilation()
GPUContext * GPU_context_create(void *ghost_window, void *ghost_context)
void * GPU_backend_ghost_system_get()
GPUContext * GPU_context_active_get()
void GPU_context_discard(GPUContext *)
void GPU_context_active_set(GPUContext *)
int64_t SpecializationBatchHandle
struct GPUContext GPUContext
SIMD_FORCE_INLINE bool isActive() const
void reset()
clear internal cached data and reset random seed
Value pop(const Key &key)
bool add(const Key &key, const Value &value)
const Value & lookup(const Key &key) const
constexpr int64_t size() const
constexpr int64_t size() const
void append(const T &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
StateManager * state_manager
ShaderCompiler * compiler
static MTLCapabilities & get_capabilities()
MTLRenderPassState & get_render_pass_state()
MTLFrameBuffer * get_current_framebuffer()
static MTLContext * get()
id< MTLBuffer > get_null_attribute_buffer()
MTLContextGlobalShaderPipelineState pipeline_state
MTLCommandBufferManager main_command_buffer
MTLAttachment get_color_attachment(uint slot)
MTLAttachment get_stencil_attachment()
MTLAttachment get_depth_attachment()
MTLParallelShaderCompiler()
~MTLParallelShaderCompiler()
bool specialization_batch_is_ready(SpecializationBatchHandle &handle)
void decrement_ref_count()
Vector< Shader * > batch_finalize(BatchHandle &handle)
void create_compile_threads()
bool batch_is_ready(BatchHandle handle)
void increment_ref_count()
BatchHandle batch_compile(MTLShaderCompiler *shade_compiler, Span< const shader::ShaderCreateInfo * > &infos)
SpecializationBatchHandle precompile_specializations(Span< ShaderSpecialization > specializations)
void bind_vertex_buffer(id< MTLBuffer > buffer, uint64_t buffer_offset, uint index)
virtual SpecializationBatchHandle precompile_specializations(Span< ShaderSpecialization > specializations) override
void release_parallel_shader_compiler()
virtual Vector< Shader * > batch_finalize(BatchHandle &handle) override
virtual ~MTLShaderCompiler() override
virtual bool specialization_batch_is_ready(SpecializationBatchHandle &handle) override
virtual BatchHandle batch_compile(Span< const shader::ShaderCreateInfo * > &infos) override
virtual bool batch_is_ready(BatchHandle handle) override
uint32_t get_total_attributes() const
const char * get_name() const
const MTLShaderBufferBlock & get_push_constant_block() const
uint32_t get_total_textures() const
const char * get_name_at_offset(uint32_t offset) const
bool uses_argument_buffer_for_samplers() const
int get_argument_buffer_bind_index(ShaderStage stage) const
const MTLShaderInputAttribute & get_attribute(uint index) const
const MTLShaderUniform & get_uniform(uint index) const
uint32_t get_total_uniform_blocks() const
uint32_t get_total_uniforms() const
uint32_t get_max_buffer_index() const
void ssbo_vertex_fetch_bind_attributes_begin()
void set_fragment_function_name(NSString *fragment_function_name)
bool transform_feedback_enable(VertBuf *buf) override
void warm_cache(int limit) override
void ssbo_vertex_fetch_bind_attribute(const MTLSSBOAttribute &ssbo_attr)
void transform_feedback_names_set(Span< const char * > name_list, const eGPUShaderTFBType geom_type) override
MTLRenderPipelineStateInstance * bake_pipeline_state(MTLContext *ctx, MTLPrimitiveTopologyClass prim_type, const MTLRenderPipelineStateDescriptor &pipeline_descriptor)
void geometry_shader_from_glsl(MutableSpan< const char * > sources) override
MTLComputePipelineStateInstance * bake_compute_pipeline_state(MTLContext *ctx, MTLComputePipelineStateDescriptor &compute_pipeline_descriptor)
void shader_compute_source_from_msl(NSString *input_compute_source)
void uniform_int(int location, int comp_len, int array_size, const int *data) override
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
bool has_compute_shader_lib()
void transform_feedback_disable() override
void fragment_shader_from_glsl(MutableSpan< const char * > sources) override
void vertex_shader_from_glsl(MutableSpan< const char * > sources) override
static int ssbo_vertex_type_to_attr_type(MTLVertexFormat attribute_type)
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)
VertBuf * get_transform_feedback_active_buffer()
MTLShaderInterface * get_interface()
void uniform_float(int location, int comp_len, int array_size, const float *data) override
MTLRenderPipelineStateInstance * bake_current_pipeline_state(MTLContext *ctx, MTLPrimitiveTopologyClass prim_type)
void ssbo_vertex_fetch_bind_attributes_end(id< MTLRenderCommandEncoder > active_encoder)
MTLShader(MTLContext *ctx, const char *name)
bool get_push_constant_is_dirty()
void compute_shader_from_glsl(MutableSpan< const char * > sources) override
void init(const shader::ShaderCreateInfo &, bool is_batch_compilation) override
bool get_uses_ssbo_vertex_fetch() const override
void set_interface(MTLShaderInterface *interface)
void push_constant_bindstate_mark_dirty(bool is_dirty)
void set_compute_function_name(NSString *compute_function_name)
MTLRenderPipelineStateDescriptor & get_pipeline_descriptor()
const ShaderInput * constant_get(const char *name) const
ShaderInterface * interface
const char *const name_get() const
struct blender::gpu::Shader::Constants constants
void print_log(Span< const char * > sources, const char *log, const char *stage, bool error, GPULogParser *parser)
eGPUTextureFormat format_get() const
CCL_NAMESPACE_BEGIN struct Options options
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define GPU_FB_MAX_COLOR_ATTACHMENT
#define SOURCES_INDEX_VERSION
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
static void error(const char *str)
#define MTL_MAX_BUFFER_BINDINGS
#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
const char datatoc_mtl_shader_common_msl[]
uint mtl_get_data_type_alignment(eMTLDataType type)
#define GPU_SHADER_ATTR_TYPE_CHAR4
#define GPU_SHADER_ATTR_TYPE_IVEC2
#define GPU_SHADER_ATTR_TYPE_UCHAR3_NORM
#define MTL_SSBO_VERTEX_FETCH_MAX_VBOS
#define GPU_SHADER_ATTR_TYPE_UCHAR_NORM
#define GPU_SHADER_ATTR_TYPE_INT1010102_NORM
#define GPU_SHADER_ATTR_TYPE_INT
#define GPU_SHADER_ATTR_TYPE_UVEC4
#define GPU_SHADER_ATTR_TYPE_CHAR2
#define GPU_SHADER_ATTR_TYPE_SHORT3_NORM
#define GPU_SHADER_ATTR_TYPE_VEC2
#define MTL_SSBO_VERTEX_FETCH_IBO_INDEX
#define GPU_SHADER_ATTR_TYPE_CHAR3
#define GPU_SHADER_ATTR_TYPE_IVEC4
#define GPU_SHADER_ATTR_TYPE_FLOAT
#define GPU_SHADER_ATTR_TYPE_VEC3
#define GPU_SHADER_ATTR_TYPE_SHORT
#define GPU_SHADER_ATTR_TYPE_IVEC3
#define GPU_SHADER_ATTR_TYPE_UCHAR4_NORM
#define GPU_SHADER_ATTR_TYPE_UINT
#define GPU_SHADER_ATTR_TYPE_UVEC3
#define GPU_SHADER_ATTR_TYPE_UVEC2
#define GPU_SHADER_ATTR_TYPE_UCHAR2_NORM
#define GPU_SHADER_ATTR_TYPE_CHAR
#define GPU_SHADER_ATTR_TYPE_VEC4
StringRefNull gpu_shader_dependency_get_filename_from_source_string(const StringRefNull source_string)
Find the name of the file from which the given string was generated.
const char * to_string(ShaderStage stage)
static Context * unwrap(GPUContext *ctx)
MTLPixelFormat gpu_texture_format_to_metal(eGPUTextureFormat tex_format)
std::mutex g_shared_parallel_shader_compiler_mutex
MTLParallelShaderCompiler * g_shared_parallel_shader_compiler
void release_shared_parallel_shader_compiler()
bool mtl_format_supports_blending(MTLPixelFormat format)
static void populate_specialization_constant_values(MTLFunctionConstantValues *values, const Shader::Constants &shader_constants, const SpecializationStateDescriptor &specialization_descriptor)
MTLParallelShaderCompiler * get_shared_parallel_shader_compiler()
GHOST_TDrawingContextType context_type
GHOST_GPUDevice preferred_device
gpu::MTLTexture * texture
int num_performance_cores
SpecializationStateDescriptor specialization_state
id< MTLFunction > compute
id< MTLComputePipelineState > pso
int base_uniform_buffer_index
int base_storage_buffer_index
uint32_t shader_pso_index
MTLColorWriteMask color_write_mask
MTLBlendFactor src_rgb_blend_factor
MTLBlendOperation alpha_blend_op
MTLBlendFactor src_alpha_blend_factor
MTLShader * active_shader
MTLBlendFactor dest_alpha_blend_factor
MTLBlendOperation rgb_blend_op
MTLBlendFactor dest_rgb_blend_factor
bool clip_distance_enabled[6]
uchar clipping_plane_enable_mask
MTLBlendFactor dest_alpha_blend_factor
MTLBlendOperation alpha_blend_op
MTLPixelFormat color_attachment_format[GPU_FB_MAX_COLOR_ATTACHMENT]
MTLPixelFormat depth_attachment_format
MTLVertexDescriptor vertex_descriptor
int num_color_attachments
MTLColorWriteMask color_write_mask
MTLBlendFactor dest_rgb_blend_factor
MTLBlendFactor src_alpha_blend_factor
MTLBlendFactor src_rgb_blend_factor
MTLPixelFormat stencil_attachment_format
MTLBlendOperation rgb_blend_op
SpecializationStateDescriptor specialization_state
bool reflection_data_available
int transform_feedback_buffer_index
int null_attribute_buffer_index
id< MTLRenderPipelineState > pso
int base_uniform_buffer_index
int base_storage_buffer_index
blender::Vector< MTLBufferArgumentData > buffer_bindings_reflection_data_frag
uint32_t shader_pso_index
blender::Vector< MTLBufferArgumentData > buffer_bindings_reflection_data_vert
MTLPrimitiveTopologyClass prim_type
std::string glsl_compute_source_
std::string glsl_fragment_source_
NSString * msl_source_vert_
NSString * msl_source_compute_
NSString * msl_source_frag_
std::string glsl_vertex_source_
GPUVertFetchMode format_conversion_mode
MTLVertexStepFunction step_function
MTLVertexBufferLayoutDescriptorPSO buffer_layouts[GPU_BATCH_VBO_MAX_LEN+GPU_BATCH_INST_VBO_MAX_LEN]
MTLVertexAttributeDescriptorPSO attributes[GPU_VERT_ATTR_MAX_LEN]
MTLPrimitiveTopologyClass prim_topology_class
Vector< gpu::shader::Type > types
Vector< Shader::Constants::Value > values
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Vector< SubpassIn > subpass_inputs_