xoyojank 的 UE4中的DynamicTexture数据更新

源地址 http://blog.youkuaiyun.com/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
  1. void ADynamicTextureTestCharacter::UpdateInGameThread()  
  2. {  
  3.     FTexture2DMipMap& Mip = DynamicTexture->PlatformData->Mips[0];  
  4.     FVector4* Dest = (FVector4*)Mip.BulkData.Lock(LOCK_READ_WRITE);  
  5.     WriteTextureData(Dest);  
  6.     Mip.BulkData.Unlock();  
  7.     DynamicTexture->UpdateResource();  
  8. }  

改完一测, Crash了, 仔细一看, 原来是FTexture2D::UpdateResource()中会重新创建D3D Texture对象,相关函数必须是GameThread中调用才可以

本身这种数据更新的方式就有问题, 能不能直接更新到对应的D3D Texture中呢?搜索UE4的代码, 发现FTwitchLiveStreaming::UpdateWebCamTexture()中有比较高效的实现, 大致思路就是把数据发到RenderThread去直接更新, 调用的是RHIUpdateTexture2D

[cpp]  view plain  copy
  1. void ADynamicTextureTestCharacter::UpdateInRenderThread()  
  2. {  
  3.     FVector4* Dest = DataBuffer.GetData();  
  4.     WriteTextureData(Dest);  
  5.   
  6.     struct FUpdateTextureContext  
  7.     {  
  8.         uint8* SourceBuffer;    // Render thread assumes ownership  
  9.         uint32 BufferPitch;  
  10.         FTexture2DResource* DestTextureResource;  
  11.     } UpdateTextureContext =  
  12.     {  
  13.         (uint8*)Dest,  
  14.         sizeof(FVector4) * DynamicTexture->GetSizeX(),  
  15.         (FTexture2DResource*)DynamicTexture->Resource  
  16.     };  
  17.   
  18.     ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(  
  19.         UpdateDynamicTexture,  
  20.         FUpdateTextureContext, Context, UpdateTextureContext,  
  21.         {  
  22.         const FUpdateTextureRegion2D UpdateRegion(  
  23.         0, 0,       // Dest X, Y  
  24.         0, 0,       // Source X, Y  
  25.         Context.DestTextureResource->GetSizeX(), // Width  
  26.         Context.DestTextureResource->GetSizeY());    // Height  
  27.   
  28.         RHIUpdateTexture2D(  
  29.             Context.DestTextureResource->GetTexture2DRHI(),  // Destination GPU texture  
  30.             0,                                              // Mip map index  
  31.             UpdateRegion,                                   // Update region  
  32.             Context.BufferPitch,                        // Source buffer pitch  
  33.             Context.SourceBuffer);                          // Source buffer pointer  
  34.     });  
  35. }  

这种做法不再权限于GameThread运行, 所以对性能影响比较小。 实际测试下来调用线程的执行时间比上一种做法要快1ms左右, 这对于FPS影响还是挺大的


参考资料

https://wiki.unrealengine.com/Dynamic_Textures

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值