观察一个StaticMesh加载其对应DDC文件的流程

news2024/11/16 22:36:35

无用的前言

很久前我观察过DDC的一些代码了解了些浅显的知识。
最近我遇到个DDC相关的问题,于是将之前写的东西又复习了一遍。同时我也将记录下我最近研究这个问题时,一些重要的部分以作备忘。

目标

观察一个StaticMesh加载其对应DDC文件的流程,记录其中的一些要点。

(注意:此处引擎版本是4.26,UE5里DDC相关代码已有较大调整)

0. 代码入手处

DDC接口的GetSynchronousGetAsynchronous函数是获得DDC数据的统一接口,断点在这里一定能触发到。

不过,我现在只想观察一个特定StaticMesh的DDC,那么如果我一开始就将断点打在GetSynchronousGetAsynchronous内部,则会断到很多其他资源。
所以,我选择首先将断点打在StaticMesh调用DDC接口的地方,然后,双击加载一个我想观察的StaticMesh资源比如这个:
在这里插入图片描述
然后断点就能触发:(可以通过Owner的值确认下触发的StaticMesh资源是自己想要观察的那个)
在这里插入图片描述
现在,即是这个StaticMesh准备获取DDC数据的时刻。

随后,再在 GetSynchronous 函数内部下断点来触发:(可以通过CacheKey值确认是这个资源)
在这里插入图片描述

这里调用的函数是 GetSynchronous,即同步的方式,所以接下来会立即执行这个任务(而不是放在另一个线程中执行)。

GetSynchronous函数核心是创建一个 FAsyncTask<FBuildAsyncWorker> 来执行任务。

1. FBuildAsyncWorker

FAsyncTask安排了一个可异步执行的任务(也可同步执行),其基础用法可见上一篇。
而任务的具体内容则由FBuildAsyncWorker定义,它本身有些成员变量,可以参考下注释对他们的解释:

/** true in the case of a cache hit, otherwise the result of the deriver build call **/
bool							bSuccess;
/** true if we should record the timing **/
bool							bSynchronousForStats;
/** true if we had to build the data */
bool							bDataWasBuilt;
/** Data dervier we are operating on **/
FDerivedDataPluginInterface*	DataDeriver;
/** Cache key associated with this build **/
FString							CacheKey;
/** Data to return to caller, later **/
TArray<uint8>					Data;

而执行的逻辑,则在 DoWork()函数中,其中最重要的是通过FDerivedDataBackend获得DDC数据。

  • 如果成功则局部变量bGetResult会记为真,那么FBuildAsyncWorker本身的成员bSuccess会变为真,且成员Data也是有值的。
  • 如果失败,那么bSuccess为假,Data也是空的。

在这里插入图片描述
这样,当任务结束后,就可以通过FBuildAsyncWorker本身的成员变量bSuccessData的值,来明白DDC是否获取成功和DDC数据是什么。

接下来,需要看FDerivedDataBackend::Get().GetRoot().GetCachedData

2. 众多的 DerivedDataBackend?

正如 《观察DerivedDataBackendInterface各个子类的关系》 所看到,DerivedDataBackend 由多个子类,且之间并非并列,而是嵌套的关系。

所以,尽管这里作为 Root 的 DerivedDataBackend 是 DerivedDataLimitKeyLengthWrapper:
在这里插入图片描述
但随后它又会调用其他的 DerivedDataBackend 来尝试获得DDC数据。

UE设计成这样众多Backend的结构肯定是有理由的,不过我还没理解清楚,所以不做讨论。

但有一点可以肯定:如果最终通过文件获得DDC数据,则一定是通过FFileSystemDerivedDataBackend

3. 在FFileSystemDerivedDataBackend::GetCachedData 下断点可以获得对应文件的路径

随后,在 FFileSystemDerivedDataBackend::GetCachedData 下断点,可以通过Filename的值知道对应的DDC文件路径:
在这里插入图片描述
可以直接在磁盘上找到这个文件:
在这里插入图片描述

4*. 缓存缺失重新构建的情况

也可以在之后手动删除这个文件,来模拟DDC文件没有找到的情况。
此时可以看到FBuildAsyncWorkerDoWork()会走到这里,结束后bSuccess为假,Data也是空的。
在这里插入图片描述
GetSynchronous由于返回的是PendingTask.GetTask().bSuccess,所以返回的是假。

那么StaticMesh调用后就会走向另一个分支
在这里插入图片描述

随后,DDC的数据会被重建。

最后,在GetDerivedDataCacheRef().Put调用后:
在这里插入图片描述

DDC文件会被重新保存(由于这次调用应该是异步的,所以这个函数返回后不会立即看到文件的产生)

总结

  1. StaticMesh 调用DDC的通用接口GetSynchronous获得DDC数据
  2. GetSynchronous内部创建一个 FAsyncTask<FBuildAsyncWorker> 来执行任务。
  3. FBuildAsyncWorkerDoWork() 是其核心,可以看到它通过DerivedDataBackend获得DDC数据。
  4. 众多的 DerivedDataBackend 相互连接,定义了找DDC数据的逻辑。
  5. 可在FFileSystemDerivedDataBackend::GetCachedData下断点知道资源加载的DDC文件路径。

小记最近的问题

最近遇到的问题从堆栈上看是,StaticMesh加载的DDC数据中一个数组的元素大小不匹配现在的定义。一般来说,DDC的问题首先要尝试的肯定是清除一遍DDC让它重新生成一遍。但是我(自以为)清除了之后,还是同样的错误。

最后,通过找到那个StaticMesh对应的DDC文件的具体路径才发现——其获得数据的文件并没有清除,而是一个共享的位置,不在本地。而且这个位置是很久前已经弃用的,之所以找到这个位置是因为之前配置了一个环境变量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/757250.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 列表 reverse()函数使用详解

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 reverse函数使用详解 1、reverse()会修改原始副本2、reverse()和reversed()的区别…

小白学懂分频器(二)

分频&#xff1a;简单来说&#xff0c;二分频后的方波一个周期为标准方波高低电平循环两个周期&#xff0c;四分频为4个周期。分频后的时钟周期为原来的n倍&#xff0c;即为n分频。   频率和周期的关系&#xff1a;f1/T &#xff08;1&#xff09;简单的计数器 计数器实质是…

【数据结构】_1.集合与复杂度

目录 1. 集合框架 2. 时间复杂度 2.1 时间复杂度和空间复杂度 2.2 时间复杂度的概念 2.3 大O的渐进表示法 2.3.1 精确的时间复杂度表达式 2.3.2 大O渐进表示法的三条规则 2.3.3 时间复杂度的最好、平均与最坏情况 2.4 时间复杂度计算示例 3.空间复杂度 1. 集合框架 …

【多线程例题】编写代码, 实现多线程数组求和.【本题学习关键点:通过一个类 进行加法】

【多线程例题】编写代码, 实现多线程数组求和. import java.util.Random;/*** 题目名称 :* 编写代码, 实现多线程数组求和.* 题目内容 :* 1. 给定一个很长的数组 (长度 1000w), 通过随机数的方式生成 1-100 之间的整数.* 2. 实现代码, 能够创建两个线程, 对这个数组的所有元素求…

CORTEX-M系列处理器

1.ARM处理器的发展 随着智能终端、人工智能、5G、物联网等技术的快速发展&#xff0c;半导体行业蓬勃发展了数十年。处理器芯片作为这些技术的“心脏”&#xff0c;迎来了井喷式的增长。世界主流的处理器分为4大类&#xff1a;Interl公司和AMD公司的的X86架构处理器&#xff0…

利用集合框架实现-超市会员管理系统

借助集合框架来实现超市会员管理系统&#xff0c;实现以下功能&#xff1a; 1.开卡 2.积分累计 3.查询剩余积分 4.积分兑换 5.修改密码 6.退出 -------------------------------------------------------------------------------------------------- 展示&#x…

第一堂棒球课:MLB棒球大联盟青训体系·野球1号位

介绍MLB棒球大联盟青训体系 1. 引言 这里我们将深入探讨MLB棒球大联盟青训体系的故事&#xff0c;了解它是如何成为全球青少年最梦寐以求的梦想&#xff0c;以及它对世界棒球运动产生的深远影响。 MLB棒球大联盟青训体系&#xff0c;即MLB Youth Coaching Program&#xff0c…

java项目之东理咨询交流论坛(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的东理咨询交流论坛。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架…

Java并发编程(10) —— ReentrantLock类详解

一、ReentrantLock介绍 ReentrantLock是juc.locks包中的一个独占式可重入锁&#xff0c;相比synchronized&#xff0c;它可以创建多个条件等待队列&#xff0c;还支持公平/非公平锁、可中断、超时、轮询等特性。 ReentrantLock实现Lock接口实现了一个锁所需的方法&#xff0c…

CSS基础特性

一、CSS概述 1.1、概述 CSS&#xff08;层叠样式表&#xff09;是一种用来表现HTML&#xff08;标准通用标记语言的一个应用&#xff09;或XML&#xff08;标准通用标记语言的一个子集&#xff09;等文件样式的计算机语言。CSS 不仅可以静态地修饰网页&#xff0c;还可以配合…

[JVM] 3. 类加载子系统(2)-- 类加载器、双亲委派机制(JDK1.8及之前)及其他

前言 JDK1.8及之前和JDK9及之后的双亲委派模型是不一样的&#xff0c;这里学习了1.8及以前的双亲委派模型&#xff0c;记录笔记 一、类加载器 1.8之前主要是这几种类加载器&#xff1a; 1. 启动类加载器(Bootstrap ClassLoader)&#xff1a; 负责将存放在<JAVA_HOME>…

JavaScript中值和变量

值是指可以存储在计算机内存中的数据。这些数据可以是数字、字符串、布尔值、对象等。变量是一种用于存储值的容器。 ● 在JS中&#xff0c;我们可以使用let参数也创建一个变量&#xff0c;使用给变量赋值&#xff0c;例如 let ITshare "IT知识一享";● 之后我们打…

力扣小技巧:如何用最简单的方式实现小写字母转换

本篇博客会讲解力扣“709. 转换成小写字母”的解题思路&#xff0c;这是题目链接。 本题的解法非常简单&#xff0c;只需利用tolower函数即可。这个函数的作用是将所有大写字母转换为小写字母&#xff0c;而对其他字符不做任何改变。 char * toLowerCase(char * s){// 把字符串…

1769_Source Insight数字前缀后缀乱码解决方法

全部学习汇总&#xff1a; GreyZhang/editors_skills: Summary for some common editor skills I used. (github.com) 这算是一个偶然的发现&#xff0c;写代码的时候发现十六进制的数字显示前缀0x显示错误。如果只输入一个0x正常&#xff0c;写成一个十六进制数据诸如0x123之后…

分析中心常见的协议字段以及语法

布尔运算符 基本语法 图中以及描述得很详细了。 日志检索高级查询语法 通配符查询&#xff1a;在一项内的单个字符用&#xff1f;去查&#xff0c;多个字符用*去查询&#xff0c;例如想查mysql和mssql就可以使用db_type:m?sql 去查询&#xff0c;而要查sql结尾就用 *sql 去…

SQL Server启用sa账户

一、简介 在安装好 SQL Server 后&#xff0c;默认 sa 用户是禁用且也没有启用 SQL Server 登陆验证&#xff0c;这需要手动开启。接下来&#xff0c;开始我们今天的教程吧。 二、sa 登陆 2.1 启用 sa 首先&#xff0c;使用 Windows 验证登陆 登陆成功后&#xff0c;找到…

Java032——反射(Reflection)

一、Java中的反射及作用 Java的反射(reflection)机制是指在程序的运行状态中&#xff1a; 可以构造任意一个类的对象&#xff0c;可以了解任意一个对象所属的类&#xff0c;可以了解任意一个类的成员变量和方法&#xff0c;可以调用任意一个对象的属性和方法。 一句话&#…

数据结构day2(2023.7.15)

一、Xmind整理&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;定义车的信息&#xff1a;品牌&#xff0c;单价&#xff0c;颜色&#xff0c;车牌号 struct Car{char name[20]; //品牌int price; //单价char color[10] //颜色char id[20] //车牌…

Spring【 Spring整合MyBatis、SpringAOP(AOP简介 、AOP相关术语、AOP入门)】(五)-全面详解(学习总结---从入门到深化)

目录 Spring整合MyBatis_准备数据库和实体类 Spring整合MyBatis_编写持久层接口和service类 Spring整合MyBatis_Spring整合Junit进行单元测试 Spring整合MyBatis_自动创建代理对象 SpringAOP_AOP简介 SpringAOP_AOP相关术语 SpringAOP_AOP入门 Spring整合MyBatis_准备数据…

推荐几个github上非常受欢迎的库

推荐几个github上非常受欢迎的库 The Book of Secret Knowledge the-book-of-secret-knowledge 这个仓库里边包含了一系列非常有趣的手册、备忘单、博客、黑客、单行话、cli/web 工具等。 Coding Interview University coding-interview-university 这里列出的项目可以帮助…