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;
205 shd_builder_->source_from_msl_ =
false;
211 std::stringstream ss;
212 for (
int i = 0; i < sources.
size(); i++) {
213 ss << sources[i] << std::endl;
215 shd_builder_->glsl_vertex_source_ = ss.str();
220 MTL_LOG_ERROR(
"MTLShader::geometry_shader_from_glsl - Geometry shaders unsupported!");
227 shd_builder_->source_from_msl_ =
false;
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";
248 shd_builder_->glsl_fragment_source_ = ss.str();
255 shd_builder_->source_from_msl_ =
false;
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;
273 shd_builder_->glsl_compute_source_ = ss.str();
284 bool is_compute =
false;
285 if (shd_builder_->glsl_compute_source_.size() > 0) {
286 BLI_assert_msg(info !=
nullptr,
"Compute shaders must use CreateInfo.\n");
287 BLI_assert_msg(!shd_builder_->source_from_msl_,
"Compute shaders must compile from GLSL.");
293 if (!shd_builder_->source_from_msl_) {
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;
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, *)) {
361 options.languageVersion = MTLLanguageVersion3_1;
366 NSString *source_to_compile = shd_builder_->msl_source_vert_;
372 uint8_t total_stages = (is_compute) ? 1 : 2;
374 for (
int stage_count = 0; stage_count < total_stages; stage_count++) {
377 shd_builder_->msl_source_vert_ :
379 shd_builder_->msl_source_compute_ :
380 shd_builder_->msl_source_frag_);
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];
409 const char *sources_c_str = (is_compute) ? shd_builder_->glsl_compute_source_.c_str() :
410 shd_builder_->glsl_fragment_source_.c_str();
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)
791 shd_builder_->msl_source_vert_ = input_vertex_source;
792 shd_builder_->msl_source_frag_ = input_fragment_source;
793 shd_builder_->source_from_msl_ =
true;
799 shd_builder_->msl_source_compute_ = input_compute_source;
800 shd_builder_->source_from_msl_ =
true;
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",
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];
1248 const char *sources_c_str = shd_builder_->glsl_fragment_source_.c_str();
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];
1271 const char *sources_c_str = shd_builder_->glsl_fragment_source_.c_str();
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
1590 uint num_required_threads_per_threadgroup = compute_pso_common_state_.threadgroup_x_len *
1591 compute_pso_common_state_.threadgroup_y_len *
1592 compute_pso_common_state_.threadgroup_z_len;
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();
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) {
2002 const shader::ShaderCreateInfo *shader_info = work_item->info;
2003 work_item->shader =
static_cast<MTLShader *
>(
2004 work_item->shader_compiler->compile(*shader_info,
true));
2006 if (work_item->shader) {
2009 work_item->shader->warm_cache(-1);
2013 else if (work_item->work_type == PARALLELWORKTYPE_BAKE_PSO) {
2014 MTLShader *shader = work_item->shader;
2019 MTLComputePipelineStateDescriptor compute_pipeline_descriptor(
2020 work_item->specialization_values);
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, {});
2038 Batch &
batch = batches.lookup(batch_handle);
2040 batch.items.reserve(batch_size);
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);
2051 Batch &
batch = batches.lookup(batch_handle);
2052 batch.items.append(work_item);
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);
2104 Batch &
batch = batches.lookup(handle);
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);
2130 Batch
batch = batches.pop(handle);
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);
2194 Batch &
batch = batches.lookup(handle);
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);
2246 return parallel_shader_compiler->batch_is_ready(handle);
2250 return parallel_shader_compiler->batch_finalize(handle);
2255 return parallel_shader_compiler->precompile_specializations(specializations);
2260 return parallel_shader_compiler->specialization_batch_is_ready(handle);
#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
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
struct GPUContext GPUContext
SIMD_FORCE_INLINE bool isActive() const
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
void reset()
clear internal cached data and reset random seed
IndexRange index_range() const
constexpr int64_t size() const
constexpr int64_t size() const
constexpr const char * c_str() const
void append(const T &value)
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)
Vector< Shader * > batch_finalize(BatchHandle &handle)
void create_compile_threads()
bool batch_is_ready(BatchHandle handle)
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
struct @157336070235062372277311340362362342103123126032::@262166344314164341202215145112231240022370055142 batch
#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
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
shader::SpecializationConstant::Value Value
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_