Files
test/intern/cycles/kernel/osl/services.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1693 lines
54 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
/* TODO(sergey): There is a bit of headers dependency hell going on
* here, so for now we just put here. In the future it might be better
* to have dedicated file for such tweaks.
*/
#if (defined(__GNUC__) && !defined(__clang__)) && defined(NDEBUG)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
# pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#include <cstring>
#include "scene/colorspace.h"
#include "scene/object.h"
#include "util/log.h"
#include "util/string.h"
#include "kernel/device/cpu/image.h"
#include "kernel/osl/globals.h"
#include "kernel/osl/services.h"
#include "kernel/osl/services_shared.h"
#include "kernel/osl/types.h"
#include "kernel/integrator/state.h"
#include "kernel/integrator/state_util.h"
#include "kernel/geom/primitive.h"
#include "kernel/geom/shader_data.h"
#include "kernel/bvh/bvh.h"
#include "kernel/camera/camera.h"
#include "kernel/svm/ao.h"
#include "kernel/svm/bevel.h"
#include "kernel/util/ies.h"
CCL_NAMESPACE_BEGIN
/* RenderServices implementation */
static void copy_matrix(OSL::Matrix44 &m, const Transform &tfm)
{
ProjectionTransform t = projection_transpose(ProjectionTransform(tfm));
memcpy((float *)&m, (const float *)&t, sizeof(m));
}
static void copy_matrix(OSL::Matrix44 &m, const ProjectionTransform &tfm)
{
ProjectionTransform t = projection_transpose(tfm);
memcpy((float *)&m, (const float *)&t, sizeof(m));
}
/* static ustrings */
ustring OSLRenderServices::u_distance("distance");
ustring OSLRenderServices::u_index("index");
ustring OSLRenderServices::u_world("world");
ustring OSLRenderServices::u_camera("camera");
ustring OSLRenderServices::u_screen("screen");
ustring OSLRenderServices::u_raster("raster");
ustring OSLRenderServices::u_ndc("NDC");
ustring OSLRenderServices::u_object_location("object:location");
ustring OSLRenderServices::u_object_color("object:color");
ustring OSLRenderServices::u_object_alpha("object:alpha");
ustring OSLRenderServices::u_object_index("object:index");
ustring OSLRenderServices::u_object_is_light("object:is_light");
ustring OSLRenderServices::u_bump_map_normal("geom:bump_map_normal");
ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated");
ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv");
ustring OSLRenderServices::u_material_index("material:index");
ustring OSLRenderServices::u_object_random("object:random");
ustring OSLRenderServices::u_particle_index("particle:index");
ustring OSLRenderServices::u_particle_random("particle:random");
ustring OSLRenderServices::u_particle_age("particle:age");
ustring OSLRenderServices::u_particle_lifetime("particle:lifetime");
ustring OSLRenderServices::u_particle_location("particle:location");
ustring OSLRenderServices::u_particle_rotation("particle:rotation");
ustring OSLRenderServices::u_particle_size("particle:size");
ustring OSLRenderServices::u_particle_velocity("particle:velocity");
ustring OSLRenderServices::u_particle_angular_velocity("particle:angular_velocity");
ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
ustring OSLRenderServices::u_geom_name("geom:name");
ustring OSLRenderServices::u_geom_undisplaced("geom:undisplaced");
ustring OSLRenderServices::u_is_smooth("geom:is_smooth");
ustring OSLRenderServices::u_is_curve("geom:is_curve");
ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
ustring OSLRenderServices::u_curve_length("geom:curve_length");
ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
ustring OSLRenderServices::u_curve_random("geom:curve_random");
ustring OSLRenderServices::u_is_point("geom:is_point");
ustring OSLRenderServices::u_point_radius("geom:point_radius");
ustring OSLRenderServices::u_point_position("geom:point_position");
ustring OSLRenderServices::u_point_random("geom:point_random");
ustring OSLRenderServices::u_normal_map_normal("geom:normal_map_normal");
ustring OSLRenderServices::u_path_ray_length("path:ray_length");
ustring OSLRenderServices::u_path_ray_depth("path:ray_depth");
ustring OSLRenderServices::u_path_diffuse_depth("path:diffuse_depth");
ustring OSLRenderServices::u_path_glossy_depth("path:glossy_depth");
ustring OSLRenderServices::u_path_transparent_depth("path:transparent_depth");
ustring OSLRenderServices::u_path_transmission_depth("path:transmission_depth");
ustring OSLRenderServices::u_trace("trace");
ustring OSLRenderServices::u_hit("hit");
ustring OSLRenderServices::u_hitdist("hitdist");
ustring OSLRenderServices::u_N("N");
ustring OSLRenderServices::u_Ng("Ng");
ustring OSLRenderServices::u_P("P");
ustring OSLRenderServices::u_I("I");
ustring OSLRenderServices::u_u("u");
ustring OSLRenderServices::u_v("v");
ustring OSLRenderServices::u_empty;
ustring OSLRenderServices::u_sensor_size("cam:sensor_size");
ustring OSLRenderServices::u_image_resolution("cam:image_resolution");
ustring OSLRenderServices::u_aperture_aspect_ratio("cam:aperture_aspect_ratio");
ustring OSLRenderServices::u_aperture_size("cam:aperture_size");
ustring OSLRenderServices::u_aperture_position("cam:aperture_position");
ustring OSLRenderServices::u_focal_distance("cam:focal_distance");
ImageManager *OSLRenderServices::image_manager = nullptr;
OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system, const int device_type)
: OSL::RendererServices(texture_system), device_type_(device_type)
{
}
OSLRenderServices::~OSLRenderServices()
{
if (m_texturesys) {
VLOG_INFO << "OSL texture system stats:\n" << m_texturesys->getstats();
}
}
int OSLRenderServices::supports(string_view feature) const
{
#ifdef WITH_OPTIX
if (feature == "OptiX") {
return device_type_ == DEVICE_OPTIX;
}
#endif
return false;
}
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSL::TransformationPtr xform,
const float time)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
if (globals == nullptr || globals->sd == nullptr) {
return false;
}
/* this is only used for shader and object space, we don't really have
2012-06-09 17:22:52 +00:00
* a concept of shader space, so we just use object space for both. */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
const ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
const int object = sd->object;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
Transform tfm;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (time == sd->time) {
tfm = object_get_transform(kg, sd);
}
else {
tfm = object_fetch_transform_motion_test(kg, object, time, nullptr);
}
#else
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
const Transform tfm = object_get_transform(kg, sd);
#endif
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
copy_matrix(result, tfm);
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return true;
}
return false;
}
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSL::TransformationPtr xform,
const float time)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
if (globals == nullptr || globals->sd == nullptr) {
return false;
}
/* this is only used for shader and object space, we don't really have
2012-06-09 17:22:52 +00:00
* a concept of shader space, so we just use object space for both. */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
const ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
const int object = sd->object;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
Transform itfm;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (time == sd->time) {
itfm = object_get_inverse_transform(kg, sd);
}
else {
object_fetch_transform_motion_test(kg, object, time, &itfm);
}
#else
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
const Transform itfm = object_get_inverse_transform(kg, sd);
#endif
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
copy_matrix(result, itfm);
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return true;
}
return false;
}
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSLUStringHash from,
const float time)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (from == u_ndc) {
copy_matrix(result, kernel_data.cam.ndctoworld);
return true;
}
if (from == u_raster) {
copy_matrix(result, kernel_data.cam.rastertoworld);
return true;
}
if (from == u_screen) {
copy_matrix(result, kernel_data.cam.screentoworld);
return true;
}
if (from == u_camera) {
copy_matrix(result, kernel_data.cam.cameratoworld);
return true;
}
if (from == u_world) {
result.makeIdentity();
return true;
}
return false;
}
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSLUStringHash to,
const float time)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (to == u_ndc) {
copy_matrix(result, kernel_data.cam.worldtondc);
return true;
}
if (to == u_raster) {
copy_matrix(result, kernel_data.cam.worldtoraster);
return true;
}
if (to == u_screen) {
copy_matrix(result, kernel_data.cam.worldtoscreen);
return true;
}
if (to == u_camera) {
copy_matrix(result, kernel_data.cam.worldtocamera);
return true;
}
if (to == u_world) {
result.makeIdentity();
return true;
}
return false;
}
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSL::TransformationPtr xform)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
if (globals == nullptr || globals->sd == nullptr) {
return false;
}
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
const ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
const int object = sd->object;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (object != OBJECT_NONE) {
const Transform tfm = object_get_transform(kg, sd);
copy_matrix(result, tfm);
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return true;
}
return false;
}
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSL::TransformationPtr xform)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
if (globals == nullptr || globals->sd == nullptr) {
return false;
}
/* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
const ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
const int object = sd->object;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (object != OBJECT_NONE) {
const Transform tfm = object_get_inverse_transform(kg, sd);
copy_matrix(result, tfm);
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return true;
}
return false;
}
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSLUStringHash from)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (from == u_ndc) {
copy_matrix(result, kernel_data.cam.ndctoworld);
return true;
}
if (from == u_raster) {
copy_matrix(result, kernel_data.cam.rastertoworld);
return true;
}
if (from == u_screen) {
copy_matrix(result, kernel_data.cam.screentoworld);
return true;
}
if (from == u_camera) {
copy_matrix(result, kernel_data.cam.cameratoworld);
return true;
}
return false;
}
bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
OSL::Matrix44 &result,
OSLUStringHash to)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (to == u_ndc) {
copy_matrix(result, kernel_data.cam.worldtondc);
return true;
}
if (to == u_raster) {
copy_matrix(result, kernel_data.cam.worldtoraster);
return true;
}
if (to == u_screen) {
copy_matrix(result, kernel_data.cam.worldtoscreen);
return true;
}
if (to == u_camera) {
copy_matrix(result, kernel_data.cam.worldtocamera);
return true;
}
return false;
}
bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg,
bool derivatives,
OSLUStringHash object,
const TypeDesc type,
OSLUStringHash name,
const int index,
2012-06-04 22:44:58 +00:00
void *val)
{
return false;
}
template<typename T>
inline bool set_attribute(
const T v, const T dx, const T dy, TypeDesc type, bool derivatives, void *val);
inline void set_data_float(
const float v, const float dx, const float dy, bool derivatives, void *val)
{
float *fval = static_cast<float *>(val);
fval[0] = v;
if (derivatives) {
fval[1] = dx;
fval[2] = dy;
}
}
inline void set_data_float3(
const float3 v, const float3 dx, const float3 dy, bool derivatives, void *val)
{
float *fval = static_cast<float *>(val);
fval[0] = v.x;
fval[1] = v.y;
fval[2] = v.z;
if (derivatives) {
fval[3] = dx.x;
fval[4] = dx.y;
fval[5] = dx.z;
fval[6] = dy.x;
fval[7] = dy.y;
fval[8] = dy.z;
}
}
inline void set_data_float4(
const float4 v, const float4 dx, const float4 dy, bool derivatives, void *val)
{
float *fval = static_cast<float *>(val);
fval[0] = v.x;
fval[1] = v.y;
fval[2] = v.z;
fval[3] = v.w;
if (derivatives) {
fval[4] = dx.x;
fval[5] = dx.y;
fval[6] = dx.z;
fval[7] = dx.w;
fval[8] = dy.x;
fval[9] = dy.y;
fval[10] = dy.z;
fval[11] = dy.w;
}
}
ccl_device_template_spec bool set_attribute(
const float v, const float dx, const float dy, TypeDesc type, bool derivatives, void *val)
{
if (type == TypeFloatArray4) {
set_data_float4(make_float4(v, v, v, 1.0f),
make_float4(dx, dx, dx, 0.0f),
make_float4(dy, dy, dy, 0.0f),
derivatives,
val);
return true;
}
if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
set_data_float3(make_float3(v), make_float3(dx), make_float3(dy), derivatives, val);
return true;
}
if (type == TypeFloat) {
set_data_float(v, dx, dy, derivatives, val);
return true;
}
return false;
}
ccl_device_template_spec bool set_attribute(
const float2 v, const float2 dx, const float2 dy, TypeDesc type, bool derivatives, void *val)
{
if (type == TypeFloatArray4) {
set_data_float4(make_float4(v.x, v.y, 0.0f, 1.0f),
make_float4(dx.x, dx.y, 0.0f, 0.0f),
make_float4(dy.x, dy.y, 0.0f, 0.0f),
derivatives,
val);
return true;
}
if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
set_data_float3(make_float3(v), make_float3(dx), make_float3(dy), derivatives, val);
return true;
}
if (type == TypeFloat) {
set_data_float(average(v), average(dx), average(dy), derivatives, val);
return true;
}
return false;
}
ccl_device_template_spec bool set_attribute(
const float3 v, const float3 dx, const float3 dy, TypeDesc type, bool derivatives, void *val)
{
if (type == TypeFloatArray4) {
set_data_float4(
make_float4(v, 1.0f), make_float4(dx, 0.0f), make_float4(dy, 0.0f), derivatives, val);
return true;
}
if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
set_data_float3(v, dx, dy, derivatives, val);
return true;
}
if (type == TypeFloat) {
set_data_float(average(v), average(dx), average(dy), derivatives, val);
return true;
}
return false;
}
/* Attributes with the TypeRGBA type descriptor should be retrieved and stored
* in a float array of size 4 (e.g. node_vertex_color.osl), this array have
* a type descriptor TypeFloatArray4. If the storage is not a TypeFloatArray4,
* we either store the first three components in a vector, store the average of
* the components in a float, or fail the retrieval and do nothing. We allow
* this for the correct operation of the Attribute node.
*/
ccl_device_template_spec bool set_attribute(
const float4 v, const float4 dx, const float4 dy, TypeDesc type, bool derivatives, void *val)
{
if (type == TypeFloatArray4) {
set_data_float4(v, dx, dy, derivatives, val);
return true;
}
if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
set_data_float3(make_float3(v), make_float3(dx), make_float3(dy), derivatives, val);
return true;
}
if (type == TypeFloat) {
set_data_float(average(make_float3(v)),
average(make_float3(dx)),
average(make_float3(dy)),
derivatives,
val);
return true;
}
return false;
}
template<typename T>
ccl_device_inline bool set_attribute(const T f, const TypeDesc type, bool derivatives, void *val)
{
return set_attribute(f, make_zero<T>(), make_zero<T>(), type, derivatives, val);
}
ccl_device_template_spec bool set_attribute(const int i,
const TypeDesc type,
bool derivatives,
void *val)
{
if (type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
int *ival = (int *)val;
ival[0] = i;
if (derivatives) {
ival[1] = 0;
ival[2] = 0;
}
return true;
}
return false;
}
ccl_device_template_spec bool set_attribute(ustring str,
const TypeDesc type,
bool derivatives,
void *val)
{
if (type.basetype == TypeDesc::STRING && type.aggregate == TypeDesc::SCALAR &&
type.arraylen == 0)
{
ustring *sval = (ustring *)val;
sval[0] = str;
if (derivatives) {
sval[1] = OSLRenderServices::u_empty;
sval[2] = OSLRenderServices::u_empty;
}
return true;
}
return false;
}
static bool set_attribute_float3_3(const float3 P[3], TypeDesc type, bool derivatives, void *val)
{
if (type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
float *fval = (float *)val;
fval[0] = P[0].x;
fval[1] = P[0].y;
fval[2] = P[0].z;
fval[3] = P[1].x;
fval[4] = P[1].y;
fval[5] = P[1].z;
fval[6] = P[2].x;
fval[7] = P[2].y;
fval[8] = P[2].z;
if (type.arraylen > 3) {
memset(fval + 3 * 3, 0, sizeof(float) * 3 * (type.arraylen - 3));
}
if (derivatives) {
memset(fval + type.arraylen * 3, 0, sizeof(float) * 2 * 3 * type.arraylen);
}
return true;
}
return false;
}
static bool set_attribute_matrix(const Transform &tfm, const TypeDesc type, void *val)
{
if (type == TypeMatrix) {
copy_matrix(*(OSL::Matrix44 *)val, tfm);
return true;
}
return false;
}
template<typename T>
inline bool get_object_attribute_impl(const ThreadKernelGlobalsCPU *kg,
ShaderData *sd,
const AttributeDescriptor &desc,
const TypeDesc &type,
bool derivatives,
void *val)
{
T v;
T dx = make_zero<T>();
T dy = make_zero<T>();
#ifdef __VOLUME__
if (primitive_is_volume_attribute(sd, desc)) {
v = primitive_volume_attribute<T>(kg, sd, desc);
}
else
#endif
{
v = primitive_surface_attribute<T>(
kg, sd, desc, derivatives ? &dx : nullptr, derivatives ? &dy : nullptr);
}
return set_attribute(v, dx, dy, type, derivatives, val);
}
static bool get_object_attribute(const ThreadKernelGlobalsCPU *kg,
ShaderData *sd,
const AttributeDescriptor &desc,
const TypeDesc &type,
bool derivatives,
void *val)
{
if (desc.type == NODE_ATTR_FLOAT) {
return get_object_attribute_impl<float>(kg, sd, desc, type, derivatives, val);
}
else if (desc.type == NODE_ATTR_FLOAT2) {
return get_object_attribute_impl<float2>(kg, sd, desc, type, derivatives, val);
}
else if (desc.type == NODE_ATTR_FLOAT3) {
return get_object_attribute_impl<float3>(kg, sd, desc, type, derivatives, val);
}
else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
return get_object_attribute_impl<float4>(kg, sd, desc, type, derivatives, val);
}
else if (desc.type == NODE_ATTR_MATRIX) {
const Transform tfm = primitive_attribute_matrix(kg, desc);
return set_attribute_matrix(tfm, type, val);
}
return false;
}
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
bool OSLRenderServices::get_object_standard_attribute(
ShaderGlobals *globals, OSLUStringHash name, const TypeDesc type, bool derivatives, void *val)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
/* todo: turn this into hash table? */
/* Object Attributes */
if (name == u_object_location) {
const float3 f = object_location(kg, sd);
return set_attribute(f, type, derivatives, val);
}
if (name == u_object_color) {
const float3 f = object_color(kg, sd->object);
return set_attribute(f, type, derivatives, val);
}
if (name == u_object_alpha) {
const float f = object_alpha(kg, sd->object);
return set_attribute(f, type, derivatives, val);
}
if (name == u_object_index) {
const float f = object_pass_id(kg, sd->object);
return set_attribute(f, type, derivatives, val);
}
if (name == u_object_is_light) {
const float f = (sd->type & PRIMITIVE_LAMP) != 0;
return set_attribute(f, type, derivatives, val);
}
if (name == u_geom_dupli_generated) {
const float3 f = object_dupli_generated(kg, sd->object);
return set_attribute(f, type, derivatives, val);
}
if (name == u_geom_dupli_uv) {
const float3 f = object_dupli_uv(kg, sd->object);
return set_attribute(f, type, derivatives, val);
}
if (name == u_material_index) {
const float f = shader_pass_id(kg, sd);
return set_attribute(f, type, derivatives, val);
}
if (name == u_object_random) {
const float f = object_random_number(kg, sd->object);
return set_attribute(f, type, derivatives, val);
}
/* Particle Attributes */
if (name == u_particle_index) {
const int particle_id = object_particle_id(kg, sd->object);
const float f = particle_index(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
if (name == u_particle_random) {
const int particle_id = object_particle_id(kg, sd->object);
const float f = hash_uint2_to_float(particle_index(kg, particle_id), 0);
return set_attribute(f, type, derivatives, val);
}
if (name == u_particle_age) {
const int particle_id = object_particle_id(kg, sd->object);
const float f = particle_age(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
if (name == u_particle_lifetime) {
const int particle_id = object_particle_id(kg, sd->object);
const float f = particle_lifetime(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
if (name == u_particle_location) {
const int particle_id = object_particle_id(kg, sd->object);
const float3 f = particle_location(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
#if 0 /* unsupported */
if (name == u_particle_rotation) {
int particle_id = object_particle_id(kg, sd->object);
float4 f = particle_rotation(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
#endif
if (name == u_particle_size) {
const int particle_id = object_particle_id(kg, sd->object);
const float f = particle_size(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
if (name == u_particle_velocity) {
const int particle_id = object_particle_id(kg, sd->object);
const float3 f = particle_velocity(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
if (name == u_particle_angular_velocity) {
const int particle_id = object_particle_id(kg, sd->object);
const float3 f = particle_angular_velocity(kg, particle_id);
return set_attribute(f, type, derivatives, val);
}
/* Geometry Attributes */
if (name == u_geom_numpolyvertices) {
return set_attribute(3, type, derivatives, val);
}
if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) &&
sd->type & PRIMITIVE_TRIANGLE)
{
float3 P[3];
if (sd->type & PRIMITIVE_MOTION) {
motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P);
}
else {
triangle_vertices(kg, sd->prim, P);
}
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &P[0]);
object_position_transform(kg, sd, &P[1]);
object_position_transform(kg, sd, &P[2]);
}
return set_attribute_float3_3(P, type, derivatives, val);
}
if (name == u_geom_name) {
const ustring object_name = kg->osl.globals->object_names[sd->object];
return set_attribute(object_name, type, derivatives, val);
}
if (name == u_is_smooth) {
const float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
return set_attribute(f, type, derivatives, val);
}
#ifdef __HAIR__
/* Hair Attributes */
if (name == u_is_curve) {
const float f = (sd->type & PRIMITIVE_CURVE) != 0;
return set_attribute(f, type, derivatives, val);
}
if (name == u_curve_thickness) {
const float f = curve_thickness(kg, sd);
return set_attribute(f, type, derivatives, val);
}
if (name == u_curve_tangent_normal) {
const float3 f = curve_tangent_normal(kg, sd);
return set_attribute(f, type, derivatives, val);
}
if (name == u_curve_random) {
const float f = curve_random(kg, sd);
return set_attribute(f, type, derivatives, val);
}
#endif
#ifdef __POINTCLOUD__
/* point attributes */
if (name == u_is_point) {
const float f = (sd->type & PRIMITIVE_POINT) != 0;
return set_attribute(f, type, derivatives, val);
}
if (name == u_point_radius) {
const float f = point_radius(kg, sd);
return set_attribute(f, type, derivatives, val);
}
if (name == u_point_position) {
const float3 f = point_position(kg, sd);
return set_attribute(f, type, derivatives, val);
}
if (name == u_point_random) {
const float f = point_random(kg, sd);
return set_attribute(f, type, derivatives, val);
}
#endif
if (name == u_normal_map_normal) {
if (sd->type & PRIMITIVE_TRIANGLE) {
const float3 f = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
return set_attribute(f, type, derivatives, val);
}
return false;
}
if (name == u_bump_map_normal) {
float3 f[3];
if (!attribute_bump_map_normal(kg, sd, f)) {
return false;
}
return set_attribute(f[0], f[1], f[2], type, derivatives, val);
}
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return get_background_attribute(globals, name, type, derivatives, val);
}
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
bool OSLRenderServices::get_background_attribute(
ShaderGlobals *globals, OSLUStringHash name, const TypeDesc type, bool derivatives, void *val)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
const IntegratorStateCPU *state = globals->path_state;
const IntegratorShadowStateCPU *shadow_state = globals->shadow_path_state;
if (name == u_path_ray_length) {
/* Ray Length */
const float f = sd->ray_length;
return set_attribute(f, type, derivatives, val);
}
#define READ_PATH_STATE(elem) \
((state != nullptr) ? state->path.elem : \
(shadow_state != nullptr) ? shadow_state->shadow_path.elem : \
0)
if (name == u_path_ray_depth) {
/* Ray Depth */
int f = READ_PATH_STATE(bounce);
/* Read bounce from different locations depending on if this is a shadow path. For background,
* light emission and shadow evaluation from a surface or volume we are effectively one bounce
* further. */
if (globals->raytype & (PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
f += 1;
}
return set_attribute(f, type, derivatives, val);
}
if (name == u_path_diffuse_depth) {
/* Diffuse Ray Depth */
const int f = READ_PATH_STATE(diffuse_bounce);
return set_attribute(f, type, derivatives, val);
}
if (name == u_path_glossy_depth) {
/* Glossy Ray Depth */
const int f = READ_PATH_STATE(glossy_bounce);
return set_attribute(f, type, derivatives, val);
}
if (name == u_path_transmission_depth) {
/* Transmission Ray Depth */
const int f = READ_PATH_STATE(transmission_bounce);
return set_attribute(f, type, derivatives, val);
}
if (name == u_path_transparent_depth) {
/* Transparent Ray Depth */
const int f = READ_PATH_STATE(transparent_bounce);
return set_attribute(f, type, derivatives, val);
}
#undef READ_PATH_STATE
if (name == u_ndc) {
2021-02-05 16:23:34 +11:00
/* NDC coordinates with special exception for orthographic projection. */
float3 ndc[3];
if ((globals->raytype & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
{
ndc[0] = camera_world_to_ndc(kg, sd, sd->ray_P);
if (derivatives) {
ndc[1] = zero_float3();
ndc[2] = zero_float3();
}
}
else {
ndc[0] = camera_world_to_ndc(kg, sd, sd->P);
if (derivatives) {
const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
ndc[1] = camera_world_to_ndc(kg, sd, sd->P + dP.dx) - ndc[0];
ndc[2] = camera_world_to_ndc(kg, sd, sd->P + dP.dy) - ndc[0];
}
}
return set_attribute(ndc[0], ndc[1], ndc[2], type, derivatives, val);
}
return false;
}
bool OSLRenderServices::get_camera_attribute(
ShaderGlobals *globals, OSLUStringHash name, TypeDesc type, bool derivatives, void *val)
{
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (name == u_sensor_size) {
const float2 sensor = make_float2(kernel_data.cam.sensorwidth, kernel_data.cam.sensorheight);
return set_attribute(sensor, type, derivatives, val);
}
else if (name == u_image_resolution) {
const float2 image = make_float2(kernel_data.cam.width, kernel_data.cam.height);
return set_attribute(image, type, derivatives, val);
}
else if (name == u_aperture_aspect_ratio) {
return set_attribute(1.0f / kernel_data.cam.inv_aperture_ratio, type, derivatives, val);
}
else if (name == u_aperture_size) {
return set_attribute(kernel_data.cam.aperturesize, type, derivatives, val);
}
else if (name == u_aperture_position) {
/* The random numbers for aperture sampling are packed into N. */
const float2 rand_lens = make_float2(globals->N.x, globals->N.y);
const float2 pos = camera_sample_aperture(&kernel_data.cam, rand_lens);
return set_attribute(pos * kernel_data.cam.aperturesize, type, derivatives, val);
}
else if (name == u_focal_distance) {
return set_attribute(kernel_data.cam.focaldistance, type, derivatives, val);
}
return false;
}
bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
bool derivatives,
OSLUStringHash object_name,
const TypeDesc type,
OSLUStringHash name,
2012-06-04 22:44:58 +00:00
void *val)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
if (globals == nullptr) {
return false;
}
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (sd == nullptr) {
/* Camera shader. */
return get_camera_attribute(globals, name, type, derivatives, val);
}
/* lookup of attribute on another object */
int object;
if (object_name != u_empty) {
const OSLGlobals::ObjectNameMap::iterator it = kg->osl.globals->object_name_map.find(
object_name);
if (it == kg->osl.globals->object_name_map.end()) {
return false;
}
object = it->second;
}
else {
object = sd->object;
}
/* find attribute on object */
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name.hash());
if (desc.offset != ATTR_STD_NOT_FOUND) {
return get_object_attribute(kg, sd, desc, type, derivatives, val);
}
/* not found in attribute, check standard object info */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return get_object_standard_attribute(globals, name, type, derivatives, val);
}
bool OSLRenderServices::get_userdata(
bool derivatives, OSLUStringHash name, const TypeDesc type, OSL::ShaderGlobals *sg, void *val)
{
return false; /* disabled by lockgeom */
}
OSL::TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(
OSLUStringHash filename, OSL::ShadingContext *context, const OSL::TextureOpt *opt)
{
return get_texture_handle(to_ustring(filename), context, opt);
}
OSL::TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(
OSL::ustring filename, OSL::ShadingContext * /*context*/, const OSL::TextureOpt * /*options*/)
{
OSLTextureHandleMap::iterator it = textures.find(filename);
if (device_type_ == DEVICE_CPU) {
/* For non-OIIO textures, just return a pointer to our own OSLTextureHandle. */
if (it != textures.end()) {
if (it->second.type != OSLTextureHandle::OIIO) {
return (OSL::TextureSystem::TextureHandle *)(&it->second);
}
}
/* Get handle from OpenImageIO. */
OSL::TextureSystem *ts = m_texturesys;
OSL::TextureSystem::TextureHandle *handle = ts->get_texture_handle(to_ustring(filename));
if (handle == nullptr) {
return nullptr;
}
/* Insert new OSLTextureHandle if needed. */
if (it == textures.end()) {
textures.insert(filename, OSLTextureHandle(OSLTextureHandle::OIIO));
it = textures.find(filename);
}
/* Assign OIIO texture handle and return.
* OIIO::unordered_map_concurrent always returns a const handle even if the underlying
* std::unordered_map supports updating values just fine. */
const_cast<OSLTextureHandle &>(it->second).oiio_handle = handle;
return (OSL::TextureSystem::TextureHandle *)(&it->second);
}
/* Construct GPU texture handle for existing textures. */
if (it != textures.end()) {
switch (it->second.type) {
case OSLTextureHandle::OIIO:
return nullptr;
case OSLTextureHandle::SVM:
if (!it->second.handle.empty() && it->second.handle.get_manager() != image_manager) {
it.clear();
break;
}
return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
it->second.svm_slots[0].y);
case OSLTextureHandle::IES:
if (!it->second.handle.empty() && it->second.handle.get_manager() != image_manager) {
it.clear();
break;
}
return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_IES |
it->second.svm_slots[0].y);
case OSLTextureHandle::AO:
return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(
OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL | 1);
case OSLTextureHandle::BEVEL:
return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(
OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL | 2);
}
}
if (!image_manager) {
return nullptr;
}
/* Load new textures using SVM image manager. */
const ImageHandle handle = image_manager->add_image(filename.string(), ImageParams());
if (handle.empty()) {
return nullptr;
}
if (!textures.insert(filename, OSLTextureHandle(handle))) {
return nullptr;
}
return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
handle.svm_slot());
}
bool OSLRenderServices::good(OSL::TextureSystem::TextureHandle *texture_handle)
{
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
if (handle->oiio_handle) {
OSL::TextureSystem *ts = m_texturesys;
return ts->good(handle->oiio_handle);
}
return true;
}
bool OSLRenderServices::texture(OSLUStringHash filename,
TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
OSL::TextureOpt &options,
OSL::ShaderGlobals *sg,
float s,
float t,
const float dsdx,
const float dtdx,
const float dsdy,
const float dtdy,
const int nchannels,
float *result,
float *dresultds,
float *dresultdt,
OSLUStringHash *errormessage)
{
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
const OSLTextureHandle::Type texture_type = (handle) ? handle->type : OSLTextureHandle::OIIO;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kernel_globals = globals->kg;
const IntegratorStateCPU *state = globals->path_state;
bool status = false;
switch (texture_type) {
case OSLTextureHandle::BEVEL: {
#ifdef __SHADER_RAYTRACE__
/* Bevel shader hack. */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (nchannels >= 3 && state != nullptr) {
const int num_samples = (int)s;
const float radius = t;
const float3 N = svm_bevel(kernel_globals, state, sd, radius, num_samples);
result[0] = N.x;
result[1] = N.y;
result[2] = N.z;
status = true;
}
#endif
break;
}
case OSLTextureHandle::AO: {
#ifdef __SHADER_RAYTRACE__
/* AO shader hack. */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
if (state != nullptr) {
const int num_samples = (int)s;
const float radius = t;
const float3 N = make_float3(dsdx, dtdx, dsdy);
int flags = 0;
if ((int)dtdy) {
flags |= NODE_AO_INSIDE;
}
if ((int)options.sblur) {
flags |= NODE_AO_ONLY_LOCAL;
}
if ((int)options.tblur) {
flags |= NODE_AO_GLOBAL_RADIUS;
}
result[0] = svm_ao(kernel_globals, state, sd, N, radius, num_samples, flags);
status = true;
}
#endif
break;
Cycles: Add Support for IES files as textures for light strength This patch adds support for IES files, a file format that is commonly used to store the directional intensity distribution of light sources. The new IES node is supposed to be plugged into the Strength input of the Emission node of the lamp. Since people generating IES files do not really seem to care about the standard, the parser is flexible enough to accept all test files I have tried. Some common weirdnesses are distributing values over multiple lines that should go into one line, using commas instead of spaces as delimiters and adding various useless stuff at the end of the file. The user interface of the node is similar to the script node, the user can either select an internal Text or load a file. Internally, IES files are handled similar to Image textures: They are stored in slots by the LightManager and each unique IES is assigned to one slot. The local coordinate system of the lamp is used, so that the direction of the light can be changed. For UI reasons, it's usually best to add an area light, rotate it and then change its type, since especially the point light does not immediately show its local coordinate system in the viewport. Reviewers: #cycles, dingto, sergey, brecht Reviewed By: #cycles, dingto, brecht Subscribers: OgDEV, crazyrobinhood, secundar, cardboard, pisuke, intrah, swerner, micah_denn, harvester, gottfried, disnel, campbellbarton, duarteframos, Lapineige, brecht, juicyfruit, dingto, marek, rickyblender, bliblubli, lockal, sergey Differential Revision: https://developer.blender.org/D1543
2018-05-27 00:46:37 +02:00
}
case OSLTextureHandle::SVM: {
int id = -1;
if (handle->svm_slots[0].w == -1) {
/* Packed single texture. */
id = handle->svm_slots[0].y;
}
else {
/* Packed tiled texture. */
const int tx = (int)s;
const int ty = (int)t;
const int tile = 1001 + 10 * ty + tx;
for (const int4 &tile_node : handle->svm_slots) {
if (tile_node.x == tile) {
id = tile_node.y;
break;
}
if (tile_node.z == tile) {
id = tile_node.w;
break;
}
}
s -= tx;
t -= ty;
}
float4 rgba;
if (id == -1) {
rgba = make_float4(
TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
}
else {
rgba = kernel_tex_image_interp(kernel_globals, id, s, 1.0f - t);
}
result[0] = rgba[0];
if (nchannels > 1) {
result[1] = rgba[1];
}
if (nchannels > 2) {
result[2] = rgba[2];
}
if (nchannels > 3) {
result[3] = rgba[3];
}
status = true;
break;
}
case OSLTextureHandle::IES: {
/* IES light. */
result[0] = kernel_ies_interp(kernel_globals, handle->svm_slots[0].y, s, t);
status = true;
break;
}
case OSLTextureHandle::OIIO: {
/* OpenImageIO texture cache. */
OSL::TextureSystem *ts = m_texturesys;
if (handle && handle->oiio_handle) {
if (texture_thread_info == nullptr) {
texture_thread_info = kernel_globals->osl.oiio_thread_info;
}
status = ts->texture(handle->oiio_handle,
texture_thread_info,
options,
s,
t,
dsdx,
dtdx,
dsdy,
dtdy,
nchannels,
result,
dresultds,
dresultdt);
}
else {
status = ts->texture(to_ustring(filename),
options,
s,
t,
dsdx,
dtdx,
dsdy,
dtdy,
nchannels,
result,
dresultds,
dresultdt);
}
if (!status) {
/* This might be slow, but prevents error messages leak and
* other nasty stuff happening. */
ts->geterror();
}
else if (handle && handle->processor) {
ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
}
break;
}
}
if (!status) {
if (nchannels == 3 || nchannels == 4) {
result[0] = 1.0f;
result[1] = 0.0f;
result[2] = 1.0f;
if (nchannels == 4) {
result[3] = 1.0f;
}
}
}
return status;
}
bool OSLRenderServices::texture3d(OSLUStringHash filename,
TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
OSL::TextureOpt &options,
OSL::ShaderGlobals *sg,
const OSL::Vec3 &P,
const OSL::Vec3 &dPdx,
const OSL::Vec3 &dPdy,
const OSL::Vec3 &dPdz,
const int nchannels,
float *result,
float *dresultds,
float *dresultdt,
float *dresultdr,
OSLUStringHash *errormessage)
{
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
const OSLTextureHandle::Type texture_type = (handle) ? handle->type : OSLTextureHandle::OIIO;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
const ThreadKernelGlobalsCPU *kernel_globals = globals->kg;
bool status = false;
switch (texture_type) {
case OSLTextureHandle::SVM: {
/* Packed texture. */
const int slot = handle->svm_slots[0].y;
const float3 P_float3 = make_float3(P.x, P.y, P.z);
float4 rgba = kernel_tex_image_interp_3d(kernel_globals, slot, P_float3, INTERPOLATION_NONE);
result[0] = rgba[0];
if (nchannels > 1) {
result[1] = rgba[1];
}
if (nchannels > 2) {
result[2] = rgba[2];
}
if (nchannels > 3) {
result[3] = rgba[3];
}
status = true;
break;
}
case OSLTextureHandle::OIIO: {
/* OpenImageIO texture cache. */
OSL::TextureSystem *ts = m_texturesys;
if (handle && handle->oiio_handle) {
if (texture_thread_info == nullptr) {
texture_thread_info = kernel_globals->osl.oiio_thread_info;
}
status = ts->texture3d(handle->oiio_handle,
texture_thread_info,
options,
P,
dPdx,
dPdy,
dPdz,
nchannels,
result,
dresultds,
dresultdt,
dresultdr);
}
else {
status = ts->texture3d(to_ustring(filename),
options,
P,
dPdx,
dPdy,
dPdz,
nchannels,
result,
dresultds,
dresultdt,
dresultdr);
}
if (!status) {
/* This might be slow, but prevents error messages leak and
* other nasty stuff happening. */
ts->geterror();
}
else if (handle && handle->processor) {
ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
}
break;
}
case OSLTextureHandle::IES:
case OSLTextureHandle::AO:
case OSLTextureHandle::BEVEL: {
status = false;
break;
}
}
if (!status) {
if (nchannels == 3 || nchannels == 4) {
result[0] = 1.0f;
result[1] = 0.0f;
result[2] = 1.0f;
if (nchannels == 4) {
result[3] = 1.0f;
}
}
}
return status;
}
bool OSLRenderServices::environment(OSLUStringHash filename,
TextureHandle *texture_handle,
TexturePerthread *thread_info,
OSL::TextureOpt &options,
OSL::ShaderGlobals *sg,
const OSL::Vec3 &R,
const OSL::Vec3 &dRdx,
const OSL::Vec3 &dRdy,
const int nchannels,
float *result,
float *dresultds,
float *dresultdt,
OSLUStringHash *errormessage)
{
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
OSL::TextureSystem *ts = m_texturesys;
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
bool status = false;
if (handle && handle->oiio_handle) {
if (thread_info == nullptr) {
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
thread_info = globals->kg->osl.oiio_thread_info;
}
status = ts->environment(handle->oiio_handle,
thread_info,
options,
R,
dRdx,
dRdy,
nchannels,
result,
dresultds,
dresultdt);
}
else {
status = ts->environment(
to_ustring(filename), options, R, dRdx, dRdy, nchannels, result, dresultds, dresultdt);
}
if (!status) {
if (nchannels == 3 || nchannels == 4) {
result[0] = 1.0f;
result[1] = 0.0f;
result[2] = 1.0f;
if (nchannels == 4) {
result[3] = 1.0f;
}
}
}
else if (handle && handle->processor) {
ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
}
return status;
}
bool OSLRenderServices::get_texture_info(OSLUStringHash filename,
TextureHandle *texture_handle,
TexturePerthread *texture_thread_info,
OSL::ShaderGlobals * /*sg*/,
const int subimage,
OSLUStringHash dataname,
const TypeDesc datatype,
void *data,
OSLUStringHash * /*errormessage*/)
{
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
OSL::TextureSystem *ts = m_texturesys;
if (handle) {
/* No texture info for other texture types. */
if (handle->type != OSLTextureHandle::OIIO) {
return false;
}
if (handle->oiio_handle) {
/* Get texture info from OpenImageIO. */
return ts->get_texture_info(handle->oiio_handle,
texture_thread_info,
subimage,
to_ustring(dataname),
datatype,
data);
}
}
/* Get texture info from OpenImageIO, slower using filename. */
return ts->get_texture_info(
to_ustring(filename), subimage, to_ustring(dataname), datatype, data);
}
int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg,
OSLUStringHash filename,
const OSL::Vec3 &center,
const float radius,
const int max_points,
2012-09-14 23:11:47 +00:00
bool sort,
#if OSL_LIBRARY_VERSION_CODE >= 11400
int *indices,
#else
2012-09-14 23:11:47 +00:00
size_t *out_indices,
#endif
2012-09-14 23:11:47 +00:00
float *out_distances,
const int derivs_offset)
{
2012-09-14 23:11:47 +00:00
return 0;
}
int OSLRenderServices::pointcloud_get(OSL::ShaderGlobals *sg,
OSLUStringHash filename,
#if OSL_LIBRARY_VERSION_CODE >= 11400
const int *indices,
#else
size_t *indices,
#endif
const int count,
OSLUStringHash attr_name,
const TypeDesc attr_type,
2012-09-14 23:11:47 +00:00
void *out_data)
{
2012-09-14 23:11:47 +00:00
return 0;
}
bool OSLRenderServices::pointcloud_write(OSL::ShaderGlobals *sg,
OSLUStringHash filename,
const OSL::Vec3 &pos,
const int nattribs,
const OSLUStringRep *names,
const TypeDesc *types,
const void **data)
{
return false;
}
bool OSLRenderServices::trace(TraceOpt &options,
OSL::ShaderGlobals *sg,
const OSL::Vec3 &P,
const OSL::Vec3 &dPdx,
const OSL::Vec3 &dPdy,
const OSL::Vec3 &R,
const OSL::Vec3 &dRdx,
const OSL::Vec3 &dRdy)
{
/* todo: options.shader support, maybe options.traceset */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
ShaderData *sd = globals->sd;
const ThreadKernelGlobalsCPU *kg = globals->kg;
if (sd == nullptr) {
return false;
}
/* setup ray */
Ray ray;
ray.P = make_float3(P.x, P.y, P.z);
ray.D = make_float3(R.x, R.y, R.z);
ray.tmin = 0.0f;
ray.tmax = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
ray.time = sd->time;
ray.self.object = OBJECT_NONE;
ray.self.prim = PRIM_NONE;
ray.self.light_object = OBJECT_NONE;
ray.self.light_prim = PRIM_NONE;
if (options.mindist == 0.0f) {
/* avoid self-intersections */
if (ray.P == sd->P) {
ray.self.object = sd->object;
ray.self.prim = sd->prim;
}
}
else {
/* offset for minimum distance */
ray.P += options.mindist * ray.D;
}
/* ray differentials */
differential3 dP;
dP.dx = make_float3(dPdx.x, dPdx.y, dPdx.z);
dP.dy = make_float3(dPdy.x, dPdy.y, dPdy.z);
ray.dP = differential_make_compact(dP);
differential3 dD;
dD.dx = make_float3(dRdx.x, dRdx.y, dRdx.z);
dD.dy = make_float3(dRdy.x, dRdy.y, dRdy.z);
ray.dD = differential_make_compact(dD);
/* allocate trace data */
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
OSLTraceData *tracedata = globals->tracedata;
tracedata->ray = ray;
tracedata->setup = false;
tracedata->init = true;
tracedata->hit = false;
2022-06-30 12:14:22 +10:00
/* Can't ray-trace from shaders like displacement, before BVH exists. */
if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
return false;
}
2022-06-30 12:14:22 +10:00
/* Ray-trace, leaving out shadow opaque to avoid early exit. */
const uint visibility = PATH_RAY_ALL_VISIBILITY - PATH_RAY_SHADOW_OPAQUE;
tracedata->hit = scene_intersect(kg, &ray, visibility, &tracedata->isect);
return tracedata->hit;
}
bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg,
OSLUStringHash source,
OSLUStringHash name,
const TypeDesc type,
void *val,
bool derivatives)
{
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
const ThreadKernelGlobalsCPU *kg = globals->kg;
OSLTraceData *tracedata = globals->tracedata;
if (source == u_trace && tracedata->init) {
if (name == u_hit) {
return set_attribute<int>(tracedata->hit, type, derivatives, val);
}
if (tracedata->hit) {
if (name == u_hitdist) {
return set_attribute(tracedata->isect.t, type, derivatives, val);
}
ShaderData *sd = &tracedata->sd;
if (!tracedata->setup) {
/* lazy shader data setup */
shader_setup_from_ray(kg, sd, &tracedata->ray, &tracedata->isect);
tracedata->setup = true;
}
if (name == u_N) {
return set_attribute(sd->N, type, derivatives, val);
}
if (name == u_Ng) {
return set_attribute(sd->Ng, type, derivatives, val);
}
if (name == u_P) {
const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
return set_attribute(sd->P, dP.dx, dP.dy, type, derivatives, val);
}
if (name == u_I) {
const differential3 dI = differential_from_compact(sd->wi, sd->dI);
return set_attribute(sd->wi, dI.dx, dI.dy, type, derivatives, val);
}
if (name == u_u) {
return set_attribute(sd->u, sd->du.dx, sd->du.dy, type, derivatives, val);
}
if (name == u_v) {
return set_attribute(sd->v, sd->dv.dx, sd->dv.dy, type, derivatives, val);
}
Cycles: Refactor: Store Cycles-specific pointers in our own ShaderGlobals OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
2025-01-28 03:39:00 +01:00
return get_attribute(sg, derivatives, u_empty, type, name, val);
}
}
return false;
}
CCL_NAMESPACE_END