38 using Payload = std::function<void(
void *, uint32, uint32, uint32)>;
44 UTextureRenderTarget2D &RenderTarget,
45 TArray<FColor> &BitMap);
50 static TUniquePtr<TImagePixelData<FColor>>
DumpPixels(
51 UTextureRenderTarget2D &RenderTarget);
57 UTextureRenderTarget2D &RenderTarget,
58 const FString &FilePath);
64 TUniquePtr<TImagePixelData<FColor>> PixelData,
65 const FString &FilePath);
73 template <
typename TSensor,
typename TPixel>
74 static void SendPixelsInRenderThread(TSensor &Sensor,
bool use16BitFormat =
false, std::function<TArray<TPixel>(
void *, uint32)> Conversor = {});
80 const UTextureRenderTarget2D &RenderTarget,
82 FRHICommandListImmediate &InRHICmdList,
95 check(Sensor.CaptureRenderTarget !=
nullptr);
97 if (!Sensor.HasActorBegunPlay() || Sensor.IsPendingKill())
103 Sensor.EnqueueRenderSceneImmediate();
106 ENQUEUE_RENDER_COMMAND(FWritePixels_SendPixelsInRenderThread)
108 [&Sensor, use16BitFormat, Conversor = std::move(Conversor)](
auto &InRHICmdList)
mutable
110 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"FWritePixels_SendPixelsInRenderThread");
113 if (!Sensor.IsPendingKill())
116 [&Sensor, Frame =
FCarlaEngine::GetFrameCounter(), Conversor = std::move(Conversor)](
void *LockedData, uint32 Size, uint32 Offset, uint32 ExpectedRowBytes)
118 if (Sensor.IsPendingKill())
return;
120 TArray<TPixel> Converted;
125 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Data conversion");
126 Converted = Conversor(LockedData, Size);
127 LockedData =
reinterpret_cast<void *
>(Converted.GetData());
128 Size = Converted.Num() * Converted.GetTypeSize();
131 auto Stream = Sensor.GetDataStream(Sensor);
132 Stream.SetFrameNumber(Frame);
133 auto Buffer = Stream.PopBufferFromPool();
135 uint32 CurrentRowBytes = ExpectedRowBytes;
139 if (IsD3DPlatform(GMaxRHIShaderPlatform,
false))
141 CurrentRowBytes = Align(ExpectedRowBytes, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
142 if (ExpectedRowBytes != CurrentRowBytes)
144 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Buffer Copy (windows, row by row)");
145 Buffer.reset(Offset + Size);
146 auto DstRow = Buffer.begin() + Offset;
147 const uint8 *SrcRow =
reinterpret_cast<uint8 *
>(LockedData);
151 FMemory::Memcpy(DstRow, SrcRow, ExpectedRowBytes);
152 DstRow += ExpectedRowBytes;
153 SrcRow += CurrentRowBytes;
154 i += ExpectedRowBytes;
160 if (ExpectedRowBytes == CurrentRowBytes)
162 check(ExpectedRowBytes == CurrentRowBytes);
163 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Buffer Copy");
164 Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Size));
169 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Sending buffer");
177 #if defined(WITH_ROS2)
179 if (ROS2->IsEnabled())
181 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"ROS2 Send PixelReader");
183 auto Res = std::async(std::launch::async, [&Sensor, ROS2, &Stream, StreamId, BufView]()
188 auto WidthOpt = Sensor.GetAttribute(
"image_size_x");
189 if (WidthOpt.has_value())
190 W = FCString::Atoi(*WidthOpt->Value);
191 auto HeightOpt = Sensor.GetAttribute(
"image_size_y");
192 if (HeightOpt.has_value())
193 H = FCString::Atoi(*HeightOpt->Value);
194 auto FovOpt = Sensor.GetAttribute(
"fov");
195 if (FovOpt.has_value())
196 Fov = FCString::Atof(*FovOpt->Value);
198 AActor* ParentActor = Sensor.GetAttachParentActor();
201 FTransform LocalTransformRelativeToParent = Sensor.GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
202 ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, LocalTransformRelativeToParent, W, H, Fov, BufView, &Sensor);
206 ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, Stream.GetSensorTransform(), W, H, Fov, BufView, &Sensor);
213 SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend);
214 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Stream Send");
215 Stream.Send(Sensor, BufView);
221 *Sensor.CaptureRenderTarget,
224 std::move(FuncForSending));
230 Sensor.WaitForRenderThreadToFinish();