|
17 | 17 | _VALIDATION_LAYER = "VK_LAYER_KHRONOS_validation" |
18 | 18 | _VALIDATION_ENV = "EXECUTORCH_VGF_VULKAN_VALIDATION" |
19 | 19 | _EXPECTED_VUID = "VUID-VkApplicationInfo-sType-sType" |
20 | | - |
21 | 20 | # We check that validation layer is enabled. |
22 | 21 | # Run the actual Vulkan call in a child process so loading Vulkan/VVL does not |
23 | 22 | # modify the pytest process. |
@@ -339,6 +338,90 @@ def test_vgf_validation_wrapper_fails_on_validation_error(): |
339 | 338 | ) |
340 | 339 |
|
341 | 340 |
|
| 341 | +def test_vgf_validation_wrapper_enables_object_lifetime_checks(): |
| 342 | + """Lifetime/core validation must be enabled without leaking Vulkan |
| 343 | + objects. |
| 344 | + """ |
| 345 | + |
| 346 | + if not _env_flag_enabled(_VALIDATION_ENV): |
| 347 | + pytest.skip(f"{_VALIDATION_ENV} is not enabled for this test run") |
| 348 | + |
| 349 | + expected_settings = { |
| 350 | + "VK_LAYER_OBJECT_LIFETIME": "1", |
| 351 | + "VK_LAYER_VALIDATE_CORE": "1", |
| 352 | + } |
| 353 | + |
| 354 | + # Verify the pytest/runner configuration first. This checks that |
| 355 | + # runner_utils._enable_vulkan_validation() and the autouse fixture propagate |
| 356 | + # the settings into VGF tests. |
| 357 | + for name, expected in expected_settings.items(): |
| 358 | + assert os.environ.get(name) == expected, ( |
| 359 | + f"VGF Vulkan validation is enabled, but {name} is not explicitly " |
| 360 | + f"enabled. Expected {name}={expected}." |
| 361 | + ) |
| 362 | + |
| 363 | + validation_wrapper = ( |
| 364 | + Path(__file__).resolve().parents[1] / "run_with_vulkan_validation.sh" |
| 365 | + ) |
| 366 | + |
| 367 | + if not validation_wrapper.is_file(): |
| 368 | + pytest.skip( |
| 369 | + "Vulkan validation shell wrapper is not available in this " |
| 370 | + "test environment" |
| 371 | + ) |
| 372 | + |
| 373 | + env = os.environ.copy() |
| 374 | + env[_VALIDATION_ENV] = "1" |
| 375 | + |
| 376 | + # Remove the inherited values so this child verifies that the wrapper |
| 377 | + # itself exports the settings. No Vulkan object is created by this probe. |
| 378 | + for name in expected_settings: |
| 379 | + env.pop(name, None) |
| 380 | + |
| 381 | + settings_probe = """\ |
| 382 | +import os |
| 383 | +
|
| 384 | +settings = ( |
| 385 | + "VK_LAYER_OBJECT_LIFETIME", |
| 386 | + "VK_LAYER_VALIDATE_CORE", |
| 387 | +) |
| 388 | +
|
| 389 | +for name in settings: |
| 390 | + value = os.environ.get(name) |
| 391 | + print(f"{name}={value}") |
| 392 | + if value != "1": |
| 393 | + raise SystemExit(f"{name} must be 1, got {value!r}") |
| 394 | +""" |
| 395 | + |
| 396 | + result = subprocess.run( # nosec B603 |
| 397 | + [ |
| 398 | + str(validation_wrapper), |
| 399 | + sys.executable, |
| 400 | + "-c", |
| 401 | + settings_probe, |
| 402 | + ], |
| 403 | + env=env, |
| 404 | + check=False, |
| 405 | + capture_output=True, |
| 406 | + text=True, |
| 407 | + timeout=30, |
| 408 | + ) |
| 409 | + |
| 410 | + assert result.returncode == 0, ( |
| 411 | + "The Vulkan validation wrapper did not propagate the explicit " |
| 412 | + "object-lifetime/core validation settings.\n\n" |
| 413 | + f"stdout:\n{result.stdout}\n\n" |
| 414 | + f"stderr:\n{result.stderr}" |
| 415 | + ) |
| 416 | + |
| 417 | + for name, expected in expected_settings.items(): |
| 418 | + assert f"{name}={expected}" in result.stdout, ( |
| 419 | + f"The wrapper child did not observe {name}={expected}.\n\n" |
| 420 | + f"stdout:\n{result.stdout}\n\n" |
| 421 | + f"stderr:\n{result.stderr}" |
| 422 | + ) |
| 423 | + |
| 424 | + |
342 | 425 | def test_vgf_validation_wrapper_preserves_error_from_earlier_vulkan_child(): |
343 | 426 | """A later clean Vulkan child must not erase an earlier validation error.""" |
344 | 427 |
|
|
0 commit comments