Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,325 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#include "device/hip/device.h"
#include "device/device.h"
#include "util/log.h"
#ifdef WITH_HIP
# include "device/hip/device_impl.h"
# include "integrator/denoiser_oidn_gpu.h" // IWYU pragma: keep
# include "util/string.h"
# ifdef _WIN32
# include "util/windows.h"
# endif
#endif /* WITH_HIP */
#ifdef WITH_HIPRT
# include "device/hiprt/device_impl.h"
#endif
CCL_NAMESPACE_BEGIN
bool device_hip_init()
{
#if !defined(WITH_HIP)
return false;
#elif defined(WITH_HIP_DYNLOAD)
static bool initialized = false;
static bool result = false;
if (initialized) {
return result;
}
initialized = true;
int hipew_result = hipewInit(HIPEW_INIT_HIP);
if (hipew_result == HIPEW_SUCCESS) {
LOG_INFO << "HIPEW initialization succeeded";
if (!hipSupportsDriver()) {
LOG_WARNING << "Driver version is too old";
}
else if (HIPDevice::have_precompiled_kernels()) {
LOG_INFO << "Found precompiled kernels";
result = true;
}
else if (hipewCompilerPath() != nullptr) {
LOG_INFO << "Found HIPCC " << hipewCompilerPath();
result = true;
}
else {
LOG_INFO << "Neither precompiled kernels nor HIPCC was found,"
<< " unable to use HIP";
}
}
else {
if (hipew_result == HIPEW_ERROR_ATEXIT_FAILED) {
LOG_WARNING << "HIPEW initialization failed: Error setting up atexit() handler";
}
else if (hipew_result == HIPEW_ERROR_OLD_DRIVER) {
LOG_WARNING << "HIPEW initialization failed: Driver version too old, requires AMD Adrenalin "
"driver 24.9.1 or newer, or AMD Radeon Pro driver 24.Q4 or newer";
}
else {
LOG_WARNING << "HIPEW initialization failed: Error opening HIP dynamic library";
}
}
return result;
#else /* WITH_HIP_DYNLOAD */
return true;
#endif /* WITH_HIP_DYNLOAD */
}
unique_ptr<Device> device_hip_create(const DeviceInfo &info,
Stats &stats,
Profiler &profiler,
const bool headless)
{
#ifdef WITH_HIPRT
if (info.use_hardware_raytracing) {
return make_unique<HIPRTDevice>(info, stats, profiler, headless);
}
return make_unique<HIPDevice>(info, stats, profiler, headless);
#elif defined(WITH_HIP)
return make_unique<HIPDevice>(info, stats, profiler, headless);
#else
(void)info;
(void)stats;
(void)profiler;
(void)headless;
LOG_FATAL << "Request to create HIP device without compiled-in support. Should never happen.";
return nullptr;
#endif
}
#ifdef WITH_HIP
static hipError_t device_hip_safe_init()
{
# ifdef _WIN32
__try
{
return hipInit(0);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
/* Ignore crashes inside the HIP driver and hope we can
* survive even with corrupted HIP installs. */
fprintf(stderr, "Cycles HIP: driver crashed, continuing without HIP.\n");
}
return hipErrorNoDevice;
# else
return hipInit(0);
# endif
}
#endif /* WITH_HIP */
void device_hip_info(vector<DeviceInfo> &devices)
{
#ifdef WITH_HIP
hipError_t result = device_hip_safe_init();
if (result != hipSuccess) {
if (result != hipErrorNoDevice) {
LOG_ERROR << "HIP hipInit: " << hipewErrorString(result);
}
return;
}
int count = 0;
result = hipGetDeviceCount(&count);
if (result != hipSuccess) {
LOG_ERROR << "HIP hipGetDeviceCount: " << hipewErrorString(result);
return;
}
# ifdef WITH_HIPRT
const bool has_hardware_raytracing = HIPRTDevice::is_supported();
# else
const bool has_hardware_raytracing = false;
# endif
vector<DeviceInfo> display_devices;
for (int num = 0; num < count; num++) {
char name[256];
result = hipDeviceGetName(name, 256, num);
if (result != hipSuccess) {
LOG_ERROR << "HIP hipDeviceGetName: " << hipewErrorString(result);
continue;
}
if (!hipSupportsDevice(num)) {
continue;
}
DeviceInfo info;
info.type = DEVICE_HIP;
info.description = string(name);
info.num = num;
info.has_nanovdb = true;
info.has_gpu_queue = true;
/* Check if the device has P2P access to any other device in the system. */
for (int peer_num = 0; peer_num < count && !info.has_peer_memory; peer_num++) {
if (num != peer_num) {
if (hipSupportsDevice(peer_num)) {
int can_access = 0;
hipDeviceCanAccessPeer(&can_access, num, peer_num);
info.has_peer_memory = (can_access != 0);
}
}
}
/* Disable on RDNA1 due to bug rendering curves in HIP-RT 2.5 or HIP SDK 6.3. */
info.use_hardware_raytracing = has_hardware_raytracing && hipIsRDNA2OrNewer(num);
int pci_location[3] = {0, 0, 0};
hipDeviceGetAttribute(&pci_location[0], hipDeviceAttributePciDomainID, num);
hipDeviceGetAttribute(&pci_location[1], hipDeviceAttributePciBusId, num);
hipDeviceGetAttribute(&pci_location[2], hipDeviceAttributePciDeviceId, num);
info.id = string_printf("HIP_%s_%04x:%02x:%02x",
name,
(unsigned int)pci_location[0],
(unsigned int)pci_location[1],
(unsigned int)pci_location[2]);
info.denoisers = 0;
# if defined(WITH_OPENIMAGEDENOISE)
/* Check first if OIDN supports it, not doing so can crash the HIP driver with
* "hipErrorNoBinaryForGpu: Unable to find code object for all current devices". */
# if OIDN_VERSION >= 20300
if (hipSupportsDeviceOIDN(num) && oidnIsHIPDeviceSupported(num)) {
# else
if (hipSupportsDeviceOIDN(num) && OIDNDenoiserGPU::is_device_supported(info)) {
# endif
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
}
# endif
/* If device has a kernel timeout and no compute preemption, we assume
* it is connected to a display and will freeze the display while doing
* computations. */
int timeout_attr = 0;
hipDeviceGetAttribute(&timeout_attr, hipDeviceAttributeKernelExecTimeout, num);
if (timeout_attr) {
LOG_INFO << "Device is recognized as display.";
info.description += " (Display)";
info.display_device = true;
display_devices.push_back(info);
}
else {
LOG_INFO << "Device has compute preemption or is not used for display.";
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) << ".";
}
}
if (!display_devices.empty()) {
devices.insert(devices.end(), display_devices.begin(), display_devices.end());
}
#else /* WITH_HIP */
(void)devices;
#endif /* WITH_HIP */
}
string device_hip_capabilities()
{
#ifdef WITH_HIP
hipError_t result = device_hip_safe_init();
if (result != hipSuccess) {
if (result != hipErrorNoDevice) {
return string("Error initializing HIP: ") + hipewErrorString(result);
}
return "No HIP device found\n";
}
int count;
result = hipGetDeviceCount(&count);
if (result != hipSuccess) {
return string("Error getting devices: ") + hipewErrorString(result);
}
string capabilities;
for (int num = 0; num < count; num++) {
char name[256];
if (hipDeviceGetName(name, 256, num) != hipSuccess) {
continue;
}
capabilities += string("\t") + name + "\n";
int value;
# define GET_ATTR(attr) \
{ \
if (hipDeviceGetAttribute(&value, hipDeviceAttribute##attr, num) == hipSuccess) { \
capabilities += string_printf("\t\thipDeviceAttribute" #attr "\t\t\t%d\n", value); \
} \
} \
(void)0
/* TODO(sergey): Strip all attributes which are not useful for us
* or does not depend on the driver.
*/
GET_ATTR(MaxThreadsPerBlock);
GET_ATTR(MaxBlockDimX);
GET_ATTR(MaxBlockDimY);
GET_ATTR(MaxBlockDimZ);
GET_ATTR(MaxGridDimX);
GET_ATTR(MaxGridDimY);
GET_ATTR(MaxGridDimZ);
GET_ATTR(MaxSharedMemoryPerBlock);
GET_ATTR(TotalConstantMemory);
GET_ATTR(WarpSize);
GET_ATTR(MaxPitch);
GET_ATTR(MaxRegistersPerBlock);
GET_ATTR(ClockRate);
GET_ATTR(TextureAlignment);
GET_ATTR(MultiprocessorCount);
GET_ATTR(KernelExecTimeout);
GET_ATTR(Integrated);
GET_ATTR(CanMapHostMemory);
GET_ATTR(ComputeMode);
GET_ATTR(MaxTexture1DWidth);
GET_ATTR(MaxTexture2DWidth);
GET_ATTR(MaxTexture2DHeight);
GET_ATTR(MaxTexture3DWidth);
GET_ATTR(MaxTexture3DHeight);
GET_ATTR(MaxTexture3DDepth);
GET_ATTR(ConcurrentKernels);
GET_ATTR(EccEnabled);
GET_ATTR(MemoryClockRate);
GET_ATTR(MemoryBusWidth);
GET_ATTR(L2CacheSize);
GET_ATTR(MaxThreadsPerMultiProcessor);
GET_ATTR(ComputeCapabilityMajor);
GET_ATTR(ComputeCapabilityMinor);
GET_ATTR(MaxSharedMemoryPerMultiprocessor);
GET_ATTR(ManagedMemory);
GET_ATTR(IsMultiGpuBoard);
# undef GET_ATTR
capabilities += "\n";
}
return capabilities;
#else /* WITH_HIP */
return "";
#endif /* WITH_HIP */
}
CCL_NAMESPACE_END

View 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_hip_init();
unique_ptr<Device> device_hip_create(const DeviceInfo &info,
Stats &stats,
Profiler &profiler,
bool headless);
void device_hip_info(vector<DeviceInfo> &devices);
string device_hip_capabilities();
CCL_NAMESPACE_END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#ifdef WITH_HIP
# include "device/device.h"
# include "device/hip/kernel.h"
# include "device/hip/queue.h"
# include "device/hip/util.h"
# ifdef WITH_HIP_DYNLOAD
# include "hipew.h"
# endif
CCL_NAMESPACE_BEGIN
class DeviceQueue;
class HIPDevice : public GPUDevice {
friend class HIPContextScope;
public:
hipDevice_t hipDevice;
hipCtx_t hipContext;
hipModule_t hipModule;
int pitch_alignment;
int hipDevId;
int hipDevArchitecture;
int hipRuntimeVersion;
bool first_error;
HIPDeviceKernels kernels;
static bool have_precompiled_kernels();
BVHLayoutMask get_bvh_layout_mask(uint /*kernel_features*/) const override;
void set_error(const string &error) override;
HIPDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless);
~HIPDevice() override;
bool support_device(const uint /*kernel_features*/);
bool check_peer_access(Device *peer_device) override;
bool use_adaptive_compilation();
string compile_kernel_get_common_cflags(const uint kernel_features);
string compile_kernel(const uint kernel_features, const char *name, const char *base = "hip");
bool load_kernels(const uint kernel_features) override;
void reserve_local_memory(const uint kernel_features);
/* 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) override;
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);
/* 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;
int get_num_multiprocessors();
int get_max_num_threads_per_multiprocessor();
protected:
bool get_device_attribute(hipDeviceAttribute_t attribute, int *value);
int get_device_default_attribute(hipDeviceAttribute_t attribute, const int default_value);
};
CCL_NAMESPACE_END
#endif

View File

@@ -0,0 +1,120 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#ifdef WITH_HIP
# include "device/hip/graphics_interop.h"
# include "device/hip/device_impl.h"
# include "device/hip/util.h"
CCL_NAMESPACE_BEGIN
HIPDeviceGraphicsInterop::HIPDeviceGraphicsInterop(HIPDeviceQueue *queue)
: queue_(queue), device_(static_cast<HIPDevice *>(queue->device))
{
}
HIPDeviceGraphicsInterop::~HIPDeviceGraphicsInterop()
{
HIPContextScope scope(device_);
free();
}
void HIPDeviceGraphicsInterop::set_buffer(GraphicsInteropBuffer &interop_buffer)
{
HIPContextScope scope(device_);
if (interop_buffer.is_empty()) {
free();
return;
}
need_zero_ |= interop_buffer.take_zero();
if (!interop_buffer.has_new_handle()) {
return;
}
free();
switch (interop_buffer.get_type()) {
case GraphicsInteropDevice::OPENGL: {
const hipError_t result = hipGraphicsGLRegisterBuffer(
&hip_graphics_resource_, interop_buffer.take_handle(), hipGraphicsRegisterFlagsNone);
if (result != hipSuccess) {
LOG_ERROR << "Error registering OpenGL buffer: " << hipewErrorString(result);
break;
}
buffer_size_ = interop_buffer.get_size();
break;
}
case GraphicsInteropDevice::VULKAN:
case GraphicsInteropDevice::METAL:
case GraphicsInteropDevice::NONE:
/* TODO: implement vulkan support. */
break;
}
}
device_ptr HIPDeviceGraphicsInterop::map()
{
hipDeviceptr_t hip_buffer = 0;
if (hip_graphics_resource_) {
HIPContextScope scope(device_);
size_t bytes;
hip_device_assert(device_,
hipGraphicsMapResources(1, &hip_graphics_resource_, queue_->stream()));
hip_device_assert(
device_, hipGraphicsResourceGetMappedPointer(&hip_buffer, &bytes, hip_graphics_resource_));
}
else {
/* Vulkan buffer is always mapped. */
hip_buffer = hip_external_memory_ptr_;
}
if (hip_buffer && need_zero_) {
hip_device_assert(device_, hipMemsetD8Async(hip_buffer, 0, buffer_size_, queue_->stream()));
need_zero_ = false;
}
return static_cast<device_ptr>(hip_buffer);
}
void HIPDeviceGraphicsInterop::unmap()
{
if (hip_graphics_resource_) {
HIPContextScope scope(device_);
hip_device_assert(device_,
hipGraphicsUnmapResources(1, &hip_graphics_resource_, queue_->stream()));
}
}
void HIPDeviceGraphicsInterop::free()
{
if (hip_graphics_resource_) {
hip_device_assert(device_, hipGraphicsUnregisterResource(hip_graphics_resource_));
hip_graphics_resource_ = nullptr;
}
if (hip_external_memory_ptr_) {
hip_device_assert(device_, hipFree(hip_external_memory_ptr_));
hip_external_memory_ptr_ = 0;
}
buffer_size_ = 0;
need_zero_ = false;
}
CCL_NAMESPACE_END
#endif

View File

@@ -0,0 +1,54 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#ifdef WITH_HIP
# include "device/graphics_interop.h"
# include "session/display_driver.h"
# ifdef WITH_HIP_DYNLOAD
# include "hipew.h"
# endif
CCL_NAMESPACE_BEGIN
class HIPDevice;
class HIPDeviceQueue;
class HIPDeviceGraphicsInterop : public DeviceGraphicsInterop {
public:
explicit HIPDeviceGraphicsInterop(HIPDeviceQueue *queue);
HIPDeviceGraphicsInterop(const HIPDeviceGraphicsInterop &other) = delete;
HIPDeviceGraphicsInterop(HIPDeviceGraphicsInterop &&other) noexcept = delete;
~HIPDeviceGraphicsInterop() override;
HIPDeviceGraphicsInterop &operator=(const HIPDeviceGraphicsInterop &other) = delete;
HIPDeviceGraphicsInterop &operator=(HIPDeviceGraphicsInterop &&other) = delete;
void set_buffer(GraphicsInteropBuffer &interop_buffer) override;
device_ptr map() override;
void unmap() override;
protected:
HIPDeviceQueue *queue_ = nullptr;
HIPDevice *device_ = nullptr;
/* Size of the buffer in bytes. */
size_t buffer_size_ = 0;
/* The destination was requested to be cleared. */
bool need_zero_ = false;
hipGraphicsResource hip_graphics_resource_ = nullptr;
hipDeviceptr_t hip_external_memory_ptr_ = 0;
void free();
};
CCL_NAMESPACE_END
#endif

View File

@@ -0,0 +1,81 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#ifdef WITH_HIP
# include "kernel/types.h"
# include "device/hip/device_impl.h"
# include "device/hip/kernel.h"
CCL_NAMESPACE_BEGIN
bool HIPDeviceKernels::load_kernel(HIPDevice *device,
hipModule_t hip_module,
const DeviceKernel kernel)
{
if (available(kernel)) {
return true;
}
if (!device_kernel_has_gpu_function(kernel)) {
return false;
}
HIPDeviceKernel &hip_kernel = kernels_[int(kernel)];
const std::string function_name = std::string("kernel_gpu_") + device_kernel_as_string(kernel);
hip_device_assert(device,
hipModuleGetFunction(&hip_kernel.function, hip_module, function_name.c_str()));
if (!hip_kernel.function) {
LOG_ERROR << "Unable to load kernel " << function_name;
return false;
}
hip_device_assert(device, hipFuncSetCacheConfig(hip_kernel.function, hipFuncCachePreferL1));
hip_device_assert(
device,
hipModuleOccupancyMaxPotentialBlockSize(
&hip_kernel.min_blocks, &hip_kernel.num_threads_per_block, hip_kernel.function, 0, 0));
LOG_DEBUG << "Loaded kernel: " << function_name;
return true;
}
void HIPDeviceKernels::load_all(HIPDevice *device, hipModule_t hip_module)
{
LOG_DEBUG << "Loading all HIP kernels";
for (int i = 0; i < (int)DEVICE_KERNEL_NUM; i++) {
load_kernel(device, hip_module, DeviceKernel(i));
}
}
void HIPDeviceKernels::load_raytrace(HIPDevice *device, hipModule_t hip_module)
{
LOG_DEBUG << "Loading ray-tracing HIP-RT kernels";
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST);
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW);
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE);
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK);
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_INTERSECT_DEDICATED_LIGHT);
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_INTERSECT_MNEE);
load_kernel(device, hip_module, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE);
}
const HIPDeviceKernel &HIPDeviceKernels::get(DeviceKernel kernel) const
{
return kernels_[(int)kernel];
}
bool HIPDeviceKernels::available(DeviceKernel kernel) const
{
return kernels_[(int)kernel].function != nullptr;
}
CCL_NAMESPACE_END
#endif /* WITH_HIP */

View File

@@ -0,0 +1,45 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#ifdef WITH_HIP
# include "device/kernel.h"
# ifdef WITH_HIP_DYNLOAD
# include "hipew.h"
# endif
CCL_NAMESPACE_BEGIN
class HIPDevice;
/* HIP kernel and associate occupancy information. */
class HIPDeviceKernel {
public:
hipFunction_t function = nullptr;
int num_threads_per_block = 0;
int min_blocks = 0;
};
/* Cache of HIP kernels for each DeviceKernel. */
class HIPDeviceKernels {
public:
void load_all(HIPDevice *device, hipModule_t hip_module);
void load_raytrace(HIPDevice *device, hipModule_t hip_module);
const HIPDeviceKernel &get(DeviceKernel kernel) const;
bool available(DeviceKernel kernel) const;
protected:
bool load_kernel(HIPDevice *device, hipModule_t hip_module, DeviceKernel kernel);
HIPDeviceKernel kernels_[DEVICE_KERNEL_NUM];
};
CCL_NAMESPACE_END
#endif /* WITH_HIP */

View File

@@ -0,0 +1,267 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#ifdef WITH_HIP
# include "device/hip/queue.h"
# include "device/hip/device_impl.h"
# include "device/hip/graphics_interop.h"
# include "device/hip/kernel.h"
CCL_NAMESPACE_BEGIN
/* HIPDeviceQueue */
HIPDeviceQueue::HIPDeviceQueue(HIPDevice *device)
: DeviceQueue(device), hip_device_(device), hip_stream_(nullptr)
{
const HIPContextScope scope(hip_device_);
hip_device_assert(hip_device_, hipStreamCreateWithFlags(&hip_stream_, hipStreamNonBlocking));
}
HIPDeviceQueue::~HIPDeviceQueue()
{
const HIPContextScope scope(hip_device_);
hipStreamDestroy(hip_stream_);
}
int HIPDeviceQueue::num_concurrent_states(const size_t state_size) const
{
const int max_num_threads = hip_device_->get_num_multiprocessors() *
hip_device_->get_max_num_threads_per_multiprocessor();
int num_states = ((max_num_threads == 0) ? 65536 : max_num_threads) * 16;
const char *factor_str = getenv("CYCLES_CONCURRENT_STATES_FACTOR");
if (factor_str) {
const float factor = (float)atof(factor_str);
if (factor != 0.0f) {
num_states = max((int)(num_states * factor), 1024);
}
else {
LOG_TRACE << "CYCLES_CONCURRENT_STATES_FACTOR evaluated to 0";
}
}
LOG_TRACE << "GPU queue concurrent states: " << num_states << ", using up to "
<< string_human_readable_size(num_states * state_size);
return num_states;
}
int HIPDeviceQueue::num_concurrent_busy_states(const size_t /*state_size*/) const
{
const int max_num_threads = hip_device_->get_num_multiprocessors() *
hip_device_->get_max_num_threads_per_multiprocessor();
if (max_num_threads == 0) {
return 65536;
}
return 4 * max_num_threads;
}
void HIPDeviceQueue::init_execution()
{
/* Synchronize all textures and memory copies before executing task. */
HIPContextScope scope(hip_device_);
hip_device_->load_image_info(nullptr);
hip_device_assert(hip_device_, hipDeviceSynchronize());
debug_init_execution();
}
void HIPDeviceQueue::load_image_info()
{
HIPContextScope scope(hip_device_);
hip_device_->load_image_info(this);
}
bool HIPDeviceQueue::enqueue(DeviceKernel kernel,
const int work_size,
const DeviceKernelArguments &args)
{
if (hip_device_->have_error()) {
return false;
}
debug_enqueue_begin(kernel, work_size);
const HIPContextScope scope(hip_device_);
/* Update image info in case memory moved to host. */
if (hip_device_->load_image_info(nullptr)) {
hip_device_assert(hip_device_, hipDeviceSynchronize());
if (hip_device_->have_error()) {
return false;
}
}
/* Compute kernel launch parameters. */
const HIPDeviceKernel &hip_kernel = hip_device_->kernels.get(kernel);
const int num_threads_per_block = hip_kernel.num_threads_per_block;
const int num_blocks = divide_up(work_size, num_threads_per_block);
int shared_mem_bytes = 0;
switch (kernel) {
case DEVICE_KERNEL_INTEGRATOR_QUEUED_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_QUEUED_SHADOW_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_ACTIVE_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_TERMINATED_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_SORTED_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_COMPACT_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_TERMINATED_SHADOW_PATHS_ARRAY:
case DEVICE_KERNEL_INTEGRATOR_COMPACT_SHADOW_PATHS_ARRAY:
/* See parall_active_index.h for why this amount of shared memory is needed. */
shared_mem_bytes = (num_threads_per_block + 1) * sizeof(int);
break;
default:
break;
}
/* Launch kernel. */
assert_success(hipModuleLaunchKernel(hip_kernel.function,
num_blocks,
1,
1,
num_threads_per_block,
1,
1,
shared_mem_bytes,
hip_stream_,
const_cast<void **>(args.values),
nullptr),
"enqueue");
debug_enqueue_end();
return !(hip_device_->have_error());
}
bool HIPDeviceQueue::synchronize()
{
if (hip_device_->have_error()) {
return false;
}
const HIPContextScope scope(hip_device_);
assert_success(hipStreamSynchronize(hip_stream_), "synchronize");
debug_synchronize();
return !(hip_device_->have_error());
}
void HIPDeviceQueue::zero_to_device(device_memory &mem)
{
assert(mem.type != MEM_IMAGE_TEXTURE);
if (mem.memory_size() == 0) {
return;
}
/* Allocate on demand. */
if (mem.device_pointer == 0) {
if (mem.type == MEM_GLOBAL) {
hip_device_->global_alloc(mem);
}
else {
hip_device_->mem_alloc(mem);
}
}
/* Zero memory on device. */
device_ptr d_ptr = mem.device->mem_device_ptr(mem, hip_device_);
assert(d_ptr != 0);
const HIPContextScope scope(hip_device_);
assert_success(hipMemsetD8Async((hipDeviceptr_t)d_ptr, 0, mem.memory_size(), hip_stream_),
"zero_to_device");
}
void HIPDeviceQueue::copy_to_device(device_memory &mem)
{
assert(mem.type != MEM_IMAGE_TEXTURE);
if (mem.memory_size() == 0) {
return;
}
/* Allocate on demand. */
if (mem.device_pointer == 0) {
if (mem.type == MEM_GLOBAL) {
hip_device_->global_alloc(mem);
}
else {
hip_device_->mem_alloc(mem);
}
}
device_ptr d_ptr = mem.device->mem_device_ptr(mem, hip_device_);
assert(d_ptr != 0);
assert(mem.host_pointer != nullptr);
/* Copy memory to device. */
const HIPContextScope scope(hip_device_);
assert_success(
hipMemcpyHtoDAsync((hipDeviceptr_t)d_ptr, mem.host_pointer, mem.memory_size(), hip_stream_),
"copy_to_device");
}
void HIPDeviceQueue::copy_from_device(device_memory &mem)
{
assert(mem.type != MEM_GLOBAL && mem.type != MEM_IMAGE_TEXTURE);
if (mem.memory_size() == 0) {
return;
}
assert(mem.device_pointer != 0);
assert(mem.host_pointer != nullptr);
/* Copy memory from device. */
const HIPContextScope scope(hip_device_);
assert_success(
hipMemcpyDtoHAsync(
mem.host_pointer, (hipDeviceptr_t)mem.device_pointer, mem.memory_size(), hip_stream_),
"copy_from_device");
}
void *HIPDeviceQueue::copy_from_device_synchronized(device_memory &mem, vector<uint8_t> &storage)
{
if (mem.memory_size() == 0) {
return nullptr;
}
storage.resize(mem.memory_size());
device_ptr d_ptr = mem.device->mem_device_ptr(mem, hip_device_);
assert(d_ptr != 0);
const HIPContextScope scope(hip_device_);
assert_success(
hipMemcpyDtoHAsync(storage.data(), (hipDeviceptr_t)d_ptr, mem.memory_size(), hip_stream_),
"copy_from_device_synchronized");
synchronize();
return storage.data();
}
void HIPDeviceQueue::assert_success(hipError_t result, const char *operation)
{
if (result != hipSuccess) {
const char *name = hipewErrorString(result);
hip_device_->set_error(
string_printf("%s in HIP queue %s (%s)", name, operation, debug_active_kernels().c_str()));
}
}
unique_ptr<DeviceGraphicsInterop> HIPDeviceQueue::graphics_interop_create()
{
return make_unique<HIPDeviceGraphicsInterop>(this);
}
CCL_NAMESPACE_END
#endif /* WITH_HIP */

View File

@@ -0,0 +1,58 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#ifdef WITH_HIP
# include "device/memory.h"
# include "device/queue.h"
# include "device/hip/util.h"
CCL_NAMESPACE_BEGIN
class HIPDevice;
class device_memory;
/* Base class for HIP queues. */
class HIPDeviceQueue : public DeviceQueue {
public:
HIPDeviceQueue(HIPDevice *device);
~HIPDeviceQueue() override;
int num_concurrent_states(const size_t state_size) const override;
int num_concurrent_busy_states(const size_t state_size) const override;
void init_execution() override;
void load_image_info() override;
bool enqueue(DeviceKernel kernel,
const int 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;
virtual hipStream_t stream()
{
return hip_stream_;
}
unique_ptr<DeviceGraphicsInterop> graphics_interop_create() override;
protected:
HIPDevice *hip_device_;
hipStream_t hip_stream_;
void assert_success(hipError_t result, const char *operation);
};
CCL_NAMESPACE_END
#endif /* WITH_HIP */

View File

@@ -0,0 +1,77 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#ifdef WITH_HIP
# include "device/hip/util.h"
# include "device/hip/device_impl.h"
CCL_NAMESPACE_BEGIN
HIPContextScope::HIPContextScope(HIPDevice *device) : device(device)
{
hip_device_assert(device, hipCtxPushCurrent(device->hipContext));
}
HIPContextScope::~HIPContextScope()
{
hip_device_assert(device, hipCtxPopCurrent(nullptr));
}
# ifndef WITH_HIP_DYNLOAD
const char *hipewErrorString(hipError_t result)
{
/* We can only give error code here without major code duplication, that
* should be enough since dynamic loading is only being disabled by folks
* who knows what they're doing anyway.
*
* NOTE: Avoid call from several threads.
*/
static string error;
error = string_printf("%d", result);
return error.c_str();
}
const char *hipewCompilerPath()
{
return CYCLES_HIP_HIPCC_EXECUTABLE;
}
int hipewCompilerVersion()
{
return (HIP_VERSION / 100) + (HIP_VERSION % 100 / 10);
}
# endif /* !WITH_HIP_DYNLOAD */
bool hipSupportsDriver()
{
int hip_driver_version = 0;
hipError_t result = hipDriverGetVersion(&hip_driver_version);
if (result != hipSuccess) {
LOG_WARNING << "Error getting driver version: " << hipewErrorString(result);
return false;
}
LOG_TRACE << "Detected HIP driver version: " << hip_driver_version;
# ifdef _WIN32
if (hip_driver_version < 60241512) {
/* Users get error messages about being unable to find GPU binaries on older GPU drivers.
* 60241512 corresponds to Adrenalin 24.9.1. */
return false;
}
# else /* Linux */
if (hip_driver_version < 60342131) {
/* Users get error messages about being unable to load GPU kernels on older ROCm versions.
* 60342131 corresponds to ROCm 6.3.0 */
return false;
}
# endif
return true;
}
CCL_NAMESPACE_END
#endif /* WITH_HIP */

View File

@@ -0,0 +1,92 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#ifdef WITH_HIP
# include <cstring>
# include <string>
# ifdef WITH_HIP_DYNLOAD
# include "hipew.h"
# endif
CCL_NAMESPACE_BEGIN
class HIPDevice;
/* Utility to push/pop HIP context. */
class HIPContextScope {
public:
HIPContextScope(HIPDevice *device);
~HIPContextScope();
private:
HIPDevice *device;
};
/* Utility for checking return values of HIP function calls. */
# define hip_device_assert(hip_device, stmt) \
{ \
hipError_t result = stmt; \
if (result != hipSuccess) { \
const char *name = hipewErrorString(result); \
hip_device->set_error( \
string_printf("%s in %s (%s:%d)", name, #stmt, __FILE__, __LINE__)); \
} \
} \
(void)0
# define hip_assert(stmt) hip_device_assert(this, stmt)
# ifndef WITH_HIP_DYNLOAD
/* Transparently implement some functions, so majority of the file does not need
* to worry about difference between dynamically loaded and linked HIP at all. */
const char *hipewErrorString(hipError_t result);
const char *hipewCompilerPath();
int hipewCompilerVersion();
# endif /* !WITH_HIP_DYNLOAD */
bool hipSupportsDriver();
static std::string hipDeviceArch(const int hipDevId)
{
hipDeviceProp_t props;
hipGetDeviceProperties(&props, hipDevId);
const char *arch = strtok(props.gcnArchName, ":");
return (arch == nullptr) ? props.gcnArchName : arch;
}
static inline bool hipSupportsDevice(const int hipDevId)
{
int major, minor;
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
return (major >= 10);
}
static inline bool hipIsRDNA2OrNewer(const int hipDevId)
{
int major, minor;
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
return (major > 10 || (major == 10 && minor >= 3));
}
static inline bool hipSupportsDeviceOIDN(const int hipDevId)
{
/* Matches HIPDevice::getArch in HIP. */
const std::string arch = hipDeviceArch(hipDevId);
return (arch == "gfx1030" || arch == "gfx1031" || arch == "gfx1032" || arch == "gfx1034" ||
arch == "gfx1035" || arch == "gfx1036" || arch == "gfx1100" || arch == "gfx1101" ||
arch == "gfx1102" || arch == "gfx1103" || arch == "gfx1150" || arch == "gfx1151" ||
arch == "gfx1152" || arch == "gfx1200" || arch == "gfx1201");
}
CCL_NAMESPACE_END
#endif /* WITH_HIP */