Fix T94464: video texture is not refreshing
In the past that worked because the `GPUMaterial` referenced the `ImageUser` from the image node. However, that design was incompatible with the recent node tree update refactor (rB7e712b2d6a0d257d272e). Also, in general it is a bad idea to have references between data that is owned by two different data blocks. This incompatibility was resolved by copying the image user from the node to the `GPUMaterial` (rB28df0107d4a8). Unfortunately, eevee depended on this reference, because the image user on the node was update when the frame changed. Because the image user was copied, the image user in the `GPUMaterial` did not receive the frame update anymore. This frame update is added back by this commit. The main change is that the image user iterator now also iterates over image users in `GPUMaterial`s on material and world data blocks. An issue is that these materials don't exist on the original data blocks and that caused the check in `build_animation_images` in the depsgraph to give the wrong answer. Therefore the check is extended. Right now the check is not optimal, because it results in more depsgraph nodes than are necessary. This can be improved when it becomes cheaper to check if a node tree contains any references to a video texture. The node tree update refactor mentioned before makes it much easier to construct this kind of run-time data from the bottom up, instead of scanning the entire node tree recursively every time some information is needed.
This commit is contained in:
@@ -98,6 +98,7 @@
|
||||
|
||||
#include "SEQ_utils.h" /* SEQ_get_topmost_sequence() */
|
||||
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "BLI_sys_types.h" /* for intptr_t support */
|
||||
@@ -3364,6 +3365,23 @@ static void image_walk_ntree_all_users(
|
||||
}
|
||||
}
|
||||
|
||||
static void image_walk_gpu_materials(
|
||||
ID *id,
|
||||
ListBase *gpu_materials,
|
||||
void *customdata,
|
||||
void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
|
||||
{
|
||||
LISTBASE_FOREACH (LinkData *, link, gpu_materials) {
|
||||
GPUMaterial *gpu_material = (GPUMaterial *)link->data;
|
||||
ListBase textures = GPU_material_textures(gpu_material);
|
||||
LISTBASE_FOREACH (GPUMaterialTexture *, gpu_material_texture, &textures) {
|
||||
if (gpu_material_texture->iuser_available) {
|
||||
callback(gpu_material_texture->ima, id, &gpu_material_texture->iuser, customdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void image_walk_id_all_users(
|
||||
ID *id,
|
||||
bool skip_nested_nodes,
|
||||
@@ -3383,6 +3401,7 @@ static void image_walk_id_all_users(
|
||||
if (ma->nodetree && ma->use_nodes && !skip_nested_nodes) {
|
||||
image_walk_ntree_all_users(ma->nodetree, &ma->id, customdata, callback);
|
||||
}
|
||||
image_walk_gpu_materials(id, &ma->gpumaterial, customdata, callback);
|
||||
break;
|
||||
}
|
||||
case ID_LA: {
|
||||
@@ -3397,6 +3416,7 @@ static void image_walk_id_all_users(
|
||||
if (world->nodetree && world->use_nodes && !skip_nested_nodes) {
|
||||
image_walk_ntree_all_users(world->nodetree, &world->id, customdata, callback);
|
||||
}
|
||||
image_walk_gpu_materials(id, &world->gpumaterial, customdata, callback);
|
||||
break;
|
||||
}
|
||||
case ID_TE: {
|
||||
|
||||
@@ -1121,7 +1121,14 @@ void DepsgraphNodeBuilder::build_animdata_nlastrip_targets(ListBase *strips)
|
||||
|
||||
void DepsgraphNodeBuilder::build_animation_images(ID *id)
|
||||
{
|
||||
if (BKE_image_user_id_has_animation(id)) {
|
||||
/* GPU materials might use an animated image. However, these materials have no been built yet. We
|
||||
* could scan the entire node tree recursively to check if any texture node has a video. That is
|
||||
* quite expensive. For now just always add this operation node, because it is very fast. */
|
||||
/* TODO: Add a more precise check when it is cheaper to iterate over all image nodes in a node
|
||||
* tree. */
|
||||
const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO);
|
||||
|
||||
if (BKE_image_user_id_has_animation(id) || can_have_gpu_material) {
|
||||
ID *id_cow = get_cow_id(id);
|
||||
add_operation_node(
|
||||
id,
|
||||
|
||||
@@ -1466,8 +1466,11 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
|
||||
|
||||
void DepsgraphRelationBuilder::build_animation_images(ID *id)
|
||||
{
|
||||
/* See #DepsgraphNodeBuilder::build_animation_images. */
|
||||
const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO);
|
||||
|
||||
/* TODO: can we check for existence of node for performance? */
|
||||
if (BKE_image_user_id_has_animation(id)) {
|
||||
if (BKE_image_user_id_has_animation(id) || can_have_gpu_material) {
|
||||
OperationKey image_animation_key(
|
||||
id, NodeType::IMAGE_ANIMATION, OperationCode::IMAGE_ANIMATION);
|
||||
TimeSourceKey time_src_key;
|
||||
|
||||
Reference in New Issue
Block a user