mirror of
https://github.com/blender/blender
synced 2026-10-25 03:07:01 +03:00
When a material contains many closures, enabling OSL in OptiX can cause OSL closure allocations to exceed the fixed size closure pool, which is currently arbitrarily set to 1024 bytes. This would then subsequently crash with CUDA illegal address errors. The fix is to introduce bounds checking to closure allocation and return nullptr when there is no space left in the pool, since OSL does handle this gracefully. There will be rendering differences in this case, since the failed closures are skipped, but that seems better than crashing. Pull Request: https://projects.blender.org/blender/blender/pulls/165060
565 lines
21 KiB
C
565 lines
21 KiB
C
/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
|
* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
* Adapted code from Open Shading Language. */
|
|
|
|
#include "kernel/geom/attribute.h"
|
|
|
|
#include "kernel/util/ies.h"
|
|
#include "kernel/util/image_3d.h"
|
|
|
|
#include "kernel/osl/services_shared.h"
|
|
#include "kernel/osl/strings.h"
|
|
|
|
#include "util/types_image.h"
|
|
|
|
#ifndef __KERNEL_GPU__
|
|
CCL_NAMESPACE_BEGIN
|
|
#endif
|
|
|
|
/* Closure */
|
|
|
|
ccl_device_extern ccl_private void *rs_allocate_closure(ccl_private ShaderGlobals *sg,
|
|
const size_t size,
|
|
const size_t alignment)
|
|
{
|
|
ccl_private uint8_t *closure_pool = sg->closure_pool;
|
|
/* Align pointer to closure struct requirement. */
|
|
closure_pool = reinterpret_cast<ccl_private uint8_t *>(
|
|
(reinterpret_cast<size_t>(closure_pool) + alignment - 1) & (-alignment));
|
|
|
|
if (closure_pool > sg->closure_pool_end || size > sg->closure_pool_end - closure_pool) {
|
|
return nullptr;
|
|
}
|
|
|
|
sg->closure_pool = closure_pool + size;
|
|
|
|
return closure_pool;
|
|
}
|
|
|
|
#if OSL_LIBRARY_VERSION_CODE < 11500
|
|
|
|
ccl_device_extern ccl_private OSLClosure *osl_mul_closure_color(ccl_private ShaderGlobals *sg,
|
|
ccl_private OSLClosure *a,
|
|
const ccl_private float3 *weight)
|
|
{
|
|
if (*weight == zero_float3() || !a) {
|
|
return nullptr;
|
|
}
|
|
if (*weight == one_float3()) {
|
|
return a;
|
|
}
|
|
|
|
ccl_private OSLClosureMul *const closure = reinterpret_cast<ccl_private OSLClosureMul *>(
|
|
rs_allocate_closure(sg, sizeof(OSLClosureMul), alignof(OSLClosureMul)));
|
|
if (closure != nullptr) {
|
|
closure->id = OSL_CLOSURE_MUL_ID;
|
|
closure->weight = *weight;
|
|
closure->closure = a;
|
|
}
|
|
return closure;
|
|
}
|
|
|
|
ccl_device_extern ccl_private OSLClosure *osl_mul_closure_float(ccl_private ShaderGlobals *sg,
|
|
ccl_private OSLClosure *a,
|
|
const float weight)
|
|
{
|
|
if (weight == 0.0f || !a) {
|
|
return nullptr;
|
|
}
|
|
if (weight == 1.0f) {
|
|
return a;
|
|
}
|
|
|
|
ccl_private OSLClosureMul *const closure = reinterpret_cast<ccl_private OSLClosureMul *>(
|
|
rs_allocate_closure(sg, sizeof(OSLClosureMul), alignof(OSLClosureMul)));
|
|
if (closure != nullptr) {
|
|
closure->id = OSL_CLOSURE_MUL_ID;
|
|
closure->weight = make_float3(weight, weight, weight);
|
|
closure->closure = a;
|
|
}
|
|
return closure;
|
|
}
|
|
|
|
ccl_device_extern ccl_private OSLClosure *osl_add_closure_closure(ccl_private ShaderGlobals *sg,
|
|
ccl_private OSLClosure *a,
|
|
ccl_private OSLClosure *b)
|
|
{
|
|
if (!a) {
|
|
return b;
|
|
}
|
|
if (!b) {
|
|
return a;
|
|
}
|
|
|
|
ccl_private OSLClosureAdd *const closure = reinterpret_cast<ccl_private OSLClosureAdd *>(
|
|
rs_allocate_closure(sg, sizeof(OSLClosureAdd), alignof(OSLClosureAdd)));
|
|
if (closure != nullptr) {
|
|
closure->id = OSL_CLOSURE_ADD_ID;
|
|
closure->closureA = a;
|
|
closure->closureB = b;
|
|
}
|
|
return closure;
|
|
}
|
|
|
|
ccl_device_extern ccl_private OSLClosure *osl_allocate_closure_component(
|
|
ccl_private ShaderGlobals *sg, const int id, const int size)
|
|
{
|
|
ccl_private OSLClosureComponent *const closure =
|
|
reinterpret_cast<ccl_private OSLClosureComponent *>(rs_allocate_closure(
|
|
sg, sizeof(OSLClosureComponent) + size, alignof(OSLClosureComponent)));
|
|
if (closure != nullptr) {
|
|
closure->id = static_cast<OSLClosureType>(id);
|
|
closure->weight = one_float3();
|
|
}
|
|
return closure;
|
|
}
|
|
|
|
ccl_device_extern ccl_private OSLClosure *osl_allocate_weighted_closure_component(
|
|
ccl_private ShaderGlobals *sg, const int id, const int size, const ccl_private float3 *weight)
|
|
{
|
|
ccl_private OSLClosureComponent *const closure =
|
|
reinterpret_cast<ccl_private OSLClosureComponent *>(rs_allocate_closure(
|
|
sg, sizeof(OSLClosureComponent) + size, alignof(OSLClosureComponent)));
|
|
if (closure != nullptr) {
|
|
closure->id = static_cast<OSLClosureType>(id);
|
|
closure->weight = *weight;
|
|
}
|
|
return closure;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Utilities */
|
|
|
|
ccl_device_extern void osl_error(ccl_private ShaderGlobals * /*sg*/,
|
|
DeviceString /*format*/,
|
|
void * /*args*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_printf(ccl_private ShaderGlobals * /*sg*/,
|
|
DeviceString /*format*/,
|
|
void * /*args*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_warning(ccl_private ShaderGlobals * /*sg*/,
|
|
DeviceString /*format*/,
|
|
void * /*args*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_fprintf(ccl_private ShaderGlobals * /*sg*/,
|
|
DeviceString /*filename*/,
|
|
DeviceString /*format*/,
|
|
void * /*args*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern uint osl_range_check_err(const int indexvalue,
|
|
const int length,
|
|
DeviceString /*symname*/,
|
|
ccl_private ShaderGlobals * /*sg*/,
|
|
DeviceString /*sourcefile*/,
|
|
const int /*sourceline*/,
|
|
DeviceString /*groupname*/,
|
|
const int /*layer*/,
|
|
DeviceString /*layername*/,
|
|
DeviceString /*shadername*/)
|
|
{
|
|
const int result = indexvalue < 0 ? 0 : indexvalue >= length ? length - 1 : indexvalue;
|
|
#if 0
|
|
if (result != indexvalue) {
|
|
printf("Index [%d] out of range\n", indexvalue);
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/* Matrix Utilities */
|
|
|
|
ccl_device_extern bool osl_get_matrix(ccl_private ShaderGlobals *sg,
|
|
ccl_private float *res,
|
|
DeviceString from)
|
|
{
|
|
KernelGlobals kg = nullptr;
|
|
|
|
if (from == DeviceStrings::u_common) {
|
|
copy_matrix(res, projection_identity());
|
|
return true;
|
|
}
|
|
if (from == DeviceStrings::u_shader || from == DeviceStrings::u_object) {
|
|
return osl_shared_get_object_matrix(kg, sg->sd, res);
|
|
}
|
|
return osl_shared_get_named_matrix(kg, from, res);
|
|
}
|
|
|
|
ccl_device_extern bool osl_get_inverse_matrix(ccl_private ShaderGlobals *sg,
|
|
ccl_private float *res,
|
|
DeviceString to)
|
|
{
|
|
KernelGlobals kg = nullptr;
|
|
|
|
if (to == DeviceStrings::u_common) {
|
|
copy_matrix(res, projection_identity());
|
|
return true;
|
|
}
|
|
if (to == DeviceStrings::u_shader || to == DeviceStrings::u_object) {
|
|
return osl_shared_get_object_inverse_matrix(kg, sg->sd, res);
|
|
}
|
|
return osl_shared_get_named_inverse_matrix(kg, to, res);
|
|
}
|
|
|
|
/* The ABI for these callbacks is different, so DeviceString and TypeDesc don't work here. */
|
|
using RSTypeDesc = long long;
|
|
|
|
struct RSDeviceString {
|
|
DeviceString val;
|
|
};
|
|
|
|
/* Attributes */
|
|
|
|
ccl_device_extern bool osl_get_attribute(ccl_private ShaderGlobals *sg,
|
|
const int derivatives,
|
|
DeviceString object_name,
|
|
DeviceString name,
|
|
const int /*array_lookup*/,
|
|
const int /*index*/,
|
|
const RSTypeDesc type_abi,
|
|
ccl_private void *res)
|
|
{
|
|
const TypeDesc type = *reinterpret_cast<const TypeDesc *>(&type_abi);
|
|
KernelGlobals kg = nullptr;
|
|
ccl_private ShaderData *const sd = sg->sd;
|
|
|
|
if (sd->shader == SHADER_NONE) {
|
|
/* Camera shader. */
|
|
return osl_shared_get_camera_attribute(kg, sg, name, type, derivatives, res);
|
|
}
|
|
|
|
if (object_name != DeviceStrings::u_empty) {
|
|
/* TODO: Get object index from name */
|
|
return false;
|
|
}
|
|
|
|
const int object = sd->object;
|
|
|
|
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name);
|
|
if (is_attribute_found(desc)) {
|
|
return osl_shared_get_object_attribute(kg, sd, desc, type, derivatives, res);
|
|
}
|
|
return osl_shared_get_object_standard_attribute(kg, sg, sd, name, type, derivatives, res);
|
|
}
|
|
|
|
/* Renderer services */
|
|
|
|
ccl_device_extern bool rend_get_userdata(RSDeviceString name,
|
|
ccl_private void *data,
|
|
int data_size,
|
|
const TypeDesc &type,
|
|
int /*index*/)
|
|
{
|
|
if (type.basetype == TypeDesc::PTR) {
|
|
kernel_assert(data_size == sizeof(void *));
|
|
(void)data_size;
|
|
|
|
ccl_private void **ptr_data = (ccl_private void **)data;
|
|
|
|
if (name.val == DeviceStrings::u_colorsystem) {
|
|
#ifdef __KERNEL_OPTIX__
|
|
*ptr_data = kernel_params.osl_colorsystem;
|
|
return true;
|
|
#else
|
|
(void)ptr_data;
|
|
return false;
|
|
#endif
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ccl_device_extern bool rs_texture(ccl_private ShaderGlobals *sg,
|
|
RSDeviceString /*filename*/,
|
|
ccl_private void *texture_handle,
|
|
ccl_private void * /*texture_thread_info*/,
|
|
ccl_private OSLTextureOptions *opt,
|
|
const float s,
|
|
const float t,
|
|
const float dsdx,
|
|
const float dtdx,
|
|
const float dsdy,
|
|
const float dtdy,
|
|
const int nchannels,
|
|
ccl_private float *result,
|
|
ccl_private float * /*dresultds*/,
|
|
ccl_private float * /*dresultdt*/,
|
|
ccl_private void * /*errormessage*/)
|
|
{
|
|
return osl_shared_texture(
|
|
nullptr, sg, texture_handle, opt, s, t, dsdx, dtdx, dsdy, dtdy, nchannels, result);
|
|
}
|
|
|
|
ccl_device_extern bool rs_texture3d(ccl_private ShaderGlobals *sg,
|
|
RSDeviceString /*filename*/,
|
|
ccl_private void *texture_handle,
|
|
ccl_private void * /*texture_thread_info*/,
|
|
ccl_private OSLTextureOptions * /*opt*/,
|
|
const ccl_private float3 *P,
|
|
const ccl_private float3 *dPdx,
|
|
const ccl_private float3 *dPdy,
|
|
const ccl_private float3 *dPdz,
|
|
const int nchannels,
|
|
ccl_private float *result,
|
|
ccl_private float * /*dresultds*/,
|
|
ccl_private float * /*dresultdt*/,
|
|
ccl_private float * /*dresultdr*/,
|
|
ccl_private void * /*errormessage*/)
|
|
{
|
|
return osl_shared_texture3d(
|
|
nullptr, sg, texture_handle, *P, *dPdx, *dPdy, *dPdz, nchannels, result);
|
|
}
|
|
|
|
ccl_device_extern bool rs_environment(ccl_private ShaderGlobals *sg,
|
|
RSDeviceString /*filename*/,
|
|
ccl_private void *texture_handle,
|
|
ccl_private void * /*texture_thread_info*/,
|
|
ccl_private OSLTextureOptions *opt,
|
|
const ccl_private float3 *R,
|
|
const ccl_private float3 *dRdx,
|
|
const ccl_private float3 *dRdy,
|
|
const int nchannels,
|
|
ccl_private float *result,
|
|
ccl_private float * /*dresultds*/,
|
|
ccl_private float * /*dresultdt*/,
|
|
ccl_private void * /*errormessage*/)
|
|
{
|
|
return osl_shared_environment(
|
|
nullptr, sg, texture_handle, opt, *R, *dRdx, *dRdy, nchannels, result);
|
|
}
|
|
|
|
ccl_device_extern bool rs_get_texture_info(ccl_private ShaderGlobals * /*sg*/,
|
|
RSDeviceString /*filename*/,
|
|
ccl_private void *texture_handle,
|
|
ccl_private void * /*texture_thread_info*/,
|
|
int /*subimage*/,
|
|
RSDeviceString dataname,
|
|
TypeDesc datatype,
|
|
ccl_private void *data,
|
|
ccl_private void * /*errormessage*/)
|
|
{
|
|
return osl_shared_get_texture_info(
|
|
nullptr, texture_handle, zero_float2(), false, dataname.val, datatype, data);
|
|
}
|
|
|
|
ccl_device_extern bool rs_get_texture_info_st(ccl_private ShaderGlobals * /*sg*/,
|
|
RSDeviceString /*filename*/,
|
|
ccl_private void *texture_handle,
|
|
const float s,
|
|
const float t,
|
|
ccl_private void * /*texture_thread_info*/,
|
|
int /*subimage*/,
|
|
RSDeviceString dataname,
|
|
TypeDesc datatype,
|
|
ccl_private void *data,
|
|
ccl_private void * /*errormessage*/)
|
|
{
|
|
return osl_shared_get_texture_info(
|
|
nullptr, texture_handle, make_float2(s, t), true, dataname.val, datatype, data);
|
|
}
|
|
|
|
ccl_device_extern int rs_pointcloud_search(ccl_private ShaderGlobals * /*sg*/,
|
|
RSDeviceString /*filename*/,
|
|
const ccl_private float3 * /*center*/,
|
|
float /*radius*/,
|
|
int /*max_points*/,
|
|
bool /*sort*/,
|
|
ccl_private int * /*out_indices*/,
|
|
ccl_private float * /*out_distances*/,
|
|
int /*derivs_offset*/)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ccl_device_extern int rs_pointcloud_get(ccl_private ShaderGlobals * /*sg*/,
|
|
RSDeviceString /*filename*/,
|
|
const ccl_private int * /*indices*/,
|
|
int /*count*/,
|
|
RSDeviceString /*attr_name*/,
|
|
TypeDesc /*attr_type*/,
|
|
ccl_private void * /*out_data*/)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ccl_device_extern bool rs_pointcloud_write(ccl_private ShaderGlobals * /*sg*/,
|
|
RSDeviceString /*filename*/,
|
|
const ccl_private float3 * /*pos*/,
|
|
int /*nattribs*/,
|
|
const ccl_private DeviceString * /*names*/,
|
|
const ccl_private TypeDesc * /*types*/,
|
|
const ccl_private void ** /*data*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ccl_device_extern bool rs_trace(ccl_private ShaderGlobals * /*sg*/,
|
|
ccl_private void * /*options*/,
|
|
const ccl_private float3 * /*P*/,
|
|
const ccl_private float3 * /*dPdx*/,
|
|
const ccl_private float3 * /*dPdy*/,
|
|
const ccl_private float3 * /*R*/,
|
|
const ccl_private float3 * /*dRdx*/,
|
|
const ccl_private float3 * /*dRdy*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ccl_device_extern bool rs_trace_get(ccl_private ShaderGlobals * /*sg*/,
|
|
RSDeviceString /*name*/,
|
|
TypeDesc /*type*/,
|
|
ccl_private void * /*data*/,
|
|
bool /*derivatives*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* These osl_ functions are supposed to be implemented by OSL itself, but they are not yet.
|
|
* See: https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/pull/1951
|
|
* So we have to keep them around for now.
|
|
*
|
|
* The 1.14.4 based beta used for Blender 4.5 does not need them though, so we check the
|
|
* version for that. */
|
|
#if (OSL_LIBRARY_VERSION_CODE >= 11405) || (OSL_LIBRARY_VERSION_CODE < 11403)
|
|
ccl_device_extern void osl_texture_set_firstchannel(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*firstchannel*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern int osl_texture_decode_wrapmode(DeviceString /*name_*/)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_swrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*mode*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_twrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*mode*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_rwrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*mode*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_stwrap_code(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*mode*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_sblur(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*blur*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_tblur(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*blur*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_rblur(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*blur*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_stblur(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*blur*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_swidth(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*width*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_twidth(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*width*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_rwidth(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*width*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_stwidth(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*width*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_fill(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*fill*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_time(ccl_private OSLTextureOptions * /*opt*/,
|
|
const float /*time*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_interp_code(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*mode*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_subimage(ccl_private OSLTextureOptions * /*opt*/,
|
|
const int /*subimage*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_subimagename(ccl_private OSLTextureOptions * /*opt*/,
|
|
DeviceString /*subimagename_*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_missingcolor_arena(ccl_private OSLTextureOptions *opt,
|
|
ccl_private float *missing)
|
|
{
|
|
opt->missingcolor = (const float *)missing;
|
|
}
|
|
|
|
ccl_device_extern void osl_texture_set_missingcolor_alpha(ccl_private OSLTextureOptions *opt,
|
|
const int alphaindex,
|
|
const float missingalpha)
|
|
{
|
|
float *m = (float *)(opt)->missingcolor;
|
|
if (m) {
|
|
m[alphaindex] = missingalpha;
|
|
}
|
|
}
|
|
|
|
ccl_device_extern void osl_init_trace_options(ccl_private void * /*oec*/,
|
|
ccl_private void * /*opt*/)
|
|
{
|
|
}
|
|
|
|
ccl_device_extern void osl_trace_set_mindist(ccl_private void * /*opt*/, float /*x*/) {}
|
|
|
|
ccl_device_extern void osl_trace_set_maxdist(ccl_private void * /*opt*/, float /*x*/) {}
|
|
|
|
ccl_device_extern void osl_trace_set_shade(ccl_private void * /*opt*/, int /*x*/) {}
|
|
|
|
ccl_device_extern void osl_trace_set_traceset(ccl_private void * /*opt*/, const DeviceString /*x*/)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#ifndef __KERNEL_GPU__
|
|
CCL_NAMESPACE_END
|
|
#endif
|