/* 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( (reinterpret_cast(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( 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( 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( 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(rs_allocate_closure( sg, sizeof(OSLClosureComponent) + size, alignof(OSLClosureComponent))); if (closure != nullptr) { closure->id = static_cast(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(rs_allocate_closure( sg, sizeof(OSLClosureComponent) + size, alignof(OSLClosureComponent))); if (closure != nullptr) { closure->id = static_cast(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(&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