2019-12-26 14:45:42 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2018-11-21 20:22:47 -05:00
|
|
|
|
|
|
|
|
#include "VisualizeTexture.h"
|
2023-01-27 14:54:10 -05:00
|
|
|
#include "Misc/App.h"
|
2018-11-21 20:22:47 -05:00
|
|
|
#include "ShaderParameters.h"
|
2023-01-27 14:54:10 -05:00
|
|
|
#include "Misc/WildcardString.h"
|
2018-11-21 20:22:47 -05:00
|
|
|
#include "RHIStaticStates.h"
|
2023-01-27 14:54:10 -05:00
|
|
|
#include "RenderingThread.h"
|
2018-11-21 20:22:47 -05:00
|
|
|
#include "Shader.h"
|
|
|
|
|
#include "RenderTargetPool.h"
|
|
|
|
|
#include "GlobalShader.h"
|
|
|
|
|
#include "PipelineStateCache.h"
|
|
|
|
|
#include "PixelShaderUtils.h"
|
2020-09-24 00:43:27 -04:00
|
|
|
#include "Misc/FileHelper.h"
|
2022-11-30 18:29:09 -05:00
|
|
|
#include "RenderCore.h"
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
void FVisualizeTexture::ParseCommands(const TCHAR* Cmd, FOutputDevice &Ar)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
#if SUPPORTS_VISUALIZE_TEXTURE
|
2021-01-29 06:51:36 -04:00
|
|
|
// Find out what command to do based on first parameter.
|
|
|
|
|
ECommand Command = ECommand::Unknown;
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
int32 ViewId = 0;
|
2024-03-13 12:03:29 -04:00
|
|
|
FString ViewName;
|
2021-01-29 06:51:36 -04:00
|
|
|
FString ResourceName;
|
|
|
|
|
TOptional<uint32> ResourceVersion;
|
|
|
|
|
TOptional<FWildcardString> ResourceListWildCard;
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
FString FirstParameter = FParse::Token(Cmd, 0);
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2020-09-25 18:53:39 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
if (FirstParameter.IsEmpty())
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
// NOP
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
2021-01-29 06:51:36 -04:00
|
|
|
else if (FChar::IsDigit(**FirstParameter))
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
Command = ECommand::DisableVisualization;
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
2021-01-29 06:51:36 -04:00
|
|
|
else if (FirstParameter == TEXT("help"))
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
Command = ECommand::DisplayHelp;
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
2021-01-29 06:51:36 -04:00
|
|
|
else if (FirstParameter == TEXT("pool"))
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
Command = ECommand::DisplayPoolResourceList;
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
else if (FirstParameter.StartsWith(TEXT("view=")))
|
|
|
|
|
{
|
|
|
|
|
if (FirstParameter.Len() == 5)
|
|
|
|
|
{
|
|
|
|
|
// Empty payload, reset view ID to zero
|
|
|
|
|
Command = ECommand::SetViewId;
|
|
|
|
|
ViewId = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (FirstParameter[5] == TEXT('?'))
|
|
|
|
|
{
|
|
|
|
|
Command = ECommand::DisplayViewList;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Command = ECommand::SetViewId;
|
2024-03-13 12:03:29 -04:00
|
|
|
|
|
|
|
|
// Supports view ID or string name of view
|
|
|
|
|
TCHAR* EndOfNumber;
|
|
|
|
|
ViewId = FCString::Strtoi(&FirstParameter[5], &EndOfNumber, 0);
|
|
|
|
|
if (EndOfNumber - &FirstParameter[0] != FirstParameter.Len())
|
|
|
|
|
{
|
|
|
|
|
// Didn't parse as a number, treat it as a string
|
|
|
|
|
ViewId = 0;
|
|
|
|
|
ViewName = FirstParameter.Right(FirstParameter.Len() - 5);
|
|
|
|
|
}
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
else
|
|
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
const TCHAR* AfterAt = *FirstParameter;
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
while (*AfterAt != 0 && *AfterAt != TCHAR('@'))
|
|
|
|
|
{
|
|
|
|
|
++AfterAt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*AfterAt == TCHAR('@'))
|
|
|
|
|
{
|
|
|
|
|
ResourceName = FirstParameter.Left(AfterAt - *FirstParameter);
|
|
|
|
|
ResourceVersion = FCString::Atoi(AfterAt + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ResourceName = FirstParameter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ResourceName.Contains(TEXT("*")))
|
|
|
|
|
{
|
|
|
|
|
ResourceListWildCard = FWildcardString(ResourceName);
|
|
|
|
|
Command = ECommand::DisplayResourceList;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Command = ECommand::VisualizeResource;
|
|
|
|
|
Visualize(ResourceName, ResourceVersion);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
|
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
if (Command == ECommand::Unknown)
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
FVisualizeTexture::DisplayHelp(Ar);
|
|
|
|
|
DisplayResourceListToLog(TOptional<FWildcardString>());
|
|
|
|
|
}
|
|
|
|
|
else if (Command == ECommand::DisplayHelp)
|
|
|
|
|
{
|
|
|
|
|
FVisualizeTexture::DisplayHelp(Ar);
|
|
|
|
|
}
|
|
|
|
|
else if (Command == ECommand::DisableVisualization)
|
|
|
|
|
{
|
|
|
|
|
Visualize({});
|
|
|
|
|
}
|
|
|
|
|
else if (Command == ECommand::VisualizeResource)
|
|
|
|
|
{
|
|
|
|
|
Config = {};
|
|
|
|
|
Visualize(ResourceName, ResourceVersion);
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
FString Parameter = FParse::Token(Cmd, 0);
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
if (Parameter.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("uv0"))
|
|
|
|
|
{
|
|
|
|
|
Config.InputUVMapping = EInputUVMapping::LeftTop;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("uv1"))
|
|
|
|
|
{
|
|
|
|
|
Config.InputUVMapping = EInputUVMapping::Whole;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("uv2"))
|
|
|
|
|
{
|
|
|
|
|
Config.InputUVMapping = EInputUVMapping::PixelPerfectCenter;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("pip"))
|
|
|
|
|
{
|
|
|
|
|
Config.InputUVMapping = EInputUVMapping::PictureInPicture;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("bmp"))
|
|
|
|
|
{
|
|
|
|
|
Config.Flags |= EFlags::SaveBitmap;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("stencil"))
|
|
|
|
|
{
|
|
|
|
|
Config.Flags |= EFlags::SaveBitmapAsStencil;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("frac"))
|
|
|
|
|
{
|
|
|
|
|
Config.ShaderOp = EShaderOp::Frac;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("sat"))
|
|
|
|
|
{
|
|
|
|
|
Config.ShaderOp = EShaderOp::Saturate;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter.Left(3) == TEXT("mip"))
|
|
|
|
|
{
|
2024-01-19 16:41:35 -05:00
|
|
|
Parameter.RightInline(Parameter.Len() - 3, EAllowShrinking::No);
|
2021-01-29 06:51:36 -04:00
|
|
|
Config.MipIndex = FCString::Atoi(*Parameter);
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter.Left(5) == TEXT("index"))
|
|
|
|
|
{
|
2024-01-19 16:41:35 -05:00
|
|
|
Parameter.RightInline(Parameter.Len() - 5, EAllowShrinking::No);
|
2021-01-29 06:51:36 -04:00
|
|
|
Config.ArrayIndex = FCString::Atoi(*Parameter);
|
|
|
|
|
}
|
|
|
|
|
// e.g. RGB*6, A, *22, /2.7, A*7
|
|
|
|
|
else if (Parameter.Left(3) == TEXT("rgb")
|
|
|
|
|
|| Parameter.Left(1) == TEXT("a")
|
|
|
|
|
|| Parameter.Left(1) == TEXT("r")
|
|
|
|
|
|| Parameter.Left(1) == TEXT("g")
|
|
|
|
|
|| Parameter.Left(1) == TEXT("b")
|
|
|
|
|
|| Parameter.Left(1) == TEXT("*")
|
|
|
|
|
|| Parameter.Left(1) == TEXT("/"))
|
|
|
|
|
{
|
|
|
|
|
Config.SingleChannel = -1;
|
|
|
|
|
|
|
|
|
|
if (Parameter.Left(3) == TEXT("rgb"))
|
|
|
|
|
{
|
2024-01-19 16:41:35 -05:00
|
|
|
Parameter.RightInline(Parameter.Len() - 3, EAllowShrinking::No);
|
2021-01-29 06:51:36 -04:00
|
|
|
}
|
|
|
|
|
else if (Parameter.Left(1) == TEXT("r")) Config.SingleChannel = 0;
|
|
|
|
|
else if (Parameter.Left(1) == TEXT("g")) Config.SingleChannel = 1;
|
|
|
|
|
else if (Parameter.Left(1) == TEXT("b")) Config.SingleChannel = 2;
|
|
|
|
|
else if (Parameter.Left(1) == TEXT("a")) Config.SingleChannel = 3;
|
|
|
|
|
if (Config.SingleChannel >= 0)
|
|
|
|
|
{
|
2024-01-19 16:41:35 -05:00
|
|
|
Parameter.RightInline(Parameter.Len() - 1, EAllowShrinking::No);
|
2021-01-29 06:51:36 -04:00
|
|
|
Config.SingleChannelMul = 1.0f;
|
|
|
|
|
Config.RGBMul = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Mul = 1.0f;
|
|
|
|
|
|
|
|
|
|
// * or /
|
|
|
|
|
if (Parameter.Left(1) == TEXT("*"))
|
|
|
|
|
{
|
2024-01-19 16:41:35 -05:00
|
|
|
Parameter.RightInline(Parameter.Len() - 1, EAllowShrinking::No);
|
2021-01-29 06:51:36 -04:00
|
|
|
Mul = FCString::Atof(*Parameter);
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter.Left(1) == TEXT("/"))
|
|
|
|
|
{
|
2024-01-19 16:41:35 -05:00
|
|
|
Parameter.RightInline(Parameter.Len() - 1, EAllowShrinking::No);
|
2021-01-29 06:51:36 -04:00
|
|
|
Mul = 1.0f / FCString::Atof(*Parameter);
|
|
|
|
|
}
|
|
|
|
|
Config.RGBMul *= Mul;
|
|
|
|
|
Config.SingleChannelMul *= Mul;
|
|
|
|
|
Config.AMul *= Mul;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Ar.Logf(TEXT("Error: parameter \"%s\" not recognized"), *Parameter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (Command == ECommand::DisplayPoolResourceList)
|
|
|
|
|
{
|
|
|
|
|
ESortBy SortBy = ESortBy::Index;
|
|
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
FString Parameter = FParse::Token(Cmd, 0);
|
|
|
|
|
|
|
|
|
|
if (Parameter.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("byname"))
|
|
|
|
|
{
|
|
|
|
|
SortBy = ESortBy::Name;
|
|
|
|
|
}
|
|
|
|
|
else if (Parameter == TEXT("bysize"))
|
|
|
|
|
{
|
|
|
|
|
SortBy = ESortBy::Size;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Ar.Logf(TEXT("Error: parameter \"%s\" not recognized"), *Parameter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DisplayPoolResourceListToLog(SortBy);
|
|
|
|
|
}
|
2024-02-03 20:57:53 -05:00
|
|
|
else if (Command == ECommand::DisplayResourceList)
|
2021-01-29 06:51:36 -04:00
|
|
|
{
|
|
|
|
|
bool bListAllocated = false;
|
|
|
|
|
ESortBy SortBy = ESortBy::Index;
|
|
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
FString Parameter = FParse::Token(Cmd, 0);
|
|
|
|
|
|
|
|
|
|
if (Parameter.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Ar.Logf(TEXT("Error: parameter \"%s\" not recognized"), *Parameter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DisplayResourceListToLog(ResourceListWildCard);
|
|
|
|
|
}
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
else if (Command == ECommand::DisplayViewList)
|
|
|
|
|
{
|
|
|
|
|
DisplayViewListToLog();
|
|
|
|
|
}
|
2024-02-03 20:57:53 -05:00
|
|
|
else if (Command == ECommand::SetViewId) //-V547
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
{
|
|
|
|
|
Requested.ViewUniqueId = ViewId;
|
2024-03-13 12:03:29 -04:00
|
|
|
Requested.ViewName = ViewName;
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
}
|
2021-01-29 06:51:36 -04:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unimplemented();
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
|
|
|
|
|
// Enable tracking when the system is first interacted with
|
|
|
|
|
if (State == EState::Inactive)
|
|
|
|
|
{
|
|
|
|
|
State = EState::TrackResources;
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
#endif
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
void FVisualizeTexture::DebugLogOnCrash()
|
|
|
|
|
{
|
|
|
|
|
#if SUPPORTS_VISUALIZE_TEXTURE
|
2021-01-29 06:51:36 -04:00
|
|
|
DisplayPoolResourceListToLog(ESortBy::Size);
|
|
|
|
|
DisplayResourceListToLog(TOptional<FWildcardString>());
|
2020-09-24 00:43:27 -04:00
|
|
|
#endif
|
|
|
|
|
}
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
void FVisualizeTexture::GetTextureInfos_GameThread(TArray<FString>& Infos) const
|
|
|
|
|
{
|
|
|
|
|
check(IsInGameThread());
|
|
|
|
|
FlushRenderingCommands();
|
|
|
|
|
|
|
|
|
|
for (uint32 Index = 0, Num = GRenderTargetPool.GetElementCount(); Index < Num; ++Index)
|
|
|
|
|
{
|
|
|
|
|
FPooledRenderTarget* RenderTarget = GRenderTargetPool.GetElementById(Index);
|
|
|
|
|
|
|
|
|
|
if (!RenderTarget)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FPooledRenderTargetDesc Desc = RenderTarget->GetDesc();
|
|
|
|
|
uint32 SizeInKB = (RenderTarget->ComputeMemorySize() + 1023) / 1024;
|
|
|
|
|
FString Entry = FString::Printf(TEXT("%s %d %s %d"),
|
|
|
|
|
*Desc.GenerateInfoString(),
|
|
|
|
|
Index + 1,
|
|
|
|
|
Desc.DebugName ? Desc.DebugName : TEXT("<Unnamed>"),
|
|
|
|
|
SizeInKB);
|
|
|
|
|
Infos.Add(Entry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TGlobalResource<FVisualizeTexture> GVisualizeTexture;
|
|
|
|
|
|
|
|
|
|
#if SUPPORTS_VISUALIZE_TEXTURE
|
|
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
void FVisualizeTexture::DisplayHelp(FOutputDevice &Ar)
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
Ar.Logf(TEXT("VisualizeTexture/Vis <RDGResourceNameWildcard>:"));
|
|
|
|
|
Ar.Logf(TEXT(" Lists all RDG resource names with wildcard filtering."));
|
|
|
|
|
Ar.Logf(TEXT(""));
|
|
|
|
|
Ar.Logf(TEXT("VisualizeTexture/Vis <RDGResourceName>[@<Version>] [<Mode>] [PIP/UV0/UV1/UV2] [BMP] [FRAC/SAT] [FULL]:"));
|
|
|
|
|
Ar.Logf(TEXT(" RDGResourceName = Name of the resource set when creating it with RDG."));
|
|
|
|
|
Ar.Logf(TEXT(" Version = Integer to specify a specific intermediate version."));
|
|
|
|
|
Ar.Logf(TEXT(" Mode (examples):"));
|
|
|
|
|
Ar.Logf(TEXT(" RGB = RGB in range 0..1 (default)"));
|
|
|
|
|
Ar.Logf(TEXT(" *8 = RGB * 8"));
|
|
|
|
|
Ar.Logf(TEXT(" A = alpha channel in range 0..1"));
|
|
|
|
|
Ar.Logf(TEXT(" R = red channel in range 0..1"));
|
|
|
|
|
Ar.Logf(TEXT(" G = green channel in range 0..1"));
|
|
|
|
|
Ar.Logf(TEXT(" B = blue channel in range 0..1"));
|
|
|
|
|
Ar.Logf(TEXT(" A*16 = Alpha * 16"));
|
|
|
|
|
Ar.Logf(TEXT(" RGB/2 = RGB / 2"));
|
|
|
|
|
Ar.Logf(TEXT(" SubResource:"));
|
|
|
|
|
Ar.Logf(TEXT(" MIP5 = Mip level 5 (0 is default)"));
|
|
|
|
|
Ar.Logf(TEXT(" INDEX5 = Array Element 5 (0 is default)"));
|
|
|
|
|
Ar.Logf(TEXT(" InputMapping:"));
|
|
|
|
|
Ar.Logf(TEXT(" PIP = like UV1 but as picture in picture with normal rendering (default)"));
|
|
|
|
|
Ar.Logf(TEXT(" UV0 = UV in left top"));
|
|
|
|
|
Ar.Logf(TEXT(" UV1 = full texture"));
|
|
|
|
|
Ar.Logf(TEXT(" UV2 = pixel perfect centered"));
|
|
|
|
|
Ar.Logf(TEXT(" Flags:"));
|
|
|
|
|
Ar.Logf(TEXT(" BMP = save out bitmap to the screenshots folder (not on console, normalized)"));
|
|
|
|
|
Ar.Logf(TEXT(" STENCIL = Stencil normally displayed in alpha channel of depth. This option is used for BMP to get a stencil only BMP."));
|
|
|
|
|
Ar.Logf(TEXT(" FRAC = use frac() in shader (default)"));
|
|
|
|
|
Ar.Logf(TEXT(" SAT = use saturate() in shader"));
|
|
|
|
|
Ar.Logf(TEXT(""));
|
|
|
|
|
Ar.Logf(TEXT("VisualizeTexture/Vis 0"));
|
|
|
|
|
Ar.Logf(TEXT(" Stops visualizing a resource."));
|
|
|
|
|
Ar.Logf(TEXT(""));
|
|
|
|
|
Ar.Logf(TEXT("VisualizeTexture/Vis pool [BYNAME/BYSIZE]:"));
|
|
|
|
|
Ar.Logf(TEXT(" Shows list of all resources in the pool."));
|
|
|
|
|
Ar.Logf(TEXT(" BYNAME = sort pool list by name"));
|
|
|
|
|
Ar.Logf(TEXT(" BYSIZE = show pool list by size"));
|
|
|
|
|
Ar.Logf(TEXT(""));
|
2024-03-13 12:03:29 -04:00
|
|
|
Ar.Logf(TEXT("VisualizeTexture/Vis view=[ID/NAME]"));
|
|
|
|
|
Ar.Logf(TEXT(" Unique ID or name of view to visualize textures from, \"view=?\" to dump list of available views"));
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
Ar.Logf(TEXT(""));
|
2021-01-29 06:51:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FVisualizeTexture::DisplayPoolResourceListToLog(FVisualizeTexture::ESortBy SortBy)
|
|
|
|
|
{
|
|
|
|
|
struct FSortedLines
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
FString Line;
|
|
|
|
|
int32 SortIndex = 0;
|
|
|
|
|
uint32 PoolIndex = 0;
|
|
|
|
|
|
|
|
|
|
bool operator < (const FSortedLines& B) const
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
// first large ones
|
|
|
|
|
if (SortIndex < B.SortIndex)
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
return true;
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
2021-01-29 06:51:36 -04:00
|
|
|
if (SortIndex > B.SortIndex)
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
return false;
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
|
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
return Line < B.Line;
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
TArray<FSortedLines> SortedLines;
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
for (uint32 Index = 0, Num = GRenderTargetPool.GetElementCount(); Index < Num; ++Index)
|
|
|
|
|
{
|
|
|
|
|
FPooledRenderTarget* RenderTarget = GRenderTargetPool.GetElementById(Index);
|
|
|
|
|
|
|
|
|
|
if (!RenderTarget)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FPooledRenderTargetDesc Desc = RenderTarget->GetDesc();
|
|
|
|
|
|
|
|
|
|
const uint32 SizeInKB = (RenderTarget->ComputeMemorySize() + 1023) / 1024;
|
|
|
|
|
|
|
|
|
|
FString UnusedStr;
|
|
|
|
|
|
|
|
|
|
if (RenderTarget->GetUnusedForNFrames() > 0)
|
|
|
|
|
{
|
|
|
|
|
UnusedStr = FString::Printf(TEXT(" unused(%d)"), RenderTarget->GetUnusedForNFrames());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FSortedLines Element;
|
|
|
|
|
Element.PoolIndex = Index;
|
|
|
|
|
Element.SortIndex = Index;
|
|
|
|
|
|
|
|
|
|
FString InfoString = Desc.GenerateInfoString();
|
|
|
|
|
|
|
|
|
|
switch (SortBy)
|
|
|
|
|
{
|
|
|
|
|
case ESortBy::Index:
|
|
|
|
|
{
|
|
|
|
|
// Constant works well with the average name length
|
|
|
|
|
const uint32 TotalSpacerSize = 36;
|
|
|
|
|
const uint32 SpaceCount = FMath::Max<int32>(0, TotalSpacerSize - InfoString.Len());
|
|
|
|
|
|
|
|
|
|
for (uint32 Space = 0; Space < SpaceCount; ++Space)
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
2021-01-29 06:51:36 -04:00
|
|
|
InfoString.AppendChar((TCHAR)' ');
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
// Sort by index
|
|
|
|
|
Element.Line = FString::Printf(TEXT("%s %s %d KB%s"), *InfoString, Desc.DebugName, SizeInKB, *UnusedStr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
case ESortBy::Name:
|
|
|
|
|
{
|
|
|
|
|
Element.Line = FString::Printf(TEXT("%s %s %d KB%s"), Desc.DebugName, *InfoString, SizeInKB, *UnusedStr);
|
|
|
|
|
Element.SortIndex = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
case ESortBy::Size:
|
|
|
|
|
{
|
|
|
|
|
Element.Line = FString::Printf(TEXT("%d KB %s %s%s"), SizeInKB, *InfoString, Desc.DebugName, *UnusedStr);
|
|
|
|
|
Element.SortIndex = -(int32)SizeInKB;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
default:
|
|
|
|
|
checkNoEntry();
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
SortedLines.Add(Element);
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
SortedLines.Sort();
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
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);
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(""));
|
|
|
|
|
|
|
|
|
|
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);
|
2021-01-29 06:51:36 -04:00
|
|
|
|
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FVisualizeTexture::DisplayResourceListToLog(const TOptional<FWildcardString>& Wildcard)
|
|
|
|
|
{
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
if (!IsActive())
|
|
|
|
|
{
|
|
|
|
|
State = EState::DisplayResources;
|
|
|
|
|
DisplayResourcesParam = Wildcard;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-29 06:51:36 -04:00
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT("RDGResourceName (what was rendered this frame, use <RDGResourceName>@<Version> to get intermediate versions):"));
|
|
|
|
|
|
|
|
|
|
TArray<FString> Entries;
|
|
|
|
|
Entries.Reserve(VersionCountMap.Num());
|
|
|
|
|
for (auto KV : VersionCountMap)
|
|
|
|
|
{
|
|
|
|
|
if (Wildcard.IsSet())
|
|
|
|
|
{
|
|
|
|
|
if (Wildcard->IsMatch(KV.Key))
|
|
|
|
|
{
|
|
|
|
|
Entries.Add(KV.Key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Entries.Add(KV.Key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Entries.Sort();
|
|
|
|
|
|
|
|
|
|
// Magic number works well with the name length we have
|
|
|
|
|
const int32 MaxColumnCount = 5;
|
|
|
|
|
const int32 SpaceBetweenColumns = 1;
|
|
|
|
|
const int32 TargetColumnHeight = 8;
|
|
|
|
|
|
|
|
|
|
int32 ColumnCount = FMath::Clamp(FMath::DivideAndRoundUp(Entries.Num(), TargetColumnHeight), 1, MaxColumnCount);
|
|
|
|
|
int32 ColumnHeight = FMath::DivideAndRoundUp(Entries.Num(), ColumnCount);
|
|
|
|
|
|
|
|
|
|
// Width of the column in characters, init with 0
|
|
|
|
|
TStaticArray<int32, MaxColumnCount> ColumnWidths;
|
|
|
|
|
for (int32 ColumnId = 0; ColumnId < MaxColumnCount; ColumnId++)
|
|
|
|
|
{
|
|
|
|
|
ColumnWidths[ColumnId] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 Index = 0, Count = Entries.Num(); Index < Count; ++Index)
|
|
|
|
|
{
|
|
|
|
|
const FString& Entry = *Entries[Index];
|
|
|
|
|
const int32 Column = Index / ColumnHeight;
|
|
|
|
|
ColumnWidths[Column] = FMath::Max(ColumnWidths[Column], Entry.Len());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print them sorted, if possible multiple in a line
|
|
|
|
|
for (int32 RowId = 0; RowId < ColumnHeight; RowId++)
|
|
|
|
|
{
|
|
|
|
|
FString Line;
|
|
|
|
|
int32 ColumnAlignment = 0;
|
|
|
|
|
|
|
|
|
|
for (int32 ColumnId = 0; ColumnId < ColumnCount; ColumnId++)
|
|
|
|
|
{
|
|
|
|
|
int32 EntryId = ColumnId * ColumnHeight + RowId;
|
|
|
|
|
|
|
|
|
|
if (EntryId >= Entries.Num())
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FString& Entry = *Entries[EntryId];
|
|
|
|
|
|
|
|
|
|
const int32 SpaceCount = ColumnAlignment - Line.Len();
|
|
|
|
|
check(SpaceCount >= 0);
|
|
|
|
|
for (int32 Space = 0; Space < SpaceCount; ++Space)
|
|
|
|
|
{
|
|
|
|
|
Line.AppendChar((TCHAR)' ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Line += Entry;
|
|
|
|
|
|
|
|
|
|
ColumnAlignment += SpaceBetweenColumns + ColumnWidths[ColumnId];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(" %s"), *Line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(""));
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
|
|
|
|
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
void FVisualizeTexture::DisplayViewListToLog()
|
|
|
|
|
{
|
|
|
|
|
if (!IsActive())
|
|
|
|
|
{
|
|
|
|
|
State = EState::DisplayViews;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Display view list sorted by unique ID
|
|
|
|
|
TArray<FSetElementId> Entries;
|
|
|
|
|
Entries.Reserve(ViewDescriptionMap.Num());
|
|
|
|
|
for (auto ViewIt = ViewDescriptionMap.CreateConstIterator(); ViewIt; ++ViewIt)
|
|
|
|
|
{
|
|
|
|
|
Entries.Add(ViewIt.GetId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Entries.Sort([ViewDescriptionMap = ViewDescriptionMap](const FSetElementId& A, const FSetElementId& B)
|
|
|
|
|
{
|
|
|
|
|
return ViewDescriptionMap.Get(A).Key < ViewDescriptionMap.Get(B).Key;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT("Visualize Texture available views:"));
|
|
|
|
|
|
|
|
|
|
for (FSetElementId ElementId : Entries)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogConsoleResponse, Log, TEXT(" %d %s"), ViewDescriptionMap.Get(ElementId).Key, *ViewDescriptionMap.Get(ElementId).Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
static TAutoConsoleVariable<int32> CVarAllowBlinking(
|
|
|
|
|
TEXT("r.VisualizeTexture.AllowBlinking"), 1,
|
|
|
|
|
TEXT("Whether to allow blinking when visualizing NaN or inf that can become irritating over time.\n"),
|
|
|
|
|
ECVF_RenderThreadSafe);
|
2018-11-21 20:22:47 -05:00
|
|
|
|
|
|
|
|
enum class EVisualisePSType
|
|
|
|
|
{
|
|
|
|
|
Cube = 0,
|
|
|
|
|
Texture1D = 1, //not supported
|
|
|
|
|
Texture2DNoMSAA = 2,
|
|
|
|
|
Texture3D = 3,
|
|
|
|
|
CubeArray = 4,
|
|
|
|
|
Texture2DMSAA = 5,
|
|
|
|
|
Texture2DDepthStencilNoMSAA = 6,
|
|
|
|
|
Texture2DUINT8 = 7,
|
2019-06-11 18:27:07 -04:00
|
|
|
Texture2DUINT32 = 8,
|
2018-11-21 20:22:47 -05:00
|
|
|
MAX
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 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)
|
|
|
|
|
class FVisualizeTexturePS : public FGlobalShader
|
|
|
|
|
{
|
|
|
|
|
DECLARE_GLOBAL_SHADER(FVisualizeTexturePS);
|
|
|
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeTexturePS, FGlobalShader);
|
|
|
|
|
|
|
|
|
|
class FVisualisePSTypeDim : SHADER_PERMUTATION_ENUM_CLASS("TEXTURE_TYPE", EVisualisePSType);
|
|
|
|
|
|
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<FVisualisePSTypeDim>;
|
|
|
|
|
|
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
|
|
|
{
|
|
|
|
|
FPermutationDomain PermutationVector(Parameters.PermutationId);
|
|
|
|
|
return PermutationVector.Get<FVisualisePSTypeDim>() != EVisualisePSType::Texture1D;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
2021-05-05 15:07:25 -04:00
|
|
|
SHADER_PARAMETER(FVector3f, TextureExtent)
|
2021-09-22 10:01:48 -04:00
|
|
|
SHADER_PARAMETER_ARRAY(FVector4f, VisualizeParam, [3])
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2022-06-01 03:50:53 -04:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, VisualizeTexture2D)
|
2018-11-21 20:22:47 -05:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, VisualizeTexture2DSampler)
|
2022-06-01 03:50:53 -04:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture3D, VisualizeTexture3D)
|
2018-11-21 20:22:47 -05:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, VisualizeTexture3DSampler)
|
2022-06-01 03:50:53 -04:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(TextureCube, VisualizeTextureCube)
|
2018-11-21 20:22:47 -05:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, VisualizeTextureCubeSampler)
|
2022-06-01 03:50:53 -04:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(TextureCubeArray, VisualizeTextureCubeArray)
|
2018-11-21 20:22:47 -05:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, VisualizeTextureCubeArraySampler)
|
2019-09-14 09:45:25 -04:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D<uint4>, VisualizeDepthStencil)
|
2018-11-21 20:22:47 -05:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2DMS<float4>, VisualizeTexture2DMS)
|
|
|
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<uint>, VisualizeUINT8Texture2D)
|
|
|
|
|
|
|
|
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeTexturePS, "/Engine/Private/Tools/VisualizeTexture.usf", "VisualizeTexturePS", SF_Pixel);
|
|
|
|
|
|
|
|
|
|
static EVisualisePSType GetVisualizePSType(const FRDGTextureDesc& Desc)
|
|
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
if(Desc.IsTexture2D())
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
|
|
|
|
// 2D
|
|
|
|
|
if(Desc.NumSamples > 1)
|
|
|
|
|
{
|
|
|
|
|
// MSAA
|
|
|
|
|
return EVisualisePSType::Texture2DMSAA;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(Desc.Format == PF_DepthStencil)
|
|
|
|
|
{
|
|
|
|
|
// DepthStencil non MSAA (needed to avoid D3DDebug error)
|
|
|
|
|
return EVisualisePSType::Texture2DDepthStencilNoMSAA;
|
|
|
|
|
}
|
|
|
|
|
else if (Desc.Format == PF_R8_UINT)
|
|
|
|
|
{
|
|
|
|
|
return EVisualisePSType::Texture2DUINT8;
|
|
|
|
|
}
|
2019-06-11 18:27:07 -04:00
|
|
|
else if (Desc.Format == PF_R32_UINT)
|
|
|
|
|
{
|
|
|
|
|
return EVisualisePSType::Texture2DUINT32;
|
|
|
|
|
}
|
2018-11-21 20:22:47 -05:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// non MSAA
|
|
|
|
|
return EVisualisePSType::Texture2DNoMSAA;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
else if(Desc.IsTextureCube())
|
|
|
|
|
{
|
|
|
|
|
if(Desc.IsTextureArray())
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
|
|
|
|
// Cube[]
|
|
|
|
|
return EVisualisePSType::CubeArray;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Cube
|
|
|
|
|
return EVisualisePSType::Cube;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
check(Desc.IsTexture3D());
|
2018-11-21 20:22:47 -05:00
|
|
|
return EVisualisePSType::Texture3D;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-09 12:58:33 -04:00
|
|
|
void FVisualizeTexture::ReleaseRHI()
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
Config = {};
|
|
|
|
|
Requested = {};
|
|
|
|
|
Captured = {};
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 13:15:46 -04:00
|
|
|
// static
|
|
|
|
|
FRDGTextureRef FVisualizeTexture::AddVisualizeTexturePass(
|
|
|
|
|
FRDGBuilder& GraphBuilder,
|
|
|
|
|
FGlobalShaderMap* ShaderMap,
|
|
|
|
|
const FRDGTextureRef InputTexture,
|
|
|
|
|
const FConfig& VisualizeConfig,
|
|
|
|
|
EInputValueMapping InputValueMapping,
|
|
|
|
|
uint32 CaptureId)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2023-04-06 13:15:46 -04:00
|
|
|
check(InputTexture);
|
|
|
|
|
check(!EnumHasAnyFlags(InputTexture->Desc.Flags, TexCreate_CPUReadback));
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
const FRDGTextureDesc& InputDesc = InputTexture->Desc;
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
FIntPoint InputExtent = InputDesc.Extent;
|
2020-09-24 00:43:27 -04:00
|
|
|
FIntPoint OutputExtent = InputExtent;
|
|
|
|
|
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
// Scene textures are padded and shared across scene renderers, with a given scene renderer using a viewport in the shared buffer.
|
|
|
|
|
// We only want to visualize the portion actually used by the given scene renderer, as the rest will be blank or garbage. The info
|
|
|
|
|
// text will display the actual texture size in addition to the viewport being visualized.
|
|
|
|
|
FIntPoint VisualizeTextureExtent = InputTexture->GetVisualizeExtent();
|
|
|
|
|
if ((VisualizeTextureExtent.X > 0) && (VisualizeTextureExtent.Y > 0))
|
|
|
|
|
{
|
|
|
|
|
// Clamp extent at actual dimensions of texture
|
|
|
|
|
OutputExtent.X = FMath::Min(VisualizeTextureExtent.X, OutputExtent.X);
|
|
|
|
|
OutputExtent.Y = FMath::Min(VisualizeTextureExtent.Y, OutputExtent.Y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (InputDesc.IsTextureCube())
|
|
|
|
|
{
|
|
|
|
|
// For pixel perfect display of cube map, we'll use a 4x3 flat unwrapping of the cube map, rather than a projection. The visualization
|
|
|
|
|
// shader detects the 4x3 aspect ratio, and generates a seamless panorama in the middle, with the adjacent floor and sky tiles above
|
|
|
|
|
// and below. There will be seams between floor and sky tiles, but the pixels shown will otherwise be exact.
|
|
|
|
|
if (GVisualizeTexture.Config.InputUVMapping == EInputUVMapping::PixelPerfectCenter)
|
|
|
|
|
{
|
|
|
|
|
InputExtent.X *= 4;
|
|
|
|
|
InputExtent.Y *= 3;
|
|
|
|
|
OutputExtent.X *= 4;
|
|
|
|
|
OutputExtent.Y *= 3;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Longitudinal rendered cube maps look better with 2 to 1 aspect ratio (same as how the texture resource viewer displays cube maps)
|
|
|
|
|
InputExtent.X *= 2;
|
|
|
|
|
OutputExtent.X *= 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GVisualizeTexture.Captured.OutputExtent = OutputExtent;
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
// Clamp to reasonable value to prevent crash
|
|
|
|
|
OutputExtent.X = FMath::Max(OutputExtent.X, 1);
|
|
|
|
|
OutputExtent.Y = FMath::Max(OutputExtent.Y, 1);
|
|
|
|
|
|
[Re-submit Backout attempt take 2 -- original horde failure didn't repro on preflight, so maybe it was a spurious issue?]
Post Process Material: Support for "UserSceneTextures" -- transient intermediate render targets that can be written and read by name in post process materials. The post process section of materials has a UserSceneTexture output name, and a new UserSceneTexture node type has been added to read back those outputs as inputs.
Shader features:
* A resolution divisor can be specified on the output to allow things like half resolution targets. If the same name is used with multiple resolutions, the most recently written resolution is used as an input.
* A UV clamping option was added to solve out of bounds interpolation issues when bilinear sampling lower resolution targets from a higher resolution pass.
* A human readable define based on the user specified name is added to HLSL (with prefix "PPIUser_"), allowing Custom HLSL nodes to refer to UserSceneTexture inputs by name. Necessary because input slots are dynamically allocated. Useful for things like blur kernels that use Custom HLSL to sample a range of inputs.
* All 5 Post Process Input slots are potentially available to UserSceneTextures -- built-in SceneTexture slots for a given location (like SceneColor, SeparateTranslucency, or SceneVelocity) are used for UserSceneTextures if not referenced in the shader.
* Supports translucent blending. If the first write to a UserSceneTexture includes blending, it will be primed with the current input for the given location.
* Missing inputs are replaced with black.
* Simplified syntax for accessing SceneTextures / UserSceneTextures in Custom HLSL (see "SceneTextureFetch" macro).
Editing / debug features:
* Material editor preview window automatically includes other edited materials that feed inputs into the current material, allowing multi-pass effects to be interactively edited.
* Debug display of post process passes with UserSceneTexture inputs or output via r.PostProcessing.UserSceneTextureDebug. Allows seeing order, location, and priority of passes, plus names of material, inputs, and output, and whether an output is written with blending.
* Debug display pops up automatically on error conditions (missing input, unused output), improving discoverability. Suppressed by DisableAllScreenMessages (or setting CVar itself to zero).
* FRDGViewableResource can now be given dynamically generated heap allocated debug names (indicated by setting a flag immediately after construction), instead of only supporting static const strings. Allows UserSceneTexture names to be displayed in debug displays, VisualizeTexture, GPU captures, and GPU dumps, instead of every resource getting the same name.
Mobile doesn't support post process domain materials at all, so the feature is not relevant there. Tested on scene captures, split screen, and both legacy and new material translate code paths. An existing bug was fixed where rendering post process materials with blending before bloom would crash, due to the output not being allocated with the render target flag set.
#rb eric.renaudhoude, Ruslan.Idrisov
[CL 34055494 by jason hoerner in ue5-main branch]
2024-06-01 13:02:37 -04:00
|
|
|
FRDGTextureRef OutputTexture = GraphBuilder.CreateTexture(FRDGTextureDesc::Create2D(OutputExtent, PF_B8G8R8A8, FClearValueBinding(FLinearColor(1, 1, 0, 1)), TexCreate_RenderTargetable | TexCreate_ShaderResource), InputTexture->Name);
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
const EVisualisePSType VisualizeType = GetVisualizePSType(InputDesc);
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
FVisualizeTexturePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeTexturePS::FParameters>();
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2019-09-14 09:45:25 -04:00
|
|
|
{
|
2022-02-02 07:59:31 -05:00
|
|
|
PassParameters->TextureExtent = FVector3f(InputExtent.X, InputExtent.Y, InputDesc.Depth);
|
2019-09-14 09:45:25 -04:00
|
|
|
|
2019-02-12 20:40:29 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
// Alternates between 0 and 1 with a short pause
|
|
|
|
|
const float FracTimeScale = 1.0f / 4.0f;
|
|
|
|
|
float FracTime = FApp::GetCurrentTime() * FracTimeScale - floor(FApp::GetCurrentTime() * FracTimeScale);
|
|
|
|
|
float BlinkState = (FracTime < 1.0f / 16.0f) ? 1.0f : 0.0f;
|
|
|
|
|
|
2021-09-22 10:01:48 -04:00
|
|
|
FVector4f VisualizeParamValue[3];
|
2020-09-24 00:43:27 -04:00
|
|
|
|
|
|
|
|
float Add = 0.0f;
|
|
|
|
|
float FracScale = 1.0f;
|
|
|
|
|
|
|
|
|
|
// w * almost_1 to avoid frac(1) => 0
|
2023-04-06 13:15:46 -04:00
|
|
|
PassParameters->VisualizeParam[0] = FVector4f(VisualizeConfig.RGBMul, VisualizeConfig.SingleChannelMul, Add, FracScale * 0.9999f);
|
2023-09-27 11:33:10 -04:00
|
|
|
PassParameters->VisualizeParam[1] = FVector4f(CVarAllowBlinking.GetValueOnRenderThread() ? BlinkState : 0.0f, (VisualizeConfig.ShaderOp == EShaderOp::Saturate) ? 1.0f : 0.0f, VisualizeConfig.ArrayIndex, VisualizeConfig.MipIndex);
|
2023-04-06 13:15:46 -04:00
|
|
|
PassParameters->VisualizeParam[2] = FVector4f((float)InputValueMapping, 0.0f, VisualizeConfig.SingleChannel);
|
2019-02-12 20:40:29 -05:00
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2022-06-01 03:50:53 -04:00
|
|
|
FRDGTextureSRV* InputSRV = nullptr;
|
2020-09-24 00:43:27 -04:00
|
|
|
FRHISamplerState* PointSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
2022-06-01 03:50:53 -04:00
|
|
|
if (InputTexture->Desc.Dimension == ETextureDimension::Texture2DArray)
|
|
|
|
|
{
|
2023-04-06 13:15:46 -04:00
|
|
|
InputSRV = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::CreateForSlice(InputTexture, FMath::Clamp(int32(VisualizeConfig.ArrayIndex), 0, int32(InputDesc.ArraySize) - 1)));
|
2022-06-01 03:50:53 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
InputSRV = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::Create(InputTexture));
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2022-06-01 03:50:53 -04:00
|
|
|
PassParameters->VisualizeTexture2D = InputSRV;
|
2020-09-24 00:43:27 -04:00
|
|
|
PassParameters->VisualizeTexture2DSampler = PointSampler;
|
2022-06-01 03:50:53 -04:00
|
|
|
PassParameters->VisualizeTexture3D = InputSRV;
|
2020-09-24 00:43:27 -04:00
|
|
|
PassParameters->VisualizeTexture3DSampler = PointSampler;
|
2022-06-01 03:50:53 -04:00
|
|
|
PassParameters->VisualizeTextureCube = InputSRV;
|
2020-09-24 00:43:27 -04:00
|
|
|
PassParameters->VisualizeTextureCubeSampler = PointSampler;
|
2022-06-01 03:50:53 -04:00
|
|
|
PassParameters->VisualizeTextureCubeArray = InputSRV;
|
2020-09-24 00:43:27 -04:00
|
|
|
PassParameters->VisualizeTextureCubeArraySampler = PointSampler;
|
|
|
|
|
|
|
|
|
|
if (VisualizeType == EVisualisePSType::Texture2DDepthStencilNoMSAA)
|
2019-02-12 20:40:29 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
FRDGTextureSRVDesc SRVDesc = FRDGTextureSRVDesc::CreateWithPixelFormat(InputTexture, PF_X24_G8);
|
|
|
|
|
PassParameters->VisualizeDepthStencil = GraphBuilder.CreateSRV(SRVDesc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PassParameters->VisualizeTexture2DMS = InputTexture;
|
|
|
|
|
PassParameters->VisualizeUINT8Texture2D = InputTexture;
|
|
|
|
|
|
|
|
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(OutputTexture, ERenderTargetLoadAction::EClear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVisualizeTexturePS::FPermutationDomain PermutationVector;
|
|
|
|
|
PermutationVector.Set<FVisualizeTexturePS::FVisualisePSTypeDim>(VisualizeType);
|
|
|
|
|
|
|
|
|
|
TShaderMapRef<FVisualizeTexturePS> PixelShader(ShaderMap, PermutationVector);
|
|
|
|
|
|
|
|
|
|
FString ExtendedDrawEvent;
|
Merging //UE5/Dev-ParallelRendering/... (up to CL 30965645) to //UE5/Main/... (base CL 30962637)
Significant refactor of RHI command list management and submission, and RHI breadcrumbs / RenderGraph (RDG) scopes, to allow for parallel translation of most RHI command lists.
See individual changelists in //UE5/Dev-ParallelRendering for details. A summary of the changes is as follows:
This work's primary goal was to allow as many RHI command lists as possible to be parallel translated, to make more efficient use of many-core systems. To achieve this:
- The submission code paths for the immediate and parallel RHI command lists have been merged into a single function: FRHICommandListExecutor::Submit().
- A "dispatch thread" (which is simply a series of chained task graph tasks) is used to decide which command lists are batched together in a single parallel translate job.
- Individual command lists can disable parallel translate, which forces them to be executed on the RHI thread. This happens automatically if an RHI command list performs an operation that is not thread safe (e.g. buffer lock, or low-level resource transition).
One of the primary blockers for parallel translation was the RHI breadcrumb system, and the way RDG builds scopes. This was also refactored to remove these limitations:
- RDG could only push/pop events on the immediate command list, which resulted in parallel and immediate work being interleaved, breaking any opportunity for parallelism.
- Platform RHI implementations of breadcrumbs (e.g. in D3D12 RHI) was not correct across multiple RHI contexts. Push/pop operations aren't necessarily balanced within any one RHI context given that RDG builds "parallel pass sets" containing arbitrary ranges of renderer passes.
A summary of the new RHI breadcrumb system is as follows:
- A tree of breadcrumb nodes is built by the render thread and RDG. Each node contains the node name, and pointers to the parent and next nodes. When fully built, the nodes form a depth-first linked list which is used for traversing the tree for GPU crash debugging.
- The memory for breadcrumb nodes is provided by ref-counted allocator objects. These allocators are pipelined through the RHI, allowing the platform RHI implementation to extend their lifetime for GPU crash debugging purposes.
- RHIPushEvent / RHIPopEvent have been removed, replaced with RHIBeginBreadcrumbGPU / RHIEndBreadcrumbGPU. Platform RHIs implement these functions to perform GPU immediate writes using the unique ID of each node, for tracking GPU progress.
- Format string arguments are captured by-value to remove the cost of string formatting while building the breadcrumb tree. String formatting only occurs when the actual formatted string is required (e.g. during GPU crash breadcrumb stack traversal, or when calling platform GPU profiling APIs).
RenderGraph scopes have been simplified:
- The separate scope trees / arrays of ops have been combined. There is now a single tree of RDG scopes containing all types.
- Each RDG pass holds a pointer to the scope it was created under.
- BeginCPU / EndCPU is called on each RDG scope as the various RDG threads enter / exit them. This allows us to mark-up each worker thread with the relevant Unreal Insights scopes.
Other changes include:
- Fixes for bugs uncovered when parallel translate was enabled.
- Adjusted platform affinities necessary due to the new layout of thread tasks in the renderer.
- Refactored RHI draw call stats to better fit the new pipeline design.
#rb jeannoe.morissette, zach.bethel
#jira UE-139543
[CL 30973133 by Luke Thatcher in ue5-main branch]
2024-01-29 12:47:28 -05:00
|
|
|
if (GraphBuilder.ShouldEmitEvents())
|
2020-09-24 00:43:27 -04:00
|
|
|
{
|
|
|
|
|
if (InputDesc.IsTexture3D())
|
|
|
|
|
{
|
2023-04-06 13:15:46 -04:00
|
|
|
ExtendedDrawEvent += FString::Printf(TEXT("x%d CapturedSlice=%d"), InputDesc.Depth, VisualizeConfig.ArrayIndex);
|
2020-09-24 00:43:27 -04:00
|
|
|
}
|
|
|
|
|
|
2022-06-01 03:50:53 -04:00
|
|
|
if (InputDesc.IsTextureArray())
|
|
|
|
|
{
|
2023-04-06 13:15:46 -04:00
|
|
|
ExtendedDrawEvent += FString::Printf(TEXT(" ArraySize=%d CapturedSlice=%d"), InputDesc.ArraySize, VisualizeConfig.ArrayIndex);
|
2022-06-01 03:50:53 -04:00
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
// Precise the mip level being captured in the mip level when there is a mip chain.
|
|
|
|
|
if (InputDesc.IsMipChain())
|
|
|
|
|
{
|
2023-04-06 13:15:46 -04:00
|
|
|
ExtendedDrawEvent += FString::Printf(TEXT(" Mips=%d CapturedMip=%d"), InputDesc.NumMips, VisualizeConfig.MipIndex);
|
2019-02-12 20:40:29 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
FPixelShaderUtils::AddFullscreenPass(
|
|
|
|
|
GraphBuilder,
|
|
|
|
|
ShaderMap,
|
|
|
|
|
RDG_EVENT_NAME("VisualizeTextureCapture(%s@%d %s %dx%d%s)",
|
|
|
|
|
InputTexture->Name, CaptureId,
|
|
|
|
|
GPixelFormats[InputDesc.Format].Name,
|
|
|
|
|
InputExtent.X, InputExtent.Y,
|
|
|
|
|
*ExtendedDrawEvent),
|
|
|
|
|
PixelShader,
|
|
|
|
|
PassParameters,
|
|
|
|
|
FIntRect(0, 0, OutputExtent.X, OutputExtent.Y));
|
2019-09-14 09:45:25 -04:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 13:15:46 -04:00
|
|
|
return OutputTexture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FVisualizeTexture::CreateContentCapturePass(FRDGBuilder& GraphBuilder, const FRDGTextureRef InputTexture, uint32 CaptureId)
|
|
|
|
|
{
|
|
|
|
|
if (!InputTexture)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const FRDGTextureDesc& InputDesc = InputTexture->Desc;
|
|
|
|
|
const FIntPoint InputExtent = InputDesc.Extent;
|
|
|
|
|
|
|
|
|
|
if (EnumHasAnyFlags(InputDesc.Flags, TexCreate_CPUReadback))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EInputValueMapping InputValueMapping = EInputValueMapping::Color;
|
|
|
|
|
{
|
|
|
|
|
if (InputDesc.Format == PF_ShadowDepth)
|
|
|
|
|
{
|
|
|
|
|
InputValueMapping = EInputValueMapping::Shadow;
|
|
|
|
|
}
|
|
|
|
|
else if (EnumHasAnyFlags(InputDesc.Flags, TexCreate_DepthStencilTargetable))
|
|
|
|
|
{
|
|
|
|
|
InputValueMapping = EInputValueMapping::Depth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(FeatureLevel);
|
|
|
|
|
FRDGTextureRef OutputTexture = AddVisualizeTexturePass(GraphBuilder, ShaderMap, InputTexture, Config, InputValueMapping, CaptureId);
|
|
|
|
|
|
|
|
|
|
FIntPoint OutputExtent = InputExtent;
|
|
|
|
|
OutputExtent.X = FMath::Max(OutputExtent.X, 1);
|
|
|
|
|
OutputExtent.Y = FMath::Max(OutputExtent.Y, 1);
|
|
|
|
|
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
Captured.Desc = Translate(InputDesc);
|
|
|
|
|
Captured.Desc.DebugName = InputTexture->Name;
|
|
|
|
|
Captured.PooledRenderTarget = nullptr;
|
|
|
|
|
Captured.Texture = OutputTexture;
|
|
|
|
|
Captured.InputValueMapping = InputValueMapping;
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
Captured.ViewRects = FamilyViewRects;
|
2020-09-24 00:43:27 -04:00
|
|
|
|
|
|
|
|
GraphBuilder.QueueTextureExtraction(OutputTexture, &Captured.PooledRenderTarget);
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
if (EnumHasAnyFlags(Config.Flags, EFlags::SaveBitmap | EFlags::SaveBitmapAsStencil))
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
uint32 MipAdjustedExtentX = FMath::Clamp(OutputExtent.X >> Config.MipIndex, 0, OutputExtent.X);
|
|
|
|
|
uint32 MipAdjustedExtentY = FMath::Clamp(OutputExtent.Y >> Config.MipIndex, 0, OutputExtent.Y);
|
2018-11-21 20:22:47 -05:00
|
|
|
FIntPoint Extent(MipAdjustedExtentX, MipAdjustedExtentY);
|
|
|
|
|
|
|
|
|
|
FReadSurfaceDataFlags ReadDataFlags;
|
|
|
|
|
ReadDataFlags.SetLinearToGamma(false);
|
2020-09-24 00:43:27 -04:00
|
|
|
ReadDataFlags.SetOutputStencil(EnumHasAnyFlags(Config.Flags, EFlags::SaveBitmapAsStencil));
|
|
|
|
|
ReadDataFlags.SetMip(Config.MipIndex);
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
const TCHAR* DebugName = Captured.Desc.DebugName;
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
AddReadbackTexturePass(GraphBuilder, RDG_EVENT_NAME("SaveBitmap"), OutputTexture,
|
|
|
|
|
[OutputTexture, Extent, ReadDataFlags, DebugName](FRHICommandListImmediate& RHICmdList)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
TArray<FColor> Bitmap;
|
|
|
|
|
RHICmdList.ReadSurfaceData(OutputTexture->GetRHI(), FIntRect(0, 0, Extent.X, Extent.Y), Bitmap, ReadDataFlags);
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
// if the format and texture type is supported
|
|
|
|
|
if (Bitmap.Num())
|
|
|
|
|
{
|
|
|
|
|
// Create screenshot folder if not already present.
|
|
|
|
|
IFileManager::Get().MakeDirectory(*FPaths::ScreenShotDir(), true);
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
const FString Filename(FPaths::ScreenShotDir() / TEXT("VisualizeTexture"));
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
uint32 ExtendXWithMSAA = Bitmap.Num() / Extent.Y;
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
// Save the contents of the array to a bitmap file. (24bit only so alpha channel is dropped)
|
|
|
|
|
FFileHelper::CreateBitmap(*Filename, ExtendXWithMSAA, Extent.Y, Bitmap.GetData());
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogRendererCore, Display, TEXT("Content was saved to \"%s\""), *FPaths::ScreenShotDir());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogRendererCore, Error, TEXT("Failed to save BMP for VisualizeTexture, format or texture type is not supported"));
|
|
|
|
|
}
|
|
|
|
|
});
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
void FVisualizeTexture::BeginFrameRenderThread()
|
|
|
|
|
{
|
|
|
|
|
bAnyViewRendered = false;
|
|
|
|
|
bIsRequestedView = false;
|
|
|
|
|
bFoundRequestedView = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-13 12:03:29 -04:00
|
|
|
static bool VisualizeTextureViewNameMatches(const FString& ViewName, const TCHAR* Description)
|
|
|
|
|
{
|
|
|
|
|
// Description will be of the form "EditorName (FName)" or "Name", with EditorName being user facing. Match name followed by space or null terminator.
|
|
|
|
|
int32 ViewNameLen = ViewName.Len();
|
|
|
|
|
return !FCString::Strnicmp(*ViewName, Description, ViewNameLen) && (Description[ViewNameLen] == ' ' || Description[ViewNameLen] == 0);
|
|
|
|
|
}
|
|
|
|
|
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
void FVisualizeTexture::BeginViewRenderThread(ERHIFeatureLevel::Type InFeatureLevel, int32 UniqueId, const TCHAR* Description, bool bIsSceneCapture)
|
|
|
|
|
{
|
|
|
|
|
// Only support visualization for views with a unique ID
|
|
|
|
|
if (State == EState::Inactive || !UniqueId)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FeatureLevel = InFeatureLevel;
|
|
|
|
|
|
|
|
|
|
if (!bAnyViewRendered)
|
|
|
|
|
{
|
|
|
|
|
// Clear list of views out when we encounter the first view on the current frame
|
|
|
|
|
ViewDescriptionMap.Empty();
|
|
|
|
|
bAnyViewRendered = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ViewDescriptionMap.FindOrAdd(UniqueId) = Description;
|
|
|
|
|
|
2024-03-13 12:03:29 -04:00
|
|
|
if (!Requested.ViewName.IsEmpty() ? VisualizeTextureViewNameMatches(Requested.ViewName, Description) : Requested.ViewUniqueId == UniqueId)
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
{
|
|
|
|
|
// Found the specific view we requested
|
|
|
|
|
bIsRequestedView = true;
|
|
|
|
|
bFoundRequestedView = true;
|
|
|
|
|
}
|
|
|
|
|
else if (!bFoundRequestedView)
|
|
|
|
|
{
|
|
|
|
|
// If specific requested view hasn't been found, visualize any view that's not a scene capture, so we still get some sort of result
|
|
|
|
|
bIsRequestedView = !bIsSceneCapture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear outputs when we are processing a requested view
|
|
|
|
|
if (bIsRequestedView)
|
|
|
|
|
{
|
|
|
|
|
VersionCountMap.Empty();
|
|
|
|
|
Captured = {};
|
|
|
|
|
Captured.ViewUniqueId = UniqueId;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FVisualizeTexture::SetSceneTextures(const TArray<FRDGTextureRef>& InSceneTextures, FIntPoint InFamilySize, const TArray<FIntRect>& InFamilyViewRects)
|
|
|
|
|
{
|
|
|
|
|
for (FRDGTextureRef Texture : InSceneTextures)
|
|
|
|
|
{
|
|
|
|
|
Texture->EncloseVisualizeExtent(InFamilySize);
|
|
|
|
|
}
|
|
|
|
|
FamilyViewRects = InFamilyViewRects;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
TOptional<uint32> FVisualizeTexture::ShouldCapture(const TCHAR* InName, uint32 InMipIndex)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
TOptional<uint32> CaptureId;
|
|
|
|
|
uint32& VersionCount = VersionCountMap.FindOrAdd(InName);
|
|
|
|
|
if (!Requested.Name.IsEmpty() && Requested.Name == InName)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
if (!Requested.Version || VersionCount == Requested.Version.GetValue())
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
CaptureId = VersionCount;
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-24 00:43:27 -04:00
|
|
|
++VersionCount;
|
|
|
|
|
return CaptureId;
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
|
Visualize Texture: Performance and feature upgrades.
* Visualize texture system starts out in an inactive state until a command is issued, avoiding overhead of tracking views and scene textures, saving 1.4% on the render thread.
* Visualization overhead eliminated for views besides the one currently being visualized.
* Support for visualization of textures from scene captures, via "view=N" option (specifying the unique ID of the view), with "view=?" displaying a list of views for reference.
* Improved visualization for cube maps. PIP uses 2:1 aspect for the longitudinal render to match resource viewer display, and pixel perfect option shows tiled flat cube map faces (actual pixels) rather than running a projection.
* Padding for scene or screen pass textures is removed in the visualization -- the padding otherwise shows up as garbage or blank space.
To remove scene texture padding, it's necessary to add a field to RDG textures to provide an option to track the viewport sizes that were rendered for a given texture. If not set, the assumption is the whole texture was rendered. The field is set for FSceneTextures and FScreenPassTexture, covering the vast majority of cases, plus the denoiser was spot fixed -- worst case if any other cases are missed, you still see the padding. You can tell padding was present when visualizing by contrasting the texture size with the viewport size.
Padding was always a potential issue for the visualizer, but is exacerbated by scene captures, as the padded scene textures are set to a size that's a union of the main view and any scene captures. Padding is also exacerbated by dynamic resolution scaling, as the buffers will be padded to the maximum resolution. For example, a cube map rendering at 512x512 will have 93% of the pixel area as padding if the front buffer is at 1440p, or the default dynamic resolution setup will have 70% of the pixels as padding at minimum res.
#rb Jason.Nadro
[CL 31160232 by jason hoerner in ue5-main branch]
2024-02-03 16:07:46 -05:00
|
|
|
void FVisualizeTexture::EndViewRenderThread()
|
|
|
|
|
{
|
|
|
|
|
if (bIsRequestedView)
|
|
|
|
|
{
|
|
|
|
|
bIsRequestedView = false;
|
|
|
|
|
FamilyViewRects.Empty();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FVisualizeTexture::EndFrameRenderThread()
|
|
|
|
|
{
|
|
|
|
|
if (bAnyViewRendered)
|
|
|
|
|
{
|
|
|
|
|
if (State == EState::DisplayResources)
|
|
|
|
|
{
|
|
|
|
|
DisplayResourceListToLog(DisplayResourcesParam);
|
|
|
|
|
DisplayResourcesParam.Reset();
|
|
|
|
|
State = EState::TrackResources;
|
|
|
|
|
}
|
|
|
|
|
else if (State == EState::DisplayViews)
|
|
|
|
|
{
|
|
|
|
|
DisplayViewListToLog();
|
|
|
|
|
State = EState::TrackResources;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
uint32 FVisualizeTexture::GetVersionCount(const TCHAR* InName) const
|
|
|
|
|
{
|
|
|
|
|
if (const uint32* VersionCount = VersionCountMap.Find(InName))
|
|
|
|
|
{
|
|
|
|
|
return *VersionCount;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2021-03-04 00:38:01 -04:00
|
|
|
void FVisualizeTexture::SetCheckPoint(FRDGBuilder& GraphBuilder, IPooledRenderTarget* PooledRenderTarget)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
|
|
|
|
check(IsInRenderingThread());
|
2020-09-24 00:43:27 -04:00
|
|
|
|
2018-11-21 20:22:47 -05:00
|
|
|
if (!PooledRenderTarget)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
const FPooledRenderTargetDesc& Desc = PooledRenderTarget->GetDesc();
|
2018-11-21 20:22:47 -05:00
|
|
|
|
2022-01-31 17:22:31 -05:00
|
|
|
if (!EnumHasAnyFlags(Desc.Flags, TexCreate_ShaderResource))
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
TOptional<uint32> CaptureId = ShouldCapture(Desc.DebugName, Config.MipIndex);
|
|
|
|
|
if (!CaptureId)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
return;
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
|
2022-01-31 17:22:31 -05:00
|
|
|
FRDGTextureRef TextureToCapture = GraphBuilder.RegisterExternalTexture(PooledRenderTarget);
|
2020-09-24 00:43:27 -04:00
|
|
|
CreateContentCapturePass(GraphBuilder, TextureToCapture, CaptureId.GetValue());
|
2021-03-04 00:38:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FVisualizeTexture::SetCheckPoint(FRHICommandListImmediate& RHICmdList, IPooledRenderTarget* PooledRenderTarget)
|
|
|
|
|
{
|
|
|
|
|
FRDGBuilder GraphBuilder(RHICmdList);
|
|
|
|
|
SetCheckPoint(GraphBuilder, PooledRenderTarget);
|
2018-11-21 20:22:47 -05:00
|
|
|
GraphBuilder.Execute();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 00:43:27 -04:00
|
|
|
void FVisualizeTexture::Visualize(const FString& InName, TOptional<uint32> InVersion)
|
2018-11-21 20:22:47 -05:00
|
|
|
{
|
2020-09-24 00:43:27 -04:00
|
|
|
Requested.Name = InName;
|
|
|
|
|
Requested.Version = InVersion;
|
2018-11-21 20:22:47 -05:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 13:38:15 -04:00
|
|
|
#endif // SUPPORTS_VISUALIZE_TEXTURE
|
2023-04-06 13:15:46 -04:00
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
FRDGTextureRef FVisualizeTexture::AddVisualizeTexturePass(
|
|
|
|
|
FRDGBuilder& GraphBuilder,
|
|
|
|
|
class FGlobalShaderMap* ShaderMap,
|
|
|
|
|
const FRDGTextureRef InputTexture)
|
|
|
|
|
#if SUPPORTS_VISUALIZE_TEXTURE
|
|
|
|
|
{
|
|
|
|
|
check(InputTexture);
|
|
|
|
|
EInputValueMapping InputValueMapping = EInputValueMapping::Color;
|
|
|
|
|
{
|
|
|
|
|
if (InputTexture->Desc.Format == PF_ShadowDepth)
|
|
|
|
|
{
|
|
|
|
|
InputValueMapping = EInputValueMapping::Shadow;
|
|
|
|
|
}
|
|
|
|
|
else if (EnumHasAnyFlags(InputTexture->Desc.Flags, TexCreate_DepthStencilTargetable))
|
|
|
|
|
{
|
|
|
|
|
InputValueMapping = EInputValueMapping::Depth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FConfig VisualizeConfig;
|
|
|
|
|
|
|
|
|
|
return AddVisualizeTexturePass(GraphBuilder, ShaderMap, InputTexture, VisualizeConfig, InputValueMapping, /* CaptureId = */ 0);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
{
|
|
|
|
|
return InputTexture;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
FRDGTextureRef FVisualizeTexture::AddVisualizeTextureAlphaPass(
|
|
|
|
|
FRDGBuilder& GraphBuilder,
|
|
|
|
|
class FGlobalShaderMap* ShaderMap,
|
|
|
|
|
const FRDGTextureRef InputTexture)
|
|
|
|
|
#if SUPPORTS_VISUALIZE_TEXTURE
|
|
|
|
|
{
|
|
|
|
|
check(InputTexture);
|
|
|
|
|
FConfig VisualizeConfig;
|
|
|
|
|
VisualizeConfig.SingleChannel = 3;
|
|
|
|
|
VisualizeConfig.SingleChannelMul = 1.0f;
|
|
|
|
|
VisualizeConfig.RGBMul = 0.0f;
|
|
|
|
|
|
|
|
|
|
return AddVisualizeTexturePass(GraphBuilder, ShaderMap, InputTexture, VisualizeConfig, EInputValueMapping::Color, /* CaptureId = */ 0);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
{
|
|
|
|
|
return InputTexture;
|
|
|
|
|
}
|
|
|
|
|
#endif
|