Added fences and separeted each step

This commit is contained in:
doterop 2020-07-28 11:36:31 +02:00 committed by bernat
parent 2430559d8c
commit a2b6f8abf6
7 changed files with 264 additions and 59 deletions

View File

@ -192,7 +192,8 @@ void ACarlaGameModeBase::BeginPlay()
Recorder->GetReplayer()->CheckPlayAfterMapLoaded();
}
CaptureAtlasDelegate = FCoreDelegates::OnEndFrameRT.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas);
SendAtlasDelegate = FCoreDelegates::OnEndFrame.AddUObject(this, &ACarlaGameModeBase::SendAtlas);
CaptureAtlasDelegate = FCoreDelegates::OnBeginFrame.AddUObject(this, &ACarlaGameModeBase::CaptureAtlas);
}
@ -206,10 +207,6 @@ void ACarlaGameModeBase::Tick(float DeltaSeconds)
Recorder->Tick(DeltaSeconds);
}
if(!IsAtlasTextureValid)
{
CreateAtlasTextures();
}
}
void ACarlaGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
@ -224,7 +221,22 @@ void ACarlaGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
CarlaSettingsDelegate->Reset();
}
FCoreDelegates::OnEndFrameRT.Remove(CaptureAtlasDelegate);
// TODO: improve this delete processs; not multithread friendly
while(!AtlasCopyRequestQueue.IsEmpty())
{
delete AtlasCopyRequestQueue.Peek();
AtlasCopyRequestQueue.Pop();
}
while(!AtlasCopyRequestsQueuePool.IsEmpty())
{
delete AtlasCopyRequestsQueuePool.Peek();
AtlasCopyRequestsQueuePool.Pop();
}
FCoreDelegates::OnEndFrame.Remove(CaptureAtlasDelegate);
FCoreDelegates::OnBeginFrame.Remove(SendAtlasDelegate);
}
void ACarlaGameModeBase::SpawnActorFactories()
@ -380,6 +392,17 @@ 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)
@ -390,7 +413,8 @@ void ACarlaGameModeBase::CreateAtlasTextures()
for(int i = 0; i < kMaxNumTextures; i++)
{
CamerasAtlasTexture[i] = RHICreateTexture2D(AtlasTextureWidth, AtlasTextureHeight, PF_B8G8R8A8, 1, 1, TexCreate_CPUReadback, CreateInfo);
AtlasPixels[i].Init(FColor(), AtlasTextureWidth * AtlasTextureHeight);
// Prepare some AtlasCopyRequests
AtlasCopyRequestQueue.Enqueue(new FAtlasCopyRequest());
}
IsAtlasTextureValid = true;
}
@ -400,20 +424,32 @@ extern FDynamicRHI* GDynamicRHI;
void ACarlaGameModeBase::CaptureAtlas()
{
ACarlaGameModeBase* This = this;
if(!IsAtlasTextureValid || !SceneCaptureSensors.Num()) return;
if(!SceneCaptureSensors.Num()) return;
#if !UE_BUILD_SHIPPING
if (!ReadSurface) return;
#endif
ENQUEUE_RENDER_COMMAND(ASceneCaptureSensor_CaptureAtlas)
(
[This](FRHICommandListImmediate& RHICmdList) mutable
if(!IsAtlasTextureValid)
{
FTexture2DRHIRef AtlasTexture = This->CamerasAtlasTexture[This->CurrentAtlas];
TArray<FColor>& CurrentAtlasPixels = This->AtlasPixels[This->CurrentAtlas];
CreateAtlasTextures();
}
//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);
ENQUEUE_RENDER_COMMAND(ACarlaGameModeBase_CaptureAtlas)
(
[This, &CurrentAtlasPixels = AtlasCopyRequest->AtlasImage](FRHICommandListImmediate& RHICmdList) mutable
{
FTexture2DRHIRef AtlasTexture = This->CamerasAtlasTexture[This->PreviousAtlas];
//TArray<FColor>& CurrentAtlasPixels = This->AtlasPixels[This->CurrentAtlas];
if (!AtlasTexture)
{
@ -422,21 +458,22 @@ void ACarlaGameModeBase::CaptureAtlas()
}
// Download Atlas texture
SCOPE_CYCLE_COUNTER(STAT_CarlaSensorReadRT);
FIntRect Rect = FIntRect(0, 0, This->AtlasTextureWidth, This->AtlasTextureHeight);
#if !UE_BUILD_SHIPPING
if(This->ReadSurface == 2) {
if(This->ReadSurfaceMode == 2) {
Rect = FIntRect(0, 0, This->SurfaceW, This->SurfaceH);
}
#endif
// GDynamicRHI->RHIReadSurfaceData(AtlasTexture, Rect, CurrentAtlasPixels, FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX));
// FRHICommandBeginRenderPass RHICommandBeginRenderPass;
// FRHICommandBeginParallelRenderPass RHICommandBeginParallelRenderPass;
#if !UE_BUILD_SHIPPING
if (This->ReadSurfaceMode == 0) return;
#endif
SCOPE_CYCLE_COUNTER(STAT_CarlaSensorReadRT);
RHICmdList.ReadSurfaceData(
AtlasTexture,
Rect,
@ -444,8 +481,61 @@ void ACarlaGameModeBase::CaptureAtlas()
FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX));
// PreviousTexture = CurrentTexture;
// CurrentTexture = (CurrentTexture + 1) & ~MaxNumTextures;
This->PreviousAtlas = This->CurrentAtlas;
This->CurrentAtlas = (This->CurrentAtlas + 1) & ~kMaxNumTextures;
}
);
// AtlasCopyRequest->Start();
// AtlasCopyRequest->Wait();
AtlasCopyRequestQueue.Enqueue(AtlasCopyRequest);
}
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;
}
#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<FColor> AtlasImage(AtlasCopyRequest->AtlasImage);
//ParallelFor(SceneCaptureSensors.Num(),
// [This, &AtlasImage, AtlasTextureWidth = AtlasCopyRequest->AtlasTextureWidth](int32 Index)
for(int32 Index = 0; Index < SceneCaptureSensors.Num(); Index++)
{
ASceneCaptureSensor* Sensor = SceneCaptureSensors[Index];
Sensor->CopyTextureFromAtlas(AtlasCopyRequest->AtlasImage, AtlasTextureWidth);
}
//);
// Remove from pending queue ...
AtlasCopyRequestQueue.Pop();
// ... add to pool
AtlasCopyRequestsQueuePool.Enqueue(AtlasCopyRequest);
}
else
{
//UE_LOG(LogCarla, Error, TEXT("ACarlaGameModeBase::SendAtlas: request didn't finish"));
}
}
}

View File

@ -26,6 +26,45 @@
#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<FColor> 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
@ -78,9 +117,9 @@ public:
}
UFUNCTION(Exec)
void SwitchReadSurface(uint32 Mode) {
void SwitchReadSurfaceMode(uint32 Mode) {
#if !UE_BUILD_SHIPPING
ReadSurface = Mode;
ReadSurfaceMode = Mode;
#endif
}
@ -92,6 +131,39 @@ public:
#endif
}
UFUNCTION(Exec)
void EnableCameraCopyToAtlas(bool Enable) {
#if !UE_BUILD_SHIPPING
CameraCopyToAtlasEnable = Enable;
#endif
}
UFUNCTION(Exec)
void EnableAtlasCopyToCamera(bool Enable) {
#if !UE_BUILD_SHIPPING
AtlasCopyToCamera = Enable;
#endif
}
UFUNCTION(Exec)
void EnableCameraStream(bool Enable) {
#if !UE_BUILD_SHIPPING
CameraStreamEnable = Enable;
#endif
}
#if !UE_BUILD_SHIPPING
bool IsCameraCopyToAtlasEnabled() const {
return CameraCopyToAtlasEnable;
}
bool IsCameraStreamEnabled() const {
return CameraStreamEnable;
}
#endif
protected:
void InitGame(const FString &MapName, const FString &Options, FString &ErrorMessage) override;
@ -110,10 +182,14 @@ private:
void ParseOpenDrive(const FString &MapName);
FAtlasCopyRequest* GetAtlasCopyRequest();
void CreateAtlasTextures();
void CaptureAtlas();
void SendAtlas();
UPROPERTY()
UCarlaGameInstance *GameInstance = nullptr;
@ -147,9 +223,14 @@ private:
boost::optional<carla::road::Map> Map;
FDelegateHandle CaptureAtlasDelegate;
FDelegateHandle SendAtlasDelegate;
TQueue<FAtlasCopyRequest*> AtlasCopyRequestQueue;
TQueue<FAtlasCopyRequest*> AtlasCopyRequestsQueuePool;
static const uint32 kMaxNumTextures = 2u; // This has to be POT
TArray<FColor> AtlasPixels[kMaxNumTextures];
// FRenderCommandFence RenderFence[kMaxNumTextures];
TArray<FColor> AtlasPixels[kMaxNumTextures]; // TODO: remove
TArray<ASceneCaptureSensor*> SceneCaptureSensors;
FTexture2DRHIRef CamerasAtlasTexture[kMaxNumTextures];
uint32 AtlasTextureWidth = 0u;
@ -160,9 +241,12 @@ private:
bool IsAtlasTextureValid = false;
#if !UE_BUILD_SHIPPING
uint32 ReadSurface = 1;
uint32 ReadSurfaceMode = 1;
uint32 SurfaceW = 0;
uint32 SurfaceH = 0;
bool CameraCopyToAtlasEnable = true;
bool AtlasCopyToCamera = true;
bool CameraStreamEnable = true;
#endif
};

View File

@ -34,7 +34,10 @@ void ADepthCamera::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
#if !UE_BUILD_SHIPPING
ACarlaGameModeBase* GameMode = Cast<ACarlaGameModeBase>(GetWorld()->GetAuthGameMode());
SendPixelsInStream(*this, GameMode->GetCurrentAtlasPixels(), GameMode->GetAtlasTextureWidth());
}
if(!GameMode->IsCameraStreamEnabled()) return;
#endif
SendPixelsInStream(*this);
}

View File

@ -28,6 +28,10 @@ void ASceneCaptureCamera::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
#if !UE_BUILD_SHIPPING
ACarlaGameModeBase* GameMode = Cast<ACarlaGameModeBase>(GetWorld()->GetAuthGameMode());
SendPixelsInStream(*this, GameMode->GetCurrentAtlasPixels(), GameMode->GetAtlasTextureWidth());
if(!GameMode->IsCameraStreamEnabled()) return;
#endif
SendPixelsInStream(*this);
}

View File

@ -18,6 +18,7 @@
#include "ContentStreaming.h"
#include "Async/Async.h"
#include "RHICommandList.h"
#include "HAL/UnrealMemory.h"
static auto SCENE_CAPTURE_COUNTER = 0u;
@ -488,6 +489,8 @@ void ASceneCaptureSensor::BeginPlay()
ACarlaGameModeBase* GameMode = Cast<ACarlaGameModeBase>(GetWorld()->GetAuthGameMode());
GameMode->AddSceneCaptureSensor(this);
ImageToSend.Init(FColor(), ImageWidth * ImageHeight);
}
void ASceneCaptureSensor::Tick(float DeltaTime)
@ -515,6 +518,31 @@ void ASceneCaptureSensor::EndPlay(const EEndPlayReason::Type EndPlayReason)
GameMode->RemoveSceneCaptureSensor(this);
}
void ASceneCaptureSensor::CopyTextureFromAtlas(
const TArray<FColor>& AtlasImage,
uint32 AtlasTextureWidth)
{
if(AtlasImage.Num() > 0 && ImageToSend.Num() > 0)
{
SCOPE_CYCLE_COUNTER(STAT_CarlaSensorBufferCopy);
const FColor* Source = &AtlasImage[0] + PositionInAtlas.X;
FColor* Dest = ImageToSend.GetData();
check(ImageToSend.Num() > 0);
check(Source != nullptr);
check(Dest != nullptr);
check(ImageWidth > 0);
for (uint32 Row = 0u; Row < ImageHeight; Row++)
{
FMemory::Memcpy(Dest, Source, sizeof(FColor)*ImageWidth);
Source += AtlasTextureWidth;
Dest += ImageWidth;
}
}
}
void ASceneCaptureSensor::CopyTextureToAtlas()
{
@ -526,6 +554,10 @@ void ASceneCaptureSensor::CopyTextureToAtlas()
ACarlaGameModeBase* GameMode = Cast<ACarlaGameModeBase>(GetWorld()->GetAuthGameMode());
if(!GameMode->IsCameraAtlasTextureValid()) return;
#if !UE_BUILD_SHIPPING
if(!GameMode->IsCameraCopyToAtlasEnabled()) return;
#endif
ENQUEUE_RENDER_COMMAND(ASceneCaptureSensor_CopyTextureToAtlas)
(
[This, GameMode](FRHICommandListImmediate& RHICmdList) mutable

View File

@ -270,38 +270,24 @@ public:
FPixelReader::SavePixelsToDisk(*CaptureRenderTarget, FilePath);
}
void CopyTextureFromAtlas(
const TArray<FColor>& AtlasImage,
uint32 AtlasTextureWidth );
template <typename TSensor>
void SendPixelsInStream(TSensor &Sensor, const TArray<FColor>& AtlasPixels, uint32 AtlasTextureWidth)
void SendPixelsInStream(TSensor &Sensor)
{
if(AtlasPixels.Num() > 0)
if(ImageToSend.Num() > 0)
{
auto Stream = GetDataStream(Sensor);
auto Buffer = Stream.PopBufferFromPool();
{
SCOPE_CYCLE_COUNTER(STAT_CarlaSensorBufferCopy);
constexpr uint32 BytesPerPixel = sizeof(FColor);
const uint32 ExpectedStride = ImageWidth * BytesPerPixel;
const FColor* Source = &AtlasPixels[0];
uint8 *SrcRow = (uint8*)Source + PositionInAtlas.X * BytesPerPixel;
uint32 DstOffset = Offset;
Buffer.reset(Offset + ImageWidth * ImageHeight * BytesPerPixel);
for (uint32 Row = 0u; Row < ImageHeight; Row++)
{
Buffer.copy_from(DstOffset, SrcRow, ExpectedStride);
DstOffset += ExpectedStride;
SrcRow += AtlasTextureWidth * BytesPerPixel;
}
}
{
SCOPE_CYCLE_COUNTER(STAT_CarlaSensorStreamSend);
auto Stream = GetDataStream(Sensor);
auto Buffer = Stream.PopBufferFromPool();
Buffer.copy_from(Offset, ImageToSend);
Stream.Send(Sensor, std::move(Buffer));
}
// TODO: remove
ImageToSend.Init(FColor(), ImageWidth * ImageHeight);
}
}
@ -319,6 +305,8 @@ protected:
FDelegateHandle CopyTextureDelegate;
TArray<FColor> ImageToSend;
/// Render target necessary for scene capture.
UPROPERTY(EditAnywhere)
UTextureRenderTarget2D *CaptureRenderTarget = nullptr;

View File

@ -30,6 +30,10 @@ void ASemanticSegmentationCamera::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
#if !UE_BUILD_SHIPPING
ACarlaGameModeBase* GameMode = Cast<ACarlaGameModeBase>(GetWorld()->GetAuthGameMode());
SendPixelsInStream(*this, GameMode->GetCurrentAtlasPixels(), GameMode->GetAtlasTextureWidth());
if(!GameMode->IsCameraStreamEnabled()) return;
#endif
SendPixelsInStream(*this);
}