Skip to content

Commit b534e4c

Browse files
committed
[Bug] Fixed potential race condition in RawColors: enqueue AsyncTask on render thread to safely move data to game thread
1 parent 813d8e5 commit b534e4c

1 file changed

Lines changed: 19 additions & 10 deletions

File tree

Source/CustomShapeButton/Private/SCustomShapeButton.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,25 +215,34 @@ void SCustomShapeButton::UpdateRawColors_Texture(const UTexture2D& Texture)
215215

216216
// Get Raw Colors data on Render thread
217217
TWeakPtr<SCustomShapeButton> WeakThisPtr = StaticCastWeakPtr<SCustomShapeButton>(AsWeak());
218-
checkf(WeakThisPtr.IsValid(), TEXT("ERROR: [%i] %hs:\n'WeakThis' is not valid!"), __LINE__, __FUNCTION__);
219-
const TWeakObjectPtr<const UTexture2D> WeakTexture = &Texture;
218+
const TWeakObjectPtr WeakTexture(&Texture);
220219
const FIntRect TextureSize(0, 0, TextureRes.X, TextureRes.Y);
221220
ENQUEUE_RENDER_COMMAND(TryUpdateRawColorsOnce)([WeakThisPtr, WeakTexture, TextureSize](FRHICommandListImmediate& RHICmdList)
222221
{
223-
SCustomShapeButton* This = WeakThisPtr.Pin().Get();
224-
if (!ensureMsgf(This, TEXT("ASSERT: [%i] %hs:\n'This' is not valid!"), __LINE__, __FUNCTION__))
222+
const UTexture2D* Texture2D = WeakTexture.Get();
223+
const FTextureResource* TextureResource = Texture2D ? Texture2D->GetResource() : nullptr;
224+
FRHITexture* RHITexture = TextureResource ? TextureResource->GetTexture2DRHI() : nullptr;
225+
if (!ensureMsgf(RHITexture, TEXT("%hs: 'RHITexture' is not valid"), __FUNCTION__))
225226
{
226227
return;
227228
}
228229

229-
const UTexture2D* Texture2D = WeakTexture.Get();
230-
const FTextureResource* TextureResource = Texture2D ? Texture2D->GetResource() : nullptr;
231-
FRHITexture* RHITexture = TextureResource ? TextureResource->GetTexture2DRHI() : nullptr;
232-
if (ensureMsgf(RHITexture, TEXT("%hs: 'RHITexture' is not valid"), __FUNCTION__))
230+
// Obtain data
231+
TArray<FColor> OutColors;
232+
RHICmdList.ReadSurfaceData(RHITexture, TextureSize, OutColors, FReadSurfaceDataFlags());
233+
if (!ensureMsgf(!OutColors.IsEmpty(), TEXT("ASSERT: [%i] %hs:\n'OutColors' is empty, failed to read texture data!"), __LINE__, __FUNCTION__))
233234
{
234-
// Copy data to cache
235-
RHICmdList.ReadSurfaceData(RHITexture, TextureSize, /*out*/This->RawColors, FReadSurfaceDataFlags());
235+
return;
236236
}
237+
238+
// Set the data on Game thread
239+
AsyncTask(ENamedThreads::GameThread, [WeakThisPtr, TempColors = MoveTemp(OutColors)]() mutable -> void
240+
{
241+
if (SCustomShapeButton* This = WeakThisPtr.Pin().Get())
242+
{
243+
This->RawColors = MoveTemp(TempColors);
244+
}
245+
});
237246
});
238247
}
239248

0 commit comments

Comments
 (0)