源地址 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的時間消耗仍然很高, 那進一步的優化就是把這部分操作扔進後臺線程
- 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
- 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