CARLA
PixelReader.cpp
Go to the documentation of this file.
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 // -- Local variables and types ------------------------------------------------
17 // =============================================================================
18 
20 {
21  LockTexture(FRHITexture2D *InTexture, uint32 &Stride)
22  : Texture(InTexture),
23  Source(reinterpret_cast<const uint8 *>(
24  RHILockTexture2D(Texture, 0, RLM_ReadOnly, Stride, false))) {}
25 
27  {
28  RHIUnlockTexture2D(Texture, 0, false);
29  }
30 
31  FRHITexture2D *Texture;
32 
33  const uint8 *Source;
34 };
35 
36 // =============================================================================
37 // -- FPixelReader -------------------------------------------------------------
38 // =============================================================================
39 
41  const UTextureRenderTarget2D &RenderTarget,
42  uint32 Offset,
43  FRHICommandListImmediate &RHICmdList,
44  FPixelReader::Payload FuncForSending)
45 {
46  TRACE_CPUPROFILER_EVENT_SCOPE_STR("WritePixelsToBuffer");
47  check(IsInRenderingThread());
48 
49  auto RenderResource =
50  static_cast<const FTextureRenderTarget2DResource *>(RenderTarget.Resource);
51  FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture();
52  if (!Texture)
53  {
54  return;
55  }
56 
57  auto BackBufferReadback = std::make_unique<FRHIGPUTextureReadback>(TEXT("CameraBufferReadback"));
58  FIntPoint BackBufferSize = Texture->GetSizeXY();
59  EPixelFormat BackBufferPixelFormat = Texture->GetFormat();
60  {
61  TRACE_CPUPROFILER_EVENT_SCOPE_STR("EnqueueCopy");
62  BackBufferReadback->EnqueueCopy(RHICmdList,
63  Texture,
64  FResolveRect(0, 0, BackBufferSize.X, BackBufferSize.Y));
65  }
66 
67  // workaround to force RHI with Vulkan to refresh the fences state in the middle of frame
68  {
69  FRenderQueryRHIRef Query = RHICreateRenderQuery(RQT_AbsoluteTime);
70  TRACE_CPUPROFILER_EVENT_SCOPE_STR("create query");
71  RHICmdList.EndRenderQuery(Query);
72  TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush");
73  RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread);
74  TRACE_CPUPROFILER_EVENT_SCOPE_STR("query result");
75  uint64 OldAbsTime = 0;
76  RHICmdList.GetRenderQueryResult(Query, OldAbsTime, true);
77  }
78 
79  AsyncTask(ENamedThreads::AnyNormalThreadNormalTask, [=, Readback=std::move(BackBufferReadback)]() mutable {
80  {
81  TRACE_CPUPROFILER_EVENT_SCOPE_STR("Wait GPU transfer");
82  while (!Readback->IsReady())
83  {
84  std::this_thread::yield();
85  }
86  }
87 
88  FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat];
89  int32 Size = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X));
90  void* LockedData = Readback->Lock(Size);
91  if (LockedData)
92  {
93  FuncForSending(LockedData, Size, Offset);
94  }
95  Readback->Unlock();
96  Readback.reset();
97  });
98 }
99 
101  UTextureRenderTarget2D &RenderTarget,
102  TArray<FColor> &BitMap)
103 {
104  check(IsInGameThread());
105  FTextureRenderTargetResource *RTResource =
106  RenderTarget.GameThread_GetRenderTargetResource();
107  if (RTResource == nullptr)
108  {
109  UE_LOG(LogCarla, Error, TEXT("FPixelReader: UTextureRenderTarget2D missing render target"));
110  return false;
111  }
112  FReadSurfaceDataFlags ReadPixelFlags(RCM_UNorm);
113  ReadPixelFlags.SetLinearToGamma(true);
114  return RTResource->ReadPixels(BitMap, ReadPixelFlags);
115 }
116 
117 TUniquePtr<TImagePixelData<FColor>> FPixelReader::DumpPixels(
118  UTextureRenderTarget2D &RenderTarget)
119 {
120  const FIntPoint DestSize(RenderTarget.GetSurfaceWidth(), RenderTarget.GetSurfaceHeight());
121  TUniquePtr<TImagePixelData<FColor>> PixelData = MakeUnique<TImagePixelData<FColor>>(DestSize);
122  TArray<FColor> Pixels(PixelData->Pixels.GetData(), PixelData->Pixels.Num());
123  if (!WritePixelsToArray(RenderTarget, Pixels))
124  {
125  return nullptr;
126  }
127  return PixelData;
128 }
129 
131  UTextureRenderTarget2D &RenderTarget,
132  const FString &FilePath)
133 {
134  return SavePixelsToDisk(DumpPixels(RenderTarget), FilePath);
135 }
136 
138  TUniquePtr<TImagePixelData<FColor>> PixelData,
139  const FString &FilePath)
140 {
141  TUniquePtr<FImageWriteTask> ImageTask = MakeUnique<FImageWriteTask>();
142  ImageTask->PixelData = MoveTemp(PixelData);
143  ImageTask->Filename = FilePath;
144  ImageTask->Format = EImageFormat::PNG;
145  ImageTask->CompressionQuality = (int32) EImageCompressionQuality::Default;
146  ImageTask->bOverwriteFile = true;
147  ImageTask->PixelPreProcessors.Add(TAsyncAlphaWrite<FColor>(255));
148 
149  FHighResScreenshotConfig &HighResScreenshotConfig = GetHighResScreenshotConfig();
150  return HighResScreenshotConfig.ImageWriteQueue->Enqueue(MoveTemp(ImageTask));
151 }
static TUniquePtr< TImagePixelData< FColor > > DumpPixels(UTextureRenderTarget2D &RenderTarget)
Dump the pixels in RenderTarget.
static bool WritePixelsToArray(UTextureRenderTarget2D &RenderTarget, TArray< FColor > &BitMap)
Copy the pixels in RenderTarget into BitMap.
LockTexture(FRHITexture2D *InTexture, uint32 &Stride)
Definition: PixelReader.cpp:21
static void WritePixelsToBuffer(const UTextureRenderTarget2D &RenderTarget, uint32 Offset, FRHICommandListImmediate &InRHICmdList, FPixelReader::Payload FuncForSending)
Copy the pixels in RenderTarget into Buffer.
Definition: PixelReader.cpp:40
std::function< void(void *, uint32, uint32)> Payload
Definition: PixelReader.h:32
const uint8 * Source
Definition: PixelReader.cpp:33
static TFuture< bool > SavePixelsToDisk(UTextureRenderTarget2D &RenderTarget, const FString &FilePath)
Asynchronously save the pixels in RenderTarget to disk.
FRHITexture2D * Texture
Definition: PixelReader.cpp:31