Memory leak UpdateTextureRegions

[RESOLVED] Coded in the example works fine. My fault.

Hello, i having a memory leak in a simple test project using UpdateTextureRegions.

My project setup its like this: A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums li

The only differences its the source of the Data, but this ins’t the problem if disable the updatetextureregions no leaks.

any idea? its this method ok/safe? anyone got similar problem?

AH: https://answers.unrealengine.com/questions/349969/memory-leak-updatetextureregions.html

How do you detect leaks?

Because in case of this method you can get false positive.



FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;
 
		RegionData->Texture2DResource = (FTexture2DResource*)Texture->Resource;
		RegionData->MipIndex = MipIndex;
		RegionData->NumRegions = NumRegions;
		RegionData->Regions = Regions;
		RegionData->SrcPitch = SrcPitch;
		RegionData->SrcBpp = SrcBpp;
		RegionData->SrcData = SrcData;
 
		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
			UpdateTextureRegionsData,
			FUpdateTextureRegionsData*, RegionData, RegionData,
			bool, bFreeData, bFreeData,
			{
			for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
			{
				int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
				if (RegionData->MipIndex >= CurrentFirstMip)
				{
					RHIUpdateTexture2D(
						RegionData->Texture2DResource->GetTexture2DRHI(),
						RegionData->MipIndex - CurrentFirstMip,
						RegionData->Regions[RegionIndex],
						RegionData->SrcPitch,
						RegionData->SrcData
						+ RegionData->Regions[RegionIndex].SrcY * RegionData->SrcPitch
						+ RegionData->Regions[RegionIndex].SrcX * RegionData->SrcBpp
						);
				}
			}
			if (bFreeData)
			{
				FMemory::Free(RegionData->Regions);
				FMemory::Free(RegionData->SrcData);
			}
			delete RegionData;
		});


This segment apparently allocates data and then deletes it in another thread. Which means that if your tool detects leak within current function only, it willl report a leak.

The code overall seems to overuse new/delete (it looks like there’s no reason to create frame/stream/etc via “new”), but I don’t see an obvious glitch there. Might be overlooking something, of course.

the memory leak its obvious, my application crash after 60 seconds running out of memory. Not use any special tool, i can see in the W10 task manager how the “Committed” go from 6gb to the limit 25GB before crash.

in the AH post there are a file with the memory profiling.

hi knack, how exacly you pass the data? opencv automanage some things like memory clean! if your project work as you say, maybe you need clean the buffer by yourself
try something like this:



uint8* data = "whatever you get";

updateyourTextureRHI(data);//this always copy the memory and pass to the render thread, but your old data keep exist

delete data;//so clean by hand


this is when you create, process the data inside a method, i am very sure something like that is happening to you!
you need be responsable some times with some buffer source, for example Mat from opencv clean the data after finish the method, or something similar with kinect color buffer

like example i using TArray<FColor> Data and he not delete.

Anyway that the code:



Data.Empty();
	Data.Init(FColor(0, 0, 0, 255), VideoSize.X * VideoSize.Y);

	for (int y = 0; y < Width ; y++)
	{
		for (int x = 0; x < Height ; x++)
		{
			int i = x + (y * Height );
			Data*.B = bitmap[i * 4 + 0];
			Data*.G = bitmap[i * 4 + 1];
			Data*.R = bitmap[i * 4 + 2];
		}
	}


	delete] bitmap;


like a i say i check first all things, and the leak only occurs when call on event tick (like the opencv example)

UpdateTextureRegions(VideoTexture, (int32)0, (uint32)3, VideoUpdateTextureRegion, (uint32)(4 * VideoSize.X), (uint32)4, (uint8*)Data.GetData(), false);

if your Tarray<FColor> Data is part of your class, i suggest intialize in the beginPlay method with know width and height, and never use Empty and Init inside your update method, maybe this raise your memory leak, anyway your code looks ok for me, try this too.
maybe your problem is not code maybe is hardware, maybe some old webcam with very slow performance, more and less 15 fps, check your code to match with the camera fps
try something like this:



const int32 frameRate = 15; //15 fps
float camTime;

void update(float deltaTime)
{
     camTime += deltaTime;
     if(camTime >= 1/frameRate)
    {
          //pass and reset time
          camTime = 0;

          //try to get your data
          uint8* data = getData();

          //always check for errors
          if(data != NULL)
          {
                //update your texture
          }
    }
}



I can’t init on begin play because i need check the bitmap if its the same x/y and if not resize. (ins’t a camera).

i slow down the refresh rate a lot with the same problems. I check a lot of things hehe :frowning:

and again i remove all things about updatetextureregions, and still receive the bitmaps and put it on Data without any memory leak.

That mean if i remove that line
UpdateTextureRegions(VideoTexture, (int32)0, (uint32)3, VideoUpdateTextureRegion, (uint32)(4 * VideoSize.X), (uint32)4, (uint8*)Data.GetData(), false);

no memory leaks.

WAIT, I check again without that line and have a memory leak. I swear the first time i check i haven’t. uhhh i going to recheck all code again.

:mad:

lets try to get things simple as posible
hypotetic talk!, first you create your texture like this in begin play



EPixelFormat pxFormat = EPixelFormat::PF_B8G8R8A8;
texture = UTexture2D::CreateTransient(width, height, pxFormat);
echoUpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, width, height);
texture->UpdateResource();


now for correct implementation lets avoid use Tarray instead we use pure unsigned char*
this is the Tick:



void YourClass::Tick(float DeltaTime)
{
	unsigned char* data = getData();//hypotetic get data
        if (data == NULL) return;



//your new data in BGRA for your texture
        unsigned char* bgra = new unsigned char[width * height *4];
//now you fix the order of your data to whatever vals of your data to BGRA texture type!!!!
        for (int i = 0,  i < width * height; i ++) {
		bgra[4 * i + 0] = data[4 * i + 0];
                bgra[4 * i + 1] = data[4 * i + 1];
                bgra[4 * i + 2] = data[4 * i + 2];
                bgra[4 * i + 3] = 255;
	}

//now pass to your region data
// fill my Texture Region data
	FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;
	RegionData->Texture2DResource = (FTexture2DResource*)texture->Resource;
	RegionData->MipIndex = 0;
	RegionData->NumRegions = 1;
	RegionData->Regions = echoUpdateTextureRegion;
	RegionData->SrcPitch = (uint32)(4 * width);
	RegionData->SrcBpp = 4;
        RegionData->SrcData = bgra;

//and finally update the texture
        bool bFreeData = false;

	// call the RHIUpdateTexture2D to refresh the texture with new info
	ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
		UpdateTextureRegionsData,
		FUpdateTextureRegionsData*, RegionData, RegionData,
		bool, bFreeData, bFreeData,
		{
			for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
			{
				int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
				if (RegionData->MipIndex >= CurrentFirstMip)
				{
					RHIUpdateTexture2D(
						RegionData->Texture2DResource->GetTexture2DRHI(),
						RegionData->MipIndex - CurrentFirstMip,
						RegionData->Regions[RegionIndex],
						RegionData->SrcPitch,
						RegionData->SrcData
						+ RegionData->Regions[RegionIndex].SrcY * RegionData->SrcPitch
						+ RegionData->Regions[RegionIndex].SrcX * RegionData->SrcBpp
						);
				}
			}
	if (bFreeData)
	{
		FMemory::Free(RegionData->Regions);
		FMemory::Free(RegionData->SrcData);
	}
	delete RegionData;
		});

//one last thing is delete this bgra unsigned char* to avoid the leak
    delete] bgra;

}


this code is functional, and must be solve your leak, at least if you dont perform in another code portion
mmm you told me about resize images and thats way you cant init your Tarray<FColor> in begin play, if you need check this every tick i afraid this approach never works, if that is the case, you need receive your data, and then resize to match with the texture size, otherway never works

I found the leak, nothing with the example code finally.
The first problem was i check my code alone and seems work fine without leak and then i assume the problem was in the example code that i c&p, especially in the update function that i not understand comptely what do and when i remove the UpdateTexture seems stop the leak. Then i focus on that. seem normal no?

Well that was another error, checking second time i see the leak continue, and finally begin again checking the code and the leak was in my “build image” code and the worst its was evident. I don’t known why first time check seems i haven’t any leak but i lost a lot of hours and your time for a stupid fault. :frowning:

Thanks to all!
y Gracias ZkarmaKun y perdona las molestias, tu codigo me puede valer si decido quitar FColor que lo pense tambien.

glad to hear!!

por nada amigo!

I was wonderring how to solve it。if possible ,show me your code or solution.
thanks

the example code of the wiki is OK no leak. Was a stupid fail mine.

I am using the example code , but not work. the same as you said ,“The only differences its the source of the Data, but this ins’t the problem if disable the updatetextureregions no leaks.”