Reading pixel color from texture, random memcpy error

Hey,

I am trying to read the pixel colors from a texture. After many hours, I finally have something that works in shipping builds. Well, half of the time. Both in the editor and in packaged builds, my code crashes ~50% of the time.

I use the same texture and settings. When I stepped through the code, the texture and other pointers seemed to be valid every time, so I have no clue why the ‘memcpy’ line keeps crashing randomly with an access violation error.

FTexture2DMipMap* MipMap = &inTexture->PlatformData->Mips[0];
FByteBulkData* RawImageData = &MipMap->BulkData;
const FColor* ImageData = reinterpret_cast<const FColor*>(RawImageData->Lock(LOCK_READ_ONLY));

const int32 NumPixels = inTexture->GetSizeX() * inTexture->GetSizeY();
outPixelColors.Empty(NumPixels);

FMemory::Memcpy(outPixelColors.GetData(), ImageData, NumPixels * sizeof(FColor)); //crashing ~50% of the time
RawImageData->Unlock();

Any ideas or help would be appreciated!

Maybe it is a source version difference (I’m on 4.27), but you FMemory::Memcpy call looks weird to me.

It looks like you are using the non-templated version of that function, but you are calling it with types that do not implicitly cast to void*, so I’m not sure how you got this to compile.

Since you are calling the void* version that includes the number of bytes for the size of the copy, the problem is likely because your destination is not the correct size.

If you’ve confirmed that to not be the case, then your source pointer might be wrong, or you are copying too much from the source pointer.

If you confirmed that all of those are fine, then it might be a lifetime issue related to outPixelColors. Perhaps when this code runs there is a race condition with the lifetime of outPixelColors that results the access violation.

If you confirmed that none of those things are happening. Well, that is a head scratcher. Put some check()s in to make sure that you are 100% sure 100% of the time that all of the above things are good. If it still gives you random crashes… that would be an interesting puzzle.

I am sure that problem related to how Unreal Engine handles Texture2D. I built custom game engines and know how graphics data is transfered in different memories, so most likely Unreal Engine makes Texture 2D as handler to texture, and after CPU passed that texture to gRAM it do not need it in most cases, so its just released.

But, the strange thing, is that I was able to get texture from Texture2D, but I avoided check BulkData->IsAvailableForUse() and used that BP function in BeginPlay, because in construction it wasn’t working. Also it has really big delay before game started. So I am sure that it was related to each time I called that function, engine was requesting that texture from drive, then system detected that this texture was already uploaded to gRAM and removed it.
I do not recommend to do that, I just tried to grope how things work under the hood.

So easiest and safest way to achive manimulation on textures in CPU IMO is just using render target once and use it to grab the texel colors.
Its not the cleanest way, but the safest. Unfortunately it was not considered during UnrealEngine development that textures could be used in CPU. The solution could be such simple, as just creating separate TextureCPU2D or kind like that.