GPU Benchmark Automation with Python! The Hitman3 Case

Python & Hitman3! Whenever I find the time, I try to finish the big project I decided to handle, an overhaul of my GPU testing, with all benchmarking performed automatically through a sophisticated piece of code (or at least I try to make it sophisticated!) This is easier said than done, but I have lots of patience when it comes to programming (only)

I have already made an article on how to extract game data automatically from CapFrameX, which will be helpful to many of you, especially the ones reviewing graphics cards either for a hobby or to make a living. In this review, I will go one big step further and show you how to automate the benchmarking procedure of a popular game title, Hitman 3.

Thankfully, several games include a built-in benchmark, which makes things easier for us reviewers. This means that, for the moment, I won’t have to create a bot that will play the game for me while measuring FPS through CapFrameX. The only thing I will have to do is to perform all selections in the options of the benchmark, start it, start CapFrameX capture once the benchmark initiates, and repeat the whole procedure till I test all options that I want, different resolutions and graphics options. Automating this entire procedure means I save lots of precious time since I won’t have to do anything manually. Moreover, from the moment I also have code for extracting all data from CapFrameX effortlessly, and with the press of a button, I make all graphs; most of the work is done without my intervention.

I assume that you already know how to install Python on your system. Suppose you don’t, make a Google search and come back here after you do it. If you are not experienced in Python, you should also check out Thonny, a Python IDE for beginners.

Let’s first import the required modules:

import os
import psutil
import requests
import json
import time
import pyautogui
from pywinauto import Desktop
from pywinauto.application import Application
from PIL import Image
import logging
import subprocess
import webbrowser

These are the CapFrameX variables

Processname = ”
TimeToCapture = 100
RecordDirectory =’C:/Users/YourUSERNAME/Documents/CapFrameX/Captures’
CaptureFileMode = ‘JSON’
Capture_Active = False
bench_count = 1 # DO NOT CHANGE THAT

The bench_count is the starting point, so you should not change that unless you want to skip some graphics options.

#Benchmark Options
Benches_per_setting = 2 #Change That #amount of runs per setting. The ideal is four
RTX_option = True
DLSS_FSR_Option = True #Change That
DLSS_Frame_Generation = False
DLSS_35 = False
Resolutions_per_test_Scenario = 3; #3x resolutions (HD, QHD, 4K)

Here is where I set the benchmark options. As you can see, I even have an option for DLSS 3.5 in case Hitman3 gets an update. I tried to make the code universal since I plan on reusing parts of it for other games, too.

if RTX_option:
    Resolutions_per_test_Scenario += 3

if DLSS_FSR_Option:
    Resolutions_per_test_Scenario += 3

if DLSS_Frame_Generation:
    Resolutions_per_test_Scenario += 3

if DLSS_35:
    Resolutions_per_test_Scenario += 3

Whenever I add an option, I must repeat the tests in all three resolutions that I will test: HD, QHD, and 4K. This means that I will have to run more benchmarks.

Total_Benches = Benches_per_setting * Resolutions_per_test_Scenario #3x resolutions per setting, I only have one setting, Ultra
print (‘Total Resolutions that I will run: ‘ + str(Resolutions_per_test_Scenario))
print (‘Benches per Resolution: ‘ + str(Benches_per_setting))
print (‘Total Runs: ‘ + str(Total_Benches))

I think the code above is self-explanatory.

#Image_Recognition
x_axis = 250
y_axis = 540

image_source = ‘Hitman3_Picture.png’

I need an image to look for, telling me when the Hitman3 benchmark starts!

To keep this post nice and clean, I won’t post ALL the functions I use, which are easy to make on your own. So, let’s continue.

def Run_App2(Selection, GameID, AppName):
     Code = ‘com.epicgames.launcher://apps//’ + GameID + ‘?action=launch&silent=true’
     isAppRunning = False
     if AppName in (p.name() for p in psutil.process_iter()):
          isAppRunning = True
     if isAppRunning == False:
         webbrowser.open(Code)
         #print(Code)
         time.sleep(5)

I decided to provide you with this function because most games nowadays open through launchers.

#Start CapFrameX
try:
     Run_App(‘C:\\Program Files (x86)\\CapFrameX\\’, ‘CapFrameX.exe’)
except:
     print(“Couldn’t start CapFrameX!”)

The code to start CapFrameX. It will need admin privileges, most likely. I could set some extra code to hit the OK button automatically.

try:
     Run_App2(1, GameID, ‘Hitman3’)
except:
     print(“Couldn’t start Benchmark!”)

The GameID is easy to find if you have a shortcut on your desktop.

app = Application(backend=’win32′).connect(path=r’C:\\Program Files\\Epic Games\\HITMAN3\\Launcher.exe’)
GameBench = app.window(title_re=”HITMAN”, found_index=0)

Through GameBench, I will set all of my options!

#Open options
GameBench.OPTIONS.click()
print(‘Options Selected’)

Open the Benchmark Options window.

GameBench2 = app.window(title_re=”Options”, found_index=0)

#Select the Basic Options which won’t change
#Display Mode
GameBench2.OptionsComboBox4.select(2) #Exclusive Fullscreen

#V-Sync
GameBench2.OptionsComboBox5.select(0) #Vsync OFF

#Level of Details
GameBench2.OptionsComboBox15.select(3) #Ultra

#Benchmark Scene
GameBench2.OptionsComboBox26.select(0) #Dubai

#Show FPS
GameBench2.OptionsComboBox27.select(0) #Off

#Show Stats
GameBench2.OptionsComboBox28.select(0) #Off

All Basic options are set with the code above. Hitman3 didn’t use identifiers for the selections, so I had to go through them until I figured them out. Thankfully, they were in a series.

Time now to start the actual work! The Benchmark session.

while bench_count < Total_Benches+1:

     #Wait for the Window to appear again
     GameBench2.wait(“exists enabled visible ready”, 20, 2)
     GameBench2.set_focus()

     #Select Ultra Preset
     if (bench_count<=Benches_per_setting*3):
          #RTX Options
           GameBench2.OptionsComboBox12.select(0) #OFF/On
          #GameBench2.OptionsComboBox13.select(0) #OFF/On
          #GameBench2.OptionsComboBox14.select(0) #OFF/On

          #Adaptive Supersampling
          GameBench2.OptionsComboBox10.select(0) #OFF/On
         #DLSS Frame Generation
          GameBench2.OptionsComboBox9.select(0) #OFF/On
          print(‘Ultra Preset’)
          time.sleep(0.2)

  #Select RTX Preset without DLSS
  elif (bench_count>Benches_per_setting*3 and bench_count<=Benches_per_setting*6) and RTX_option:
         #RTX Options
         GameBench2.OptionsComboBox12.select(1) #OFF/On
         GameBench2.OptionsComboBox13.select(1) #OFF/On
         GameBench2.OptionsComboBox14.select(1) #OFF/On
         time.sleep(0.2)
         #Adaptive Supersampling
         GameBench2.OptionsComboBox10.select(0) #OFF/On
        #DLSS Frame Generation
         GameBench2.OptionsComboBox9.select(0) #OFF/On
         print(‘RTX Preset’)
         time.sleep(0.2)

   #Select RTX Preset with DLSS or FSR
   elif (bench_count>Benches_per_setting*6 and bench_count<=Benches_per_setting*9) and DLSS_FSR_Option:
         #RTX Options
          GameBench2.OptionsComboBox12.select(1) #OFF/On
          GameBench2.OptionsComboBox13.select(1) #OFF/On
          GameBench2.OptionsComboBox14.select(1) #OFF/On
          time.sleep(0.2)
          #Adaptive Supersampling
          GameBench2.OptionsComboBox10.select(1) #OFF/On
         #DLSS Frame Generation
          GameBench2.OptionsComboBox9.select(0) #OFF/On
          print(‘RTX Preset & DLSS’)
          time.sleep(0.2)

    #Select RTX Preset with DLSS or FSR and Frame Generation
    elif (bench_count>Benches_per_setting*9) and DLSS_FSR_Option and DLSS_Frame_Generation:
          #RTX Options
            GameBench2.OptionsComboBox12.select(1) #OFF/On
            GameBench2.OptionsComboBox13.select(1) #OFF/On
            GameBench2.OptionsComboBox14.select(1) #OFF/On
            time.sleep(0.2)
            #Adaptive Supersampling
            GameBench2.OptionsComboBox10.select(1) #OFF/On
            #DLSS Frame Generation
            GameBench2.OptionsComboBox9.select(1) #OFF/On
            print(‘RTX Preset & DLSS & Frame Generation’)
            time.sleep(0.2)

    if (bench_count== 1 or bench_count== Benches_per_setting*3+1 or bench_count== Benches_per_setting*6+1 or       bench_count== Benches_per_setting*9+1):
             #Change Resolution to HD
               GameBench2.OptionsComboBox3.select(4) #0 for 4K, 1 for QHD, 4 for HD
               print(‘HD Resolution’)
               x_axis = 960
               y_axis = 540
              time.sleep(0.2)

    if (bench_count== Benches_per_setting+1 or bench_count== Benches_per_setting*4+1 or bench_count== Benches_per_setting*7+1 or bench_count== Benches_per_setting*10+1):
            #Change Resolution to QHD
             GameBench2.OptionsComboBox3.select(1) #0 for 4K, 1 for QHD, 4 for HD
             print(‘QHD Resolution’)
             x_axis = 1280
             y_axis = 720
            time.sleep(0.2)

   if (bench_count== Benches_per_setting*2+1 or bench_count== Benches_per_setting*5+1 or bench_count== Benches_per_setting*8+1 or bench_count== Benches_per_setting*11+1):
           #Change Resolution to 4K
            GameBench2.OptionsComboBox3.select(0) #0 for 4K, 1 for QHD, 4 for HD
            print(‘UHD Resolution’)
            x_axis = 1980
            y_axis = 1080
            time.sleep(0.2)

   #Start Benchmark
   GameBench2.Button4.click()
   print(‘Run Button is Pressed ‘ + str(bench_count))
   time.sleep(5)

   #Detect Image
    while not image_search(image_source, x_axis, y_axis, 1500, clicks=0, duration=0, interval=0, debug_msg=’found!’, time_limit=None, sample_dump=None):
            print()
    #Here the Benchmark starts  
     start_capture(‘HITMAN3’, RecordDirectory, CaptureFileMode, TimeToCapture)
     time.sleep(TimeToCapture)
     bench_count += 1
     Benchmark ends here and it will start again
     time.sleep(5)

Indentation might not be perfect because WordPress didn’t paste the Python code correctly, but I tried to make it as straightforward as possible for you. When no bots are involved, you use a counter to check the number of benchmarks you run, and according to the number of times you want to run the benchmark in each resolution, you make the corresponding changes. You have to start CapFrameX, of course. This is easy; you search for an image, preferably at the start of the benchmark. The image I used is shown below.

If you liked today’s article, leave a comment to encourage me to make more like this. Please note that the purpose of this article is NOT to provide the whole code and make your life easier, but without understanding anything from what is happening. I intend to educate you on how Python can make your lives easier and provide valuable tips on automating GPU/CPU testing. This means that you have to have an idea of how to code with Python. 

 

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *