Compare commits
8 Commits
c6edc9f3fe
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ad6b94be53 | |||
| f67522cbfc | |||
| e422f44377 | |||
| 8d5fc4eaae | |||
| 546f96b6d0 | |||
| 770c17349d | |||
| 3aeae2e81e | |||
| 75fa9cae18 |
+24
-5
@@ -2,16 +2,14 @@ FROM ubuntu-hlsdk
|
|||||||
|
|
||||||
# Avoid interactive prompts during package installation
|
# Avoid interactive prompts during package installation
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV VULKAN_SDK_VERSION=1.4.341.1
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
# Install Vulkan SDK repos
|
RUN apt-get update && apt-get full-upgrade -y && apt-get autoremove -y
|
||||||
RUN wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | tee /etc/apt/trusted.gpg.d/lunarg.asc \
|
|
||||||
&& wget -qO /etc/apt/sources.list.d/lunarg-vulkan-noble.list http://packages.lunarg.com/vulkan/lunarg-vulkan-noble.list
|
|
||||||
|
|
||||||
# Install system dependencies and development packages
|
# Install system dependencies and development packages
|
||||||
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y \
|
RUN apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
vulkan-sdk \
|
|
||||||
libsdl2-dev \
|
libsdl2-dev \
|
||||||
libfreetype-dev \
|
libfreetype-dev \
|
||||||
\
|
\
|
||||||
@@ -33,6 +31,27 @@ RUN apt-get update && apt-get install --no-install-recommends --no-install-sugge
|
|||||||
libvulkan1 \
|
libvulkan1 \
|
||||||
imagemagick
|
imagemagick
|
||||||
|
|
||||||
|
# Install Vulkan SDK runtime dependencies only
|
||||||
|
#RUN apt-get update && apt-get install -y \
|
||||||
|
# libxcb-xinput0 libxcb-xinerama0 libxcb-cursor-dev
|
||||||
|
|
||||||
|
# Install Vulkan SDK
|
||||||
|
RUN mkdir -p /opt/VulkanSDK && wget -qO- \
|
||||||
|
https://sdk.lunarg.com/sdk/download/${VULKAN_SDK_VERSION}/linux/vulkansdk-linux-x86_64-${VULKAN_SDK_VERSION}.tar.xz | \
|
||||||
|
tar -xJ -C /opt/VulkanSDK/
|
||||||
|
|
||||||
|
ENV VULKAN_SDK=/opt/VulkanSDK/${VULKAN_SDK_VERSION}/x86_64
|
||||||
|
ENV PATH=$VULKAN_SDK/bin:$PATH
|
||||||
|
ENV LD_LIBRARY_PATH="$VULKAN_SDK/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||||
|
ENV VK_ADD_LAYER_PATH="$VULKAN_SDK/share/vulkan/explicit_layer.d${VK_ADD_LAYER_PATH:+:$VK_ADD_LAYER_PATH}"
|
||||||
|
ENV PKG_CONFIG_PATH="$VULKAN_SDK/share/pkgconfig:$VULKAN_SDK/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
|
||||||
|
|
||||||
|
# Common dev utils
|
||||||
|
RUN apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
|
ripgrep \
|
||||||
|
less \
|
||||||
|
fd-find
|
||||||
|
|
||||||
# Remove extra cache after all the installations
|
# Remove extra cache after all the installations
|
||||||
RUN rm -rf /var/lib/apt/lists/*
|
RUN rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ build() {
|
|||||||
|
|
||||||
rendertest() {
|
rendertest() {
|
||||||
pushd /build/HLRTest/render
|
pushd /build/HLRTest/render
|
||||||
WAYLAND_DISPLAY=/tmp/wayland-headless ./rendertest.py --xash-dir /opt/hl run
|
WAYLAND_DISPLAY=/tmp/wayland-headless ./rendertest.py \
|
||||||
|
--xash-dir /opt/hl \
|
||||||
|
--xash-revision "${XASH3D_REVISION}" \
|
||||||
|
--pbr-revision "${PBR_REVISION}" \
|
||||||
|
--tests-revision "${HLRTEST_REVISION}" \
|
||||||
|
run
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-5
@@ -1,9 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -eux
|
set -eux
|
||||||
|
|
||||||
|
# just podman things
|
||||||
|
export DBUS_SESSION_BUS_ADDRESS=
|
||||||
|
|
||||||
NAME=xash-builder
|
NAME=xash-builder
|
||||||
|
|
||||||
HLRTEST_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
|
HLRTEST_REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
|
||||||
|
|
||||||
source .env
|
source .env
|
||||||
|
|
||||||
@@ -20,10 +23,38 @@ build() {
|
|||||||
build-image
|
build-image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_short() {
|
||||||
|
local dir="${1:-.}"
|
||||||
|
local hash dirty_flag
|
||||||
|
|
||||||
|
# Get short commit hash
|
||||||
|
hash=$(cd "$dir" && git rev-parse --short HEAD 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -z "$hash" ]]; then
|
||||||
|
echo "Not a git repository" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for uncommitted changes (staged or unstaged)
|
||||||
|
dirty_flag=$(cd "$dir" && git status --porcelain --untracked-files=no 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -n "$dirty_flag" ]]; then
|
||||||
|
echo "${hash}-dirty"
|
||||||
|
else
|
||||||
|
echo "$hash"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
render-test() {
|
render-test() {
|
||||||
OUTPUT="${HLRTEST_PATH}/render/work"
|
local OUTPUT="${HLRTEST_REPO_DIR}/render/work"
|
||||||
# Make sure the image ubuntu user can write to the output
|
mkdir -p "${OUTPUT}"
|
||||||
chmod -R o+rw "${OUTPUT}"
|
|
||||||
|
local HLRTEST_REVISION=$(git_short "${HLRTEST_REPO_DIR}")
|
||||||
|
local XASH3D_REVISION=$(git_short "${XASH3D_RT_REPO_DIR}")
|
||||||
|
local PBR_REVISION=$(git_short "${HALFLIFE_PBR_REPO_DIR}")
|
||||||
|
|
||||||
|
# Make sure the image's ubuntu (uid=1000) user can write to the output
|
||||||
|
#chmod -R o+rw "${OUTPUT}"
|
||||||
|
|
||||||
podman run -it --rm \
|
podman run -it --rm \
|
||||||
--name ${NAME} \
|
--name ${NAME} \
|
||||||
@@ -34,14 +65,21 @@ render-test() {
|
|||||||
--read-only \
|
--read-only \
|
||||||
--tmpfs /tmp \
|
--tmpfs /tmp \
|
||||||
\
|
\
|
||||||
|
-e HLRTEST_REVISION="${HLRTEST_REVISION}" \
|
||||||
|
-e XASH3D_REVISION="${XASH3D_REVISION}" \
|
||||||
|
-e PBR_REVISION="${PBR_REVISION}" \
|
||||||
|
\
|
||||||
-v /dev/dri/renderD128:/dev/dri/renderD128:ro \
|
-v /dev/dri/renderD128:/dev/dri/renderD128:ro \
|
||||||
|
-v /etc/localtime:/etc/localtime:ro \
|
||||||
\
|
\
|
||||||
-v /opt/hl \
|
-v /opt/hl \
|
||||||
|
-v /home/ubuntu \
|
||||||
-v ${HALFLIFE_PBR_REPO_DIR}/valve/pbr:/opt/hl/valve/pbr:ro \
|
-v ${HALFLIFE_PBR_REPO_DIR}/valve/pbr:/opt/hl/valve/pbr:ro \
|
||||||
|
-v ${HALFLIFE_PBR_REPO_DIR}/valve/bluenoise:/opt/hl/valve/bluenoise:ro \
|
||||||
\
|
\
|
||||||
-v ${XASH3D_RT_REPO_DIR}:/build/xash3d-fwgs:O \
|
-v ${XASH3D_RT_REPO_DIR}:/build/xash3d-fwgs:O \
|
||||||
\
|
\
|
||||||
-v ${HLRTEST_PATH}:/build/HLRTest:ro \
|
-v ${HLRTEST_REPO_DIR}:/build/HLRTest:O \
|
||||||
-v ${OUTPUT}:/build/HLRTest/render/work \
|
-v ${OUTPUT}:/build/HLRTest/render/work \
|
||||||
\
|
\
|
||||||
ubuntu-xash-builder:latest \
|
ubuntu-xash-builder:latest \
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
imagecompare: imagecompare.c stb_image.h stb_image_write.h Makefile
|
imagecompare: imagecompare.c stb_image.h stb_image_write.h Makefile
|
||||||
${CC} -O3 -ggdb3 -march=native -Wall -Werror -pedantic -lm -o imagecompare imagecompare.c
|
${CC} -O3 -ggdb3 -march=native -Wall -Werror -pedantic -o imagecompare imagecompare.c -lm
|
||||||
|
|||||||
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.
+37
-29
@@ -114,7 +114,7 @@ function isPassed(value) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeTable(fields, data, attrs_func) {
|
function makeTable(fields, tests, attrs_func) {
|
||||||
const table = Tag('table', null, null, [
|
const table = Tag('table', null, null, [
|
||||||
Tag('tr', null, null, (() => {
|
Tag('tr', null, null, (() => {
|
||||||
let tds = [];
|
let tds = [];
|
||||||
@@ -126,8 +126,8 @@ function makeTable(fields, data, attrs_func) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
for (const di in data) {
|
for (const di in tests) {
|
||||||
let d = data[di];
|
let d = tests[di];
|
||||||
const attrs = attrs_func ? attrs_func(d) : null;
|
const attrs = attrs_func ? attrs_func(d) : null;
|
||||||
table.appendChild(Tag('tr', attrs, null, (() => {
|
table.appendChild(Tag('tr', attrs, null, (() => {
|
||||||
let ret = [];
|
let ret = [];
|
||||||
@@ -159,7 +159,7 @@ function makeTable(fields, data, attrs_func) {
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildTestResultsTable(data) {
|
function buildTestResultsTable(tests) {
|
||||||
const fields = [
|
const fields = [
|
||||||
{label: 'Test', field: 'test', tags_func: sectionLink},
|
{label: 'Test', field: 'test', tags_func: sectionLink},
|
||||||
{label: 'Channel', field: 'channel', tags_func: channelWithEmoji},
|
{label: 'Channel', field: 'channel', tags_func: channelWithEmoji},
|
||||||
@@ -167,27 +167,37 @@ function buildTestResultsTable(data) {
|
|||||||
{label: 'Passed', field: 'fail', tags_func: isPassed},
|
{label: 'Passed', field: 'fail', tags_func: isPassed},
|
||||||
];
|
];
|
||||||
|
|
||||||
return [makeTable(fields, data, rowAttribs)];
|
return [makeTable(fields, tests, rowAttribs)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter out all success
|
// Filter out all success
|
||||||
function filterData(data) {
|
function filterTests(tests) {
|
||||||
return data
|
return tests
|
||||||
.filter((d) => { return d.diff_pct !== 0; })
|
.filter((t) => { return t.diff_pct !== 0; })
|
||||||
.sort((l, r) => {
|
.sort((l, r) => {
|
||||||
return l.diff_pct < r.diff_pct ? 1 : -1; // RTFM
|
return l.diff_pct < r.diff_pct ? 1 : -1; // RTFM
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSummary(data) {
|
function buildSummary(test_results) {
|
||||||
const total = data.length;
|
const tests = test_results.tests
|
||||||
const fails = data.filter((d) => { return !!d.fail; }).length;
|
const total = tests.length;
|
||||||
|
const fails = tests.filter((d) => { return !!d.fail; }).length;
|
||||||
const fails_pct = fails * 100.0 / total;
|
const fails_pct = fails * 100.0 / total;
|
||||||
return emojiToTag(`🧪 Tests 💥: ${fails}/${total}🏁 (⚠${fails_pct.toFixed(3)}%)`);
|
const meta = test_results.metadata;
|
||||||
|
return [
|
||||||
|
Tag('ul', null, null, [
|
||||||
|
Tag('li', null, `Test date: ${meta.time}`),
|
||||||
|
// TODO add links to repos at specified revisions
|
||||||
|
Tag('li', null, `Xash3D-FWGS revision: ${meta.revisions.xash3d}`),
|
||||||
|
Tag('li', null, `Half-Life-PBR revision: ${meta.revisions.pbr}`),
|
||||||
|
Tag('li', null, `HLRTest revision: ${meta.revisions.tests}`),
|
||||||
|
Tag('li', null, `Rendering took: ${meta.phase_render_time_sec.toFixed(1)} seconds`)
|
||||||
|
])].concat(emojiToTag(`🧪 Tests 💥: ${fails}/${total}🏁 (⚠${fails_pct.toFixed(3)}%)`));
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildTestResultImages(data) {
|
function buildTestResultImages(tests) {
|
||||||
return data.flatMap((d) => {
|
return tests.flatMap((d) => {
|
||||||
//return Tag('details', {id: makeId(d)}, null, [
|
//return Tag('details', {id: makeId(d)}, null, [
|
||||||
return Tag('div', {id: makeId(d), "class": "meta-block"}, null, [
|
return Tag('div', {id: makeId(d), "class": "meta-block"}, null, [
|
||||||
//Tag('summary', null, `${d.test}/${d.channel} δ=${d.diff_pct}`),
|
//Tag('summary', null, `${d.test}/${d.channel} δ=${d.diff_pct}`),
|
||||||
@@ -207,10 +217,8 @@ function buildTestResultImages(data) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function buildData(table, images, data, sort, filter, exact_match) {
|
function buildData(table, images, test_results, sort, filter, exact_match) {
|
||||||
if (sort) {
|
let tests = sort ? filterTests(test_results.tests) : test_results.tests
|
||||||
data = filterData(data);
|
|
||||||
}
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
let test = "", channel = "";
|
let test = "", channel = "";
|
||||||
const args = filter.split(" ");
|
const args = filter.split(" ");
|
||||||
@@ -221,7 +229,7 @@ function buildData(table, images, data, sort, filter, exact_match) {
|
|||||||
test = filter;
|
test = filter;
|
||||||
channel = filter;
|
channel = filter;
|
||||||
}
|
}
|
||||||
data = data.filter((d) => {
|
tests = tests.filter((d) => {
|
||||||
const test_result = exact_match ? d.test === test : d.test.includes(test);
|
const test_result = exact_match ? d.test === test : d.test.includes(test);
|
||||||
const channel_result = exact_match ? d.channel === channel : d.channel.includes(channel);
|
const channel_result = exact_match ? d.channel === channel : d.channel.includes(channel);
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
@@ -232,8 +240,8 @@ function buildData(table, images, data, sort, filter, exact_match) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
table.replaceChildren(...buildTestResultsTable(data));
|
table.replaceChildren(...buildTestResultsTable(tests));
|
||||||
images.replaceChildren(...buildTestResultImages(data));
|
images.replaceChildren(...buildTestResultImages(tests));
|
||||||
|
|
||||||
for (let block of images.querySelectorAll(".image-container")) {
|
for (let block of images.querySelectorAll(".image-container")) {
|
||||||
block.addEventListener("click", function() {
|
block.addEventListener("click", function() {
|
||||||
@@ -255,8 +263,8 @@ function buildData(table, images, data, sort, filter, exact_match) {
|
|||||||
|
|
||||||
saveToLocalStorage("rendertest_tablesort", sort);
|
saveToLocalStorage("rendertest_tablesort", sort);
|
||||||
}
|
}
|
||||||
const buildDataSlowMode = debounce((table, images, data, sort, filter, exact_match) => {
|
const buildDataSlowMode = debounce((table, images, test_results, sort, filter, exact_match) => {
|
||||||
buildData(table, images, data, sort, filter, exact_match);
|
buildData(table, images, test_results, sort, filter, exact_match);
|
||||||
}, ()=>{}, 250);
|
}, ()=>{}, 250);
|
||||||
|
|
||||||
|
|
||||||
@@ -550,7 +558,7 @@ window.onload = () => {
|
|||||||
]),
|
]),
|
||||||
Tag("label", null, null, [
|
Tag("label", null, null, [
|
||||||
Tag("input", {"type": "radio", "name": "sort_table", "value": "yes", ...uglyChecked(tableSort)}, null, null, "input", (e) => {
|
Tag("input", {"type": "radio", "name": "sort_table", "value": "yes", ...uglyChecked(tableSort)}, null, null, "input", (e) => {
|
||||||
buildData(table, images, data, true, filter.value, exactmatch_input.checked);
|
buildData(table, images, TEST_RESULTS, true, filter.value, exactmatch_input.checked);
|
||||||
// TODO: rewrite use reactive programming
|
// TODO: rewrite use reactive programming
|
||||||
tableSort = true;
|
tableSort = true;
|
||||||
}),
|
}),
|
||||||
@@ -558,7 +566,7 @@ window.onload = () => {
|
|||||||
]),
|
]),
|
||||||
Tag("label", null, null, [
|
Tag("label", null, null, [
|
||||||
Tag("input", {"type": "radio", "name": "sort_table", "value": "no", ...uglyChecked(!tableSort)}, null, null, "input", (e) => {
|
Tag("input", {"type": "radio", "name": "sort_table", "value": "no", ...uglyChecked(!tableSort)}, null, null, "input", (e) => {
|
||||||
buildData(table, images, data, false, filter.value, exactmatch_input.checked);
|
buildData(table, images, TEST_RESULTS, false, filter.value, exactmatch_input.checked);
|
||||||
tableSort = false;
|
tableSort = false;
|
||||||
}),
|
}),
|
||||||
Text(" no")
|
Text(" no")
|
||||||
@@ -570,12 +578,12 @@ window.onload = () => {
|
|||||||
Tag("label", {"class": "filter sticky"}, "Filter", [
|
Tag("label", {"class": "filter sticky"}, "Filter", [
|
||||||
filter = Tag("input", {"type": "input", "title": "Hotkey: ALT+F", "name": "filter", "value": filter_value}, null, null, "input", (e) => {
|
filter = Tag("input", {"type": "input", "title": "Hotkey: ALT+F", "name": "filter", "value": filter_value}, null, null, "input", (e) => {
|
||||||
saveToLocalStorage("rendertest_filter", e.target.value);
|
saveToLocalStorage("rendertest_filter", e.target.value);
|
||||||
buildDataSlowMode(table, images, data, tableSort, e.target.value, exactmatch_input.checked);
|
buildDataSlowMode(table, images, TEST_RESULTS, tableSort, e.target.value, exactmatch_input.checked);
|
||||||
}),
|
}),
|
||||||
Tag("label", null, null, [
|
Tag("label", null, null, [
|
||||||
exactmatch_input = Tag("input", {"type": "checkbox", "name": "exactmatch", ...uglyChecked(exactMatch)}, null, null, "change", (e) => {
|
exactmatch_input = Tag("input", {"type": "checkbox", "name": "exactmatch", ...uglyChecked(exactMatch)}, null, null, "change", (e) => {
|
||||||
saveToLocalStorage("rendertest_exactmatch", e.target.checked);
|
saveToLocalStorage("rendertest_exactmatch", e.target.checked);
|
||||||
buildDataSlowMode(table, images, data, tableSort, filter.value, exactmatch_input.checked);
|
buildDataSlowMode(table, images, TEST_RESULTS, tableSort, filter.value, exactmatch_input.checked);
|
||||||
}),
|
}),
|
||||||
Text("exact match")
|
Text("exact match")
|
||||||
])
|
])
|
||||||
@@ -586,7 +594,7 @@ window.onload = () => {
|
|||||||
Tag("div", {"class": "content"}, null, [
|
Tag("div", {"class": "content"}, null, [
|
||||||
Tag("h1", null, "Rendertest report"),
|
Tag("h1", null, "Rendertest report"),
|
||||||
Tag("h2", null, "Summary"),
|
Tag("h2", null, "Summary"),
|
||||||
Tag("div", {"id": "summary"}, null, [...buildSummary(data)]),
|
Tag("div", {"id": "summary"}, null, buildSummary(TEST_RESULTS)),
|
||||||
Tag("h2", null, "Images of things that are not perfect ", [
|
Tag("h2", null, "Images of things that are not perfect ", [
|
||||||
Tag("span", {"class": "emoji"}, "⤵")
|
Tag("span", {"class": "emoji"}, "⤵")
|
||||||
]),
|
]),
|
||||||
@@ -595,7 +603,7 @@ window.onload = () => {
|
|||||||
])
|
])
|
||||||
document.body.appendChild(gridContainer);
|
document.body.appendChild(gridContainer);
|
||||||
|
|
||||||
buildData(table, images, data, tableSort, filter_value, exactmatch_input.checked);
|
buildData(table, images, TEST_RESULTS, tableSort, filter_value, exactmatch_input.checked);
|
||||||
|
|
||||||
// TODO: remove this
|
// TODO: remove this
|
||||||
if (sidebarPos === "right") {
|
if (sidebarPos === "right") {
|
||||||
|
|||||||
+38
-4
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import time
|
||||||
|
|
||||||
ROOT = os.path.dirname(os.path.abspath(__file__))
|
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||||
imagecompare = f'{ROOT}/imagecompare'
|
imagecompare = f'{ROOT}/imagecompare'
|
||||||
@@ -66,10 +68,28 @@ parser.add_argument('--tests', '-t', type=test_list, default=saves, help='Run on
|
|||||||
# TODO how to check that the dir is valid? presence of xash3d executable and valve dir?
|
# TODO how to check that the dir is valid? presence of xash3d executable and valve dir?
|
||||||
parser.add_argument('--xash-dir', '-x', type=str, default=os.getcwd(), help='Path to xash3d-fwgs installation directory')
|
parser.add_argument('--xash-dir', '-x', type=str, default=os.getcwd(), help='Path to xash3d-fwgs installation directory')
|
||||||
|
|
||||||
|
parser.add_argument('--xash-revision', type=str, default='unknown', help='xash engine repo revision, commit_id<-dirty>')
|
||||||
|
parser.add_argument('--pbr-revision', type=str, default='unknown', help='PBR textures repo revision, commit_id<-dirty>')
|
||||||
|
parser.add_argument('--tests-revision', type=str, default='unknown', help='HLRTest (this) repo revision, commit_id<-dirty>')
|
||||||
|
|
||||||
# TODO parse commands in type=.. function
|
# TODO parse commands in type=.. function
|
||||||
parser.add_argument('command', type=str, default=None, help='Action to perform')
|
parser.add_argument('command', type=str, default=None, help='Action to perform')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
metadata = {}
|
||||||
|
metadata['time'] = datetime.now().astimezone().isoformat()
|
||||||
|
metadata['revisions'] = {
|
||||||
|
'xash3d': args.xash_revision,
|
||||||
|
'pbr': args.pbr_revision,
|
||||||
|
'tests': args.tests_revision,
|
||||||
|
}
|
||||||
|
# TODO:
|
||||||
|
# - OS/kernel version
|
||||||
|
# - GPU model
|
||||||
|
# - Vulkan version
|
||||||
|
# - GPU driver version
|
||||||
|
|
||||||
def make_script(file, tests: [str]):
|
def make_script(file, tests: [str]):
|
||||||
header = '''sv_cheats 1
|
header = '''sv_cheats 1
|
||||||
developer 0
|
developer 0
|
||||||
@@ -130,8 +150,9 @@ def render():
|
|||||||
print('Running xash3d...')
|
print('Running xash3d...')
|
||||||
mkdir_p(f'{args.xash_dir}/valve/rendertest')
|
mkdir_p(f'{args.xash_dir}/valve/rendertest')
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['LD_LIBRARY_PATH'] = f'{args.xash_dir}'
|
env['LD_LIBRARY_PATH'] = f'{args.xash_dir}:{env["LD_LIBRARY_PATH"]}'
|
||||||
|
|
||||||
|
start_time_sec = time.perf_counter()
|
||||||
with open(f'{WORKDIR}/xash-stdout.log', 'wb') as stdout, open(f'{WORKDIR}/xash-stderr.log', 'wb') as stderr:
|
with open(f'{WORKDIR}/xash-stdout.log', 'wb') as stdout, open(f'{WORKDIR}/xash-stderr.log', 'wb') as stderr:
|
||||||
result = subprocess.run([f'{args.xash_dir}/xash3d', '-ref', 'vk',
|
result = subprocess.run([f'{args.xash_dir}/xash3d', '-ref', 'vk',
|
||||||
'-nowriteconfig', '-nosound', '-log',
|
'-nowriteconfig', '-nosound', '-log',
|
||||||
@@ -139,6 +160,8 @@ def render():
|
|||||||
'-width', '1280', '-height', '800',
|
'-width', '1280', '-height', '800',
|
||||||
'+exec', 'rendertest.script'],
|
'+exec', 'rendertest.script'],
|
||||||
env=env, check=True, stdout=stdout, stderr=stderr)
|
env=env, check=True, stdout=stdout, stderr=stderr)
|
||||||
|
end_time_sec = time.perf_counter()
|
||||||
|
metadata['phase_render_time_sec'] = end_time_sec - start_time_sec
|
||||||
|
|
||||||
def compare_one(test: str, channel: str, image_base: str, image_gold: str, image_test: str, image_diff: str):
|
def compare_one(test: str, channel: str, image_base: str, image_gold: str, image_test: str, image_diff: str):
|
||||||
result = subprocess.run([imagecompare, image_gold, image_test, image_diff], text=True, capture_output=True)
|
result = subprocess.run([imagecompare, image_gold, image_test, image_diff], text=True, capture_output=True)
|
||||||
@@ -165,6 +188,7 @@ def compare():
|
|||||||
diffs = []
|
diffs = []
|
||||||
command_png()
|
command_png()
|
||||||
print(f'Comparing...')
|
print(f'Comparing...')
|
||||||
|
start_time_sec = time.perf_counter()
|
||||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||||
for test in args.tests:
|
for test in args.tests:
|
||||||
for channel, _ in channels.items():
|
for channel, _ in channels.items():
|
||||||
@@ -175,11 +199,19 @@ def compare():
|
|||||||
|
|
||||||
diffs.append(executor.submit(compare_one, test, channel, image_base, image_gold, image_test, image_diff))
|
diffs.append(executor.submit(compare_one, test, channel, image_base, image_gold, image_test, image_diff))
|
||||||
|
|
||||||
results = [diff.result() for diff in diffs]
|
tests = [diff.result() for diff in diffs]
|
||||||
|
end_time_sec = time.perf_counter()
|
||||||
|
metadata['phase_compare_time_sec'] = end_time_sec - start_time_sec
|
||||||
|
|
||||||
|
results = {
|
||||||
|
'metadata': metadata,
|
||||||
|
'tests': tests,
|
||||||
|
}
|
||||||
|
|
||||||
json.dump(results, open(f'{WORKDIR}/test_results.json', 'w'))
|
json.dump(results, open(f'{WORKDIR}/test_results.json', 'w'))
|
||||||
jsons = json.dumps(results)
|
jsons = json.dumps(results)
|
||||||
with open(f'{WORKDIR}/data.js', 'w') as js:
|
with open(f'{WORKDIR}/results.js', 'w') as js:
|
||||||
js.write(f'"use strict";\nconst data = {jsons};\n')
|
js.write(f'"use strict";\nconst TEST_RESULTS = {jsons};\n')
|
||||||
|
|
||||||
def command_compare():
|
def command_compare():
|
||||||
compile()
|
compile()
|
||||||
@@ -215,6 +247,8 @@ def command_render():
|
|||||||
copy_assets()
|
copy_assets()
|
||||||
render()
|
render()
|
||||||
|
|
||||||
|
# TODO make one long sequence of functions, and then call enabled ones, passing state via files
|
||||||
|
|
||||||
# TODO dict
|
# TODO dict
|
||||||
match args.command:
|
match args.command:
|
||||||
case 'run':
|
case 'run':
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
<link rel="stylesheet alternate" type="text/css" href="theme-light.css" disabled="true" data-theme="theme-light" title="☀️ Light theme">
|
<link rel="stylesheet alternate" type="text/css" href="theme-light.css" disabled="true" data-theme="theme-light" title="☀️ Light theme">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<script src="utils.js"></script>
|
<script src="utils.js"></script>
|
||||||
<script src="work/data.js"></script>
|
<script src="work/results.js"></script>
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Reference in New Issue
Block a user