Blender V5.0
device/metal/kernel.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#ifdef WITH_METAL
8
9# include "device/kernel.h"
10
11# include <Metal/Metal.h>
12
14
15class MetalDevice;
16
17enum {
18 METALRT_TABLE_DEFAULT,
19 METALRT_TABLE_SHADOW,
20 METALRT_TABLE_SHADOW_ALL,
21 METALRT_TABLE_VOLUME,
22 METALRT_TABLE_LOCAL,
23 METALRT_TABLE_LOCAL_MBLUR,
24 METALRT_TABLE_LOCAL_SINGLE_HIT,
25 METALRT_TABLE_LOCAL_SINGLE_HIT_MBLUR,
26 METALRT_TABLE_NUM
27};
28
29/* Pipeline State Object types */
30enum MetalPipelineType {
31 /* A kernel that can be used with all scenes, supporting all features.
32 * It is slow to compile, but only needs to be compiled once and is then
33 * cached for future render sessions. This allows a render to get underway
34 * on the GPU quickly.
35 */
36 PSO_GENERIC,
37
38 /* A intersection kernel that is very quick to specialize and results in faster intersection
39 * kernel performance. It uses Metal function constants to replace several KernelData variables
40 * with fixed constants.
41 */
42 PSO_SPECIALIZED_INTERSECT,
43
44 /* A shading kernel that is slow to specialize, but results in faster shading kernel performance
45 * rendered. It uses Metal function constants to replace several KernelData variables with fixed
46 * constants and short-circuit all unused SVM node case handlers.
47 */
48 PSO_SPECIALIZED_SHADE,
49
50 PSO_NUM
51};
52
53# define METALRT_FEATURE_MASK \
54 (KERNEL_FEATURE_HAIR | KERNEL_FEATURE_HAIR_THICK | KERNEL_FEATURE_POINTCLOUD)
55
56const char *kernel_type_as_string(MetalPipelineType pso_type);
57
58/* A pipeline object that can be shared between multiple instances of MetalDeviceQueue. */
59class MetalKernelPipeline {
60 public:
61 void compile();
62
63 int pipeline_id;
64 int originating_device_id;
65
66 id<MTLLibrary> mtlLibrary = nil;
67 MetalPipelineType pso_type;
68 string kernels_md5;
69 size_t usage_count = 0;
70
71 KernelData kernel_data_;
72 bool use_metalrt;
73 uint32_t kernel_features = 0;
74
75 int threads_per_threadgroup;
76
77 DeviceKernel device_kernel;
78 bool loaded = false;
79 id<MTLDevice> mtlDevice = nil;
80 id<MTLFunction> function = nil;
81 id<MTLComputePipelineState> pipeline = nil;
82 int num_threads_per_block = 0;
83
84 bool should_use_binary_archive() const;
85 id<MTLFunction> make_intersection_function(const char *function_name);
86
87 string error_str;
88
89 NSArray *table_functions[METALRT_TABLE_NUM] = {nil};
90};
91
92/* An actively instanced pipeline that can only be used by a single instance of MetalDeviceQueue.
93 */
94class MetalDispatchPipeline {
95 public:
96 ~MetalDispatchPipeline();
97
98 bool update(MetalDevice *metal_device, DeviceKernel kernel);
99 void free_intersection_function_tables();
100
101 private:
102 friend class MetalDeviceQueue;
103 friend struct ShaderCache;
104
105 int pipeline_id = -1;
106
107 MetalPipelineType pso_type;
108 id<MTLComputePipelineState> pipeline = nil;
109 int num_threads_per_block = 0;
110
111 API_AVAILABLE(macos(11.0))
112 id<MTLIntersectionFunctionTable> intersection_func_table[METALRT_TABLE_NUM] = {nil};
113};
114
115/* Cache of Metal kernels for each DeviceKernel. */
116namespace MetalDeviceKernels {
117
118int num_incomplete_specialization_requests();
119int get_loaded_kernel_count(const MetalDevice *device, MetalPipelineType pso_type);
120bool should_load_kernels(const MetalDevice *device, MetalPipelineType pso_type);
121bool load(MetalDevice *device, MetalPipelineType pso_type);
122const MetalKernelPipeline *get_best_pipeline(const MetalDevice *device, DeviceKernel kernel);
123void wait_for_all();
124bool is_benchmark_warmup();
125
126/* Deinitialize all static variables, so that no code would run on application exit. */
127void static_deinitialize();
128
129} /* namespace MetalDeviceKernels */
130
132
133#endif /* WITH_METAL */
#define CCL_NAMESPACE_END
DeviceKernel
void load(const VolumeGridData &grid)
static void update(bNodeTree *ntree)