37 UTextureRenderTarget2D &RenderTarget,
39 FRHICommandListImmediate &RHICmdList,
43 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"WritePixelsToBuffer");
44 check(IsInRenderingThread());
47 static_cast<const FTextureRenderTarget2DResource *
>(RenderTarget.GetResource());
48 if (RenderResource ==
nullptr)
52 auto Texture = RenderResource->GetRenderTargetTexture();
60 FRHIGPUTextureReadback *Readback =
nullptr;
61 int32 SlotIndex = INDEX_NONE;
62 TUniquePtr<FRHIGPUTextureReadback> FallbackReadback;
65 Readback = Pool->Acquire(SlotIndex);
67 if (Readback ==
nullptr)
69 FallbackReadback = MakeUnique<FRHIGPUTextureReadback>(TEXT(
"CameraBufferReadback"));
70 Readback = FallbackReadback.Get();
73 FIntPoint BackBufferSize = Texture->GetSizeXY();
74 EPixelFormat BackBufferPixelFormat = Texture->GetFormat();
76 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"EnqueueCopy");
77 Readback->EnqueueCopy(RHICmdList,
79 FResolveRect(0, 0, BackBufferSize.X, BackBufferSize.Y));
85 FRenderQueryRHIRef Query = RHICreateRenderQuery(RQT_AbsoluteTime);
86 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"create query");
87 RHICmdList.EndRenderQuery(Query);
88 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Flush");
89 RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread);
90 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"query result");
91 uint64 OldAbsTime = 0;
92 RHIGetRenderQueryResult(Query, OldAbsTime,
true);
99 AsyncTask(ENamedThreads::AnyBackgroundHiPriTask,
100 [=, FuncForSending = std::move(FuncForSending), Pool = std::move(Pool),
101 Fallback = std::move(FallbackReadback)]()
mutable {
103 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Wait GPU transfer");
108 while (!Readback->IsReady())
110 std::this_thread::sleep_for(std::chrono::microseconds(100));
111 if (++Spins > 50000u)
113 if (Pool && SlotIndex != INDEX_NONE)
114 Pool->Release(SlotIndex);
125 ENQUEUE_RENDER_COMMAND(PixelReaderDeliver)(
126 [=, FuncForSending = std::move(FuncForSending), Pool = std::move(Pool),
127 Fallback = std::move(Fallback)](FRHICommandListImmediate&)
mutable
130 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Readback data");
131 FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat];
132 uint32 ExpectedRowBytes = BackBufferSize.X * PixelFormat.BlockBytes;
133 int32 Size = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X));
137 int32 RowPitchInPixels = 0;
138 void* LockedData = Readback->Lock(RowPitchInPixels);
141 FuncForSending(LockedData, Size, Offset, ExpectedRowBytes);
146 if (Pool && SlotIndex != INDEX_NONE)
148 Pool->Release(SlotIndex);
156 UTextureRenderTarget2D &RenderTarget,
157 TArray<FColor> &BitMap)
159 check(IsInGameThread());
160 FTextureRenderTargetResource *RTResource =
161 RenderTarget.GameThread_GetRenderTargetResource();
162 if (RTResource ==
nullptr)
164 UE_LOG(LogCarla, Error, TEXT(
"FPixelReader: UTextureRenderTarget2D missing render target"));
167 FReadSurfaceDataFlags ReadPixelFlags(RCM_UNorm);
168 ReadPixelFlags.SetLinearToGamma(
true);
169 return RTResource->ReadPixels(BitMap, ReadPixelFlags);
194 TUniquePtr<TImagePixelData<FColor>> PixelData,
195 const FString &FilePath)
197 TUniquePtr<FImageWriteTask> ImageTask = MakeUnique<FImageWriteTask>();
198 ImageTask->PixelData = MoveTemp(PixelData);
199 ImageTask->Filename = FilePath;
200 ImageTask->Format = EImageFormat::PNG;
201 ImageTask->CompressionQuality = (int32) EImageCompressionQuality::Default;
202 ImageTask->bOverwriteFile =
true;
203 ImageTask->PixelPreProcessors.Add(TAsyncAlphaWrite<FColor>(255));
205 FHighResScreenshotConfig &HighResScreenshotConfig = GetHighResScreenshotConfig();
206 return HighResScreenshotConfig.ImageWriteQueue->Enqueue(MoveTemp(ImageTask));