Merge branch 'blender-v5.2-release'

# Conflicts:
#	source/blender/sequencer/intern/utils.cc
This commit is contained in:
Aras Pranckevicius 2026-06-16 11:04:43 +03:00
commit 01ff4fb425
10 changed files with 262 additions and 72 deletions

View file

@ -322,6 +322,15 @@ void Film::init(const int2 &extent, const rcti *output_rect)
enabled_passes_ = enabled_passes(inst_.view_layer);
}
/* Force enable color passes if light passes are enabled.
* This is needed since we need to pre-divide by them. */
if (enabled_passes_ & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
enabled_passes_ |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
}
if (enabled_passes_ & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
enabled_passes_ |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
}
/* Filter obsolete passes. */
enabled_passes_ &= ~(EEVEE_RENDER_PASS_UNUSED_8 | EEVEE_RENDER_PASS_UNUSED_14);
@ -393,11 +402,11 @@ void Film::init(const int2 &extent, const rcti *output_rect)
EEVEE_RENDER_PASS_POSITION |
EEVEE_RENDER_PASS_VECTOR;
const eViewLayerEEVEEPassType color_passes_1 = EEVEE_RENDER_PASS_DIFFUSE_LIGHT |
EEVEE_RENDER_PASS_DIFFUSE_COLOR |
EEVEE_RENDER_PASS_SPECULAR_LIGHT |
EEVEE_RENDER_PASS_VOLUME_LIGHT |
EEVEE_RENDER_PASS_EMIT;
const eViewLayerEEVEEPassType color_passes_2 = EEVEE_RENDER_PASS_DIFFUSE_COLOR |
EEVEE_RENDER_PASS_SPECULAR_COLOR |
EEVEE_RENDER_PASS_SPECULAR_COLOR;
const eViewLayerEEVEEPassType color_passes_2 = EEVEE_RENDER_PASS_VOLUME_LIGHT |
EEVEE_RENDER_PASS_EMIT |
EEVEE_RENDER_PASS_ENVIRONMENT |
EEVEE_RENDER_PASS_MIST |
EEVEE_RENDER_PASS_SHADOW | EEVEE_RENDER_PASS_AO;

View file

@ -138,15 +138,15 @@ void combine_frag([[resource_table]] Combine &srt,
case CLOSURE_BSSRDF_BURLEY_ID:
case CLOSURE_BSDF_DIFFUSE_ID:
diffuse_color += cl.color;
diffuse_direct += closure_direct_light;
diffuse_indirect += closure_indirect_light;
diffuse_direct += closure_direct_light * cl.color;
diffuse_indirect += closure_indirect_light * cl.color;
break;
case CLOSURE_BSDF_MICROFACET_GGX_REFLECTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_THIN_GLASS_TRANSMISSION_ID:
specular_color += cl.color;
specular_direct += closure_direct_light;
specular_indirect += closure_indirect_light;
specular_direct += closure_direct_light * cl.color;
specular_indirect += closure_indirect_light * cl.color;
break;
case CLOSURE_NONE_ID:
assert(false);

View file

@ -17,6 +17,7 @@
#include "gpu_shader_fullscreen_lib.glsl"
#include "gpu_shader_math_safe_lib.glsl"
#include "gpu_shader_math_vector_lib.glsl"
#include "gpu_shader_math_vector_safe_lib.glsl"
namespace eevee::film {
@ -77,6 +78,38 @@ float patch_float_for_16f_storage(float value)
return uintBitsToFloat(floatBitsToUint(value) + 0x1000);
}
float4 safe_divide_even_color(float4 a, float4 b)
{
a *= safe_rcp(b);
/* Try to get gray even if b is zero. */
if (b.x == 0.0f) {
if (b.y == 0.0f) {
a.x = a.z;
a.y = a.z;
}
else if (b.z == 0.0f) {
a.x = a.y;
a.z = a.y;
}
else {
a.x = 0.5f * (a.y + a.z);
}
}
else if (b.y == 0.0f) {
if (b.z == 0.0f) {
a.y = a.x;
a.z = a.x;
}
else {
a.y = 0.5f * (a.x + a.z);
}
}
else if (b.z == 0.0f) {
a.z = 0.5f * (a.x + a.y);
}
return a;
}
struct Film {
[[resource_table]] srt_t<CameraVelocity> camera;
[[resource_table]] srt_t<draw::View> views_;
@ -630,20 +663,9 @@ struct Film {
imageStoreFast(out_combined_img, dst.texel, color);
}
void store_color(FilmSample dst,
int pass_id,
float4 color,
float4 &display,
bool do_clamp_negative_values = true)
void store_color_ex(
FilmSample dst, int pass_id, float4 color, float4 &display, bool do_clamp_negative_values)
{
if (pass_id == -1) {
return;
}
float4 data_film = imageLoadFast(color_accum_img, int3(dst.texel, pass_id));
color = (data_film * dst.weight + color) * dst.weight_sum_inv;
/* Filter NaNs. */
if (any(isnan(color))) {
color = float4(0.0f, 0.0f, 0.0f, 1.0f);
@ -666,6 +688,50 @@ struct Film {
imageStoreFast(color_accum_img, int3(dst.texel, pass_id), color);
}
void store_color(FilmSample dst,
int pass_id,
float4 color,
float4 &display,
bool do_clamp_negative_values = true)
{
if (pass_id == -1) {
return;
}
float4 data_film = imageLoadFast(color_accum_img, int3(dst.texel, pass_id));
color = (data_film * dst.weight + color) * dst.weight_sum_inv;
store_color_ex(dst, pass_id, color, display, do_clamp_negative_values);
}
void store_color_and_light(FilmSample dst,
int color_pass_id,
int light_pass_id,
float4 color,
float4 light,
float4 &display)
{
if (color_pass_id == -1) {
return;
}
float4 color_film = imageLoadFast(color_accum_img, int3(dst.texel, color_pass_id));
color = (color_film * dst.weight + color) * dst.weight_sum_inv;
store_color_ex(dst, color_pass_id, color, display, true);
if (light_pass_id == -1) {
return;
}
float4 light_film = imageLoadFast(color_accum_img, int3(dst.texel, light_pass_id));
/* Undivide. */
light_film *= color_film;
light = (light_film * dst.weight + light) * dst.weight_sum_inv;
light = safe_divide_even_color(light, color);
store_color_ex(dst, light_pass_id, light, display, true);
}
void store_value(FilmSample dst, int pass_id, float value, float4 &display)
{
if (pass_id == -1) {
@ -807,47 +873,10 @@ struct Film {
}
if (flag_test(enabled_categories, PASS_CATEGORY_COLOR_1)) {
float4 diffuse_light_accum = float4(0.0f);
float4 specular_light_accum = float4(0.0f);
float4 volume_light_accum = float4(0.0f);
float4 emission_accum = float4(0.0f);
for (int i = 0; i < samples_len; i++) {
FilmSample src = sample_get(i, texel_film);
sample_accum(src,
uni.uniform_buf.film.diffuse_light_id,
uni.uniform_buf.render_pass.diffuse_light_id,
rp_color_tx,
diffuse_light_accum);
sample_accum(src,
uni.uniform_buf.film.specular_light_id,
uni.uniform_buf.render_pass.specular_light_id,
rp_color_tx,
specular_light_accum);
sample_accum(src,
uni.uniform_buf.film.volume_light_id,
uni.uniform_buf.render_pass.volume_light_id,
rp_color_tx,
volume_light_accum);
sample_accum(src,
uni.uniform_buf.film.emission_id,
uni.uniform_buf.render_pass.emission_id,
rp_color_tx,
emission_accum);
}
store_color(dst, uni.uniform_buf.film.diffuse_light_id, diffuse_light_accum, out_color);
store_color(dst, uni.uniform_buf.film.specular_light_id, specular_light_accum, out_color);
store_color(dst, uni.uniform_buf.film.volume_light_id, volume_light_accum, out_color);
store_color(dst, uni.uniform_buf.film.emission_id, emission_accum, out_color);
}
if (flag_test(enabled_categories, PASS_CATEGORY_COLOR_2)) {
float4 diffuse_color_accum = float4(0.0f);
float4 specular_color_accum = float4(0.0f);
float4 environment_accum = float4(0.0f);
float mist_accum = 0.0f;
float shadow_accum = 0.0f;
float ao_accum = 0.0f;
float4 diffuse_light_accum = float4(0.0f);
float4 specular_light_accum = float4(0.0f);
for (int i = 0; i < samples_len; i++) {
FilmSample src = sample_get(i, texel_film);
@ -861,6 +890,52 @@ struct Film {
uni.uniform_buf.render_pass.specular_color_id,
rp_color_tx,
specular_color_accum);
sample_accum(src,
uni.uniform_buf.film.diffuse_light_id,
uni.uniform_buf.render_pass.diffuse_light_id,
rp_color_tx,
diffuse_light_accum);
sample_accum(src,
uni.uniform_buf.film.specular_light_id,
uni.uniform_buf.render_pass.specular_light_id,
rp_color_tx,
specular_light_accum);
}
store_color_and_light(dst,
uni.uniform_buf.film.diffuse_color_id,
uni.uniform_buf.film.diffuse_light_id,
diffuse_color_accum,
diffuse_light_accum,
out_color);
store_color_and_light(dst,
uni.uniform_buf.film.specular_color_id,
uni.uniform_buf.film.specular_light_id,
specular_color_accum,
specular_light_accum,
out_color);
}
if (flag_test(enabled_categories, PASS_CATEGORY_COLOR_2)) {
float4 environment_accum = float4(0.0f);
float4 volume_light_accum = float4(0.0f);
float4 emission_accum = float4(0.0f);
float mist_accum = 0.0f;
float shadow_accum = 0.0f;
float ao_accum = 0.0f;
for (int i = 0; i < samples_len; i++) {
FilmSample src = sample_get(i, texel_film);
sample_accum(src,
uni.uniform_buf.film.volume_light_id,
uni.uniform_buf.render_pass.volume_light_id,
rp_color_tx,
volume_light_accum);
sample_accum(src,
uni.uniform_buf.film.emission_id,
uni.uniform_buf.render_pass.emission_id,
rp_color_tx,
emission_accum);
sample_accum(src,
uni.uniform_buf.film.environment_id,
uni.uniform_buf.render_pass.environment_id,
@ -882,8 +957,8 @@ struct Film {
float4 shadow_accum_color = float4(float3(shadow_accum), weight_accum);
float4 ao_accum_color = float4(float3(ao_accum), weight_accum);
store_color(dst, uni.uniform_buf.film.diffuse_color_id, diffuse_color_accum, out_color);
store_color(dst, uni.uniform_buf.film.specular_color_id, specular_color_accum, out_color);
store_color(dst, uni.uniform_buf.film.volume_light_id, volume_light_accum, out_color);
store_color(dst, uni.uniform_buf.film.emission_id, emission_accum, out_color);
store_color(dst, uni.uniform_buf.film.environment_id, environment_accum, out_color);
store_color(dst, uni.uniform_buf.film.shadow_id, shadow_accum_color, out_color);
store_color(dst, uni.uniform_buf.film.ambient_occlusion_id, ao_accum_color, out_color);

View file

@ -21,6 +21,7 @@
#include "BLI_path_utils.hh"
#include "BLI_string.hh"
#include "BLI_string_utf8.hh"
#include "BLI_string_utils.hh"
#include "BLT_translation.hh"
@ -87,13 +88,12 @@ void strip_unique_name_set(Scene *scene, ListBaseT<Strip> *seqbasep, Strip *stri
sui.count = 1;
sui.match = 1; /* assume the worst to start the loop */
/* Strip off the suffix */
/* Strip off the suffix only if it is purely numeric. */
if ((dot = strrchr(sui.name_src, '.'))) {
*dot = '\0';
dot++;
if (*dot) {
sui.count = atoi(dot) + 1;
char *suffix = dot + 1;
if (BLI_string_is_decimal(suffix)) {
*dot = '\0';
sui.count = atoi(suffix) + 1;
}
}

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3a6b0a9e9c73daa37c8074efccd5b8150132f3ddcccd028bd09525b3e94250d6
size 13955
oid sha256:7fa6e99f3dd1d19231e0fe51567a96cd6f594e9066d013b3cf2e33418ce94d4f
size 12939

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2f11d0a612c752f745605788ea8c1cea06b875d33b46a192e3289c23d5dd0ade
size 7135
oid sha256:d45818cf24a988eed08695c26fe2dd959984be915e1fb6b81be716cf8a4d599a
size 6598

View file

@ -1526,6 +1526,11 @@ if(TEST_SRC_DIR_EXISTS)
--testdir "${TEST_SRC_DIR}/sequence_editing"
)
add_blender_test(
sequencer_strip_naming
--python ${CMAKE_CURRENT_LIST_DIR}/sequencer_strip_naming.py
)
add_blender_test(
sequencer_load_meta_stack
${TEST_SRC_DIR}/sequence_editing/vse_load_meta_stack.blend

View file

@ -101,6 +101,12 @@ BLOCKLIST_AMD_WINDOWS_VK = [
"implicit_volume.blend"
]
# Block list for Linux/AMD official driver. On buildbot this driver can fail and the artifacts are likely
# caused by incorrect index buffer synchronization or vertex shader execution.
BLOCKLIST_AMD_LINUX_VK = [
".*"
]
BLOCKLIST_INTEL_WINDOWS_GL = [
# Fails sporadically and causes all subsequent volume tests to fail (See #153612).
"volume_instance.blend"
@ -295,6 +301,8 @@ def main():
blocklist += BLOCKLIST_NVIDIA_GL
if gpu_vendor == "AMD" and sys.platform == "win32" and args.gpu_backend == "vulkan":
blocklist += BLOCKLIST_AMD_WINDOWS_VK
if gpu_vendor == "AMD" and sys.platform == "linux" and args.gpu_backend == "vulkan":
blocklist += BLOCKLIST_AMD_LINUX_VK
report = EEVEEReport("EEVEE", args.outdir, args.oiiotool, variation=args.gpu_backend, blocklist=blocklist)
if args.gpu_backend == "vulkan":

View file

@ -0,0 +1,81 @@
# SPDX-FileCopyrightText: 2026 Blender Authors
#
# SPDX-License-Identifier: Apache-2.0
# ./blender.bin --background --factory-startup --python tests/python/sequencer_strip_naming.py
import bpy
import sys
import unittest
class StripNamingTest(unittest.TestCase):
def setUp(self):
bpy.context.scene.sequence_editor_create()
self.strips = bpy.context.scene.sequence_editor.strips
def tearDown(self):
bpy.context.scene.sequence_editor_clear()
def test_duplicate_name_gets_numeric_suffix(self):
# identical names get .001, .002, ...
s1 = self.strips.new_meta("Meta", 1, 1)
s2 = self.strips.new_meta("Meta", 2, 1)
s3 = self.strips.new_meta("Meta", 3, 1)
self.assertEqual(s1.name, "Meta")
self.assertEqual(s2.name, "Meta.001")
self.assertEqual(s3.name, "Meta.002")
def test_purely_numeric_suffix_increments(self):
# strip name already ends in .###: the number should be increased
s1 = self.strips.new_meta("Clip.012", 1, 1)
s2 = self.strips.new_meta("Clip.012", 2, 1)
self.assertEqual(s1.name, "Clip.012")
self.assertEqual(s2.name, "Clip.013")
def test_dot_number_nonnumeric_suffix_not_stripped(self):
# a ".###" followed by more characters should not be stripped
name = "name.123_anything_456"
s1 = self.strips.new_meta(name, 1, 1)
s2 = self.strips.new_meta(name, 2, 1)
s3 = self.strips.new_meta(name, 3, 1)
self.assertEqual(s1.name, "name.123_anything_456")
self.assertEqual(s2.name, "name.123_anything_456.001")
self.assertEqual(s3.name, "name.123_anything_456.002")
def test_isoformat_name_not_stripped(self):
# naming case from #160144:
# datetime.isoformat() produces names like YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM
# The ".ffffff+HH:MM" part must be preserved, not stripped
name = "2024-01-15T12:30:45.123456+02:00"
s1 = self.strips.new_meta(name, 1, 1)
s2 = self.strips.new_meta(name, 2, 1)
self.assertEqual(s1.name, name)
self.assertEqual(s2.name, name + ".001")
def test_multiple_dots_last_numeric_increments(self):
# "a.b.002": last suffix is purely numeric, so it should increment
s1 = self.strips.new_meta("a.b.002", 1, 1)
s2 = self.strips.new_meta("a.b.002", 2, 1)
self.assertEqual(s1.name, "a.b.002")
self.assertEqual(s2.name, "a.b.003")
def test_multiple_dots_last_nonnumeric_appends(self):
# "a.b.c": last suffix is non-numeric, whole name is the base
s1 = self.strips.new_meta("a.b.c", 1, 1)
s2 = self.strips.new_meta("a.b.c", 2, 1)
self.assertEqual(s1.name, "a.b.c")
self.assertEqual(s2.name, "a.b.c.001")
def main():
argv = [sys.argv[0]]
if '--' in sys.argv:
argv += sys.argv[sys.argv.index('--') + 1:]
unittest.main(argv=argv)
if __name__ == "__main__":
main()

View file

@ -31,6 +31,12 @@ BLOCKLIST_VULKAN = [
"image_log.blend",
]
# Block list for Linux/AMD official driver. On buildbot this driver can fail and the artifacts are likely
# caused by incorrect index buffer synchronization or vertex shader execution.
BLOCKLIST_AMD_LINUX_VK = [
".*"
]
def setup():
import bpy
@ -107,6 +113,12 @@ def main():
if args.gpu_backend == "vulkan":
blocklist += BLOCKLIST_VULKAN
# AMD Linux Vulkan driver blocks all tests due to index/vertex shader sync issues.
gpu_vendor = render_report.get_gpu_device_vendor(args.blender)
if os.getenv("BLENDER_TEST_IGNORE_VENDOR_BLOCKLIST") is None:
if gpu_vendor == "AMD" and sys.platform == "linux" and args.gpu_backend == "vulkan":
blocklist += BLOCKLIST_AMD_LINUX_VK
report = WorkbenchReport("Workbench", args.outdir, args.oiiotool, variation=args.gpu_backend, blocklist=blocklist)
if args.gpu_backend == "vulkan":
report.set_compare_engine('workbench', 'opengl')