diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp index 401277846..58275648e 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.cpp @@ -8,6 +8,7 @@ #include "Carla/Sensor/PixelReader.h" #include "Engine/TextureRenderTarget2D.h" +#include "Async/Async.h" #include "HighResScreenshot.h" #include "Runtime/ImageWriteQueue/Public/ImageWriteQueue.h" @@ -36,18 +37,15 @@ struct LockTexture // -- Static local functions --------------------------------------------------- // ============================================================================= -// Temporal; this avoid allocating the array each time and also avoids checking -// for a bigger texture, ReadSurfaceData will allocate the space needed. -TArray gPixels; - static void WritePixelsToBuffer_Vulkan( const UTextureRenderTarget2D &RenderTarget, - carla::Buffer &Buffer, uint32 Offset, - FRHICommandListImmediate &InRHICmdList) + FRHICommandListImmediate &RHICmdList, + FPixelReader::Payload FuncForSending) { TRACE_CPUPROFILER_EVENT_SCOPE_STR("WritePixelsToBuffer_Vulkan"); check(IsInRenderingThread()); + auto RenderResource = static_cast(RenderTarget.Resource); FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); @@ -56,21 +54,46 @@ static void WritePixelsToBuffer_Vulkan( return; } - FIntPoint Rect = RenderResource->GetSizeXY(); + auto BackBufferReadback = std::make_unique(TEXT("CameraBufferReadback")); + FIntPoint BackBufferSize = Texture->GetSizeXY(); + EPixelFormat BackBufferPixelFormat = Texture->GetFormat(); + { + TRACE_CPUPROFILER_EVENT_SCOPE_STR("EnqueueCopy"); + BackBufferReadback->EnqueueCopy(RHICmdList, Texture, FResolveRect(0, 0, BackBufferSize.X, BackBufferSize.Y)); + } - // NS: Extra copy here, don't know how to avoid it. + // workaround to force RHI with Vulkan to refresh the fences state in the middle of frame { - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Read Surface"); - InRHICmdList.ReadSurfaceData( - Texture, - FIntRect(0, 0, Rect.X, Rect.Y), - gPixels, - FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)); - } - { - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy"); - Buffer.copy_from(Offset, gPixels); + FRenderQueryRHIRef Query = RHICreateRenderQuery(RQT_AbsoluteTime); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("create query"); + RHICmdList.EndRenderQuery(Query); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush"); + RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("query result"); + uint64 OldAbsTime = 0; + RHICmdList.GetRenderQueryResult(Query, OldAbsTime, true); } + + AsyncTask(ENamedThreads::AnyNormalThreadNormalTask, [=, Readback=std::move(BackBufferReadback)]() mutable { + { + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Wait GPU transfer"); + while (!Readback->IsReady()) + { + std::this_thread::yield(); + } + } + + FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat]; + int32 Count = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X)); + void* LockedData = Readback->Lock(Count); + if (LockedData) + { + FuncForSending(LockedData, Count, Offset); + } + Readback->Unlock(); + Readback.reset(); + }); + } // Temporal; this avoid allocating the array each time @@ -78,12 +101,13 @@ TArray gFloatPixels; static void WriteFloatPixelsToBuffer_Vulkan( const UTextureRenderTarget2D &RenderTarget, - carla::Buffer &Buffer, uint32 Offset, - FRHICommandListImmediate &InRHICmdList) + FRHICommandListImmediate &RHICmdList, + FPixelReader::Payload FuncForSending) { + TRACE_CPUPROFILER_EVENT_SCOPE_STR("WritePixelsToBuffer_Vulkan"); check(IsInRenderingThread()); - gFloatPixels.Empty(); + auto RenderResource = static_cast(RenderTarget.Resource); FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); @@ -92,25 +116,58 @@ static void WriteFloatPixelsToBuffer_Vulkan( return; } - FIntPoint Rect = RenderResource->GetSizeXY(); - - // NS: Extra copy here, don't know how to avoid it. - InRHICmdList.ReadSurfaceFloatData( - Texture, - FIntRect(0, 0, Rect.X, Rect.Y), - gFloatPixels, - CubeFace_PosX,0,0); - - TArray IntermediateBuffer; - IntermediateBuffer.Reserve(gFloatPixels.Num() * 2); - for (FFloat16Color& color : gFloatPixels) { - float x = (color.R.GetFloat() - 0.5f)*4.f; - float y = (color.G.GetFloat() - 0.5f)*4.f; - IntermediateBuffer.Add(x); - IntermediateBuffer.Add(y); + auto BackBufferReadback = std::make_unique(TEXT("CameraBufferReadback")); + FIntPoint BackBufferSize = Texture->GetSizeXY(); + EPixelFormat BackBufferPixelFormat = Texture->GetFormat(); + { + TRACE_CPUPROFILER_EVENT_SCOPE_STR("EnqueueCopy"); + BackBufferReadback->EnqueueCopy(RHICmdList, Texture, FResolveRect(0, 0, BackBufferSize.X, BackBufferSize.Y)); } - Buffer.copy_from(Offset, IntermediateBuffer); -} + + // workaround to force RHI with Vulkan to refresh the fences state in the middle of frame + { + FRenderQueryRHIRef Query = RHICreateRenderQuery(RQT_AbsoluteTime); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("create query"); + RHICmdList.EndRenderQuery(Query); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush"); + RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("query result"); + uint64 OldAbsTime = 0; + RHICmdList.GetRenderQueryResult(Query, OldAbsTime, true); + } + + AsyncTask(ENamedThreads::AnyNormalThreadNormalTask, [=, Readback=std::move(BackBufferReadback)]() mutable { + { + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Wait GPU transfer"); + while (!Readback->IsReady()) + { + std::this_thread::yield(); + } + } + + FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat]; + int32 Count = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X)); + int32 TotalPixels = (BackBufferSize.Y * BackBufferSize.X); + void* LockedData = Readback->Lock(Count); + if (LockedData) + { + TArray IntermediateBuffer; + FFloat16Color *Data = reinterpret_cast(LockedData); + IntermediateBuffer.Reserve(TotalPixels * 2); + for (int i=0; iR.GetFloat() - 0.5f) * 4.f; + float y = (Data->G.GetFloat() - 0.5f) * 4.f; + IntermediateBuffer.Add(x); + IntermediateBuffer.Add(y); + ++Data; + } + FuncForSending(reinterpret_cast(IntermediateBuffer.GetData()), TotalPixels * sizeof(float) * 2 , Offset); + } + Readback->Unlock(); + Readback.reset(); + }); + } // ============================================================================= // -- FPixelReader ------------------------------------------------------------- @@ -171,11 +228,10 @@ TFuture FPixelReader::SavePixelsToDisk( void FPixelReader::WritePixelsToBuffer( UTextureRenderTarget2D &RenderTarget, - carla::Buffer &Buffer, uint32 Offset, FRHICommandListImmediate &InRHICmdList, - bool use16BitFormat - ) + FPixelReader::Payload FuncForSending, + bool use16BitFormat) { TRACE_CPUPROFILER_EVENT_SCOPE_STR("WritePixelsToBuffer"); check(IsInRenderingThread()); @@ -184,15 +240,15 @@ void FPixelReader::WritePixelsToBuffer( { if (use16BitFormat) { - WriteFloatPixelsToBuffer_Vulkan(RenderTarget, Buffer, Offset, InRHICmdList); + WriteFloatPixelsToBuffer_Vulkan(RenderTarget, Offset, InRHICmdList, std::move(FuncForSending)); } else { - WritePixelsToBuffer_Vulkan(RenderTarget, Buffer, Offset, InRHICmdList); + WritePixelsToBuffer_Vulkan(RenderTarget, Offset, InRHICmdList, std::move(FuncForSending)); } return; } - + /* FTextureRenderTargetResource* RenderTargetResource = RenderTarget.GetRenderTargetResource(); if(!RenderTargetResource) { @@ -235,4 +291,5 @@ void FPixelReader::WritePixelsToBuffer( Buffer.copy_from(Offset, Source, ExpectedStride * Height); } } + */ } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h index 339222802..e362f9c0a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader.h @@ -11,6 +11,7 @@ #include "Runtime/ImageWriteQueue/Public/ImagePixelData.h" #include +#include #include #include #include @@ -26,6 +27,8 @@ class FPixelReader { public: + using Payload = std::function; + /// Copy the pixels in @a RenderTarget into @a BitMap. /// /// @pre To be called from game-thread. @@ -71,9 +74,9 @@ private: /// @pre To be called from render-thread. static void WritePixelsToBuffer( UTextureRenderTarget2D &RenderTarget, - carla::Buffer &Buffer, uint32 Offset, FRHICommandListImmediate &InRHICmdList, + FPixelReader::Payload FuncForSending, bool use16BitFormat = false); }; @@ -101,26 +104,43 @@ void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat // game-thread. ENQUEUE_RENDER_COMMAND(FWritePixels_SendPixelsInRenderThread) ( - [&Sensor, Stream=Sensor.GetDataStream(Sensor), use16BitFormat](auto &InRHICmdList) mutable + [&Sensor, use16BitFormat](auto &InRHICmdList) mutable { TRACE_CPUPROFILER_EVENT_SCOPE_STR("FWritePixels_SendPixelsInRenderThread"); /// @todo Can we make sure the sensor is not going to be destroyed? if (!Sensor.IsPendingKill()) { - auto Buffer = Stream.PopBufferFromPool(); + FPixelReader::Payload FuncForSending = [&Sensor, Frame = FCarlaEngine::GetFrameCounter()](void *LockedData, uint32 Count, uint32 Offset) + { + if (Sensor.IsPendingKill()) return; + + auto Stream = Sensor.GetDataStream(Sensor); + // Stream.SetFrameNumber(Frame); + auto Buffer = Stream.PopBufferFromPool(); + + { + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy"); + Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Count)); + } + { + // send + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Sending buffer"); + if(Buffer.data()) + { + SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend); + TRACE_CPUPROFILER_EVENT_SCOPE_STR("Stream Send"); + Stream.Send(Sensor, std::move(Buffer)); + } + } + }; + WritePixelsToBuffer( *Sensor.CaptureRenderTarget, - Buffer, carla::sensor::SensorRegistry::get::type::header_offset, - InRHICmdList, use16BitFormat); - - if(Buffer.data()) - { - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend); - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Stream Send"); - Stream.Send(Sensor, std::move(Buffer)); - } + InRHICmdList, + std::move(FuncForSending), + use16BitFormat); } } ); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader2.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader2.cpp deleted file mode 100644 index 4a70f4ab3..000000000 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader2.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma -// de Barcelona (UAB). -// -// This work is licensed under the terms of the MIT license. -// For a copy, see . - -#include "Carla.h" -#include "Carla/Sensor/PixelReader2.h" - -#include "Engine/TextureRenderTarget2D.h" -#include "Async/Async.h" -#include "HighResScreenshot.h" -#include "Runtime/ImageWriteQueue/Public/ImageWriteQueue.h" - -// ============================================================================= -// -- Local variables and types ------------------------------------------------ -// ============================================================================= - -struct LockTexture2 -{ - LockTexture2(FRHITexture2D *InTexture, uint32 &Stride) - : Texture(InTexture), - Source(reinterpret_cast( - RHILockTexture2D(Texture, 0, RLM_ReadOnly, Stride, false))) {} - - ~LockTexture2() - { - RHIUnlockTexture2D(Texture, 0, false); - } - - FRHITexture2D *Texture; - - const uint8 *Source; -}; - -// ============================================================================= -// -- Static local functions --------------------------------------------------- -// ============================================================================= - -// Temporal; this avoid allocating the array each time and also avoids checking -// for a bigger texture, ReadSurfaceData will allocate the space needed. -TArray gPixels2; - -static void WritePixelsToBuffer_Vulkan2( - const UTextureRenderTarget2D &RenderTarget, - uint32 Offset, - FRHICommandListImmediate &RHICmdList, - std::function FuncForSending) -{ - TRACE_CPUPROFILER_EVENT_SCOPE_STR(__FUNCTION__); - check(IsInRenderingThread()); - - auto RenderResource = static_cast(RenderTarget.Resource); - FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); - if (!Texture) - { - return; - } - - auto BackBufferReadback = std::make_unique(TEXT("CameraBufferReadback")); - FIntPoint BackBufferSize = Texture->GetSizeXY(); - EPixelFormat BackBufferPixelFormat = Texture->GetFormat(); - { - TRACE_CPUPROFILER_EVENT_SCOPE_STR("EnqueueCopy"); - BackBufferReadback->EnqueueCopy(RHICmdList, Texture, FResolveRect(0, 0, BackBufferSize.X, BackBufferSize.Y)); - } - - // workaround to force RHI with Vulkan to refresh the fences state in the middle of frame - { - FRenderQueryRHIRef Query = RHICreateRenderQuery(RQT_AbsoluteTime); - TRACE_CPUPROFILER_EVENT_SCOPE_STR("create query"); - RHICmdList.EndRenderQuery(Query); - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Flush"); - RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); - TRACE_CPUPROFILER_EVENT_SCOPE_STR("query result"); - uint64 OldAbsTime = 0; - RHICmdList.GetRenderQueryResult(Query, OldAbsTime, true); - } - - AsyncTask(ENamedThreads::AnyNormalThreadNormalTask, [=, Readback=std::move(BackBufferReadback)]() mutable { - { - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Wait GPU transfer"); - while (!Readback->IsReady()) - { - std::this_thread::yield(); - } - } - - FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat]; - int32 Count = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X)); - void* LockedData = Readback->Lock(Count); - if (LockedData) - { - FuncForSending(LockedData, Count, Offset); - } - Readback->Unlock(); - Readback.reset(); - }); - -} - -// Temporal; this avoid allocating the array each time -TArray gFloatPixels2; - -static void WriteFloatPixelsToBuffer_Vulkan2( - const UTextureRenderTarget2D &RenderTarget, - carla::Buffer &Buffer, - uint32 Offset, - FRHICommandListImmediate &InRHICmdList) - -{ - check(IsInRenderingThread()); - gFloatPixels2.Empty(); - auto RenderResource = - static_cast(RenderTarget.Resource); - FTexture2DRHIRef Texture = RenderResource->GetRenderTargetTexture(); - if (!Texture) - { - return; - } - - FIntPoint Rect = RenderResource->GetSizeXY(); - - // NS: Extra copy here, don't know how to avoid it. - InRHICmdList.ReadSurfaceFloatData( - Texture, - FIntRect(0, 0, Rect.X, Rect.Y), - gFloatPixels2, - CubeFace_PosX,0,0); - - TArray IntermediateBuffer; - IntermediateBuffer.Reserve(gFloatPixels2.Num() * 2); - for (FFloat16Color& color : gFloatPixels2) { - float x = (color.R.GetFloat() - 0.5f)*4.f; - float y = (color.G.GetFloat() - 0.5f)*4.f; - IntermediateBuffer.Add(x); - IntermediateBuffer.Add(y); - } - Buffer.copy_from(Offset, IntermediateBuffer); -} - -// ============================================================================= -// -- FPixelReader ------------------------------------------------------------- -// ============================================================================= - -bool FPixelReader2::WritePixelsToArray( - UTextureRenderTarget2D &RenderTarget, - TArray &BitMap) -{ - check(IsInGameThread()); - FTextureRenderTargetResource *RTResource = - RenderTarget.GameThread_GetRenderTargetResource(); - if (RTResource == nullptr) - { - UE_LOG(LogCarla, Error, TEXT("FPixelReader2: UTextureRenderTarget2D missing render target")); - return false; - } - FReadSurfaceDataFlags ReadPixelFlags(RCM_UNorm); - ReadPixelFlags.SetLinearToGamma(true); - return RTResource->ReadPixels(BitMap, ReadPixelFlags); -} - -TUniquePtr> FPixelReader2::DumpPixels( - UTextureRenderTarget2D &RenderTarget) -{ - const FIntPoint DestSize(RenderTarget.GetSurfaceWidth(), RenderTarget.GetSurfaceHeight()); - TUniquePtr> PixelData = MakeUnique>(DestSize); - TArray Pixels(PixelData->Pixels.GetData(), PixelData->Pixels.Num()); - if (!WritePixelsToArray(RenderTarget, Pixels)) - { - return nullptr; - } - return PixelData; -} - -TFuture FPixelReader2::SavePixelsToDisk( - UTextureRenderTarget2D &RenderTarget, - const FString &FilePath) -{ - return SavePixelsToDisk(DumpPixels(RenderTarget), FilePath); -} - -TFuture FPixelReader2::SavePixelsToDisk( - TUniquePtr> PixelData, - const FString &FilePath) -{ - TUniquePtr ImageTask = MakeUnique(); - ImageTask->PixelData = MoveTemp(PixelData); - ImageTask->Filename = FilePath; - ImageTask->Format = EImageFormat::PNG; - ImageTask->CompressionQuality = (int32) EImageCompressionQuality::Default; - ImageTask->bOverwriteFile = true; - ImageTask->PixelPreProcessors.Add(TAsyncAlphaWrite(255)); - - FHighResScreenshotConfig &HighResScreenshotConfig = GetHighResScreenshotConfig(); - return HighResScreenshotConfig.ImageWriteQueue->Enqueue(MoveTemp(ImageTask)); -} - -void FPixelReader2::WritePixelsToBuffer( - UTextureRenderTarget2D &RenderTarget, - uint32 Offset, - FRHICommandListImmediate &InRHICmdList, - std::function FuncForSending, - bool use16BitFormat) -{ - TRACE_CPUPROFILER_EVENT_SCOPE_STR(__FUNCTION__); - check(IsInRenderingThread()); - - if (IsVulkanPlatform(GMaxRHIShaderPlatform) || IsD3DPlatform(GMaxRHIShaderPlatform, false)) - { - if (use16BitFormat) - { - // WriteFloatPixelsToBuffer_Vulkan2(RenderTarget, Buffer, Offset, InRHICmdList); - } - else - { - WritePixelsToBuffer_Vulkan2(RenderTarget, Offset, InRHICmdList, std::move(FuncForSending)); - } - } -} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader2.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader2.h deleted file mode 100644 index 3840f7811..000000000 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/PixelReader2.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma -// de Barcelona (UAB). -// -// This work is licensed under the terms of the MIT license. -// For a copy, see . - -#pragma once - -#include "CoreGlobals.h" -#include "Engine/TextureRenderTarget2D.h" -#include "Runtime/ImageWriteQueue/Public/ImagePixelData.h" - -#include -#include -#include -#include -#include - -// ============================================================================= -// -- FPixelReader ------------------------------------------------------------- -// ============================================================================= - -/// Utils for reading pixels from UTextureRenderTarget2D. -/// -/// @todo This class only supports PF_R8G8B8A8 format. -class FPixelReader2 -{ -public: - - /// Copy the pixels in @a RenderTarget into @a BitMap. - /// - /// @pre To be called from game-thread. - static bool WritePixelsToArray( - UTextureRenderTarget2D &RenderTarget, - TArray &BitMap); - - /// Dump the pixels in @a RenderTarget. - /// - /// @pre To be called from game-thread. - static TUniquePtr> DumpPixels( - UTextureRenderTarget2D &RenderTarget); - - /// Asynchronously save the pixels in @a RenderTarget to disk. - /// - /// @pre To be called from game-thread. - static TFuture SavePixelsToDisk( - UTextureRenderTarget2D &RenderTarget, - const FString &FilePath); - - /// Asynchronously save the pixels in @a PixelData to disk. - /// - /// @pre To be called from game-thread. - static TFuture SavePixelsToDisk( - TUniquePtr> PixelData, - const FString &FilePath); - - /// Convenience function to enqueue a render command that sends the pixels - /// down the @a Sensor's data stream. It expects a sensor derived from - /// ASceneCaptureSensor or compatible. - /// - /// Note that the serializer needs to define a "header_offset" that it's - /// allocated in front of the buffer. - /// - /// @pre To be called from game-thread. - template - static void SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat = false); - -private: - - /// Copy the pixels in @a RenderTarget into @a Buffer. - /// - /// @pre To be called from render-thread. - static void WritePixelsToBuffer( - UTextureRenderTarget2D &RenderTarget, - uint32 Offset, - FRHICommandListImmediate &InRHICmdList, - std::function FuncForSending, - bool use16BitFormat = false); - -}; - -// ============================================================================= -// -- FPixelReader::SendPixelsInRenderThread ----------------------------------- -// ============================================================================= - -template -void FPixelReader2::SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat) -{ - TRACE_CPUPROFILER_EVENT_SCOPE(FPixelReader2::SendPixelsInRenderThread); - check(Sensor.CaptureRenderTarget != nullptr); - - if (!Sensor.HasActorBegunPlay() || Sensor.IsPendingKill()) - { - return; - } - - /// Blocks until the render thread has finished all it's tasks. - Sensor.EnqueueRenderSceneImmediate(); - - // Enqueue a command in the render-thread that will write the image buffer to - // the data stream. The stream is created in the capture thus executed in the - // game-thread. - ENQUEUE_RENDER_COMMAND(FWritePixels2_SendPixelsInRenderThread) - ( - [&Sensor, use16BitFormat](auto &InRHICmdList) mutable - { - TRACE_CPUPROFILER_EVENT_SCOPE_STR("FWritePixels2_SendPixelsInRenderThread"); - - /// @todo Can we make sure the sensor is not going to be destroyed? - if (!Sensor.IsPendingKill()) - { - - std::function FuncForSending = [&Sensor, Frame = FCarlaEngine::GetFrameCounter()](void *LockedData, uint32 Count, uint32 Offset) - { - if (Sensor.IsPendingKill()) return; - - auto Stream = Sensor.GetDataStream(Sensor); - // Stream.SetFrameNumber(Frame); - auto Buffer = Stream.PopBufferFromPool(); - - { - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy"); - Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Count)); - } - { - // send - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Sending buffer"); - if(Buffer.data()) - { - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend); - TRACE_CPUPROFILER_EVENT_SCOPE_STR("Stream Send"); - Stream.Send(Sensor, std::move(Buffer)); - } - } - }; - - WritePixelsToBuffer( - *Sensor.CaptureRenderTarget, - carla::sensor::SensorRegistry::get::type::header_offset, - InRHICmdList, - std::move(FuncForSending), - use16BitFormat); - - } - } - ); - - // Blocks until the render thread has finished all it's tasks - Sensor.WaitForRenderThreadToFinish(); -} diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp index 6bb79258a..e9317c784 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp @@ -60,5 +60,5 @@ void ASceneCaptureCamera::PostPhysTick(UWorld *World, ELevelTick TickType, float TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*ProfilerText); } ); - FPixelReader2::SendPixelsInRenderThread(*this); + FPixelReader::SendPixelsInRenderThread(*this); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h index 0d7b2c965..1de3ca798 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h @@ -32,7 +32,6 @@ class CARLA_API ASceneCaptureSensor : public ASensor friend class ACarlaGameModeBase; friend class FPixelReader; - friend class FPixelReader2; public: