Prep for rhi

Many changes to add in support for Unreal RHI
This is the first step. Afterwords we need more changes such as finalizing the for_unreal switch to premake.

Diffs=
1cc5f2b6f Prep for rhi (#8270)

Co-authored-by: Jonathon Copeland <jcopela4@gmail.com>
This commit is contained in:
blakdragan7
2024-10-10 00:00:05 +00:00
parent 84519b5114
commit fc31e5e757
116 changed files with 3544 additions and 158 deletions

View File

@@ -1 +1 @@
f9715435dd9605d0c9636088d69ef684b819ac81
1cc5f2b6f6cf02d15bcb3654343e4f3322a95402

View File

@@ -40,7 +40,6 @@ project('rive')
do
kind('StaticLib')
language('C++')
cppdialect('C++11')
targetdir('%{cfg.system}/bin/%{cfg.buildcfg}')
objdir('%{cfg.system}/obj/%{cfg.buildcfg}')
includedirs({
@@ -57,6 +56,17 @@ do
flags({ 'FatalCompileWarnings' })
filter({ 'options:for_unreal' })
do
cppdialect('C++17')
defines({ '_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR' })
end
filter({ 'options:not for_unreal' })
do
cppdialect('C++11')
end
filter({ 'system:macosx' })
do
buildoptions({

View File

@@ -102,6 +102,11 @@ newoption({
description = 'Don\'t build with link time optimizations.',
})
newoption({
trigger = 'for_unreal',
description = 'compile for unreal engine',
})
location(RIVE_BUILD_OUT)
targetdir(RIVE_BUILD_OUT)
objdir(RIVE_BUILD_OUT .. '/obj')
@@ -165,39 +170,49 @@ newoption({
-- This is just to match our old windows config. Rive Native specifically sets
-- static/dynamic and maybe we should do the same elsewhere.
filter({ 'system:windows', 'options:windows_runtime=default' })
filter({ 'system:windows', 'options:windows_runtime=default', 'options:not for_unreal' })
do
staticruntime('on') -- Match Skia's /MT flag for link compatibility
runtime('Release')
end
filter({ 'system:windows', 'options:windows_runtime=static' })
filter({ 'system:windows', 'options:windows_runtime=static', 'options:not for_unreal' })
do
staticruntime('on') -- Match Skia's /MT flag for link compatibility
end
filter({ 'system:windows', 'options:windows_runtime=dynamic' })
filter({ 'system:windows', 'options:windows_runtime=dynamic', 'options:not for_unreal' })
do
staticruntime('off')
end
filter({ 'system:windows', 'options:not windows_runtime=default', 'options:config=debug' })
filter({
'system:windows',
'options:not windows_runtime=default',
'options:config=debug',
'options:not for_unreal',
})
do
runtime('Debug')
end
filter({ 'system:windows', 'options:not windows_runtime=default', 'options:config=release' })
filter({
'system:windows',
'options:not windows_runtime=default',
'options:config=release',
'options:not for_unreal',
})
do
runtime('Release')
end
filter({ 'system:windows', 'options:windows_runtime=dynamic_debug' })
filter({ 'system:windows', 'options:windows_runtime=dynamic_debug', 'options:not for_unreal' })
do
staticruntime('off')
runtime('Debug')
end
filter({ 'system:windows', 'options:windows_runtime=dynamic_release' })
filter({ 'system:windows', 'options:windows_runtime=dynamic_release', 'options:not for_unreal' })
do
staticruntime('off')
runtime('Release')
@@ -209,6 +224,12 @@ do
defines({ '_USE_MATH_DEFINES', 'NOMINMAX' })
end
filter({ 'system:windows', 'options:for_unreal' })
do
staticruntime('off')
runtime('Release')
end
filter({ 'system:windows', 'options:toolset=clang' })
do
buildoptions({
@@ -361,31 +382,62 @@ if _OPTIONS['os'] == 'android' then
'-static-libstdc++',
})
filter('options:arch=x86')
filter({ 'options:arch=x86', 'options:not for_unreal' })
do
architecture('x86')
buildoptions({ '--target=i686-none-linux-android21' })
linkoptions({ '--target=i686-none-linux-android21' })
end
filter('options:arch=x64')
filter({ 'options:arch=x86', 'options:for_unreal' })
do
architecture('x86')
buildoptions({ '--target=i686-none-linux-android31' })
linkoptions({ '--target=i686-none-linux-android31' })
end
filter({ 'options:arch=x64', 'options:not for_unreal' })
do
architecture('x64')
buildoptions({ '--target=x86_64-none-linux-android21' })
linkoptions({ '--target=x86_64-none-linux-android21' })
end
filter('options:arch=arm')
filter({ 'options:arch=x64', 'options:for_unreal' })
do
architecture('x64')
buildoptions({ '--target=x86_64-none-linux-androi31' })
linkoptions({ '--target=x86_64-none-linux-android31' })
end
filter({ 'options:arch=arm', 'options:not for_unreal' })
do
architecture('arm')
buildoptions({ '--target=armv7a-none-linux-android21' })
linkoptions({ '--target=armv7a-none-linux-android21' })
end
filter('options:arch=arm64')
filter({ 'options:arch=arm', 'options:for_unreal' })
do
architecture('arm')
buildoptions({ '--target=armv7a-none-linux-android31' })
linkoptions({ '--target=armv7a-none-linux-android31' })
end
filter({ 'options:arch=arm64', 'options:not for_unreal' })
do
architecture('arm64')
buildoptions({ '--target=aarch64-none-linux-android21' })
linkoptions({ '--target=aarch64-none-linux-android21' })
end
filter({ 'options:arch=arm64', 'options:for_unreal' })
do
architecture('arm64')
buildoptions({ '--target=aarch64-none-linux-android31' })
linkoptions({ '--target=aarch64-none-linux-android31' })
end
filter({})
end

View File

@@ -209,30 +209,61 @@ if _OPTIONS['os'] == 'android' then
})
pic('on') -- Position-independent code is required for NDK libraries.
filter('options:arch=x86')
filter({ 'options:arch=x86', 'options:not for_unreal' })
do
architecture('x86')
buildoptions({ '--target=i686-none-linux-android21' })
linkoptions({ '--target=i686-none-linux-android21' })
end
filter('options:arch=x64')
filter({ 'options:arch=x86', 'options:for_unreal' })
do
architecture('x86')
buildoptions({ '--target=i686-none-linux-android31' })
linkoptions({ '--target=i686-none-linux-android31' })
end
filter({ 'options:arch=x64', 'options:not for_unreal' })
do
architecture('x64')
buildoptions({ '--target=x86_64-none-linux-android21' })
linkoptions({ '--target=x86_64-none-linux-android21' })
end
filter('options:arch=arm')
filter({ 'options:arch=x64', 'options:for_unreal' })
do
architecture('x64')
buildoptions({ '--target=x86_64-none-linux-androi31' })
linkoptions({ '--target=x86_64-none-linux-android31' })
end
filter({ 'options:arch=arm', 'options:not for_unreal' })
do
architecture('arm')
buildoptions({ '--target=armv7a-none-linux-android21' })
linkoptions({ '--target=armv7a-none-linux-android21' })
end
filter('options:arch=arm64')
filter({ 'options:arch=arm', 'options:for_unreal' })
do
architecture('arm')
buildoptions({ '--target=armv7a-none-linux-android31' })
linkoptions({ '--target=armv7a-none-linux-android31' })
end
filter({ 'options:arch=arm64', 'options:not for_unreal' })
do
architecture('arm64')
buildoptions({ '--target=aarch64-none-linux-android21' })
linkoptions({ '--target=aarch64-none-linux-android21' })
end
filter({ 'options:arch=arm64', 'options:for_unreal' })
do
architecture('arm64')
buildoptions({ '--target=aarch64-none-linux-android31' })
linkoptions({ '--target=aarch64-none-linux-android31' })
end
filter({})
end

View File

@@ -264,7 +264,7 @@ do
})
end
filter('options:config=release')
filter({ 'options:config=release', 'options:not for_unreal' })
do
optimize('Size')
end

View File

@@ -56,6 +56,10 @@ do
filter('options:config=release')
do
defines({ 'SB_CONFIG_UNITY' })
end
filter({ 'options:config=release', 'options:not for_unreal' })
do
optimize('Size')
end

View File

@@ -37,7 +37,6 @@ dofile(path.join(dependencies, 'premake5_yoga_v2.lua'))
project('rive')
do
kind('StaticLib')
cppdialect('C++11')
includedirs({
'include',
harfbuzz .. '/src',
@@ -58,7 +57,17 @@ do
files({ 'src/**.cpp' })
filter('options:not for_unreal')
do
cppdialect('C++11')
flags({ 'FatalCompileWarnings' })
end
filter({ 'options:for_unreal' })
do
cppdialect('C++17')
defines({ '_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR' })
end
filter({ 'options:with_rive_text', 'options:not no-harfbuzz-renames' })
do

View File

@@ -94,28 +94,31 @@ nproc = nproc:gsub('%s+', '') -- remove whitespace
local python_ply = dependency.github('dabeaz/ply', '5c4dc94d4c6d059ec127ee1493c735963a5d2645')
local pls_generated_headers = RIVE_BUILD_OUT .. '/include'
local pls_shaders_absolute_dir = path.getabsolute(pls_generated_headers .. '/generated/shaders')
local makecommand
if os.host() == 'windows' then
makecommand = '"set PYTHONPATH=' .. python_ply .. '/src" && '
else
makecommand = 'PYTHONPATH="' .. python_ply .. '/src" '
end
makecommand = makecommand
.. 'make -C '
local makecommand = 'make -C '
.. path.getabsolute('src/shaders')
.. ' -j'
.. nproc
.. ' OUT='
.. pls_shaders_absolute_dir
local minify_flags = '-p ' .. python_ply .. '/src'
newoption({
trigger = 'raw_shaders',
description = 'don\'t rename shader variables, or remove whitespace or comments',
})
if _OPTIONS['raw_shaders'] then
makecommand = makecommand .. ' FLAGS=--human-readable'
minify_flags = minify_flags .. ' --human-readable'
end
local minified_extension = 'glsl'
if _OPTIONS['for_unreal'] then
minified_extension = 'ush'
end
minify_flags = minify_flags .. ' --minified-extension=' .. minified_extension
makecommand = makecommand .. ' FLAGS="' .. minify_flags .. '"'
if os.host() == 'macosx' then
if _OPTIONS['os'] == 'ios' and _OPTIONS['variant'] == 'system' then
makecommand = makecommand .. ' rive_pls_ios_metallib'

View File

@@ -7,7 +7,14 @@
#ifdef @VERTEX
ATTR_BLOCK_BEGIN(Attrs)
#ifdef SPLIT_UINT4_ATTRIBUTES
ATTR(0, uint, @a_spanX);
ATTR(1, uint, @a_y);
ATTR(2, uint, @a_color0);
ATTR(3, uint, @a_color1);
#else
ATTR(0, uint4, @a_span); // [spanX, y, color0, color1]
#endif
ATTR_BLOCK_END
#endif
@@ -30,8 +37,15 @@ half4 unpackColorInt(uint color)
VERTEX_MAIN(@colorRampVertexMain, Attrs, attrs, _vertexID, _instanceID)
{
#ifdef SPLIT_UINT4_ATTRIBUTES
ATTR_UNPACK(_instanceID, attrs, @a_spanX, uint);
ATTR_UNPACK(_instanceID, attrs, @a_y, uint);
ATTR_UNPACK(_instanceID, attrs, @a_color0, uint);
ATTR_UNPACK(_instanceID, attrs, @a_color1, uint);
uint4 @a_span = uint4(@a_spanX, @a_y, @a_color0, @a_color1);
#else
ATTR_UNPACK(_instanceID, attrs, @a_span, uint4);
#endif
VARYING_INIT(v_rampColor, half4);
float x = float((_vertexID & 1) == 0 ? @a_span.x & 0xffffu : @a_span.x >> 16) / 65536.;

View File

@@ -3,7 +3,6 @@
*/
// Common functions shared by multiple shaders.
#define PI float(3.141592653589793238)
#ifndef @USING_DEPTH_STENCIL
@@ -138,6 +137,8 @@ INLINE half min_value(half4 min4)
INLINE float manhattan_width(float2 x) { return abs(x.x) + abs(x.y); }
#ifdef @VERTEX
#ifndef $UNIFORM_DEFINITIONS_AUTO_GENERATED
UNIFORM_BLOCK_BEGIN(FLUSH_UNIFORM_BUFFER_IDX, @FlushUniforms)
float gradInverseViewportY;
float tessInverseViewportY;
@@ -151,6 +152,7 @@ int4 renderTargetUpdateBounds; // drawBounds, or renderTargetBounds if there is
uint pathIDGranularity; // Spacing between adjacent path IDs (1 if IEEE compliant).
float vertexDiscardValue;
UNIFORM_BLOCK_END(uniforms)
#endif
#define RENDER_TARGET_COORD_TO_CLIP_COORD(COORD) \
float4((COORD).x* uniforms.renderTargetInverseViewportX - 1., \
@@ -218,6 +220,7 @@ INLINE void set_clip_rect_plane_distances(float2x2 clipRectInverseMatrix,
#endif // VERTEX
#ifdef @DRAW_IMAGE
#ifndef $UNIFORM_DEFINITIONS_AUTO_GENERATED
UNIFORM_BLOCK_BEGIN(IMAGE_DRAW_UNIFORM_BUFFER_IDX, @ImageDrawUniforms)
float4 viewMatrix;
float2 translate;
@@ -232,3 +235,4 @@ uint blendMode;
uint zIndex;
UNIFORM_BLOCK_END(imageDrawUniforms)
#endif
#endif

View File

@@ -1,7 +1,6 @@
import argparse
import glob
import os
import ply.lex as lex
import re
import sys
from collections import defaultdict
@@ -36,8 +35,16 @@ parser.add_argument("-o", "--outdir", required=True,
help="OUTPUT directory to store the header files")
parser.add_argument("-H", "--human-readable", action='store_true',
help="don't rename or strip out comments or whitespace")
parser.add_argument("-e", "--minified-extension", type=str, default="glsl",
help="use this extension for minified files")
parser.add_argument("-p", "--ply-path", required=True, type=str, help="path to ply module")
args = parser.parse_args()
sys.path.append(args.ply_path)
import ply.lex as lex
# tokens used by PLY to run lexical analysis on our glsl files.
tokens = [
"DEFINE",
@@ -539,6 +546,7 @@ class Minifier:
out.write('#pragma once\n\n')
for exp in sorted(self.exports):
out.write('#define GLSL_%s "%s"\n' % (exp[1:], new_names[exp]))
out.write('#define GLSL_%s_raw %s\n' % (exp[1:], new_names[exp]))
out.close()
@@ -568,7 +576,7 @@ class Minifier:
def write_offline_glsl(self, outdir):
output_path = os.path.join(outdir, os.path.splitext(self.basename)[0] + ".minified.glsl")
output_path = os.path.join(outdir, os.path.splitext(self.basename)[0] + ".minified." + args.minified_extension)
print("Minifying %s <- %s" % (output_path, self.basename))
out = open(output_path, "w", newline='\n')
self.emit_tokens_to_rewritten_glsl(out, preserve_exported_switches=True)

View File

@@ -0,0 +1,355 @@
/*
* Copyright 2023 Rive
*/
// This header provides GLSL-specific #defines and declarations that enable our shaders to be
// compiled on MSL and GLSL both.
// HLSL warns that it will unroll the loops through r,g,b values in advanced_blend.glsl, but
// unrolling these loops is exactly what we want.
#pragma $warning($disable : 3550)
// Don't warn about uninitialized variables. If we leave one uninitialized it's because we know what
// we're doing and don't want to pay the cost of initializing it.
#pragma $warning($disable : 4000)
// #define native hlsl types if their names are being rewritten.
#define _ARE_TOKEN_NAMES_PRESERVED
#ifndef $_ARE_TOKEN_NAMES_PRESERVED
#define half $half
#define half2 $half2
#define half3 $half3
#define half4 $half4
#define short $short
#define short2 $short2
#define short3 $short3
#define short4 $short4
#define ushort $ushort
#define ushort2 $ushort2
#define ushort3 $ushort3
#define ushort4 $ushort4
#define float2 $float2
#define float3 $float3
#define float4 $float4
#define bool2 $bool2
#define bool3 $bool3
#define bool4 $bool4
#define uint2 $uint2
#define uint3 $uint3
#define uint4 $uint4
#define int2 $int2
#define int3 $int3
#define int4 $int4
#define float4x2 $float4x2
#define ushort $ushort
#define float2x2 $float2x2
#define half3x4 $half3x4
#endif
$typedef float3 packed_float3;
#ifdef @ENABLE_MIN_16_PRECISION
$typedef $min16uint ushort;
#else
$typedef $uint ushort;
#endif
#define SPLAT(A, B) A##B
#define INLINE $inline
#define OUT(ARG_TYPE) out ARG_TYPE
#define ATTR_BLOCK_BEGIN(NAME) \
struct NAME \
{
#define ATTR(IDX, TYPE, NAME) TYPE NAME : SPLAT(ATTRIBUTE, IDX)
#define ATTR_BLOCK_END \
} \
;
#define ATTR_LOAD(T, A, N, I)
#define ATTR_UNPACK(ID, attrs, NAME, TYPE) TYPE NAME = attrs.NAME
#define UNIFORM_BUFFER_REGISTER(IDX) $register(SPLAT($b, IDX))
#define UNIFORM_BLOCK_BEGIN(IDX, NAME) \
$cbuffer NAME : UNIFORM_BUFFER_REGISTER(IDX) \
{ \
struct \
{
#define UNIFORM_BLOCK_END(NAME) \
} \
NAME; \
}
#define VARYING_BLOCK_BEGIN \
struct Varyings \
{
#define NO_PERSPECTIVE $noperspective
#define @OPTIONALLY_FLAT $nointerpolation
#define FLAT $nointerpolation
#define VARYING(IDX, TYPE, NAME) TYPE NAME : SPLAT($TEXCOORD, IDX)
#define VARYING_BLOCK_END \
float4 _pos : $SV_Position; \
} \
;
#define VARYING_INIT(NAME, TYPE) TYPE NAME
#define VARYING_PACK(NAME) _varyings.NAME = NAME
#define VARYING_UNPACK(NAME, TYPE) TYPE NAME = _varyings.NAME
#ifdef @VERTEX
#define VERTEX_TEXTURE_BLOCK_BEGIN
#define VERTEX_TEXTURE_BLOCK_END
#endif
#ifdef @FRAGMENT
#define FRAG_TEXTURE_BLOCK_BEGIN
#define FRAG_TEXTURE_BLOCK_END
#endif
#define TEXTURE_RGBA32UI(SET, IDX, NAME) uniform $Texture2D<uint4> NAME : $register(SPLAT($t, IDX))
#define TEXTURE_RGBA32F(SET, IDX, NAME) uniform $Texture2D<float4> NAME : $register(SPLAT($t, IDX))
#define TEXTURE_RGBA8(SET, IDX, NAME) \
uniform $Texture2D<$unorm float4> NAME : $register(SPLAT($t, IDX))
// SAMPLER_LINEAR and SAMPLER_MIPMAP are the same because in d3d11, sampler parameters are defined
// at the API level.
#define SAMPLER(TEXTURE_IDX, NAME) $SamplerState NAME : $register(SPLAT($s, TEXTURE_IDX));
#define SAMPLER_LINEAR SAMPLER
#define SAMPLER_MIPMAP SAMPLER
#define TEXEL_FETCH(NAME, COORD) NAME[COORD]
#define TEXTURE_SAMPLE(NAME, SAMPLER_NAME, COORD) NAME.$Sample(SAMPLER_NAME, COORD)
#define TEXTURE_SAMPLE_LOD(NAME, SAMPLER_NAME, COORD, LOD) \
NAME.$SampleLevel(SAMPLER_NAME, COORD, LOD)
#define TEXTURE_SAMPLE_GRAD(NAME, SAMPLER_NAME, COORD, DDX, DDY) \
NAME.$SampleGrad(SAMPLER_NAME, COORD, DDX, DDY)
#define PLS_INTERLOCK_BEGIN
#define PLS_INTERLOCK_END
#ifdef @ENABLE_RASTERIZER_ORDERED_VIEWS
#define PLS_TEX2D $RasterizerOrderedTexture2D
#else
#define PLS_TEX2D $RWTexture2D
#endif
#define PLS_BLOCK_BEGIN
#ifdef @ENABLE_TYPED_UAV_LOAD_STORE
#define PLS_DECL4F(IDX, NAME) uniform PLS_TEX2D<$unorm half4> NAME : $register($SPLAT(u, IDX))
#else
#define PLS_DECL4F(IDX, NAME) uniform PLS_TEX2D<uint> NAME : $register(SPLAT($u, IDX))
#endif
#define PLS_DECLUI(IDX, NAME) uniform PLS_TEX2D<uint> NAME : $register(SPLAT($u, IDX))
#define PLS_DECLUI_ATOMIC PLS_DECLUI
#define PLS_LOADUI_ATOMIC PLS_LOADUI
#define PLS_STOREUI_ATOMIC PLS_STOREUI
#define PLS_BLOCK_END
#ifdef @ENABLE_TYPED_UAV_LOAD_STORE
#define PLS_LOAD4F(PLANE) PLANE[_plsCoord]
#else
#define PLS_LOAD4F(PLANE) unpackUnorm4x8(PLANE[_plsCoord])
#endif
#define PLS_LOADUI(PLANE) PLANE[_plsCoord]
#ifdef @ENABLE_TYPED_UAV_LOAD_STORE
#define PLS_STORE4F(PLANE, VALUE) PLANE[_plsCoord] = (VALUE)
#else
#define PLS_STORE4F(PLANE, VALUE) PLANE[_plsCoord] = packUnorm4x8(VALUE)
#endif
#define PLS_STOREUI(PLANE, VALUE) PLANE[_plsCoord] = (VALUE)
INLINE uint pls_atomic_max(PLS_TEX2D<uint> plane, int2 _plsCoord, uint x)
{
uint originalValue;
$InterlockedMax(plane[_plsCoord], x, originalValue);
return originalValue;
}
#define PLS_ATOMIC_MAX(PLANE, X) pls_atomic_max(PLANE, _plsCoord, X)
INLINE uint pls_atomic_add(PLS_TEX2D<uint> plane, int2 _plsCoord, uint x)
{
uint originalValue;
$InterlockedAdd(plane[_plsCoord], x, originalValue);
return originalValue;
}
#define PLS_ATOMIC_ADD(PLANE, X) pls_atomic_add(PLANE, _plsCoord, X)
#define PLS_PRESERVE_4F(PLANE)
#define PLS_PRESERVE_UI(PLANE)
#define VERTEX_CONTEXT_DECL
#define VERTEX_CONTEXT_UNPACK
#define VERTEX_MAIN(NAME, Attrs, attrs, _vertexID, _instanceID) \
\
uint $baseInstance; \
\
Varyings NAME(Attrs attrs, uint _vertexID \
: $SV_VertexID, uint _instanceIDWithoutBase \
: $SV_InstanceID) \
{ \
uint _instanceID = _instanceIDWithoutBase + $baseInstance; \
Varyings _varyings;
#define IMAGE_RECT_VERTEX_MAIN(NAME, Attrs, attrs, _vertexID, _instanceID) \
Varyings NAME(Attrs attrs, uint _vertexID : $SV_VertexID) \
{ \
Varyings _varyings; \
float4 _pos;
#define IMAGE_MESH_VERTEX_MAIN(NAME, PositionAttr, position, UVAttr, uv, _vertexID) \
Varyings NAME(PositionAttr position, UVAttr uv, uint _vertexID : $SV_VertexID) \
{ \
Varyings _varyings; \
float4 _pos;
#define EMIT_VERTEX(POSITION) \
_varyings._pos = POSITION; \
} \
return _varyings;
#define FRAG_DATA_MAIN(DATA_TYPE, NAME) \
DATA_TYPE NAME(Varyings _varyings) : $SV_Target \
{
#define EMIT_FRAG_DATA(VALUE) \
return VALUE; \
}
#define FRAGMENT_CONTEXT_DECL , float2 _fragCoord
#define FRAGMENT_CONTEXT_UNPACK , _fragCoord
#define PLS_CONTEXT_DECL , int2 _plsCoord
#define PLS_CONTEXT_UNPACK , _plsCoord
#define PLS_MAIN(NAME) [$earlydepthstencil] void NAME(Varyings _varyings) { \
float2 _fragCoord = _varyings._pos.xy;\
int2 _plsCoord = int2(floor(_fragCoord));
#define PLS_MAIN_WITH_IMAGE_UNIFORMS(NAME) PLS_MAIN(NAME)
#define EMIT_PLS }
#define PLS_FRAG_COLOR_MAIN(NAME) \
[$earlydepthstencil] half4 NAME(Varyings _varyings) : $SV_Target \
{ \
float2 _fragCoord = _varyings._pos.xy; \
int2 _plsCoord = int2(floor(_fragCoord)); \
half4 _fragColor;
#define PLS_FRAG_COLOR_MAIN_WITH_IMAGE_UNIFORMS(NAME) PLS_FRAG_COLOR_MAIN(NAME)
#define EMIT_PLS_AND_FRAG_COLOR \
} \
return _fragColor;
#define uintBitsToFloat $asfloat
#define intBitsToFloat $asfloat
#define floatBitsToInt $asint
#define floatBitsToUint $asuint
#define inversesqrt $rsqrt
#define notEqual(A, B) ((A) != (B))
#define lessThanEqual(A, B) ((A) <= (B))
#define greaterThanEqual(A, B) ((A) >= (B))
// HLSL matrices are stored in row-major order, and therefore transposed from their counterparts
// in GLSL and Metal. We can work around this entirely by reversing the arguments to mul().
#define MUL(A, B) $mul(B, A)
#define VERTEX_STORAGE_BUFFER_BLOCK_BEGIN
#define VERTEX_STORAGE_BUFFER_BLOCK_END
#define FRAG_STORAGE_BUFFER_BLOCK_BEGIN
#define FRAG_STORAGE_BUFFER_BLOCK_END
#define STORAGE_BUFFER_U32x2(IDX, GLSL_STRUCT_NAME, NAME) \
$StructuredBuffer<uint2> NAME : $register(SPLAT($t, IDX))
#define STORAGE_BUFFER_U32x4(IDX, GLSL_STRUCT_NAME, NAME) \
$StructuredBuffer<uint4> NAME : $register(SPLAT($t, IDX))
#define STORAGE_BUFFER_F32x4(IDX, GLSL_STRUCT_NAME, NAME) \
$StructuredBuffer<float4> NAME : $register(SPLAT($t, IDX))
#define STORAGE_BUFFER_LOAD4(NAME, I) NAME[I]
#define STORAGE_BUFFER_LOAD2(NAME, I) NAME[I]
INLINE half2 unpackHalf2x16(uint u)
{
uint y = (u >> 16);
uint x = u & 0xffffu;
return half2($f16tof32(x), $f16tof32(y));
}
INLINE uint packHalf2x16(float2 v)
{
uint x = $f32tof16(v.x);
uint y = $f32tof16(v.y);
return (y << 16) | x;
}
INLINE half4 unpackUnorm4x8(uint u)
{
uint4 vals = uint4(u & 0xffu, (u >> 8) & 0xffu, (u >> 16) & 0xffu, u >> 24);
return half4(vals) * (1. / 255.);
}
INLINE uint packUnorm4x8(half4 color)
{
uint4 vals = (uint4(color * 255.) & 0xff) << uint4(0, 8, 16, 24);
vals.rg |= vals.ba;
vals.r |= vals.g;
return vals.r;
}
INLINE float atan(float y, float x) { return $atan2(y, x); }
INLINE float2x2 inverse(float2x2 m)
{
float2x2 adjoint = float2x2(m[1][1], -m[0][1], -m[1][0], m[0][0]);
return adjoint * (1. / determinant(m));
}
// Redirects for intrinsics that have different names in HLSL
INLINE float mix(float x, float y, float s) { return $lerp(x, y, s); }
INLINE float2 mix(float2 x, float2 y, float2 s) { return $lerp(x, y, s); }
INLINE float3 mix(float3 x, float3 y, float3 s) { return $lerp(x, y, s); }
INLINE float4 mix(float4 x, float4 y, float4 s) { return $lerp(x, y, s); }
INLINE float fract(float x) { return $frac(x); }
INLINE float2 fract(float2 x) { return $frac(x); }
INLINE float3 fract(float3 x) { return $frac(x); }
INLINE float4 fract(float4 x) { return $frac(x); }
// Reimplement intrinsics for half types.
// This shadows the intrinsic function for floats, so we also have to declare that overload.
INLINE float rive_sign(float x) { return sign(x); }
INLINE float2 rive_sign(float2 x) { return sign(x); }
INLINE float3 rive_sign(float3 x) { return sign(x); }
INLINE float4 rive_sign(float4 x) { return sign(x); }
#define sign rive_sign
INLINE float rive_abs(float x) { return abs(x); }
INLINE float2 rive_abs(float2 x) { return abs(x); }
INLINE float3 rive_abs(float3 x) { return abs(x); }
INLINE float4 rive_abs(float4 x) { return abs(x); }
#define abs rive_abs
INLINE float rive_sqrt(float x) { return sqrt(x); }
INLINE float2 rive_sqrt(float2 x) { return sqrt(x); }
INLINE float3 rive_sqrt(float3 x) { return sqrt(x); }
INLINE float4 rive_sqrt(float4 x) { return sqrt(x); }
#define sqrt rive_sqrt

View File

@@ -16,7 +16,14 @@ ATTR_BLOCK_BEGIN(Attrs)
ATTR(0, float4, @a_p0p1_); // End in '_' because D3D interprets the '1' as a semantic index.
ATTR(1, float4, @a_p2p3_);
ATTR(2, float4, @a_joinTan_and_ys); // [joinTangent, y, reflectionY]
#ifdef SPLIT_UINT4_ATTRIBUTES
ATTR(3, uint, @a_x0x1);
ATTR(4, uint, @a_reflectionX0X1);
ATTR(5, uint, @a_segmentCounts);
ATTR(6, uint, @a_contourIDWithFlags);
#else
ATTR(3, uint4, @a_args); // [x0x1, reflectionX0X1, segmentCounts, contourIDWithFlags]
#endif
ATTR_BLOCK_END
#endif
@@ -61,7 +68,16 @@ VERTEX_MAIN(@tessellateVertexMain, Attrs, attrs, _vertexID, _instanceID)
ATTR_UNPACK(_instanceID, attrs, @a_p0p1_, float4);
ATTR_UNPACK(_instanceID, attrs, @a_p2p3_, float4);
ATTR_UNPACK(_instanceID, attrs, @a_joinTan_and_ys, float4);
#ifdef SPLIT_UINT4_ATTRIBUTES
ATTR_UNPACK(_instanceID, attrs, @a_x0x1, uint);
ATTR_UNPACK(_instanceID, attrs, @a_reflectionX0X1, uint);
ATTR_UNPACK(_instanceID, attrs, @a_segmentCounts, uint);
ATTR_UNPACK(_instanceID, attrs, @a_contourIDWithFlags, uint);
uint4 @a_args = uint4(@a_x0x1, @a_reflectionX0X1, @a_segmentCounts, @a_contourIDWithFlags);
#else
ATTR_UNPACK(_instanceID, attrs, @a_args, uint4);
#endif
VARYING_INIT(v_p0p1, float4);
VARYING_INIT(v_p2p3, float4);

View File

@@ -0,0 +1,14 @@
#pragma once
#define USING_PLS_STORAGE_TEXTURES 1
#define ENABLE_TYPED_UAV_LOAD_STORE 1
#define UNIFORM_DEFINITIONS_AUTO_GENERATED 1
#define OPTIONALLY_FLAT flat
#include "/Engine/Generated/GeneratedUniformBuffers.ush"
#include "parse_environment.ush"
#include "Generated/rhi.minified.ush"
#include "Generated/constants.minified.ush"
#include "Generated/common.minified.ush"
#include "Generated/advanced_blend.minified.ush"
#include "Generated/draw_path_common.minified.ush"
#include "Generated/atomic_draw.minified.ush"

View File

@@ -0,0 +1,4 @@
#define DRAW_IMAGE
#define DRAW_IMAGE_MESH
#include "/Engine/Public/Platform.ush"
#include "atomic_base.ush"

View File

@@ -0,0 +1,4 @@
#define DRAW_IMAGE
#define DRAW_IMAGE_RECT
#include "/Engine/Public/Platform.ush"
#include "atomic_base.ush"

View File

@@ -0,0 +1,3 @@
#define DRAW_INTERIOR_TRIANGLES
#include "/Engine/Public/Platform.ush"
#include "atomic_base.ush"

View File

@@ -0,0 +1,3 @@
#define DRAW_PATH
#include "/Engine/Public/Platform.ush"
#include "atomic_base.ush"

View File

@@ -0,0 +1,4 @@
#define DRAW_RENDER_TARGET_UPDATE_BOUNDS 1
#define RESOLVE_PLS 1
#include "/Engine/Public/Platform.ush"
#include "atomic_base.ush"

View File

@@ -0,0 +1,10 @@
#include "/Engine/Public/Platform.ush"
#define UNIFORM_DEFINITIONS_AUTO_GENERATED 1
#define SPLIT_UINT4_ATTRIBUTES 1
#include "/Engine/Generated/GeneratedUniformBuffers.ush"
#include "parse_environment.ush"
#include "Generated/rhi.minified.ush"
#include "Generated/constants.minified.ush"
#include "Generated/common.minified.ush"
#include "Generated/color_ramp.minified.ush"

View File

@@ -0,0 +1,15 @@
#define PLS_IMPL_SUBPASS_LOAD
#define OPTIONALLY_FLAT flat
#define DRAW_IMAGE
#define DRAW_IMAGE_MESH
#include "/Engine/Public/Platform.ush"
#include "/Engine/Generated/GeneratedUniformBuffers.ush"
#include "parse_environment.ush"
#include "Generated/rhi.minified.ush"
#include "Generated/constants.minified.ush"
#include "Generated/specialization.minified.ush"
#include "Generated/common.minified.ush"
#include "Generated/advanced_blend.minified.ush"
#include "Generated/draw_image_mesh.minified.ush"

View File

@@ -0,0 +1,14 @@
#define PLS_IMPL_SUBPASS_LOAD
#define OPTIONALLY_FLAT flat
#define DRAW_INTERIOR_TRIANGLES
#include "/Engine/Public/Platform.ush"
#include "/Engine/Generated/GeneratedUniformBuffers.ush"
#include "parse_environment.ush"
#include "Generated/rhi.minified.ush"
#include "Generated/constants.minified.ush"
#include "Generated/common.minified.ush"
#include "Generated/draw_path_common.minified.ush"
#include "Generated/advanced_blend.minified.ush"
#include "Generated/draw_path.minified.ush"

View File

@@ -0,0 +1,15 @@
#define ENABLE_INSTANCE_INDEX
#define PLS_IMPL_SUBPASS_LOAD
#define OPTIONALLY_FLAT flat
#define DRAW_PATH
#include "/Engine/Public/Platform.ush"
#include "/Engine/Generated/GeneratedUniformBuffers.ush"
#include "parse_environment.ush"
#include "Generated/rhi.minified.ush"
#include "Generated/constants.minified.ush"
#include "Generated/common.minified.ush"
#include "Generated/draw_path_common.minified.ush"
#include "Generated/advanced_blend.minified.ush"
#include "Generated/draw_path.minified.ush"

View File

@@ -0,0 +1,29 @@
// unreal rhi always defines the permutation values, however, we expect them to either exist or not. so
// here we check if its set to false and undef if it is
#if !ENABLE_CLIPPING
#undef ENABLE_CLIPPING
#endif
#if !ENABLE_CLIP_RECT
#undef ENABLE_CLIP_RECT
#endif
#if !ENABLE_ADVANCED_BLEND
#undef ENABLE_ADVANCED_BLEND
#endif
#if !FIXED_FUNCTION_COLOR_BLEND
#undef FIXED_FUNCTION_COLOR_BLEND
#endif
#if !ENABLE_HSL_BLEND_MODES
#undef ENABLE_HSL_BLEND_MODES
#endif
#if !ENABLE_NESTED_CLIPPING
#undef ENABLE_NESTED_CLIPPING
#endif
#if !ENABLE_EVEN_ODD
#undef ENABLE_EVEN_ODD
#endif

View File

@@ -0,0 +1,10 @@
#include "/Engine/Public/Platform.ush"
#define UNIFORM_DEFINITIONS_AUTO_GENERATED 1
#define SPLIT_UINT4_ATTRIBUTES 1
#include "/Engine/Generated/GeneratedUniformBuffers.ush"
#include "parse_environment.ush"
#include "Generated/rhi.minified.ush"
#include "Generated/constants.minified.ush"
#include "Generated/common.minified.ush"
#include "Generated/tessellate.minified.ush"

View File

@@ -12,6 +12,11 @@ ARGS=
while :; do
case $1 in
-u)
TARGET="unreal"
DEFAULT_BACKEND=rhi
shift
;;
-i)
TARGET="ios"
DEFAULT_BACKEND=metal

View File

@@ -417,9 +417,15 @@ void TestHarness::onApplicationCrash(const char* message)
{
if (m_primaryTCPClient != nullptr)
{
// Buy monitorStdIOThread() some time to finish pumping any messages
// related to this abort.
// Buy monitorStdIOThread() some time to finish pumping any messages
// related to this abort.
// std::this_thread::sleep_for causes weird link issues in unreal. just use sleep instead
#if defined(RIVE_UNREAL) && defined(_WIN32)
Sleep(100);
#else
std::this_thread::sleep_for(std::chrono::milliseconds(100));
#endif
shutdownStdioThread();
shutdownInputPumpThread();
m_primaryTCPClient->send4(REQUEST_TYPE_APPLICATION_CRASH);

View File

@@ -101,8 +101,8 @@ private:
std::filesystem::path m_outputDir;
// Forwarding stdout and stderr to the server.
int m_savedStdout;
int m_savedStderr;
int m_savedStdout = 0;
int m_savedStderr = 0;
std::array<int, 2> m_stdioPipe = {0, 0};
std::thread m_stdioThread;

View File

@@ -12,10 +12,8 @@
#include <windows.h>
#endif
// Don't explicitly delete this object. Calling eglDestroyContext during app
// teardown causes a crash on Pixel 4. The OS will clean this up for us
// automatically when we exit.
std::unique_ptr<TestingWindow> s_TestingWindow = nullptr;
// Call TestingWindow::Destroy if you want to delete the window singleton
TestingWindow* s_TestingWindow = nullptr;
const char* TestingWindow::BackendName(Backend backend)
{
@@ -55,6 +53,8 @@ const char* TestingWindow::BackendName(Backend backend)
return "dawn";
case TestingWindow::Backend::coregraphics:
return "coregraphics";
case Backend::rhi:
return "rhi";
}
RIVE_UNREACHABLE();
}
@@ -116,6 +116,8 @@ TestingWindow::Backend TestingWindow::ParseBackend(const char* name, std::string
return Backend::dawn;
if (nameStr == "coregraphics")
return Backend::coregraphics;
if (nameStr == "rhi")
return Backend::rhi;
fprintf(stderr, "'%s': invalid TestingWindow::Backend\n", name);
abort();
}
@@ -142,7 +144,13 @@ TestingWindow* TestingWindow::Init(Backend backend,
const std::string& gpuNameFilterStr,
void* platformWindow)
{
const char* gpuNameFilter = !gpuNameFilterStr.empty() ? gpuNameFilterStr.c_str() : nullptr;
const char* gpuNameFilter RIVE_MAYBE_UNUSED =
!gpuNameFilterStr.empty() ? gpuNameFilterStr.c_str() : nullptr;
if (backend == Backend::rhi)
assert(s_TestingWindow);
else
assert(!s_TestingWindow);
switch (backend)
{
@@ -236,29 +244,33 @@ TestingWindow* TestingWindow::Init(Backend backend,
s_TestingWindow = MakeCoreGraphics();
#endif
break;
case Backend::rhi:
break;
}
if (!s_TestingWindow)
{
fprintf(stderr, "Failed to create testing window for Backend::%s\n", BackendName(backend));
abort();
}
return s_TestingWindow.get();
return s_TestingWindow;
}
TestingWindow* TestingWindow::Get()
{
assert(s_TestingWindow); // Call Init() first!
return s_TestingWindow.get();
return s_TestingWindow;
}
void TestingWindow::Set(TestingWindow* inWindow)
{
assert(inWindow);
s_TestingWindow = inWindow;
}
void TestingWindow::Destroy()
{
assert(s_TestingWindow);
delete s_TestingWindow;
s_TestingWindow = nullptr;
}
char TestingWindow::getKey()
{
fprintf(stderr, "TestingWindow::getKey not implemented.");
abort();
}

View File

@@ -30,6 +30,7 @@ class RenderTarget;
// renderer = TestingWindow::Get()->reset(width, height);
// ...
//
class TestingWindow
{
public:
@@ -62,6 +63,8 @@ public:
anglemsaa,
dawn,
coregraphics,
rhi,
};
constexpr static bool IsGL(Backend backend)
@@ -86,6 +89,7 @@ public:
case Backend::swiftshadercore:
case Backend::dawn:
case Backend::coregraphics:
case Backend::rhi:
return false;
}
RIVE_UNREACHABLE();
@@ -113,6 +117,7 @@ public:
case Backend::swiftshadercore:
case Backend::dawn:
case Backend::coregraphics:
case Backend::rhi:
return false;
}
RIVE_UNREACHABLE();
@@ -140,6 +145,7 @@ public:
case Backend::coregraphics:
case Backend::angle:
case Backend::anglemsaa:
case Backend::rhi:
return false;
}
RIVE_UNREACHABLE();
@@ -152,6 +158,7 @@ public:
case Backend::glatomic:
case Backend::d3datomic:
case Backend::metalatomic:
case Backend::rhi:
case Backend::vkcore:
case Backend::moltenvkcore:
case Backend::swiftshadercore:
@@ -194,6 +201,7 @@ public:
case Backend::anglemsaa:
case Backend::dawn:
case Backend::coregraphics:
case Backend::rhi:
return false;
}
RIVE_UNREACHABLE();
@@ -221,6 +229,7 @@ public:
case Backend::angle:
case Backend::dawn:
case Backend::coregraphics:
case Backend::rhi:
return false;
}
RIVE_UNREACHABLE();
@@ -247,6 +256,7 @@ public:
const std::string& gpuNameFilter,
void* platformWindow = nullptr);
static TestingWindow* Get();
static void Set(TestingWindow* inWindow);
static void Destroy();
uint32_t width() const { return m_width; }
@@ -273,7 +283,11 @@ public:
// Blocks until a key is pressed.
virtual bool peekKey(char& key) { return false; }
virtual char getKey();
virtual char getKey()
{
fprintf(stderr, "TestingWindow::getKey not implemented.");
abort();
}
virtual bool shouldQuit() const { return false; }
virtual ~TestingWindow() {}
@@ -283,24 +297,23 @@ protected:
uint32_t m_height = 0;
private:
static std::unique_ptr<TestingWindow> MakeGLFW(Backend, Visibility);
static std::unique_ptr<TestingWindow> MakeEGL(Backend, void* platformWindow);
static TestingWindow* MakeGLFW(Backend, Visibility);
static TestingWindow* MakeEGL(Backend, void* platformWindow);
#ifdef _WIN32
static std::unique_ptr<TestingWindow> MakeD3D(Visibility);
static TestingWindow* MakeD3D(Visibility);
#endif
#ifdef __APPLE__
static std::unique_ptr<TestingWindow> MakeMetalTexture();
static TestingWindow* MakeMetalTexture();
#endif
#ifdef RIVE_MACOSX
static std::unique_ptr<TestingWindow> MakeCoreGraphics();
static TestingWindow* MakeCoreGraphics();
#endif
static std::unique_ptr<TestingWindow> MakeFiddleContext(Backend,
static TestingWindow* MakeFiddleContext(Backend,
Visibility,
const char* gpuNameFilter,
void* platformWindow);
static std::unique_ptr<TestingWindow> MakeVulkanTexture(bool coreFeaturesOnly,
const char* gpuNameFilter);
static std::unique_ptr<TestingWindow> MakeAndroidVulkan(void* platformWindow);
static TestingWindow* MakeVulkanTexture(bool coreFeaturesOnly, const char* gpuNameFilter);
static TestingWindow* MakeAndroidVulkan(void* platformWindow);
};
RIVE_MAKE_ENUM_BITSET(TestingWindow::RendererFlags);

View File

@@ -6,10 +6,7 @@
#if !defined(RIVE_ANDROID)
std::unique_ptr<TestingWindow> TestingWindow::MakeAndroidVulkan(void* platformWindow)
{
return nullptr;
}
TestingWindow* TestingWindow::MakeAndroidVulkan(void* platformWindow) { return nullptr; }
#else
@@ -283,10 +280,9 @@ private:
rcp<RenderTargetVulkan> m_renderTarget;
};
std::unique_ptr<TestingWindow> TestingWindow::MakeAndroidVulkan(void* platformWindow)
TestingWindow* TestingWindow::MakeAndroidVulkan(void* platformWindow)
{
return std::make_unique<TestingWindowAndroidVulkan>(
reinterpret_cast<ANativeWindow*>(platformWindow));
return new TestingWindowAndroidVulkan(reinterpret_cast<ANativeWindow*>(platformWindow));
}
#endif

View File

@@ -71,9 +71,6 @@ private:
AutoCF<CGColorSpaceRef> m_space;
};
std::unique_ptr<TestingWindow> TestingWindow::MakeCoreGraphics()
{
return std::make_unique<TestingWindowCoreGraphics>();
}
TestingWindow* TestingWindow::MakeCoreGraphics() { return new TestingWindowCoreGraphics; }
#endif

View File

@@ -6,10 +6,7 @@
#ifdef RIVE_TOOLS_NO_GL
std::unique_ptr<TestingWindow> TestingWindow::MakeEGL(Backend backend, void* platformWindow)
{
return nullptr;
}
TestingWindow* TestingWindow::MakeEGL(Backend backend, void* platformWindow) { return nullptr; }
#else
@@ -512,7 +509,7 @@ private:
glutils::Texture m_headlessRenderTexture = glutils::Texture::Zero();
};
std::unique_ptr<TestingWindow> TestingWindow::MakeEGL(Backend backend, void* platformWindow)
TestingWindow* TestingWindow::MakeEGL(Backend backend, void* platformWindow)
{
auto rendererFlags = RendererFlags::none;
EGLint angleBackend = EGL_NONE;
@@ -556,11 +553,12 @@ std::unique_ptr<TestingWindow> TestingWindow::MakeEGL(Backend backend, void* pla
case Backend::swiftshadercore:
case Backend::dawn:
case Backend::coregraphics:
case Backend::rhi:
printf("Invalid backend for TestingWindow::MakeEGLPbuffer.");
abort();
break;
}
return std::make_unique<TestingWindowEGL>(angleBackend,
return new TestingWindowEGL(angleBackend,
samples,
TestingGLRenderer::Make(rendererFlags),
platformWindow);

View File

@@ -5,8 +5,7 @@
#include "testing_window.hpp"
#if defined(TESTING) || defined(RIVE_TOOLS_NO_GLFW)
std::unique_ptr<TestingWindow> TestingWindow::MakeFiddleContext(Backend,
TestingWindow* TestingWindow::MakeFiddleContext(Backend,
Visibility,
const char*,
void* platformWindow)
@@ -190,6 +189,7 @@ public:
switch (backend)
{
case Backend::rhi:
case Backend::coregraphics:
break;
case Backend::gl:
@@ -328,15 +328,12 @@ private:
std::unique_ptr<FiddleContext> m_fiddleContext;
};
std::unique_ptr<TestingWindow> TestingWindow::MakeFiddleContext(Backend backend,
TestingWindow* TestingWindow::MakeFiddleContext(Backend backend,
Visibility visibility,
const char* gpuNameFilter,
void* platformWindow)
{
return std::make_unique<TestingWindowFiddleContext>(backend,
visibility,
gpuNameFilter,
platformWindow);
return new TestingWindowFiddleContext(backend, visibility, gpuNameFilter, platformWindow);
}
#endif

View File

@@ -132,9 +132,9 @@ private:
};
}; // namespace rive::gpu
std::unique_ptr<TestingWindow> TestingWindow::MakeMetalTexture()
TestingWindow* TestingWindow::MakeMetalTexture()
{
return std::make_unique<rive::gpu::TestingWindowMetalTexture>();
return new rive::gpu::TestingWindowMetalTexture();
}
#endif

View File

@@ -6,8 +6,7 @@
#ifndef RIVE_VULKAN
std::unique_ptr<TestingWindow> TestingWindow::MakeVulkanTexture(bool coreFeaturesOnly,
const char* gpuNameFilter)
TestingWindow* TestingWindow::MakeVulkanTexture(bool coreFeaturesOnly, const char* gpuNameFilter)
{
return nullptr;
}
@@ -261,10 +260,9 @@ private:
};
}; // namespace rive::gpu
std::unique_ptr<TestingWindow> TestingWindow::MakeVulkanTexture(bool coreFeaturesOnly,
const char* gpuNameFilter)
TestingWindow* TestingWindow::MakeVulkanTexture(bool coreFeaturesOnly, const char* gpuNameFilter)
{
return std::make_unique<rive::gpu::TestingWindowVulkanTexture>(coreFeaturesOnly, gpuNameFilter);
return new rive::gpu::TestingWindowVulkanTexture(coreFeaturesOnly, gpuNameFilter);
}
#endif

View File

@@ -65,7 +65,7 @@ parser.add_argument("-m", "--match",
help="`match` patter for gms")
parser.add_argument("-t", "--target",
default="host",
choices=["host", "android", "ios", "iossim"],
choices=["host", "android", "ios", "iossim", "unreal"],
help="which platform to run on")
parser.add_argument("-u", "--ios_udid",
type=str,
@@ -338,6 +338,10 @@ def update_cmd_to_deploy_on_target(cmd):
dirname = os.path.dirname(cmd[0])
toolname = os.path.basename(cmd[0])
if args.target == "unreal":
unreal_exe_path = os.path.join(dirname, "Windows", "rive_unreal.exe")
return [unreal_exe_path, "/Game/maps/" + toolname, "-ResX=1280", "-ResY=720", "-WINDOWED"] + cmd[1:]
if args.target == "android":
sharedlib = os.path.join(dirname, "lib%s.so" % toolname)
print("\nDeploying %s on android..." % sharedlib)
@@ -491,6 +495,13 @@ def main():
args.remote = True # Since we can't do port forwarding in iOS, it always has to be remote.
if not args.ios_udid:
args.ios_udid = "booted"
elif args.target == 'unreal':
# currently, unreal needs to run only one job at a time for goldens and gms to work
args.jobs_per_tool = 1
if args.builddir == None:
args.builddir = "out/debug"
# unreal is currently always rhi, we may have seperate rhi types in the future like rhi_metal etc..
args.backend = 'rhi'
else:
assert(args.target == "host")
if args.builddir == None:
@@ -596,7 +607,7 @@ def main():
flush=True)
# On mobile we can't launch >1 instance of the app at a time.
serial_deploy = not args.server_only and ("ios" in args.target or args.target == "android")
serial_deploy = not args.server_only and ("ios" in args.target or args.target == "android" or args.target == "unreal")
procs = []
def keyboard_interrupt_handler(signal, frame):

View File

@@ -81,7 +81,80 @@ static bool is_arg(const char arg[], const char target[], const char alt[] = nul
return !strcmp(arg, target) || (arg && !strcmp(arg, alt));
}
#if defined(RIVE_IOS) || defined(RIVE_IOS_SIMULATOR)
#if defined(RIVE_UNREAL)
typedef const void* REGISTRY_HANDLE;
REGISTRY_HANDLE gms_get_registry_head() { return rivegm::GMRegistry::head(); }
REGISTRY_HANDLE gms_registry_get_next(REGISTRY_HANDLE position_handle)
{
const GMRegistry* position = reinterpret_cast<const GMRegistry*>(position_handle);
if (position == nullptr)
return nullptr;
return position->next();
}
bool gms_run_gm(REGISTRY_HANDLE gm_handle)
{
const GMRegistry* position = reinterpret_cast<const GMRegistry*>(gm_handle);
if (position == nullptr)
return false;
auto gm = position->get()();
if (!gm)
{
return false;
}
gm->onceBeforeDraw();
uint32_t width = gm->width();
uint32_t height = gm->height();
TestingWindow::Get()->resize(width, height);
gm->run(nullptr);
return true;
}
bool gms_registry_get_name(REGISTRY_HANDLE position_handle, std::string& name)
{
const GMRegistry* position = reinterpret_cast<const GMRegistry*>(position_handle);
if (position == nullptr)
return false;
auto gm = position->get()();
if (!gm)
{
return false;
}
name = gm->name();
return true;
}
bool gms_registry_get_size(REGISTRY_HANDLE position_handle, size_t& width, size_t& height)
{
const GMRegistry* position = reinterpret_cast<const GMRegistry*>(position_handle);
if (position == nullptr)
return false;
width = 0;
height = 0;
auto gm = position->get()();
if (!gm)
{
return false;
}
width = gm->width();
height = gm->height();
return true;
}
int gms_main(int argc, const char* argv[])
#elif defined(RIVE_IOS) || defined(RIVE_IOS_SIMULATOR)
int gms_ios_main(int argc, const char* argv[])
#elif defined(RIVE_ANDROID)
int rive_android_main(int argc, const char* const* argv, struct android_app*)
@@ -157,6 +230,7 @@ int main(int argc, const char* argv[])
dumpGMs(std::string(match), interactive);
TestingWindow::Destroy(); // Exercise our PLS teardown process now that we're done.
TestHarness::Instance().shutdown();
return 0;
}

View File

@@ -19,7 +19,6 @@
#include <filesystem>
#include <fstream>
#include <iostream>
constexpr static int kWindowTargetSize = 1600;
GoldensArguments s_args;
@@ -165,6 +164,8 @@ private:
int goldens_ios_main(int argc, const char* argv[])
#elif defined(RIVE_ANDROID)
int rive_android_main(int argc, const char* const* argv, struct android_app*)
#elif defined(RIVE_UNREAL)
int goldens_main(int argc, const char* argv[])
#else
int main(int argc, const char* argv[])
#endif

View File

@@ -22,21 +22,19 @@ public:
args::Group required(*m_parser, "required arguments:", args::Group::Validators::All);
args::Group optional(*m_parser, "optional arguments:", args::Group::Validators::DontCare);
args::ValueFlag<std::string> testHarness(optional,
"test_harness",
"TCP server address of python test harness",
{"test_harness"},
"/dev/null");
args::ValueFlag<std::string> src(optional,
"src",
"source src filename (ignored if --test_harness)",
{'s', "src"});
args::ValueFlag<std::string> testHarness(optional,
"test_harness",
"TCP server address of python test harness",
{"test_harness"});
// no default for windows because /dev/null isnt a thing
args::ValueFlag<std::string> output(optional,
"output",
"output png directory (ignored if --test_harness)",
{'o', "output"},
"/dev/null");
{'o', "output"});
args::ValueFlag<std::string> artboard(optional,
"artboard",
"artboard to draw from (only when src != '-')",
@@ -49,7 +47,7 @@ public:
args::ValueFlag<std::string> backend(optional,
"backend",
"backend type: [gl, metal, angle_gl, angle_d3d, "
"angle_vk, angle_mtl, coregraphics, skia_raster]",
"angle_vk, angle_mtl, coregraphics, skia_raster, rhi]",
{'b', "backend"});
args::Flag headless(optional,
"headless",

View File

@@ -1,6 +1,5 @@
dofile('rive_tools_project.lua')
project('imagediff')
do
kind('ConsoleApp')
@@ -32,6 +31,10 @@ do
do
links({ 'opengl32' })
end
filter({ 'system:windows', 'options:for_unreal' })
do
kind('None')
end
filter('system:linux')
do
links({ 'GL' })
@@ -42,23 +45,32 @@ do
end
end
rive_tools_project('bench', _OPTIONS['os'] == 'ios' and 'StaticLib' or 'ConsoleApp')
do
if not _OPTIONS['for_unreal'] then
rive_tools_project('bench', _OPTIONS['os'] == 'ios' and 'StaticLib' or 'ConsoleApp')
do
files({ 'bench/*.cpp' })
end
end
rive_tools_project('gms', 'RiveTool')
do
files({ 'gm/*.cpp' })
filter({ 'options:for_unreal' })
do
defines({ 'RIVE_UNREAL' })
end
end
rive_tools_project('goldens', 'RiveTool')
do
exceptionhandling('On')
files({ 'goldens/goldens.cpp' })
filter({ 'options:for_unreal' })
do
defines({ 'RIVE_UNREAL' })
end
end
rive_tools_project('player', 'RiveTool')
do
files({ 'player/player.cpp' })

View File

@@ -18,6 +18,7 @@ function rive_tools_project(name, project_kind)
kind(
_OPTIONS['os'] == 'android' and 'SharedLib'
or _OPTIONS['os'] == 'ios' and 'StaticLib'
or _OPTIONS['for_unreal'] and 'StaticLib'
or 'ConsoleApp'
)
else
@@ -129,13 +130,8 @@ function rive_tools_project(name, project_kind)
})
end
filter({})
if
project_kind == 'ConsoleApp'
or project_kind == 'SharedLib'
or project_kind == 'RiveTool'
then
filter({ 'kind:ConsoleApp or SharedLib or WindowedApp' })
do
libdirs({ RIVE_RUNTIME_DIR .. '/build/%{cfg.system}/bin/' .. RIVE_BUILD_CONFIG })
links({
@@ -150,22 +146,24 @@ function rive_tools_project(name, project_kind)
'libwebp',
'rive_yoga',
'rive_harfbuzz',
'rive_sheenbidi'
'rive_sheenbidi',
})
if ndk then
relative_ndk = ndk
if string.sub(ndk, 1, 1) == '/' then
-- An absolute file path wasn't working with premake.
local current_path = string.gmatch(path.getabsolute('.'), "([^\\/]+)")
local current_path = string.gmatch(path.getabsolute('.'), '([^\\/]+)')
for dir in current_path do
relative_ndk = '../' .. relative_ndk
end
end
files({ relative_ndk .. '/sources/android/native_app_glue/android_native_app_glue.c' })
files({
relative_ndk .. '/sources/android/native_app_glue/android_native_app_glue.c',
})
end
filter({ 'system:windows' })
filter({ 'kind:ConsoleApp or SharedLib or WindowedApp', 'system:windows' })
do
libdirs({
RIVE_RUNTIME_DIR .. '/skia/dependencies/glfw_build/src/Release',
@@ -173,7 +171,7 @@ function rive_tools_project(name, project_kind)
links({ 'glfw3', 'opengl32', 'd3d11', 'dxgi', 'd3dcompiler', 'ws2_32' })
end
filter('system:macosx')
filter({ 'kind:ConsoleApp or SharedLib or WindowedApp', 'system:macosx' })
do
libdirs({ RIVE_RUNTIME_DIR .. '/skia/dependencies/glfw_build/src' })
links({
@@ -195,18 +193,18 @@ function rive_tools_project(name, project_kind)
})
end
filter('system:linux')
filter({ 'kind:ConsoleApp or SharedLib or WindowedApp', 'system:linux' })
do
libdirs({ RIVE_RUNTIME_DIR .. '/skia/dependencies/glfw_build/src' })
links({ 'glfw3', 'm', 'z', 'dl', 'pthread', 'GL' })
end
filter('system:android')
filter({ 'kind:ConsoleApp or SharedLib or WindowedApp', 'system:android' })
do
links({ 'EGL', 'GLESv3', 'log' })
end
filter('options:with-dawn')
filter({ 'kind:ConsoleApp or SharedLib or WindowedApp', 'options:with-dawn' })
do
links({
'dawn_native_static',
@@ -216,21 +214,28 @@ function rive_tools_project(name, project_kind)
})
end
filter({ 'options:with-dawn', 'system:windows' })
filter({
'kind:ConsoleApp or SharedLib or WindowedApp',
'options:with-dawn',
'system:windows',
})
do
links({ 'dxguid' })
end
filter({ 'options:with-dawn', 'system:macosx' })
filter({
'kind:ConsoleApp or SharedLib or WindowedApp',
'options:with-dawn',
'system:macosx',
})
do
links({ 'IOSurface.framework' })
end
end
filter({})
end
end
rive_tools_project('tools_common', 'StaticLib')
do
files({
@@ -242,6 +247,12 @@ do
RIVE_PLS_DIR .. '/path_fiddle/fiddle_context_dawn.cpp',
})
filter({ 'options:for_unreal' })
do
defines({ 'RIVE_UNREAL', 'RIVE_TOOLS_NO_GLFW', 'RIVE_TOOLS_NO_GL' })
cppdialect('C++20')
end
filter({ 'toolset:not msc' })
do
buildoptions({ '-Wshorten-64-to-32' })

View File

@@ -88,5 +88,4 @@ do
end
filter({})
end

18
tests/unreal/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File with Arguments",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"args": [
"C:/Git/rive/packages/runtime/tests"
]
}
]
}

View File

View File

@@ -0,0 +1,100 @@
[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/maps/TestMap.TestMap
EditorStartupMap=/Game/maps/TestMap.TestMap
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_Vulkan
-D3D12TargetedShaderFormats=PCD3D_SM5
+D3D12TargetedShaderFormats=PCD3D_SM6
-D3D11TargetedShaderFormats=PCD3D_SM5
+D3D11TargetedShaderFormats=PCD3D_SM5
+VulkanTargetedShaderFormats=SF_VULKAN_SM6
Compiler=Default
AudioSampleRate=48000
AudioCallbackBufferFrameSize=1024
AudioNumBuffersToEnqueue=1
AudioMaxChannels=0
AudioNumSourceWorkers=4
SpatializationPlugin=
SourceDataOverridePlugin=
ReverbPlugin=
OcclusionPlugin=
CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0)
CacheSizeKB=65536
MaxChunkSizeOverrideKB=0
bResampleForDevice=False
MaxSampleRate=48000.000000
HighSampleRate=32000.000000
MedSampleRate=24000.000000
LowSampleRate=12000.000000
MinSampleRate=8000.000000
CompressionQualityModifier=1.000000
AutoStreamingThreshold=0.000000
SoundCueCookQualityIndex=-1
[/Script/Engine.RendererSettings]
r.Mobile.EnableNoPrecomputedLightingCSMShader=True
r.GenerateMeshDistanceFields=True
r.DynamicGlobalIlluminationMethod=1
r.ReflectionMethod=1
r.Shadow.Virtual.Enable=1
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8
r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8
r.GPUCrashDebugging=True
[/Script/LinuxTargetPlatform.LinuxTargetSettings]
SpatializationPlugin=
SourceDataOverridePlugin=
ReverbPlugin=
OcclusionPlugin=
SoundCueCookQualityIndex=-1
-TargetedRHIs=SF_VULKAN_SM5
+TargetedRHIs=SF_VULKAN_SM5
+TargetedRHIs=SF_VULKAN_SM6
+TargetedRHIs=SF_VULKAN_ES31
[/Script/HardwareTargeting.HardwareTargetingSettings]
TargetedHardwareClass=Desktop
AppliedTargetedHardwareClass=Desktop
DefaultGraphicsPerformance=Maximum
AppliedDefaultGraphicsPerformance=Maximum
[/Script/WorldPartitionEditor.WorldPartitionEditorSettings]
CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet'
[/Script/Engine.UserInterfaceSettings]
bAuthorizeAutomaticWidgetVariableCreation=False
FontDPIPreset=Standard
FontDPI=72
[/Script/Engine.Engine]
+ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/rive_unreal")
+ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/rive_unreal")
[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings]
bEnablePlugin=True
bAllowNetworkConnection=True
SecurityToken=6B3C9F5B4A0292AFFA62F192840FB8EC
bIncludeInShipping=False
bAllowExternalStartInShipping=False
bCompileAFSProject=False
bUseCompression=False
bLogFiles=False
bReportStats=False
ConnectionType=USBOnly
bUseManualIPAddress=False
ManualIPAddress=
[/Script/RiveRenderer.RiveRendererSettings]
bEnableRHITechPreview=True

View File

@@ -0,0 +1,100 @@
[/Script/EngineSettings.GeneralProjectSettings]
ProjectID=0E9694AD44863D7CA6FDE5839ADA271C
[/Script/UnrealEd.ProjectPackagingSettings]
Build=IfProjectHasCode
BuildConfiguration=PPBC_Development
BuildTarget=
FullRebuild=False
ForDistribution=False
IncludeDebugFiles=False
BlueprintNativizationMethod=Disabled
bIncludeNativizedAssetsInProjectGeneration=False
bExcludeMonolithicEngineHeadersInNativizedCode=False
UsePakFile=True
bUseIoStore=True
bUseZenStore=False
bMakeBinaryConfig=False
bGenerateChunks=False
bGenerateNoChunks=False
bChunkHardReferencesOnly=False
bForceOneChunkPerFile=False
MaxChunkSize=0
bBuildHttpChunkInstallData=False
HttpChunkInstallDataDirectory=(Path="")
WriteBackMetadataToAssetRegistry=Disabled
bWritePluginSizeSummaryJsons=False
bCompressed=True
PackageCompressionFormat=Oodle
bForceUseProjectCompressionFormatIgnoreHardwareOverride=False
PackageAdditionalCompressionOptions=
PackageCompressionMethod=Kraken
PackageCompressionLevel_DebugDevelopment=4
PackageCompressionLevel_TestShipping=4
PackageCompressionLevel_Distribution=7
PackageCompressionMinBytesSaved=1024
PackageCompressionMinPercentSaved=5
bPackageCompressionEnableDDC=False
PackageCompressionMinSizeToConsiderDDC=0
HttpChunkInstallDataVersion=
IncludePrerequisites=True
IncludeAppLocalPrerequisites=False
bShareMaterialShaderCode=True
bDeterministicShaderCodeOrder=False
bSharedMaterialNativeLibraries=True
ApplocalPrerequisitesDirectory=(Path="")
IncludeCrashReporter=False
InternationalizationPreset=English
-CulturesToStage=en
+CulturesToStage=en
LocalizationTargetCatchAllChunkId=0
bCookAll=False
bCookMapsOnly=False
bSkipEditorContent=False
bSkipMovies=False
-IniKeyDenylist=KeyStorePassword
-IniKeyDenylist=KeyPassword
-IniKeyDenylist=rsa.privateexp
-IniKeyDenylist=rsa.modulus
-IniKeyDenylist=rsa.publicexp
-IniKeyDenylist=aes.key
-IniKeyDenylist=SigningPublicExponent
-IniKeyDenylist=SigningModulus
-IniKeyDenylist=SigningPrivateExponent
-IniKeyDenylist=EncryptionKey
-IniKeyDenylist=DevCenterUsername
-IniKeyDenylist=DevCenterPassword
-IniKeyDenylist=IOSTeamID
-IniKeyDenylist=SigningCertificate
-IniKeyDenylist=MobileProvision
-IniKeyDenylist=IniKeyDenylist
-IniKeyDenylist=IniSectionDenylist
+IniKeyDenylist=KeyStorePassword
+IniKeyDenylist=KeyPassword
+IniKeyDenylist=rsa.privateexp
+IniKeyDenylist=rsa.modulus
+IniKeyDenylist=rsa.publicexp
+IniKeyDenylist=aes.key
+IniKeyDenylist=SigningPublicExponent
+IniKeyDenylist=SigningModulus
+IniKeyDenylist=SigningPrivateExponent
+IniKeyDenylist=EncryptionKey
+IniKeyDenylist=DevCenterUsername
+IniKeyDenylist=DevCenterPassword
+IniKeyDenylist=IOSTeamID
+IniKeyDenylist=SigningCertificate
+IniKeyDenylist=MobileProvision
+IniKeyDenylist=IniKeyDenylist
+IniKeyDenylist=IniSectionDenylist
-IniSectionDenylist=HordeStorageServers
-IniSectionDenylist=StorageServers
+IniSectionDenylist=HordeStorageServers
+IniSectionDenylist=StorageServers
+MapsToCook=(FilePath="/Game/maps/gms")
+MapsToCook=(FilePath="/Game/maps/goldens")
+DirectoriesToAlwaysCook=(Path="/Game")
bRetainStagedDirectory=False
CustomStageCopyHandler=

View File

@@ -0,0 +1,467 @@
[/Script/Engine.InputSettings]
-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f))
-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
-AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f))
+AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Mouse2D",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
+AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False))
bAltEnterTogglesFullscreen=True
bF11TogglesFullscreen=True
bUseMouseForTouch=False
bEnableMouseSmoothing=True
bEnableFOVScaling=True
bCaptureMouseOnLaunch=True
bEnableLegacyInputScales=True
bEnableMotionControls=True
bFilterInputByPlatformUser=False
bShouldFlushPressedKeysOnViewportFocusLost=True
bAlwaysShowTouchInterface=False
bShowConsoleOnFourFingerTap=True
bEnableGestureRecognizer=False
bUseAutocorrect=False
DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown
DefaultViewportMouseLockMode=LockOnCapture
FOVScale=0.011110
DoubleClickTime=0.200000
DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput
DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent
DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks
-ConsoleKeys=Tilde
+ConsoleKeys=Tilde
+ConsoleKeys=Caret
[/Script/EngineSettings.ConsoleSettings]
MaxScrollbackSize=1024
-ManualAutoCompleteList=(Command="Exit",Desc="Exits the game")
-ManualAutoCompleteList=(Command="DebugCreatePlayer 1",Desc=)
-ManualAutoCompleteList=(Command="ToggleDrawEvents",Desc="Toggles annotations for shader debugging with Pix, Razor or similar GPU capture tools")
-ManualAutoCompleteList=(Command="Shot",Desc="Make a screenshot")
-ManualAutoCompleteList=(Command="RecompileShaders changed",Desc="Recompile shaders that have any changes on their source files")
-ManualAutoCompleteList=(Command="RecompileShaders global",Desc="Recompile global shaders that have any changes on their source files")
-ManualAutoCompleteList=(Command="RecompileShaders material ",Desc="Recompile shaders for a specific material if it's source files have changed")
-ManualAutoCompleteList=(Command="RecompileShaders all",Desc="Recompile all shaders that have any changes on their source files")
-ManualAutoCompleteList=(Command="Debug Crash",Desc="Simulates a game thread crash for debugging")
-ManualAutoCompleteList=(Command="Debug RenderCrash",Desc="Simulates a render thread crash for debugging")
-ManualAutoCompleteList=(Command="DumpMaterialStats",Desc="Dump material information")
-ManualAutoCompleteList=(Command="DumpShaderStats",Desc="Dump shader information")
-ManualAutoCompleteList=(Command="DumpShaderPipelineStats",Desc="Dump shader pipeline information")
-ManualAutoCompleteList=(Command="DumpShaderCompileStats",Desc="Dump shader compilation information")
-ManualAutoCompleteList=(Command="DumpGPU -upload",Desc="Dump the GPU's intermediary resources and upload to network")
-ManualAutoCompleteList=(Command="StartFPSChart",Desc="after that use StopFPSChart")
-ManualAutoCompleteList=(Command="StopFPSChart",Desc="after that look for the output in Saved/Profiling/FPSChartStats")
-ManualAutoCompleteList=(Command="FreezeAt",Desc="Locks the player view and rendering time.")
-ManualAutoCompleteList=(Command="Open",Desc="<MapName> Opens the specified map, doesn't pass previously set options")
-ManualAutoCompleteList=(Command="Travel",Desc="<MapName> Travels to the specified map, passes along previously set options")
-ManualAutoCompleteList=(Command="ServerTravel",Desc="<MapName> Travels to the specified map and brings clients along, passes along previously set options")
-ManualAutoCompleteList=(Command="DisplayAll",Desc="<ClassName> <PropertyName> Display property values for instances of classname")
-ManualAutoCompleteList=(Command="DisplayAllLocation",Desc="<ClassName> Display location for all instances of classname")
-ManualAutoCompleteList=(Command="DisplayAllRotation",Desc="<ClassName> Display rotation for all instances of classname")
-ManualAutoCompleteList=(Command="DisplayClear",Desc="Clears previous DisplayAll entries")
-ManualAutoCompleteList=(Command="FlushPersistentDebugLines",Desc="Clears persistent debug line cache")
-ManualAutoCompleteList=(Command="GetAll ",Desc="<ClassName> <PropertyName> <Name=ObjectInstanceName> <OUTER=ObjectInstanceName> <SHOWDEFAULTS> <SHOWPENDINGKILLS> <DETAILED> Log property values of all instances of classname")
-ManualAutoCompleteList=(Command="GetAllLocation",Desc="<ClassName> Log location for all instances of classname")
-ManualAutoCompleteList=(Command="GetAllRotation",Desc="<ClassName> Log rotation for all instances of classname")
-ManualAutoCompleteList=(Command="Obj List ",Desc="<Class=ClassName> <Type=MetaClass> <Outer=OuterObject> <Package=InsidePackage> <Inside=InsideObject>")
-ManualAutoCompleteList=(Command="Obj ListContentRefs",Desc="<Class=ClassName> <ListClass=ClassName>")
-ManualAutoCompleteList=(Command="Obj Classes",Desc="Shows all classes")
-ManualAutoCompleteList=(Command="Obj Refs",Desc="Name=<ObjectName> [Shortest] [Longest] [All] [External] [Direct] [Full] [Minimal] [GCOnly] [History=<MaxHistoryLevel>] Lists referencers of the specified object")
-ManualAutoCompleteList=(Command="Obj GC",Desc="Runs the UObject Garbage Collector and resets the GC timer.")
-ManualAutoCompleteList=(Command="Obj Dump ",Desc="<ObjectName> [Recurse or Hide/Show=\"category1,...\"] or <Class=ClassName> <Name=ObjectName> [Recurse or Hide/Show=\"category1,...\"] Prints the value of all variables for the specified object")
-ManualAutoCompleteList=(Command="EditActor",Desc="<Class=ClassName> or <Name=ObjectName> or TRACE")
-ManualAutoCompleteList=(Command="EditDefault",Desc="<Class=ClassName>")
-ManualAutoCompleteList=(Command="EditObject",Desc="<Class=ClassName> or <Name=ObjectName> or <ObjectName>")
-ManualAutoCompleteList=(Command="ReloadCfg ",Desc="<Class/ObjectName> Reloads config variables for the specified object/class")
-ManualAutoCompleteList=(Command="ReloadLoc ",Desc="<Class/ObjectName> Reloads localized variables for the specified object/class")
-ManualAutoCompleteList=(Command="Set ",Desc="<ClassName> <PropertyName> <Value> Sets property to value on objectname")
-ManualAutoCompleteList=(Command="SetNoPEC",Desc="<ClassName> <PropertyName> <Value> Sets property to value on objectname without Pre/Post Edit Change notifications")
-ManualAutoCompleteList=(Command="Stat FPS",Desc="Shows FPS counter")
-ManualAutoCompleteList=(Command="Stat UNIT",Desc="Shows hardware unit framerate")
-ManualAutoCompleteList=(Command="Stat DrawCount",Desc="Shows draw counts broken down by category")
-ManualAutoCompleteList=(Command="Stat UnitGraph",Desc="Draws simple unit time graph")
-ManualAutoCompleteList=(Command="Stat NamedEvents",Desc="Stat NamedEvents (Enables named events for external profilers)")
-ManualAutoCompleteList=(Command="Stat VerboseNamedEvents",Desc="Stat VerboseNamedEvents (Enables verbose named events for external profilers)")
-ManualAutoCompleteList=(Command="Stat StartFile",Desc="Stat StartFile (starts a stats capture, creating a new file in the Profiling directory; stop with stat StopFile to close the file)")
-ManualAutoCompleteList=(Command="Stat StopFile",Desc="Stat StopFile (finishes a stats capture started by stat StartFile)")
-ManualAutoCompleteList=(Command="Stat CPULoad",Desc="Stat CPULoad (Shows CPU Utilization)")
-ManualAutoCompleteList=(Command="Stat DUMPHITCHES",Desc="executes dumpstats on hitches - see log")
-ManualAutoCompleteList=(Command="Stat D3D11RHI",Desc="Shows Direct3D 11 stats")
-ManualAutoCompleteList=(Command="Stat LEVELS",Desc="Displays level streaming info")
-ManualAutoCompleteList=(Command="Stat GAME",Desc="Displays game performance stats")
-ManualAutoCompleteList=(Command="Stat MEMORY",Desc="Displays memory stats")
-ManualAutoCompleteList=(Command="Stat PHYSICS",Desc="Displays physics performance stats")
-ManualAutoCompleteList=(Command="Stat STREAMING",Desc="Displays basic texture streaming stats")
-ManualAutoCompleteList=(Command="Stat STREAMINGDETAILS",Desc="Displays detailed texture streaming stats")
-ManualAutoCompleteList=(Command="Stat GPU",Desc="Displays GPU stats for the frame")
-ManualAutoCompleteList=(Command="Stat COLLISION",Desc=)
-ManualAutoCompleteList=(Command="Stat PARTICLES",Desc=)
-ManualAutoCompleteList=(Command="Stat SCRIPT",Desc=)
-ManualAutoCompleteList=(Command="Stat AUDIO",Desc=)
-ManualAutoCompleteList=(Command="Stat ANIM",Desc=)
-ManualAutoCompleteList=(Command="Stat NET",Desc=)
-ManualAutoCompleteList=(Command="Stat LIST",Desc="<Groups/Sets/Group> List groups of stats, saved sets, or specific stats within a specified group")
-ManualAutoCompleteList=(Command="Stat splitscreen",Desc=)
-ManualAutoCompleteList=(Command="MemReport",Desc="Outputs memory stats to a profile file. -Full gives more data, -Log outputs to the log")
-ManualAutoCompleteList=(Command="ListTextures",Desc="[Streaming|NonStreaming|Forced] [-Alphasort] [-csv] Lists all loaded textures and their current memory footprint")
-ManualAutoCompleteList=(Command="ListStreamingTextures",Desc="Lists info for all streaming textures")
-ManualAutoCompleteList=(Command="ListAnims",Desc="Lists info for all animations")
-ManualAutoCompleteList=(Command="ListSkeletalMeshes",Desc="Lists info for all skeletal meshes")
-ManualAutoCompleteList=(Command="ListStaticMeshes",Desc="Lists info for all static meshes")
-ManualAutoCompleteList=(Command="InvestigateTexture",Desc="Shows streaming info about the specified texture")
-ManualAutoCompleteList=(Command="DumpTextureStreamingStats",Desc="Dump current streaming stats (e.g. pool capacity) to the log")
-ManualAutoCompleteList=(Command="RestartLevel",Desc="Restarts the level")
-ManualAutoCompleteList=(Command="Module List",Desc="Lists all known modules")
-ManualAutoCompleteList=(Command="Module Load",Desc="Attempts to load the specified module name")
-ManualAutoCompleteList=(Command="Module Unload",Desc="Unloads the specified module name")
-ManualAutoCompleteList=(Command="Module Reload",Desc="Reloads the specified module name, unloading it first if needed")
-ManualAutoCompleteList=(Command="Module Recompile",Desc="Attempts to recompile a module, first unloading it if needed")
-ManualAutoCompleteList=(Command="HotReload",Desc="<UObject DLL Hot Reload> Attempts to recompile a UObject DLL and reload it on the fly")
-ManualAutoCompleteList=(Command="au.debug.AudioDebugSound",Desc="<filter> Rejects new USoundBase requests where the sound name does not contain the provided filter")
-ManualAutoCompleteList=(Command="au.debug.AudioGetDynamicSoundVolume",Desc="Gets volume for given sound type ('Class', 'Cue' or 'Wave') with provided name")
-ManualAutoCompleteList=(Command="au.debug.AudioMemReport",Desc="Lists info for audio memory")
-ManualAutoCompleteList=(Command="au.debug.AudioMixerDebugSound",Desc="<filter> With new mixer enabled, rejects new USoundBase requests where the sound name does not contain the provided filter")
-ManualAutoCompleteList=(Command="au.debug.AudioResetAllDynamicSoundVolumes",Desc="Resets all dynamic volumes to unity")
-ManualAutoCompleteList=(Command="au.debug.AudioResetDynamicSoundVolume",Desc="Resets volume for given sound type ('Class', 'Cue' or 'Wave') with provided name to unity")
-ManualAutoCompleteList=(Command="au.debug.AudioSetDynamicSoundVolume",Desc="Name=<name> Type=<type> Vol=<vol> Sets volume for given sound type ('Class', 'Cue' or 'Wave') with provided name")
-ManualAutoCompleteList=(Command="au.debug.AudioSoloSoundClass",Desc="<name> [nonexclusive] Solos sounds using this USoundClass. If nonexclusive, existing solos will persist")
-ManualAutoCompleteList=(Command="au.debug.AudioSoloSoundCue",Desc="<name> [nonexclusive] Solos any type of USoundBase. If nonexclusive, existing solos will persist")
-ManualAutoCompleteList=(Command="au.debug.AudioSoloSoundWave",Desc="<name> [nonexclusive] Solos USoundWave. If nonexclusive, existing solos will persist")
-ManualAutoCompleteList=(Command="au.debug.ClearSoloAudio",Desc="Clears solo'ed object")
-ManualAutoCompleteList=(Command="au.debug.DisableLPF",Desc="Disables low-pass filter")
-ManualAutoCompleteList=(Command="au.debug.DisableEQFilter",Desc="Disables EQ")
-ManualAutoCompleteList=(Command="au.debug.DisableRadio",Desc="Disables radio effect")
-ManualAutoCompleteList=(Command="au.debug.DumpSoundInfo",Desc="Dumps sound information to log")
-ManualAutoCompleteList=(Command="au.debug.EnableRadio",Desc="Enables radio effect")
-ManualAutoCompleteList=(Command="au.debug.IsolateDryAudio",Desc="Isolates dry audio")
-ManualAutoCompleteList=(Command="au.debug.IsolateReverb",Desc="Isolates reverb")
-ManualAutoCompleteList=(Command="au.debug.ListAudioComponents",Desc="Dumps a detailed list of all AudioComponent objects")
-ManualAutoCompleteList=(Command="au.debug.ListSoundClasses",Desc="Lists a summary of loaded sound collated by class")
-ManualAutoCompleteList=(Command="au.debug.ListSoundClassVolumes",Desc="Lists all sound class volumes")
-ManualAutoCompleteList=(Command="au.debug.ListSoundDurations",Desc="Lists durations of all active sounds")
-ManualAutoCompleteList=(Command="au.debug.ListWaves",Desc="List the WaveInstances and whether they have a source")
-ManualAutoCompleteList=(Command="au.debug.PlayAllPIEAudio",Desc="Toggls whether or not all devices should play their audio")
-ManualAutoCompleteList=(Command="au.debug.PlaySoundCue",Desc="Plays the given soundcue")
-ManualAutoCompleteList=(Command="au.debug.PlaySoundWave",Desc="<name> Plays the given soundwave")
-ManualAutoCompleteList=(Command="au.debug.ResetSoundState",Desc="Resets volumes to default and removes test filters")
-ManualAutoCompleteList=(Command="au.debug.SetBaseSoundMix",Desc="<MixName> Sets the base sound mix")
-ManualAutoCompleteList=(Command="au.debug.ShowSoundClassHierarchy",Desc="")
-ManualAutoCompleteList=(Command="au.debug.SoloAudio",Desc="Solos the audio device associated with the parent world")
-ManualAutoCompleteList=(Command="au.debug.SoundClassFixup",Desc="Deprecated")
-ManualAutoCompleteList=(Command="au.debug.TestLFEBleed",Desc="Sets LPF to max for all sources")
-ManualAutoCompleteList=(Command="au.debug.TestLPF",Desc="Sets LPF to max for all sources")
-ManualAutoCompleteList=(Command="au.debug.TestStereoBleed",Desc="Test bleeding stereo sounds fully to the rear speakers")
-ManualAutoCompleteList=(Command="au.debug.ToggleHRTFForAll",Desc="Toggles whether or not HRTF spatialization is enabled for all")
-ManualAutoCompleteList=(Command="au.debug.ToggleSpatExt",Desc="Toggles enablement of the Spatial Audio Extension")
-ManualAutoCompleteList=(Command="DisableAllScreenMessages",Desc="Disables all on-screen warnings/messages")
-ManualAutoCompleteList=(Command="EnableAllScreenMessages",Desc="Enables all on-screen warnings/messages")
-ManualAutoCompleteList=(Command="ToggleAllScreenMessages",Desc="Toggles display state of all on-screen warnings/messages")
-ManualAutoCompleteList=(Command="ToggleAsyncCompute",Desc="Toggles AsyncCompute for platforms that have it")
-ManualAutoCompleteList=(Command="ToggleRenderingThread",Desc="Toggles the rendering thread for platforms that have it")
-ManualAutoCompleteList=(Command="CaptureMode",Desc="Toggles display state of all on-screen warnings/messages")
-ManualAutoCompleteList=(Command="ShowDebug None",Desc="Toggles ShowDebug w/ current debug type selection")
-ManualAutoCompleteList=(Command="ShowDebug Reset",Desc="Turns off ShowDebug, and clears debug type selection")
-ManualAutoCompleteList=(Command="ShowDebug NET",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug PHYSICS",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug COLLISION",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug AI",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug CAMERA",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug WEAPON",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug ANIMATION",Desc="Toggles display state of animation debug data")
-ManualAutoCompleteList=(Command="ShowDebug BONES",Desc="Toggles display of skeletalmesh bones")
-ManualAutoCompleteList=(Command="ShowDebug INPUT",Desc=)
-ManualAutoCompleteList=(Command="ShowDebug FORCEFEEDBACK",Desc="Toggles display of current force feedback values and what is contributing to that calculation")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory 3DBONES",Desc="With ShowDebug Bones: Toggles bone rendering between single lines and a more complex 3D model per bone")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory SYNCGROUPS",Desc="With ShowDebug Animation: Toggles display of sync group data")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory MONTAGES",Desc="With ShowDebug Animation: Toggles display of montage data")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory GRAPH",Desc="With ShowDebug Animation: Toggles display of animation blueprint graph")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory CURVES",Desc="With ShowDebug Animation: Toggles display of curve data")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory NOTIFIES",Desc="With ShowDebug Animation: Toggles display of notify data")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory FULLGRAPH",Desc="With ShowDebug Animation: Toggles graph display between active nodes only and all nodes")
-ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory FULLBLENDSPACEDISPLAY",Desc="With ShowDebug Animation: Toggles display of sample blend weights on blendspaces")
-ManualAutoCompleteList=(Command="ShowDebugForReticleTargetToggle ",Desc="<DesiredClass> Toggles 'ShowDebug' from showing debug info between reticle target actor (of subclass <DesiredClass>) and camera view target")
-ManualAutoCompleteList=(Command="Stat SoundCues",Desc="Deprecated (Use au.debug.SoundCues): Shows active SoundCues")
-ManualAutoCompleteList=(Command="Stat SoundMixes",Desc="Deprecated (Use au.debug.SoundMixes): Shows active SoundMixes")
-ManualAutoCompleteList=(Command="Stat SoundModulators",Desc="Deprecated (Use au.debug.SoundModulators): Shows modulator debug info as provided by active audio modulation plugin")
-ManualAutoCompleteList=(Command="Stat SoundModulatorsHelp",Desc="Deprecated (Use au.debug.SoundModulatorsHelp):Shows modulator debug help provided by active audio modulation plugin")
-ManualAutoCompleteList=(Command="Stat SoundReverb",Desc="Deprecated (Use au.debug.SoundReverb): Shows active SoundReverb")
-ManualAutoCompleteList=(Command="Stat SoundWaves",Desc="Deprecated (Use au.debug.SoundWaves): Shows active SoundWaves")
-ManualAutoCompleteList=(Command="Stat Sounds",Desc="Deprecated (Use au.debug.Sounds): <?> <sort=class|distance|name|priority|time|volume|waves> <-debug> Shows all active sounds. Displays value sorted by when sort is set")
-ManualAutoCompleteList=(Command="ScriptAudit LongestFunctions",Desc="List functions that contain the most bytecode - optionally include # of entries to list")
-ManualAutoCompleteList=(Command="ScriptAudit FrequentFunctionsCalled",Desc="List functions that are most frequently called from bytecode - optionally include # of entries to list")
-ManualAutoCompleteList=(Command="ScriptAudit FrequentInstructions",Desc="List most frequently used instructions - optionally include # of entries to list")
-ManualAutoCompleteList=(Command="ScriptAudit TotalBytecodeSize",Desc="Gather total size of bytecode in bytes of currently loaded functions")
-ManualAutoCompleteList=(Command="Audio3dVisualize",Desc="Shows locations of sound sources playing (white text) and their left and right channel locations respectively (red and green). Virtualized loops (if enabled) display in blue.")
-ManualAutoCompleteList=(Command="StartMovieCapture",Desc=)
-ManualAutoCompleteList=(Command="StopMovieCapture",Desc=)
-ManualAutoCompleteList=(Command="TraceTag",Desc="Draw traces that use the specified tag")
-ManualAutoCompleteList=(Command="TraceTagAll",Desc="Draw all scene queries regardless of the trace tag")
-ManualAutoCompleteList=(Command="VisLog",Desc="Launches Log Visualizer tool")
-ManualAutoCompleteList=(Command="CycleNavDrawn",Desc="Cycles through navigation data (navmeshes for example) to draw one at a time")
-ManualAutoCompleteList=(Command="Log ",Desc="<category> <level> Change verbosity level for a log category")
-ManualAutoCompleteList=(Command="Log list",Desc="<search string> Search for log categories")
-ManualAutoCompleteList=(Command="Log reset",Desc="Undo any changes to log verbosity")
-ManualAutoCompleteList=(Command="RecordAnimation ActorName AnimName",Desc="Record animation for a specified actor to the specified file")
-ManualAutoCompleteList=(Command="StopRecordingAnimation All",Desc="Stop all recording animations")
-ManualAutoCompleteList=(Command="RecordSequence Filter ActorOrClassName",Desc="Record a level sequence from gameplay. Filter=<All|Actor|Class>")
-ManualAutoCompleteList=(Command="StopRecordingSequence",Desc="Stop recording the current sequence. Only one sequence recording can be active at one time.")
-ManualAutoCompleteList=(Command="RecordTake Filter ActorOrClassName",Desc="Record a level sequence from gameplay. Filter=<All|Actor|Class>")
-ManualAutoCompleteList=(Command="StopRecordingTake",Desc="Stop recording the current sequence. Only one sequence recording can be active at one time.")
-ManualAutoCompleteList=(Command="FreezeRendering",Desc="Toggle freezing of most aspects of rendering (such as visibility calculations), useful in conjunction with ToggleDebugCamera to fly around and see how frustum and occlusion culling is working")
-ManualAutoCompleteList=(Command="ProfileGPU",Desc="Profile one frame of rendering commands sent to the GPU")
-ManualAutoCompleteList=(Command="ProfileGPUHitches",Desc="Toggle profiling of GPU hitches.")
-ManualAutoCompleteList=(Command="DumpGPU",Desc="Dump one frame of rendering intermediary resources to disk.")
-ManualAutoCompleteList=(Command="Automation",Desc="Run an automation command (e.g., Automation RunTests TestName)")
-ManualAutoCompleteList=(Command="CsvProfile Start",Desc="Start CSV profiling.")
-ManualAutoCompleteList=(Command="CsvProfile Stop",Desc="Stop CSV profiling.")
-ManualAutoCompleteList=(Command="NetProfile Enable",Desc="Start network profiling.")
-ManualAutoCompleteList=(Command="NetProfile Disable",Desc="Stop network profiling.")
+ManualAutoCompleteList=(Command="Exit",Desc="Exits the game")
+ManualAutoCompleteList=(Command="DebugCreatePlayer 1",Desc="")
+ManualAutoCompleteList=(Command="ToggleDrawEvents",Desc="Toggles annotations for shader debugging with Pix, Razor or similar GPU capture tools")
+ManualAutoCompleteList=(Command="Shot",Desc="Make a screenshot")
+ManualAutoCompleteList=(Command="RecompileShaders changed",Desc="Recompile shaders that have any changes on their source files")
+ManualAutoCompleteList=(Command="RecompileShaders global",Desc="Recompile global shaders that have any changes on their source files")
+ManualAutoCompleteList=(Command="RecompileShaders material ",Desc="Recompile shaders for a specific material if it\'s source files have changed")
+ManualAutoCompleteList=(Command="RecompileShaders all",Desc="Recompile all shaders that have any changes on their source files")
+ManualAutoCompleteList=(Command="Debug Crash",Desc="Simulates a game thread crash for debugging")
+ManualAutoCompleteList=(Command="Debug RenderCrash",Desc="Simulates a render thread crash for debugging")
+ManualAutoCompleteList=(Command="DumpMaterialStats",Desc="Dump material information")
+ManualAutoCompleteList=(Command="DumpShaderStats",Desc="Dump shader information")
+ManualAutoCompleteList=(Command="DumpShaderPipelineStats",Desc="Dump shader pipeline information")
+ManualAutoCompleteList=(Command="DumpShaderCompileStats",Desc="Dump shader compilation information")
+ManualAutoCompleteList=(Command="DumpGPU -upload",Desc="Dump the GPU\'s intermediary resources and upload to network")
+ManualAutoCompleteList=(Command="StartFPSChart",Desc="after that use StopFPSChart")
+ManualAutoCompleteList=(Command="StopFPSChart",Desc="after that look for the output in Saved/Profiling/FPSChartStats")
+ManualAutoCompleteList=(Command="FreezeAt",Desc="Locks the player view and rendering time.")
+ManualAutoCompleteList=(Command="Open",Desc="<MapName> Opens the specified map, doesn\'t pass previously set options")
+ManualAutoCompleteList=(Command="Travel",Desc="<MapName> Travels to the specified map, passes along previously set options")
+ManualAutoCompleteList=(Command="ServerTravel",Desc="<MapName> Travels to the specified map and brings clients along, passes along previously set options")
+ManualAutoCompleteList=(Command="DisplayAll",Desc="<ClassName> <PropertyName> Display property values for instances of classname")
+ManualAutoCompleteList=(Command="DisplayAllLocation",Desc="<ClassName> Display location for all instances of classname")
+ManualAutoCompleteList=(Command="DisplayAllRotation",Desc="<ClassName> Display rotation for all instances of classname")
+ManualAutoCompleteList=(Command="DisplayClear",Desc="Clears previous DisplayAll entries")
+ManualAutoCompleteList=(Command="FlushPersistentDebugLines",Desc="Clears persistent debug line cache")
+ManualAutoCompleteList=(Command="GetAll ",Desc="<ClassName> <PropertyName> <Name=ObjectInstanceName> <OUTER=ObjectInstanceName> <SHOWDEFAULTS> <SHOWPENDINGKILLS> <DETAILED> Log property values of all instances of classname")
+ManualAutoCompleteList=(Command="GetAllLocation",Desc="<ClassName> Log location for all instances of classname")
+ManualAutoCompleteList=(Command="GetAllRotation",Desc="<ClassName> Log rotation for all instances of classname")
+ManualAutoCompleteList=(Command="Obj List ",Desc="<Class=ClassName> <Type=MetaClass> <Outer=OuterObject> <Package=InsidePackage> <Inside=InsideObject>")
+ManualAutoCompleteList=(Command="Obj ListContentRefs",Desc="<Class=ClassName> <ListClass=ClassName>")
+ManualAutoCompleteList=(Command="Obj Classes",Desc="Shows all classes")
+ManualAutoCompleteList=(Command="Obj Refs",Desc="Name=<ObjectName> [Shortest] [Longest] [All] [External] [Direct] [Full] [Minimal] [GCOnly] [History=<MaxHistoryLevel>] Lists referencers of the specified object")
+ManualAutoCompleteList=(Command="Obj GC",Desc="Runs the UObject Garbage Collector and resets the GC timer.")
+ManualAutoCompleteList=(Command="Obj Dump ",Desc="<ObjectName> [Recurse or Hide/Show=\"category1,...\"] or <Class=ClassName> <Name=ObjectName> [Recurse or Hide/Show=\"category1,...\"] Prints the value of all variables for the specified object")
+ManualAutoCompleteList=(Command="EditActor",Desc="<Class=ClassName> or <Name=ObjectName> or TRACE")
+ManualAutoCompleteList=(Command="EditDefault",Desc="<Class=ClassName>")
+ManualAutoCompleteList=(Command="EditObject",Desc="<Class=ClassName> or <Name=ObjectName> or <ObjectName>")
+ManualAutoCompleteList=(Command="ReloadCfg ",Desc="<Class/ObjectName> Reloads config variables for the specified object/class")
+ManualAutoCompleteList=(Command="ReloadLoc ",Desc="<Class/ObjectName> Reloads localized variables for the specified object/class")
+ManualAutoCompleteList=(Command="Set ",Desc="<ClassName> <PropertyName> <Value> Sets property to value on objectname")
+ManualAutoCompleteList=(Command="SetNoPEC",Desc="<ClassName> <PropertyName> <Value> Sets property to value on objectname without Pre/Post Edit Change notifications")
+ManualAutoCompleteList=(Command="Stat FPS",Desc="Shows FPS counter")
+ManualAutoCompleteList=(Command="Stat UNIT",Desc="Shows hardware unit framerate")
+ManualAutoCompleteList=(Command="Stat DrawCount",Desc="Shows draw counts broken down by category")
+ManualAutoCompleteList=(Command="Stat UnitGraph",Desc="Draws simple unit time graph")
+ManualAutoCompleteList=(Command="Stat NamedEvents",Desc="Stat NamedEvents (Enables named events for external profilers)")
+ManualAutoCompleteList=(Command="Stat VerboseNamedEvents",Desc="Stat VerboseNamedEvents (Enables verbose named events for external profilers)")
+ManualAutoCompleteList=(Command="Stat StartFile",Desc="Stat StartFile (starts a stats capture, creating a new file in the Profiling directory; stop with stat StopFile to close the file)")
+ManualAutoCompleteList=(Command="Stat StopFile",Desc="Stat StopFile (finishes a stats capture started by stat StartFile)")
+ManualAutoCompleteList=(Command="Stat CPULoad",Desc="Stat CPULoad (Shows CPU Utilization)")
+ManualAutoCompleteList=(Command="Stat DUMPHITCHES",Desc="executes dumpstats on hitches - see log")
+ManualAutoCompleteList=(Command="stat D3D11 RHI",Desc="Shows Direct3D 11 stats")
+ManualAutoCompleteList=(Command="Stat LEVELS",Desc="Displays level streaming info")
+ManualAutoCompleteList=(Command="Stat GAME",Desc="Displays game performance stats")
+ManualAutoCompleteList=(Command="Stat MEMORY",Desc="Displays memory stats")
+ManualAutoCompleteList=(Command="Stat PHYSICS",Desc="Displays physics performance stats")
+ManualAutoCompleteList=(Command="Stat STREAMING",Desc="Displays basic texture streaming stats")
+ManualAutoCompleteList=(Command="Stat STREAMINGDETAILS",Desc="Displays detailed texture streaming stats")
+ManualAutoCompleteList=(Command="Stat GPU",Desc="Displays GPU stats for the frame")
+ManualAutoCompleteList=(Command="Stat COLLISION",Desc="")
+ManualAutoCompleteList=(Command="Stat PARTICLES",Desc="")
+ManualAutoCompleteList=(Command="Stat SCRIPT",Desc="")
+ManualAutoCompleteList=(Command="Stat AUDIO",Desc="")
+ManualAutoCompleteList=(Command="Stat ANIM",Desc="")
+ManualAutoCompleteList=(Command="Stat NET",Desc="")
+ManualAutoCompleteList=(Command="Stat LIST",Desc="<Groups/Sets/Group> List groups of stats, saved sets, or specific stats within a specified group")
+ManualAutoCompleteList=(Command="Stat splitscreen",Desc="")
+ManualAutoCompleteList=(Command="MemReport",Desc="Outputs memory stats to a profile file. -Full gives more data, -Log outputs to the log")
+ManualAutoCompleteList=(Command="ListTextures",Desc="[Streaming|NonStreaming|Forced] [-Alphasort] [-csv] Lists all loaded textures and their current memory footprint")
+ManualAutoCompleteList=(Command="ListStreamingTextures",Desc="Lists info for all streaming textures")
+ManualAutoCompleteList=(Command="ListAnims",Desc="Lists info for all animations")
+ManualAutoCompleteList=(Command="ListSkeletalMeshes",Desc="Lists info for all skeletal meshes")
+ManualAutoCompleteList=(Command="ListStaticMeshes",Desc="Lists info for all static meshes")
+ManualAutoCompleteList=(Command="InvestigateTexture",Desc="Shows streaming info about the specified texture")
+ManualAutoCompleteList=(Command="DumpTextureStreamingStats",Desc="Dump current streaming stats (e.g. pool capacity) to the log")
+ManualAutoCompleteList=(Command="RestartLevel",Desc="Restarts the level")
+ManualAutoCompleteList=(Command="Module List",Desc="Lists all known modules")
+ManualAutoCompleteList=(Command="Module Load",Desc="Attempts to load the specified module name")
+ManualAutoCompleteList=(Command="Module Unload",Desc="Unloads the specified module name")
+ManualAutoCompleteList=(Command="Module Reload",Desc="Reloads the specified module name, unloading it first if needed")
+ManualAutoCompleteList=(Command="Module Recompile",Desc="Attempts to recompile a module, first unloading it if needed")
+ManualAutoCompleteList=(Command="HotReload",Desc="<UObject DLL Hot Reload> Attempts to recompile a UObject DLL and reload it on the fly")
+ManualAutoCompleteList=(Command="au.debug.AudioDebugSound",Desc="<filter> Rejects new USoundBase requests where the sound name does not contain the provided filter")
+ManualAutoCompleteList=(Command="au.debug.AudioGetDynamicSoundVolume",Desc="Gets volume for given sound type (\'Class\', \'Cue\' or \'Wave\') with provided name")
+ManualAutoCompleteList=(Command="au.debug.AudioMemReport",Desc="Lists info for audio memory")
+ManualAutoCompleteList=(Command="au.debug.AudioMixerDebugSound",Desc="<filter> With new mixer enabled, rejects new USoundBase requests where the sound name does not contain the provided filter")
+ManualAutoCompleteList=(Command="au.debug.AudioResetAllDynamicSoundVolumes",Desc="Resets all dynamic volumes to unity")
+ManualAutoCompleteList=(Command="au.debug.AudioResetDynamicSoundVolume",Desc="Resets volume for given sound type (\'Class\', \'Cue\' or \'Wave\') with provided name to unity")
+ManualAutoCompleteList=(Command="au.debug.AudioSetDynamicSoundVolume",Desc="Name=<name> Type=<type> Vol=<vol> Sets volume for given sound type (\'Class\', \'Cue\' or \'Wave\') with provided name")
+ManualAutoCompleteList=(Command="au.debug.AudioSoloSoundClass",Desc="<name> [nonexclusive] Solos sounds using this USoundClass. If nonexclusive, existing solos will persist")
+ManualAutoCompleteList=(Command="au.debug.AudioSoloSoundCue",Desc="<name> [nonexclusive] Solos any type of USoundBase. If nonexclusive, existing solos will persist")
+ManualAutoCompleteList=(Command="au.debug.AudioSoloSoundWave",Desc="<name> [nonexclusive] Solos USoundWave. If nonexclusive, existing solos will persist")
+ManualAutoCompleteList=(Command="au.debug.ClearSoloAudio",Desc="Clears solo\'ed object")
+ManualAutoCompleteList=(Command="au.debug.DisableLPF",Desc="Disables low-pass filter")
+ManualAutoCompleteList=(Command="au.debug.DisableEQFilter",Desc="Disables EQ")
+ManualAutoCompleteList=(Command="au.debug.DisableRadio",Desc="Disables radio effect")
+ManualAutoCompleteList=(Command="au.debug.DumpSoundInfo",Desc="Dumps sound information to log")
+ManualAutoCompleteList=(Command="au.debug.EnableRadio",Desc="Enables radio effect")
+ManualAutoCompleteList=(Command="au.debug.IsolateDryAudio",Desc="Isolates dry audio")
+ManualAutoCompleteList=(Command="au.debug.IsolateReverb",Desc="Isolates reverb")
+ManualAutoCompleteList=(Command="au.debug.ListAudioComponents",Desc="Dumps a detailed list of all AudioComponent objects")
+ManualAutoCompleteList=(Command="au.debug.ListSoundClasses",Desc="Lists a summary of loaded sound collated by class")
+ManualAutoCompleteList=(Command="au.debug.ListSoundClassVolumes",Desc="Lists all sound class volumes")
+ManualAutoCompleteList=(Command="au.debug.ListSoundDurations",Desc="Lists durations of all active sounds")
+ManualAutoCompleteList=(Command="au.debug.ListWaves",Desc="List the WaveInstances and whether they have a source")
+ManualAutoCompleteList=(Command="au.debug.PlayAllPIEAudio",Desc="Toggls whether or not all devices should play their audio")
+ManualAutoCompleteList=(Command="au.debug.PlaySoundCue",Desc="Plays the given soundcue")
+ManualAutoCompleteList=(Command="au.debug.PlaySoundWave",Desc="<name> Plays the given soundwave")
+ManualAutoCompleteList=(Command="au.debug.ResetSoundState",Desc="Resets volumes to default and removes test filters")
+ManualAutoCompleteList=(Command="au.debug.SetBaseSoundMix",Desc="<MixName> Sets the base sound mix")
+ManualAutoCompleteList=(Command="au.debug.ShowSoundClassHierarchy",Desc="")
+ManualAutoCompleteList=(Command="au.debug.SoloAudio",Desc="Solos the audio device associated with the parent world")
+ManualAutoCompleteList=(Command="au.debug.SoundClassFixup",Desc="Deprecated")
+ManualAutoCompleteList=(Command="au.debug.TestLFEBleed",Desc="Sets LPF to max for all sources")
+ManualAutoCompleteList=(Command="au.debug.TestLPF",Desc="Sets LPF to max for all sources")
+ManualAutoCompleteList=(Command="au.debug.TestStereoBleed",Desc="Test bleeding stereo sounds fully to the rear speakers")
+ManualAutoCompleteList=(Command="au.debug.ToggleHRTFForAll",Desc="Toggles whether or not HRTF spatialization is enabled for all")
+ManualAutoCompleteList=(Command="au.debug.ToggleSpatExt",Desc="Toggles enablement of the Spatial Audio Extension")
+ManualAutoCompleteList=(Command="DisableAllScreenMessages",Desc="Disables all on-screen warnings/messages")
+ManualAutoCompleteList=(Command="EnableAllScreenMessages",Desc="Enables all on-screen warnings/messages")
+ManualAutoCompleteList=(Command="ToggleAllScreenMessages",Desc="Toggles display state of all on-screen warnings/messages")
+ManualAutoCompleteList=(Command="ToggleAsyncCompute",Desc="Toggles AsyncCompute for platforms that have it")
+ManualAutoCompleteList=(Command="ToggleRenderingThread",Desc="Toggles the rendering thread for platforms that have it")
+ManualAutoCompleteList=(Command="CaptureMode",Desc="Toggles display state of all on-screen warnings/messages")
+ManualAutoCompleteList=(Command="ShowDebug None",Desc="Toggles ShowDebug w/ current debug type selection")
+ManualAutoCompleteList=(Command="ShowDebug Reset",Desc="Turns off ShowDebug, and clears debug type selection")
+ManualAutoCompleteList=(Command="ShowDebug NET",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug PHYSICS",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug COLLISION",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug AI",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug CAMERA",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug WEAPON",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug ANIMATION",Desc="Toggles display state of animation debug data")
+ManualAutoCompleteList=(Command="ShowDebug BONES",Desc="Toggles display of skeletalmesh bones")
+ManualAutoCompleteList=(Command="ShowDebug INPUT",Desc="")
+ManualAutoCompleteList=(Command="ShowDebug FORCEFEEDBACK",Desc="Toggles display of current force feedback values and what is contributing to that calculation")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory 3DBONES",Desc="With ShowDebug Bones: Toggles bone rendering between single lines and a more complex 3D model per bone")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory SYNCGROUPS",Desc="With ShowDebug Animation: Toggles display of sync group data")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory MONTAGES",Desc="With ShowDebug Animation: Toggles display of montage data")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory GRAPH",Desc="With ShowDebug Animation: Toggles display of animation blueprint graph")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory CURVES",Desc="With ShowDebug Animation: Toggles display of curve data")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory NOTIFIES",Desc="With ShowDebug Animation: Toggles display of notify data")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory FULLGRAPH",Desc="With ShowDebug Animation: Toggles graph display between active nodes only and all nodes")
+ManualAutoCompleteList=(Command="ShowDebugToggleSubCategory FULLBLENDSPACEDISPLAY",Desc="With ShowDebug Animation: Toggles display of sample blend weights on blendspaces")
+ManualAutoCompleteList=(Command="ShowDebugForReticleTargetToggle ",Desc="<DesiredClass> Toggles \'ShowDebug\' from showing debug info between reticle target actor (of subclass <DesiredClass>) and camera view target")
+ManualAutoCompleteList=(Command="Stat SoundCues",Desc="Deprecated (Use au.debug.SoundCues): Shows active SoundCues")
+ManualAutoCompleteList=(Command="Stat SoundMixes",Desc="Deprecated (Use au.debug.SoundMixes): Shows active SoundMixes")
+ManualAutoCompleteList=(Command="Stat SoundModulators",Desc="Deprecated (Use au.debug.SoundModulators): Shows modulator debug info as provided by active audio modulation plugin")
+ManualAutoCompleteList=(Command="Stat SoundModulatorsHelp",Desc="Deprecated (Use au.debug.SoundModulatorsHelp):Shows modulator debug help provided by active audio modulation plugin")
+ManualAutoCompleteList=(Command="Stat SoundReverb",Desc="Deprecated (Use au.debug.SoundReverb): Shows active SoundReverb")
+ManualAutoCompleteList=(Command="Stat SoundWaves",Desc="Deprecated (Use au.debug.SoundWaves): Shows active SoundWaves")
+ManualAutoCompleteList=(Command="Stat Sounds",Desc="Deprecated (Use au.debug.Sounds): <?> <sort=class|distance|name|priority|time|volume|waves> <-debug> Shows all active sounds. Displays value sorted by when sort is set")
+ManualAutoCompleteList=(Command="ScriptAudit LongestFunctions",Desc="List functions that contain the most bytecode - optionally include # of entries to list")
+ManualAutoCompleteList=(Command="ScriptAudit FrequentFunctionsCalled",Desc="List functions that are most frequently called from bytecode - optionally include # of entries to list")
+ManualAutoCompleteList=(Command="ScriptAudit FrequentInstructions",Desc="List most frequently used instructions - optionally include # of entries to list")
+ManualAutoCompleteList=(Command="ScriptAudit TotalBytecodeSize",Desc="Gather total size of bytecode in bytes of currently loaded functions")
+ManualAutoCompleteList=(Command="Audio3dVisualize",Desc="Shows locations of sound sources playing (white text) and their left and right channel locations respectively (red and green). Virtualized loops (if enabled) display in blue.")
+ManualAutoCompleteList=(Command="StartMovieCapture",Desc="")
+ManualAutoCompleteList=(Command="StopMovieCapture",Desc="")
+ManualAutoCompleteList=(Command="TraceTag",Desc="Draw traces that use the specified tag")
+ManualAutoCompleteList=(Command="TraceTagAll",Desc="Draw all scene queries regardless of the trace tag")
+ManualAutoCompleteList=(Command="VisLog",Desc="Launches Log Visualizer tool")
+ManualAutoCompleteList=(Command="CycleNavDrawn",Desc="Cycles through navigation data (navmeshes for example) to draw one at a time")
+ManualAutoCompleteList=(Command="Log ",Desc="<category> <level> Change verbosity level for a log category")
+ManualAutoCompleteList=(Command="Log list",Desc="<search string> Search for log categories")
+ManualAutoCompleteList=(Command="Log reset",Desc="Undo any changes to log verbosity")
+ManualAutoCompleteList=(Command="RecordAnimation ActorName AnimName",Desc="Record animation for a specified actor to the specified file")
+ManualAutoCompleteList=(Command="StopRecordingAnimation All",Desc="Stop all recording animations")
+ManualAutoCompleteList=(Command="RecordSequence Filter ActorOrClassName",Desc="Record a level sequence from gameplay. Filter=<All|Actor|Class>")
+ManualAutoCompleteList=(Command="StopRecordingSequence",Desc="Stop recording the current sequence. Only one sequence recording can be active at one time.")
+ManualAutoCompleteList=(Command="RecordTake Filter ActorOrClassName",Desc="Record a level sequence from gameplay. Filter=<All|Actor|Class>")
+ManualAutoCompleteList=(Command="StopRecordingTake",Desc="Stop recording the current sequence. Only one sequence recording can be active at one time.")
+ManualAutoCompleteList=(Command="FreezeRendering",Desc="Toggle freezing of most aspects of rendering (such as visibility calculations), useful in conjunction with ToggleDebugCamera to fly around and see how frustum and occlusion culling is working")
+ManualAutoCompleteList=(Command="ProfileGPU",Desc="Profile one frame of rendering commands sent to the GPU")
+ManualAutoCompleteList=(Command="ProfileGPUHitches",Desc="Toggle profiling of GPU hitches.")
+ManualAutoCompleteList=(Command="DumpGPU",Desc="Dump one frame of rendering intermediary resources to disk.")
+ManualAutoCompleteList=(Command="Automation",Desc="Run an automation command (e.g., Automation RunTests TestName)")
+ManualAutoCompleteList=(Command="CsvProfile Start",Desc="Start CSV profiling.")
+ManualAutoCompleteList=(Command="CsvProfile Stop",Desc="Stop CSV profiling.")
+ManualAutoCompleteList=(Command="NetProfile Enable",Desc="Start network profiling.")
+ManualAutoCompleteList=(Command="NetProfile Disable",Desc="Stop network profiling.")
+ManualAutoCompleteList=(Command="ShowDebug EnhancedInput",Desc="Displays debug information about the current state of any Enhanced Input Mapping Contexts")
+ManualAutoCompleteList=(Command="ShowDebug WorldSubsystemInput",Desc="Displays debug information about the current state of any Enhanced Input Mapping Contexts applied to the Enhanced Input world subsystem.")
+ManualAutoCompleteList=(Command="ShowDebug InputSettings",Desc="Displays debug information any user input settings, such as player mappable keys.")
+ManualAutoCompleteList=(Command="ShowDebug DeviceProperty",Desc="Display debug information about currently active Input Device Properties")
+ManualAutoCompleteList=(Command="ShowDebug Devices",Desc="Displays all current Platform Users and their Input Devices.")
-AutoCompleteMapPaths=Content/Maps
+AutoCompleteMapPaths=Content/Maps
BackgroundOpacityPercentage=85.000000
bOrderTopToBottom=False
bDisplayHelpInAutoComplete=True
InputColor=(B=230,G=230,R=230,A=255)
HistoryColor=(B=180,G=180,R=180,A=255)
AutoCompleteCommandColor=(B=185,G=109,R=144,A=255)
AutoCompleteCVarColor=(B=86,G=158,R=86,A=255)
AutoCompleteFadedColor=(B=100,G=100,R=100,A=255)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,30 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "GM",
"Description": "Rive GM tests for unreal",
"Category": "Other",
"CreatedBy": "Rive Inc",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "GM",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "Rive",
"Enabled": true
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,66 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using System.IO;
using UnrealBuildTool;
public class GM : ModuleRules
{
public GM(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
var fullPluginPath = Path.GetFullPath(Path.Combine(PluginDirectory, "../"));
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
Path.Combine(fullPluginPath, "Rive", "Source", "RiveRenderer", "Private")
});
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"CoreUObject",
"InputCore",
"Projects",
"RHI",
"RenderCore",
"Rive",
"RiveLibrary",
"RiveRenderer",
"Engine",
"GMLibrary",
// ... add other public dependencies that you statically link with here ...
}
);
#if UE_UE_5_0_OR_LATER
PublicDependencyModuleNames.Add("RHICore");
#else
#endif
PrivateDependencyModuleNames.AddRange(
new string[]
{
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}

View File

@@ -0,0 +1,22 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "GM.h"
#include "Misc/MessageDialog.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#include "Misc/Paths.h"
#include "HAL/PlatformProcess.h"
#include "gms.hpp"
#include "goldens.hpp"
#define LOCTEXT_NAMESPACE "FGMModule"
void FGMModule::StartupModule() {}
void FGMModule::ShutdownModule() {}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FGMModule, GM)
DEFINE_LOG_CATEGORY(GM_Log);

View File

@@ -0,0 +1,527 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "GMTestingManager.h"
#include "IRiveRenderer.h"
#include "IRiveRendererModule.h"
#include "Rive/RiveTextureObject.h"
#include "GM.h"
#include "goldens.hpp"
#if WITH_EDITOR
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#endif
#include "Platform/RenderContextRHIImpl.hpp"
AGMTestingManager::AGMTestingManager()
{
StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
RootComponent = StaticMeshComponent;
}
void AGMTestingManager::StartTesting()
{
ENQUEUE_RENDER_COMMAND(GMGoldenMainCommand)
([this](FRHICommandListImmediate& RHICmdList) {
FString CmdLine = FCommandLine::GetOriginal();
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::StartTesting() Start testing with command line "
"and %s cwd %s"),
*CmdLine,
*FPaths::LaunchDir());
TArray<FString> CommandLineOptions;
auto Parsed = CmdLine.ParseIntoArray(CommandLineOptions, TEXT(" "));
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::StartTesting() Processing %i arguments"),
Parsed);
int argc = 0;
// all possible values + some padding
// we ignore -p since we are always single threaded
const char* argv[16];
if (CommandLineOptions.Num() > 1)
{
argv[argc++] = TCHAR_TO_ANSI(*CommandLineOptions[0]);
}
else
{
argv[argc++] = TCHAR_TO_ANSI(*FPaths::LaunchDir());
}
for (size_t i = 1; i < CommandLineOptions.Num(); ++i)
{
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::StartTesting() Processing {%s}"),
*CommandLineOptions[i]);
if (CommandLineOptions[i] == TEXT("--test_harness"))
{
argv[argc++] = "--test_harness";
argv[argc++] = TCHAR_TO_ANSI(*CommandLineOptions[++i]);
}
else if (CommandLineOptions[i] == TEXT("-o"))
{
FString output = FPaths::Combine(FPaths::LaunchDir(), CommandLineOptions[++i]);
output = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*output);
argv[argc++] = "--output";
argv[argc++] = TCHAR_TO_ANSI(*output);
}
else if (CommandLineOptions[i] == TEXT("--output"))
{
FString output = FPaths::Combine(FPaths::LaunchDir(), CommandLineOptions[++i]);
output = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*output);
argv[argc++] = "--output";
argv[argc++] = TCHAR_TO_ANSI(*output);
}
else if (CommandLineOptions[i] == TEXT("-s"))
{
FString src = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(
*CommandLineOptions[++i]);
argv[argc++] = "--src";
argv[argc++] = TCHAR_TO_ANSI(*src);
}
else if (CommandLineOptions[i] == TEXT("--src"))
{
FString src = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(
*CommandLineOptions[++i]);
argv[argc++] = "--src";
argv[argc++] = TCHAR_TO_ANSI(*src);
}
else if (CommandLineOptions[i] == TEXT("--match"))
{
argv[argc++] = "--match";
argv[argc++] = TCHAR_TO_ANSI(*CommandLineOptions[++i]);
}
else if (CommandLineOptions[i] == TEXT("-m"))
{
argv[argc++] = "--match";
argv[argc++] = TCHAR_TO_ANSI(*CommandLineOptions[++i]);
}
else if (CommandLineOptions[i] == TEXT("--fast-png"))
{
argv[argc++] = "--fast-png";
}
else if (CommandLineOptions[i] == TEXT("-f"))
{
argv[argc++] = "--fast-png";
}
else if (CommandLineOptions[i] == TEXT("--interactive"))
{
argv[argc++] = "--interactive";
}
else if (CommandLineOptions[i] == TEXT("-i"))
{
argv[argc++] = "--interactive";
}
else if (CommandLineOptions[i] == TEXT("--backend"))
{
++i;
UE_LOG(GM_Log,
Warning,
TEXT("Ingoring backend command because it is hardcoded to rhi"));
}
else if (CommandLineOptions[i] == TEXT("-b"))
{
++i;
UE_LOG(GM_Log,
Warning,
TEXT("Ingoring backend command because it is hardcoded to rhi"));
}
else if (CommandLineOptions[i] == TEXT("--headless"))
{
argv[argc++] = "--headless";
}
else if (CommandLineOptions[i] == TEXT("-h"))
{
argv[argc++] = "--headless";
}
else if (CommandLineOptions[i] == TEXT("--verbose"))
{
argv[argc++] = "--verbose";
}
else if (CommandLineOptions[i] == TEXT("-v"))
{
argv[argc++] = "--verbose";
}
}
argv[argc++] = "--backend";
argv[argc++] = "rhi";
if (bShouldAddTestArguments)
{
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::InitTesting() gms_main adding test params"));
argv[argc++] = "--verbose";
FString ProjectDir = FPaths::ProjectDir();
ProjectDir =
IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*ProjectDir);
argv[argc++] = "--output";
argv[argc++] = TCHAR_TO_ANSI(*FPaths::Combine(ProjectDir, "output"));
if (TestingType == EGMTestingType::Golden)
{
FString RivePath =
FPaths::Combine(FPaths::ProjectDir(), "../../../../gold/rivs/Bear.riv");
RivePath =
IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*RivePath);
argv[argc++] = "--src";
argv[argc++] = TCHAR_TO_ANSI(*RivePath);
}
}
FString ArgLog;
for (size_t i = 0; i < argc; i++)
{
ArgLog += argv[i] + FString(" ");
}
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::StartTesting() starting gms with argc %i argv %s"),
argc,
*ArgLog);
switch (TestingType)
{
case EGMTestingType::GM:
RunGMs(argc, argv);
break;
case EGMTestingType::Golden:
RunGoldens(argc, argv);
break;
case EGMTestingType::Both:
RunGMs(argc, argv);
RunGoldens(argc, argv);
}
// we have to reset this here because both gms and goldens delete the window
TestingWindow = nullptr;
AsyncTask(ENamedThreads::GameThread, [this]() {
if (bShouldExitOnFinish)
{
#if WITH_EDITOR
UKismetSystemLibrary::QuitGame(GetWorld(),
UGameplayStatics::GetPlayerController(GetWorld(), 0),
EQuitPreference::Type::Quit,
false);
#else
FGenericPlatformMisc::RequestExit(false);
#endif
}
else
{
OnGmTestingFinished.Broadcast();
}
});
});
}
void AGMTestingManager::DeInitTesting() {}
void AGMTestingManager::SetDMTexture(UTexture2DDynamic* Texture, bool MeshIsVisible)
{
check(DM);
DM->SetTextureParameterValue("texture", Texture);
StaticMeshComponent->SetHiddenInGame(!MeshIsVisible, true);
}
void AGMTestingManager::RunGM(UPARAM(ref) FGMData& GM, bool ShouldGenerateDisplayTexture)
{
TestingWindow->isGoldens = false;
if (GM.registry_position == nullptr)
{
UE_LOG(GM_Log, Error, TEXT("Failed to find gm of name %s"), *GM.Name);
return;
}
if (ShouldGenerateDisplayTexture)
{
UE_LOG(GM_Log, Display, TEXT("Generating display texture for gm named %s"), *GM.Name);
if (GM.Width == 0 || GM.Height == 0)
{
size_t width, height;
if (gms_registry_get_size(GM.registry_position, width, height))
{
GM.Width = width;
GM.Height = height;
}
else
{
UE_LOG(GM_Log, Error, TEXT("Failed to get size of gm named %s"), *GM.Name);
return;
}
}
GM.RiveTexture = NewObject<URiveTexture>(GetOuter());
GM.RiveTexture->OnResourceInitializedOnRenderThread.AddUObject(
this,
&AGMTestingManager::RunSpecificGM_RenderThread);
TestingWindow->RenderTexture = GM.RiveTexture;
GMToRun = &GM;
GM.RiveTexture->ResizeRenderTargets(FIntPoint(GM.Width, GM.Height));
}
}
void AGMTestingManager::RunGolden(FGoldenData& Golden, bool ShouldGenerateDisplayTexture)
{
TestingWindow->isGoldens = true;
}
void AGMTestingManager::BeginPlay()
{
DM = StaticMeshComponent->CreateDynamicMaterialInstance(0);
CustomTestTexture = NewObject<URiveTexture>(GetOuter());
auto& RenderModule = IRiveRendererModule::Get();
auto InRenderer = RenderModule.GetRenderer();
InRenderer->CallOrRegister_OnInitialized(
IRiveRenderer::FOnRendererInitialized::FDelegate::CreateUObject(
this,
&AGMTestingManager::RiveReady));
}
void AGMTestingManager::RiveReady(IRiveRenderer* InRiveRenderer)
{
Renderer = InRiveRenderer;
bRiveReady = true;
// just in case we didnt run gms yet
if (TestingWindow)
delete TestingWindow;
TestingWindow = new UnrealTestingWindow(this, InRiveRenderer);
::TestingWindow::Set(TestingWindow);
if (bShouldGenerateGMList)
{
// populate GMList with info
REGISTRY_HANDLE registery_handle = rivegm::GMRegistry::head();
while (registery_handle)
{
FGMData GMData;
std::string GMName;
if (gms_registry_get_name(registery_handle, GMName))
{
GMData.Name.AppendChars(GMName.c_str(), GMName.size());
}
size_t width, height;
if (gms_registry_get_size(registery_handle, width, height))
{
GMData.Width = width;
GMData.Height = height;
}
GMData.registry_position = registery_handle;
GMList.Add(GMData);
registery_handle = gms_registry_get_next(registery_handle);
}
UE_LOG(GM_Log, Display, TEXT("GMs ready for testing with %i GMs"), GMList.Num());
}
UE_LOG(GM_Log, Display, TEXT("GMs ready for testing with"));
OnGMTestingReady.Broadcast();
}
void AGMTestingManager::RunGMs(int argc, const char* argv[])
{
TestingWindow->isGoldens = false;
int error = gms_main(argc, argv);
if (error != 0)
{
UE_LOG(GM_Log,
Error,
TEXT("AGMTestingManager::StartTesting() gms_main failed with error code %i"),
error);
}
else
{
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::StartTesting() gms_main finished succefully"));
}
}
void AGMTestingManager::RunGoldens(int argc, const char* argv[])
{
TestingWindow->isGoldens = true;
int error = goldens_main(argc, argv);
if (error != 0)
{
UE_LOG(GM_Log,
Error,
TEXT("AGMTestingManager::StartTesting() goldens_main failed with error code %i"),
error);
}
else
{
UE_LOG(GM_Log,
Display,
TEXT("AGMTestingManager::StartTesting() goldens_main finished succefully"));
}
}
void AGMTestingManager::RunCustomTestClear()
{
check(CustomTestTexture);
DM->SetTextureParameterValue(TEXT("texture"), CustomTestTexture);
CustomTestTexture->OnResourceInitializedOnRenderThread.AddUObject(
this,
&AGMTestingManager::RunCustomTestClear_RenderThread);
CustomTestTexture->ResizeRenderTargets(FIntPoint(256, 256));
}
void AGMTestingManager::RunCustomTestManyPaths(int32 NumberOfPathsToRun)
{
auto Size = sqrt(NumberOfPathsToRun);
check(CustomTestTexture);
check(Size);
Size = FMath::Clamp(Size, RIVE_MIN_TEX_RESOLUTION, RIVE_MAX_TEX_RESOLUTION);
DM->SetTextureParameterValue(TEXT("texture"), CustomTestTexture);
CustomTestTexture->OnResourceInitializedOnRenderThread.AddUObject(
this,
&AGMTestingManager::RunCustomTestManyPaths_RenderThread);
CustomTestTexture->ResizeRenderTargets(FIntPoint(Size, Size));
}
void AGMTestingManager::RunCustomTestClear_RenderThread(FRHICommandListImmediate& RHICmdList,
FTextureRHIRef& NewResource)
{
auto context = Renderer->GetRenderContext();
auto impl = context->static_impl_cast<RenderContextRHIImpl>();
auto renderTarget = impl->makeRenderTarget(RHICmdList, NewResource);
context->beginFrame({.renderTargetWidth = NewResource->GetSizeX(),
.renderTargetHeight = NewResource->GetSizeY(),
.loadAction = rive::gpu::LoadAction::clear,
.clearColor = 0xFFFFFF00});
context->flush({.renderTarget = renderTarget.get()});
}
void AGMTestingManager::RunCustomTestManyPaths_RenderThread(FRHICommandListImmediate& RHICmdList,
FTextureRHIRef& NewResource)
{
auto context = Renderer->GetRenderContext();
auto impl = context->static_impl_cast<RenderContextRHIImpl>();
auto renderTarget = impl->makeRenderTarget(RHICmdList, NewResource);
auto width = NewResource->GetSizeX();
auto height = NewResource->GetSizeY();
context->beginFrame({.renderTargetWidth = width,
.renderTargetHeight = height,
.loadAction = rive::gpu::LoadAction::clear,
.clearColor = 0xFF000000});
auto renderer = std::make_unique<rive::RiveRenderer>(context);
rive::ColorInt Color = 0;
const int ColorStep = 0xFFFFFF / (width * height);
for (size_t x = 0; x < width; x++)
{
for (size_t y = 0; y < height; y++)
{
Color += ColorStep;
auto strokePaint = context->makeRenderPaint();
strokePaint->style(rive::RenderPaintStyle::fill);
strokePaint->color(rive::colorWithAlpha(Color, 0xFF));
strokePaint->blendMode(rive::BlendMode::srcOver);
rive::RawPath path;
path.addRect({static_cast<float>(x),
static_cast<float>(y),
static_cast<float>(x + 1),
static_cast<float>(y + 1)});
auto renderPath = context->makeRenderPath(path, rive::FillRule::nonZero);
renderer->drawPath(renderPath.get(), strokePaint.get());
}
}
context->flush({.renderTarget = renderTarget.get()});
}
void AGMTestingManager::RunSpecificGM_RenderThread(FRHICommandListImmediate& RHICmdList,
FTextureRHIRef& NewResource)
{
if (GMToRun == nullptr)
{
UE_LOG(GM_Log, Error, TEXT("No GM To Run!"));
return;
}
// we are already on the render thread so we don't need to enque a new command
if (!gms_run_gm(GMToRun->registry_position))
{
UE_LOG(GM_Log, Error, TEXT("Failed to run gm named %s"), *GMToRun->Name);
}
AsyncTask(ENamedThreads::GameThread, [this, GM = GMToRun]() { SetDMTexture(GM->RiveTexture); });
// null it out since we already ran it
GMToRun = nullptr;
}
void UGMDataStatics::ResetGmTexture(FGMData& Data) { Data.RiveTexture = nullptr; }
void UGMDataStatics::ResetGoldenTexture(FGoldenData& Data) { Data.RiveTexture = nullptr; }
void UGMDataStatics::MakeGoldenData(FString PathToRiv, FGoldenData& OutGoldenData, bool& Successful)
{
auto& FileManager = IFileManager::Get();
if (!FileManager.FileExists(*PathToRiv))
{
Successful = false;
return;
}
OutGoldenData.Name = FPaths::GetBaseFilename(PathToRiv);
OutGoldenData.FilePath = PathToRiv;
Successful = true;
}
void UGMDataStatics::GenerateGoldenForDefaultLocation(TArray<FGoldenData>& OutGoldens)
{
auto& FileManager = IFileManager::Get();
const auto ProjectFile = FPaths::GetProjectFilePath();
auto RelativePath = FPaths::Combine(ProjectFile, "../../../../../gold/rivs");
auto RivDir = FileManager.ConvertToAbsolutePathForExternalAppForRead(*RelativePath);
UE_LOG(GM_Log, Display, TEXT("Generating Default Golden List for %s"), *RivDir);
FileManager.IterateDirectoryStat(
*RivDir,
[&OutGoldens](const TCHAR* Path, const FFileStatData& Stat) -> bool {
FGoldenData Data;
bool success = false;
UGMDataStatics::MakeGoldenData(Path, Data, success);
if (success)
{
OutGoldens.Add(Data);
}
return true;
});
}

View File

@@ -0,0 +1,156 @@
#include "UnrealTestingWindow.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetInputLibrary.h"
#include "RiveRenderer/Public/IRiveRenderer.h"
#include "Platform/RenderContextRHIImpl.hpp"
#include "Rive/RiveTexture.h"
#include "GMTestingManager.h"
#include <goldens.hpp>
#include "Misc/EngineVersionComparison.h"
#if UE_VERSION_OLDER_THAN(5, 4, 0)
#define CREATE_TEXTURE(RHICmdList, Desc) RHICreateTexture(Desc)
#else // UE_VERSION_OLDER_THAN (5, 4,0)
#define CREATE_TEXTURE(RHICmdList, Desc) RHICmdList.CreateTexture(Desc)
#endif
UnrealTestingWindow::UnrealTestingWindow(UObject* WorldContextObject, IRiveRenderer* RiveRenderer) :
RiveRenderer(RiveRenderer),
RenderContext(RiveRenderer->GetRenderContext()),
WorldContextObject(WorldContextObject)
{}
void UnrealTestingWindow::resize(int width, int height)
{
TestingWindow::resize(width, height);
auto impl = RenderContext->static_impl_cast<RenderContextRHIImpl>();
auto& RHICmdList = GRHICommandList.GetImmediateCommandList();
if (RenderTexture)
{
// use the render texture created external for visibility
check(RenderTexture->Size.X == width);
check(RenderTexture->Size.Y == height);
auto Texture = RenderTexture->GetResource()->GetTexture2DRHI();
RenderTarget = impl->makeRenderTarget(RHICmdList, Texture);
}
else
{
FRHITextureCreateDesc Desc =
FRHITextureCreateDesc::Create2D(TEXT("RiveTestingWindowRenderTarget"),
width,
height,
EPixelFormat::PF_R8G8B8A8);
Desc.SetFlags(ETextureCreateFlags::UAV | ETextureCreateFlags::Dynamic |
ETextureCreateFlags::ShaderResource | ETextureCreateFlags::RenderTargetable);
FTexture2DRHIRef Texture = CREATE_TEXTURE(RHICmdList, Desc);
RenderTarget = impl->makeRenderTarget(RHICmdList, Texture);
}
FRHITextureCreateDesc CopyDesc =
FRHITextureCreateDesc::Create2D(TEXT("RiveTestingWindowCopyDest"),
width,
height,
EPixelFormat::PF_R8G8B8A8);
CopyDesc.SetFlags(ETextureCreateFlags::CPUReadback);
CopyDestTexture = CREATE_TEXTURE(RHICmdList, CopyDesc);
}
rive::Factory* UnrealTestingWindow::factory() { return RenderContext; }
std::unique_ptr<rive::Renderer> UnrealTestingWindow::beginFrame(uint32_t clearColor, bool doClear)
{
rive::gpu::RenderContext::FrameDescriptor FrameDescriptor;
FrameDescriptor.renderTargetWidth = width();
FrameDescriptor.renderTargetHeight = height();
FrameDescriptor.loadAction =
doClear ? rive::gpu::LoadAction::clear : rive::gpu::LoadAction::preserveRenderTarget;
FrameDescriptor.clearColor = clearColor;
FrameDescriptor.wireframe = false;
FrameDescriptor.fillsDisabled = false;
FrameDescriptor.strokesDisabled = false;
RenderContext->beginFrame(std::move(FrameDescriptor));
return std::make_unique<rive::RiveRenderer>(RenderContext);
}
void UnrealTestingWindow::endFrame(std::vector<uint8_t>* pixelData)
{
RenderContext->flush({RenderTarget.get()});
if (pixelData == nullptr)
return;
const size_t size = m_height * m_width * 4;
pixelData->resize(size);
check(pixelData->size() == size);
auto& RHICmdList = GRHICommandList.GetImmediateCommandList();
auto RHIRenderTarget = static_cast<RenderTargetRHI*>(RenderTarget.get());
auto RenderTargetTexture = RHIRenderTarget->texture();
auto Fence = GDynamicRHI->RHICreateGPUFence(TEXT("GM_FLUSH_FENCE"));
TransitionAndCopyTexture(RHICmdList,
RenderTargetTexture,
CopyDestTexture,
FRHICopyTextureInfo());
RHICmdList.Transition(
FRHITransitionInfo(CopyDestTexture, ERHIAccess::Unknown, ERHIAccess::CPURead));
RHICmdList.WriteGPUFence(Fence);
void* Data = nullptr;
int32 Width;
int32 Height;
RHICmdList.MapStagingSurface(CopyDestTexture, Fence.GetReference(), Data, Width, Height);
check(Width >= static_cast<int32>(m_width));
check(Height >= static_cast<int32>(m_height));
uint32 DestStride = Width * 4;
for (uint32_t y = 0; y < m_height; ++y)
{
uint8_t* src = static_cast<uint8_t*>(Data) + (DestStride * y);
uint8_t* dst = pixelData->data() + ((m_height - y - 1) * m_width * 4);
memcpy(dst, src, m_width * 4);
}
RHICmdList.UnmapStagingSurface(CopyDestTexture);
}
rive::gpu::RenderContext* UnrealTestingWindow::renderContext() const { return RenderContext; }
rive::gpu::RenderTarget* UnrealTestingWindow::renderTarget() const { return RenderTarget.get(); }
void UnrealTestingWindow::flushPLSContext() { RenderContext->flush({RenderTarget.get()}); }
bool UnrealTestingWindow::peekKey(char& key)
{
auto controller = UGameplayStatics::GetPlayerController(WorldContextObject, 0);
return controller->GetInputAnalogKeyState(EKeys::SpaceBar) != 0;
}
char UnrealTestingWindow::getKey()
{
char key = ' ';
while (!peekKey(key))
{
if (shouldQuit())
{
printf("Window terminated by user.\n");
exit(0);
}
}
return key;
}
bool UnrealTestingWindow::shouldQuit() const { return false; }

View File

@@ -0,0 +1,15 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Modules/ModuleManager.h"
class FGMModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
DECLARE_LOG_CATEGORY_EXTERN(GM_Log, Display, All);

View File

@@ -0,0 +1,183 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Rive/RiveTexture.h"
#include "UObject/Object.h"
#include "UnrealTestingWindow.h"
#include "GMTestingManager.generated.h"
UENUM(Blueprintable, BlueprintType)
enum class EGMTestingType : uint8
{
GM,
Golden,
Both
};
USTRUCT(Blueprintable, BlueprintType)
struct GM_API FGMData
{
GENERATED_BODY()
// Width of the GM gets populate when GM list is created
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
int32 Width = 0;
// Height of the GM gets populate when GM list is created
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
int32 Height = 0;
// transient texture that gets deleted after this gm is removed from view to save memory
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
URiveTexture* RiveTexture = nullptr;
// the name of the golden
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
FString Name;
// opaque handle to GM registry u accessed and provided by gms.dll
const void* registry_position = nullptr;
};
USTRUCT(Blueprintable, BlueprintType)
struct GM_API FGoldenData
{
GENERATED_BODY()
// this is only populated after the first time this golden has been drawn
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
int32 Width = 0;
// this is only populated after the first time this golden has been drawn
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
int32 Height = 0;
// transient texture that gets deleted after this golden is removed from view to save memory
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
URiveTexture* RiveTexture = nullptr;
// base file name for then golden
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
FString Name;
// full absolute path to golden
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
FString FilePath;
};
UCLASS()
class GM_API UGMDataStatics : public UObject
{
GENERATED_BODY()
public:
// Resets the RiveTexture to nullptr to release the memory
UFUNCTION(BlueprintCallable)
static void ResetGmTexture(UPARAM(ref) FGMData& Data);
// Resets the RiveTexture to nullptr to release the memory
UFUNCTION(BlueprintCallable)
static void ResetGoldenTexture(UPARAM(ref) FGoldenData& Data);
// Create a new golden with minimal info, verifying the path exists
UFUNCTION(BlueprintCallable)
static void MakeGoldenData(FString PathToRiv, FGoldenData& OutGoldenData, bool& Successful);
// Create Goldens using assumed launch location is the Unreal Project root directory, like
// running from editor
UFUNCTION(BlueprintCallable)
static void GenerateGoldenForDefaultLocation(TArray<FGoldenData>& OutGoldens);
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGMTestingReady);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGMTestingFinished);
/**
*
*/
UCLASS()
class GM_API AGMTestingManager : public AActor
{
GENERATED_BODY()
public:
AGMTestingManager();
UFUNCTION(BlueprintCallable)
void StartTesting();
UFUNCTION(BlueprintCallable)
void DeInitTesting();
UFUNCTION(BlueprintCallable)
void SetDMTexture(UTexture2DDynamic* Texture, bool MeshIsVisible = true);
/*
* Runs the given GM through gms.dll
* If @ShouldGenerateDisplayTexture is true, a new RiveTexture will be created and stored in GM
* That will be rendered to assuming it will be used to display the finished GM
*/
UFUNCTION(BlueprintCallable)
void RunGM(UPARAM(ref) FGMData& GM, bool ShouldGenerateDisplayTexture = true);
/*
* Runs the given Golden through goldens_main
* If @ShouldGenerateDisplayTexture is true, a new RiveTexture will be created and stored in
* Golden That will be rendered to assuming it will be used to display the finished Golden
*/
UFUNCTION(BlueprintCallable)
void RunGolden(UPARAM(ref) FGoldenData& Golden, bool ShouldGenerateDisplayTexture = true);
UFUNCTION(BlueprintCallable)
void RunCustomTestClear();
UFUNCTION(BlueprintCallable)
void RunCustomTestManyPaths(int32 NumberOfPathsToRun);
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool bShouldAddTestArguments;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool bShouldExitOnFinish;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool bShouldGenerateGMList;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "GM")
FGMTestingReady OnGMTestingReady;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "GM")
FGMTestingFinished OnGmTestingFinished;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "GM")
EGMTestingType TestingType = EGMTestingType::GM;
protected:
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
UStaticMeshComponent* StaticMeshComponent;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
TArray<FGMData> GMList;
protected:
virtual void BeginPlay() override;
void RiveReady(IRiveRenderer* InRiveRenderer);
private:
void RunGMs(int argc, const char* argv[]);
void RunGoldens(int argc, const char* argv[]);
void RunCustomTestClear_RenderThread(FRHICommandListImmediate& RHICmdList,
FTextureRHIRef& NewResource);
void RunCustomTestManyPaths_RenderThread(FRHICommandListImmediate& RHICmdList,
FTextureRHIRef& NewResource);
void RunSpecificGM_RenderThread(FRHICommandListImmediate& RHICmdList,
FTextureRHIRef& NewResource);
// GMRan in RunSpecificGM_RenderThread and set by RunGM
FGMData* GMToRun = nullptr;
// this is managed by the GM lib. so we just reset this to null after running gms_main
UnrealTestingWindow* TestingWindow;
UPROPERTY()
URiveTexture* CustomTestTexture;
UPROPERTY()
UMaterialInstanceDynamic* DM;
IRiveRenderer* Renderer;
bool bRiveReady;
bool bResourceReady;
};

View File

@@ -0,0 +1,54 @@
#pragma once
#include "rive/refcnt.hpp"
#include "Rive/RiveTexture.h"
struct FGMData;
class IRiveRenderer;
class IRiveRenderTarget;
class URiveTexture;
THIRD_PARTY_INCLUDES_START
#include "gms.hpp"
THIRD_PARTY_INCLUDES_END
/*
* UnrealTestingWindow is the testing window implementation for rhi intended to be used with gms
* unit testing. This is assumed to be on the Render thread. If used on the Game thread it will
* cause unexpected behaviour.
*/
class UnrealTestingWindow : public TestingWindow
{
public:
UnrealTestingWindow(UObject* WorldContextObject, IRiveRenderer* RenderTarget);
virtual void resize(int width, int height) override;
virtual rive::Factory* factory() override;
virtual std::unique_ptr<rive::Renderer> beginFrame(uint32_t clearColor,
bool doClear = true) override;
virtual void endFrame(std::vector<uint8_t>* pixelData = nullptr) override;
virtual rive::gpu::RenderContext* renderContext() const override;
virtual rive::gpu::RenderTarget* renderTarget() const override;
virtual void flushPLSContext() override;
virtual bool peekKey(char& key) override;
virtual char getKey() override;
virtual bool shouldQuit() const override;
bool isGoldens = false;
// texture used for rendering GM
URiveTexture* RenderTexture = nullptr;
private:
// we don't reference count this here because a UObject owns this class and the render target
IRiveRenderer* RiveRenderer;
rive::gpu::RenderContext* RenderContext;
rive::rcp<rive::gpu::RenderTarget> RenderTarget;
// I am not allowed to both render to and read from the same texture, so i'm going to copy to
// this one and read from here
FTexture2DRHIRef CopyDestTexture;
UObject* WorldContextObject;
};

View File

@@ -0,0 +1,23 @@
#if defined _WIN32 || defined _WIN64
#include <Windows.h>
#define EXAMPLELIBRARY_EXPORT __declspec(dllexport)
#else
#include <stdio.h>
#endif
#ifndef EXAMPLELIBRARY_EXPORT
#define EXAMPLELIBRARY_EXPORT
#endif
EXAMPLELIBRARY_EXPORT void ExampleLibraryFunction()
{
#if defined _WIN32 || defined _WIN64
MessageBox(NULL,
TEXT("Loaded ExampleLibrary.dll from Third Party Plugin sample."),
TEXT("Third Party Plugin"),
MB_OK);
#else
printf("Loaded ExampleLibrary from Third Party Plugin sample");
#endif
}

View File

@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExampleLibrary", "ExampleLibrary.vcxproj", "{9B50F1F8-0116-442C-A071-F5C3A120A5CB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9B50F1F8-0116-442C-A071-F5C3A120A5CB}.Debug|x64.ActiveCfg = Debug|x64
{9B50F1F8-0116-442C-A071-F5C3A120A5CB}.Debug|x64.Build.0 = Debug|x64
{9B50F1F8-0116-442C-A071-F5C3A120A5CB}.Release|x64.ActiveCfg = Release|x64
{9B50F1F8-0116-442C-A071-F5C3A120A5CB}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Some files were not shown because too many files have changed in this diff Show More