I build my project in UE5 5.2 version.
When I test my game but sometimes it crash and I find the break point is RHIUpdateTexture2D
of these code in UTexture2D::UpdateTextureRegions
void UTexture2D::UpdateTextureRegions(int32 MipIndex, uint32 NumRegions, const FUpdateTextureRegion2D* Regions, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, TFunction<void(uint8* SrcData, const FUpdateTextureRegion2D* Regions)> DataCleanupFunc)
{
// other code
ENQUEUE_RENDER_COMMAND(UpdateTextureRegionsData)(
[RegionData, DataCleanupFunc](FRHICommandListImmediate& RHICmdList)
{
for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
{
int32 CurrentFirstMip = RegionData->Texture2DResource->State.AssetLODBias;
if (RegionData->MipIndex >= CurrentFirstMip)
{
// Some RHIs don't support source offsets. Offset source data pointer now and clear source offsets
FUpdateTextureRegion2D RegionCopy = RegionData->Regions[RegionIndex];
const uint8* RegionSourceData = RegionData->SrcData
+ RegionCopy.SrcY * RegionData->SrcPitch
+ RegionCopy.SrcX * RegionData->SrcBpp;
RegionCopy.SrcX = 0;
RegionCopy.SrcY = 0;
RHIUpdateTexture2D(
RegionData->Texture2DResource->TextureRHI->GetTexture2D(),
RegionData->MipIndex - CurrentFirstMip,
RegionCopy,
RegionData->SrcPitch,
RegionSourceData);
}
}
// other code
}
I see the code make the source data pointer start with (RegionCopy.SrcX, RegionCopy.SrcY).
And then I find these code in FD3D11DynamicRHI::RHIUpdateTexture2D
, in which the final break point occurs in FMemory::Memcpy(SourceDataCopy, SourceData, SourceDataSize);
void FD3D11DynamicRHI::RHIUpdateTexture2D(FRHICommandListBase& RHICmdList, FRHITexture2D* TextureRHI, uint32 MipIndex, const FUpdateTextureRegion2D& UpdateRegion, uint32 SourcePitch, const uint8* SourceData)
{
const FPixelFormatInfo& FormatInfo = GPixelFormats[TextureRHI->GetFormat()];
const size_t UpdateHeightInTiles = FMath::DivideAndRoundUp(UpdateRegion.Height, (uint32)FormatInfo.BlockSizeY);
const size_t SourceDataSize = static_cast<size_t>(SourcePitch) * UpdateHeightInTiles;
uint8* SourceDataCopy = (uint8*)FMemory::Malloc(SourceDataSize);
FMemory::Memcpy(SourceDataCopy, SourceData, SourceDataSize);
SourceData = SourceDataCopy;
// other code
}
And I find that the SourceDataSize
is static_cast<size_t>(SourcePitch) * UpdateHeightInTiles
And I think when the RegionCopy.SrcY + UpdateRegion.Height
== Height of the texture and RegionCopy.SrcX != 0
, because the code make the SourceData start with (RegionCopy.SrcX, RegionCopy.SrcY), Memcpy
will access the invalid memory.
The debug info also shows the crash occur when RegionCopy.SrcY + UpdateRegion.Height
== Height of the texture and RegionCopy.SrcX != 0
. I think it confirm my guess