Files
test/source/blender/gpu/intern/gpu_platform.cc
Omar Emara 56b0b709ea Compositor: Support GPU OIDN denoising
This patch supports GPU OIDN denoising in the compositor. A new
compositor performance option was added to allow choosing between CPU,
GPU, and Auto device selection. Auto will use whatever the compositor is
using for execution.

The code is two folds, first, denoising code was adapted to use buffers
as opposed to passing in pointers to filters directly, this is needed to
support GPU devices. Second, device creation is now a bit more involved,
it tries to choose the device is being used by the compositor for
execution.

Matching GPU devices is done by choosing the OIDN device that matches
the UUID or LUID of the active GPU platform. We need both UUID and LUID
because not all platforms support both. UUID is supported on all
platforms except MacOS Metal, while LUID is only supported on Window and
MacOS metal.

If there is no active GPU device or matching is unsuccessful, we let
OIDN choose the best device, which is typically the fastest.

To support this case, UUID and LUID identifiers were added to the
GPUPlatformGlobal and are initialized by the GPU backend if supported.
OpenGL now requires GL_EXT_memory_object and GL_EXT_memory_object_win32
to support this use case, but it should function without it.

Pull Request: https://projects.blender.org/blender/blender/pulls/136660
2025-04-04 11:17:08 +02:00

203 lines
4.9 KiB
C++

/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*
* Wrap OpenGL features such as textures, shaders and GLSL
* with checks for drivers and GPU support.
*/
#include <cstdint>
#include "MEM_guardedalloc.h"
#include "BLI_dynstr.h"
#include "BLI_string.h"
#include "BLI_string_utils.hh"
#include "BLI_vector.hh"
#include "GPU_platform.hh"
#include "gpu_platform_private.hh"
/* -------------------------------------------------------------------- */
/** \name GPUPlatformGlobal
* \{ */
namespace blender::gpu {
GPUPlatformGlobal GPG;
static char *create_key(eGPUSupportLevel support_level,
const char *vendor,
const char *renderer,
const char *version)
{
DynStr *ds = BLI_dynstr_new();
BLI_dynstr_appendf(ds, "{%s/%s/%s}=", vendor, renderer, version);
if (support_level == GPU_SUPPORT_LEVEL_SUPPORTED) {
BLI_dynstr_append(ds, "SUPPORTED");
}
else if (support_level == GPU_SUPPORT_LEVEL_LIMITED) {
BLI_dynstr_append(ds, "LIMITED");
}
else {
BLI_dynstr_append(ds, "UNSUPPORTED");
}
char *support_key = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
BLI_string_replace_char(support_key, '\n', ' ');
BLI_string_replace_char(support_key, '\r', ' ');
return support_key;
}
static char *create_gpu_name(const char *vendor, const char *renderer, const char *version)
{
DynStr *ds = BLI_dynstr_new();
BLI_dynstr_appendf(ds, "%s %s %s", vendor, renderer, version);
char *gpu_name = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
BLI_string_replace_char(gpu_name, '\n', ' ');
BLI_string_replace_char(gpu_name, '\r', ' ');
return gpu_name;
}
void GPUPlatformGlobal::init(eGPUDeviceType gpu_device,
eGPUOSType os_type,
eGPUDriverType driver_type,
eGPUSupportLevel gpu_support_level,
eGPUBackendType backend,
const char *vendor_str,
const char *renderer_str,
const char *version_str,
GPUArchitectureType arch_type)
{
this->clear();
this->initialized = true;
this->device = gpu_device;
this->os = os_type;
this->driver = driver_type;
this->support_level = gpu_support_level;
const char *vendor = vendor_str ? vendor_str : "UNKNOWN";
const char *renderer = renderer_str ? renderer_str : "UNKNOWN";
const char *version = version_str ? version_str : "UNKNOWN";
this->vendor = BLI_strdup(vendor);
this->renderer = BLI_strdup(renderer);
this->version = BLI_strdup(version);
this->support_key = create_key(gpu_support_level, vendor, renderer, version);
this->gpu_name = create_gpu_name(vendor, renderer, version);
this->backend = backend;
this->architecture_type = arch_type;
}
void GPUPlatformGlobal::clear()
{
MEM_SAFE_FREE(vendor);
MEM_SAFE_FREE(renderer);
MEM_SAFE_FREE(version);
MEM_SAFE_FREE(support_key);
MEM_SAFE_FREE(gpu_name);
devices.clear_and_shrink();
device_uuid.reinitialize(0);
device_luid.reinitialize(0);
device_luid_node_mask = 0;
initialized = false;
}
} // namespace blender::gpu
/** \} */
/* -------------------------------------------------------------------- */
/** \name C-API
* \{ */
using namespace blender::gpu;
eGPUSupportLevel GPU_platform_support_level()
{
BLI_assert(GPG.initialized);
return GPG.support_level;
}
const char *GPU_platform_vendor()
{
BLI_assert(GPG.initialized);
return GPG.vendor;
}
const char *GPU_platform_renderer()
{
BLI_assert(GPG.initialized);
return GPG.renderer;
}
const char *GPU_platform_version()
{
BLI_assert(GPG.initialized);
return GPG.version;
}
const char *GPU_platform_support_level_key()
{
BLI_assert(GPG.initialized);
return GPG.support_key;
}
const char *GPU_platform_gpu_name()
{
BLI_assert(GPG.initialized);
return GPG.gpu_name;
}
GPUArchitectureType GPU_platform_architecture()
{
BLI_assert(GPG.initialized);
return GPG.architecture_type;
}
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
{
return GPU_type_matches_ex(device, os, driver, GPU_BACKEND_ANY);
}
bool GPU_type_matches_ex(eGPUDeviceType device,
eGPUOSType os,
eGPUDriverType driver,
eGPUBackendType backend)
{
BLI_assert(GPG.initialized);
return (GPG.device & device) && (GPG.os & os) && (GPG.driver & driver) &&
(GPG.backend & backend);
}
blender::Span<GPUDevice> GPU_platform_devices_list()
{
return GPG.devices.as_span();
}
blender::Span<uint8_t> GPU_platform_uuid()
{
return GPG.device_uuid.as_span();
}
blender::Span<uint8_t> GPU_platform_luid()
{
return GPG.device_luid.as_span();
}
uint32_t GPU_platform_luid_node_mask()
{
return GPG.device_luid_node_mask;
}
/** \} */