You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3232283 on 2016/12/13 by Ben.Woodhouse D3D12 - downgrade root signature size warning to a log following a discussion with Microsoft. There's not much we can actually do about it, and it's not relevant to all hardware #jira UE-36999 Change 3232641 on 2016/12/13 by Mark.Satterthwaite - Eliminate redundant state changes in MetalRHI in the state cache. - Add a new debug level for setting buffers to nil prior to calls to set*Bytes so that the tool doesn't display incorrect data. - Make testing for validation & statistics features use the same EMetalFeatures API as everything else for consistency. - Cache the fallback depth-stencil texture in the state cache and ignore it for determining whether a pass can restart - if we are using this texture its contents are worthless anyway. Change 3232661 on 2016/12/13 by Mark.Satterthwaite Re-enable Metal SM5 & DFAO/DistanceFieldShadowing on Intel for 10.12.2 or later. Change 3232759 on 2016/12/13 by Ben.Woodhouse Fix memory leak on XB1 when calling GPURealloc with count of 0, suggested on UDN https://udn.unrealengine.com/questions/326660/gpurealloc-leak.html Change 3232803 on 2016/12/13 by Ben.Marsh Add UT to the populate DDC job, and cook UT and Fortnite for Mac as well. Change 3232836 on 2016/12/13 by Ben.Marsh Split cooks to populate DDC into separate nodes for each platform. May help to reduce number of timeouts on remote VMs. Change 3232974 on 2016/12/13 by Rolando.Caloca DR - Refactor common code to UWorld::RecreateScene #jira UE-36719 PR #2824 Change 3232976 on 2016/12/13 by Ben.Marsh Add missing dependency on tools node for Mac cooks. Need to compile SCW first. Change 3233289 on 2016/12/13 by Olaf.Piesche Fixing potentially broken spot/point light fade with old content; initialize new properties properly Change 3233811 on 2016/12/13 by Mark.Satterthwaite Fix compiling QA-Material tessellation shaders that don't need to emit from Hull or sample in Domain the HSOut buffer which was confusing MetalBackend. Change 3233854 on 2016/12/13 by Mark.Satterthwaite More information about texture type validation errors in Metal. Change 3234650 on 2016/12/14 by Rolando.Caloca DR - vk - Fix bad aspect on depth cubemaps Change 3234651 on 2016/12/14 by Rolando.Caloca DR - vk - Fix for 32 bit crash on dump layer Change 3234813 on 2016/12/14 by Guillaume.Abadie Fixes texture mask static lighting when using GBuffer selective outputs. #jira UE-39527 Change 3235047 on 2016/12/14 by Uriel.Doyon Refactored HLOD texture streaming strategy to separate forced load from visibility. Added an incremental update in the last stage of the texture streaming update load to clear any pending work. Added an option "All" to the "BuildMateriaTexturelStreamingData" command to force rebuild everything. Change 3235317 on 2016/12/14 by Uriel.Doyon Removed timed primitives in the texture streaming since it was not used and there is now a fallback implementation in UPrimitiveComponent::GetStreamingTextureInfo. Change 3235431 on 2016/12/14 by Rolando.Caloca DR - Fix for Vulkan drawing black Change 3236788 on 2016/12/15 by Mark.Satterthwaite Fix 10.11.6 support (aka -nometalv2): the stencil view workaround necessitates a mid-render blit and the way things were setup resulted in the HasValidRenderTargets assert firing. Refactored the code to separate the concept or valid render-states in the cache from active render-states in the render-pass. Now it works as intended and will be needed for 4.15. Change 3236850 on 2016/12/15 by Mark.Satterthwaite Make changing the Metal Shader Version project setting prompt the user to restart for the changes to take effect. #jira UE-39801 Change 3237002 on 2016/12/15 by Benjamin.Hyder submitting updated TM-Shadermodels map Change 3237312 on 2016/12/15 by Rolando.Caloca DR - Change more macros to lambdas Change 3237394 on 2016/12/15 by Mark.Satterthwaite Add Metal-specific permutations of TBasePassHS - they affect the C++ definition on all platforms but are only cached or used on Metal - because the way we compile the combined VS+HS tessellation stage requires that the combined VS + HS HLSL code references the same resources, otherwise we get incorrect resouce bindings and subsequently fail to render properly. Long-term the Metal tessellation code will need to be refactored so that the vertex shader stage is emitted as a separate shader from the hull shader stage as this but will keep cropping back up and continue to complicate the engine. #jira UE-39799 Change 3237490 on 2016/12/15 by Daniel.Wright Fixed ULandscapeComponent::GetUsedMaterials Change 3237597 on 2016/12/15 by Ben.Woodhouse Disable timestamp queries on pre-Maxwell nvidia hardware. Local testing suggests that this is the major cause of instability in the UE4.14 release. It's possible that we could be more targeted by only excluding Fermi and older hardware, but identifying fermi hardware by device ID is difficult in practice, since the range overlaps with Kepler. Change 3237654 on 2016/12/15 by Daniel.Wright Non-editor compile fix Change 3238229 on 2016/12/16 by Rolando.Caloca DR - Remove ExcludeRect from inner RHI Clear methods; ensure will happen if trying to use it Change 3238236 on 2016/12/16 by Rolando.Caloca DR - Compile fixes Change 3238280 on 2016/12/16 by Marc.Olano Small optimization to Lanczos-3 upsample shader code. Change 3238321 on 2016/12/16 by Rolando.Caloca DR - Compile fix Change 3238331 on 2016/12/16 by Rolando.Caloca DR - compile fix Change 3238495 on 2016/12/16 by Marc.Olano Replace TEA random number generator with PCG. Was only used in #if-disabled reference rendering, but ldoes make better quality reference rendering when enabled. Change 3238496 on 2016/12/16 by Marc.Olano Tone mapping fix for OR-31752, cherry picked from Orion 3208273 Assumption that green is approximates luminance fails on red/blue HDR content, resulting in ugly black artifacts. Go back to luminance. Change 3238520 on 2016/12/16 by Rolando.Caloca DR - CIS Fix Change 3238571 on 2016/12/16 by Rolando.Caloca DR - CIS fix Change 3238605 on 2016/12/16 by Daniel.Wright Sharing IndirectLightingCacheTextureSampler samplers Change 3238626 on 2016/12/16 by Daniel.Wright Ray Traced Distance Field Shadow optimizations * Tighter light space tile culling * Skip ray marching pixels before the RTDF cascade near distance, or further than the cascade far distance * Depth bounds test on upsample * Created FLightTileIntersectionParameters for encapsulation of light tile culling functionality * RTDF shadow time went from 1.8ms -> .8ms and 3.1ms -> 1.2ms in FortGPUTestbed on 7870 with these changes Change 3238652 on 2016/12/16 by Rolando.Caloca DR - RHI clear methods no longer have an ExcludeRect, use DrawClearQuad functions instead Change 3238855 on 2016/12/16 by Rolando.Caloca DR - Added FRHITexture2D GetSizeXY Change 3238881 on 2016/12/16 by Rolando.Caloca DR - CIS fix Change 3239008 on 2016/12/16 by Arne.Schober DR - Fixing accidently returning a stackpointer in EnqueueRenderCommands Change 3239012 on 2016/12/16 by Arne.Schober DR - missing file Change 3239255 on 2016/12/17 by Rolando.Caloca DR - Remove shader clears from D3D11 Change 3239690 on 2016/12/19 by Rolando.Caloca DR - vk - Misc fixes from 1.0.37.00 SDK warnings Change 3239964 on 2016/12/19 by Rolando.Caloca DR - Fix click on editor not showing selected Change 3239995 on 2016/12/19 by Rolando.Caloca DR - Enable dist field on GL4 & Vulkan SM5 Change 3240162 on 2016/12/19 by Daniel.Wright Added EnableDepthBoundsTest / DisableDepthBoundsTest to RHIUtilites to share some common code Change 3240163 on 2016/12/19 by Daniel.Wright Distance field self shadowing controls for hiding world position offset self-shadow artifacts * Removed static mesh build settings DistanceFieldBias, which shrunk the distance field, breaking AO and shadows * Added DistanceFieldSelfShadowBias, which prevents occlusion close to the surface only, maintaining shadows on the ground and AO on the ground Change3240271on 2016/12/19 by Daniel.Wright Use 16 bit indices for distance field objects culled to tiles, when 16 bit will be enough. Saves 10mb of tile culling buffers. Change 3240282 on 2016/12/19 by Rolando.Caloca DR - Proper fix for hit proxies clear - Added missing stencil ref to DrawClearQuad Change 3240316 on 2016/12/19 by Rolando.Caloca DR - vk - Fixed some new 1.0.37.0 warnings Change 3240354 on 2016/12/19 by Rolando.Caloca DR - Dev shaders on sm4/5 Change 3240759 on 2016/12/20 by Rolando.Caloca DR - Fix bad crc on GL element declarations Change 3240895 on 2016/12/20 by Rolando.Caloca DR - vk - Swapchain fixes Change 3241057 on 2016/12/20 by Rolando.Caloca DR - vk - Fix resize on desktop Change 3241112 on 2016/12/20 by Rolando.Caloca DR - vk - Fix 1.0.37.0 warnings - Ignore some warnings we know we can't fix Change 3241310 on 2016/12/20 by Rolando.Caloca DR - vk - Fix crash Change 3241417 on 2016/12/20 by Daniel.Wright [Copy] Fixed race condition with FPrecomputedLightVolume::Data which was exposed when switching lighting scenarios Change 3241990 on 2016/12/21 by Daniel.Wright Converted DistanceFieldVolume data to BulkData * FDistanceFieldVolumeData Serialize time from .7s on PS4 to 0s Change 3242005 on 2016/12/21 by Daniel.Wright Removed unused !USE_DEPTH_RANGE_LISTS path to reduce complexity Change 3242295 on 2016/12/21 by Bob.Tellez Duplicating CL#3242294 from //Fortnite/Main #UE4 Re-applying the fix for rendering editor primitives when r.EarlyZPassOnlyMaterialMasking is enabled Change 3242487 on 2016/12/21 by Marcus.Wassmer Fix typo Change 3243091 on 2016/12/22 by Daniel.Wright Fixed too many groups dispatched for TConeTraceScreenGridGlobalOcclusionCS Change 3243161 on 2016/12/22 by Uriel.Doyon New async tasks for the streaming update. Optimizing the biggest frame cost. Change 3243179 on 2016/12/22 by Uriel.Doyon Fixed possible invalid access from the async FNormalizeLightmapTexelFactorTask Change 3243236 on 2016/12/22 by Daniel.Wright Fixed DFAO bilateral upsample * Depth buffer was being unbound due to lack of DepthRead_StencilNop Change 3243452 on 2016/12/23 by Ben.Woodhouse Bring back 1024 render query limit workaround on D3D12 which was lost during the merge from partners #jira UE-35247 Change 3243512 on 2016/12/23 by Uriel.Doyon Improved task system for texture streaming. Change 3243742 on 2016/12/26 by Rolando.Caloca DR - vk - Fix UAV clears - Removed old validation layer - Print found device layers Change 3243745 on 2016/12/27 by Rolando.Caloca DR - vk - Fix for texture cube arrays - Warning for ClearUAVs Change 3243762 on 2016/12/27 by Rolando.Caloca DR - vk - Always use pipeline cache Change 3244450 on 2016/12/31 by Rolando.Caloca DR - vk - Pre reqs for separate transfer queue Change 3244453 on 2016/12/31 by Rolando.Caloca DR - vk - Win32 compile fix Change3244756on 2017/01/03 by Marcus.Wassmer Copying //Tasks/UE4/Dev-Niagara@3244743 to Dev-Rendering (//UE4/Dev-Rendering) Change 3244757 on 2017/01/03 by Marcus.Wassmer Niagara is still experimental in non-task branches. Change 3245059 on 2017/01/03 by Benjamin.Hyder Submitting TM-TrigNodes map Change 3245500 on 2017/01/03 by Olaf.Piesche Compile fix #1 for post-merge problems Change 3245572 on 2017/01/03 by Olaf.Piesche (Speculative) fix #2 for post-merge build problem. Hopefully fixes public distribution level error for cross compiler tool. Change 3245683 on 2017/01/03 by Marcus.Wassmer Fix some niagara warnings Change 3245732 on 2017/01/03 by Marcus.Wassmer Fix Niagara compile on clang platforms. Fix a few warnings / static analysis things as well. Change 3246403 on 2017/01/04 by Rolando.Caloca DR - vk - Fix bogus warning Change 3246432 on 2017/01/04 by Marcus.Wassmer Copying //Tasks/UE4/Dev-Niagara@3246424 to Dev-Rendering (//UE4/Dev-Rendering) Change 3246538 on 2017/01/04 by Rolando.Caloca DR - vk - Show hitch time for compute psos Change 3246580 on 2017/01/04 by Rolando.Caloca DR - vk - compile fix Change 3246610 on 2017/01/04 by Rolando.Caloca DR - Compute PSO pre reqs Change 3246707 on 2017/01/04 by Marcus.Wassmer Add missing integer operations to UnrealMathDirectX.h Change 3246786 on 2017/01/04 by Marcus.Wassmer Avoid public dependency build errors. Should probably just remove the DDCUtils module instead Change 3246828 on 2017/01/04 by Olaf.Piesche UE-39249; need to check the view as well as the view family in CheckAndUpdateLastFrame; scene captures use a different family, but each eye for VR uses a different scene view. Change 3247026 on 2017/01/04 by Rolando.Caloca DR - Remove CrossCompilerTool as it's not required anymore Change 3247086 on 2017/01/04 by Marcus.Wassmer Remove includes for Core.h monolithic header Change 3247227 on 2017/01/04 by Marcus.Wassmer Fix typo and compile errors. Change 3247228 on 2017/01/04 by Marcus.Wassmer Use crossplatform intrinsics Change 3247229 on 2017/01/04 by Marcus.Wassmer Implement missing integer NEON operations. Change NEON vectorint to match name and sign from other platforms Change 3247245 on 2017/01/04 by Marcus.Wassmer Fixing various warnings/errors from clang platforms (Mac/Linux) Change 3247331 on 2017/01/04 by Marcus.Wassmer More Mac/clang fixes Change 3247958 on 2017/01/05 by Marcus.Wassmer VectorInt < - > Float ops should be conversions not reinterpret cast Change 3247959 on 2017/01/05 by Marcus.Wassmer Add missing ops to non-vector header Change 3247964 on 2017/01/05 by Rolando.Caloca DR - Temp fix for crash #jira UE-40211 Change 3248067 on 2017/01/05 by Rolando.Caloca DR - Static analysis fixes #jira UE-40167 Change 3248284 on 2017/01/05 by Rolando.Caloca DR - Linuix Compile fix #jira UE-40260 Change 3248288 on 2017/01/05 by Rolando.Caloca DR - Linux compile fix #jira UE-40264 Change 3248399 on 2017/01/05 by Brian.Karis Filtered importance sampling for envmap prefiltering. Fixed SSR on clearcoat with skylight only. Change 3248503 on 2017/01/05 by Rolando.Caloca DR - Linux fixes #jira UE-40264 Change 3248666 on 2017/01/05 by Brian.Karis Fix GL compile error Change 3248740 on 2017/01/05 by Marcus.Wassmer Fix linux and clang errors/warnings Change 3248851 on 2017/01/05 by Marcus.Wassmer Simplest fix for ES2 compile errors Change 3249217 on 2017/01/06 by Simon.Tovey Speculative fix for static analysis warning Change 3249296 on 2017/01/06 by Ben.Woodhouse XB1/Fast semantics: Add missing L1/L2 cache flush on transition to readable (or RW). The missing cache flush was causing indeterminism when reading from a texture shortly after writing to it as a render target. This fixes bloom and diffuse irradiance issues The bug has been there for a while, but CL 3227787 (drawclear early out) caused it to manifest #jira UE-39727 #jira UE-40238 Change 3249300 on 2017/01/06 by Ben.Woodhouse Remove workaround for diffuse irradiance (redundant clear). No longer necessary with CL 3249296 Change 3249387 on 2017/01/06 by Rolando.Caloca DR - Fix GL clear issues #jira UE-40254 Change 3249435 on 2017/01/06 by Ben.Woodhouse Duplicated from UT CL3238664Fix dbuffer decal rendering issues in fullscreen on PC. Also fixes crash in editor when viewing dbuffer materials. Pass clearcolor in RT params for system textures to workaround a bug with ClearColorTexture not working in fullscreen mode on DX11. Make sure dbuffer targets are bound if we're rendering mesh decals #jira UT-6891 #jira UE-39842 Change 3249721 on 2017/01/06 by Marcus.Wassmer Remove final references to non-existent Niagara data Change 3249742 on 2017/01/06 by Marcus.Wassmer Fix missing GPU particles on Mac. Pointers getting reused is causing the blendstate equality operator to fail. Simple workaround until we have time for a proper fix. [CL 3249983 by Marcus Wassmer in Main branch]
1038 lines
33 KiB
C++
1038 lines
33 KiB
C++
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
VisualizeTexture.cpp: Post processing visualize texture.
|
|
=============================================================================*/
|
|
|
|
#include "PostProcess/VisualizeTexture.h"
|
|
#include "ShaderParameters.h"
|
|
#include "RHIStaticStates.h"
|
|
#include "Shader.h"
|
|
#include "StaticBoundShaderState.h"
|
|
#include "SceneUtils.h"
|
|
#include "HAL/FileManager.h"
|
|
#include "Misc/FileHelper.h"
|
|
#include "Misc/Paths.h"
|
|
#include "Misc/App.h"
|
|
#include "CanvasTypes.h"
|
|
#include "UnrealEngine.h"
|
|
#include "PostProcess/RenderTargetPool.h"
|
|
#include "PostProcess/SceneRenderTargets.h"
|
|
#include "GlobalShader.h"
|
|
#include "RenderTargetTemp.h"
|
|
#include "ScreenRendering.h"
|
|
#include "PostProcess/SceneFilterRendering.h"
|
|
#include "PostProcess/PostProcessing.h"
|
|
|
|
|
|
/** A pixel shader which filters a texture. */
|
|
// @param TextureType 0:Cube, 1:1D(not yet supported), 2:2D no MSAA, 3:3D, 4:Cube[], 5:2D MSAA, 6:2D DepthStencil no MSAA (needed to avoid D3DDebug error)
|
|
template<uint32 TextureType>
|
|
class VisualizeTexturePS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(VisualizeTexturePS,Global);
|
|
public:
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("TEXTURE_TYPE"), TextureType);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
VisualizeTexturePS() {}
|
|
|
|
/** Initialization constructor. */
|
|
VisualizeTexturePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer):
|
|
FGlobalShader(Initializer)
|
|
{
|
|
VisualizeTexture2D.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture2D"));
|
|
VisualizeDepthStencilTexture.Bind(Initializer.ParameterMap, TEXT("VisualizeDepthStencilTexture"));
|
|
|
|
VisualizeTexture2DSampler.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture2DSampler"));
|
|
VisualizeTexture2DMS.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture2DMS"));
|
|
VisualizeTexture3D.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture3D"));
|
|
VisualizeTexture3DSampler.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture3DSampler"));
|
|
VisualizeTextureCube.Bind(Initializer.ParameterMap,TEXT("VisualizeTextureCube"));
|
|
VisualizeTextureCubeSampler.Bind(Initializer.ParameterMap,TEXT("VisualizeTextureCubeSampler"));
|
|
VisualizeTextureCubeArray.Bind(Initializer.ParameterMap,TEXT("VisualizeTextureCubeArray"));
|
|
VisualizeTextureCubeArraySampler.Bind(Initializer.ParameterMap,TEXT("VisualizeTextureCubeArraySampler"));
|
|
VisualizeParam.Bind(Initializer.ParameterMap,TEXT("VisualizeParam"));
|
|
TextureExtent.Bind(Initializer.ParameterMap,TEXT("TextureExtent"));
|
|
}
|
|
|
|
/** Serializer */
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << VisualizeTexture2D;
|
|
Ar << VisualizeDepthStencilTexture;
|
|
Ar << VisualizeTexture2DSampler;
|
|
Ar << VisualizeTexture2DMS;
|
|
Ar << VisualizeTexture3D;
|
|
Ar << VisualizeTexture3DSampler;
|
|
Ar << VisualizeTextureCube;
|
|
Ar << VisualizeTextureCubeSampler;
|
|
Ar << VisualizeTextureCubeArray;
|
|
Ar << VisualizeTextureCubeArraySampler;
|
|
Ar << VisualizeParam;
|
|
Ar << TextureExtent;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FVisualizeTextureData& Data)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
{
|
|
// alternates between 0 and 1 with a short pause
|
|
const float FracTimeScale = 2.0f;
|
|
float FracTime = FApp::GetCurrentTime() * FracTimeScale - floor(FApp::GetCurrentTime() * FracTimeScale);
|
|
float BlinkState = (FracTime > 0.5f) ? 1.0f : 0.0f;
|
|
|
|
FVector4 VisualizeParamValue[3];
|
|
|
|
float Add = 0.0f;
|
|
float FracScale = 1.0f;
|
|
|
|
// w * almost_1 to avoid frac(1) => 0
|
|
VisualizeParamValue[0] = FVector4(Data.RGBMul, Data.SingleChannelMul, Add, FracScale * 0.9999f);
|
|
VisualizeParamValue[1] = FVector4(BlinkState, Data.bSaturateInsteadOfFrac ? 1.0f : 0.0f, Data.ArrayIndex, Data.CustomMip);
|
|
VisualizeParamValue[2] = FVector4(Data.InputValueMapping, 0.0f, Data.SingleChannel );
|
|
|
|
SetShaderValueArray(RHICmdList, ShaderRHI, VisualizeParam, VisualizeParamValue, 3);
|
|
}
|
|
|
|
{
|
|
FVector4 TextureExtentValue(Data.Desc.Extent.X, Data.Desc.Extent.Y, Data.Desc.Depth, 0);
|
|
|
|
SetShaderValue(RHICmdList, ShaderRHI, TextureExtent, TextureExtentValue);
|
|
}
|
|
|
|
|
|
SetSRVParameter(RHICmdList, ShaderRHI, VisualizeDepthStencilTexture, Data.StencilSRV );
|
|
SetTextureParameter(RHICmdList, ShaderRHI, VisualizeTexture2D, VisualizeTexture2DSampler, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), (FTextureRHIRef&)Data.RenderTargetItem.ShaderResourceTexture);
|
|
SetTextureParameter(RHICmdList, ShaderRHI, VisualizeTexture2DMS, (FTextureRHIRef&)Data.RenderTargetItem.TargetableTexture);
|
|
SetTextureParameter(RHICmdList, ShaderRHI, VisualizeTexture3D, VisualizeTexture3DSampler, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), (FTextureRHIRef&)Data.RenderTargetItem.ShaderResourceTexture);
|
|
SetTextureParameter(RHICmdList, ShaderRHI, VisualizeTextureCube, VisualizeTextureCubeSampler, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), (FTextureRHIRef&)Data.RenderTargetItem.ShaderResourceTexture);
|
|
SetTextureParameter(RHICmdList, ShaderRHI, VisualizeTextureCubeArray, VisualizeTextureCubeArraySampler, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), (FTextureRHIRef&)Data.RenderTargetItem.ShaderResourceTexture);
|
|
}
|
|
|
|
static const TCHAR* GetSourceFilename()
|
|
{
|
|
return TEXT("VisualizeTexture");
|
|
}
|
|
|
|
static const TCHAR* GetFunctionName()
|
|
{
|
|
return TEXT("VisualizeTexturePS");
|
|
}
|
|
|
|
protected:
|
|
FShaderResourceParameter VisualizeTexture2D;
|
|
FShaderResourceParameter VisualizeDepthStencilTexture;
|
|
FShaderResourceParameter VisualizeTexture2DSampler;
|
|
FShaderResourceParameter VisualizeTexture2DMS;
|
|
FShaderResourceParameter VisualizeTexture3D;
|
|
FShaderResourceParameter VisualizeTexture3DSampler;
|
|
FShaderResourceParameter VisualizeTextureCube;
|
|
FShaderResourceParameter VisualizeTextureCubeSampler;
|
|
FShaderResourceParameter VisualizeTextureCubeArray;
|
|
FShaderResourceParameter VisualizeTextureCubeArraySampler;
|
|
FShaderParameter VisualizeParam;
|
|
FShaderParameter TextureExtent;
|
|
};
|
|
|
|
// #define avoids a lot of code duplication
|
|
#define VARIATION1(A) typedef VisualizeTexturePS<A> VisualizeTexturePS##A; \
|
|
IMPLEMENT_SHADER_TYPE2(VisualizeTexturePS##A, SF_Pixel);
|
|
|
|
VARIATION1(0) VARIATION1(2) VARIATION1(3) VARIATION1(4) VARIATION1(5) VARIATION1(6)
|
|
#undef VARIATION1
|
|
|
|
|
|
/** Encapsulates a simple copy pixel shader. */
|
|
class FVisualizeTexturePresentPS : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FVisualizeTexturePresentPS, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FVisualizeTexturePresentPS() {}
|
|
|
|
public:
|
|
FShaderResourceParameter VisualizeTexture2D;
|
|
FShaderResourceParameter VisualizeTexture2DSampler;
|
|
|
|
/** Initialization constructor. */
|
|
FVisualizeTexturePresentPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
VisualizeTexture2D.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture2D"));
|
|
VisualizeTexture2DSampler.Bind(Initializer.ParameterMap,TEXT("VisualizeTexture2DSampler"));
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << VisualizeTexture2D << VisualizeTexture2DSampler;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
|
|
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const IPooledRenderTarget& Src)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
|
|
SetTextureParameter(RHICmdList, ShaderRHI, VisualizeTexture2D, VisualizeTexture2DSampler,
|
|
TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), (FTextureRHIRef&)Src.GetRenderTargetItem().ShaderResourceTexture);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FVisualizeTexturePresentPS,TEXT("VisualizeTexture"),TEXT("PresentPS"),SF_Pixel);
|
|
|
|
|
|
template<uint32 TextureType> void VisualizeTextureForTextureType(FRHICommandList& RHICmdList, ERHIFeatureLevel::Type FeatureLevel, const FVisualizeTextureData& Data)
|
|
{
|
|
auto ShaderMap = GetGlobalShaderMap(FeatureLevel);
|
|
TShaderMapRef<FScreenVS> VertexShader(ShaderMap);
|
|
TShaderMapRef<VisualizeTexturePS<TextureType> > PixelShader(ShaderMap);
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
PixelShader->SetParameters(RHICmdList, Data);
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
DrawRectangle(
|
|
RHICmdList,
|
|
// XY
|
|
0, 0,
|
|
// SizeXY
|
|
SceneContext.GetBufferSizeXY().X, SceneContext.GetBufferSizeXY().Y,
|
|
// UV
|
|
Data.Tex00.X, Data.Tex00.Y,
|
|
// SizeUV
|
|
Data.Tex11.X - Data.Tex00.X, Data.Tex11.Y - Data.Tex00.Y,
|
|
// TargetSize
|
|
SceneContext.GetBufferSizeXY(),
|
|
// TextureSize
|
|
FIntPoint(1, 1),
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
}
|
|
|
|
void RenderVisualizeTexture(FRHICommandListImmediate& RHICmdList, ERHIFeatureLevel::Type FeatureLevel, const FVisualizeTextureData& Data)
|
|
{
|
|
RHICmdList.CopyToResolveTarget(Data.RenderTargetItem.ShaderResourceTexture, Data.RenderTargetItem.ShaderResourceTexture, true, FResolveParams());
|
|
if(Data.Desc.Is2DTexture())
|
|
{
|
|
// 2D
|
|
if(Data.Desc.NumSamples > 1)
|
|
{
|
|
// MSAA
|
|
VisualizeTextureForTextureType<5>(RHICmdList, FeatureLevel, Data);
|
|
}
|
|
else
|
|
{
|
|
if(Data.Desc.Format == PF_DepthStencil)
|
|
{
|
|
// DepthStencil non MSAA (needed to avoid D3DDebug error)
|
|
VisualizeTextureForTextureType<6>(RHICmdList, FeatureLevel, Data);
|
|
}
|
|
else
|
|
{
|
|
// non MSAA
|
|
VisualizeTextureForTextureType<2>(RHICmdList, FeatureLevel, Data);
|
|
}
|
|
}
|
|
}
|
|
else if(Data.Desc.Is3DTexture())
|
|
{
|
|
VisualizeTextureForTextureType<3>(RHICmdList, FeatureLevel, Data);
|
|
}
|
|
else if(Data.Desc.IsCubemap())
|
|
{
|
|
if(Data.Desc.IsArray())
|
|
{
|
|
// Cube[]
|
|
VisualizeTextureForTextureType<4>(RHICmdList, FeatureLevel, Data);
|
|
}
|
|
else
|
|
{
|
|
// Cube
|
|
VisualizeTextureForTextureType<0>(RHICmdList, FeatureLevel, Data);
|
|
}
|
|
}
|
|
}
|
|
|
|
FVisualizeTexture::FVisualizeTexture()
|
|
{
|
|
Mode = 0;
|
|
RGBMul = 1.0f;
|
|
SingleChannelMul = 0.0f;
|
|
SingleChannel = -1;
|
|
AMul = 0.0f;
|
|
UVInputMapping = 3;
|
|
Flags = 0;
|
|
ObservedDebugNameReusedGoal = 0xffffffff;
|
|
ArrayIndex = 0;
|
|
CustomMip = 0;
|
|
bSaveBitmap = false;
|
|
bOutputStencil = false;
|
|
bFullList = false;
|
|
SortOrder = -1;
|
|
bEnabled = true;
|
|
}
|
|
|
|
void FVisualizeTexture::Destroy()
|
|
{
|
|
VisualizeTextureContent.SafeRelease();
|
|
StencilSRV.SafeRelease();
|
|
}
|
|
|
|
FIntRect FVisualizeTexture::ComputeVisualizeTextureRect(FIntPoint InputTextureSize) const
|
|
{
|
|
FIntRect ret = ViewRect;
|
|
FIntPoint ViewExtent = ViewRect.Size();
|
|
|
|
// set ViewRect
|
|
switch(UVInputMapping)
|
|
{
|
|
// pixel perfect centered (not yet for volume textures)
|
|
case 2:
|
|
{
|
|
FIntPoint Center = ViewExtent / 2;
|
|
FIntPoint HalfMin = InputTextureSize / 2;
|
|
FIntPoint HalfMax = InputTextureSize - HalfMin;
|
|
|
|
ret = FIntRect(Center - HalfMin, Center + HalfMax);
|
|
break;
|
|
}
|
|
|
|
// whole texture in PIP
|
|
case 3:
|
|
{
|
|
int32 LeftOffset = AspectRatioConstrainedViewRect.Min.X;
|
|
int32 BottomOffset = AspectRatioConstrainedViewRect.Max.Y - ViewRect.Max.Y;
|
|
|
|
ret = FIntRect(LeftOffset + 80, ViewExtent.Y - ViewExtent.Y / 3 - 10 + BottomOffset, ViewExtent.X / 3 + 10, ViewExtent.Y - 10 + BottomOffset) + ViewRect.Min;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void FVisualizeTexture::GenerateContent(FRHICommandListImmediate& RHICmdList, const FSceneRenderTargetItem& RenderTargetItem, const FPooledRenderTargetDesc& Desc)
|
|
{
|
|
// otherwise StartFrame() wasn't called
|
|
check(ViewRect != FIntRect(0, 0, 0, 0))
|
|
|
|
|
|
FTexture2DRHIRef VisTexture = (FTexture2DRHIRef&)RenderTargetItem.ShaderResourceTexture;
|
|
|
|
if(!IsValidRef(VisTexture) || !Desc.IsValid())
|
|
{
|
|
// todo: improve
|
|
return;
|
|
}
|
|
|
|
FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent);
|
|
|
|
FIntPoint Size = VisualizeTextureRect.Size();
|
|
|
|
// clamp to reasonable value to prevent crash
|
|
Size.X = FMath::Max(Size.X, 1);
|
|
Size.Y = FMath::Max(Size.Y, 1);
|
|
|
|
FPooledRenderTargetDesc OutputDesc(FPooledRenderTargetDesc::Create2DDesc(Size, PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable | TexCreate_ShaderResource, false));
|
|
|
|
GRenderTargetPool.FindFreeElement(RHICmdList, OutputDesc, VisualizeTextureContent, TEXT("VisualizeTexture"));
|
|
|
|
if(!VisualizeTextureContent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = VisualizeTextureContent->GetRenderTargetItem();
|
|
|
|
SetRenderTarget(RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), true);
|
|
RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor(1, 1, 0, 1));
|
|
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
FIntPoint RTExtent = FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY();
|
|
|
|
FVector2D Tex00 = FVector2D(0, 0);
|
|
FVector2D Tex11 = FVector2D(1, 1);
|
|
|
|
uint32 LocalVisualizeTextureInputMapping = UVInputMapping;
|
|
|
|
if(!Desc.Is2DTexture())
|
|
{
|
|
LocalVisualizeTextureInputMapping = 1;
|
|
}
|
|
|
|
// set UV
|
|
switch(LocalVisualizeTextureInputMapping)
|
|
{
|
|
// UV in left top
|
|
case 0:
|
|
Tex11 = FVector2D((float)ViewRect.Width() / RTExtent.X, (float)ViewRect.Height() / RTExtent.Y);
|
|
break;
|
|
|
|
// whole texture
|
|
default:
|
|
break;
|
|
}
|
|
|
|
bool bIsDefault = StencilSRVSrc == GBlackTexture->TextureRHI;
|
|
bool bDepthStencil = Desc.Is2DTexture() && Desc.Format == PF_DepthStencil;
|
|
|
|
//clear if this is a new different Stencil buffer, or it's not a stencil buffer and we haven't switched to the default yet.
|
|
bool bNeedsClear = bDepthStencil && (StencilSRVSrc != RenderTargetItem.TargetableTexture);
|
|
bNeedsClear |= !bDepthStencil && !bIsDefault;
|
|
if (bNeedsClear)
|
|
{
|
|
StencilSRVSrc = nullptr;
|
|
StencilSRV.SafeRelease();
|
|
}
|
|
|
|
//always set something into the StencilSRV slot for platforms that require a full resource binding, even if
|
|
//dynamic branching will cause them not to be used.
|
|
if(bDepthStencil && !StencilSRVSrc)
|
|
{
|
|
StencilSRVSrc = RenderTargetItem.TargetableTexture;
|
|
StencilSRV = RHICreateShaderResourceView((FTexture2DRHIRef&) RenderTargetItem.TargetableTexture, 0, 1, PF_X24_G8);
|
|
}
|
|
else if(!StencilSRVSrc)
|
|
{
|
|
StencilSRVSrc = GBlackTexture->TextureRHI;
|
|
StencilSRV = RHICreateShaderResourceView((FTexture2DRHIRef&) GBlackTexture->TextureRHI, 0, 1, PF_B8G8R8A8);
|
|
}
|
|
|
|
FVisualizeTextureData VisualizeTextureData(RenderTargetItem, Desc);
|
|
|
|
// distinguish between standard depth and shadow depth to produce more reasonable default value mapping in the pixel shader.
|
|
const bool bDepthTexture = (Desc.TargetableFlags & TexCreate_DepthStencilTargetable) != 0;
|
|
const bool bShadowDepth = (Desc.Format == PF_ShadowDepth);
|
|
|
|
VisualizeTextureData.RGBMul = RGBMul;
|
|
VisualizeTextureData.SingleChannelMul = SingleChannelMul;
|
|
VisualizeTextureData.SingleChannel = SingleChannel;
|
|
VisualizeTextureData.AMul = AMul;
|
|
VisualizeTextureData.Tex00 = Tex00;
|
|
VisualizeTextureData.Tex11 = Tex11;
|
|
VisualizeTextureData.bSaturateInsteadOfFrac = (Flags & 1) != 0;
|
|
VisualizeTextureData.InputValueMapping = bShadowDepth ? 2 : (bDepthTexture ? 1 : 0);
|
|
VisualizeTextureData.ArrayIndex = ArrayIndex;
|
|
VisualizeTextureData.CustomMip = CustomMip;
|
|
VisualizeTextureData.StencilSRV = StencilSRV;
|
|
|
|
if(!(Desc.Flags & TexCreate_CPUReadback)) // We cannot make a texture lookup on such elements
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, VisualizeTexture);
|
|
// continue rendering to HDR if necessary
|
|
RenderVisualizeTexture(RHICmdList, FeatureLevel, VisualizeTextureData);
|
|
}
|
|
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, VisCopy);
|
|
RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
VisualizeTextureDesc = Desc;
|
|
|
|
// save to disk
|
|
if(bSaveBitmap)
|
|
{
|
|
bSaveBitmap = false;
|
|
|
|
uint32 MipAdjustedExtentX = FMath::Clamp(Desc.Extent.X >> CustomMip, 0, Desc.Extent.X);
|
|
uint32 MipAdjustedExtentY = FMath::Clamp(Desc.Extent.Y >> CustomMip, 0, Desc.Extent.Y);
|
|
FIntPoint Extent(MipAdjustedExtentX, MipAdjustedExtentY);
|
|
|
|
FReadSurfaceDataFlags ReadDataFlags;
|
|
ReadDataFlags.SetLinearToGamma(false);
|
|
ReadDataFlags.SetOutputStencil(bOutputStencil);
|
|
ReadDataFlags.SetMip(CustomMip);
|
|
|
|
FTextureRHIRef Texture = RenderTargetItem.TargetableTexture ? RenderTargetItem.TargetableTexture : RenderTargetItem.ShaderResourceTexture;
|
|
|
|
check(Texture);
|
|
|
|
TArray<FColor> Bitmap;
|
|
|
|
|
|
|
|
RHICmdList.ReadSurfaceData(Texture, FIntRect(0, 0, Extent.X, Extent.Y), Bitmap, ReadDataFlags);
|
|
|
|
// if the format and texture type is supported
|
|
if(Bitmap.Num())
|
|
{
|
|
// Create screenshot folder if not already present.
|
|
IFileManager::Get().MakeDirectory(*FPaths::ScreenShotDir(), true);
|
|
|
|
const FString ScreenFileName(FPaths::ScreenShotDir() / TEXT("VisualizeTexture"));
|
|
|
|
uint32 ExtendXWithMSAA = Bitmap.Num() / Extent.Y;
|
|
|
|
// Save the contents of the array to a bitmap file. (24bit only so alpha channel is dropped)
|
|
FFileHelper::CreateBitmap(*ScreenFileName, ExtendXWithMSAA, Extent.Y, Bitmap.GetData());
|
|
|
|
UE_LOG(LogConsoleResponse, Display, TEXT("Content was saved to \"%s\""), *FPaths::ScreenShotDir());
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogConsoleResponse, Error, TEXT("Failed to save BMP for VisualizeTexture, format or texture type is not supported"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void FVisualizeTexture::PresentContent(FRHICommandListImmediate& RHICmdList, const FViewInfo& View)
|
|
{
|
|
if(Mode != 0)
|
|
{
|
|
// old mode is used, lets copy the specified texture to do it similar to the new system
|
|
FPooledRenderTarget* Element = GRenderTargetPool.GetElementById(Mode - 1);
|
|
if(Element)
|
|
{
|
|
GenerateContent(RHICmdList, Element->GetRenderTargetItem(), Element->GetDesc());
|
|
}
|
|
}
|
|
|
|
const FTexture2DRHIRef& RenderTargetTexture = View.Family->RenderTarget->GetRenderTargetTexture();
|
|
|
|
if(!VisualizeTextureContent
|
|
|| !IsValidRef(RenderTargetTexture)
|
|
|| !bEnabled)
|
|
{
|
|
// visualize feature is deactivated
|
|
return;
|
|
}
|
|
|
|
FPooledRenderTargetDesc Desc = VisualizeTextureDesc;
|
|
|
|
auto& RenderTarget = View.Family->RenderTarget->GetRenderTargetTexture();
|
|
SetRenderTarget(RHICmdList, RenderTarget, FTextureRHIRef(), true);
|
|
RHICmdList.SetViewport(0, 0, 0.0f, RenderTarget->GetSizeX(), RenderTarget->GetSizeY(), 1.0f);
|
|
|
|
RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
auto ShaderMap = View.ShaderMap;
|
|
TShaderMapRef<FPostProcessVS> VertexShader(ShaderMap);
|
|
TShaderMapRef<FVisualizeTexturePresentPS> PixelShader(ShaderMap);
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetParameters(RHICmdList, View);
|
|
PixelShader->SetParameters(RHICmdList, View, *VisualizeTextureContent);
|
|
|
|
FIntRect DestRect = View.ViewRect;
|
|
|
|
FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent);
|
|
|
|
{
|
|
SCOPED_DRAW_EVENT(RHICmdList, VisCopyToMain);
|
|
// Draw a quad mapping scene color to the view's render target
|
|
DrawRectangle(
|
|
RHICmdList,
|
|
VisualizeTextureRect.Min.X, VisualizeTextureRect.Min.Y,
|
|
VisualizeTextureRect.Width(), VisualizeTextureRect.Height(),
|
|
0, 0,
|
|
VisualizeTextureRect.Width(), VisualizeTextureRect.Height(),
|
|
FIntPoint(RenderTarget->GetSizeX(), RenderTarget->GetSizeY()),
|
|
VisualizeTextureRect.Size(),
|
|
*VertexShader,
|
|
EDRF_Default);
|
|
}
|
|
|
|
FRenderTargetTemp TempRenderTarget(View, View.UnscaledViewRect.Size());
|
|
FCanvas Canvas(&TempRenderTarget, NULL, View.Family->CurrentRealTime, View.Family->CurrentWorldTime, View.Family->DeltaWorldTime, View.GetFeatureLevel());
|
|
|
|
float X = 100 + View.ViewRect.Min.X;
|
|
float Y = 160 + View.ViewRect.Min.Y;
|
|
float YStep = 14;
|
|
|
|
{
|
|
uint32 ReuseCount = ObservedDebugNameReusedCurrent;
|
|
|
|
FString ExtendedName;
|
|
if(ReuseCount)
|
|
{
|
|
uint32 ReuseGoal = FMath::Min(ReuseCount - 1, ObservedDebugNameReusedGoal);
|
|
|
|
// was reused this frame
|
|
ExtendedName = FString::Printf(TEXT("%s@%d @0..%d"), Desc.DebugName, ReuseGoal, ReuseCount - 1);
|
|
}
|
|
else
|
|
{
|
|
// was not reused this frame but can be referenced
|
|
ExtendedName = FString::Printf(TEXT("%s"), Desc.DebugName);
|
|
}
|
|
|
|
FString Channels = TEXT("RGB");
|
|
switch( SingleChannel )
|
|
{
|
|
case 0: Channels = TEXT("R"); break;
|
|
case 1: Channels = TEXT("G"); break;
|
|
case 2: Channels = TEXT("B"); break;
|
|
case 3: Channels = TEXT("A"); break;
|
|
}
|
|
float Multiplier = ( SingleChannel == -1 ) ? RGBMul : SingleChannelMul;
|
|
|
|
FString Line = FString::Printf(TEXT("VisualizeTexture: %d \"%s\" %s*%g UV%d"),
|
|
Mode,
|
|
*ExtendedName,
|
|
*Channels,
|
|
Multiplier,
|
|
UVInputMapping);
|
|
|
|
Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
|
|
}
|
|
{
|
|
FString Line = FString::Printf(TEXT(" TextureInfoString(): %s"), *(Desc.GenerateInfoString()));
|
|
Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
|
|
}
|
|
{
|
|
FString Line = FString::Printf(TEXT(" BufferSize:(%d,%d)"), FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY().X, FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY().Y);
|
|
Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
|
|
}
|
|
|
|
const FSceneViewFamily& ViewFamily = *View.Family;
|
|
|
|
for(int32 ViewId = 0; ViewId < ViewFamily.Views.Num(); ++ViewId)
|
|
{
|
|
const FSceneView& ViewIt = *ViewFamily.Views[ViewId];
|
|
FString Line = FString::Printf(TEXT(" View #%d: (%d,%d)-(%d,%d)"), ViewId + 1,
|
|
ViewIt.ViewRect.Min.X, ViewIt.ViewRect.Min.Y, ViewIt.ViewRect.Max.X, ViewIt.ViewRect.Max.Y);
|
|
Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
|
|
}
|
|
|
|
X += 40;
|
|
|
|
if(Desc.Flags & TexCreate_CPUReadback)
|
|
{
|
|
Canvas.DrawShadowedString( X, Y += YStep, TEXT("Content cannot be visualized on the GPU (TexCreate_CPUReadback)"), GetStatsFont(), FLinearColor(1,1,0));
|
|
}
|
|
else
|
|
{
|
|
Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Red: <0"), GetStatsFont(), FLinearColor(1,0,0));
|
|
Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Blue: NAN or Inf"), GetStatsFont(), FLinearColor(0,0,1));
|
|
|
|
// add explicit legend for SceneDepth and ShadowDepth as the display coloring is an artificial choice.
|
|
const bool bDepthTexture = (Desc.TargetableFlags & TexCreate_DepthStencilTargetable) != 0;
|
|
const bool bShadowDepth = (Desc.Format == PF_ShadowDepth);
|
|
if (bShadowDepth)
|
|
{
|
|
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Color Key: Linear with white near and teal distant"), GetStatsFont(), FLinearColor(54.f / 255.f, 117.f / 255.f, 136.f / 255.f));
|
|
}
|
|
else if (bDepthTexture)
|
|
{
|
|
Canvas.DrawShadowedString(X, Y += YStep, TEXT("Color Key: Nonlinear with white distant"), GetStatsFont(), FLinearColor(0.5, 0, 0));
|
|
}
|
|
}
|
|
|
|
Canvas.Flush_RenderThread(RHICmdList);
|
|
}
|
|
|
|
|
|
void FVisualizeTexture::SetObserveTarget(const FString& InObservedDebugName, uint32 InObservedDebugNameReusedGoal)
|
|
{
|
|
ObservedDebugName = InObservedDebugName;
|
|
ObservedDebugNameReusedGoal = InObservedDebugNameReusedGoal;
|
|
}
|
|
|
|
void FVisualizeTexture::SetCheckPoint(FRHICommandList& RHICmdList, const IPooledRenderTarget* PooledRenderTarget)
|
|
{
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
check(IsInRenderingThread());
|
|
if (!PooledRenderTarget || !bEnabled)
|
|
{
|
|
// Don't checkpoint on ES2 to avoid TMap alloc/reallocations
|
|
return;
|
|
}
|
|
|
|
const FSceneRenderTargetItem& RenderTargetItem = PooledRenderTarget->GetRenderTargetItem();
|
|
const FPooledRenderTargetDesc& Desc = PooledRenderTarget->GetDesc();
|
|
const TCHAR* DebugName = Desc.DebugName;
|
|
|
|
uint32* UsageCountPtr = VisualizeTextureCheckpoints.Find(DebugName);
|
|
|
|
if(!UsageCountPtr)
|
|
{
|
|
// create a new element with count 0
|
|
UsageCountPtr = &VisualizeTextureCheckpoints.Add(DebugName, 0);
|
|
}
|
|
|
|
// is this is the name we are observing with visualize texture?
|
|
// First check if we need to find anything to avoid string the comparison
|
|
if (!ObservedDebugName.IsEmpty() && ObservedDebugName == DebugName)
|
|
{
|
|
// if multiple times reused during the frame, is that the one we want to look at?
|
|
if(*UsageCountPtr == ObservedDebugNameReusedGoal || ObservedDebugNameReusedGoal == 0xffffffff)
|
|
{
|
|
FRHICommandListImmediate& RHICmdListIm = FRHICommandListExecutor::GetImmediateCommandList();
|
|
if (RHICmdListIm.IsExecuting())
|
|
{
|
|
UE_LOG(LogConsoleResponse, Fatal, TEXT("We can't create a checkpoint because that requires the immediate commandlist, which is currently executing. You might try disabling parallel rendering."));
|
|
}
|
|
else
|
|
{
|
|
if (&RHICmdList != &RHICmdListIm)
|
|
{
|
|
UE_LOG(LogConsoleResponse, Warning, TEXT("Attempt to checkpoint a render target from a non-immediate command list. We will flush it and hope that works. If it doesn't you might try disabling parallel rendering."));
|
|
RHICmdList.Flush();
|
|
}
|
|
GenerateContent(RHICmdListIm, RenderTargetItem, Desc);
|
|
if (&RHICmdList != &RHICmdListIm)
|
|
{
|
|
RHICmdListIm.Flush();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// only needed for VisualizeTexture (todo: optimize out when possible)
|
|
*UsageCountPtr = *UsageCountPtr + 1;
|
|
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
}
|
|
|
|
|
|
struct FSortedLines
|
|
{
|
|
FString Line;
|
|
int32 SortIndex;
|
|
uint32 PoolIndex;
|
|
|
|
FORCEINLINE bool operator<( const FSortedLines &B ) const
|
|
{
|
|
// first large ones
|
|
if(SortIndex < B.SortIndex)
|
|
{
|
|
return true;
|
|
}
|
|
if(SortIndex > B.SortIndex)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return Line < B.Line;
|
|
}
|
|
};
|
|
|
|
void FVisualizeTexture::DebugLog(bool bExtended)
|
|
{
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
{
|
|
TArray<FSortedLines> SortedLines;
|
|
|
|
for(uint32 i = 0, Num = GRenderTargetPool.GetElementCount(); i < Num; ++i)
|
|
{
|
|
FPooledRenderTarget* RT = GRenderTargetPool.GetElementById(i);
|
|
|
|
if(!RT)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
FPooledRenderTargetDesc Desc = RT->GetDesc();
|
|
|
|
if(bFullList || (Desc.Flags & TexCreate_HideInVisualizeTexture) == 0)
|
|
{
|
|
uint32 SizeInKB = (RT->ComputeMemorySize() + 1023) / 1024;
|
|
|
|
FString UnusedStr;
|
|
|
|
if(RT->GetUnusedForNFrames() > 0)
|
|
{
|
|
if(!bFullList)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
UnusedStr = FString::Printf(TEXT(" unused(%d)"), RT->GetUnusedForNFrames());
|
|
}
|
|
|
|
FSortedLines Element;
|
|
|
|
Element.PoolIndex = i;
|
|
|
|
// sort by index
|
|
Element.SortIndex = i;
|
|
|
|
FString InfoString = Desc.GenerateInfoString();
|
|
if(SortOrder == -1)
|
|
{
|
|
// constant works well with the average name length
|
|
const uint32 TotelSpacerSize = 36;
|
|
uint32 SpaceCount = FMath::Max<int32>(0, TotelSpacerSize - InfoString.Len());
|
|
|
|
for(uint32 Space = 0; Space < SpaceCount; ++Space)
|
|
{
|
|
InfoString.AppendChar((TCHAR)' ');
|
|
}
|
|
|
|
// sort by index
|
|
Element.Line = FString::Printf(TEXT("%s %s %d KB%s"), *InfoString, Desc.DebugName, SizeInKB, *UnusedStr);
|
|
}
|
|
else if(SortOrder == 0)
|
|
{
|
|
// sort by name
|
|
Element.Line = FString::Printf(TEXT("%s %s %d KB%s"), Desc.DebugName, *InfoString, SizeInKB, *UnusedStr);
|
|
Element.SortIndex = 0;
|
|
}
|
|
else if(SortOrder == 1)
|
|
{
|
|
// sort by size (large ones first)
|
|
Element.Line = FString::Printf(TEXT("%d KB %s %s%s"), SizeInKB, *InfoString, Desc.DebugName, *UnusedStr);
|
|
Element.SortIndex = -(int32)SizeInKB;
|
|
}
|
|
else
|
|
{
|
|
check(0);
|
|
}
|
|
|
|
if(Desc.Flags & TexCreate_FastVRAM)
|
|
{
|
|
FRHIResourceInfo Info;
|
|
|
|
FTextureRHIRef Texture = RT->GetRenderTargetItem().ShaderResourceTexture;
|
|
|
|
if(!IsValidRef(Texture))
|
|
{
|
|
Texture = RT->GetRenderTargetItem().TargetableTexture;
|
|
}
|
|
|
|
if(IsValidRef(Texture))
|
|
{
|
|
RHIGetResourceInfo(Texture, Info);
|
|
}
|
|
|
|
if(Info.VRamAllocation.AllocationSize)
|
|
{
|
|
// note we do KB for more readable numbers but this can cause quantization loss
|
|
Element.Line += FString::Printf(TEXT(" VRamInKB(Start/Size):%d/%d"),
|
|
Info.VRamAllocation.AllocationStart / 1024,
|
|
(Info.VRamAllocation.AllocationSize + 1023) / 1024);
|
|
}
|
|
else
|
|
{
|
|
Element.Line += TEXT(" VRamInKB(Start/Size):<NONE>");
|
|
}
|
|
}
|
|
|
|
SortedLines.Add(Element);
|
|
}
|
|
}
|
|
|
|
SortedLines.Sort();
|
|
|
|
{
|
|
for(int32 Index = 0; Index < SortedLines.Num(); Index++)
|
|
{
|
|
const FSortedLines& Entry = SortedLines[Index];
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(" %3d = %s"), Entry.PoolIndex + 1, *Entry.Line);
|
|
}
|
|
}
|
|
|
|
// clean flags for next use
|
|
bFullList = false;
|
|
SortOrder = -1;
|
|
}
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(""));
|
|
|
|
// log names (alternative method to look at the rendertargets)
|
|
if(bExtended)
|
|
{
|
|
UE_LOG(LogConsoleResponse, Log, TEXT("CheckpointName (what was rendered this frame, use <Name>@<Number> to get intermediate versions):"));
|
|
|
|
TArray<FString> Entries;
|
|
|
|
// sorted by pointer for efficiency, now we want to print sorted alphabetically
|
|
for (TMap<const TCHAR*, uint32>:: TIterator It(GRenderTargetPool.VisualizeTexture.VisualizeTextureCheckpoints); It; ++It)
|
|
{
|
|
const TCHAR* Key = It.Key();
|
|
uint32 Value = It.Value();
|
|
|
|
/* if(Value)
|
|
{
|
|
// was reused this frame
|
|
Entries.Add(FString::Printf(TEXT("%s @0..%d"), *Key.GetPlainNameString(), Value - 1));
|
|
}
|
|
else
|
|
*/ {
|
|
// was not reused this frame but can be referenced
|
|
Entries.Add(Key);
|
|
}
|
|
}
|
|
|
|
Entries.Sort();
|
|
|
|
// that number works well with the name length we have
|
|
const uint32 ColumnCount = 5;
|
|
const uint32 SpaceBetweenColumns = 1;
|
|
uint32 ColumnHeight = FMath::DivideAndRoundUp((uint32)Entries.Num(), ColumnCount);
|
|
|
|
// width of the column in characters, init with 0
|
|
uint32 ColumnWidths[ColumnCount] = {};
|
|
|
|
for(int32 Index = 0; Index < Entries.Num(); ++Index)
|
|
{
|
|
uint32 Column = Index / ColumnHeight;
|
|
|
|
const FString& Entry = *Entries[Index];
|
|
|
|
ColumnWidths[Column] = FMath::Max(ColumnWidths[Column], (uint32)Entry.Len());
|
|
}
|
|
|
|
// print them sorted, if possible multiple in a line
|
|
{
|
|
FString Line;
|
|
|
|
for(int32 OutputIndex = 0; OutputIndex < Entries.Num(); ++OutputIndex)
|
|
{
|
|
// 0..ColumnCount-1
|
|
uint32 Column = OutputIndex % ColumnCount;
|
|
int32 Row = OutputIndex / ColumnCount;
|
|
|
|
uint32 Index = Row + Column * ColumnHeight;
|
|
|
|
bool bLineEnd = true;
|
|
|
|
if(Index < (uint32)Entries.Num())
|
|
{
|
|
bLineEnd = (Column + 1 == ColumnCount);
|
|
|
|
// for human readability we order them to be per column
|
|
const FString& Entry = *Entries[Index];
|
|
|
|
Line += Entry;
|
|
|
|
int32 SpaceCount = ColumnWidths[Column] + SpaceBetweenColumns - Entry.Len();
|
|
|
|
// otehrwise a fomer pass was producing bad data
|
|
check(SpaceCount >= 0);
|
|
|
|
for(int32 Space = 0; Space < SpaceCount; ++Space)
|
|
{
|
|
Line.AppendChar((TCHAR)' ');
|
|
}
|
|
}
|
|
|
|
if(bLineEnd)
|
|
{
|
|
Line = Line.TrimTrailing();
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(" %s"), *Line);
|
|
Line.Empty();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
uint32 WholeCount;
|
|
uint32 WholePoolInKB;
|
|
uint32 UsedInKB;
|
|
|
|
GRenderTargetPool.GetStats(WholeCount, WholePoolInKB, UsedInKB);
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT("Pool: %d/%d MB (referenced/allocated)"), (UsedInKB + 1023) / 1024, (WholePoolInKB + 1023) / 1024);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// @return 0 if not found
|
|
IPooledRenderTarget* FVisualizeTexture::GetObservedElement() const
|
|
{
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
IPooledRenderTarget* RT = VisualizeTextureContent.GetReference();
|
|
|
|
if(!RT && Mode >= 0)
|
|
{
|
|
uint32 Id = Mode - 1;
|
|
|
|
RT = GRenderTargetPool.GetElementById(Id);
|
|
}
|
|
|
|
return RT;
|
|
#else
|
|
return 0;
|
|
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
}
|
|
|
|
void FVisualizeTexture::OnStartFrame(const FSceneView& View)
|
|
{
|
|
FeatureLevel = View.GetFeatureLevel();
|
|
bEnabled = true;
|
|
ViewRect = View.UnscaledViewRect;
|
|
AspectRatioConstrainedViewRect = View.Family->EngineShowFlags.CameraAspectRatioBars ? View.CameraConstrainedViewRect : ViewRect;
|
|
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
// VisualizeTexture observed render target is set each frame
|
|
VisualizeTextureContent.SafeRelease();
|
|
VisualizeTextureDesc = FPooledRenderTargetDesc();
|
|
VisualizeTextureDesc.DebugName = TEXT("VisualizeTexture");
|
|
|
|
ObservedDebugNameReusedCurrent = 0;
|
|
|
|
// only needed for VisualizeTexture (todo: optimize out when possible)
|
|
{
|
|
for (TMap<const TCHAR*, uint32>:: TIterator It(VisualizeTextureCheckpoints); It; ++It)
|
|
{
|
|
uint32& Value = It.Value();
|
|
|
|
// 0 as it was not used this frame yet
|
|
Value = 0;
|
|
}
|
|
}
|
|
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
|
}
|
|
|
|
void FVisualizeTexture::QueryInfo( FQueryVisualizeTexureInfo& Out )
|
|
{
|
|
for(uint32 i = 0, Num = GRenderTargetPool.GetElementCount(); i < Num; ++i)
|
|
{
|
|
FPooledRenderTarget* RT = GRenderTargetPool.GetElementById(i);
|
|
|
|
if(!RT)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
FPooledRenderTargetDesc Desc = RT->GetDesc();
|
|
uint32 SizeInKB = (RT->ComputeMemorySize() + 1023) / 1024;
|
|
FString Entry = FString::Printf(TEXT("%s %d %s %d"),
|
|
*Desc.GenerateInfoString(),
|
|
i + 1,
|
|
Desc.DebugName ? Desc.DebugName : TEXT("<Unnamed>"),
|
|
SizeInKB);
|
|
Out.Entries.Add(Entry);
|
|
}
|
|
}
|