9 #include "CoreGlobals.h" 10 #include "Engine/TextureRenderTarget2D.h" 11 #include "Runtime/ImageWriteQueue/Public/ImagePixelData.h" 14 #define WIN32_LEAN_AND_MEAN 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,
93 template <
typename TSensor,
typename TPixel>
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);
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();
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.
static void SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat=false, std::function< TArray< TPixel >(void *, uint32)> Conversor={})
Convenience function to enqueue a render command that sends the pixels down the Sensor's data stream...
typename detail::CompileTimeTypeMapImpl< sizeof...(Items), Items... >::template get< InKey > get
std::deque< std::shared_ptr< SimpleWaypoint > > Buffer
Utils for reading pixels from UTextureRenderTarget2D.
static std::shared_ptr< BufferView > CreateFrom(Buffer &&buffer)
static void WritePixelsToBuffer(const UTextureRenderTarget2D &RenderTarget, uint32 Offset, FRHICommandListImmediate &InRHICmdList, FPixelReader::Payload FuncForSending)
Copy the pixels in RenderTarget into Buffer.
static uint64_t GetFrameCounter()
static Buffer Serialize(Sensor &sensor, Args &&... args)
Serialize the arguments provided into a Buffer by calling to the serializer registered for the given ...
detail::Stream< detail::MultiStreamState > Stream
A stream represents an unidirectional channel for sending data from server to client.
std::shared_ptr< BufferView > SharedBufferView
static std::shared_ptr< ROS2 > GetInstance()
std::function< void(void *, uint32, uint32, uint32)> Payload
static TFuture< bool > SavePixelsToDisk(UTextureRenderTarget2D &RenderTarget, const FString &FilePath)
Asynchronously save the pixels in RenderTarget to disk.
carla::streaming::detail::token_type token_type