mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Fix #157384: Cycles attribute breaks under certain conditions
Caused by 4d6c7718c5.
Under certain conditions it is possible that the offset logic in the
AttributeTableBuilder::add() assigns offset of -1. This value just
happens to match ATTR_STD_NOT_FOUND, leading to false-positive check
that attribute is not found (for example, svm_node_attr_init() that
checks desc.offset != ATTR_STD_NOT_FOUND.
The simplest solution is to tweak the value of the ATTR_STD_NOT_FOUND
to make it very big negative value.
There is now an utility function to check whether AttributeDescriptor
points to an attribute that is found, to help possibly tweaking this
check in the future, and to make code a bit more semantically clear.
Pull Request: https://projects.blender.org/blender/blender/pulls/157410
This commit is contained in:
parent
50b08224cd
commit
dcac328db3
18 changed files with 39 additions and 32 deletions
|
|
@ -21,6 +21,11 @@ CCL_NAMESPACE_BEGIN
|
|||
* Lookup of attributes is different between OSL and SVM, as OSL is ustring
|
||||
* based while for SVM we use integer ids. */
|
||||
|
||||
ccl_device_forceinline bool is_attribute_found(const ccl_private AttributeDescriptor &desc)
|
||||
{
|
||||
return desc.offset != ATTR_STD_NOT_FOUND;
|
||||
}
|
||||
|
||||
ccl_device_inline AttributeDescriptor attribute_not_found()
|
||||
{
|
||||
const AttributeDescriptor desc = {ATTR_ELEMENT_NONE, (NodeAttributeType)0, ATTR_STD_NOT_FOUND};
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ ccl_device float curve_random(KernelGlobals kg, const ccl_private ShaderData *sd
|
|||
{
|
||||
if (sd->type & PRIMITIVE_CURVE) {
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_CURVE_RANDOM);
|
||||
return (desc.offset != ATTR_STD_NOT_FOUND) ? curve_attribute<float>(kg, sd, desc) : 0.0f;
|
||||
return is_attribute_found(desc) ? curve_attribute<float>(kg, sd, desc) : 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ ccl_device float point_random(KernelGlobals kg, const ccl_private ShaderData *sd
|
|||
{
|
||||
if (sd->type & PRIMITIVE_POINT) {
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POINT_RANDOM);
|
||||
return (desc.offset != ATTR_STD_NOT_FOUND) ? point_attribute<float>(kg, sd, desc) : 0.0f;
|
||||
return is_attribute_found(desc) ? point_attribute<float>(kg, sd, desc) : 0.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ ccl_device void primitive_normal_set_undisplaced(KernelGlobals kg,
|
|||
|
||||
if (sd->shader & SHADER_SMOOTH_NORMAL) {
|
||||
const AttributeDescriptor ndesc = find_attribute(kg, sd, ATTR_STD_NORMAL_UNDISPLACED);
|
||||
if (ndesc.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(ndesc)) {
|
||||
return;
|
||||
}
|
||||
N = safe_normalize(primitive_surface_attribute<float3>(kg, sd, ndesc));
|
||||
|
|
@ -112,7 +112,7 @@ ccl_device_forceinline float3 primitive_uv(KernelGlobals kg, const ccl_private S
|
|||
{
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
|
||||
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(desc)) {
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ ccl_device bool primitive_ptex(KernelGlobals kg,
|
|||
const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
|
||||
const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
|
||||
|
||||
if (desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(desc_face_id) || !is_attribute_found(desc_uv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ ccl_device Float3Type primitive_tangent(KernelGlobals kg, ccl_private ShaderData
|
|||
/* try to create spherical tangent from generated coordinates */
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED);
|
||||
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
if constexpr (is_dual_v<Float3Type>) {
|
||||
dual3 data = primitive_surface_attribute<dual3>(kg, sd, desc);
|
||||
data = make_float3(-(data.y() - 0.5f), (data.x() - 0.5f), dual1());
|
||||
|
|
@ -224,7 +224,7 @@ ccl_device_forceinline float4 primitive_motion_vector(KernelGlobals kg,
|
|||
/* deformation motion */
|
||||
AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
/* get motion info */
|
||||
const int numverts = kernel_data_fetch(objects, sd->object).numverts;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ ccl_device_inline Float3Type volume_normalized_position(KernelGlobals kg,
|
|||
|
||||
object_inverse_position_transform_if_object(kg, sd, &P);
|
||||
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
const Transform tfm = primitive_attribute_matrix(kg, desc);
|
||||
P = transform_point(&tfm, P);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ ccl_device_inline void volume_shader_motion_blur(KernelGlobals kg,
|
|||
}
|
||||
|
||||
const AttributeDescriptor v_desc = find_attribute(kg, sd, ATTR_STD_VOLUME_VELOCITY);
|
||||
kernel_assert(v_desc.offset != ATTR_STD_NOT_FOUND);
|
||||
kernel_assert(is_attribute_found(v_desc));
|
||||
|
||||
const float3 P = sd->P;
|
||||
const float velocity_scale = kernel_data_fetch(objects, sd->object).velocity_scale;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
|
|||
#lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr);
|
||||
|
||||
#include "closures_template.h"
|
||||
|
||||
ss->register_closure(
|
||||
"layer", OSL_CLOSURE_LAYER_ID, osl_closure_layer_params(), nullptr, nullptr);
|
||||
}
|
||||
|
|
@ -135,7 +136,7 @@ void osl_eval_nodes_surface(const ThreadKernelGlobalsCPU *kg,
|
|||
/* set state as if undisplaced */
|
||||
if (sd->flag & SD_HAS_DISPLACEMENT) {
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
|
||||
kernel_assert(desc.offset != ATTR_STD_NOT_FOUND);
|
||||
kernel_assert(is_attribute_found(desc));
|
||||
|
||||
dual3 P = primitive_surface_attribute<dual3>(kg, sd, desc);
|
||||
object_position_transform(kg, sd, &P);
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ ccl_device void flatten_closure_tree(KernelGlobals kg,
|
|||
break; \
|
||||
}
|
||||
#include "closures_template.h"
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -218,7 +219,7 @@ ccl_device_inline void osl_eval_nodes(KernelGlobals kg,
|
|||
/* Set position state as if undisplaced. */
|
||||
if (sd->flag & SD_HAS_DISPLACEMENT) {
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
|
||||
kernel_assert(desc.offset != ATTR_STD_NOT_FOUND);
|
||||
kernel_assert(is_attribute_found(desc));
|
||||
|
||||
dual3 P = primitive_surface_attribute<dual3>(kg, sd, desc);
|
||||
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ bool OSLRenderServices::get_attribute(ShaderGlobals *globals,
|
|||
|
||||
/* find attribute on object */
|
||||
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name.hash());
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
return osl_shared_get_object_attribute(kg, sd, desc, type, derivatives, val);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ ccl_device_extern bool osl_get_attribute(ccl_private ShaderGlobals *sg,
|
|||
const int object = sd->object;
|
||||
|
||||
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name);
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
return osl_shared_get_object_attribute(kg, sd, desc, type, derivatives, res);
|
||||
}
|
||||
return osl_shared_get_object_standard_attribute(kg, sg, sd, name, type, derivatives, res);
|
||||
|
|
|
|||
|
|
@ -1179,7 +1179,7 @@ ccl_device_inline bool osl_shared_get_object_standard_attribute(KernelGlobals kg
|
|||
if (sd->type & PRIMITIVE_TRIANGLE) {
|
||||
const AttributeDescriptor desc = find_attribute(
|
||||
kg, sd->object, sd->prim, ATTR_STD_NORMAL_UNDISPLACED);
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
return osl_shared_get_object_attribute(kg, sd, desc, type, derivatives, val);
|
||||
}
|
||||
const float3 f = triangle_smooth_normal_unnormalized_object_space(kg, sd);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals kg,
|
|||
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
desc = find_attribute(kg, sd, node.attr);
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(desc)) {
|
||||
desc = attribute_not_found();
|
||||
desc.offset = 0;
|
||||
desc.type = (NodeAttributeType)node.output_type;
|
||||
|
|
@ -85,7 +85,7 @@ svm_node_attr_surface_eval(KernelGlobals kg,
|
|||
return uv;
|
||||
}
|
||||
|
||||
if (node.attr == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
|
||||
if (node.attr == ATTR_STD_GENERATED && !is_attribute_found(desc)) {
|
||||
Float3Type f = shading_position<Float3Type>(sd);
|
||||
object_inverse_position_transform_if_object(kg, sd, &f);
|
||||
return f;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ ccl_device_noinline void svm_node_enter_bump_eval(KernelGlobals kg,
|
|||
|
||||
/* Set position as if undisplaced. */
|
||||
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
|
||||
if (desc.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(desc)) {
|
||||
dual3 attr = primitive_surface_attribute<dual3>(kg, sd, desc);
|
||||
object_position_transform(kg, sd, &attr);
|
||||
|
||||
|
|
|
|||
|
|
@ -858,7 +858,7 @@ ccl_device
|
|||
|
||||
const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, hdata.attr_random);
|
||||
float random = 0.0f;
|
||||
if (attr_descr_random.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(attr_descr_random)) {
|
||||
random = primitive_surface_attribute<float>(kg, sd, attr_descr_random);
|
||||
}
|
||||
else {
|
||||
|
|
@ -1263,7 +1263,7 @@ ccl_device_noinline void svm_node_principled_volume(
|
|||
if (density > 0.0f) {
|
||||
/* Density and color attribute lookup if available. */
|
||||
const AttributeDescriptor attr_density = find_attribute(kg, sd, node.attr_density);
|
||||
if (attr_density.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(attr_density)) {
|
||||
primitive_density = primitive_volume_attribute<float>(kg, sd, attr_density, true);
|
||||
density = fmaxf(density * primitive_density, 0.0f);
|
||||
}
|
||||
|
|
@ -1274,7 +1274,7 @@ ccl_device_noinline void svm_node_principled_volume(
|
|||
Spectrum color = closure_weight;
|
||||
|
||||
const AttributeDescriptor attr_color = find_attribute(kg, sd, node.attr_color);
|
||||
if (attr_color.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(attr_color)) {
|
||||
color *= rgb_to_spectrum(primitive_volume_attribute<float3>(kg, sd, attr_color, true));
|
||||
}
|
||||
|
||||
|
|
@ -1317,7 +1317,7 @@ ccl_device_noinline void svm_node_principled_volume(
|
|||
|
||||
/* Add flame temperature from attribute if available. */
|
||||
const AttributeDescriptor attr_temperature = find_attribute(kg, sd, node.attr_temperature);
|
||||
if (attr_temperature.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(attr_temperature)) {
|
||||
const float temperature = primitive_volume_attribute<float>(kg, sd, attr_temperature, true);
|
||||
T *= fmaxf(temperature, 0.0f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ ccl_device_noinline void svm_node_vector_displacement(
|
|||
|
||||
const AttributeDescriptor attr = find_attribute(kg, sd, node.attr);
|
||||
float3 tangent;
|
||||
if (attr.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(attr)) {
|
||||
tangent = primitive_surface_attribute<float3>(kg, sd, attr);
|
||||
}
|
||||
else {
|
||||
|
|
@ -174,7 +174,7 @@ ccl_device_noinline void svm_node_vector_displacement(
|
|||
|
||||
float3 bitangent = safe_normalize(cross(normal, tangent));
|
||||
const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.attr_sign);
|
||||
if (attr_sign.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(attr_sign)) {
|
||||
const float sign = primitive_surface_attribute<float>(kg, sd, attr_sign);
|
||||
bitangent *= sign;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
|||
const AttributeDescriptor attr = find_attribute(kg, sd, node.attr);
|
||||
const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.attr_sign);
|
||||
|
||||
if (attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(attr) || !is_attribute_found(attr_sign)) {
|
||||
/* Fall back to unperturbed normal. */
|
||||
stack_store_float3(stack, node.normal_offset, sd->N);
|
||||
return;
|
||||
|
|
@ -260,8 +260,8 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
|||
const AttributeDescriptor attr_undisplaced_normal =
|
||||
(node.use_original_base) ?
|
||||
find_attribute(kg, sd->object, sd->prim, ATTR_STD_NORMAL_UNDISPLACED) :
|
||||
AttributeDescriptor{ATTR_ELEMENT_NONE, NODE_ATTR_FLOAT3, ATTR_STD_NOT_FOUND};
|
||||
if (attr_undisplaced_normal.offset != ATTR_STD_NOT_FOUND) {
|
||||
attribute_not_found();
|
||||
if (is_attribute_found(attr_undisplaced_normal)) {
|
||||
normal = primitive_surface_attribute<float3>(kg, sd, attr_undisplaced_normal);
|
||||
/* Can't interpolate in tangent space as the displaced normal is not used
|
||||
* for the tangent frame. */
|
||||
|
|
@ -351,7 +351,7 @@ ccl_device_noinline void svm_node_tangent(KernelGlobals kg,
|
|||
Float3Type tangent;
|
||||
if (node.direction_type == NODE_TANGENT_UVMAP) {
|
||||
/* UV map */
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(desc)) {
|
||||
stack_store(stack, node.tangent_offset, Float3Type());
|
||||
return;
|
||||
}
|
||||
|
|
@ -370,7 +370,7 @@ ccl_device_noinline void svm_node_tangent(KernelGlobals kg,
|
|||
else {
|
||||
/* radial */
|
||||
Float3Type generated;
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
if (!is_attribute_found(desc)) {
|
||||
generated = shading_position<Float3Type>(sd);
|
||||
}
|
||||
else if (desc.type == NODE_ATTR_FLOAT2) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ ccl_device_noinline void svm_node_vertex_color(KernelGlobals kg,
|
|||
float alpha;
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, node.layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(descriptor)) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
const float4 vertex_color = primitive_surface_attribute<float4>(kg, sd, descriptor);
|
||||
color = make_float3(vertex_color);
|
||||
|
|
@ -56,7 +56,7 @@ ccl_device_noinline void svm_node_vertex_color_derivative(
|
|||
float alpha;
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, node.layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (is_attribute_found(descriptor)) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
dual4 vertex_color = primitive_surface_attribute<dual4>(kg, sd, descriptor);
|
||||
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ enum AttributeElement {
|
|||
ATTR_ELEMENT_IS_MOTION,
|
||||
};
|
||||
|
||||
enum AttributeStandard {
|
||||
enum AttributeStandard : int {
|
||||
ATTR_STD_NONE = 0,
|
||||
ATTR_STD_VERTEX_NORMAL,
|
||||
ATTR_STD_CORNER_NORMAL,
|
||||
|
|
@ -747,7 +747,7 @@ enum AttributeStandard {
|
|||
ATTR_STD_SHADOW_TRANSPARENCY,
|
||||
ATTR_STD_NUM,
|
||||
|
||||
ATTR_STD_NOT_FOUND = ~0
|
||||
ATTR_STD_NOT_FOUND = -0x7fffffff
|
||||
};
|
||||
|
||||
enum AttributeFlag {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue