@@ -20,7 +20,11 @@ bool ConvertRAWSurfaceDataToFLinearColor(EPixelFormat Format, uint32 Width, uint
2020#endif
2121
2222UBH_GameRecorder::UBH_GameRecorder (const FObjectInitializer& ObjectInitializer)
23- : Super(ObjectInitializer), bIsRecording(false ), bCopyTextureStarted(false ), StagingTexture(nullptr ), BackTextureWidth(0 ), BackTextureHeight(0 )
23+ : Super(ObjectInitializer)
24+ , bIsRecording(false )
25+ , bCopyTextureStarted(false )
26+ , StagingTexture(nullptr )
27+ , RawFrameBufferPool(3 )
2428{
2529 FrameBuffer = ObjectInitializer.CreateDefaultSubobject <UBH_FrameBuffer>(this , TEXT (" FrameBuffer" ));
2630}
@@ -162,32 +166,33 @@ void UBH_GameRecorder::Tick(float DeltaTime)
162166 {
163167 AsyncTask (ENamedThreads::AnyBackgroundThreadNormalTask, [this ]()
164168 {
165- FScopeLock Lock (&AsyncTextureProcessingLock);
166-
167- BackTextureLock.Lock ();
168- TextureBuffer.SwapBuffers (); // swap back with current
169-
170- const uint8 *RawData = reinterpret_cast <const uint8*>(TextureBuffer.GetCurrentBuffer ());
171- int32 RawDataWidth = BackTextureWidth;
172- int32 RawDataHeight = BackTextureHeight;
169+ BH_RawFrameBuffer<uint8>* TextureBuffer = RawFrameBufferQueue.Dequeue ();
170+ if (!TextureBuffer)
171+ {
172+ // no texture buffer in the queue, nothing to process
173+ return ;
174+ }
173175
174- BackTextureLock.Unlock ();
175-
176176 // Make sure that PendingPixels is of the correct size
177- int32 NumPixels = RawDataWidth * RawDataHeight ;
177+ int32 NumPixels = TextureBuffer-> GetWidth () * TextureBuffer-> GetHeight () ;
178178
179179 if (PendingLinearPixels.Num () != NumPixels)
180180 {
181181 PendingLinearPixels.SetNumUninitialized (NumPixels);
182182 PendingPixels.SetNumUninitialized (NumPixels);
183183 }
184184
185- uint32 Pitch = GPixelFormats[StagingTextureFormat].BlockBytes * RawDataWidth ;
185+ uint32 Pitch = GPixelFormats[StagingTextureFormat].BlockBytes * TextureBuffer-> GetWidth () ;
186186
187187
188188 // Convert raw surface data to linear color
189- ConvertRAWSurfaceDataToFLinearColor (StagingTextureFormat, RawDataWidth, RawDataHeight, const_cast <uint8*>(RawData),
190- Pitch, PendingLinearPixels.GetData (), FReadSurfaceDataFlags ({}));
189+ ConvertRAWSurfaceDataToFLinearColor (
190+ StagingTextureFormat,
191+ TextureBuffer->GetWidth (), TextureBuffer->GetHeight (),
192+ TextureBuffer->GetData (),
193+ Pitch,
194+ PendingLinearPixels.GetData (),
195+ FReadSurfaceDataFlags ({}));
191196
192197 // Convert linear color to FColor
193198 for (int32 i = 0 ; i < NumPixels; ++i)
@@ -196,7 +201,7 @@ void UBH_GameRecorder::Tick(float DeltaTime)
196201 }
197202
198203 // Resize image to frame
199- ResizeImageToFrame (PendingPixels, RawDataWidth, RawDataHeight , FrameWidth, FrameHeight, ResizedPixels);
204+ ResizeImageToFrame (PendingPixels, TextureBuffer-> GetWidth (), TextureBuffer-> GetHeight () , FrameWidth, FrameHeight, ResizedPixels);
200205
201206 // Set frame data on the game thread
202207 AsyncTask (ENamedThreads::GameThread, [this ]()
@@ -206,6 +211,7 @@ void UBH_GameRecorder::Tick(float DeltaTime)
206211
207212 // only when I complete this, allow another read pixels
208213 bCopyTextureStarted = false ;
214+ RawFrameBufferPool.ReleaseElement (TextureBuffer);
209215 });
210216 }
211217}
@@ -332,25 +338,31 @@ void UBH_GameRecorder::ReadPixels()
332338 FViewport* Viewport = GEngine->GameViewport ->Viewport ;
333339 if (!Viewport) return ;
334340
341+ BH_RawFrameBuffer<uint8>* TextureBuffer = RawFrameBufferPool.GetElement ();
342+ if (!TextureBuffer)
343+ {
344+ // no texture buffer available at this time
345+ // UE_LOG(LogTemp, Error, TEXT("No texture buffer available."));
346+ return ;
347+ }
348+
335349 FRHICopyTextureInfo CopyInfo;
336350 RHICmdList.CopyTexture (GEngine->GameViewport ->Viewport ->GetRenderTargetTexture (), StagingTexture, CopyInfo);
337351
338- void * RawDataTemp = nullptr ;
339- int32 RawDataWidthTemp = 0 ;
340- int32 RawDataHeightTemp = 0 ;
341-
342- RHICmdList.MapStagingSurface (StagingTexture, RawDataTemp, RawDataWidthTemp, RawDataHeightTemp);
352+ void * RawData = nullptr ;
353+ int32 RawDataWidth = 0 ;
354+ int32 RawDataHeight = 0 ;
343355
344- // copy the memory, because RawDataTemp is temporary
345- BackTextureLock.Lock ();
356+ RHICmdList.MapStagingSurface (StagingTexture, RawData, RawDataWidth, RawDataHeight);
346357
347- TextureBuffer. MemCopyFrom (
348- reinterpret_cast <uint8*>(RawDataTemp ),
349- RawDataWidthTemp * RawDataHeightTemp * GPixelFormats[StagingTextureFormat]. BlockBytes );
350- BackTextureWidth = RawDataWidthTemp;
351- BackTextureHeight = RawDataHeightTemp ;
358+ TextureBuffer-> CopyFrom (
359+ reinterpret_cast <uint8*>(RawData ),
360+ RawDataWidth,
361+ RawDataHeight,
362+ GPixelFormats[StagingTextureFormat]. BlockBytes ) ;
352363
353- BackTextureLock.Unlock ();
364+ // async queue for processing
365+ RawFrameBufferQueue.Enqueue (TextureBuffer);
354366
355367 RHICmdList.UnmapStagingSurface (StagingTexture);
356368 }
0 commit comments