xoyojank 的 UE4中的DynamicTexture数据更新
2016-04-08 11:03
603 查看
源地址 http://blog.csdn.net/xoyojank/article/details/49232841
问题:gamethread 和render thread
static ENGINE_API class UTexture2D *
CreateTransient
(
int32 InSizeX,
int32 InSizeY,
EPixelFormat InFormat
)
最近在UE4中实现了程序实时生成的Mesh顶点动画, 使用的顶点数目很多(几十万量级)
一开始是创建Dynamic Vertex Buffer, 然后每帧去更新顶点数据,发现效率比较低
效率的瓶颈在顶点坐标的计算上, 毕竟数量有点多
于是改成了基于Vertex Texture(Material中的World Position Offset)的实现,那VB就不用更新了, 只需要每帧更新Texture
这么做虽然传输的数据量是一致的, 但是可以把顶点坐标的一部分计算转入GPU端, 大大减轻了CPU压力
实际测下来发现GameThread的时间消耗仍然很高, 那进一步的优化就是把这部分操作扔进后台线程
[cpp] view
plain copy
void ADynamicTextureTestCharacter::UpdateInGameThread()
{
FTexture2DMipMap& Mip = DynamicTexture->PlatformData->Mips[0];
FVector4* Dest = (FVector4*)Mip.BulkData.Lock(LOCK_READ_WRITE);
WriteTextureData(Dest);
Mip.BulkData.Unlock();
DynamicTexture->UpdateResource();
}
改完一测, Crash了, 仔细一看, 原来是FTexture2D::UpdateResource()中会重新创建D3D Texture对象,相关函数必须是GameThread中调用才可以
本身这种数据更新的方式就有问题, 能不能直接更新到对应的D3D Texture中呢?搜索UE4的代码, 发现FTwitchLiveStreaming::UpdateWebCamTexture()中有比较高效的实现, 大致思路就是把数据发到RenderThread去直接更新, 调用的是RHIUpdateTexture2D
[cpp] view
plain copy
void ADynamicTextureTestCharacter::UpdateInRenderThread()
{
FVector4* Dest = DataBuffer.GetData();
WriteTextureData(Dest);
struct FUpdateTextureContext
{
uint8* SourceBuffer; // Render thread assumes ownership
uint32 BufferPitch;
FTexture2DResource* DestTextureResource;
} UpdateTextureContext =
{
(uint8*)Dest,
sizeof(FVector4) * DynamicTexture->GetSizeX(),
(FTexture2DResource*)DynamicTexture->Resource
};
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
UpdateDynamicTexture,
FUpdateTextureContext, Context, UpdateTextureContext,
{
const FUpdateTextureRegion2D UpdateRegion(
0, 0, // Dest X, Y
0, 0, // Source X, Y
Context.DestTextureResource->GetSizeX(), // Width
Context.DestTextureResource->GetSizeY()); // Height
RHIUpdateTexture2D(
Context.DestTextureResource->GetTexture2DRHI(), // Destination GPU texture
0, // Mip map index
UpdateRegion, // Update region
Context.BufferPitch, // Source buffer pitch
Context.SourceBuffer); // Source buffer pointer
});
}
这种做法不再权限于GameThread运行, 所以对性能影响比较小。 实际测试下来调用线程的执行时间比上一种做法要快1ms左右, 这对于FPS影响还是挺大的
参考资料
https://wiki.unrealengine.com/Dynamic_Textures
问题:gamethread 和render thread
static ENGINE_API class UTexture2D *
CreateTransient
(
int32 InSizeX,
int32 InSizeY,
EPixelFormat InFormat
)
最近在UE4中实现了程序实时生成的Mesh顶点动画, 使用的顶点数目很多(几十万量级)
一开始是创建Dynamic Vertex Buffer, 然后每帧去更新顶点数据,发现效率比较低
效率的瓶颈在顶点坐标的计算上, 毕竟数量有点多
于是改成了基于Vertex Texture(Material中的World Position Offset)的实现,那VB就不用更新了, 只需要每帧更新Texture
这么做虽然传输的数据量是一致的, 但是可以把顶点坐标的一部分计算转入GPU端, 大大减轻了CPU压力
实际测下来发现GameThread的时间消耗仍然很高, 那进一步的优化就是把这部分操作扔进后台线程
[cpp] view
plain copy
void ADynamicTextureTestCharacter::UpdateInGameThread()
{
FTexture2DMipMap& Mip = DynamicTexture->PlatformData->Mips[0];
FVector4* Dest = (FVector4*)Mip.BulkData.Lock(LOCK_READ_WRITE);
WriteTextureData(Dest);
Mip.BulkData.Unlock();
DynamicTexture->UpdateResource();
}
改完一测, Crash了, 仔细一看, 原来是FTexture2D::UpdateResource()中会重新创建D3D Texture对象,相关函数必须是GameThread中调用才可以
本身这种数据更新的方式就有问题, 能不能直接更新到对应的D3D Texture中呢?搜索UE4的代码, 发现FTwitchLiveStreaming::UpdateWebCamTexture()中有比较高效的实现, 大致思路就是把数据发到RenderThread去直接更新, 调用的是RHIUpdateTexture2D
[cpp] view
plain copy
void ADynamicTextureTestCharacter::UpdateInRenderThread()
{
FVector4* Dest = DataBuffer.GetData();
WriteTextureData(Dest);
struct FUpdateTextureContext
{
uint8* SourceBuffer; // Render thread assumes ownership
uint32 BufferPitch;
FTexture2DResource* DestTextureResource;
} UpdateTextureContext =
{
(uint8*)Dest,
sizeof(FVector4) * DynamicTexture->GetSizeX(),
(FTexture2DResource*)DynamicTexture->Resource
};
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
UpdateDynamicTexture,
FUpdateTextureContext, Context, UpdateTextureContext,
{
const FUpdateTextureRegion2D UpdateRegion(
0, 0, // Dest X, Y
0, 0, // Source X, Y
Context.DestTextureResource->GetSizeX(), // Width
Context.DestTextureResource->GetSizeY()); // Height
RHIUpdateTexture2D(
Context.DestTextureResource->GetTexture2DRHI(), // Destination GPU texture
0, // Mip map index
UpdateRegion, // Update region
Context.BufferPitch, // Source buffer pitch
Context.SourceBuffer); // Source buffer pointer
});
}
这种做法不再权限于GameThread运行, 所以对性能影响比较小。 实际测试下来调用线程的执行时间比上一种做法要快1ms左右, 这对于FPS影响还是挺大的
参考资料
https://wiki.unrealengine.com/Dynamic_Textures
相关文章推荐
- [IOS 开发] 获取设备UUID
- UINavigationBar的视图层级关系
- iOS---[UIDevice identifierForVendor]慎用!
- Qt 示例学习--2. calendar quick controls
- ios GPUImage简单滤镜 -- 录制视频(保存+聚焦)
- android 开发,百度地图 UI 控制器常用方法及作用
- UITabView使用详解
- LeetCode *** 232. Implement Queue using Stacks
- requirejs和r.js的心得
- 重写的easyui-validatebox 验证规则
- UI 常用(UIButton)
- easyui-validatebox form表单提交时校验 ajax提交时校验
- Android中的requestWindowFeature()函数
- 去掉UItableview headerview黏性
- 如何现实隐藏UIBarButtonItem? show/hide a UIBarButtonItem
- Building VirtualBox OSE 5.0.0 on Windows 7 (x86)
- Strtus2——request、response等内置对象的获取方式
- 解决AndroidStduio出现merger failed with multiple errors, see logs
- UITableView 相关属性的设置
- zookeeper、zkui、kafka部署技术