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);
75 template <
typename TSensor,
typename TPixel>
76 static void SendPixelsInRenderThread(TSensor &Sensor,
bool use16BitFormat =
false, std::function<TArray<TPixel>(
void *, uint32)> Conversor = {});
82 const UTextureRenderTarget2D &RenderTarget,
84 FRHICommandListImmediate &InRHICmdList,
97 check(Sensor.CaptureRenderTarget !=
nullptr);
99 if (!Sensor.HasActorBegunPlay() || Sensor.IsPendingKill())
105 Sensor.EnqueueRenderSceneImmediate();
110 ENQUEUE_RENDER_COMMAND(FWritePixels_SendPixelsInRenderThread)
112 [&Sensor, use16BitFormat, Conversor = std::move(Conversor)](
auto &InRHICmdList)
mutable
114 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"FWritePixels_SendPixelsInRenderThread");
117 if (!Sensor.IsPendingKill())
120 [&Sensor, Frame =
FCarlaEngine::GetFrameCounter(), Conversor = std::move(Conversor)](
void *LockedData, uint32 Size, uint32 Offset, uint32 ExpectedRowBytes)
122 if (Sensor.IsPendingKill())
return;
124 TArray<TPixel> Converted;
129 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Data conversion");
130 Converted = Conversor(LockedData, Size);
131 LockedData =
reinterpret_cast<void *
>(Converted.GetData());
132 Size = Converted.Num() * Converted.GetTypeSize();
135 auto Stream = Sensor.GetDataStream(Sensor);
136 Stream.SetFrameNumber(Frame);
137 auto Buffer = Stream.PopBufferFromPool();
139 uint32 CurrentRowBytes = ExpectedRowBytes;
144 if (IsD3DPlatform(GMaxRHIShaderPlatform,
false))
146 CurrentRowBytes = Align(ExpectedRowBytes, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
147 if (ExpectedRowBytes != CurrentRowBytes)
149 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Buffer Copy (windows, row by row)");
150 Buffer.reset(Offset + Size);
151 auto DstRow = Buffer.begin() + Offset;
152 const uint8 *SrcRow =
reinterpret_cast<uint8 *
>(LockedData);
156 FMemory::Memcpy(DstRow, SrcRow, ExpectedRowBytes);
157 DstRow += ExpectedRowBytes;
158 SrcRow += CurrentRowBytes;
159 i += ExpectedRowBytes;
165 if (ExpectedRowBytes == CurrentRowBytes)
167 check(ExpectedRowBytes == CurrentRowBytes);
168 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Buffer Copy");
169 Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Size));
174 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Sending buffer");
182 #if defined(WITH_ROS2)
184 if (ROS2->IsEnabled())
186 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"ROS2 Send PixelReader");
188 auto Res = std::async(std::launch::async, [&Sensor, ROS2, &Stream, StreamId, BufView]()
193 auto WidthOpt = Sensor.GetAttribute(
"image_size_x");
194 if (WidthOpt.has_value())
195 W = FCString::Atoi(*WidthOpt->Value);
196 auto HeightOpt = Sensor.GetAttribute(
"image_size_y");
197 if (HeightOpt.has_value())
198 H = FCString::Atoi(*HeightOpt->Value);
199 auto FovOpt = Sensor.GetAttribute(
"fov");
200 if (FovOpt.has_value())
201 Fov = FCString::Atof(*FovOpt->Value);
203 AActor* ParentActor = Sensor.GetAttachParentActor();
206 FTransform LocalTransformRelativeToParent = Sensor.GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
207 ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, LocalTransformRelativeToParent, W, H, Fov, BufView, &Sensor);
211 ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, Stream.GetSensorTransform(), W, H, Fov, BufView, &Sensor);
218 SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend);
219 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Stream Send");
220 Stream.Send(Sensor, BufView);
226 *Sensor.CaptureRenderTarget,
229 std::move(FuncForSending));
235 Sensor.WaitForRenderThreadToFinish();