Blender V4.3
device/device.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifndef __DEVICE_H__
6#define __DEVICE_H__
7
8#include <stdlib.h>
9
10#include "bvh/params.h"
11
12#include "device/denoise.h"
13#include "device/memory.h"
14
15#include "util/function.h"
16#include "util/list.h"
17#include "util/log.h"
18#include "util/stats.h"
19#include "util/string.h"
20#include "util/texture.h"
21#include "util/thread.h"
22#include "util/types.h"
23#include "util/unique_ptr.h"
24#include "util/vector.h"
25
27
28class BVH;
29class DeviceQueue;
30class Progress;
31class CPUKernels;
33class Scene;
34
35/* Device Types */
36
49
59
60#define DEVICE_MASK(type) (DeviceTypeMask)(1 << type)
61
69
77
79 public:
82 string id; /* used for user preferences, should stay fixed with changing hardware config */
83 int num;
84 bool display_device; /* GPU is used as a display device. */
85 bool has_nanovdb; /* Support NanoVDB volumes. */
86 bool has_mnee; /* Support MNEE. */
87 bool has_osl; /* Support Open Shading Language. */
88 bool has_guiding; /* Support path guiding. */
89 bool has_profiling; /* Supports runtime collection of profiling info. */
90 bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
91 bool has_gpu_queue; /* Device supports GPU queue. */
92 bool use_hardware_raytracing; /* Use hardware instructions to accelerate ray tracing. */
93 bool use_metalrt_by_default; /* Use MetalRT by default. */
94 KernelOptimizationLevel kernel_optimization_level; /* Optimization level applied to path tracing
95 * kernels (Metal only). */
96 DenoiserTypeMask denoisers; /* Supported denoiser types. */
99 string error_msg;
100
102 {
103 type = DEVICE_CPU;
104 id = "CPU";
105 num = 0;
106 cpu_threads = 0;
107 display_device = false;
108 has_nanovdb = false;
109 has_mnee = true;
110 has_osl = false;
111 has_guiding = false;
112 has_profiling = false;
113 has_peer_memory = false;
114 has_gpu_queue = false;
118 }
119
120 bool operator==(const DeviceInfo &info) const
121 {
122 /* Multiple Devices with the same ID would be very bad. */
123 assert(id != info.id ||
124 (type == info.type && num == info.num && description == info.description));
125 return id == info.id && use_hardware_raytracing == info.use_hardware_raytracing &&
127 }
128 bool operator!=(const DeviceInfo &info) const
129 {
130 return !(*this == info);
131 }
132};
133
134/* Device */
135
136class Device {
137 friend class device_sub_ptr;
138
139 protected:
140 Device(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool headless_)
141 : info(info_), stats(stats_), profiler(profiler_), headless(headless_)
142 {
143 }
144
145 string error_msg;
146
147 virtual device_ptr mem_alloc_sub_ptr(device_memory & /*mem*/, size_t /*offset*/, size_t /*size*/)
148 {
149 /* Only required for devices that implement denoising. */
150 assert(false);
151 return (device_ptr)0;
152 }
153 virtual void mem_free_sub_ptr(device_ptr /*ptr*/){};
154
155 public:
156 /* noexcept needed to silence TBB warning. */
157 virtual ~Device() noexcept(false);
158
159 /* info */
161 virtual const string &error_message()
162 {
163 return error_msg;
164 }
166 {
167 return !error_message().empty();
168 }
169 virtual void set_error(const string &error)
170 {
171 if (!have_error()) {
173 }
174 fprintf(stderr, "%s\n", error.c_str());
175 fflush(stderr);
176 }
177 virtual BVHLayoutMask get_bvh_layout_mask(uint kernel_features) const = 0;
178
179 /* statistics */
182 bool headless = true;
183
184 /* constant memory */
185 virtual void const_copy_to(const char *name, void *host, size_t size) = 0;
186
187 /* load/compile kernels, must be called before adding tasks */
188 virtual bool load_kernels(uint /*kernel_features*/)
189 {
190 return true;
191 }
192
193 virtual bool load_osl_kernels()
194 {
195 return true;
196 }
197
198 /* Request cancellation of any long-running work. */
199 virtual void cancel() {}
200
201 /* Report status and return true if device is ready for rendering. */
202 virtual bool is_ready(string & /*status*/) const
203 {
204 return true;
205 }
206
207 /* GPU device only functions.
208 * These may not be used on CPU or multi-devices. */
209
210 /* Create new queue for executing kernels in. */
211 virtual unique_ptr<DeviceQueue> gpu_queue_create();
212
213 /* CPU device only functions.
214 * These may not be used on GPU or multi-devices. */
215
216 /* Get CPU kernel functions for native instruction set. */
217 static const CPUKernels &get_cpu_kernels();
218 /* Get kernel globals to pass to kernels. */
220 vector<CPUKernelThreadGlobals> & /*kernel_thread_globals*/);
221 /* Get OpenShadingLanguage memory buffer. */
222 virtual void *get_cpu_osl_memory();
223
224 /* Acceleration structure building. */
225 virtual void build_bvh(BVH *bvh, Progress &progress, bool refit);
226 /* Used by Metal and OptiX. */
227 virtual void release_bvh(BVH * /*bvh*/) {}
228
229 /* multi device */
230 virtual int device_number(Device * /*sub_device*/)
231 {
232 return 0;
233 }
234
235 /* Called after kernel texture setup, and prior to integrator state setup. */
236 virtual void optimize_for_scene(Scene * /*scene*/) {}
237
238 virtual bool is_resident(device_ptr /*key*/, Device *sub_device)
239 {
240 /* Memory is always resident if this is not a multi device, regardless of whether the pointer
241 * is valid or not (since it may not have been allocated yet). */
242 return sub_device == this;
243 }
244 virtual bool check_peer_access(Device * /*peer_device*/)
245 {
246 return false;
247 }
248
249 /* Graphics resources interoperability.
250 *
251 * The interoperability comes here by the meaning that the device is capable of computing result
252 * directly into an OpenGL (or other graphics library) buffer. */
253
254 /* Check display is to be updated using graphics interoperability.
255 * The interoperability can not be used is it is not supported by the device. But the device
256 * might also force disable the interoperability if it detects that it will be slower than
257 * copying pixels from the render buffer. */
259 {
260 return false;
261 }
262
263 /* Returns native buffer handle for device pointer. */
264 virtual void *get_native_buffer(device_ptr /*ptr*/)
265 {
266 return nullptr;
267 }
268
269 /* Guiding */
270
271 /* Returns path guiding device handle. */
272 virtual void *get_guiding_device() const
273 {
274 LOG(ERROR) << "Request guiding field from a device which does not support it.";
275 return nullptr;
276 }
277
278 /* Sub-devices */
279
280 /* Run given callback for every individual device which will be handling rendering.
281 * For the single device the callback is called for the device itself. For the multi-device the
282 * callback is only called for the sub-devices. */
283 virtual void foreach_device(const function<void(Device *)> &callback)
284 {
285 callback(this);
286 }
287
288 /* static */
289 static Device *create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless);
290
291 static DeviceType type_from_string(const char *name);
292 static string string_from_type(DeviceType type);
294 static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
295 static DeviceInfo dummy_device(const string &error_msg = "");
296 static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
297 static DeviceInfo get_multi_device(const vector<DeviceInfo> &subdevices,
298 int threads,
299 bool background);
300
301 /* Tag devices lists for update. */
302 static void tag_update();
303
304 static void free_memory();
305
306 protected:
307 /* Memory allocation, only accessed through device_memory. */
308 friend class MultiDevice;
309 friend class DeviceServer;
310 friend class device_memory;
311
312 virtual void mem_alloc(device_memory &mem) = 0;
313 virtual void mem_copy_to(device_memory &mem) = 0;
314 virtual void mem_copy_from(device_memory &mem, size_t y, size_t w, size_t h, size_t elem) = 0;
315 virtual void mem_zero(device_memory &mem) = 0;
316 virtual void mem_free(device_memory &mem) = 0;
317
318 private:
319 /* Indicted whether device types and devices lists were initialized. */
320 static bool need_types_update, need_devices_update;
321 static thread_mutex device_mutex;
322 static vector<DeviceInfo> cuda_devices;
323 static vector<DeviceInfo> optix_devices;
324 static vector<DeviceInfo> cpu_devices;
325 static vector<DeviceInfo> hip_devices;
326 static vector<DeviceInfo> metal_devices;
327 static vector<DeviceInfo> oneapi_devices;
328 static uint devices_initialized_mask;
329};
330
331/* Device, which is GPU, with some common functionality for GPU back-ends. */
332class GPUDevice : public Device {
333 protected:
334 GPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool headless_)
335 : Device(info_, stats_, profiler_, headless_),
336 texture_info(this, "texture_info", MEM_GLOBAL),
339 map_host_used(0),
347 {
348 }
349
350 public:
351 virtual ~GPUDevice() noexcept(false);
352
353 /* For GPUs that can use bindless textures in some way or another. */
356 /* Returns true if the texture info was copied to the device (meaning, some more
357 * re-initialization might be needed). */
358 virtual bool load_texture_info();
359
360 protected:
361 /* Memory allocation, only accessed through device_memory. */
362 friend class device_memory;
363
369 typedef unsigned long long texMemObject;
370 typedef unsigned long long arrayMemObject;
371 struct Mem {
372 Mem() : texobject(0), array(0), use_mapped_host(false) {}
373
376
377 /* If true, a mapped host memory in shared_pointer is being used. */
379 };
380 typedef map<device_memory *, Mem> MemMap;
384 /* Simple counter which will try to track amount of used device memory */
386
387 virtual void init_host_memory(size_t preferred_texture_headroom = 0,
388 size_t preferred_working_headroom = 0);
389 virtual void move_textures_to_host(size_t size, bool for_texture);
390
391 /* Allocation, deallocation and copy functions, with corresponding
392 * support of device/host allocations. */
393 virtual GPUDevice::Mem *generic_alloc(device_memory &mem, size_t pitch_padding = 0);
394 virtual void generic_free(device_memory &mem);
395 virtual void generic_copy_to(device_memory &mem);
396
397 /* total - amount of device memory, free - amount of available device memory */
398 virtual void get_device_memory_info(size_t &total, size_t &free) = 0;
399
400 virtual bool alloc_device(void *&device_pointer, size_t size) = 0;
401
402 virtual void free_device(void *device_pointer) = 0;
403
404 virtual bool alloc_host(void *&shared_pointer, size_t size) = 0;
405
406 virtual void free_host(void *shared_pointer) = 0;
407
408 /* This function should return device pointer corresponding to shared pointer, which
409 * is host buffer, allocated in `alloc_host`. The function should `true`, if such
410 * address transformation is possible and `false` otherwise. */
411 virtual void transform_host_pointer(void *&device_pointer, void *&shared_pointer) = 0;
412
413 virtual void copy_host_to_device(void *device_pointer, void *host_pointer, size_t size) = 0;
414};
415
417
418#endif /* __DEVICE_H__ */
void BLI_kdtree_nd_ free(KDTree *tree)
unsigned int uint
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
Definition bvh/bvh.h:66
KernelOptimizationLevel kernel_optimization_level
vector< DeviceInfo > multi_devices
DenoiserTypeMask denoisers
bool operator==(const DeviceInfo &info) const
bool display_device
string error_msg
bool has_peer_memory
bool has_gpu_queue
bool operator!=(const DeviceInfo &info) const
bool use_metalrt_by_default
bool has_profiling
DeviceType type
string description
bool use_hardware_raytracing
virtual void optimize_for_scene(Scene *)
virtual const string & error_message()
virtual bool is_resident(device_ptr, Device *sub_device)
virtual void release_bvh(BVH *)
static void free_memory()
static DeviceInfo dummy_device(const string &error_msg="")
Device(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool headless_)
static void tag_update()
virtual bool is_ready(string &) const
static vector< DeviceInfo > available_devices(uint device_type_mask=DEVICE_MASK_ALL)
static const CPUKernels & get_cpu_kernels()
virtual void const_copy_to(const char *name, void *host, size_t size)=0
virtual bool load_osl_kernels()
virtual void mem_zero(device_memory &mem)=0
virtual void get_cpu_kernel_thread_globals(vector< CPUKernelThreadGlobals > &)
string error_msg
virtual void * get_native_buffer(device_ptr)
virtual int device_number(Device *)
virtual ~Device() noexcept(false)
virtual void mem_copy_from(device_memory &mem, size_t y, size_t w, size_t h, size_t elem)=0
virtual void mem_free_sub_ptr(device_ptr)
virtual unique_ptr< DeviceQueue > gpu_queue_create()
Profiler & profiler
Stats & stats
virtual void build_bvh(BVH *bvh, Progress &progress, bool refit)
virtual bool load_kernels(uint)
static DeviceType type_from_string(const char *name)
virtual void * get_cpu_osl_memory()
bool headless
virtual bool check_peer_access(Device *)
virtual void mem_free(device_memory &mem)=0
virtual void foreach_device(const function< void(Device *)> &callback)
virtual BVHLayoutMask get_bvh_layout_mask(uint kernel_features) const =0
virtual void set_error(const string &error)
virtual void mem_copy_to(device_memory &mem)=0
virtual device_ptr mem_alloc_sub_ptr(device_memory &, size_t, size_t)
static string device_capabilities(uint device_type_mask=DEVICE_MASK_ALL)
friend class DeviceServer
DeviceInfo info
static vector< DeviceType > available_types()
static string string_from_type(DeviceType type)
virtual void mem_alloc(device_memory &mem)=0
static DeviceInfo get_multi_device(const vector< DeviceInfo > &subdevices, int threads, bool background)
virtual bool should_use_graphics_interop()
static Device * create(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
virtual void cancel()
virtual void * get_guiding_device() const
bool have_error()
int DenoiserTypeMask
Definition denoise.h:25
@ DENOISER_NONE
Definition denoise.h:18
DEGForeachIDComponentCallback callback
#define CCL_NAMESPACE_END
KernelOptimizationLevel
@ KERNEL_OPTIMIZATION_LEVEL_OFF
@ KERNEL_OPTIMIZATION_LEVEL_FULL
@ KERNEL_OPTIMIZATION_LEVEL_INTERSECT
@ KERNEL_OPTIMIZATION_NUM_LEVELS
DeviceTypeMask
@ DEVICE_MASK_OPTIX
@ DEVICE_MASK_CPU
@ DEVICE_MASK_HIP
@ DEVICE_MASK_ALL
@ DEVICE_MASK_CUDA
@ DEVICE_MASK_METAL
@ DEVICE_MASK_ONEAPI
MetalRTSetting
@ METALRT_OFF
@ METALRT_NUM_SETTINGS
@ METALRT_ON
@ METALRT_AUTO
DeviceType
@ DEVICE_DUMMY
@ DEVICE_NONE
@ DEVICE_METAL
@ DEVICE_MULTI
@ DEVICE_CUDA
@ DEVICE_CPU
@ DEVICE_HIPRT
@ DEVICE_OPTIX
@ DEVICE_HIP
@ DEVICE_ONEAPI
#define LOG(severity)
Definition log.h:33
static void error(const char *str)
int BVHLayoutMask
Definition params.h:51
texMemObject texobject
arrayMemObject array
unsigned long long texMemObject
bool need_texture_info
virtual GPUDevice::Mem * generic_alloc(device_memory &mem, size_t pitch_padding=0)
size_t map_host_used
GPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool headless_)
bool can_map_host
size_t device_texture_headroom
virtual void get_device_memory_info(size_t &total, size_t &free)=0
size_t device_working_headroom
virtual void init_host_memory(size_t preferred_texture_headroom=0, size_t preferred_working_headroom=0)
virtual bool alloc_host(void *&shared_pointer, size_t size)=0
map< device_memory *, Mem > MemMap
virtual void transform_host_pointer(void *&device_pointer, void *&shared_pointer)=0
virtual void copy_host_to_device(void *device_pointer, void *host_pointer, size_t size)=0
virtual void generic_copy_to(device_memory &mem)
unsigned long long arrayMemObject
virtual void free_host(void *shared_pointer)=0
virtual ~GPUDevice() noexcept(false)
virtual bool load_texture_info()
size_t map_host_limit
virtual void free_device(void *device_pointer)=0
thread_mutex device_mem_map_mutex
virtual bool alloc_device(void *&device_pointer, size_t size)=0
virtual void generic_free(device_memory &mem)
size_t device_mem_in_use
bool move_texture_to_host
device_vector< TextureInfo > texture_info
MemMap device_mem_map
virtual void move_textures_to_host(size_t size, bool for_texture)
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
Definition thread.h:29
uint64_t device_ptr
Definition util/types.h:45