Add Chromium-only Blender WebEngine parity work
This commit is contained in:
183
blender-5.2.0/intern/cycles/device/oneapi/device.cpp
Normal file
183
blender-5.2.0/intern/cycles/device/oneapi/device.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/* SPDX-FileCopyrightText: 2021-2022 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "device/oneapi/device.h"
|
||||
#include "device/device.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#ifdef WITH_ONEAPI
|
||||
# include "device/oneapi/device_impl.h"
|
||||
# include "integrator/denoiser_oidn_gpu.h" // IWYU pragma: keep
|
||||
|
||||
# include "util/string.h"
|
||||
|
||||
# ifdef __linux__
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
#endif /* WITH_ONEAPI */
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
bool device_oneapi_init()
|
||||
{
|
||||
#if !defined(WITH_ONEAPI)
|
||||
return false;
|
||||
#else
|
||||
|
||||
/* NOTE(@nsirgien): we need to enable JIT cache from here and
|
||||
* right now this cache policy is controlled by env. variables. */
|
||||
/* NOTE(@xavierh-intel) we enable the use of copy engine, incl. for fill
|
||||
* operations as it lowers the overhead from zeCommandListAppendMemoryFill
|
||||
* when running paths_array kernels on Linux+A750.
|
||||
* All these env variable can be set beforehand by end-users and
|
||||
* will in that case -not- be overwritten. */
|
||||
/* By default, enable only Level-Zero and if all devices are allowed, also CUDA and HIP.
|
||||
* OpenCL backend isn't currently well supported. */
|
||||
# ifdef _WIN32
|
||||
if (getenv("SYCL_CACHE_PERSISTENT") == nullptr) {
|
||||
_putenv_s("SYCL_CACHE_PERSISTENT", "1");
|
||||
}
|
||||
if (getenv("SYCL_CACHE_THRESHOLD") == nullptr) {
|
||||
_putenv_s("SYCL_CACHE_THRESHOLD", "0");
|
||||
}
|
||||
if (getenv("ONEAPI_DEVICE_SELECTOR") == nullptr) {
|
||||
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") == nullptr) {
|
||||
_putenv_s("ONEAPI_DEVICE_SELECTOR", "level_zero:*");
|
||||
}
|
||||
else {
|
||||
_putenv_s("ONEAPI_DEVICE_SELECTOR", "!opencl:*");
|
||||
}
|
||||
}
|
||||
/* SYSMAN is needed for free_memory queries. */
|
||||
if (getenv("ZES_ENABLE_SYSMAN") == nullptr) {
|
||||
_putenv_s("ZES_ENABLE_SYSMAN", "1");
|
||||
}
|
||||
if (getenv("UR_L0_USE_COPY_ENGINE") == nullptr) {
|
||||
_putenv_s("UR_L0_USE_COPY_ENGINE", "1");
|
||||
}
|
||||
if (getenv("UR_L0_USE_COPY_ENGINE_FOR_FILL") == nullptr) {
|
||||
_putenv_s("UR_L0_USE_COPY_ENGINE_FOR_FILL", "1");
|
||||
}
|
||||
# elif __linux__
|
||||
setenv("SYCL_CACHE_PERSISTENT", "1", false);
|
||||
setenv("SYCL_CACHE_THRESHOLD", "0", false);
|
||||
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") == nullptr) {
|
||||
setenv("ONEAPI_DEVICE_SELECTOR", "level_zero:*", false);
|
||||
}
|
||||
else {
|
||||
setenv("ONEAPI_DEVICE_SELECTOR", "!opencl:*", false);
|
||||
}
|
||||
/* SYSMAN is needed for free_memory queries. */
|
||||
setenv("ZES_ENABLE_SYSMAN", "1", false);
|
||||
setenv("UR_L0_USE_COPY_ENGINE", "1", false);
|
||||
setenv("UR_L0_USE_COPY_ENGINE_FOR_FILL", "1", false);
|
||||
# endif
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
unique_ptr<Device> device_oneapi_create(const DeviceInfo &info,
|
||||
Stats &stats,
|
||||
Profiler &profiler,
|
||||
bool headless)
|
||||
{
|
||||
#ifdef WITH_ONEAPI
|
||||
return make_unique<OneapiDevice>(info, stats, profiler, headless);
|
||||
#else
|
||||
(void)info;
|
||||
(void)stats;
|
||||
(void)profiler;
|
||||
(void)headless;
|
||||
|
||||
LOG_FATAL << "Requested to create oneAPI device while not enabled for this build.";
|
||||
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_ONEAPI
|
||||
static void device_iterator_cb(const char *id,
|
||||
const char *name,
|
||||
const int num,
|
||||
bool hwrt_support,
|
||||
bool oidn_support,
|
||||
bool has_execution_optimization,
|
||||
void *user_ptr)
|
||||
{
|
||||
vector<DeviceInfo> *devices = (vector<DeviceInfo> *)user_ptr;
|
||||
|
||||
DeviceInfo info;
|
||||
|
||||
info.type = DEVICE_ONEAPI;
|
||||
info.description = name;
|
||||
info.num = num;
|
||||
|
||||
/* NOTE(@nsirgien): Should be unique at least on proper oneapi installation. */
|
||||
info.id = id;
|
||||
|
||||
info.has_nanovdb = true;
|
||||
# if defined(WITH_OPENIMAGEDENOISE)
|
||||
# if OIDN_VERSION >= 20300
|
||||
if (oidn_support) {
|
||||
# else
|
||||
if (OIDNDenoiserGPU::is_device_supported(info)) {
|
||||
# endif
|
||||
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
||||
}
|
||||
# endif
|
||||
(void)oidn_support;
|
||||
|
||||
info.has_gpu_queue = true;
|
||||
|
||||
/* NOTE(@nsirgien): oneAPI right now is focused on one device usage. In future it maybe will
|
||||
* change, but right now peer access from one device to another device is not supported. */
|
||||
info.has_peer_memory = false;
|
||||
|
||||
/* NOTE(@nsirgien): Seems not possible to know from SYCL/oneAPI or Level0. */
|
||||
info.display_device = false;
|
||||
|
||||
# ifdef WITH_EMBREE_GPU
|
||||
info.use_hardware_raytracing = hwrt_support;
|
||||
# else
|
||||
info.use_hardware_raytracing = false;
|
||||
(void)hwrt_support;
|
||||
# endif
|
||||
|
||||
info.has_execution_optimization = has_execution_optimization;
|
||||
|
||||
devices->push_back(info);
|
||||
LOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
|
||||
|
||||
if (info.denoisers & DENOISER_OPENIMAGEDENOISE) {
|
||||
LOG_INFO << "Device with id \"" << info.id << "\" supports "
|
||||
<< denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE) << ".";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void device_oneapi_info(vector<DeviceInfo> &devices)
|
||||
{
|
||||
#ifdef WITH_ONEAPI
|
||||
OneapiDevice::iterate_devices(device_iterator_cb, &devices);
|
||||
#else /* WITH_ONEAPI */
|
||||
(void)devices;
|
||||
#endif /* WITH_ONEAPI */
|
||||
}
|
||||
|
||||
string device_oneapi_capabilities()
|
||||
{
|
||||
string capabilities;
|
||||
#ifdef WITH_ONEAPI
|
||||
char *c_capabilities = OneapiDevice::device_capabilities();
|
||||
if (c_capabilities) {
|
||||
capabilities = c_capabilities;
|
||||
free(c_capabilities);
|
||||
}
|
||||
#endif
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
29
blender-5.2.0/intern/cycles/device/oneapi/device.h
Normal file
29
blender-5.2.0/intern/cycles/device/oneapi/device.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/string.h"
|
||||
#include "util/unique_ptr.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Device;
|
||||
class DeviceInfo;
|
||||
class Profiler;
|
||||
class Stats;
|
||||
|
||||
bool device_oneapi_init();
|
||||
|
||||
unique_ptr<Device> device_oneapi_create(const DeviceInfo &info,
|
||||
Stats &stats,
|
||||
Profiler &profiler,
|
||||
bool headless);
|
||||
|
||||
void device_oneapi_info(vector<DeviceInfo> &devices);
|
||||
|
||||
string device_oneapi_capabilities();
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
1856
blender-5.2.0/intern/cycles/device/oneapi/device_impl.cpp
Normal file
1856
blender-5.2.0/intern/cycles/device/oneapi/device_impl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
175
blender-5.2.0/intern/cycles/device/oneapi/device_impl.h
Normal file
175
blender-5.2.0/intern/cycles/device/oneapi/device_impl.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/* SPDX-FileCopyrightText: 2021-2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifdef WITH_ONEAPI
|
||||
# include "device/device.h"
|
||||
# include "device/oneapi/device.h"
|
||||
# include "device/oneapi/queue.h"
|
||||
# include "kernel/device/oneapi/kernel.h"
|
||||
|
||||
# include "util/map.h"
|
||||
# include "util/unique_ptr.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class DeviceQueue;
|
||||
|
||||
using OneAPIDeviceIteratorCallback =
|
||||
void (*)(const char *, const char *, const int, bool, bool, bool, void *);
|
||||
|
||||
class OneapiDevice : public GPUDevice {
|
||||
private:
|
||||
SyclQueue *device_queue_ = nullptr;
|
||||
# ifdef WITH_EMBREE_GPU
|
||||
RTCDevice embree_device = nullptr;
|
||||
# if RTC_VERSION >= 40400
|
||||
RTCTraversable embree_traversable = nullptr;
|
||||
# else
|
||||
RTCScene embree_traversable = nullptr;
|
||||
# endif
|
||||
# if RTC_VERSION >= 40302
|
||||
thread_mutex scene_data_mutex;
|
||||
vector<RTCScene> all_embree_scenes;
|
||||
# endif
|
||||
# endif
|
||||
using ConstMemMap = map<string, unique_ptr<device_vector<uchar>>>;
|
||||
ConstMemMap const_mem_map_;
|
||||
void *kg_memory_ = nullptr;
|
||||
void *kg_memory_device_ = nullptr;
|
||||
size_t kg_memory_size_ = 0;
|
||||
size_t max_memory_on_device_ = 0;
|
||||
std::string oneapi_error_string_;
|
||||
bool use_hardware_raytracing = false;
|
||||
unsigned int kernel_features = 0;
|
||||
int scene_max_shaders_ = 0;
|
||||
/* On some driver versions, usage of Intel oneAPI extension for host->GPU copy optimization
|
||||
* is causing crashes and failures. As a result, to ensure functionality, we disable
|
||||
* this extension as a workaround. This class member variable is controlling this behavior
|
||||
* and is set appropriately during device enumeration, based on the presented devices
|
||||
* and their driver version (at the moment not checked, no public driver with a fix exists yet).
|
||||
*/
|
||||
bool use_intel_copy_optimization = true;
|
||||
|
||||
size_t get_free_mem() const;
|
||||
|
||||
public:
|
||||
BVHLayoutMask get_bvh_layout_mask(const uint requested_features) const override;
|
||||
|
||||
OneapiDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless);
|
||||
|
||||
~OneapiDevice() override;
|
||||
# ifdef WITH_EMBREE_GPU
|
||||
void build_bvh(BVH *bvh, Progress &progress, bool refit) override;
|
||||
# endif
|
||||
bool check_peer_access(Device *peer_device) override;
|
||||
|
||||
bool load_kernels(const uint requested_features) override;
|
||||
|
||||
void reserve_private_memory(const uint kernel_features);
|
||||
|
||||
string oneapi_error_message();
|
||||
|
||||
int scene_max_shaders();
|
||||
|
||||
void *kernel_globals_device_pointer();
|
||||
|
||||
/* All memory types. */
|
||||
void mem_alloc(device_memory &mem) override;
|
||||
void mem_copy_to(device_memory &mem) override;
|
||||
void mem_move_to_host(device_memory &mem) override;
|
||||
void mem_copy_from(device_memory &mem,
|
||||
const size_t y,
|
||||
size_t w,
|
||||
const size_t h,
|
||||
size_t elem,
|
||||
void *host_pointer);
|
||||
void mem_copy_from(
|
||||
device_memory &mem, const size_t y, size_t w, const size_t h, size_t elem) override;
|
||||
void mem_copy_from(device_memory &mem);
|
||||
void mem_zero(device_memory &mem) override;
|
||||
void mem_free(device_memory &mem) override;
|
||||
|
||||
device_ptr mem_alloc_sub_ptr(device_memory &mem, const size_t offset, size_t /*size*/) override;
|
||||
|
||||
/* Global memory. */
|
||||
void global_alloc(device_memory &mem);
|
||||
void global_copy_to(device_memory &mem);
|
||||
void global_free(device_memory &mem);
|
||||
|
||||
/* Image memory. */
|
||||
void image_alloc(device_image &mem);
|
||||
void image_copy_to(device_image &mem);
|
||||
void image_free(device_image &mem);
|
||||
|
||||
/* Host side memory, override for more efficient copies. */
|
||||
void *host_alloc(const MemoryType type, const size_t size) override;
|
||||
void host_free(const MemoryType type, void *host_pointer, const size_t size) override;
|
||||
|
||||
/* Device side memory. */
|
||||
void get_device_memory_info(size_t &total, size_t &free) override;
|
||||
bool alloc_device(void *&device_pointer, const size_t size) override;
|
||||
void free_device(void *device_pointer) override;
|
||||
|
||||
/* Shared memory. */
|
||||
bool shared_alloc(void *&shared_pointer, const size_t size) override;
|
||||
void shared_free(void *shared_pointer) override;
|
||||
void *shared_to_device_pointer(const void *shared_pointer) override;
|
||||
|
||||
/* Memory copy. */
|
||||
void copy_host_to_device(void *device_pointer, void *host_pointer, const size_t size) override;
|
||||
void const_copy_to(const char *name, void *host, const size_t size) override;
|
||||
|
||||
/* Graphics resources interoperability. */
|
||||
bool should_use_graphics_interop(const GraphicsInteropDevice &interop_device,
|
||||
const bool log) override;
|
||||
|
||||
unique_ptr<DeviceQueue> gpu_queue_create() override;
|
||||
|
||||
/* NOTE(@nsirgien): Create this methods to avoid some compilation problems on Windows with host
|
||||
* side compilation (MSVC). */
|
||||
void *usm_aligned_alloc_host(const size_t memory_size, const size_t alignment);
|
||||
void usm_free(void *usm_ptr);
|
||||
|
||||
static void architecture_information(const SyclDevice *device, string &name, bool &is_optimized);
|
||||
static char *device_capabilities();
|
||||
static void iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_ptr);
|
||||
|
||||
size_t get_memcapacity();
|
||||
int get_num_multiprocessors();
|
||||
int get_max_num_threads_per_multiprocessor();
|
||||
bool queue_synchronize(SyclQueue *queue);
|
||||
bool kernel_globals_size(size_t &kernel_global_size);
|
||||
void set_global_memory(SyclQueue *queue,
|
||||
void *kernel_globals,
|
||||
const char *memory_name,
|
||||
void *memory_device_pointer);
|
||||
bool enqueue_kernel(KernelContext *kernel_context,
|
||||
const int kernel,
|
||||
const size_t global_size,
|
||||
const size_t local_size,
|
||||
void **args);
|
||||
void get_adjusted_global_and_local_sizes(SyclQueue *queue,
|
||||
const DeviceKernel kernel,
|
||||
size_t &kernel_global_size,
|
||||
size_t &kernel_local_size);
|
||||
SyclQueue *sycl_queue();
|
||||
|
||||
protected:
|
||||
bool can_use_hardware_raytracing_for_features(const uint requested_features) const;
|
||||
void check_usm(SyclQueue *queue, const void *usm_ptr, bool allow_host);
|
||||
bool create_queue(SyclQueue *&external_queue,
|
||||
const int device_index,
|
||||
void *embree_device,
|
||||
bool *multiple_level_zero_platforms_detected_pointer);
|
||||
void free_queue(SyclQueue *queue);
|
||||
void *usm_aligned_alloc_host(SyclQueue *queue, const size_t memory_size, const size_t alignment);
|
||||
void *usm_alloc_device(SyclQueue *queue, const size_t memory_size);
|
||||
void usm_free(SyclQueue *queue, void *usm_ptr);
|
||||
bool usm_memcpy(SyclQueue *queue, void *dest, void *src, const size_t num_bytes);
|
||||
bool usm_memset(SyclQueue *queue, void *usm_ptr, unsigned char value, const size_t num_bytes);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
168
blender-5.2.0/intern/cycles/device/oneapi/graphics_interop.cpp
Normal file
168
blender-5.2.0/intern/cycles/device/oneapi/graphics_interop.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#if defined(WITH_ONEAPI) && defined(SYCL_LINEAR_MEMORY_INTEROP_AVAILABLE)
|
||||
|
||||
# include "device/oneapi/graphics_interop.h"
|
||||
|
||||
# include "device/oneapi/device.h"
|
||||
# include "device/oneapi/device_impl.h"
|
||||
# include "device/oneapi/queue.h"
|
||||
|
||||
# include "session/display_driver.h"
|
||||
|
||||
# ifdef _WIN32
|
||||
# include "util/windows.h"
|
||||
# else
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
OneapiDeviceGraphicsInterop::OneapiDeviceGraphicsInterop(OneapiDeviceQueue *queue)
|
||||
: queue_(queue), device_(static_cast<OneapiDevice *>(queue->device))
|
||||
{
|
||||
}
|
||||
|
||||
OneapiDeviceGraphicsInterop::~OneapiDeviceGraphicsInterop()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
void OneapiDeviceGraphicsInterop::set_buffer(GraphicsInteropBuffer &interop_buffer)
|
||||
{
|
||||
if (interop_buffer.is_empty()) {
|
||||
free();
|
||||
return;
|
||||
}
|
||||
|
||||
need_zero_ |= interop_buffer.take_zero();
|
||||
|
||||
if (!interop_buffer.has_new_handle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
free();
|
||||
|
||||
if (interop_buffer.get_type() != GraphicsInteropDevice::VULKAN) {
|
||||
/* SYCL only supports interop with Vulkan and D3D. */
|
||||
LOG_ERROR
|
||||
<< "oneAPI interop set_buffer called for invalid graphics API. Only Vulkan is supported.";
|
||||
return;
|
||||
}
|
||||
|
||||
# ifdef _WIN32
|
||||
/* import_external_memory will not take ownership of the handle. */
|
||||
vulkan_windows_handle_ = reinterpret_cast<void *>(interop_buffer.take_handle());
|
||||
auto sycl_mem_handle_type =
|
||||
sycl::ext::oneapi::experimental::external_mem_handle_type::win32_nt_handle;
|
||||
sycl::ext::oneapi::experimental::external_mem_descriptor<
|
||||
sycl::ext::oneapi::experimental::resource_win32_handle>
|
||||
sycl_external_mem_descriptor{{vulkan_windows_handle_}, sycl_mem_handle_type};
|
||||
# else
|
||||
/* import_external_memory will take ownership of the file descriptor. */
|
||||
auto sycl_mem_handle_type = sycl::ext::oneapi::experimental::external_mem_handle_type::opaque_fd;
|
||||
sycl::ext::oneapi::experimental::external_mem_descriptor<
|
||||
sycl::ext::oneapi::experimental::resource_fd>
|
||||
sycl_external_mem_descriptor{{static_cast<int>(interop_buffer.take_handle())},
|
||||
sycl_mem_handle_type};
|
||||
# endif
|
||||
|
||||
sycl::queue *sycl_queue = reinterpret_cast<sycl::queue *>(device_->sycl_queue());
|
||||
try {
|
||||
sycl_external_memory_ = sycl::ext::oneapi::experimental::import_external_memory(
|
||||
sycl_external_mem_descriptor, *sycl_queue);
|
||||
}
|
||||
catch (sycl::exception &e) {
|
||||
# ifdef _WIN32
|
||||
CloseHandle(HANDLE(vulkan_windows_handle_));
|
||||
vulkan_windows_handle_ = nullptr;
|
||||
# else
|
||||
close(sycl_external_mem_descriptor.external_resource.file_descriptor);
|
||||
# endif
|
||||
LOG_ERROR << "Error importing Vulkan memory: " << e.what();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_size_ = interop_buffer.get_size();
|
||||
|
||||
/* Like the CUDA/HIP backend, we map the buffer persistently. */
|
||||
try {
|
||||
sycl_memory_ptr_ = sycl::ext::oneapi::experimental::map_external_linear_memory(
|
||||
sycl_external_memory_, 0, buffer_size_, *sycl_queue);
|
||||
}
|
||||
catch (sycl::exception &e) {
|
||||
try {
|
||||
sycl::ext::oneapi::experimental::release_external_memory(sycl_external_memory_, *sycl_queue);
|
||||
}
|
||||
catch (sycl::exception &e) {
|
||||
LOG_ERROR << "Could not release external Vulkan memory: " << e.what();
|
||||
}
|
||||
sycl_external_memory_ = {};
|
||||
buffer_size_ = 0;
|
||||
/* Only need to close Windows handle, as file descriptor is owned by compute API. */
|
||||
# ifdef _WIN32
|
||||
CloseHandle(HANDLE(vulkan_windows_handle_));
|
||||
vulkan_windows_handle_ = nullptr;
|
||||
# endif
|
||||
LOG_ERROR << "Error mapping external Vulkan memory: " << e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
device_ptr OneapiDeviceGraphicsInterop::map()
|
||||
{
|
||||
if (sycl_memory_ptr_ && need_zero_) {
|
||||
try {
|
||||
/* We do not wait on the returned event here, as CUDA also uses "cuMemsetD8Async". */
|
||||
sycl::queue *sycl_queue = reinterpret_cast<sycl::queue *>(device_->sycl_queue());
|
||||
sycl_queue->memset(sycl_memory_ptr_, 0, buffer_size_);
|
||||
}
|
||||
catch (sycl::exception &e) {
|
||||
LOG_ERROR << "Error clearing external Vulkan memory: " << e.what();
|
||||
return device_ptr(0);
|
||||
}
|
||||
need_zero_ = false;
|
||||
}
|
||||
|
||||
return reinterpret_cast<device_ptr>(sycl_memory_ptr_);
|
||||
}
|
||||
|
||||
void OneapiDeviceGraphicsInterop::unmap() {}
|
||||
|
||||
void OneapiDeviceGraphicsInterop::free()
|
||||
{
|
||||
if (sycl_external_memory_.raw_handle) {
|
||||
sycl::queue *sycl_queue = reinterpret_cast<sycl::queue *>(device_->sycl_queue());
|
||||
try {
|
||||
sycl::ext::oneapi::experimental::unmap_external_linear_memory(sycl_memory_ptr_, *sycl_queue);
|
||||
}
|
||||
catch (sycl::exception &e) {
|
||||
LOG_ERROR << "Could not unmap external Vulkan memory: " << e.what();
|
||||
}
|
||||
try {
|
||||
sycl::ext::oneapi::experimental::release_external_memory(sycl_external_memory_, *sycl_queue);
|
||||
}
|
||||
catch (sycl::exception &e) {
|
||||
LOG_ERROR << "Could not release external Vulkan memory: " << e.what();
|
||||
}
|
||||
sycl_memory_ptr_ = {};
|
||||
sycl_external_memory_ = {};
|
||||
}
|
||||
|
||||
# ifdef _WIN32
|
||||
if (vulkan_windows_handle_) {
|
||||
CloseHandle(HANDLE(vulkan_windows_handle_));
|
||||
vulkan_windows_handle_ = nullptr;
|
||||
}
|
||||
# endif
|
||||
|
||||
buffer_size_ = 0;
|
||||
|
||||
need_zero_ = false;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
61
blender-5.2.0/intern/cycles/device/oneapi/graphics_interop.h
Normal file
61
blender-5.2.0/intern/cycles/device/oneapi/graphics_interop.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#if defined(WITH_ONEAPI) && defined(SYCL_LINEAR_MEMORY_INTEROP_AVAILABLE)
|
||||
|
||||
# include <sycl/sycl.hpp>
|
||||
|
||||
# include "device/graphics_interop.h"
|
||||
# include "session/display_driver.h"
|
||||
|
||||
# include "device/oneapi/device.h"
|
||||
# include "device/oneapi/queue.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class OneapiDevice;
|
||||
class OneapiDeviceQueue;
|
||||
|
||||
class OneapiDeviceGraphicsInterop : public DeviceGraphicsInterop {
|
||||
public:
|
||||
explicit OneapiDeviceGraphicsInterop(OneapiDeviceQueue *queue);
|
||||
|
||||
OneapiDeviceGraphicsInterop(const OneapiDeviceGraphicsInterop &other) = delete;
|
||||
OneapiDeviceGraphicsInterop(OneapiDeviceGraphicsInterop &&other) noexcept = delete;
|
||||
|
||||
~OneapiDeviceGraphicsInterop() override;
|
||||
|
||||
OneapiDeviceGraphicsInterop &operator=(const OneapiDeviceGraphicsInterop &other) = delete;
|
||||
OneapiDeviceGraphicsInterop &operator=(OneapiDeviceGraphicsInterop &&other) = delete;
|
||||
|
||||
void set_buffer(GraphicsInteropBuffer &interop_buffer) override;
|
||||
|
||||
device_ptr map() override;
|
||||
void unmap() override;
|
||||
|
||||
protected:
|
||||
OneapiDeviceQueue *queue_ = nullptr;
|
||||
OneapiDevice *device_ = nullptr;
|
||||
|
||||
/* Size of the buffer in bytes. */
|
||||
size_t buffer_size_ = 0;
|
||||
|
||||
/* The destination was requested to be cleared. */
|
||||
bool need_zero_ = false;
|
||||
|
||||
/* OneAPI resources. */
|
||||
sycl::ext::oneapi::experimental::external_mem sycl_external_memory_{};
|
||||
void *sycl_memory_ptr_ = nullptr;
|
||||
|
||||
/* Vulkan handle to free. */
|
||||
# ifdef _WIN32
|
||||
void *vulkan_windows_handle_ = nullptr;
|
||||
# endif
|
||||
|
||||
void free();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
173
blender-5.2.0/intern/cycles/device/oneapi/queue.cpp
Normal file
173
blender-5.2.0/intern/cycles/device/oneapi/queue.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* SPDX-FileCopyrightText: 2021-2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifdef WITH_ONEAPI
|
||||
|
||||
# include "device/oneapi/queue.h"
|
||||
# include "device/oneapi/device_impl.h"
|
||||
# include "device/oneapi/graphics_interop.h"
|
||||
# include "util/log.h"
|
||||
|
||||
# include "kernel/device/oneapi/kernel.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
struct KernelExecutionInfo {
|
||||
double elapsed_summary = 0.0;
|
||||
int enqueue_count = 0;
|
||||
};
|
||||
|
||||
/* OneapiDeviceQueue */
|
||||
|
||||
OneapiDeviceQueue::OneapiDeviceQueue(OneapiDevice *device)
|
||||
: DeviceQueue(device), oneapi_device_(device)
|
||||
{
|
||||
}
|
||||
|
||||
int OneapiDeviceQueue::num_concurrent_states(const size_t state_size) const
|
||||
{
|
||||
int num_states = 4 * num_concurrent_busy_states(state_size);
|
||||
|
||||
LOG_TRACE << "GPU queue concurrent states: " << num_states << ", using up to "
|
||||
<< string_human_readable_size(num_states * state_size);
|
||||
|
||||
return num_states;
|
||||
}
|
||||
|
||||
int OneapiDeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const
|
||||
{
|
||||
const int max_num_threads = oneapi_device_->get_num_multiprocessors() *
|
||||
oneapi_device_->get_max_num_threads_per_multiprocessor();
|
||||
|
||||
return 4 * max(8 * max_num_threads, 65536);
|
||||
}
|
||||
|
||||
int OneapiDeviceQueue::num_sort_partitions(int max_num_paths, uint /*max_scene_shaders*/) const
|
||||
{
|
||||
int sort_partition_elements = (oneapi_device_->get_max_num_threads_per_multiprocessor() >= 128) ?
|
||||
65536 :
|
||||
8192;
|
||||
/* Sort partitioning with local sorting on Intel GPUs is currently the most effective solution no
|
||||
* matter the number of shaders. */
|
||||
return max(max_num_paths / sort_partition_elements, 1);
|
||||
}
|
||||
|
||||
void OneapiDeviceQueue::init_execution()
|
||||
{
|
||||
oneapi_device_->load_image_info(nullptr);
|
||||
|
||||
SyclQueue *device_queue = oneapi_device_->sycl_queue();
|
||||
void *kg_dptr = oneapi_device_->kernel_globals_device_pointer();
|
||||
assert(device_queue);
|
||||
assert(kg_dptr);
|
||||
kernel_context_ = make_unique<KernelContext>();
|
||||
kernel_context_->queue = device_queue;
|
||||
kernel_context_->kernel_globals = kg_dptr;
|
||||
|
||||
debug_init_execution();
|
||||
}
|
||||
|
||||
void OneapiDeviceQueue::load_image_info()
|
||||
{
|
||||
oneapi_device_->load_image_info(this);
|
||||
}
|
||||
|
||||
bool OneapiDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
const int signed_kernel_work_size,
|
||||
const DeviceKernelArguments &_args)
|
||||
{
|
||||
if (oneapi_device_->have_error()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Update image info in case memory moved to host. */
|
||||
if (oneapi_device_->load_image_info(nullptr)) {
|
||||
if (!synchronize()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void **args = const_cast<void **>(_args.values);
|
||||
|
||||
debug_enqueue_begin(kernel, signed_kernel_work_size);
|
||||
assert(signed_kernel_work_size >= 0);
|
||||
size_t kernel_global_size = (size_t)signed_kernel_work_size;
|
||||
size_t kernel_local_size;
|
||||
|
||||
assert(kernel_context_);
|
||||
kernel_context_->scene_max_shaders = oneapi_device_->scene_max_shaders();
|
||||
|
||||
oneapi_device_->get_adjusted_global_and_local_sizes(
|
||||
kernel_context_->queue, kernel, kernel_global_size, kernel_local_size);
|
||||
|
||||
/* Call the oneAPI kernel DLL to launch the requested kernel. */
|
||||
bool is_finished_ok = oneapi_device_->enqueue_kernel(
|
||||
kernel_context_.get(), kernel, kernel_global_size, kernel_local_size, args);
|
||||
|
||||
if (is_finished_ok == false) {
|
||||
oneapi_device_->set_error("oneAPI kernel \"" + std::string(device_kernel_as_string(kernel)) +
|
||||
"\" execution error: got runtime exception \"" +
|
||||
oneapi_device_->oneapi_error_message() + "\"");
|
||||
}
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return is_finished_ok;
|
||||
}
|
||||
|
||||
bool OneapiDeviceQueue::synchronize()
|
||||
{
|
||||
if (oneapi_device_->have_error()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_finished_ok = oneapi_device_->queue_synchronize(oneapi_device_->sycl_queue());
|
||||
if (is_finished_ok == false) {
|
||||
oneapi_device_->set_error("oneAPI unknown kernel execution error: got runtime exception \"" +
|
||||
oneapi_device_->oneapi_error_message() + "\"");
|
||||
}
|
||||
|
||||
debug_synchronize();
|
||||
|
||||
return !(oneapi_device_->have_error());
|
||||
}
|
||||
|
||||
void OneapiDeviceQueue::zero_to_device(device_memory &mem)
|
||||
{
|
||||
oneapi_device_->mem_zero(mem);
|
||||
}
|
||||
|
||||
void OneapiDeviceQueue::copy_to_device(device_memory &mem)
|
||||
{
|
||||
oneapi_device_->mem_copy_to(mem);
|
||||
}
|
||||
|
||||
void OneapiDeviceQueue::copy_from_device(device_memory &mem)
|
||||
{
|
||||
oneapi_device_->mem_copy_from(mem);
|
||||
}
|
||||
|
||||
void *OneapiDeviceQueue::copy_from_device_synchronized(device_memory &mem,
|
||||
vector<uint8_t> &storage)
|
||||
{
|
||||
if (mem.memory_size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
storage.resize(mem.memory_size());
|
||||
oneapi_device_->mem_copy_from(mem, 0, 0, 0, 0, storage.data());
|
||||
synchronize();
|
||||
return storage.data();
|
||||
}
|
||||
|
||||
# ifdef SYCL_LINEAR_MEMORY_INTEROP_AVAILABLE
|
||||
unique_ptr<DeviceGraphicsInterop> OneapiDeviceQueue::graphics_interop_create()
|
||||
{
|
||||
return make_unique<OneapiDeviceGraphicsInterop>(this);
|
||||
}
|
||||
# endif
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* WITH_ONEAPI */
|
||||
62
blender-5.2.0/intern/cycles/device/oneapi/queue.h
Normal file
62
blender-5.2.0/intern/cycles/device/oneapi/queue.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* SPDX-FileCopyrightText: 2021-2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_ONEAPI
|
||||
|
||||
# include "device/memory.h"
|
||||
# include "device/queue.h"
|
||||
|
||||
# include "kernel/device/oneapi/kernel.h"
|
||||
|
||||
# include "util/unique_ptr.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class OneapiDevice;
|
||||
class device_memory;
|
||||
|
||||
/* Base class for OneAPI queues. */
|
||||
class OneapiDeviceQueue : public DeviceQueue {
|
||||
public:
|
||||
explicit OneapiDeviceQueue(OneapiDevice *device);
|
||||
|
||||
int num_concurrent_states(const size_t state_size) const override;
|
||||
|
||||
int num_concurrent_busy_states(const size_t state_size) const override;
|
||||
|
||||
int num_sort_partitions(int max_num_paths, uint max_scene_shaders) const override;
|
||||
|
||||
void init_execution() override;
|
||||
void load_image_info() override;
|
||||
|
||||
bool enqueue(DeviceKernel kernel,
|
||||
const int kernel_work_size,
|
||||
const DeviceKernelArguments &args) override;
|
||||
|
||||
bool synchronize() override;
|
||||
|
||||
void zero_to_device(device_memory &mem) override;
|
||||
void copy_to_device(device_memory &mem) override;
|
||||
void copy_from_device(device_memory &mem) override;
|
||||
void *copy_from_device_synchronized(device_memory &mem, vector<uint8_t> &storage) override;
|
||||
|
||||
bool supports_local_atomic_sort() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
# ifdef SYCL_LINEAR_MEMORY_INTEROP_AVAILABLE
|
||||
unique_ptr<DeviceGraphicsInterop> graphics_interop_create() override;
|
||||
# endif
|
||||
|
||||
protected:
|
||||
OneapiDevice *oneapi_device_;
|
||||
unique_ptr<KernelContext> kernel_context_;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* WITH_ONEAPI */
|
||||
Reference in New Issue
Block a user