我試圖從一個遊戲攝像頭像素訪問數據和圖像保存到磁盤。最初,簡單的方法是使用一個渲染目標,隨後RenderTarget-> ReadPixels(),但由於本機實現ReadPixels的()包含)調用FlushRenderingCommands(,直到圖像保存它會阻止遊戲線程。作爲一個計算密集型操作,這是降低我的FPS方式太多。虛幻引擎4:適應ReadPixels(),以多線程框架
爲了解決這個問題,我想創建一個專用的線程可以訪問相機作爲CaptureComponent,然後按照類似的方法。但隨着FlushRenderingCommands()塊只能從遊戲線程調用的,我有沒有那個電話重寫ReadPixels(),(在各種各樣的非阻塞的方式,通過在https://wiki.unrealengine.com/Render_Target_Lookup教程啓發):但即使如此,我在保存圖像時(我確認這不是因爲實際保存到磁盤操作,而是因爲像素數據訪問),我的遊戲內FPS出現問題。我重寫的ReadPixels()函數如下所示,我希望得到一些關於這裏可能會出錯的一些建議。我不確定是否可以從非遊戲線程調用ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER,並且這是我的問題的一部分。
APIPCamera* cam = GameThread->CameraDirector->getCamera(0);
USceneCaptureComponent2D* capture = cam->getCaptureComponent(EPIPCameraType::PIP_CAMERA_TYPE_SCENE, true);
if (capture != nullptr) {
if (capture->TextureTarget != nullptr) {
FTextureRenderTargetResource* RenderResource = capture->TextureTarget->GetRenderTargetResource();
if (RenderResource != nullptr) {
width = capture->TextureTarget->GetSurfaceWidth();
height = capture->TextureTarget->GetSurfaceHeight();
// Read the render target surface data back.
struct FReadSurfaceContext
{
FRenderTarget* SrcRenderTarget;
TArray<FColor>* OutData;
FIntRect Rect;
FReadSurfaceDataFlags Flags;
};
bmp.Reset();
FReadSurfaceContext ReadSurfaceContext =
{
RenderResource,
&bmp,
FIntRect(0, 0, RenderResource->GetSizeXY().X, RenderResource->GetSizeXY().Y),
FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)
};
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
ReadSurfaceCommand,
FReadSurfaceContext, Context, ReadSurfaceContext,
{
RHICmdList.ReadSurfaceData(
Context.SrcRenderTarget->GetRenderTargetTexture(),
Context.Rect,
*Context.OutData,
Context.Flags
);
});
}
}
}
編輯:我注意到一件事是,口吃消失,如果我在我的渲染目標設置禁用HDR(但這會導致低質量的圖像):所以它似乎是合理的圖像的大小或許,由於我正在實施它的方式,它仍然阻塞了一個核心線程。
我也試圖通過分析工具看着它(單臺攝像機HDR的情況下):大部分是最大的安打所花費的時間方面的事件有「CPU攤位:等待事件」,「CPU攤主:睡眠」寫在他們,我猜表明他們正在等待GPU趕上? – HighVoltage
感謝您的評論:當我運行統計單位圖時,這是我發現:沒有人類發展報告:所有線程在一個不錯的利率。 HDR:渲染線程尖峯了很多,導致幀定時的尖峯。偶爾的GPU線程滯後。 i.imgur.com/S1YVGaz.png – HighVoltage
即使在渲染線程中,它看起來像'ReadSurfaceData'方法花費了太多時間。假設你沒有犯任何其他錯誤(如多次調用read函數),它使得多線程優化不可能使用這種特殊的讀取像素數據的方法。你有沒有想過使用原始的DirectX?您可以直接從RHI對象訪問它,但它使您的項目高度依賴於平臺。 – JKovalsky