18#include <Metal/Metal.h>
19#include <QuartzCore/QuartzCore.h>
21#include <unordered_map>
42#define MTL_SHADER_DEBUG_EXPORT_SOURCE 0
43#define MTL_SHADER_TRANSLATION_DEBUG_OUTPUT 0
46#if MTL_SHADER_TRANSLATION_DEBUG_OUTPUT
47# define shader_debug_printf printf
49# define shader_debug_printf(...)
53#define MTL_SHADER_SPECIALIZATION_CONSTANT_BASE_ID 30
57#define MTL_SHADER_MAX_SPECIALIZED_PSOS 5
75 id<MTLRenderPipelineState>
pso;
110 int workgroup_size_y,
111 int workgroup_size_z)
113 this->threadgroup_x_len = workgroup_size_x;
114 this->threadgroup_y_len = workgroup_size_y;
115 this->threadgroup_z_len = workgroup_size_z;
135 id<MTLComputePipelineState>
pso = nil;
176 NSString *vertex_function_name_ =
@"";
177 NSString *fragment_function_name_ =
@"";
178 NSString *compute_function_name_ =
@"";
181 id<MTLLibrary> shader_library_vert_ = nil;
182 id<MTLLibrary> shader_library_frag_ = nil;
183 id<MTLLibrary> shader_library_compute_ = nil;
188 MTLRenderPipelineDescriptor *pso_descriptor_ = nil;
194 std::mutex pso_cache_lock_;
202 bool uses_gpu_layer =
false;
205 bool uses_gpu_viewport_index =
false;
214 void *push_constant_data_ =
nullptr;
215 bool push_constant_modified_ =
false;
218 uint maxTotalThreadsPerThreadgroup_Tuning_ = 0;
221 bool async_compilation_ =
false;
224 int arg_buf_samplers_vert_ = 0;
225 int arg_buf_samplers_frag_ = 0;
226 int arg_buf_samplers_comp_ = 0;
235 NSString *input_vertex_source,
236 NSString *input_fragment_source,
237 NSString *vertex_function_name_,
238 NSString *fragment_function_name_);
261 return (shader_library_compute_ != nil);
269 return current_pipeline_state_;
277 return push_constant_data_;
293 void uniform_float(
int location,
int comp_len,
int array_size,
const float *
data)
override;
294 void uniform_int(
int location,
int comp_len,
int array_size,
const int *
data)
override;
307 MTLPrimitiveTopologyClass prim_type);
310 MTLPrimitiveTopologyClass prim_type,
318 return compute_pso_common_state_;
326 MEM_CXX_CLASS_ALLOC_FUNCS(
"MTLShader");
355#define RESIZE_TYPE(_type, _suffix) \
356 case MTLVertexFormat##_type##_suffix: \
357 case MTLVertexFormat##_type##2##_suffix: \
358 case MTLVertexFormat##_type##3##_suffix: \
359 case MTLVertexFormat##_type##4##_suffix: \
360 switch (components) { \
362 return MTLVertexFormat##_type##_suffix; \
364 return MTLVertexFormat##_type##2##_suffix; \
366 return MTLVertexFormat##_type##3##_suffix; \
368 return MTLVertexFormat##_type##4##_suffix; \
372 switch (mtl_format) {
392 return MTLVertexFormatInvalid;
402 uint32_t component_len)
404#define FORMAT_PER_COMP(_type, _suffix) \
405 switch (component_len) { \
407 return MTLVertexFormat##_type##_suffix; \
409 return MTLVertexFormat##_type##2##_suffix; \
411 return MTLVertexFormat##_type##3##_suffix; \
413 return MTLVertexFormat##_type##4##_suffix; \
415 BLI_assert_msg(0, "Invalid attribute component count"); \
420#define FORMAT_PER_COMP_SMALL_INT(_type) \
421 switch (fetch_mode) { \
422 case GPU_FETCH_INT: \
423 FORMAT_PER_COMP(_type, ) \
424 case GPU_FETCH_INT_TO_FLOAT_UNIT: \
425 FORMAT_PER_COMP(_type, Normalized) \
426 case GPU_FETCH_FLOAT: \
427 BLI_assert_msg(0, "Invalid fetch mode for integer attribute"); \
432#define FORMAT_PER_COMP_INT(_type) \
433 switch (fetch_mode) { \
434 case GPU_FETCH_INT: \
435 FORMAT_PER_COMP(_type, ) \
436 case GPU_FETCH_FLOAT: \
437 BLI_assert_msg(0, "Invalid fetch mode for integer attribute"); \
439 case GPU_FETCH_INT_TO_FLOAT_UNIT: \
445 switch (component_type) {
459 switch (fetch_mode) {
469 switch (fetch_mode) {
471 return MTLVertexFormatInt1010102Normalized;
481#undef FORMAT_PER_COMP
483 return MTLVertexFormatInvalid;
488#define FORMAT_PER_TYPE(_comp, _value) \
489 case MTLVertexFormatChar##_comp: \
490 case MTLVertexFormatChar##_comp##Normalized: \
491 case MTLVertexFormatUChar##_comp: \
492 case MTLVertexFormatUChar##_comp##Normalized: \
493 case MTLVertexFormatShort##_comp: \
494 case MTLVertexFormatShort##_comp##Normalized: \
495 case MTLVertexFormatUShort##_comp: \
496 case MTLVertexFormatUShort##_comp##Normalized: \
497 case MTLVertexFormatInt##_comp: \
498 case MTLVertexFormatUInt##_comp: \
499 case MTLVertexFormatHalf##_comp: \
500 case MTLVertexFormatFloat##_comp: \
508 case MTLVertexFormatUInt1010102Normalized:
509 case MTLVertexFormatInt1010102Normalized:
510 case MTLVertexFormatUChar4Normalized_BGRA:
512#if defined(MAC_OS_VERSION_14_0)
513 case MTLVertexFormatFloatRG11B10:
515 case MTLVertexFormatFloatRGB9E5:
518 case MTLVertexFormatInvalid:
522#undef FORMAT_PER_TYPE
528#define FORMAT_PER_TYPE(_comp) \
529 case MTLVertexFormatChar##_comp##Normalized: \
530 case MTLVertexFormatUChar##_comp##Normalized: \
531 case MTLVertexFormatShort##_comp##Normalized: \
532 case MTLVertexFormatUShort##_comp##Normalized: \
544#undef FORMAT_PER_TYPE
564 uint32_t component_len,
567 MTLVertexFormat vertex_attr_format =
to_mtl(component_type, fetch_mode, component_len);
569 if (vertex_attr_format == MTLVertexFormatInvalid) {
571 return vertex_attr_format;
574 if (vertex_attr_format == shader_attr_format) {
576 return vertex_attr_format;
579 if (vertex_attr_format == MTLVertexFormatInt1010102Normalized) {
581 "Vertex format is GPU_COMP_I10 but shader input is not float");
582 return vertex_attr_format;
589 if (shader_attr_comp_type == vertex_attr_comp_type) {
591 return vertex_attr_format;
594 if (shader_attr_comp_type != MTLVertexFormatFloat) {
596 "Vertex format is GPU_COMP_F32 but shader input is not float");
599 if (shader_attr_comp_type == MTLVertexFormatFloat) {
601 "Vertex format is INT_TO_FLOAT_UNIT but shader input is not float");
605 if (shader_attr_comp_type == MTLVertexFormatInt) {
606 BLI_assert_msg(
ELEM(vertex_attr_comp_type, MTLVertexFormatChar, MTLVertexFormatShort),
607 "Vertex format is either I8 or I16 but shader input is not float");
609 if (shader_attr_comp_type == MTLVertexFormatUInt) {
610 BLI_assert_msg(
ELEM(vertex_attr_comp_type, MTLVertexFormatUChar, MTLVertexFormatUShort),
611 "Vertex format is either U8 or U16 but shader input is not float");
614 return vertex_attr_format;
619 uint32_t component_len,
621 MTLVertexFormat *r_convertedFormat)
624 shader_attr_format, component_type, component_len, fetch_mode);
625 return (*r_convertedFormat != MTLVertexFormatInvalid);
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
Read Guarded memory(de)allocation.
BMesh const char void * data
Shader * compile_shader(const shader::ShaderCreateInfo &info) override
void specialize_shader(ShaderSpecialization &specialization) override
void set_fragment_function_name(NSString *fragment_function_name)
void warm_cache(int limit) override
void geometry_shader_from_glsl(MutableSpan< StringRefNull > sources) override
MTLRenderPipelineStateInstance * bake_pipeline_state(MTLContext *ctx, MTLPrimitiveTopologyClass prim_type, const MTLRenderPipelineStateDescriptor &pipeline_descriptor)
const MTLComputePipelineStateCommon & get_compute_common_state()
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
void * get_push_constant_data()
MTLComputePipelineStateInstance * bake_compute_pipeline_state(MTLContext *ctx, MTLComputePipelineStateDescriptor &compute_pipeline_descriptor)
std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override
bool finalize_compute(const shader::ShaderCreateInfo *info)
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
void bind(const shader::SpecializationConstants *constants_state) override
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
void fragment_shader_from_glsl(MutableSpan< StringRefNull > sources) override
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override
bool has_compute_shader_lib()
std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override
void compute_shader_from_glsl(MutableSpan< StringRefNull > sources) override
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 uniform_float(int location, int comp_len, int array_size, const float *data) override
void vertex_shader_from_glsl(MutableSpan< StringRefNull > sources) override
MTLRenderPipelineStateInstance * bake_current_pipeline_state(MTLContext *ctx, MTLPrimitiveTopologyClass prim_type)
MTLShader(MTLContext *ctx, const char *name)
bool get_push_constant_is_dirty()
std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
MTLRenderPipelineStateDescriptor & get_current_pipeline_state()
void set_interface(MTLShaderInterface *interface)
void push_constant_bindstate_mark_dirty(bool is_dirty)
void set_compute_function_name(NSString *compute_function_name)
ShaderCompiler(uint32_t threads_count=1, GPUWorker::ContextType context_type=GPUWorker::ContextType::PerThread, bool support_specializations=false)
ShaderInterface * interface
#define FORMAT_PER_COMP_INT(_type)
#define RESIZE_TYPE(_type, _suffix)
#define FORMAT_PER_TYPE(_comp, _value)
#define FORMAT_PER_COMP_SMALL_INT(_type)
#define FORMAT_PER_COMP(_type, _suffix)
MTLVertexFormat format_resize_comp(MTLVertexFormat mtl_format, uint32_t components)
MTLVertexFormat format_get_component_type(MTLVertexFormat mtl_format)
bool mtl_convert_vertex_format(MTLVertexFormat shader_attr_format, GPUVertCompType component_type, uint32_t component_len, GPUVertFetchMode fetch_mode, MTLVertexFormat *r_convertedFormat)
MTLVertexFormat to_mtl(GPUVertCompType component_type, GPUVertFetchMode fetch_mode, uint32_t component_len)
MTLVertexFormat mtl_convert_vertex_format_ex(MTLVertexFormat shader_attr_format, GPUVertCompType component_type, uint32_t component_len, GPUVertFetchMode fetch_mode)
bool mtl_format_is_normalized(MTLVertexFormat format)
int mtl_format_component_len(MTLVertexFormat format)
void set_compute_workgroup_size(int workgroup_size_x, int workgroup_size_y, int workgroup_size_z)
id< MTLFunction > compute
id< MTLComputePipelineState > pso
int base_uniform_buffer_index
int base_storage_buffer_index
uint32_t shader_pso_index
bool reflection_data_available
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_
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...