Fix #156474, #156473: Cycles wrong mipmap with some types of texture coords

Creating a texture coordinate by combining a UV Map with a white noise
texture did not properly handle that one provides derivatives while the
other does not. It would read from wrong or uninitialized stack memory,
now make sure that is zeroed.

Pull Request: https://projects.blender.org/blender/blender/pulls/156596
This commit is contained in:
Brecht Van Lommel 2026-04-01 17:56:58 +02:00 • committed by Brecht Van Lommel
parent ba6a8ca4da
commit 329e8a5cfc
9 changed files with 42 additions and 12 deletions

View file

@ -17,6 +17,7 @@
#include "scene/svm.h"
#include "util/log.h"
#include "util/math_float3.h"
#include "util/progress.h"
#include "util/queue.h"
#include "util/task.h"
@ -470,6 +471,37 @@ void SVMCompiler::add_value_node(const ShaderNode *node,
add_node(NODE_VALUE_V, value, node->need_derivatives());
}
void SVMCompiler::stack_zero_incomplete_derivatives(const ShaderNode *node)
{
/* No derivatives in volumes yet. */
if (current_type == SHADER_TYPE_VOLUME) {
return;
}
/* Does this node need derivatives but it doesn't have a derivative variation? */
const bool incomplete_derivatives = node->need_derivatives() &&
svm_node_type_with_derivatives(node->shader_node_type()) ==
node->shader_node_type();
if (!incomplete_derivatives) {
return;
}
/* Zero derivatives. */
for (const ShaderOutput *output : node->outputs) {
if (output->stack_offset == SVM_STACK_INVALID) {
continue;
}
const int base_size = stack_size(output->type());
if (base_size == 3) {
add_value_node(node, zero_float3(), output->stack_offset + 3);
add_value_node(node, zero_float3(), output->stack_offset + 6);
}
else if (base_size == 1) {
add_value_node(node, __float_as_int(0.0f), output->stack_offset + 1);
add_value_node(node, __float_as_int(0.0f), output->stack_offset + 2);
}
}
}
uint SVMCompiler::attribute(ustring name)
{
return scene->shader_manager->get_attribute_id(name);
@ -505,6 +537,7 @@ void SVMCompiler::find_dependencies(ShaderNodeSet &dependencies,
void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
{
node->compile(*this);
stack_zero_incomplete_derivatives(node);
stack_clear_users(node, done);
stack_clear_temporary(node);

View file

@ -204,6 +204,7 @@ class SVMCompiler {
int stack_size(SocketType::Type type);
int stack_size(const ShaderIO *io);
void stack_clear_users(ShaderNode *node, ShaderNodeSet &done);
void stack_zero_incomplete_derivatives(const ShaderNode *node);
/* single closure */
void find_dependencies(ShaderNodeSet &dependencies,

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5850c279206d23fa5b4853f0f38ab6002b8241fb55469cc2061596f24cda6e32
size 18039

View file

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:00a11d46552adca5cc5643b06aab1326d89980d9a797c4d5322b8e90dc53d98a
size 16956

View file

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b01ae1161c2efad0692797b0eac52dcfefa133bd58d08402ca6667b98facb900
size 24727

View file

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fc78d3fe50060bcaa173a86ace4498b89c7296458ef1e445d28bde169454c557
size 13595

View file

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0e1bb375452be84d1269265a1a7ee999ee0301522b5d0c6805dbb4d31c442dd9
size 25548

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c70461f34d78af0f8b7ea53b84d07527d22e4bcb4e3c6142d7d35ed87cf3c7f5
size 101296

View file

@ -51,6 +51,8 @@ BLOCKLIST_OSL_ALL = BLOCKLIST_OSL_LIMITED + [
'render_passes_.*.blend',
# OSL can not specify parameters when reading attribute, which we need for stochastic sampling
'volume_tricubic_interpolation.blend',
# Test specifically for how SVM deals with missing derivatives, which OSL has.
"image_mipmap_incomplete_derivs.blend"
]
BLOCKLIST_OPTIX = [