CARLA
 
载入中...
搜索中...
未找到
PixelReader.cpp
浏览该文件的文档.
1// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include "Carla.h"
9
10#include "Engine/TextureRenderTarget2D.h"
11#include "Async/Async.h"
12#include "HighResScreenshot.h"
13#include "Runtime/ImageWriteQueue/Public/ImageWriteQueue.h"
14
15// =============================================================================
16// -- FPixelReader -------------------------------------------------------------
17// =============================================================================
18
20 const UTextureRenderTarget2D &RenderTarget,
21 uint32 Offset,
22 FRHICommandListImmediate &RHICmdList,
23 FPixelReader::Payload FuncForSending)
24{
25 TRACE_CPUPROFILER_EVENT_SCOPE_STR("WritePixelsToBuffer");
26 check(IsInRenderingThread());
27
28 auto RenderResource =
29 static_cast<const FTextureRenderTarget2DResource *>(RenderTarget.Resource);
30 FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture();
31 if (!Texture)
32 {
33 return;
34 }
35
36 auto BackBufferReadback = std::make_unique<FRHIGPUTextureReadback>(TEXT("CameraBufferReadback"));
37 FIntPoint BackBufferSize = Texture->GetSizeXY();
38 EPixelFormat BackBufferPixelFormat = Texture->GetFormat();
39 {
40 TRACE_CPUPROFILER_EVENT_SCOPE_STR("EnqueueCopy");
41 BackBufferReadback->EnqueueCopy(RHICmdList,
42 Texture,
43 FResolveRect(0, 0, BackBufferSize.X, BackBufferSize.Y));
44 }
45
46 // workaround to force RHI with Vulkan to refresh the fences state in the middle of frame
47 {
48 FRenderQueryRHIRef Query = RHICreateRenderQuery(RQT_AbsoluteTime);
49 TRACE_CPUPROFILER_EVENT_SCOPE_STR("create query");
50 RHICmdList.EndRenderQuery(Query);
51 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush");
52 RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread);
53 TRACE_CPUPROFILER_EVENT_SCOPE_STR("query result");
54 uint64 OldAbsTime = 0;
55 RHICmdList.GetRenderQueryResult(Query, OldAbsTime, true);
56 }
57
58 AsyncTask(ENamedThreads::HighTaskPriority, [=, Readback=std::move(BackBufferReadback)]() mutable {
59 {
60 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Wait GPU transfer");
61 while (!Readback->IsReady())
62 {
63 std::this_thread::yield();
64 }
65 }
66
67 {
68 TRACE_CPUPROFILER_EVENT_SCOPE_STR("Readback data");
69 FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat];
70 uint32 ExpectedRowBytes = BackBufferSize.X * PixelFormat.BlockBytes;
71 int32 Size = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X));
72 void* LockedData = Readback->Lock(Size);
73 if (LockedData)
74 {
75 FuncForSending(LockedData, Size, Offset, ExpectedRowBytes);
76 }
77 Readback->Unlock();
78 Readback.reset();
79 }
80 });
81}
82
84 UTextureRenderTarget2D &RenderTarget,
85 TArray<FColor> &BitMap)
86{
87 check(IsInGameThread());
88 FTextureRenderTargetResource *RTResource =
89 RenderTarget.GameThread_GetRenderTargetResource();
90 if (RTResource == nullptr)
91 {
92 UE_LOG(LogCarla, Error, TEXT("FPixelReader: UTextureRenderTarget2D missing render target"));
93 return false;
94 }
95 FReadSurfaceDataFlags ReadPixelFlags(RCM_UNorm);
96 ReadPixelFlags.SetLinearToGamma(true);
97 return RTResource->ReadPixels(BitMap, ReadPixelFlags);
98}
99
100TUniquePtr<TImagePixelData<FColor>> FPixelReader::DumpPixels(
101 UTextureRenderTarget2D &RenderTarget)
102{
103 const FIntPoint DestSize(RenderTarget.GetSurfaceWidth(), RenderTarget.GetSurfaceHeight());
104 TUniquePtr<TImagePixelData<FColor>> PixelData = MakeUnique<TImagePixelData<FColor>>(DestSize);
105 TArray<FColor> Pixels(PixelData->Pixels.GetData(), PixelData->Pixels.Num());
106 if (!WritePixelsToArray(RenderTarget, Pixels))
107 {
108 return nullptr;
109 }
110 PixelData->Pixels = Pixels;
111 return PixelData;
112}
113
115 UTextureRenderTarget2D &RenderTarget,
116 const FString &FilePath)
117{
118 return SavePixelsToDisk(DumpPixels(RenderTarget), FilePath);
119}
120
122 TUniquePtr<TImagePixelData<FColor>> PixelData,
123 const FString &FilePath)
124{
125 TUniquePtr<FImageWriteTask> ImageTask = MakeUnique<FImageWriteTask>();
126 ImageTask->PixelData = MoveTemp(PixelData);
127 ImageTask->Filename = FilePath;
128 ImageTask->Format = EImageFormat::PNG;
129 ImageTask->CompressionQuality = (int32) EImageCompressionQuality::Default;
130 ImageTask->bOverwriteFile = true;
131 ImageTask->PixelPreProcessors.Add(TAsyncAlphaWrite<FColor>(255));
132
133 FHighResScreenshotConfig &HighResScreenshotConfig = GetHighResScreenshotConfig();
134 return HighResScreenshotConfig.ImageWriteQueue->Enqueue(MoveTemp(ImageTask));
135}
static bool WritePixelsToArray(UTextureRenderTarget2D &RenderTarget, TArray< FColor > &BitMap)
Copy the pixels in RenderTarget into BitMap.
std::function< void(void *, uint32, uint32, uint32)> Payload
Definition PixelReader.h:38
static TUniquePtr< TImagePixelData< FColor > > DumpPixels(UTextureRenderTarget2D &RenderTarget)
Dump the pixels in RenderTarget.
static void WritePixelsToBuffer(const UTextureRenderTarget2D &RenderTarget, uint32 Offset, FRHICommandListImmediate &InRHICmdList, FPixelReader::Payload FuncForSending)
Copy the pixels in RenderTarget into Buffer.
static TFuture< bool > SavePixelsToDisk(UTextureRenderTarget2D &RenderTarget, const FString &FilePath)
Asynchronously save the pixels in RenderTarget to disk.