Audit RDR2 (#31)

* remove graphics presets

* remove unused assets

* pep8 lint

* update readme

* lint

* add resolution func

* implement get resolution stub for rdr2
This commit is contained in:
Derek Hirotsu
2023-09-19 09:56:16 -07:00
committed by GitHub
parent 67a786f9fd
commit 995469aae0
12 changed files with 76 additions and 198 deletions

View File

@@ -4,7 +4,7 @@ import re
import winreg
import logging
def get_resolution() -> tuple[int]:
def get_resolution() -> tuple[int]:
"""Gets resolution width and height from local xml file created by game."""
username = os.getlogin()
config_path = f"C:\\Users\\{username}\\Documents\\My Games\\F1 22\\hardwaresettings"

View File

@@ -1,45 +1,15 @@
# Red Dead Redemption 2
This script navigates through in-game menus to the built in benchmark and runs it with the current settings.
## Prerequisites
- Python 3.10+
- Red Dead Redemp installed.
- Red Dead Redemption 2 installed via Steam.
## Setup
1. Follow the setup instructions for the framework. If you have done so, all required python dependencies *should* be installed.
2. Install Red Dead Redemption 2 from steam.
1. Location does not matter, this harness uses steam to launch the game.
## Configuration
Below is an example use of this harness as a test in a benchmark configuration.
```yaml
...
...
tests:
- name: reddeadredemption2
executable: "reddeadredemption2.py"
process_name: "RDR2.exe"
output_dir:
- 'harness/reddeadredemption2/run'
```
__name__ : _(required)_ name of the test. This much match the name of a directory in the harness folder so the framework
can find the executable and any supplementary files.
__executable__ : _(required)_ the entry point to the test harness. In this case a python script.
__process_name__ : _(required)_ The process name that should be the target for FPS recording (ex: PresentMon).
__output_dir__: _(optional)_ Directory containing files to aggregate copies of after a successful test run. If a directory path is
given, the contents are copied.
__args__ : _(optional)_ list of arguments to be appended to the command to execute. All the arguments will be passed to
the executable when invoked by the framework.
### Arguments
## Common Issues
## Output
report.json
- `resolution`: string representing the resolution the test was run at, formatted as "[width]x[heigt]", e.x. `1920x1080`
- `start_time`: number representing a timestamp of the test's start time in milliseconds
- `end_time`: number representing a timestamp of the test's end time in milliseconds

Binary file not shown.

Before

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

View File

@@ -2,8 +2,4 @@ friendly_name: "Red Dead Redemption 2"
executable: "reddeadredemption2.py"
process_name: "RDR2.exe"
hidden: 0
output_dir: "run"
options:
- name: preset
type: select
values: [current]
output_dir: "run"

View File

@@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rage__fwuiSystemSettingsCollection>
<version value="37" />
<configSource>kSettingsConfig_Auto</configSource>
<graphics>
<tessellation>kSettingLevel_High</tessellation>
<shadowQuality>kSettingLevel_Ultra</shadowQuality>
<farShadowQuality>kSettingLevel_High</farShadowQuality>
<reflectionQuality>kSettingLevel_Low</reflectionQuality>
<mirrorQuality>kSettingLevel_Ultra</mirrorQuality>
<ssao>kSettingLevel_Ultra</ssao>
<textureQuality>kSettingLevel_Ultra</textureQuality>
<particleQuality>kSettingLevel_Medium</particleQuality>
<waterQuality>kSettingLevel_High</waterQuality>
<volumetricsQuality>kSettingLevel_Ultra</volumetricsQuality>
<lightingQuality>kSettingLevel_Ultra</lightingQuality>
<ambientLightingQuality>kSettingLevel_Ultra</ambientLightingQuality>
<anisotropicFiltering value="4" />
<dlssIndex value="0" />
<dlssQuality value="5" />
<taa>kSettingLevel_High</taa>
<fxaaEnabled value="false" />
<msaa value="0" />
<graphicsQualityPreset value="0.500000" />
<hdr value="true" />
<hdrIntensity value="100" />
<hdrPeakBrightness value="1000" />
<hdrFilmicMode value="true" />
<gamma value="15" />
<hdrSettingsMigrated value="true" />
</graphics>
<advancedGraphics>
<API>kSettingAPI_Vulkan</API>
<locked value="true" />
<asyncComputeEnabled value="false" />
<transferQueuesEnabled value="true" />
<shadowSoftShadows>kSettingLevel_Ultra</shadowSoftShadows>
<motionBlur value="true" />
<motionBlurLimit value="16.000000" />
<particleLightingQuality>kSettingLevel_Medium</particleLightingQuality>
<waterReflectionSSR value="true" />
<waterRefractionQuality>kSettingLevel_High</waterRefractionQuality>
<waterReflectionQuality>kSettingLevel_High</waterReflectionQuality>
<waterSimulationQuality value="3" />
<waterLightingQuality>kSettingLevel_Ultra</waterLightingQuality>
<furDisplayQuality>kSettingLevel_Medium</furDisplayQuality>
<maxTexUpgradesPerFrame value="5" />
<shadowGrassShadows>kSettingLevel_High</shadowGrassShadows>
<shadowParticleShadows value="true" />
<shadowLongShadows value="true" />
<directionalShadowsAlpha value="false" />
<worldHeightShadowQuality value="0.660000" />
<directionalScreenSpaceShadowQuality value="0.660000" />
<ambientMaskVolumesHighPrecision value="false" />
<scatteringVolumeQuality>kSettingLevel_Ultra</scatteringVolumeQuality>
<volumetricsRaymarchQuality>kSettingLevel_Ultra</volumetricsRaymarchQuality>
<volumetricsLightingQuality>kSettingLevel_Ultra</volumetricsLightingQuality>
<volumetricsRaymarchResolutionUnclamped value="false" />
<terrainShadowQuality>kSettingLevel_High</terrainShadowQuality>
<damageModelsDisabled value="false" />
<decalQuality>kSettingLevel_High</decalQuality>
<ssaoFullScreenEnabled value="false" />
<ssaoType value="0" />
<ssdoSampleCount value="4" />
<ssdoUseDualRadii value="false" />
<ssdoResolution>kSettingLevel_Low</ssdoResolution>
<ssdoTAABlendEnabled value="true" />
<ssroSampleCount value="2" />
<snowGlints value="true" />
<POMQuality>kSettingLevel_Ultra</POMQuality>
<probeRelightEveryFrame value="false" />
<scalingMode>kSettingScale_Mode1o1</scalingMode>
<reflectionMSAA value="0" />
<lodScale value="1.000000" />
<grassLod value="3.000000" />
<pedLodBias value="0.000000" />
<vehicleLodBias value="0.000000" />
<sharpenIntensity value="1.000000" />
<treeQuality>kSettingLevel_Medium</treeQuality>
<deepsurfaceQuality>kSettingLevel_High</deepsurfaceQuality>
<treeTessellationEnabled value="false" />
</advancedGraphics>
<video>
<adapterIndex value="0" />
<outputIndex value="0" />
<resolutionIndex value="16" />
<screenWidth value="2560" />
<screenHeight value="1440" />
<resolutionIndexWindowed value="16" />
<screenWidthWindowed value="2560" />
<screenHeightWindowed value="1440" />
<refreshRateIndex value="6" />
<refreshRateNumerator value="165" />
<refreshRateDenominator value="1" />
<windowed value="0" />
<vSync value="0" />
<tripleBuffered value="true" />
<pauseOnFocusLoss value="false" />
<constrainMousePointer value="false" />
</video>
<videoCardDescription>NVIDIA NVIDIA GeForce RTX 3080 Ti</videoCardDescription>
</rage__fwuiSystemSettingsCollection>

View File

@@ -1,21 +0,0 @@
[tool.poetry]
name = "reddeadredemption2-harness"
version = "0.1.0"
description = ""
authors = ["Nikolas Harris <nikolas@linusmediagroup.com"]
[tool.poetry.dependencies]
python = "^3.10"
PyAutoGUI = "^0.9.53"
PyDirectInput = "^1.0.4"
opencv-python = "^4.5.5"
Pillow = "^9.1.1"
psutil = "^5.9.1"
PyYAML = "^6.0"
imutils = "^0.5.4"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

View File

@@ -1,3 +1,35 @@
# stub
def get_resolution(config_path: str) -> tuple[int]:
return 0, 0
"""Utility functions supporting RDR2 test script."""
import getpass
import pathlib
import re
def get_resolution() -> tuple[int]:
"""Gets resolution width and height from local xml file created by game."""
# C:\Users\User\Documents\Rockstar Games\Red Dead Redemption 2\Settings\system.xml"
path = pathlib.Path(
"C:/Users/", getpass.getuser(),
"Documents", "Rockstar Games", "Red Dead Redemption 2", "Settings",
"system.xml"
)
width = "0"
height = "0"
screen_width = re.compile(r"<screenWidth value=\"(\d+)\" />")
screen_height = re.compile(r"<screenHeight value=\"(\d+)\" />")
try:
with open(path, encoding="utf-8") as file:
lines = file.readlines()
for line in lines:
width_match = screen_width.search(line)
height_match = screen_height.search(line)
if width_match is not None:
width = width_match.group(1)
if height_match is not None:
height = height_match.group(1)
except OSError:
width = "0"
height = "0"
return (width, height)

View File

@@ -1,49 +1,58 @@
"""Red Dead Redemption 2 test script"""
import logging
import os
import pydirectinput as user
import time
from subprocess import Popen
import sys
import pydirectinput as user
from red_dead_redemption_2_utils import get_resolution
sys.path.insert(1, os.path.join(sys.path[0], '..'))
from harness_utils.logging import *
#pylint: disable=wrong-import-position
from harness_utils.logging import (
format_resolution,
seconds_to_milliseconds,
setup_log_directory,
write_report_json,
DEFAULT_LOGGING_FORMAT,
DEFAULT_DATE_FORMAT,
)
from harness_utils.process import terminate_processes
from harness_utils.steam import get_run_game_id_command, DEFAULT_EXECUTABLE_PATH as STEAM_PATH
#pylint: enable=wrong-import-position
STEAM_GAME_ID = 1174180
PROCESS_NAME = "RDR2"
SCRIPT_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
LOG_DIRECTORY = os.path.join(SCRIPT_DIRECTORY, "run")
config_path = os.path.join(os.environ["HOMEPATH"], "Documents" ,"Rockstar Games", "Red Dead Redemption 2", "Settings", "system.xml")
config_path = os.path.join(
os.environ["HOMEPATH"], "Documents" ,"Rockstar Games",
"Red Dead Redemption 2", "Settings", "system.xml"
)
def start_game():
"""Starts the game via steam command"""
steam_run_arg = get_run_game_id_command(STEAM_GAME_ID)
logging.info(STEAM_PATH + " " + steam_run_arg)
logging.info("%s %s", STEAM_PATH, steam_run_arg)
return Popen([STEAM_PATH, steam_run_arg])
def run_benchmark():
##
"""Starts the benchmark"""
# Wait for game to load to main menu
##
t1 = time.time()
setup_start_time = time.time()
start_game()
time.sleep(65)
##
# Press Z to enter settings
##
user.press("z")
time.sleep(3)
##
# Enter graphics menu
##
## ensure we are starting from the top left of the screen
user.press("up")
user.press("up")
@@ -54,31 +63,26 @@ def run_benchmark():
user.press("enter")
time.sleep(3)
##
# Run benchmark by holding X for 2 seconds
##
user.keyDown('x')
time.sleep(1.5)
user.keyUp("x")
##
# Press enter to confirm benchmark
##
t2 = time.time()
logging.info(f"Harness setup took {round((t2 - t1), 2)} seconds")
elapsed_setup_time = round(time.time() - setup_start_time, 2)
logging.info("Setup took %f seconds", elapsed_setup_time)
user.press("enter")
start_time = time.time()
test_start_time = time.time()
##
# Wait for the benchmark to complete
##
time.sleep(315) # 5 min, 15 seconds.
end_time = time.time()
logging.info(f"Benchark took {round((end_time - start_time), 2)} seconds")
test_end_time = time.time()
elapsed_test_time = round(test_end_time - test_start_time, 2)
logging.info("Benchmark took %f seconds", elapsed_test_time)
# Exit
terminate_processes(PROCESS_NAME)
return start_time, end_time
return test_start_time, test_end_time
setup_log_directory(LOG_DIRECTORY)
@@ -95,16 +99,16 @@ logging.getLogger('').addHandler(console)
try:
start_time, end_time = run_benchmark()
width, height = get_resolution(config_path)
result = {
report = {
"resolution": format_resolution(width, height),
"graphics_preset": "current",
"start_time": seconds_to_milliseconds(start_time),
"end_time": seconds_to_milliseconds(end_time)
}
write_report_json(LOG_DIRECTORY, "report.json", result)
write_report_json(LOG_DIRECTORY, "report.json", report)
#pylint: disable=broad-exception-caught
except Exception as e:
logging.error("Something went wrong running the benchmark!")
logging.exception(e)
terminate_processes(PROCESS_NAME)
exit(1)
sys.exit(1)