Add Chromium-only Blender WebEngine parity work
This commit is contained in:
54
blender-5.2.0/intern/cycles/device/cpu/device.cpp
Normal file
54
blender-5.2.0/intern/cycles/device/cpu/device.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "device/cpu/device.h"
|
||||
#include "device/cpu/device_impl.h"
|
||||
#include "device/device.h"
|
||||
|
||||
/* Used for `info.denoisers`. */
|
||||
/* TODO(sergey): The denoisers are probably to be moved completely out of the device into their
|
||||
* own class. But until then keep API consistent with how it used to work before. */
|
||||
#include "util/guiding.h"
|
||||
#include "util/openimagedenoise.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
unique_ptr<Device> device_cpu_create(const DeviceInfo &info,
|
||||
Stats &stats,
|
||||
Profiler &profiler,
|
||||
bool headless)
|
||||
{
|
||||
return make_unique<CPUDevice>(info, stats, profiler, headless);
|
||||
}
|
||||
|
||||
void device_cpu_info(vector<DeviceInfo> &devices)
|
||||
{
|
||||
DeviceInfo info;
|
||||
|
||||
info.type = DEVICE_CPU;
|
||||
info.description = system_cpu_brand_string();
|
||||
info.id = "CPU";
|
||||
info.num = 0;
|
||||
info.has_osl = true;
|
||||
info.has_nanovdb = true;
|
||||
info.has_profiling = true;
|
||||
if (guiding_supported()) {
|
||||
info.has_guiding = true;
|
||||
}
|
||||
else {
|
||||
info.has_guiding = false;
|
||||
}
|
||||
if (openimagedenoise_supported()) {
|
||||
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
||||
}
|
||||
|
||||
devices.insert(devices.begin(), info);
|
||||
}
|
||||
|
||||
string device_cpu_capabilities()
|
||||
{
|
||||
return system_cpu_support_avx2() ? "AVX2" : "";
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
27
blender-5.2.0/intern/cycles/device/cpu/device.h
Normal file
27
blender-5.2.0/intern/cycles/device/cpu/device.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* 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;
|
||||
|
||||
unique_ptr<Device> device_cpu_create(const DeviceInfo &info,
|
||||
Stats &stats,
|
||||
Profiler &profiler,
|
||||
bool headless);
|
||||
|
||||
void device_cpu_info(vector<DeviceInfo> &devices);
|
||||
|
||||
string device_cpu_capabilities();
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
369
blender-5.2.0/intern/cycles/device/cpu/device_impl.cpp
Normal file
369
blender-5.2.0/intern/cycles/device/cpu/device_impl.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "device/cpu/device_impl.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
/* So ImathMath is included before our kernel_cpu_compat. */
|
||||
#ifdef WITH_OSL
|
||||
/* So no context pollution happens from indirectly included windows.h */
|
||||
# ifdef _WIN32
|
||||
# include "util/windows.h"
|
||||
# endif
|
||||
# include <OSL/oslexec.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
# include <embree4/rtcore.h>
|
||||
#endif
|
||||
|
||||
#include "device/cpu/kernel.h"
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "kernel/device/cpu/kernel.h"
|
||||
#include "kernel/globals.h"
|
||||
#include "kernel/types.h"
|
||||
|
||||
#include "bvh/embree.h"
|
||||
|
||||
#include "session/buffers.h"
|
||||
|
||||
#include "util/guiding.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/task.h"
|
||||
#include "util/types_image.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
CPUDevice::CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool headless_)
|
||||
: Device(info_, stats_, profiler_, headless_)
|
||||
{
|
||||
image_info = make_unique<device_vector<KernelImageInfo>>(this, "image_info", MEM_GLOBAL);
|
||||
|
||||
/* Pick any kernel, all of them are supposed to have same level of microarchitecture
|
||||
* optimization. */
|
||||
LOG_INFO << "Using " << get_cpu_kernels().integrator_init_from_camera.get_uarch_name()
|
||||
<< " CPU kernels.";
|
||||
|
||||
if (info.cpu_threads == 0) {
|
||||
info.cpu_threads = TaskScheduler::max_concurrency();
|
||||
}
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
embree_device = rtcNewDevice("verbose=0");
|
||||
#endif
|
||||
}
|
||||
|
||||
CPUDevice::~CPUDevice()
|
||||
{
|
||||
#ifdef WITH_EMBREE
|
||||
rtcReleaseDevice(embree_device);
|
||||
#endif
|
||||
|
||||
image_info->free();
|
||||
}
|
||||
|
||||
BVHLayoutMask CPUDevice::get_bvh_layout_mask(uint /*kernel_features*/) const
|
||||
{
|
||||
BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
|
||||
#ifdef WITH_EMBREE
|
||||
bvh_layout_mask |= BVH_LAYOUT_EMBREE;
|
||||
#endif /* WITH_EMBREE */
|
||||
return bvh_layout_mask;
|
||||
}
|
||||
|
||||
void CPUDevice::mem_alloc(device_memory &mem)
|
||||
{
|
||||
if (mem.type == MEM_IMAGE_TEXTURE) {
|
||||
assert(!"mem_alloc not supported for images.");
|
||||
}
|
||||
else if (mem.type == MEM_GLOBAL) {
|
||||
assert(!"mem_alloc not supported for global memory.");
|
||||
}
|
||||
else {
|
||||
LOG_DEBUG << "Buffer allocate: " << mem.log_name() << ", "
|
||||
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
||||
<< string_human_readable_size(mem.memory_size()) << ")";
|
||||
|
||||
if (mem.type == MEM_DEVICE_ONLY) {
|
||||
size_t alignment = MIN_ALIGNMENT_DEVICE_MEMORY;
|
||||
void *data = util_aligned_malloc(mem.memory_size(), alignment);
|
||||
mem.device_pointer = (device_ptr)data;
|
||||
}
|
||||
else {
|
||||
assert(!(mem.host_pointer == nullptr && mem.memory_size() > 0));
|
||||
mem.device_pointer = (device_ptr)mem.host_pointer;
|
||||
}
|
||||
|
||||
mem.device_size = mem.memory_size();
|
||||
stats.mem_alloc(mem.device_size);
|
||||
}
|
||||
}
|
||||
|
||||
void CPUDevice::mem_copy_to(device_memory &mem)
|
||||
{
|
||||
if (mem.type == MEM_GLOBAL) {
|
||||
global_free(mem);
|
||||
global_alloc(mem);
|
||||
}
|
||||
else if (mem.type == MEM_IMAGE_TEXTURE) {
|
||||
image_free((device_image &)mem);
|
||||
image_alloc((device_image &)mem);
|
||||
}
|
||||
else {
|
||||
if (!mem.device_pointer) {
|
||||
mem_alloc(mem);
|
||||
}
|
||||
|
||||
/* copy is no-op */
|
||||
}
|
||||
}
|
||||
|
||||
void CPUDevice::mem_move_to_host(device_memory & /*mem*/)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
void CPUDevice::mem_copy_from(
|
||||
device_memory & /*mem*/, size_t /*y*/, size_t /*w*/, size_t /*h*/, size_t /*elem*/)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
void CPUDevice::mem_or_from_device(device_memory & /*mem*/)
|
||||
{
|
||||
/* Nothing to do data is already in host buffer. */
|
||||
}
|
||||
|
||||
void CPUDevice::mem_zero(device_memory &mem)
|
||||
{
|
||||
if (!mem.device_pointer) {
|
||||
mem_alloc(mem);
|
||||
}
|
||||
|
||||
if (mem.device_pointer) {
|
||||
memset((void *)mem.device_pointer, 0, mem.memory_size());
|
||||
}
|
||||
}
|
||||
|
||||
void CPUDevice::mem_free(device_memory &mem)
|
||||
{
|
||||
if (mem.type == MEM_GLOBAL) {
|
||||
global_free(mem);
|
||||
}
|
||||
else if (mem.type == MEM_IMAGE_TEXTURE) {
|
||||
image_free((device_image &)mem);
|
||||
}
|
||||
else if (mem.device_pointer) {
|
||||
if (mem.type == MEM_DEVICE_ONLY) {
|
||||
util_aligned_free((void *)mem.device_pointer, mem.memory_size());
|
||||
}
|
||||
mem.device_pointer = 0;
|
||||
stats.mem_free(mem.device_size);
|
||||
mem.device_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
device_ptr CPUDevice::mem_alloc_sub_ptr(device_memory &mem, const size_t offset, size_t /*size*/)
|
||||
{
|
||||
return (device_ptr)(((char *)mem.device_pointer) + mem.memory_elements_size(offset));
|
||||
}
|
||||
|
||||
void CPUDevice::const_copy_to(const char *name, void *host, const size_t size)
|
||||
{
|
||||
#ifdef WITH_EMBREE
|
||||
if (strcmp(name, "data") == 0) {
|
||||
assert(size <= sizeof(KernelData));
|
||||
|
||||
/* Update scene handle (since it is different for each device on multi devices).
|
||||
* This must be a raw pointer copy since at some points during scene update this
|
||||
* pointer may be invalid. */
|
||||
KernelData *const data = (KernelData *)host;
|
||||
data->device_bvh = embree_traversable;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update both the main one, and the per-thread globals in case of updates during
|
||||
* render from e.g. the texture cache. */
|
||||
kernel_const_copy(&kernel_globals, name, host, size);
|
||||
for (ThreadKernelGlobalsCPU &kg : kernel_thread_globals_) {
|
||||
kernel_const_copy(&kg, name, host, size);
|
||||
}
|
||||
}
|
||||
|
||||
void CPUDevice::global_alloc(device_memory &mem)
|
||||
{
|
||||
LOG_DEBUG << "Global memory allocate: " << mem.log_name() << ", "
|
||||
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
||||
<< string_human_readable_size(mem.memory_size()) << ")";
|
||||
|
||||
/* Update both the main one, and the per-thread globals in case of updates during
|
||||
* render from e.g. the texture cache. */
|
||||
kernel_global_memory_copy(&kernel_globals, mem.global_name(), mem.host_pointer, mem.data_size);
|
||||
for (ThreadKernelGlobalsCPU &kg : kernel_thread_globals_) {
|
||||
kernel_global_memory_copy(&kg, mem.global_name(), mem.host_pointer, mem.data_size);
|
||||
}
|
||||
|
||||
mem.device_pointer = (device_ptr)mem.host_pointer;
|
||||
mem.device_size = mem.memory_size();
|
||||
stats.mem_alloc(mem.device_size);
|
||||
}
|
||||
|
||||
void CPUDevice::global_free(device_memory &mem)
|
||||
{
|
||||
if (mem.device_pointer) {
|
||||
mem.device_pointer = 0;
|
||||
stats.mem_free(mem.device_size);
|
||||
mem.device_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CPUDevice::image_alloc(device_image &mem)
|
||||
{
|
||||
LOG_DEBUG << "Texture allocate: " << mem.log_name() << ", "
|
||||
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
|
||||
<< string_human_readable_size(mem.memory_size()) << ")";
|
||||
|
||||
mem.device_pointer = (device_ptr)mem.host_pointer;
|
||||
mem.device_size = mem.memory_size();
|
||||
stats.mem_alloc(mem.device_size);
|
||||
|
||||
const uint image_info_id = mem.image_info_id;
|
||||
if (image_info_id >= image_info->size()) {
|
||||
/* Geometric growth to amortize reallocation cost. */
|
||||
const size_t new_size = max(size_t(image_info_id) + 128, image_info->size() * 2);
|
||||
|
||||
unique_ptr<device_vector<KernelImageInfo>> new_info =
|
||||
make_unique<device_vector<KernelImageInfo>>(this, "image_info", MEM_GLOBAL);
|
||||
new_info->resize(new_size);
|
||||
|
||||
if (image_info->size() > 0) {
|
||||
std::copy_n(image_info->data(), image_info->size(), new_info->data());
|
||||
}
|
||||
|
||||
/* Move old vector to backup list to keep memory alive for concurrent access. */
|
||||
old_image_infos.push_back(std::move(image_info));
|
||||
image_info = std::move(new_info);
|
||||
|
||||
/* Update kernel globals pointers immediately. */
|
||||
image_info->copy_to_device();
|
||||
}
|
||||
|
||||
(*image_info)[image_info_id] = mem.info;
|
||||
(*image_info)[image_info_id].data = (uint64_t)mem.host_pointer;
|
||||
}
|
||||
|
||||
void CPUDevice::image_free(device_image &mem)
|
||||
{
|
||||
if (mem.device_pointer) {
|
||||
mem.device_pointer = 0;
|
||||
stats.mem_free(mem.device_size);
|
||||
mem.device_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPUDevice::has_unified_memory() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPUDevice::has_unified_image_memory() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPUDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
|
||||
{
|
||||
#ifdef WITH_EMBREE
|
||||
if (bvh->params.bvh_layout == BVH_LAYOUT_EMBREE ||
|
||||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE ||
|
||||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_METAL_EMBREE ||
|
||||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_HIPRT_EMBREE ||
|
||||
bvh->params.bvh_layout == BVH_LAYOUT_MULTI_EMBREEGPU_EMBREE)
|
||||
{
|
||||
BVHEmbree *const bvh_embree = static_cast<BVHEmbree *>(bvh);
|
||||
if (refit) {
|
||||
bvh_embree->refit(progress);
|
||||
}
|
||||
else {
|
||||
bvh_embree->build(progress, &stats, embree_device);
|
||||
}
|
||||
|
||||
if (bvh->params.top_level) {
|
||||
# if RTC_VERSION >= 40400
|
||||
embree_traversable = rtcGetSceneTraversable(bvh_embree->scene);
|
||||
# else
|
||||
embree_traversable = bvh_embree->scene;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Device::build_bvh(bvh, progress, refit);
|
||||
}
|
||||
}
|
||||
|
||||
void *CPUDevice::get_guiding_device() const
|
||||
{
|
||||
#if defined(WITH_PATH_GUIDING)
|
||||
if (!guiding_device) {
|
||||
if (guiding_device_type() == 8) {
|
||||
guiding_device = make_unique<openpgl::cpp::Device>(PGL_DEVICE_TYPE_CPU_8);
|
||||
}
|
||||
else if (guiding_device_type() == 4) {
|
||||
guiding_device = make_unique<openpgl::cpp::Device>(PGL_DEVICE_TYPE_CPU_4);
|
||||
}
|
||||
}
|
||||
return guiding_device.get();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
vector<ThreadKernelGlobalsCPU> *CPUDevice::acquire_cpu_kernel_thread_globals()
|
||||
{
|
||||
assert(kernel_thread_globals_.empty());
|
||||
|
||||
kernel_thread_globals_.clear();
|
||||
OSLGlobals *osl_globals = get_cpu_osl_memory();
|
||||
for (int i = 0; i < info.cpu_threads; i++) {
|
||||
kernel_thread_globals_.emplace_back(kernel_globals, osl_globals, profiler, i);
|
||||
}
|
||||
|
||||
return &kernel_thread_globals_;
|
||||
}
|
||||
|
||||
void CPUDevice::release_cpu_kernel_thread_globals()
|
||||
{
|
||||
kernel_thread_globals_.clear();
|
||||
old_image_infos.clear();
|
||||
}
|
||||
|
||||
OSLGlobals *CPUDevice::get_cpu_osl_memory()
|
||||
{
|
||||
#ifdef WITH_OSL
|
||||
return &osl_globals;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPUDevice::set_image_cache_func(KernelImageLoadRequestedCPU image_load_requested_cpu,
|
||||
KernelImageLoadRequestedGPU /*image_load_requested_gpu*/)
|
||||
{
|
||||
kernel_globals.image_load_requested_cpu = image_load_requested_cpu;
|
||||
}
|
||||
|
||||
bool CPUDevice::load_kernels(const uint /*kernel_features*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
101
blender-5.2.0/intern/cycles/device/cpu/device_impl.h
Normal file
101
blender-5.2.0/intern/cycles/device/cpu/device_impl.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* So ImathMath is included before our kernel_cpu_compat. */
|
||||
#ifdef WITH_OSL
|
||||
# include <cstdint> /* Needed before `sdlexec.h` for `int32_t` with GCC 15.1. */
|
||||
/* So no context pollution happens from indirectly included windows.h */
|
||||
# ifdef _WIN32
|
||||
# include "util/windows.h"
|
||||
# endif
|
||||
# include <OSL/oslexec.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
# include <embree4/rtcore.h>
|
||||
#endif
|
||||
|
||||
#include "device/cpu/kernel.h"
|
||||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/cpu/kernel.h"
|
||||
#include "kernel/globals.h"
|
||||
|
||||
#include "kernel/osl/globals.h"
|
||||
// clang-format on
|
||||
|
||||
#include "util/guiding.h" // IWYU pragma: keep
|
||||
#include "util/list.h"
|
||||
#include "util/unique_ptr.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class CPUDevice : public Device {
|
||||
public:
|
||||
KernelGlobalsCPU kernel_globals;
|
||||
vector<ThreadKernelGlobalsCPU> kernel_thread_globals_;
|
||||
|
||||
unique_ptr<device_vector<KernelImageInfo>> image_info;
|
||||
list<unique_ptr<device_vector<KernelImageInfo>>> old_image_infos;
|
||||
|
||||
#ifdef WITH_OSL
|
||||
OSLGlobals osl_globals;
|
||||
#endif
|
||||
#ifdef WITH_EMBREE
|
||||
# if RTC_VERSION >= 40400
|
||||
RTCTraversable embree_traversable = nullptr;
|
||||
# else
|
||||
RTCScene embree_traversable = nullptr;
|
||||
# endif
|
||||
RTCDevice embree_device;
|
||||
#endif
|
||||
#if defined(WITH_PATH_GUIDING)
|
||||
mutable unique_ptr<openpgl::cpp::Device> guiding_device;
|
||||
#endif
|
||||
|
||||
CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool headless_);
|
||||
~CPUDevice() override;
|
||||
|
||||
BVHLayoutMask get_bvh_layout_mask(uint /*kernel_features*/) const override;
|
||||
|
||||
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) override;
|
||||
void mem_zero(device_memory &mem) override;
|
||||
void mem_free(device_memory &mem) override;
|
||||
void mem_or_from_device(device_memory &mem) override;
|
||||
device_ptr mem_alloc_sub_ptr(device_memory &mem, const size_t offset, size_t /*size*/) override;
|
||||
|
||||
void const_copy_to(const char *name, void *host, const size_t size) override;
|
||||
|
||||
void global_alloc(device_memory &mem);
|
||||
void global_free(device_memory &mem);
|
||||
|
||||
void image_alloc(device_image &mem);
|
||||
void image_free(device_image &mem);
|
||||
|
||||
bool has_unified_memory() const override;
|
||||
bool has_unified_image_memory() const override;
|
||||
|
||||
void build_bvh(BVH *bvh, Progress &progress, bool refit) override;
|
||||
|
||||
void *get_guiding_device() const override;
|
||||
|
||||
vector<ThreadKernelGlobalsCPU> *acquire_cpu_kernel_thread_globals() override;
|
||||
void release_cpu_kernel_thread_globals() override;
|
||||
OSLGlobals *get_cpu_osl_memory() override;
|
||||
void set_image_cache_func(KernelImageLoadRequestedCPU image_load_requested_cpu,
|
||||
KernelImageLoadRequestedGPU image_load_requested_gpu) override;
|
||||
|
||||
protected:
|
||||
bool load_kernels(uint /*kernel_features*/) override;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
59
blender-5.2.0/intern/cycles/device/cpu/kernel.cpp
Normal file
59
blender-5.2.0/intern/cycles/device/cpu/kernel.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "device/cpu/kernel.h"
|
||||
|
||||
#include "kernel/device/cpu/kernel.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#define KERNEL_FUNCTIONS(name) KERNEL_NAME_EVAL(cpu, name), KERNEL_NAME_EVAL(cpu_avx2, name)
|
||||
|
||||
#define REGISTER_KERNEL(name) name(KERNEL_FUNCTIONS(name))
|
||||
#define REGISTER_KERNEL_FILM_CONVERT(name) \
|
||||
film_convert_##name(KERNEL_FUNCTIONS(film_convert_##name)), \
|
||||
film_convert_half_rgba_##name(KERNEL_FUNCTIONS(film_convert_half_rgba_##name))
|
||||
|
||||
CPUKernels::CPUKernels()
|
||||
: /* Integrator. */
|
||||
REGISTER_KERNEL(integrator_init_from_camera),
|
||||
REGISTER_KERNEL(integrator_init_from_bake),
|
||||
REGISTER_KERNEL(integrator_megakernel),
|
||||
/* Shader evaluation. */
|
||||
REGISTER_KERNEL(shader_eval_displace),
|
||||
REGISTER_KERNEL(shader_eval_background),
|
||||
REGISTER_KERNEL(shader_eval_curve_shadow_transparency),
|
||||
REGISTER_KERNEL(shader_eval_volume_density),
|
||||
/* Adaptive sampling. */
|
||||
REGISTER_KERNEL(adaptive_sampling_convergence_check),
|
||||
REGISTER_KERNEL(adaptive_sampling_filter_x),
|
||||
REGISTER_KERNEL(adaptive_sampling_filter_y),
|
||||
/* Volume Scattering Probability Guiding. */
|
||||
REGISTER_KERNEL(volume_guiding_filter_x),
|
||||
REGISTER_KERNEL(volume_guiding_filter_y),
|
||||
/* Cryptomatte. */
|
||||
REGISTER_KERNEL(cryptomatte_postprocess),
|
||||
/* Film Convert. */
|
||||
REGISTER_KERNEL_FILM_CONVERT(depth),
|
||||
REGISTER_KERNEL_FILM_CONVERT(mist),
|
||||
REGISTER_KERNEL_FILM_CONVERT(volume_majorant),
|
||||
REGISTER_KERNEL_FILM_CONVERT(sample_count),
|
||||
REGISTER_KERNEL_FILM_CONVERT(float),
|
||||
REGISTER_KERNEL_FILM_CONVERT(light_path),
|
||||
REGISTER_KERNEL_FILM_CONVERT(rgbe),
|
||||
REGISTER_KERNEL_FILM_CONVERT(float3),
|
||||
REGISTER_KERNEL_FILM_CONVERT(motion),
|
||||
REGISTER_KERNEL_FILM_CONVERT(cryptomatte),
|
||||
REGISTER_KERNEL_FILM_CONVERT(shadow_catcher),
|
||||
REGISTER_KERNEL_FILM_CONVERT(shadow_catcher_matte_with_shadow),
|
||||
REGISTER_KERNEL_FILM_CONVERT(combined),
|
||||
REGISTER_KERNEL_FILM_CONVERT(float4)
|
||||
{
|
||||
}
|
||||
|
||||
#undef REGISTER_KERNEL
|
||||
#undef REGISTER_KERNEL_FILM_CONVERT
|
||||
#undef KERNEL_FUNCTIONS
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
137
blender-5.2.0/intern/cycles/device/cpu/kernel.h
Normal file
137
blender-5.2.0/intern/cycles/device/cpu/kernel.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "device/cpu/kernel_function.h"
|
||||
#include "util/half.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
struct ThreadKernelGlobalsCPU;
|
||||
struct KernelFilmConvert;
|
||||
struct IntegratorStateCPU;
|
||||
struct TileInfo;
|
||||
|
||||
class CPUKernels {
|
||||
public:
|
||||
/* Integrator. */
|
||||
|
||||
using IntegratorFunction =
|
||||
CPUKernelFunction<void (*)(const ThreadKernelGlobalsCPU *kg, IntegratorStateCPU *state)>;
|
||||
using IntegratorShadeFunction = CPUKernelFunction<void (*)(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorStateCPU *state,
|
||||
ccl_global float *render_buffer)>;
|
||||
using IntegratorInitFunction = CPUKernelFunction<bool (*)(const ThreadKernelGlobalsCPU *kg,
|
||||
IntegratorStateCPU *state,
|
||||
KernelWorkTile *tile,
|
||||
ccl_global float *render_buffer)>;
|
||||
|
||||
IntegratorInitFunction integrator_init_from_camera;
|
||||
IntegratorInitFunction integrator_init_from_bake;
|
||||
IntegratorShadeFunction integrator_megakernel;
|
||||
|
||||
/* Shader evaluation. */
|
||||
|
||||
using ShaderEvalFunction = CPUKernelFunction<void (*)(
|
||||
const ThreadKernelGlobalsCPU *kg, const KernelShaderEvalInput *, float *, const int)>;
|
||||
|
||||
ShaderEvalFunction shader_eval_displace;
|
||||
ShaderEvalFunction shader_eval_background;
|
||||
ShaderEvalFunction shader_eval_curve_shadow_transparency;
|
||||
ShaderEvalFunction shader_eval_volume_density;
|
||||
|
||||
/* Adaptive stopping. */
|
||||
|
||||
using AdaptiveSamplingConvergenceCheckFunction =
|
||||
CPUKernelFunction<bool (*)(const ThreadKernelGlobalsCPU *kg,
|
||||
ccl_global float *render_buffer,
|
||||
const int x,
|
||||
const int y,
|
||||
const float threshold,
|
||||
const int reset,
|
||||
const int offset,
|
||||
int stride)>;
|
||||
|
||||
using FilterXFunction = CPUKernelFunction<void (*)(const ThreadKernelGlobalsCPU *kg,
|
||||
ccl_global float *render_buffer,
|
||||
const int y,
|
||||
const int start_x,
|
||||
const int width,
|
||||
const int offset,
|
||||
int stride)>;
|
||||
|
||||
using FilterYFunction = CPUKernelFunction<void (*)(const ThreadKernelGlobalsCPU *kg,
|
||||
ccl_global float *render_buffer,
|
||||
const int x,
|
||||
const int start_y,
|
||||
const int height,
|
||||
const int offset,
|
||||
int stride)>;
|
||||
|
||||
AdaptiveSamplingConvergenceCheckFunction adaptive_sampling_convergence_check;
|
||||
|
||||
FilterXFunction adaptive_sampling_filter_x;
|
||||
FilterYFunction adaptive_sampling_filter_y;
|
||||
|
||||
/* Volume Scattering Probability Guiding. */
|
||||
CPUKernelFunction<void (*)(const ThreadKernelGlobalsCPU *kg,
|
||||
ccl_global float *render_buffer,
|
||||
const int y,
|
||||
const int center_x,
|
||||
const int min_x,
|
||||
const int max_x,
|
||||
const int offset,
|
||||
int stride)>
|
||||
volume_guiding_filter_x;
|
||||
FilterYFunction volume_guiding_filter_y;
|
||||
|
||||
/* Cryptomatte. */
|
||||
|
||||
using CryptomattePostprocessFunction = CPUKernelFunction<void (*)(
|
||||
const ThreadKernelGlobalsCPU *kg, ccl_global float *render_buffer, const int pixel_index)>;
|
||||
|
||||
CryptomattePostprocessFunction cryptomatte_postprocess;
|
||||
|
||||
/* Film Convert. */
|
||||
using FilmConvertFunction = CPUKernelFunction<void (*)(const KernelFilmConvert *kfilm_convert,
|
||||
const float *buffer,
|
||||
float *pixel,
|
||||
const int width,
|
||||
const int buffer_stride,
|
||||
const int pixel_stride)>;
|
||||
using FilmConvertHalfRGBAFunction =
|
||||
CPUKernelFunction<void (*)(const KernelFilmConvert *kfilm_convert,
|
||||
const float *buffer,
|
||||
half4 *pixel,
|
||||
const int width,
|
||||
const int buffer_stride)>;
|
||||
|
||||
#define KERNEL_FILM_CONVERT_FUNCTION(name) \
|
||||
FilmConvertFunction film_convert_##name; \
|
||||
FilmConvertHalfRGBAFunction film_convert_half_rgba_##name;
|
||||
|
||||
KERNEL_FILM_CONVERT_FUNCTION(depth)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(mist)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(volume_majorant)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(sample_count)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(float)
|
||||
|
||||
KERNEL_FILM_CONVERT_FUNCTION(light_path)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(rgbe)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(float3)
|
||||
|
||||
KERNEL_FILM_CONVERT_FUNCTION(motion)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(cryptomatte)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(shadow_catcher)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(shadow_catcher_matte_with_shadow)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(combined)
|
||||
KERNEL_FILM_CONVERT_FUNCTION(float4)
|
||||
|
||||
#undef KERNEL_FILM_CONVERT_FUNCTION
|
||||
|
||||
CPUKernels();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
71
blender-5.2.0/intern/cycles/device/cpu/kernel_function.h
Normal file
71
blender-5.2.0/intern/cycles/device/cpu/kernel_function.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/debug.h" // IWYU pragma: keep
|
||||
#include "util/system.h" // IWYU pragma: keep
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* A wrapper around per-microarchitecture variant of a kernel function.
|
||||
*
|
||||
* Provides a function-call-like API which gets routed to the most suitable implementation.
|
||||
*
|
||||
* For example, on a computer which only has AVX2 the kernel_avx2 will be used. */
|
||||
template<typename FunctionType> class CPUKernelFunction {
|
||||
public:
|
||||
CPUKernelFunction(FunctionType kernel_default, FunctionType kernel_avx2)
|
||||
{
|
||||
kernel_info_ = get_best_kernel_info(kernel_default, kernel_avx2);
|
||||
}
|
||||
|
||||
template<typename... Args> auto operator()(Args... args) const
|
||||
{
|
||||
assert(kernel_info_.kernel);
|
||||
|
||||
return kernel_info_.kernel(args...);
|
||||
}
|
||||
|
||||
const char *get_uarch_name() const
|
||||
{
|
||||
return kernel_info_.uarch_name;
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Helper class which allows to pass human-readable microarchitecture name together with function
|
||||
* pointer. */
|
||||
class KernelInfo {
|
||||
public:
|
||||
KernelInfo() : KernelInfo("", nullptr) {}
|
||||
|
||||
/* TODO(sergey): Use string view, to have higher-level functionality (i.e. comparison) without
|
||||
* memory allocation. */
|
||||
KernelInfo(const char *uarch_name, FunctionType kernel)
|
||||
: uarch_name(uarch_name), kernel(kernel)
|
||||
{
|
||||
}
|
||||
|
||||
const char *uarch_name;
|
||||
FunctionType kernel;
|
||||
};
|
||||
|
||||
KernelInfo get_best_kernel_info(FunctionType kernel_default, FunctionType kernel_avx2)
|
||||
{
|
||||
/* Silence warnings about unused variables when compiling without some architectures. */
|
||||
(void)kernel_avx2;
|
||||
|
||||
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
|
||||
if (DebugFlags().cpu.has_avx2() && system_cpu_support_avx2()) {
|
||||
return KernelInfo("AVX2", kernel_avx2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return KernelInfo("default", kernel_default);
|
||||
}
|
||||
|
||||
KernelInfo kernel_info_;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
Reference in New Issue
Block a user