资产浏览器可视化改造 + 材质缩略图 GPU 烘焙 + 纹理上传批式化
- 资产浏览器可视化与配色:面板重构(网格/列表/缩略图)、AssetKind 分类、 EditorColors 统一配色、AssetItemView 抽出条目绘制;HierarchyPanel/ MaterialEditorPanel 同步调整 - 材质缩略图改走 GPU 回读烘焙:MaterialPreviewPass 新增 bake pass (SDR atlas → host staging copyImageToBuffer)、Renderer 提供 Request/PollMaterialPreviewBake(无 waitIdle,依赖 per-slot fence), Editor 每帧排空后注入 ThumbnailCache——脱离预览 tile 池,消除"滚出视野 即失效/池耗尽"两问题 - 缩略图失效:BakedIdentity(serial, editVersion) 与当前材质身份比对, 换贴图槽(重载新 serial)/调参数(editVersion++)不符即 Invalidate 重烘, 修"修改材质后资产浏览器缩略图不更新" - 材质加载闸门:每帧至多 1 个 + 按实测耗时冷却,替代固定 2/帧 - 纹理上传批式化:VulkanAssetUploader 新增路径纹理缓存(跨材质去重, 同一贴图只解码/上传一次)+ 同批新纹理合并为单 cmd/单 submit/单 fence; Texture 抽出 RecordPixelsUpload/CreateDeferred/ReleasePendingStaging, 析构兜底释放 staging;MaterialAsset 纹理所有权移交 uploader 缓存—— 修大材质目录首次打开卡顿
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// ThumbnailCache.h:编辑器缩略图缓存(Content Browser / 材质纹理槽共用)。
|
||||
//
|
||||
// 逐帧限量 CPU 解码 + box 降采样 → ImGui 用户纹理(ImTextureData +
|
||||
// RegisterUserTexture)→ 后端建/传 VkImage。零引擎改动。
|
||||
//
|
||||
// 生命周期(详见 .cpp 注释):进程级静态单例,析构晚于 ImGuiLayer,
|
||||
// CPU 侧由静态析构回收、GPU 侧由 ImGui_ImplVulkan_Shutdown 回收。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_THUMBNAILCACHE_H
|
||||
#define HELLOVULKAN_THUMBNAILCACHE_H
|
||||
|
||||
#include <imgui.h> // ImTextureData / ImTextureRef
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
// 一次请求的结果:State==Ready 时 tex 可用于 ImGui::Image(tex, size)
|
||||
struct ThumbView {
|
||||
enum class State { Pending, Ready, Failed };
|
||||
State state = State::Pending;
|
||||
ImTextureRef tex{};
|
||||
int w = 0; // 缩略图原始像素尺寸(按比例显示用)
|
||||
int h = 0;
|
||||
};
|
||||
|
||||
class EditorThumbnailCache {
|
||||
public:
|
||||
// 进程级单例(编辑器首帧 BeginFrame 时惰性构造)
|
||||
static EditorThumbnailCache& Get();
|
||||
|
||||
// 每帧一次:Editor::Draw 开头(ImGui::NewFrame 之后、面板绘制之前)
|
||||
void BeginFrame();
|
||||
|
||||
// 幂等请求:命中且就绪即返回;未命中则入队,本帧返回 Pending
|
||||
ThumbView Request(const std::string& assetPath);
|
||||
|
||||
// 只读查状态(**不**触发解码入队):缺省 → Failed。材质球烘焙用——
|
||||
// 材质路径不走 stbi 解码,注入前必须能区分"未注入"与"上传中"
|
||||
//(Pending 表示已注入、等后端建纹理)
|
||||
ThumbView Peek(const std::string& assetPath);
|
||||
|
||||
// 作废某条目的缓存纹理(材质重载/参数编辑后缩略图过期 → 重烘)。
|
||||
// 丢弃 CPU 记录、纹理交回回收流程;随后 Peek 缺省 → Failed
|
||||
void Invalidate(const std::string& assetPath);
|
||||
|
||||
// ---- 材质球烘焙(GPU 回读结果注入)----
|
||||
// path ↔ key 幂等映射:Renderer 只接受/回传 u64 令牌,App 侧登记
|
||||
unsigned long long BakeKeyForPath(const std::string& path);
|
||||
// 回读结果注入:RGBA8 像素(w×h)→ 缩略图纹理(内部等比降到最长边
|
||||
// ≤ kThumbMaxDim)。key 未登记则忽略
|
||||
void CompleteBake(unsigned long long key, const unsigned char* rgba,
|
||||
int w, int h);
|
||||
|
||||
EditorThumbnailCache(const EditorThumbnailCache&) = delete;
|
||||
EditorThumbnailCache& operator=(const EditorThumbnailCache&) = delete;
|
||||
|
||||
private:
|
||||
EditorThumbnailCache() = default;
|
||||
~EditorThumbnailCache();
|
||||
|
||||
struct Entry {
|
||||
ImTextureData* tex = nullptr; // 非拥有(删由回收流程)
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
ThumbView::State state = ThumbView::State::Pending;
|
||||
unsigned long long lastUseFrame = 0;
|
||||
int pendingFrames = 0; // 注册后等待后端上传的帧数
|
||||
};
|
||||
|
||||
void DecodeOne(const std::string& path, Entry& e); // 解码→降采样→注册
|
||||
// 源像素(RGBA8,sw×sh)→ 等比降采样 → ImTextureData 注册(解码与
|
||||
// 烘焙回读注入共用同一条上传路径)
|
||||
static void UploadRGBA8(const unsigned char* src, int sw, int sh, Entry& e);
|
||||
void InjectRGBA8(const std::string& path, const unsigned char* rgba,
|
||||
int w, int h);
|
||||
bool RetireOne(); // 淘汰最久未用(返回是否淘汰)
|
||||
void DrainRetired(); // 后端已释放→回收
|
||||
|
||||
std::unordered_map<std::string, Entry> m_Entries;
|
||||
std::deque<std::string> m_Queue; // 待解码(重复请求命 entries,天然去重)
|
||||
std::vector<ImTextureData*> m_Retire; // 已标 WantDestroy,等后端释放
|
||||
unsigned long long m_Frame = 0;
|
||||
|
||||
// 材质球烘焙 path ↔ key 映射(幂等分配;回读完成即注销)
|
||||
unsigned long long m_BakeKeyCounter = 0;
|
||||
std::unordered_map<std::string, unsigned long long> m_PathToBakeKey;
|
||||
std::unordered_map<unsigned long long, std::string> m_BakeKeyToPath;
|
||||
};
|
||||
|
||||
#endif //HELLOVULKAN_THUMBNAILCACHE_H
|
||||
Reference in New Issue
Block a user