Files
UnrealEngineUWP/Engine/Source/Editor/Blutility/Private/AsyncCaptureScene.cpp

140 lines
4.2 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AsyncCaptureScene.h"
#include "EditorUtilitySubsystem.h"
#include "Editor.h"
#include "Camera/CameraComponent.h"
#include "Engine/SceneCapture2D.h"
#include "Engine/TextureRenderTarget2D.h"
#include "Components/SceneCaptureComponent2D.h"
#include "ImageWriteQueue.h"
#include "Modules/ModuleManager.h"
#include "ImagePixelData.h"
#include "Engine/GameEngine.h"
#include "ContentStreaming.h"
#include "HAL/PlatformProperties.h"
#include "ShaderCompiler.h"
#include "IAutomationControllerManager.h"
#include "IAutomationControllerModule.h"
Adding functionality to compile remaining shaders for materials. When running with ODSC in the editor Materials can have incomplete or partial shader maps. In other words some shaders _might_ be missing. If a render system requires all shaders to be present and can't use ODSC functionality to compile the necessary shaders we need a mechanism for compiling just the missing shaders. - Added UMaterialInterface::CacheShaders() which is implemented for UMatetrial and UMaterialInstance. The call is just forwarded along to CacheResourceShadersForRendering and InitStaticPermutation respectively. - You can call CacheResourceShadersForRendering multiple times (even with a completed shader map) and it will not recache uniform expressions. If the Resource's shader map is complete the function is a no-op. - FObjectCacheContext can accept a UWorld and will only return primitives that are in that world. - Added a function SubmitRemainingJobsForWorld(UWorld* World, EMaterialShaderPrecompileMode CompileMode) that will iterate all materials used by primitives in the world and compile the missing shaders. - SubmitRemainingJobsForWorld() is used in various scenarios in the editor to ensure _all_ shaders are compiled for all materials before proceeding. - Explicitly try to compile UI and PP materials. Since we don't know which ones are used in the given world we just have to iterate all loaded ones. This is a potential area of optimization. - If there are already complete shader maps (if you are not running with the shader job cache), SubmitRemainingJobsForWorld is fast and results in a no-op for each material. #rb Arciel.Rekman, Danny.Couture #jira UE-136442, UE-136447 #preflight 61fc0e9c176256ec4f764206 [CL 18848560 by Jason Nadro in ue5-main branch]
2022-02-03 15:12:58 -05:00
#include "Materials/MaterialInterface.h"
#include "AssetCompilingManager.h"
//----------------------------------------------------------------------//
// UAsyncCaptureScene
//----------------------------------------------------------------------//
UAsyncCaptureScene::UAsyncCaptureScene()
{
}
UAsyncCaptureScene* UAsyncCaptureScene::CaptureSceneAsync(UCameraComponent* ViewCamera, TSubclassOf<ASceneCapture2D> SceneCaptureClass, int ResX, int ResY)
{
UAsyncCaptureScene* AsyncTask = NewObject<UAsyncCaptureScene>();
AsyncTask->Start(ViewCamera, SceneCaptureClass, ResX, ResY, 0);
return AsyncTask;
}
UAsyncCaptureScene* UAsyncCaptureScene::CaptureSceneWithWarmupAsync(UCameraComponent* ViewCamera, TSubclassOf<ASceneCapture2D> SceneCaptureClass, int ResX, int ResY, int WarmUpFrames)
{
UAsyncCaptureScene* AsyncTask = NewObject<UAsyncCaptureScene>();
AsyncTask->Start(ViewCamera, SceneCaptureClass, ResX, ResY, WarmUpFrames);
return AsyncTask;
}
void UAsyncCaptureScene::Start(UCameraComponent* ViewCamera, TSubclassOf<ASceneCapture2D> SceneCaptureClass, int ResX, int ResY, int InWarmUpFrames)
{
const FVector CaptureLocation = ViewCamera->GetComponentLocation();
const FRotator CaptureRotation = ViewCamera->GetComponentRotation();
UWorld* World = ViewCamera->GetWorld();
SceneCapture = World->SpawnActor<ASceneCapture2D>(SceneCaptureClass, CaptureLocation, CaptureRotation);
if (SceneCapture)
{
USceneCaptureComponent2D* CaptureComponent = SceneCapture->GetCaptureComponent2D();
if (CaptureComponent->TextureTarget == nullptr)
{
SceneCaptureRT = NewObject<UTextureRenderTarget2D>(this, TEXT("AsyncCaptureScene_RT"), RF_Transient);
SceneCaptureRT->RenderTargetFormat = RTF_RGBA8_SRGB;
SceneCaptureRT->InitAutoFormat(ResX, ResY);
SceneCaptureRT->UpdateResourceImmediate(true);
CaptureComponent->TextureTarget = SceneCaptureRT;
}
else
{
SceneCaptureRT = CaptureComponent->TextureTarget;
}
FMinimalViewInfo CaptureView;
ViewCamera->GetCameraView(0, CaptureView);
CaptureComponent->SetCameraView(CaptureView);
}
WarmUpFrames = FMath::Max(InWarmUpFrames, 1);
}
void UAsyncCaptureScene::Activate()
{
if (!SceneCapture)
{
NotifyComplete(nullptr);
}
FinishLoadingBeforeScreenshot();
USceneCaptureComponent2D* CaptureComponent = SceneCapture->GetCaptureComponent2D();
CaptureComponent->CaptureScene();
FinishLoadingBeforeScreenshot();
for (int32 FrameCount = 0; FrameCount < WarmUpFrames; ++FrameCount)
{
CaptureComponent->CaptureScene();
}
NotifyComplete(SceneCaptureRT);
}
void UAsyncCaptureScene::NotifyComplete(UTextureRenderTarget2D* InTexture)
{
Complete.Broadcast(InTexture);
SetReadyToDestroy();
if (SceneCapture)
{
SceneCapture->Destroy();
}
}
void UAsyncCaptureScene::FinishLoadingBeforeScreenshot()
{
FlushAsyncLoading();
Adding functionality to compile remaining shaders for materials. When running with ODSC in the editor Materials can have incomplete or partial shader maps. In other words some shaders _might_ be missing. If a render system requires all shaders to be present and can't use ODSC functionality to compile the necessary shaders we need a mechanism for compiling just the missing shaders. - Added UMaterialInterface::CacheShaders() which is implemented for UMatetrial and UMaterialInstance. The call is just forwarded along to CacheResourceShadersForRendering and InitStaticPermutation respectively. - You can call CacheResourceShadersForRendering multiple times (even with a completed shader map) and it will not recache uniform expressions. If the Resource's shader map is complete the function is a no-op. - FObjectCacheContext can accept a UWorld and will only return primitives that are in that world. - Added a function SubmitRemainingJobsForWorld(UWorld* World, EMaterialShaderPrecompileMode CompileMode) that will iterate all materials used by primitives in the world and compile the missing shaders. - SubmitRemainingJobsForWorld() is used in various scenarios in the editor to ensure _all_ shaders are compiled for all materials before proceeding. - Explicitly try to compile UI and PP materials. Since we don't know which ones are used in the given world we just have to iterate all loaded ones. This is a potential area of optimization. - If there are already complete shader maps (if you are not running with the shader job cache), SubmitRemainingJobsForWorld is fast and results in a no-op for each material. #rb Arciel.Rekman, Danny.Couture #jira UE-136442, UE-136447 #preflight 61fc0e9c176256ec4f764206 [CL 18848560 by Jason Nadro in ue5-main branch]
2022-02-03 15:12:58 -05:00
UWorld* CurrentWorld{ nullptr };
// Make sure we finish all level streaming
if (UGameEngine* GameEngine = Cast<UGameEngine>(GEngine))
{
if (UWorld* GameWorld = GameEngine->GetGameWorld())
{
Adding functionality to compile remaining shaders for materials. When running with ODSC in the editor Materials can have incomplete or partial shader maps. In other words some shaders _might_ be missing. If a render system requires all shaders to be present and can't use ODSC functionality to compile the necessary shaders we need a mechanism for compiling just the missing shaders. - Added UMaterialInterface::CacheShaders() which is implemented for UMatetrial and UMaterialInstance. The call is just forwarded along to CacheResourceShadersForRendering and InitStaticPermutation respectively. - You can call CacheResourceShadersForRendering multiple times (even with a completed shader map) and it will not recache uniform expressions. If the Resource's shader map is complete the function is a no-op. - FObjectCacheContext can accept a UWorld and will only return primitives that are in that world. - Added a function SubmitRemainingJobsForWorld(UWorld* World, EMaterialShaderPrecompileMode CompileMode) that will iterate all materials used by primitives in the world and compile the missing shaders. - SubmitRemainingJobsForWorld() is used in various scenarios in the editor to ensure _all_ shaders are compiled for all materials before proceeding. - Explicitly try to compile UI and PP materials. Since we don't know which ones are used in the given world we just have to iterate all loaded ones. This is a potential area of optimization. - If there are already complete shader maps (if you are not running with the shader job cache), SubmitRemainingJobsForWorld is fast and results in a no-op for each material. #rb Arciel.Rekman, Danny.Couture #jira UE-136442, UE-136447 #preflight 61fc0e9c176256ec4f764206 [CL 18848560 by Jason Nadro in ue5-main branch]
2022-02-03 15:12:58 -05:00
CurrentWorld = GameWorld;
GameWorld->FlushLevelStreaming(EFlushLevelStreamingType::Full);
}
}
Adding functionality to compile remaining shaders for materials. When running with ODSC in the editor Materials can have incomplete or partial shader maps. In other words some shaders _might_ be missing. If a render system requires all shaders to be present and can't use ODSC functionality to compile the necessary shaders we need a mechanism for compiling just the missing shaders. - Added UMaterialInterface::CacheShaders() which is implemented for UMatetrial and UMaterialInstance. The call is just forwarded along to CacheResourceShadersForRendering and InitStaticPermutation respectively. - You can call CacheResourceShadersForRendering multiple times (even with a completed shader map) and it will not recache uniform expressions. If the Resource's shader map is complete the function is a no-op. - FObjectCacheContext can accept a UWorld and will only return primitives that are in that world. - Added a function SubmitRemainingJobsForWorld(UWorld* World, EMaterialShaderPrecompileMode CompileMode) that will iterate all materials used by primitives in the world and compile the missing shaders. - SubmitRemainingJobsForWorld() is used in various scenarios in the editor to ensure _all_ shaders are compiled for all materials before proceeding. - Explicitly try to compile UI and PP materials. Since we don't know which ones are used in the given world we just have to iterate all loaded ones. This is a potential area of optimization. - If there are already complete shader maps (if you are not running with the shader job cache), SubmitRemainingJobsForWorld is fast and results in a no-op for each material. #rb Arciel.Rekman, Danny.Couture #jira UE-136442, UE-136447 #preflight 61fc0e9c176256ec4f764206 [CL 18848560 by Jason Nadro in ue5-main branch]
2022-02-03 15:12:58 -05:00
// Finish compiling the shaders if the platform doesn't require cooked data.
if (!FPlatformProperties::RequiresCookedData())
{
UMaterialInterface::SubmitRemainingJobsForWorld(CurrentWorld);
FAssetCompilingManager::Get().FinishAllCompilation();
IAutomationControllerModule& AutomationController = IAutomationControllerModule::Get();
AutomationController.GetAutomationController()->ResetAutomationTestTimeout(TEXT("shader compilation"));
}
// Force all mip maps to load before taking the screenshot.
UTexture::ForceUpdateTextureStreaming();
IStreamingManager::Get().StreamAllResources(0.0f);
}