Restore behavioral render preset override coverage
This commit is contained in:
1 parent
bd343a7be1
commit
56e1b76622
4 files changed
+117
-7
No files matched your search
@@ -54,6 +54,10 @@
|
|||||||
frame retirement. Rebuilt shim/bridge and rechecked a loaded Cyberpunk scene with camera
|
frame retirement. Rebuilt shim/bridge and rechecked a loaded Cyberpunk scene with camera
|
||||||
motion, RR E and path tracing at 1080p Ultra Performance on gfx1201.
|
motion, RR E and path tracing at 1080p Ultra Performance on gfx1201.
|
||||||
Removed brittle source-text/wording tests; configuration validation remains covered.
|
Removed brittle source-text/wording tests; configuration validation remains covered.
|
||||||
|
- Restore behavioral preset-override coverage through a shared, allocation-free policy used by
|
||||||
|
feature creation: SR/RR isolation, every quality mode, unset/empty overrides, and explicit
|
||||||
|
default-preset selection. Tests compile the helper directly without extracting shim source
|
||||||
|
or matching diagnostic wording; polling configuration validation and precedence remain covered.
|
||||||
|
|
||||||
# d4r 0.1.3
|
# d4r 0.1.3
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Marker polling configuration validation and environment precedence."""
|
"""Engine opt-in, preset-selection behavior and polling configuration precedence."""
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -29,6 +29,7 @@ class ShimConfigTests(unittest.TestCase):
|
|||||||
ini.write_text('[Engine]\nEnabled = maybe\n')
|
ini.write_text('[Engine]\nEnabled = maybe\n')
|
||||||
result = subprocess.run(cmd, env=env, text=True, capture_output=True)
|
result = subprocess.run(cmd, env=env, text=True, capture_output=True)
|
||||||
self.assertEqual(result.returncode, 2)
|
self.assertEqual(result.returncode, 2)
|
||||||
|
|
||||||
def test_launcher_marker_poll_defaults_overrides_and_validation(self):
|
def test_launcher_marker_poll_defaults_overrides_and_validation(self):
|
||||||
with tempfile.TemporaryDirectory() as temporary:
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
ini = Path(temporary) / 'd4r.ini'
|
ini = Path(temporary) / 'd4r.ini'
|
||||||
@@ -46,7 +47,79 @@ class ShimConfigTests(unittest.TestCase):
|
|||||||
ini.write_text(f'[Interop]\nMarkerPollUs = {value}\n')
|
ini.write_text(f'[Interop]\nMarkerPollUs = {value}\n')
|
||||||
result = subprocess.run(cmd, env=env, text=True, capture_output=True)
|
result = subprocess.run(cmd, env=env, text=True, capture_output=True)
|
||||||
self.assertEqual(result.returncode, 2)
|
self.assertEqual(result.returncode, 2)
|
||||||
self.assertIn('MarkerPollUs must be a number of microseconds', result.stderr)
|
|
||||||
|
|
||||||
|
class RenderPresetPolicyTests(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.directory = tempfile.TemporaryDirectory()
|
||||||
|
cls.addClassCleanup(cls.directory.cleanup)
|
||||||
|
cls.runner = Path(cls.directory.name) / 'render-presets'
|
||||||
|
source = r'''
|
||||||
|
#include "d4r_render_presets.h"
|
||||||
|
#include <cstdio>
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc != 2) return 2;
|
||||||
|
const bool rr = argv[1][0] == '1';
|
||||||
|
unsigned int presets[6] = {21, 22, 23, 24, 25, 26};
|
||||||
|
if (rr) {
|
||||||
|
for (unsigned int& preset : presets) preset += 10;
|
||||||
|
}
|
||||||
|
const auto overrideValue = d4r_parse_render_preset_override(
|
||||||
|
std::getenv(d4r_render_preset_variable(rr)));
|
||||||
|
overrideValue.apply(presets);
|
||||||
|
for (unsigned int preset : presets) std::printf("%u ", preset);
|
||||||
|
std::puts("");
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
subprocess.run(
|
||||||
|
['c++', '-std=c++17', '-Wall', '-Wextra', '-Werror',
|
||||||
|
'-I', str(ROOT / 'tools'), '-x', 'c++', '-', '-o', str(cls.runner)],
|
||||||
|
input=source, text=True, capture_output=True, check=True)
|
||||||
|
|
||||||
|
def select(self, rr=False, **overrides):
|
||||||
|
env = dict(os.environ)
|
||||||
|
for name in ('D4R_DLSS_PRESET', 'D4R_RR_PRESET'):
|
||||||
|
env.pop(name, None)
|
||||||
|
env.update(overrides)
|
||||||
|
result = subprocess.run(
|
||||||
|
[str(self.runner), '1' if rr else '0'], env=env,
|
||||||
|
text=True, capture_output=True, check=True, timeout=5)
|
||||||
|
return [int(value) for value in result.stdout.split()]
|
||||||
|
|
||||||
|
def test_sr_models_override_every_quality_mode(self):
|
||||||
|
for value in (5, 11, 12, 13):
|
||||||
|
with self.subTest(preset=value):
|
||||||
|
self.assertEqual(
|
||||||
|
self.select(D4R_DLSS_PRESET=str(value), D4R_RR_PRESET='4'),
|
||||||
|
[value] * 6)
|
||||||
|
|
||||||
|
def test_rr_models_do_not_use_the_sr_override(self):
|
||||||
|
for value in (4, 5):
|
||||||
|
with self.subTest(preset=value):
|
||||||
|
self.assertEqual(
|
||||||
|
self.select(rr=True, D4R_RR_PRESET=str(value), D4R_DLSS_PRESET='13'),
|
||||||
|
[value] * 6)
|
||||||
|
|
||||||
|
def test_unset_override_preserves_quality_specific_game_presets(self):
|
||||||
|
for rr, foreign in ((False, 'D4R_RR_PRESET'), (True, 'D4R_DLSS_PRESET')):
|
||||||
|
with self.subTest(rr=rr):
|
||||||
|
expected = list(range(31, 37) if rr else range(21, 27))
|
||||||
|
self.assertEqual(self.select(rr=rr), expected)
|
||||||
|
self.assertEqual(self.select(rr=rr, **{foreign: '13'}), expected)
|
||||||
|
|
||||||
|
def test_empty_override_does_not_fall_back_to_the_other_feature(self):
|
||||||
|
self.assertEqual(
|
||||||
|
self.select(D4R_DLSS_PRESET='', D4R_RR_PRESET='5'),
|
||||||
|
list(range(21, 27)))
|
||||||
|
self.assertEqual(
|
||||||
|
self.select(rr=True, D4R_RR_PRESET='', D4R_DLSS_PRESET='13'),
|
||||||
|
list(range(31, 37)))
|
||||||
|
|
||||||
|
def test_explicit_default_preset_overrides_game_presets(self):
|
||||||
|
self.assertEqual(self.select(D4R_DLSS_PRESET='0'), [0] * 6)
|
||||||
|
self.assertEqual(self.select(rr=True, D4R_RR_PRESET='0'), [0] * 6)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "d4r_event_wait.h"
|
#include "d4r_event_wait.h"
|
||||||
#include "d4r_frame_completion.h"
|
#include "d4r_frame_completion.h"
|
||||||
|
#include "d4r_render_presets.h"
|
||||||
#include "d4r_win32_wait.h"
|
#include "d4r_win32_wait.h"
|
||||||
#include "d4r_vkd3d_interop.h"
|
#include "d4r_vkd3d_interop.h"
|
||||||
#include "../engine/game.h"
|
#include "../engine/game.h"
|
||||||
@@ -7109,18 +7110,18 @@ static NgxResult create_feature(unsigned int featureId, void* parameters, NgxHan
|
|||||||
unsigned int presets[6];
|
unsigned int presets[6];
|
||||||
for (int index = 0; index < 6; ++index)
|
for (int index = 0; index < 6; ++index)
|
||||||
presets[index] = get_uint_or(parameters, presetNames[index], 0);
|
presets[index] = get_uint_or(parameters, presetNames[index], 0);
|
||||||
const std::string forced = env_string(rayReconstruction ? "D4R_RR_PRESET" : "D4R_DLSS_PRESET");
|
const std::string forced = env_string(d4r_render_preset_variable(rayReconstruction));
|
||||||
if (!forced.empty())
|
const auto presetOverride = d4r_parse_render_preset_override(forced.c_str());
|
||||||
|
if (presetOverride.enabled)
|
||||||
{
|
{
|
||||||
const unsigned int value = static_cast<unsigned int>(strtoul(forced.c_str(), nullptr, 0));
|
const unsigned int value = presetOverride.value;
|
||||||
const char* model = value == 5 ? "E" : value == 11 ? "K" : value == 12 ? "L" : value == 13 ? "M" : "custom";
|
const char* model = value == 5 ? "E" : value == 11 ? "K" : value == 12 ? "L" : value == 13 ? "M" : "custom";
|
||||||
logf("DLSS model override: D4R_DLSS_PRESET=%s (model %s) overrides game/OptiScaler presets "
|
logf("DLSS model override: D4R_DLSS_PRESET=%s (model %s) overrides game/OptiScaler presets "
|
||||||
"[DLAA=%u Quality=%u Balanced=%u Performance=%u UltraPerformance=%u UltraQuality=%u]; "
|
"[DLAA=%u Quality=%u Balanced=%u Performance=%u UltraPerformance=%u UltraQuality=%u]; "
|
||||||
"using preset=%u for all quality modes",
|
"using preset=%u for all quality modes",
|
||||||
forced.c_str(), model, presets[0], presets[1], presets[2], presets[3], presets[4], presets[5], value);
|
forced.c_str(), model, presets[0], presets[1], presets[2], presets[3], presets[4], presets[5], value);
|
||||||
for (unsigned int& preset : presets)
|
|
||||||
preset = value;
|
|
||||||
}
|
}
|
||||||
|
presetOverride.apply(presets);
|
||||||
feature->preset = presets[1];
|
feature->preset = presets[1];
|
||||||
// Direct output needs the native output kernel of the preset in use (verified: K = 11 through
|
// Direct output needs the native output kernel of the preset in use (verified: K = 11 through
|
||||||
// hiluma_engine_output, M = 13 through rrlite_downsample_kernel, its last kernel). Only a forced
|
// hiluma_engine_output, M = 13 through rrlite_downsample_kernel, its last kernel). Only a forced
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// Platform-specific environment reads stay in the caller. SR and RR deliberately
|
||||||
|
// use separate settings, even when both are configured for the same feature call.
|
||||||
|
inline constexpr const char* d4r_render_preset_variable(bool rayReconstruction)
|
||||||
|
{
|
||||||
|
return rayReconstruction ? "D4R_RR_PRESET" : "D4R_DLSS_PRESET";
|
||||||
|
}
|
||||||
|
|
||||||
|
// An absent/empty override leaves every game-selected quality preset unchanged.
|
||||||
|
// An explicit zero is an override too: it requests NGX's default preset.
|
||||||
|
struct D4rRenderPresetOverride
|
||||||
|
{
|
||||||
|
bool enabled;
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
void apply(unsigned int (&presets)[6]) const
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
for (unsigned int& preset : presets)
|
||||||
|
preset = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline D4rRenderPresetOverride d4r_parse_render_preset_override(const char* overrideValue)
|
||||||
|
{
|
||||||
|
if (overrideValue == nullptr || *overrideValue == '\0')
|
||||||
|
return {false, 0};
|
||||||
|
return {true, static_cast<unsigned int>(std::strtoul(overrideValue, nullptr, 0))};
|
||||||
|
}
|
||||||
Reference in new issue
Block a user