Files
UnrealEngineUWP/Engine/Shaders/Private/ShaderPrintCommon.ush
charles derousiers b402ba8720 Fix vulkan compilation issue with new ShaderPrint coloring.
Vulkan/DXC does not support initialization of static const variable having complex type. This change lines change the initialization to some simple define instead.

#rb none


#ROBOMERGE-SOURCE: CL 16574414
#ROBOMERGE-BOT: (v828-16531559)

[CL 16574416 by charles derousiers in ue5-main branch]
2021-06-07 14:15:34 -04:00

495 lines
15 KiB
Plaintext

/*=============================================================================
ShaderPrintCommon.ush:
Include this to be able to call ShaderPrint() from arbitrary shaders
=============================================================================*/
#pragma once
// Include the MiniFont symbol definitions
#include "MiniFontCommon.ush"
// --------------------------------------------------------------------------
// Uniforms and structures
// Needs to match C++ code in ShaderPrintUniform.cpp
struct FShaderPrintItem
{
float2 ScreenPos; // Position in normalized coordinates
int Value; // Cast to value or symbol
int Type; // SHADER_PRINT_TYPE_* defines how to read Value
float3 Color; // Color
};
struct FPackedShaderPrintItem
{
float2 ScreenPos; // Position in normalized coordinates
int Value; // Cast to value or symbol
uint TypeAndColor;//
};
RWStructuredBuffer<FPackedShaderPrintItem> RWValuesBuffer;
// --------------------------------------------------------------------------
// Input types
// Content of FShaderPrintItem.Type defines what to cast FShaderPrintItem.Value as
#define SHADER_PRINT_TYPE_SYMBOL 0
#define SHADER_PRINT_TYPE_FLOAT 1
#define SHADER_PRINT_TYPE_INT 2
#define SHADER_PRINT_TYPE_UINT 3
#define SHADER_PRINT_TYPE_HEX 4
#define SHADER_PRINT_COUNT_OFFSET 0
#define SHADER_PRINT_VALUE_OFFSET 1
// --------------------------------------------------------------------------
// Font Color
struct FFontColor
{
float3 Color;
};
FFontColor InitFontColor(float InX, float InY, float InZ) { FFontColor Out; Out.Color = float3(InX, InY, InZ); return Out; }
FFontColor InitFontColor(float3 In) { FFontColor Out; Out.Color = In; return Out; }
FFontColor GetDefaultFontColor() { FFontColor Out; Out.Color = float3(1,1,1); return Out; }
// Certain shader compiler does not support static initialization with complex type.
// In the meantime, using define to provide default color initialization
#if 1
#define FontWhite InitFontColor(1, 1, 1)
#define FontBlack InitFontColor(0, 0, 0)
#define FontRed InitFontColor(1, 0, 0)
#define FontGreen InitFontColor(0, 1, 0)
#define FontBlue InitFontColor(0, 0, 1)
#define FontYellow InitFontColor(1, 1, 0)
#define FontCyan InitFontColor(0, 1, 1)
#define FontMagenta InitFontColor(1, 0, 1)
#define FontOrange InitFontColor(243.f / 255.f, 156.f / 255.f, 18.f / 255.f)
#define FontPurple InitFontColor(169.f / 255.f, 7.f / 255.f, 228.f / 255.f)
#define FontTurquoise InitFontColor(26.f / 255.f, 188.f / 255.f, 156.f / 255.f)
#define FontSilver InitFontColor(189.f / 255.f, 195.f / 255.f, 199.f / 255.f)
#define FontEmerald InitFontColor(46.f / 255.f, 204.f / 255.f, 113.f / 255.f)
#else
static const FFontColor FontWhite = InitFontColor(1, 1, 1);
static const FFontColor FontBlack = InitFontColor(0, 0, 0);
static const FFontColor FontRed = InitFontColor(1, 0, 0);
static const FFontColor FontGreen = InitFontColor(0, 1, 0);
static const FFontColor FontBlue = InitFontColor(0, 0, 1);
static const FFontColor FontYellow = InitFontColor(1, 1, 0);
static const FFontColor FontCyan = InitFontColor(0, 1, 1);
static const FFontColor FontMagenta = InitFontColor(1, 0, 1);
static const FFontColor FontOrange = InitFontColor(243.f / 255.f, 156.f / 255.f, 18.f / 255.f);
static const FFontColor FontPurple = InitFontColor(169.f /255.f, 7.f / 255.f, 228.f / 255.f);
static const FFontColor FontTurquoise = InitFontColor( 26.f / 255.f, 188.f / 255.f, 156.f / 255.f);
static const FFontColor FontSilver = InitFontColor(189.f / 255.f, 195.f / 255.f, 199.f / 255.f);
static const FFontColor FontEmerald = InitFontColor( 46.f / 255.f, 204.f / 255.f, 113.f / 255.f);
#endif
// --------------------------------------------------------------------------
// Util pack/unpac functions
FPackedShaderPrintItem PackShaderPrintItem(FShaderPrintItem In)
{
const uint3 Color8bits = saturate(In.Color) * 0xFF;
FPackedShaderPrintItem Out;
Out.ScreenPos = In.ScreenPos;
Out.Value = In.Value;
Out.TypeAndColor = Color8bits.z<<24 | Color8bits.y<<16 | Color8bits.x<<8 | (In.Type & 0xFF);
return Out;
}
FShaderPrintItem UnpackShaderPrintItem(FPackedShaderPrintItem In)
{
FShaderPrintItem Out;
Out.ScreenPos = In.ScreenPos;
Out.Value = In.Value;
Out.Type = (In.TypeAndColor) & 0xFF;
Out.Color.x = float((In.TypeAndColor >> 8) & 0xFF) / 255.f;
Out.Color.y = float((In.TypeAndColor >> 16) & 0xFF) / 255.f;
Out.Color.z = float((In.TypeAndColor >> 24) & 0xFF) / 255.f;
return Out;
}
// --------------------------------------------------------------------------
// Global variables
#include "/Engine/Generated/UniformBuffers/ShaderPrintUniform.ush"
//float4 FontSize; // .xy character size, .zw character spacing (in normalized coordinates)
//int MaxValueCount; // maximum number of values that we can print in one frame
//int MaxSymbolCount; // maximum number of symbols (after conversion from characters) that we can print in one frame
static const float2 ShaderPrintCursorStart = float2(0.05f, 0.05f);
static const float ShaderPrintTabCount = 12.f;
// 'Global' values for tracking printing state (per thread)
static float2 ShaderPrintCursorPos = ShaderPrintCursorStart;
static bool ShaderPrintFilterEnable = true;
// --------------------------------------------------------------------------
// Internal helpers
void ShaderPrint_Internal(in FShaderPrintItem Item)
{
// If MaxValueCount is 0 then we don't reset the buffer counter so early out here
if (ShaderPrintUniform.MaxValueCount == 0)
{
return;
}
// Buffer counter is stored in first element .Value
int IndexToStore = 0;
InterlockedAdd(RWValuesBuffer[SHADER_PRINT_COUNT_OFFSET].Value, 1, IndexToStore);
// Prevent writing off the buffer
// Note that counter still increases so need clamp when reading it in later passes
if (IndexToStore >= ShaderPrintUniform.MaxValueCount)
{
return;
}
// Because counter is in first element, read/writes need to be offset by 1
RWValuesBuffer[IndexToStore + SHADER_PRINT_VALUE_OFFSET] = PackShaderPrintItem(Item);
}
void ShaderPrint_Internal(in float2 ScreenPos, in int Value, in FFontColor FontColor, in int Type)
{
FShaderPrintItem Item;
Item.ScreenPos = ScreenPos;
Item.Value = Value;
Item.Type = Type;
Item.Color = FontColor.Color;
ShaderPrint_Internal(Item);
}
// --------------------------------------------------------------------------
// Symbol printing
float2 ShaderPrintSymbol(in float2 ScreenPos, in int Symbol, in FFontColor Color)
{
if (ShaderPrintFilterEnable)
{
ShaderPrint_Internal(ScreenPos, Symbol, Color, SHADER_PRINT_TYPE_SYMBOL);
ScreenPos.x += ShaderPrintUniform.FontSize.z;
}
return ScreenPos;
}
float2 ShaderPrintSymbol(in float2 ScreenPos, in int Symbol)
{
return ShaderPrintSymbol(ScreenPos, Symbol, GetDefaultFontColor());
}
void ShaderPrintSymbol(in int symbol, in FFontColor Color)
{
ShaderPrintCursorPos = ShaderPrintSymbol(ShaderPrintCursorPos, symbol, Color);
}
void ShaderPrintSymbol(in int symbol)
{
ShaderPrintCursorPos = ShaderPrintSymbol(ShaderPrintCursorPos, symbol, GetDefaultFontColor());
}
// Function for reading global TEXT string.
// The data and function are generated by the shader compiler.
//float2 ShaderPrintText(float2 Pos, uint InTextEntry, float3 InColor);
GENERATED_SHADER_PRINT
float2 ShaderPrintHelloWorld(in float2 ScreenPos)
{
if (ShaderPrintFilterEnable)
{
ScreenPos = ShaderPrintSymbol(ScreenPos, _H_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _E_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _L_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _L_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _O_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _SPC_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _W_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _O_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _R_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _L_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _D_);
ScreenPos = ShaderPrintSymbol(ScreenPos, _SPC_);
}
return ScreenPos;
}
void ShaderPrintHelloWorld()
{
ShaderPrintCursorPos = ShaderPrintHelloWorld(ShaderPrintCursorPos);
}
// --------------------------------------------------------------------------
// Value printing (common value printing)
// float
float2 ShaderPrintValue(in float2 ScreenPos, in float Value, in FFontColor Color)
{
ShaderPrint_Internal(ScreenPos, asint(Value), Color, SHADER_PRINT_TYPE_FLOAT);
ScreenPos.x += ShaderPrintUniform.FontSize.z * ShaderPrintTabCount;
return ScreenPos;
}
// int
float2 ShaderPrintValue(in float2 ScreenPos, in int Value, in FFontColor Color)
{
ShaderPrint_Internal(ScreenPos, Value, Color, SHADER_PRINT_TYPE_INT);
ScreenPos.x += ShaderPrintUniform.FontSize.z * ShaderPrintTabCount;
return ScreenPos;
}
// uint
float2 ShaderPrintValue(in float2 ScreenPos, in uint Value, in FFontColor Color)
{
ShaderPrint_Internal(ScreenPos, asint(Value), Color, SHADER_PRINT_TYPE_UINT);
ScreenPos.x += ShaderPrintUniform.FontSize.z * ShaderPrintTabCount;
return ScreenPos;
}
// bool
float2 ShaderPrintValue(in float2 ScreenPos, in bool Value, in FFontColor Color)
{
ShaderPrint_Internal(ScreenPos, asint(Value ? 1u : 0u), Color, SHADER_PRINT_TYPE_UINT);
ScreenPos.x += ShaderPrintUniform.FontSize.z * ShaderPrintTabCount;
return ScreenPos;
}
// --------------------------------------------------------------------------
// Scalar type printing
#define SHADER_PRINT_OVERLOAD_1(InNumComponent, InType) \
float2 ShaderPrint(in float2 ScreenPos, in InType Value, in FFontColor Color) \
{ \
if (ShaderPrintFilterEnable) \
{ \
ScreenPos = ShaderPrintValue(ScreenPos, Value, Color); \
} \
return ScreenPos; \
} \
float2 ShaderPrint(in float2 ScreenPos, in InType Value) \
{ \
if (ShaderPrintFilterEnable) \
{ \
ScreenPos = ShaderPrint(ScreenPos, Value, GetDefaultFontColor()); \
} \
return ScreenPos; \
} \
void ShaderPrint(in InType Value, in FFontColor Color) \
{ \
if (ShaderPrintFilterEnable) \
{ \
ShaderPrintCursorPos = ShaderPrint(ShaderPrintCursorPos, Value, Color); \
} \
} \
void ShaderPrint(in InType Value) \
{ \
if (ShaderPrintFilterEnable) \
{ \
ShaderPrintCursorPos = ShaderPrint(ShaderPrintCursorPos, Value, GetDefaultFontColor()); \
} \
}
// --------------------------------------------------------------------------
// Vector type printing
#define SHADER_PRINT_OVERLOAD_N(InNumComponent, InType) \
float2 ShaderPrint(in float2 ScreenPos, in InType Value, in FFontColor Color) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompIt = 0; CompIt < InNumComponent; ++CompIt) \
{ \
ScreenPos = ShaderPrintValue(ScreenPos, Value[CompIt], Color); \
} \
} \
return ScreenPos; \
} \
float2 ShaderPrint(in float2 ScreenPos, in InType Value) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompIt=0;CompIt<InNumComponent;++CompIt) \
{ \
ScreenPos = ShaderPrint(ScreenPos, Value[CompIt], GetDefaultFontColor()); \
} \
} \
return ScreenPos; \
} \
void ShaderPrint(in InType Value, in FFontColor Color) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompIt=0;CompIt<InNumComponent;++CompIt) \
{ \
ShaderPrintCursorPos = ShaderPrint(ShaderPrintCursorPos, Value[CompIt], Color); \
} \
} \
} \
void ShaderPrint(in InType Value) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompIt=0;CompIt<InNumComponent;++CompIt) \
{ \
ShaderPrintCursorPos = ShaderPrint(ShaderPrintCursorPos, Value[CompIt], GetDefaultFontColor()); \
} \
} \
}
SHADER_PRINT_OVERLOAD_1(1, float)
SHADER_PRINT_OVERLOAD_N(2, float2)
SHADER_PRINT_OVERLOAD_N(3, float3)
SHADER_PRINT_OVERLOAD_N(4, float4)
SHADER_PRINT_OVERLOAD_1(1, uint)
SHADER_PRINT_OVERLOAD_N(2, uint2)
SHADER_PRINT_OVERLOAD_N(3, uint3)
SHADER_PRINT_OVERLOAD_N(4, uint4)
SHADER_PRINT_OVERLOAD_1(1, int)
SHADER_PRINT_OVERLOAD_N(2, int2)
SHADER_PRINT_OVERLOAD_N(3, int3)
SHADER_PRINT_OVERLOAD_N(4, int4)
SHADER_PRINT_OVERLOAD_1(1, bool)
// --------------------------------------------------------------------------
// Matrix type printing
#define SHADER_PRINT_OVERLOAD_NN(InNumComponentX, InNumComponentY, InType) \
float2 ShaderPrint(in float2 ScreenPos, in InType Value, in FFontColor Color) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompY=0;CompY<InNumComponentY;++CompY) \
{ \
ScreenPos = ShaderPrint(ScreenPos, Value[CompY], Color); \
ScreenPos += float2(0.f, ShaderPrintUniform.FontSize.w); \
} \
} \
return ScreenPos; \
} \
float2 ShaderPrint(in float2 ScreenPos, in InType Value) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompY = 0; CompY < InNumComponentY; ++CompY) \
{ \
ScreenPos = ShaderPrint(ScreenPos, Value[CompY], GetDefaultFontColor()); \
ScreenPos += float2(0.f, ShaderPrintUniform.FontSize.w); \
} \
} \
return ScreenPos; \
} \
void ShaderPrint(in InType Value, in FFontColor Color) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompY = 0; CompY < InNumComponentY; ++CompY) \
{ \
ShaderPrintCursorPos = ShaderPrint(ShaderPrintCursorPos, Value[CompY], Color); \
ShaderPrintCursorPos += float2(0.f, ShaderPrintUniform.FontSize.w); \
} \
} \
} \
void ShaderPrint(in InType Value) \
{ \
if (ShaderPrintFilterEnable) \
{ \
UNROLL \
for (uint CompY = 0; CompY < InNumComponentY; ++CompY) \
{ \
ShaderPrintCursorPos = ShaderPrint(ShaderPrintCursorPos, Value[CompY], GetDefaultFontColor()); \
ShaderPrintCursorPos += float2(0.f, ShaderPrintUniform.FontSize.w); \
} \
} \
}
SHADER_PRINT_OVERLOAD_NN(3, 3, float3x3)
SHADER_PRINT_OVERLOAD_NN(4, 3, float4x3)
SHADER_PRINT_OVERLOAD_NN(4, 4, float4x4)
// --------------------------------------------------------------------------
// Formating helpers
float2 ShaderPrintSpace(in float2 ScreenPos, in float Count = 1)
{
if (ShaderPrintFilterEnable)
{
ScreenPos.x += ShaderPrintUniform.FontSize.z * Count;
}
return ScreenPos;
}
void ShaderPrintSpace(in float Count = 1)
{
ShaderPrintCursorPos = ShaderPrintSpace(ShaderPrintCursorPos, Count);
}
float2 ShaderPrintNewline(in float2 ScreenPos)
{
if (ShaderPrintFilterEnable)
{
ScreenPos.x = ShaderPrintCursorStart.x;
ScreenPos.y += ShaderPrintUniform.FontSize.w;
}
return ScreenPos;
}
void ShaderPrintNewline()
{
ShaderPrintCursorPos = ShaderPrintNewline(ShaderPrintCursorPos);
}
float2 ShaderPrintGetCursorPos()
{
return ShaderPrintCursorPos;
}
float2 ShaderPrintSetCursorPos(in float2 ScreenPos)
{
float2 PrevScreenPos = ShaderPrintCursorPos;
ShaderPrintCursorPos = ScreenPos;
return PrevScreenPos;
}
// --------------------------------------------------------------------------
// Filter helpers
// Use these to restrict ShaderPrint to a subset of active threads
// The filter functions can be called once at the start of the shader to filter all later printing
//
// Example use cases would be:
//
// ShaderPrintFilter(all(SvPosition.xy == float2(100, 100)));
// to debug a single pixel
//
// ShaderPrintFilter(all(DispatchThreadId == uint3(0, 0, 0)));
// to debug a single compute shader thread
//
// ShaderPrintFilterOneThread()
// to debug a single random active thread
// Note that ShaderPrintFilterOneThread() only works for one shader invocation in a view since it relies on a global memory location
void ShaderPrintFilter(bool bFilter)
{
ShaderPrintFilterEnable = bFilter;
}
void ShaderPrintFilterOneThread()
{
// Atomic flag is stored in first element .Type Value
uint PrevValue;
InterlockedCompareExchange(RWValuesBuffer[SHADER_PRINT_COUNT_OFFSET].TypeAndColor, 0, 1, PrevValue);
ShaderPrintFilter(PrevValue == 0);
}