diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp index b0cc6b63e..5d3c47144 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.cpp @@ -193,10 +193,7 @@ void ACarlaGameModeBase::BeginPlay() Recorder->GetReplayer()->CheckPlayAfterMapLoaded(); } - // OnBeginFrame - // OnEndFrame - CaptureAtlasDelegate = FCoreDelegates::OnBeginFrame.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas); - // SendAtlasDelegate = FCoreDelegates::OnEndFrame.AddUObject(this, &ACarlaGameModeBase::SendAtlas); + CaptureAtlasDelegate = FCoreDelegates::OnEndFrame.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas); } @@ -223,25 +220,7 @@ void ACarlaGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) CarlaSettingsDelegate->Reset(); } - // TODO: improve this delete processs; not multithread friendly - /* - while(!AtlasCopyRequestQueue.IsEmpty()) - { - delete AtlasCopyRequestQueue.Peek(); - AtlasCopyRequestQueue.Pop(); - } - - while(!AtlasCopyRequestsQueuePool.IsEmpty()) - { - delete AtlasCopyRequestsQueuePool.Peek(); - AtlasCopyRequestsQueuePool.Pop(); - } - */ - - - // OnEndFrame FCoreDelegates::OnEndFrame.Remove(CaptureAtlasDelegate); - //FCoreDelegates::OnEndFrame.Remove(SendAtlasDelegate); } void ACarlaGameModeBase::SpawnActorFactories() @@ -396,39 +375,20 @@ void ACarlaGameModeBase::DebugShowSignals(bool enable) } } -/* -FAtlasCopyRequest* ACarlaGameModeBase::GetAtlasCopyRequest() -{ - if(AtlasCopyRequestsQueuePool.IsEmpty()) { - UE_LOG(LogCarla, Warning, TEXT("ACarlaGameModeBase::GetAtlasCopyRequest new FAtlasCopyRequest")); - return new FAtlasCopyRequest(); - } - FAtlasCopyRequest* AtlasCopyRequest = nullptr; - AtlasCopyRequestsQueuePool.Dequeue(AtlasCopyRequest); - return AtlasCopyRequest; -} - */ + void ACarlaGameModeBase::CreateAtlasTextures() { if(AtlasTextureWidth > 0 && AtlasTextureHeight > 0) { - UE_LOG(LogCarla, Warning, TEXT("ACarlaGameModeBase::CreateAtlasTextures %d %dx%d"), SceneCaptureSensors.Num(), AtlasTextureWidth, AtlasTextureHeight); - FRHIResourceCreateInfo CreateInfo; CamerasAtlasTexture = RHICreateTexture2D(AtlasTextureWidth, AtlasTextureHeight, PF_B8G8R8A8, 1, 1, TexCreate_CPUReadback, CreateInfo); - for(int i = 0; i < kMaxNumTextures; i++) - { - AtlasImage[i].Init(FColor(), AtlasTextureWidth * AtlasTextureHeight); - // Prepare some AtlasCopyRequests - //AtlasCopyRequestQueue.Enqueue(new FAtlasCopyRequest()); - } + AtlasImage.Init(FColor(), AtlasTextureWidth * AtlasTextureHeight); + IsAtlasTextureValid = true; } } -//extern FDynamicRHI* GDynamicRHI; - void ACarlaGameModeBase::CaptureAtlas() { @@ -448,16 +408,6 @@ void ACarlaGameModeBase::CaptureAtlas() Sensor->CopyTextureToAtlas(); } - //if (!AtlasCopyRequestQueue.IsEmpty()) - //{ - // UE_LOG(LogCarla, Error, TEXT("ACarlaGameModeBase::CaptureAtlas: request full")); - // return; - //} - //UE_LOG(LogCarla, Warning, TEXT("ACarlaGameModeBase::CaptureAtlas: creating request")); - - //FAtlasCopyRequest* AtlasCopyRequest = GetAtlasCopyRequest(); - //AtlasCopyRequest->ResizeBuffer(AtlasTextureWidth, AtlasTextureHeight); - // Download Atlas texture ENQUEUE_RENDER_COMMAND(ACarlaGameModeBase_CaptureAtlas) ( @@ -476,7 +426,6 @@ void ACarlaGameModeBase::CaptureAtlas() #if !UE_BUILD_SHIPPING if(This->ReadSurfaceMode == 2) Rect = FIntRect(0, 0, This->SurfaceW, This->SurfaceH); #endif - // GDynamicRHI->RHIReadSurfaceData(AtlasTexture, Rect, CurrentAtlasPixels, FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)); #if !UE_BUILD_SHIPPING if (This->ReadSurfaceMode == 0) return; @@ -486,68 +435,29 @@ void ACarlaGameModeBase::CaptureAtlas() RHICmdList.ReadSurfaceData( AtlasTexture, Rect, - This->AtlasImage[This->CurrentAtlas], + This->AtlasImage, FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX)); - - This->PreviousAtlas = This->CurrentAtlas; - This->CurrentAtlas = (This->CurrentAtlas + 1) & ~kMaxNumTextures; } ); - //AtlasCopyRequest->Start(); - // AtlasCopyRequest->Wait(); - //AtlasCopyRequestQueue.Enqueue(AtlasCopyRequest); - SendAtlas(); } void ACarlaGameModeBase::SendAtlas() { - //if(!AtlasCopyRequestQueue.IsEmpty()) - { - //FAtlasCopyRequest* AtlasCopyRequest = nullptr; - //AtlasCopyRequestQueue.Peek(AtlasCopyRequest); - // Be sure that the request has finished - - //if( AtlasCopyRequest && AtlasCopyRequest->IsComplete() ) - { - //UE_LOG(LogCarla, Warning, TEXT("ACarlaGameModeBase::SendAtlas: DONE")); #if !UE_BUILD_SHIPPING - if(!AtlasCopyToCamera) - { - //AtlasCopyRequestQueue.Pop(); - //AtlasCopyRequestsQueuePool.Enqueue(AtlasCopyRequest); - return; - } + if(!AtlasCopyToCamera) + { + return; + } #endif - ACarlaGameModeBase* This = this; - // We need to make a copy of the atlas to avoid possible threads issues later - // since the AtlasCopyRequest could be used later - //TArray AtlasImage(AtlasCopyRequest->AtlasImage); - //ParallelFor(SceneCaptureSensors.Num(), - // [This, &AtlasImage](int32 Index) - for(int32 Index = 0; Index < SceneCaptureSensors.Num(); Index++) - { - ASceneCaptureSensor* Sensor = SceneCaptureSensors[Index]; - // TODO: merge this functions and avoid double copy - Sensor->CopyTextureFromAtlas(AtlasImage[PreviousAtlas], AtlasTextureWidth); - Sensor->SendPixels(); - } - //); - - // Remove from pending queue ... - //AtlasCopyRequestQueue.Pop(); - // ... add to pool - //AtlasCopyRequestsQueuePool.Enqueue(AtlasCopyRequest); - } - //else - { - //UE_LOG(LogCarla, Error, TEXT("ACarlaGameModeBase::SendAtlas: request didn't finish")); - } - + for(int32 Index = 0; Index < SceneCaptureSensors.Num(); Index++) + { + ASceneCaptureSensor* Sensor = SceneCaptureSensors[Index]; + Sensor->SendPixels(AtlasImage, AtlasTextureWidth); } } \ No newline at end of file diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h index c07bf5808..0e608619d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Game/CarlaGameModeBase.h @@ -26,47 +26,6 @@ #include "CarlaGameModeBase.generated.h" - -/* -USTRUCT() -struct FAtlasCopyRequest -{ - GENERATED_BODY() - - void ResizeBuffer(uint32 Width, uint32 Height) - { - if(AtlasTextureWidth != Width || AtlasTextureHeight != Height) - { - UE_LOG(LogCarla, Warning, TEXT("FAtlasCopyRequest::ResizeBuffer %dx%d"), Width, Height); - AtlasTextureWidth = Width; - AtlasTextureHeight = Height; - AtlasImage.Init(FColor(), Width * Height); - } - } - - void Start() - { - RenderFence.BeginFence(true); - } - - void Wait() - { - RenderFence.Wait(false); - } - - bool IsComplete() - { - return RenderFence.IsFenceComplete(); - } - - TArray AtlasImage; - FRenderCommandFence RenderFence; - uint32 AtlasTextureWidth = 0u; - uint32 AtlasTextureHeight = 0u; -}; -*/ - - /// Base class for the CARLA Game Mode. UCLASS(HideCategories=(ActorTick)) class CARLA_API ACarlaGameModeBase : public AGameModeBase @@ -221,23 +180,13 @@ private: boost::optional Map; FDelegateHandle CaptureAtlasDelegate; - FDelegateHandle SendAtlasDelegate; - //TQueue AtlasCopyRequestQueue; - //TQueue AtlasCopyRequestsQueuePool; - - // TODO: clean - - // TODO: remove kMaxNumTextures and current/prev index - static const uint32 kMaxNumTextures = 1u; // This has to be POT TArray SceneCaptureSensors; FTexture2DRHIRef CamerasAtlasTexture; - TArray AtlasImage[kMaxNumTextures]; + TArray AtlasImage; uint32 AtlasTextureWidth = 0u; uint32 AtlasTextureHeight = 0u; uint32 CurrentAtlasTextureHeight = 0u; - uint32 CurrentAtlas = 0u; - uint32 PreviousAtlas = 0u; bool IsAtlasTextureValid = false; #if !UE_BUILD_SHIPPING diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp index 5c9eccc18..c60abf991 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.cpp @@ -30,12 +30,12 @@ ADepthCamera::ADepthCamera(const FObjectInitializer &ObjectInitializer) Offset = carla::sensor::SensorRegistry::get::type::header_offset; } -void ADepthCamera::SendPixels() +void ADepthCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) { #if !UE_BUILD_SHIPPING ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); if(!GameMode->IsCameraStreamEnabled()) return; #endif - SendPixelsInStream(*this); + SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h index 60c450fc2..f4bda659d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/DepthCamera.h @@ -26,5 +26,5 @@ public: protected: - void SendPixels() override; + void SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) override; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp index 800054a47..c86d22714 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.cpp @@ -24,12 +24,12 @@ ASceneCaptureCamera::ASceneCaptureCamera(const FObjectInitializer &ObjectInitial Offset = carla::sensor::SensorRegistry::get::type::header_offset; } -void ASceneCaptureCamera::SendPixels() +void ASceneCaptureCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) { #if !UE_BUILD_SHIPPING ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); if(!GameMode->IsCameraStreamEnabled()) return; #endif - SendPixelsInStream(*this); + SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h index ee5d8a719..bdd2fdf2b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureCamera.h @@ -26,6 +26,6 @@ public: protected: - void SendPixels() override; + void SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) override; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp index 4df292b6e..bba7eab1a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.cpp @@ -484,19 +484,14 @@ void ASceneCaptureSensor::BeginPlay() Super::BeginPlay(); - //CopyTextureDelegate = FCoreDelegates::OnEndFrame.AddUObject(this, &ASceneCaptureCamera::CopyTextureToAtlas); - ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); GameMode->AddSceneCaptureSensor(this); - ImageToSend.Init(FColor(), ImageWidth * ImageHeight); - } void ASceneCaptureSensor::Tick(float DeltaTime) { Super::Tick(DeltaTime); - // TODO: can I remove this? // Add the view information every tick. Its only used for one tick and then // removed by the streamer. @@ -505,7 +500,6 @@ void ASceneCaptureSensor::Tick(float DeltaTime) ImageWidth, ImageWidth / FMath::Tan(CaptureComponent2D->FOVAngle)); - // UE_LOG(LogCarla, Warning, TEXT("ASceneCaptureSensor::Tick")); } void ASceneCaptureSensor::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -513,7 +507,6 @@ void ASceneCaptureSensor::EndPlay(const EEndPlayReason::Type EndPlayReason) Super::EndPlay(EndPlayReason); SCENE_CAPTURE_COUNTER = 0u; - FCoreDelegates::OnEndFrame.Remove(CopyTextureDelegate); ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); GameMode->RemoveSceneCaptureSensor(this); } @@ -562,32 +555,38 @@ void ASceneCaptureSensor::CopyTextureToAtlas() ); } -void ASceneCaptureSensor::CopyTextureFromAtlas(const TArray& AtlasImage, uint32 AtlasTextureWidth) +bool ASceneCaptureSensor::CopyTextureFromAtlas( + carla::Buffer &Buffer, + const TArray& AtlasImage, + uint32 AtlasTextureWidth) { // Check that the atlas alreay contains our texture // and our image has been initialized - if(AtlasImage.Num() < (PositionInAtlas.Y * AtlasTextureWidth + ImageWidth * ImageHeight) || - ImageToSend.Num() <= 0) + if(AtlasImage.GetData() && + AtlasImage.Num() < (PositionInAtlas.Y * AtlasTextureWidth + ImageWidth * ImageHeight)) { - return; + return false; } + SCOPE_CYCLE_COUNTER(STAT_CarlaSensorBufferCopy); + + const FColor* SourceFColor = AtlasImage.GetData() + PositionInAtlas.Y * AtlasTextureWidth; + const uint8* Source = (uint8*)SourceFColor; + uint32 Dest = Offset; + + const uint32 DstStride = ImageWidth * sizeof(FColor); + const uint32 SrcStride = AtlasTextureWidth * sizeof(FColor); + + Buffer.reset(Offset + ImageHeight * DstStride); + for(uint32 i = 0; i < ImageHeight; i++) { - SCOPE_CYCLE_COUNTER(STAT_CarlaSensorBufferCopy); - - const FColor* SourceFColor = &AtlasImage[0] + PositionInAtlas.Y * AtlasTextureWidth; - const uint8* Source = (uint8*)SourceFColor; - uint8* Dest = (uint8*)ImageToSend.GetData(); - - for(uint32 i = 0; i < ImageHeight; i++) - { - FMemory::Memcpy(Dest, Source, ImageWidth * sizeof(FColor)); - Source += AtlasTextureWidth * sizeof(FColor); - Dest += ImageWidth * sizeof(FColor); - } - + Buffer.copy_from(Dest, Source, DstStride); + Source += SrcStride; + Dest += DstStride; } + + return true; } // ============================================================================= diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h index 648337bea..677cf70b1 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SceneCaptureSensor.h @@ -272,20 +272,20 @@ public: void CopyTextureToAtlas(); - void CopyTextureFromAtlas(const TArray& AtlasImage, uint32 AtlasTextureWidth); + bool CopyTextureFromAtlas(carla::Buffer &Buffer, const TArray& AtlasImage, uint32 AtlasTextureWidth); - virtual void SendPixels() {} + virtual void SendPixels(const TArray& /* AtlasImage */, uint32 /* AtlasTextureWidth */) {} template - void SendPixelsInStream(TSensor &Sensor) + void SendPixelsInStream(TSensor &Sensor, const TArray& AtlasImage, uint32 AtlasTextureWidth) { - if(ImageToSend.Num() > 0) + auto Stream = GetDataStream(Sensor); + auto Buffer = Stream.PopBufferFromPool(); + + if(CopyTextureFromAtlas(Buffer, AtlasImage, AtlasTextureWidth)) { { SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend); - auto Stream = GetDataStream(Sensor); - auto Buffer = Stream.PopBufferFromPool(); - Buffer.copy_from(Offset, ImageToSend); Stream.Send(Sensor, std::move(Buffer)); } } @@ -301,10 +301,6 @@ protected: virtual void SetUpSceneCaptureComponent(USceneCaptureComponent2D &SceneCapture) {} - FDelegateHandle CopyTextureDelegate; - - TArray ImageToSend; - /// Render target necessary for scene capture. UPROPERTY(EditAnywhere) UTextureRenderTarget2D *CaptureRenderTarget = nullptr; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp index fba0ddc95..df085db7b 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.cpp @@ -26,12 +26,12 @@ ASemanticSegmentationCamera::ASemanticSegmentationCamera( Offset = carla::sensor::SensorRegistry::get::type::header_offset; } -void ASemanticSegmentationCamera::SendPixels() +void ASemanticSegmentationCamera::SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) { #if !UE_BUILD_SHIPPING ACarlaGameModeBase* GameMode = Cast(GetWorld()->GetAuthGameMode()); if(!GameMode->IsCameraStreamEnabled()) return; #endif - SendPixelsInStream(*this); + SendPixelsInStream(*this, AtlasImage, AtlasTextureWidth); } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h index dd5310385..d622b05fa 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/SemanticSegmentationCamera.h @@ -26,5 +26,5 @@ public: protected: - void SendPixels() override; + void SendPixels(const TArray& AtlasImage, uint32 AtlasTextureWidth) override; };