feat: 环境异步加载——HDR 解码移后台线程,运行时切换不卡主线程
decode 是切换耗时大头(4k ≈ 130-160ms),搬出主线程后运行时切换 只剩 GPU 段(~40ms)。IblGenerator 拆两段式:DecodeHdr(static, 纯 CPU 无线程状态,worker 可调)+ FromDecoded(GPU 生成,主线程); FromHdrEquirect 保留为同步便捷路径。Assets 层经 IAssetUploader 重载 + AssetManager 重载传递预解码产物(路径已缓存则丢弃去重)。 App 层单 in-flight 状态机:worker 只产出纯 CPU 像素数据,忙肋期 新请求记 pending 接力(只保留最终意图),OnUpdate 每帧收割 + SetEnvironment 换绑,析构 join。 实测(RTX 5060 Laptop,4 实例网格 + 运行中连切 3 环境): ~180fps 无感知尖峰;0 validation。
This commit is contained in:
@@ -197,26 +197,48 @@ namespace Engine
|
||||
}
|
||||
}
|
||||
|
||||
Scope<Cubemap> IblGenerator::FromHdrEquirect(const std::string& path,
|
||||
u32 faceSize)
|
||||
DecodedEquirect IblGenerator::DecodeHdr(const std::string& path)
|
||||
{
|
||||
const auto t0 = std::chrono::steady_clock::now();
|
||||
|
||||
// stbi_loadf 无共享可变状态(失败原因每次调用独立),可并发调用
|
||||
int w = 0, h = 0, channels = 0;
|
||||
f32* pixels = stbi_loadf(path.c_str(), &w, &h, &channels, STBI_rgb_alpha);
|
||||
if (!pixels) {
|
||||
ENGINE_ERROR("IblGenerator: failed to load HDR: {}", path);
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
const f32 decodeMs = MsSince(t0);
|
||||
auto cubemap = Generate(pixels, static_cast<u32>(w),
|
||||
static_cast<u32>(h), faceSize, path);
|
||||
DecodedEquirect decoded;
|
||||
decoded.w = static_cast<u32>(w);
|
||||
decoded.h = static_cast<u32>(h);
|
||||
decoded.pixels.assign(pixels,
|
||||
pixels + static_cast<size_t>(w) * h * 4);
|
||||
stbi_image_free(pixels);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
ENGINE_INFO("IblGenerator: HDR decode {:.2f} ms",
|
||||
decodeMs);
|
||||
return cubemap;
|
||||
Scope<Cubemap> IblGenerator::FromDecoded(const DecodedEquirect& decoded,
|
||||
u32 faceSize,
|
||||
const std::string& debugName)
|
||||
{
|
||||
if (!decoded.Valid()) {
|
||||
ENGINE_ERROR("IblGenerator: invalid decoded equirect ({})",
|
||||
debugName);
|
||||
return nullptr;
|
||||
}
|
||||
return Generate(decoded.pixels.data(), decoded.w, decoded.h,
|
||||
faceSize, debugName);
|
||||
}
|
||||
|
||||
Scope<Cubemap> IblGenerator::FromHdrEquirect(const std::string& path,
|
||||
u32 faceSize)
|
||||
{
|
||||
const auto t0 = std::chrono::steady_clock::now();
|
||||
DecodedEquirect decoded = DecodeHdr(path);
|
||||
if (!decoded.Valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
ENGINE_INFO("IblGenerator: HDR decode {:.2f} ms", MsSince(t0));
|
||||
return FromDecoded(decoded, faceSize, path);
|
||||
}
|
||||
|
||||
Scope<Cubemap> IblGenerator::Neutral(const glm::vec3& rgb)
|
||||
|
||||
Reference in New Issue
Block a user