diff options
| author | Gangzheng Tong <tonggangzheng@gmail.com> | 2025-09-22 15:46:42 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-22 22:46:42 +0000 |
| commit | ba8132345cbae5b749b4a01deda732ad6f8251a0 (patch) | |
| tree | f00ad0dd2d26f49112e430615106c9f6d22de032 /tools/render-test/slang-test-device-cache.h | |
| parent | bd24cc271c5d151dbaa7e4da674cbc219aef8153 (diff) | |
Add RHI Device Caching and Test Prefix Exclusion (#8448)
# Add RHI Device Caching and Test Prefix Exclusion
## Summary
This PR introduces two key improvements to the Slang test
infrastructure:
1. **RHI Device Caching**: Implements device caching to significantly
speed up test execution by reusing graphics devices across tests, **RHI
Device Caching reduces slang-test execution time from ~15 minutes to ~5
minutes in Windows release builds**
2. **Test Prefix Exclusion**: Adds `-exclude-prefix` option to skip
tests matching specified path prefixes
## Changes
### RHI Device Caching
- **New `DeviceCache` class** (`slang-test-device-cache.h/cpp`):
Thread-safe device cache with LRU eviction (max 10 devices)
- **Cache control option**: `-cache-rhi-device` flag in both
`slang-test` and `render-test`
- Default: **enabled** in slang-test, **disabled** in render-test when
run standalone
- Automatically skips caching for CUDA devices (due to driver issues)
- **Performance benefit**: Eliminates expensive device
creation/destruction cycles, especially beneficial for Vulkan on Tegra
platforms
### Test Prefix Exclusion
- **New `-exclude-prefix <prefix>` option** in slang-test
- Allows excluding entire test directories or patterns from execution
- Complements existing `-category` and individual test filtering options
### Usage Examples
```bash
# Enable device caching (default)
slang-test
# Disable device caching
slang-test -cache-rhi-device false
# Exclude tests from specific directories
slang-test -exclude-prefix tests/problematic/
slang-test -exclude-prefix tests/slow/ -exclude-prefix tests/experimental/
```
This change should significantly improve test execution performance,
particularly in CI environments with frequent device operations. This is
needed for running the GPU test in aarch64, where repeated device
creation/destroy is causing driver issues.
Needed by: https://github.com/shader-slang/slang/issues/8346
---------
Co-authored-by: slangbot <ellieh+slangbot@nvidia.com>
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'tools/render-test/slang-test-device-cache.h')
| -rw-r--r-- | tools/render-test/slang-test-device-cache.h | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/tools/render-test/slang-test-device-cache.h b/tools/render-test/slang-test-device-cache.h new file mode 100644 index 000000000..752d03ff1 --- /dev/null +++ b/tools/render-test/slang-test-device-cache.h @@ -0,0 +1,97 @@ +#pragma once + +#include <mutex> +#include <slang-rhi.h> +#include <string> +#include <unordered_map> +#include <vector> + +// Device Cache for preventing NVIDIA Tegra driver state corruption +// This cache reuses Vulkan instances and devices to avoid the VK_ERROR_INCOMPATIBLE_DRIVER +// issue that occurs after ~19 device creation/destruction cycles on Tegra platforms. +// Uses ComPtr for automatic device lifecycle management - devices are released when removed from +// cache. +class DeviceCache +{ +public: + struct DeviceCacheKey + { + rhi::DeviceType deviceType; + bool enableValidation; + bool enableRayTracingValidation; + std::string profileName; + std::vector<std::string> requiredFeatures; + + bool operator==(const DeviceCacheKey& other) const; + }; + + struct DeviceCacheKeyHash + { + std::size_t operator()(const DeviceCacheKey& key) const; + }; + + struct CachedDevice + { + Slang::ComPtr<rhi::IDevice> device; + uint64_t creationOrder; + + CachedDevice(); + }; + +private: + static constexpr int MAX_CACHED_DEVICES = 10; + + // Use function-local statics to control destruction order (Meyer's singleton pattern) + static std::mutex& getMutex(); + static std::unordered_map<DeviceCacheKey, CachedDevice, DeviceCacheKeyHash>& getDeviceCache(); + static uint64_t& getNextCreationOrder(); + + static void evictOldestDeviceIfNeeded(); + +public: + static SlangResult acquireDevice(const rhi::DeviceDesc& desc, rhi::IDevice** outDevice); + static void cleanCache(); +}; + +// RAII wrapper for cached devices to ensure proper cleanup +class CachedDeviceWrapper +{ +private: + Slang::ComPtr<rhi::IDevice> m_device; + +public: + CachedDeviceWrapper() = default; + + CachedDeviceWrapper(Slang::ComPtr<rhi::IDevice> device) + : m_device(device) + { + } + + ~CachedDeviceWrapper() {} + + // Move constructor + CachedDeviceWrapper(CachedDeviceWrapper&& other) noexcept + : m_device(std::move(other.m_device)) + { + } + + // Move assignment + CachedDeviceWrapper& operator=(CachedDeviceWrapper&& other) noexcept + { + if (this != &other) + { + m_device = std::move(other.m_device); + } + return *this; + } + + // Delete copy constructor and assignment + CachedDeviceWrapper(const CachedDeviceWrapper&) = delete; + CachedDeviceWrapper& operator=(const CachedDeviceWrapper&) = delete; + + rhi::IDevice* get() const { return m_device.get(); } + rhi::IDevice* operator->() const { return m_device.get(); } + operator bool() const { return m_device != nullptr; } + + Slang::ComPtr<rhi::IDevice>& getComPtr() { return m_device; } +}; |
