EEVEE-Next: Tests support
Enable tests for EEVEE Next. As a workaround for allowing the use of EEVEE Next (still an experimental feature) with `--factory-startup`, `arg_handle_engine_set` enables the feature when `-E BLENDER_EEVEE_NEXT` is used. In addition, EEVEE Next is always registered, so it's available when calling `WM_init`. If it's actually disabled, it will be immediately unregistered after that. Notes: - `get_gpu_device_type` always fails with error: > GPU API is not available in background mode - Setup and tests are the same as EEVEE. There are many tests that only make sense for Cycles, and many EEVEE Next features that are not actually tested. Pull Request: https://projects.blender.org/blender/blender/pulls/112161
This commit is contained in:
parent
361d4abbfc
commit
b4de568cc4
@ -3042,14 +3042,38 @@ void DRW_engine_register(DrawEngineType *draw_engine_type)
|
||||
|
||||
void DRW_engines_register_experimental()
|
||||
{
|
||||
if (U.experimental.enable_eevee_next) {
|
||||
RE_engines_register(&DRW_engine_viewport_eevee_next_type);
|
||||
if (!U.experimental.enable_eevee_next) {
|
||||
/** Since EEVEE Next is always registered in `DRW_engines_register`,
|
||||
* Here we just have to unregister if it's not actually enabled. */
|
||||
for (auto *type = static_cast<RenderEngineType *>(R_engines.first); type; type = type->next) {
|
||||
if (type == &DRW_engine_viewport_eevee_next_type) {
|
||||
BLI_remlink(&R_engines, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto *type = static_cast<DRWRegisteredDrawEngine *>(g_registered_engines.engines.first);
|
||||
type != nullptr;
|
||||
type = static_cast<DRWRegisteredDrawEngine *>(type->next))
|
||||
{
|
||||
if (type->draw_engine == DRW_engine_viewport_eevee_next_type.draw_engine) {
|
||||
BLI_remlink(&g_registered_engines.engines, type);
|
||||
type->draw_engine->engine_free();
|
||||
g_registered_engines.len--;
|
||||
MEM_freeN(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_engines_register()
|
||||
{
|
||||
RE_engines_register(&DRW_engine_viewport_eevee_type);
|
||||
/* Always register EEVEE Next so it can be used in background mode with `--factory-startup`.
|
||||
* (Needed for tests). */
|
||||
RE_engines_register(&DRW_engine_viewport_eevee_next_type);
|
||||
|
||||
RE_engines_register(&DRW_engine_viewport_workbench_type);
|
||||
|
||||
DRW_engine_register(&draw_engine_gpencil_type);
|
||||
|
@ -2246,6 +2246,7 @@ enum {
|
||||
|
||||
/** #RenderData::engine (scene.cc) */
|
||||
extern const char *RE_engine_id_BLENDER_EEVEE;
|
||||
extern const char *RE_engine_id_BLENDER_EEVEE_NEXT;
|
||||
extern const char *RE_engine_id_BLENDER_WORKBENCH;
|
||||
extern const char *RE_engine_id_CYCLES;
|
||||
|
||||
|
@ -536,9 +536,6 @@ int main(int argc,
|
||||
|
||||
WM_init(C, argc, (const char **)argv);
|
||||
|
||||
/* Need to be after WM init so that userpref are loaded. */
|
||||
RE_engines_init_experimental();
|
||||
|
||||
#ifndef WITH_PYTHON
|
||||
printf(
|
||||
"\n* WARNING * - Blender compiled without Python!\n"
|
||||
@ -557,6 +554,10 @@ int main(int argc,
|
||||
BLI_args_parse(ba, ARG_PASS_FINAL, main_args_handle_load_file, C);
|
||||
#endif
|
||||
|
||||
/* Need to be after WM init so that userpref are loaded,
|
||||
* and after ars_parse, in case and experimental engine is enabled there. */
|
||||
RE_engines_init_experimental();
|
||||
|
||||
/* Explicitly free data allocated for argument parsing:
|
||||
* - 'ba'
|
||||
* - 'argv' on WIN32.
|
||||
|
@ -1614,6 +1614,12 @@ static int arg_handle_engine_set(int argc, const char **argv, void *data)
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
if (strcmp(argv[1], RE_engine_id_BLENDER_EEVEE_NEXT) == 0) {
|
||||
/** NOTE: Temp workaround to support EEVEE Next tests.
|
||||
* This ensures the engine is not unregistered in `DRW_engines_register_experimental`
|
||||
* when using --factory-startup. */
|
||||
U.experimental.enable_eevee_next = true;
|
||||
}
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
if (scene) {
|
||||
if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
|
||||
|
@ -679,6 +679,18 @@ if(WITH_CYCLES OR WITH_OPENGL_RENDER_TESTS)
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Eevee Next
|
||||
foreach(render_test ${render_tests})
|
||||
add_python_test(
|
||||
eevee_next_${render_test}_test
|
||||
${CMAKE_CURRENT_LIST_DIR}/eevee_next_render_tests.py
|
||||
-blender "${TEST_BLENDER_EXE}"
|
||||
-testdir "${TEST_SRC_DIR}/render/${render_test}"
|
||||
-idiff "${OPENIMAGEIO_IDIFF}"
|
||||
-outdir "${TEST_OUT_DIR}/eevee_next"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
foreach(render_test ${render_tests})
|
||||
# Workbench
|
||||
add_python_test(
|
||||
|
147
tests/python/eevee_next_render_tests.py
Normal file
147
tests/python/eevee_next_render_tests.py
Normal file
@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2015-2022 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def setup():
|
||||
import bpy
|
||||
|
||||
for scene in bpy.data.scenes:
|
||||
scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||||
|
||||
# Enable Eevee features
|
||||
scene = bpy.context.scene
|
||||
eevee = scene.eevee
|
||||
|
||||
eevee.gtao_distance = 1
|
||||
eevee.use_volumetric_shadows = True
|
||||
eevee.volumetric_tile_size = '2'
|
||||
eevee.use_motion_blur = True
|
||||
|
||||
# Does not work in edit mode
|
||||
try:
|
||||
# Simple probe setup
|
||||
bpy.ops.object.lightprobe_add(type='CUBEMAP', location=(0.5, 0, 1.5))
|
||||
cubemap = bpy.context.selected_objects[0]
|
||||
cubemap.scale = (2.5, 2.5, 1.0)
|
||||
cubemap.data.falloff = 0
|
||||
cubemap.data.clip_start = 2.4
|
||||
|
||||
bpy.ops.object.lightprobe_add(type='GRID', location=(0, 0, 0.25))
|
||||
grid = bpy.context.selected_objects[0]
|
||||
grid.scale = (1.735, 1.735, 1.735)
|
||||
grid.data.bake_samples = 256
|
||||
except:
|
||||
pass
|
||||
|
||||
# Only include the plane in probes
|
||||
for ob in scene.objects:
|
||||
if ob.name != 'Plane' and ob.type != 'LIGHT':
|
||||
ob.hide_probe_volume = True
|
||||
ob.hide_probe_cubemap = True
|
||||
|
||||
bpy.ops.scene.light_cache_bake()
|
||||
|
||||
|
||||
# When run from inside Blender, render and exit.
|
||||
try:
|
||||
import bpy
|
||||
inside_blender = True
|
||||
except ImportError:
|
||||
inside_blender = False
|
||||
|
||||
if inside_blender:
|
||||
try:
|
||||
setup()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_gpu_device_type(blender):
|
||||
#TODO: This always fails.
|
||||
command = [
|
||||
blender,
|
||||
"-noaudio",
|
||||
"--background"
|
||||
"--factory-startup"
|
||||
"--python",
|
||||
str(pathlib.Path(__file__).parent / "gpu_info.py")
|
||||
]
|
||||
try:
|
||||
completed_process = subprocess.run(command, stdout=subprocess.PIPE)
|
||||
for line in completed_process.stdout.read_text():
|
||||
if line.startswith("GPU_DEVICE_TYPE:"):
|
||||
vendor = line.split(':')[1]
|
||||
return vendor
|
||||
except BaseException as e:
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def get_arguments(filepath, output_filepath):
|
||||
return [
|
||||
"--background",
|
||||
"-noaudio",
|
||||
"--factory-startup",
|
||||
"--enable-autoexec",
|
||||
"--debug-memory",
|
||||
"--debug-exit-on-error",
|
||||
filepath,
|
||||
"-E", "BLENDER_EEVEE_NEXT",
|
||||
"-P",
|
||||
os.path.realpath(__file__),
|
||||
"-o", output_filepath,
|
||||
"-F", "PNG",
|
||||
"-f", "1"]
|
||||
|
||||
|
||||
def create_argparse():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-blender", nargs="+")
|
||||
parser.add_argument("-testdir", nargs=1)
|
||||
parser.add_argument("-outdir", nargs=1)
|
||||
parser.add_argument("-idiff", nargs=1)
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
parser = create_argparse()
|
||||
args = parser.parse_args()
|
||||
|
||||
blender = args.blender[0]
|
||||
test_dir = args.testdir[0]
|
||||
idiff = args.idiff[0]
|
||||
output_dir = args.outdir[0]
|
||||
|
||||
gpu_device_type = get_gpu_device_type(blender)
|
||||
reference_override_dir = None
|
||||
if gpu_device_type == "AMD":
|
||||
reference_override_dir = "eevee_next_renders/amd"
|
||||
|
||||
from modules import render_report
|
||||
report = render_report.Report("Eevee Next", output_dir, idiff)
|
||||
report.set_pixelated(True)
|
||||
report.set_reference_dir("eevee_next_renders")
|
||||
report.set_reference_override_dir(reference_override_dir)
|
||||
report.set_compare_engine('cycles', 'CPU')
|
||||
|
||||
test_dir_name = Path(test_dir).name
|
||||
if test_dir_name.startswith('image'):
|
||||
report.set_fail_threshold(0.051)
|
||||
|
||||
ok = report.run(test_dir, blender, get_arguments, batch=True)
|
||||
|
||||
sys.exit(not ok)
|
||||
|
||||
|
||||
if not inside_blender and __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user