Download

FViewPort::ReadPixels crash while play on "standalone Game" mode

hi, i am a newer doing project on ue4.5
Now i need to render the cube to a image. And the render texture can not use MSAA, So i need to render the vireport six times and capture viewport and merge the six image to a cubemap.
I change new render window to 1024 * 1024 mode(cubemap must be width == height).
But i found that FViewPort::ReadPixels crash while play on “standalone Game” mode and runs well on “Selected Viewport” mode.(“Selected Viewport” mode could not resize window to 1024 * 1024)

why FViewPort::ReadPixels crash? the crash message is: counld not located import “SetCheckUserInterruptShared” on dbgeng.dll

My code like this:



			UWorld* world = GetWorld();
			if (world)
			{
				UGameViewportClient* viewportClient = GEngine->GameViewportForWorld(world);

				FSceneViewport* svp = viewportClient->GetGameViewport();
                                TArray<FColor> left;
                                svp->ReadPixels(left, FReadSurfaceDataFlags());
                         }



And i confirm the svp not NULL.
My os is windows 8.
Sorry for my poor english.

Thankyou.

Are you sure that pointer will be available outside PiE?

Could you post the crash log?

Only Call ReadPixels inside of GameViewport:: Draw

I had this issue during the Beta, you can only call ReadPixels inside of the Draw function of Viewport class!

So this means you need to use your own custom GameViewport class and override Draw()

For your entertainment here is my example of using ReadPixels to take a screenshot!

Anywhere in your code base you can set the bool to true to trigger a screenshot on the next Draw call.

Enjoy!



//Draw
void USolusViewportClient::Draw(FViewport * Viewport, FCanvas * SceneCanvas)
{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//this line is reaalllly important
	Super::Draw(Viewport, SceneCanvas);
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	//UE_LOG(Victory,Warning,TEXT("VICTORY GAME VIEWPORT Ticking!"));
	
	//Take Screen shot?
	if (VictoryDoScreenShot)
	{
		VictoryDoScreenShot = false;
		VictoryTakeScreenShot();	
	}
}


So inside of VictoryTakeScreenShot() is where you’d make the call to ReadPixels()

But this setup allows you to trigger a screenshot from anywhere!


.h

Here's what the .h looks like.



```



#pragma once

#include "SolusViewportClient.generated.h"

UCLASS()
class USolusViewportClient : public UGameViewportClient
{
	GENERATED_UCLASS_BODY()
	
//set this from anywhere to trigger screenshot inside of Draw()
public:  
	//Triggers ScreenShot
	bool VictoryDoScreenShot;

//protected because must only be run from Draw() or causes crash
protected:
	
	void VictoryTakeScreenShot();
	
	virtual void Draw(FViewport* Viewport,FCanvas* SceneCanvas) override;

};



```



DefaultEngine.ini Config

You have to tell UE4 to use your custom viewport class:



[/Script/Engine.Engine]
GameViewportClientClassName=/Script/Solus.SolusViewportClient


:heart:

Rama

As Rama said, try doing it within a Draw function, normally accessing view stuff requires a valid view which is only valid while drawing. This applies to accessing the view or the canvas when you are doing stuff with the HUD.

Thanks for all reply, I call ReadPixels on Tick (virtual void Tick(float /DeltaTime/DeltaSeconds)), I’ll try rewrite Draw.

the crash log:


[2014.11.03-04.08.35:526][132]LogWindows: === Critical error: ===
Fatal error: [File:E:\unreal4.5\Source\UnrealEngine-4.5.0-release\Engine\Source\Runtime\RenderCore\Private\RenderingThread.cpp] [Line: 641] 
Rendering thread exception:
Fatal error!

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000020

UE4Editor-D3D11RHI-Win64-Debug.dll!FD3D11DynamicRHI::RHIReadSurfaceData() (0x00007fffea4a5937) + 5 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\windows\d3d11rhi\private\d3d11rendertarget.cpp:991]
UE4Editor-RHI-Win64-Debug.dll!ReadSurfaceData_Internal() (0x00007ffff758bd52) + 186 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\rhi\public\rhimethods.h:1226]
UE4Editor-RHI-Win64-Debug.dll!FRHICommandListImmediate::ReadSurfaceData() (0x00007ffff758b5f2) + 2486 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\rhi\public\rhimethods.h:1226]
UE4Editor-Engine-Win64-Debug.dll!`FRenderTarget::ReadPixels'::`5'::EURCMacro_ReadSurfaceCommand::DoTask() (0x00007fffef806b33) + 191 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\engine\private\unrealclient.cpp:72]
UE4Editor-Engine-Win64-Debug.dll!TGraphTask<`FRenderTarget::ReadPixels'::`5'::EURCMacro_ReadSurfaceCommand>::ExecuteTask() (0x00007fffef843745) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\public\async	askgraphinterfaces.h:667]
UE4Editor-Core-Win64-Debug.dll!FBaseGraphTask::Execute() (0x00007ffff7d9208d) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\public\async	askgraphinterfaces.h:299]
UE4Editor-Core-Win64-Debug.dll!FTaskThread::ProcessTasks() (0x00007ffff7de9a59) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\private\async	askgraph.cpp:334]
UE4Editor-Core-Win64-Debug.dll!FTaskThread::ProcessTasksUntilQuit() (0x00007ffff7dea2a6) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\private\async	askgraph.cpp:177]
UE4Editor-Core-Win64-Debug.dll!FTaskGraphImplementation::ProcessThreadUntilRequestReturn() (0x00007ffff7dea47a) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\private\async	askgraph.cpp:838]
UE4Editor-RenderCore-Win64-Debug.dll!RenderingThreadMain() (0x00007ffff7659ebc) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\rendercore\private\renderingthread.cpp:268]
UE4Editor-RenderCore-Win64-Debug.dll!FRenderingThread::Run() (0x00007ffff765a439) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\rendercore\private\renderingthread.cpp:368]
UE4Editor-Core-Win64-Debug.dll!FRunnableThreadWin::Run() (0x00007ffff8200191) + 24 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\private\windows\windowsrunnablethread.cpp:71]
UE4Editor-Core-Win64-Debug.dll!FRunnableThreadWin::GuardedRun() (0x00007ffff81f0f9c) + 13 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\private\windows\windowsrunnablethread.cpp:26]
UE4Editor-Core-Win64-Debug.dll!FRunnableThreadWin::_ThreadProc() (0x00007ffff8210e90) + 0 bytes [e:\unreal4.5\source\unrealengine-4.5.0-release\engine\source\runtime\core\private\windows\windowsrunnablethread.h:85]
KERNEL32.DLL!UnknownFunction (0x00007ff8135316ad) + 0 bytes [UnknownFile:0]
ntdll.dll!UnknownFunction (0x00007ff815994409) + 0 bytes [UnknownFile:0]
ntdll.dll!UnknownFunction (0x00007ff815994409) + 0 bytes [UnknownFile:0]

Are you calling it still from a tick or a draw call? From the place it crashes it seams that the Texture is not valid and its GetResource() returns a null pointer, could you put a breakpoint there or a log checking for null both for the texture and it’s resource?

Thanks for Rama, I had done it.

Thanks for Moss. i call the readpixel function during character tick. Maybe it can’t be called. I had done it as Rama’s method. Thankyou for all replys.