Integrating latest 47acbe8
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
@@ -0,0 +1,440 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
This file generates automated asset load benchmark timings for different asset loading scenarios. It uses the launcher
|
||||
so that it can be run on any platform. The test works as follows:
|
||||
- Starts with a series of predefined "benchmarksettings" asset files that are used by the Asset Processor to generate
|
||||
"benchmark" files for loading
|
||||
- These get copied to the current project, where AssetProcessor will process them
|
||||
- After they're processed, the Launcher is launched and tries to load each set of benchmark assets N times in a row
|
||||
- Once that's done, the results are gathered and summarized into a CSV
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import pytest
|
||||
import logging
|
||||
import re
|
||||
from statistics import mean, median
|
||||
from ctypes import *
|
||||
from ctypes.wintypes import *
|
||||
|
||||
pytest.importorskip("ly_test_tools")
|
||||
|
||||
import time as time
|
||||
|
||||
import ly_test_tools.launchers.launcher_helper as launcher_helper
|
||||
import ly_remote_console.remote_console_commands as remote_console_commands
|
||||
from ly_remote_console.remote_console_commands import (
|
||||
send_command_and_expect_response as send_command_and_expect_response,
|
||||
)
|
||||
import ly_test_tools.environment.waiter as waiter
|
||||
from automatedtesting_shared.network_utils import check_for_listening_port
|
||||
from automatedtesting_shared.file_utils import delete_check
|
||||
|
||||
remote_console_port = 4600
|
||||
remote_command_timeout = 20
|
||||
listener_timeout = 120
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Number of times to run each benchmark test.
|
||||
benchmark_trials = 5
|
||||
|
||||
class Benchmark:
|
||||
"""
|
||||
Data structure used to define the list of benchmark tests we want to run.
|
||||
|
||||
:attr base_name: The base name of the .benchmarksettings test file. This is also used as
|
||||
a tag when logging.
|
||||
:attr num_copies: Number of copies to make of the .benchmarksettings test file; the
|
||||
generated .benchmark files will all get loaded separately in parallel.
|
||||
:attr load_times: The set of load times that have been captured.
|
||||
"""
|
||||
def __init__(self, base_name, num_copies):
|
||||
self.base_name = base_name
|
||||
self.num_copies = num_copies
|
||||
self.load_times = []
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["Simple"])
|
||||
class TestBenchmarkAssetLoads(object):
|
||||
@pytest.fixture
|
||||
def launcher_instance(self, request, workspace, level):
|
||||
self.launcher = launcher_helper.create_launcher(workspace)
|
||||
|
||||
@pytest.fixture
|
||||
def remote_console_instance(self, request):
|
||||
console = remote_console_commands.RemoteConsole()
|
||||
|
||||
def teardown():
|
||||
if console.connected:
|
||||
console.stop()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return console
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project):
|
||||
def teardown():
|
||||
# Clean up in the following order:
|
||||
# 1) Kill the interactive AP
|
||||
# 2) Remove our source .benchmarksettings files that we put in the project
|
||||
# 3) Run APBatch to process the missing source files to clean up our generated cached files
|
||||
# By going in this order, we guarantee that we won't hit any file locks and we can
|
||||
# easily detect when AP is done cleaning everything up for us.
|
||||
workspace.asset_processor.stop()
|
||||
logger.debug('Cleaning up the benchmark asset artifacts.')
|
||||
if self.remove_benchmark_assets(self.get_temp_benchmark_asset_directory(workspace)):
|
||||
self.run_ap_batch(workspace.asset_processor)
|
||||
|
||||
# On setup, make sure to clean up any benchmark assets that stuck around from a previous run.
|
||||
request.addfinalizer(teardown)
|
||||
logger.debug('Cleaning up any previously-existing benchmark asset artifacts.')
|
||||
if self.remove_benchmark_assets(self.get_temp_benchmark_asset_directory(workspace)):
|
||||
self.run_ap_batch(workspace.asset_processor)
|
||||
|
||||
def run_ap_batch(self, asset_processor):
|
||||
"""
|
||||
Run AssetProcessorBatch to process any changed assets.
|
||||
|
||||
:param asset_processor: The asset processor object
|
||||
"""
|
||||
process_assets_success = asset_processor.batch_process(timeout=600, fastscan=True)
|
||||
assert process_assets_success, 'Assets did not process correctly'
|
||||
|
||||
|
||||
def get_temp_benchmark_asset_directory(self, workspace):
|
||||
return os.path.join(workspace.paths.dev(), workspace.project, 'benchmark')
|
||||
|
||||
def create_benchmark_assets(self, dest_directory, benchmarks):
|
||||
"""
|
||||
Create a directory of benchmarksettings assets in the selected project.
|
||||
|
||||
:param dest_direcotry: The path of the temporary directory to create the benchmark assets in
|
||||
:param benchmarks: The list of Benchmark objects to process and create
|
||||
"""
|
||||
source_directory = os.path.join(os.path.dirname(__file__), 'assets')
|
||||
logger.debug(f'Creating directory: {dest_directory}')
|
||||
os.makedirs(dest_directory, exist_ok=True)
|
||||
|
||||
# For each Benchmark object, either just copy the .benchmarksettings file as-is with the same name
|
||||
# if we only want one copy, or else append _<num> to the name for each copy if we want multiples.
|
||||
for benchmark in benchmarks:
|
||||
if benchmark.num_copies > 1:
|
||||
for asset_num in range (0, benchmark.num_copies):
|
||||
shutil.copy(os.path.join(source_directory, f'{benchmark.base_name}.benchmarksettings'),
|
||||
os.path.join(dest_directory, f'{benchmark.base_name}_{asset_num}.benchmarksettings'))
|
||||
else:
|
||||
shutil.copy(os.path.join(source_directory, f'{benchmark.base_name}.benchmarksettings'), dest_directory)
|
||||
|
||||
|
||||
def remove_benchmark_assets(self, dest_directory):
|
||||
"""
|
||||
Remove the project/benchmark directory that we created.
|
||||
|
||||
:param dest_directory: The path to the temp directory that we created the source benchmarks assets in
|
||||
:return True if assets were found and removed, False if they weren't
|
||||
"""
|
||||
return delete_check(dest_directory)
|
||||
|
||||
|
||||
def set_cvar(self, remote_console_instance, cvar_name, cvar_value):
|
||||
"""
|
||||
Helper function to set a CVar value and wait for confirmation.
|
||||
"""
|
||||
send_command_and_expect_response(remote_console_instance, f"{cvar_name} {cvar_value}",
|
||||
f"{cvar_name} : {cvar_value}", timeout=remote_command_timeout)
|
||||
|
||||
|
||||
def run_benchmark(self, remote_console_instance, num_trials, benchmark):
|
||||
"""
|
||||
Run a series of benchmark trials.
|
||||
|
||||
:param remote_console_instance: The remote console instance
|
||||
:param num_trials: The number of times to run the same benchmark in a row
|
||||
:param benchmark: The Benchmark object describing the set of assets to try loading
|
||||
"""
|
||||
# The root benchmark asset is the one with sub ID 1, so it has '_00000001' at the end of the base name.
|
||||
name_suffix='_00000001.benchmark'
|
||||
|
||||
for trial in range (0, num_trials):
|
||||
# Set a unique log label to make it easier to parse for the results
|
||||
self.set_cvar(remote_console_instance, 'benchmarkLoadAssetLogLabel', f"{benchmark.base_name}_{trial}")
|
||||
|
||||
# Clear the list of assets to load for the benchmark
|
||||
send_command_and_expect_response(remote_console_instance,
|
||||
f"benchmarkClearAssetList",
|
||||
f"({benchmark.base_name}_{trial}) - Benchmark asset list cleared.", timeout=remote_command_timeout)
|
||||
|
||||
# Build up the load asset command.
|
||||
# Note that there is a limit to the number of parameters we can send in each console command, so we need to split it up
|
||||
# if we have too many assets.
|
||||
max_params_per_line = 50
|
||||
if benchmark.num_copies > 1:
|
||||
benchmark_command = f"benchmarkAddAssetsToList"
|
||||
for asset_num in range (0, benchmark.num_copies):
|
||||
benchmark_command += f" benchmark/{benchmark.base_name}_{asset_num}{name_suffix}"
|
||||
if (asset_num % max_params_per_line == (max_params_per_line - 1)) or (asset_num == benchmark.num_copies - 1):
|
||||
send_command_and_expect_response(remote_console_instance,
|
||||
benchmark_command,
|
||||
f"({benchmark.base_name}_{trial}) - All requested assets added.", timeout=remote_command_timeout)
|
||||
benchmark_command = f"benchmarkAddAssetsToList"
|
||||
else:
|
||||
send_command_and_expect_response(remote_console_instance,
|
||||
f"benchmarkAddAssetsToList benchmark/{benchmark.base_name}{name_suffix}",
|
||||
f"({benchmark.base_name}_{trial}) - All requested assets added.", timeout=remote_command_timeout)
|
||||
|
||||
# Attempt to clear the Windows file cache between each run
|
||||
self.clear_windows_file_cache()
|
||||
|
||||
# Send it and wait for the benchmark to complete
|
||||
send_command_and_expect_response(remote_console_instance,
|
||||
f"benchmarkLoadAssetList",
|
||||
f"({benchmark.base_name}_{trial}) - Benchmark run complete.", timeout=remote_command_timeout)
|
||||
|
||||
def move_artifact(self, artifact_manager, artifact_name):
|
||||
"""
|
||||
Move the artifact to our TestResults.
|
||||
"""
|
||||
# Save the artifact to be examined later
|
||||
logger.debug('Preserving artifact: {}'.format(artifact_name))
|
||||
artifact_manager.save_artifact(artifact_name)
|
||||
os.remove(artifact_name)
|
||||
|
||||
def extract_benchmark_results(self, launcher_log, extracted_log, benchmarks):
|
||||
"""
|
||||
Extract the benchmark timing results, save them in a summary file, and put the timings into our benchmarks structure.
|
||||
|
||||
:param launcher_log: the path to the game.log to parse
|
||||
:param extracted_log: the output path to save the summarized log
|
||||
:param benchmarks: the benchmarks structure to fill in with our timing results
|
||||
"""
|
||||
logger.debug('Parsing benchmark results.')
|
||||
with open(extracted_log, 'w') as summary_log:
|
||||
with open(launcher_log) as log:
|
||||
for line in log:
|
||||
for benchmark in benchmarks:
|
||||
for trial in range (0, benchmark_trials):
|
||||
if f'({benchmark.base_name}_{trial}) - Results:' in line:
|
||||
# For each timing result we find, write it as-is into our summary log.
|
||||
summary_log.write(line)
|
||||
# Pull out the timing value and save it in the appropriate benchmark entry.
|
||||
match = re.search("Time=([\\d]+)", line)
|
||||
if match:
|
||||
benchmark.load_times.append(int(match.groups()[0]))
|
||||
|
||||
def clear_windows_file_cache(self):
|
||||
"""
|
||||
Clear the Windows file cache, using the undocumented NtSetSystemInformation call.
|
||||
For this to work, the process needs to be run with Administrator privileges.
|
||||
:return True if file cache cleared, False if not.
|
||||
"""
|
||||
|
||||
# Define the LUID Windows class
|
||||
class LUID(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('low_part', c_uint32),
|
||||
('high_part', c_int32),
|
||||
]
|
||||
|
||||
# Define an abbreviated version of the TOKEN_PRIVILEGES Windows class.
|
||||
# The correct version would use an array of dynamic size for LUID_AND_ATTRIBUTES inside of itself,
|
||||
# but since we're only every using one entry, we can simplify the code and hard-code the definition at
|
||||
# a single entry.
|
||||
class TOKEN_PRIVILEGES(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('count', c_uint32),
|
||||
('luid', LUID),
|
||||
('attributes', c_uint32),
|
||||
]
|
||||
|
||||
# Force the construction to always fill in the array count with 1, since we've hard-coded a single
|
||||
# array definition into our structure definition.
|
||||
def __init__(self, luid, attributes):
|
||||
super(TOKEN_PRIVILEGES, self).__init__(1, luid, attributes)
|
||||
|
||||
# Windows constants that we'll need
|
||||
TOKEN_QUERY = 0x0008
|
||||
TOKEN_ADJUST_PRIVILEGES = 0x0020
|
||||
SE_PRIVILEGE_ENABLED = 0x0002
|
||||
STATUS_PRIVILEGE_NOT_HELD = 0xc0000061
|
||||
ERROR_NOT_ALL_ASSIGNED = 1300
|
||||
SystemMemoryListInformation = 0x0050
|
||||
MemoryPurgeStandbyList = 4
|
||||
|
||||
logger.info('Attempting to clear the Windows file cache')
|
||||
|
||||
# Get the token for the currently-running process
|
||||
token_handle = HANDLE()
|
||||
result = windll.advapi32.OpenProcessToken(
|
||||
windll.kernel32.GetCurrentProcess(),
|
||||
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||
byref(token_handle))
|
||||
if (result == 0):
|
||||
logger.error('Failed on the OpenProcessToken call')
|
||||
|
||||
# Get the LUID for the privilege we need to escalate
|
||||
luid = LUID()
|
||||
if (result > 0):
|
||||
result = windll.advapi32.LookupPrivilegeValueW(None, 'SeProfileSingleProcessPrivilege', byref(luid))
|
||||
if (result == 0):
|
||||
logger.error('Failed on the LookupPrivilegeValueW call')
|
||||
|
||||
# Adjust the privilege for the current process so that we have access to clear the Windows file cache.
|
||||
# This will only succeed if we're running with Administrator privileges.
|
||||
if (result > 0):
|
||||
tp = TOKEN_PRIVILEGES(luid, SE_PRIVILEGE_ENABLED)
|
||||
result = windll.advapi32.AdjustTokenPrivileges(token_handle, False, byref(tp), 0, None, None)
|
||||
if (result > 0):
|
||||
# The AdjustTokenPrivileges call itself succeeded, but we need to separately check to see if the privilege was escalated
|
||||
errCode = windll.kernel32.GetLastError()
|
||||
if (errCode == ERROR_NOT_ALL_ASSIGNED):
|
||||
# This is an acceptable error, but it means we won't be able to clear the file cache.
|
||||
# Don't fail the benchmark run due to it though.
|
||||
windll.kernel32.CloseHandle(token_handle)
|
||||
logger.info('Windows file cache will not be cleared, insufficient privileges.')
|
||||
logger.info('If you wish to clear the cache when running this benchmark, run with Administrator privileges.')
|
||||
return False
|
||||
elif (errCode > 0):
|
||||
# Flag that something unexpected happened.
|
||||
result = 0
|
||||
if (result == 0):
|
||||
logger.error('Failed on the AdjustTokenPrivileges call')
|
||||
|
||||
# Privileges have been escalated, so clear the Windows file cache.
|
||||
if (result > 0):
|
||||
command = c_uint32(MemoryPurgeStandbyList)
|
||||
status = c_int32(windll.ntdll.NtSetSystemInformation(SystemMemoryListInformation, byref(command), sizeof(command) ))
|
||||
if (status.value == c_int32(STATUS_PRIVILEGE_NOT_HELD).value):
|
||||
# This is an acceptable error, but it means we won't be able to clear the file cache.
|
||||
# Don't fail the benchmark run due to it though.
|
||||
windll.kernel32.CloseHandle(token_handle)
|
||||
logger.info('Windows file cache will not be cleared, insufficient privileges.')
|
||||
logger.info('If you wish to clear the cache when running this benchmark, run with Administrator privileges.')
|
||||
return False
|
||||
elif (status.value < 0):
|
||||
# Flag that something unexpected happened.
|
||||
result = 0
|
||||
logger.error('Failed on the NtSetSystemInformation call')
|
||||
|
||||
# Print the final results
|
||||
if (result > 0):
|
||||
logger.info('Successfully cleared the Windows file cache.')
|
||||
else:
|
||||
errCode = windll.kernel32.GetLastError()
|
||||
logger.error(f'Unexpected error while attempting to clear the Windows file cache: {errCode}')
|
||||
|
||||
windll.kernel32.CloseHandle(token_handle)
|
||||
return (result > 0)
|
||||
|
||||
|
||||
def base_test_BenchmarkAssetLoads(self, workspace, launcher, level, remote_console_instance, use_dev_mode):
|
||||
benchmarks = [
|
||||
# The choice of 650 MB as the benchmark size is arbitrary. It was picked as large enough to get reasonably stable
|
||||
# and measureable results even when running on an SSD, and because the "balanced tree" test causes a total size
|
||||
# of (2^N + 1)*AssetSize. Working with that constraint, and a base asset size of 10 MB, the main contenders were
|
||||
# either 330 MB, 650 MB, or 1290 MB.
|
||||
|
||||
# The first set of benchmarks measures the load time effects of different asset dependency hierarchies.
|
||||
|
||||
# Load 650 MB from a single root 10MB asset where each asset has 2 dependent 10MB assets 6 levels deep
|
||||
Benchmark('10mb_2x6', 1),
|
||||
# Load 650 MB from a single root 10MB asset where each asset has 4 dependent 10MB assets 3 levels deep
|
||||
Benchmark('10mb_4x3', 1),
|
||||
# Load 650 MB from a single root 10MB asset that has 64 dependent 10MB assets
|
||||
Benchmark('10mb_64x1', 1),
|
||||
# Load 650 MB from a single root 10MB asset where each asset has 1 dependent 10MB asset 64 levels deep
|
||||
# (Currently removed because it crashes Lumberyard, re-enable once LY can handle it - SPEC-1314)
|
||||
#Benchmark('10mb_1x64', 1),
|
||||
|
||||
# The second set of benchmarks measures the load time effects of different quantities of parallel asset loads.
|
||||
|
||||
# Load a single 650 MB asset
|
||||
Benchmark('650mb', 1),
|
||||
# Load 2 x 325 MB assets in parallel
|
||||
Benchmark('325mb', 2),
|
||||
# Load 3 x 216 MB assets in parallel
|
||||
Benchmark('216mb', 3),
|
||||
# Load 4 x 162 MB assets in parallel
|
||||
Benchmark('162mb', 4),
|
||||
# Load 65 x 10 MB assets in parallel
|
||||
Benchmark('10mb', 65),
|
||||
# Load 650 x 1 MB assets in parallel
|
||||
Benchmark('1mb', 650),
|
||||
]
|
||||
|
||||
# Create test assets
|
||||
logger.debug('Generating new benchmark asset artifacts.')
|
||||
self.create_benchmark_assets(self.get_temp_benchmark_asset_directory(workspace), benchmarks)
|
||||
self.run_ap_batch(workspace.asset_processor)
|
||||
|
||||
# Set the launcher arguments to choose either dev mode or optimized mode for the streamer.
|
||||
if (use_dev_mode):
|
||||
launcher.args = ['-NullRenderer', '-cl_streamerDevMode=true']
|
||||
else:
|
||||
launcher.args = ['-NullRenderer', '-cl_streamerDevMode=false']
|
||||
streamer_mode = 'devMode' if use_dev_mode else 'optMode'
|
||||
|
||||
# Run the benchmarks in the launcher
|
||||
logger.debug(f'Running benchmark in launcher with args={launcher.args}')
|
||||
with launcher.start():
|
||||
waiter.wait_for(
|
||||
lambda: check_for_listening_port(remote_console_port),
|
||||
listener_timeout,
|
||||
exc=AssertionError("Port {} not listening.".format(remote_console_port)),
|
||||
)
|
||||
remote_console_instance.start(timeout=remote_command_timeout)
|
||||
|
||||
# Set up the benchmarking parameters to use across all the tests
|
||||
self.set_cvar(remote_console_instance, "benchmarkLoadAssetTimeoutMs", "30000")
|
||||
self.set_cvar(remote_console_instance, "benchmarkLoadAssetPollMs", "20")
|
||||
self.set_cvar(remote_console_instance, "benchmarkLoadAssetDisplayProgress", "false")
|
||||
self.set_cvar(remote_console_instance, "cl_assetLoadWarningEnable", "false")
|
||||
|
||||
# Run all our benchmarks
|
||||
for benchmark in benchmarks:
|
||||
self.run_benchmark(remote_console_instance, benchmark_trials, benchmark)
|
||||
|
||||
# Give the launcher a chance to quit before forcibly stopping it.
|
||||
# This way our game.log will contain all the information we want instead of potentially truncating early.
|
||||
send_command_and_expect_response(remote_console_instance, f"quit", "Executing console command 'quit'",
|
||||
timeout=remote_command_timeout)
|
||||
launcher.stop()
|
||||
remote_console_instance.stop()
|
||||
|
||||
# Extract all the benchmark timings out of the game.log, save it into a summary log file,
|
||||
# and put the timings into the benchmarks list so we can gather summarized metrics
|
||||
launcher_log = os.path.join(launcher.workspace.paths.project_log(), 'Game.log')
|
||||
summary_log = f'load_benchmark_{level}_{streamer_mode}.log'
|
||||
self.extract_benchmark_results(launcher_log, summary_log, benchmarks)
|
||||
self.move_artifact(workspace.artifact_manager, summary_log)
|
||||
|
||||
# Generate a CSV of the min/max/avg results for each test.
|
||||
results_csv = f'load_benchmark_{level}_{streamer_mode}.csv'
|
||||
with open(results_csv, 'w') as csv_file:
|
||||
csv_file.write(f'"Test Name","Num Assets Loaded","First Time(ms)","Last Time(ms)","Max Time(ms)","Min Time (ms)",'+
|
||||
f'"Avg Time (ms)","Median Time (ms)"\n')
|
||||
for benchmark in benchmarks:
|
||||
csv_file.write(f'{benchmark.base_name},{benchmark.num_copies},{benchmark.load_times[0]},{benchmark.load_times[-1]},'+
|
||||
f'{max(benchmark.load_times)},{min(benchmark.load_times)},{mean(benchmark.load_times)},'+
|
||||
f'{median(benchmark.load_times)}\n')
|
||||
self.move_artifact(workspace.artifact_manager, results_csv)
|
||||
|
||||
@pytest.mark.SUITE_benchmark
|
||||
def test_BenchmarkAssetLoads_optMode(self, workspace, launcher, level, remote_console_instance):
|
||||
self.base_test_BenchmarkAssetLoads(workspace, launcher, level, remote_console_instance, use_dev_mode = False)
|
||||
|
||||
@pytest.mark.SUITE_benchmark
|
||||
def test_BenchmarkAssetLoads_devMode(self, workspace, launcher, level, remote_console_instance):
|
||||
self.base_test_BenchmarkAssetLoads(workspace, launcher, level, remote_console_instance, use_dev_mode = True)
|
||||
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="64" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="4" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="10485760" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="64" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="170393600" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="1048576" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="227191466" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="340787200" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<ObjectStream version="3">
|
||||
<Class name="BenchmarkSettingsAsset" type="{D570D0DD-CE8D-4DF3-BC3E-77DB92D72626}">
|
||||
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
|
||||
<Class name="AZ::u64" field="PrimaryAssetByteSize" value="681574400" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="AZ::u64" field="DependentAssetByteSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
|
||||
<Class name="unsigned int" field="DependencyDepth" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="unsigned int" field="NumAssetsPerDependency" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
|
||||
<Class name="int" field="AssetStorageType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||
</Class>
|
||||
</ObjectStream>
|
||||
|
||||
Reference in New Issue
Block a user