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;
230 NSString *input_vertex_source,
231 NSString *input_fragment_source,
232 NSString *vertex_function_name_,
233 NSString *fragment_function_name_);
257 return (shader_library_compute_ != nil);
265 return current_pipeline_state_;
273 return push_constant_data_;
289 void uniform_float(
int location,
int comp_len,
int array_size,
const float *
data)
override;
290 void uniform_int(
int location,
int comp_len,
int array_size,
const int *
data)
override;
303 MTLPrimitiveTopologyClass prim_type);
306 MTLPrimitiveTopologyClass prim_type,
314 return compute_pso_common_state_;
322 MEM_CXX_CLASS_ALLOC_FUNCS(
"MTLShader");
351#define RESIZE_TYPE(_type, _suffix) \
352 case MTLVertexFormat##_type##_suffix: \
353 case MTLVertexFormat##_type##2##_suffix: \
354 case MTLVertexFormat##_type##3##_suffix: \
355 case MTLVertexFormat##_type##4##_suffix: \
356 switch (components) { \
358 return MTLVertexFormat##_type##_suffix; \
360 return MTLVertexFormat##_type##2##_suffix; \
362 return MTLVertexFormat##_type##3##_suffix; \
364 return MTLVertexFormat##_type##4##_suffix; \
368 switch (mtl_format) {
388 return MTLVertexFormatInvalid;
398 uint32_t component_len)
400#define FORMAT_PER_COMP(_type, _suffix) \
401 switch (component_len) { \
403 return MTLVertexFormat##_type##_suffix; \
405 return MTLVertexFormat##_type##2##_suffix; \
407 return MTLVertexFormat##_type##3##_suffix; \
409 return MTLVertexFormat##_type##4##_suffix; \
411 BLI_assert_msg(0, "Invalid attribute component count"); \
416#define FORMAT_PER_COMP_SMALL_INT(_type) \
417 switch (fetch_mode) { \
418 case GPU_FETCH_INT: \
419 FORMAT_PER_COMP(_type, ) \
420 case GPU_FETCH_INT_TO_FLOAT_UNIT: \
421 FORMAT_PER_COMP(_type, Normalized) \
422 case GPU_FETCH_FLOAT: \
423 BLI_assert_msg(0, "Invalid fetch mode for integer attribute"); \
428#define FORMAT_PER_COMP_INT(_type) \
429 switch (fetch_mode) { \
430 case GPU_FETCH_INT: \
431 FORMAT_PER_COMP(_type, ) \
432 case GPU_FETCH_FLOAT: \
433 BLI_assert_msg(0, "Invalid fetch mode for integer attribute"); \
435 case GPU_FETCH_INT_TO_FLOAT_UNIT: \
441 switch (component_type) {
455 switch (fetch_mode) {
465 switch (fetch_mode) {
467 return MTLVertexFormatInt1010102Normalized;
477#undef FORMAT_PER_COMP
479 return MTLVertexFormatInvalid;
484#define FORMAT_PER_TYPE(_comp, _value) \
485 case MTLVertexFormatChar##_comp: \
486 case MTLVertexFormatChar##_comp##Normalized: \
487 case MTLVertexFormatUChar##_comp: \
488 case MTLVertexFormatUChar##_comp##Normalized: \
489 case MTLVertexFormatShort##_comp: \
490 case MTLVertexFormatShort##_comp##Normalized: \
491 case MTLVertexFormatUShort##_comp: \
492 case MTLVertexFormatUShort##_comp##Normalized: \
493 case MTLVertexFormatInt##_comp: \
494 case MTLVertexFormatUInt##_comp: \
495 case MTLVertexFormatHalf##_comp: \
496 case MTLVertexFormatFloat##_comp: \
504 case MTLVertexFormatUInt1010102Normalized:
505 case MTLVertexFormatInt1010102Normalized:
506 case MTLVertexFormatUChar4Normalized_BGRA:
508#if defined(MAC_OS_VERSION_14_0)
509 case MTLVertexFormatFloatRG11B10:
511 case MTLVertexFormatFloatRGB9E5:
514 case MTLVertexFormatInvalid:
518#undef FORMAT_PER_TYPE
524#define FORMAT_PER_TYPE(_comp) \
525 case MTLVertexFormatChar##_comp##Normalized: \
526 case MTLVertexFormatUChar##_comp##Normalized: \
527 case MTLVertexFormatShort##_comp##Normalized: \
528 case MTLVertexFormatUShort##_comp##Normalized: \
540#undef FORMAT_PER_TYPE
560 uint32_t component_len,
563 MTLVertexFormat vertex_attr_format =
to_mtl(component_type, fetch_mode, component_len);
565 if (vertex_attr_format == MTLVertexFormatInvalid) {
567 return vertex_attr_format;
570 if (vertex_attr_format == shader_attr_format) {
572 return vertex_attr_format;
575 if (vertex_attr_format == MTLVertexFormatInt1010102Normalized) {
577 "Vertex format is GPU_COMP_I10 but shader input is not float");
578 return vertex_attr_format;
585 if (shader_attr_comp_type == vertex_attr_comp_type) {
587 return vertex_attr_format;
590 if (shader_attr_comp_type != MTLVertexFormatFloat) {
592 "Vertex format is GPU_COMP_F32 but shader input is not float");
595 if (shader_attr_comp_type == MTLVertexFormatFloat) {
597 "Vertex format is INT_TO_FLOAT_UNIT but shader input is not float");
601 if (shader_attr_comp_type == MTLVertexFormatInt) {
602 BLI_assert_msg(
ELEM(vertex_attr_comp_type, MTLVertexFormatChar, MTLVertexFormatShort),
603 "Vertex format is either I8 or I16 but shader input is not float");
605 if (shader_attr_comp_type == MTLVertexFormatUInt) {
606 BLI_assert_msg(
ELEM(vertex_attr_comp_type, MTLVertexFormatUChar, MTLVertexFormatUShort),
607 "Vertex format is either U8 or U16 but shader input is not float");
610 return vertex_attr_format;
615 uint32_t component_len,
617 MTLVertexFormat *r_convertedFormat)
620 shader_attr_format, component_type, component_len, fetch_mode);
621 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...