1
- #include < algorithm>
2
1
#include " slang-test-device-cache.h"
3
2
3
+ #include < algorithm>
4
+
4
5
// Static member accessor functions (Meyer's singleton pattern)
5
6
// This ensures proper destruction order - function-local statics are destroyed
6
7
// in reverse order of first access, avoiding the static destruction order fiasco
@@ -10,7 +11,11 @@ std::mutex& DeviceCache::getMutex()
10
11
return instance;
11
12
}
12
13
13
- std::unordered_map<DeviceCache::DeviceCacheKey, DeviceCache::CachedDevice, DeviceCache::DeviceCacheKeyHash>& DeviceCache::getDeviceCache ()
14
+ std::unordered_map<
15
+ DeviceCache::DeviceCacheKey,
16
+ DeviceCache::CachedDevice,
17
+ DeviceCache::DeviceCacheKeyHash>&
18
+ DeviceCache::getDeviceCache ()
14
19
{
15
20
static std::unordered_map<DeviceCacheKey, CachedDevice, DeviceCacheKeyHash> instance;
16
21
return instance;
@@ -24,11 +29,9 @@ uint64_t& DeviceCache::getNextCreationOrder()
24
29
25
30
bool DeviceCache::DeviceCacheKey::operator ==(const DeviceCacheKey& other) const
26
31
{
27
- return deviceType == other.deviceType &&
28
- enableValidation == other.enableValidation &&
32
+ return deviceType == other.deviceType && enableValidation == other.enableValidation &&
29
33
enableRayTracingValidation == other.enableRayTracingValidation &&
30
- profileName == other.profileName &&
31
- requiredFeatures == other.requiredFeatures ;
34
+ profileName == other.profileName && requiredFeatures == other.requiredFeatures ;
32
35
}
33
36
34
37
std::size_t DeviceCache::DeviceCacheKeyHash::operator ()(const DeviceCacheKey& key) const
@@ -37,17 +40,17 @@ std::size_t DeviceCache::DeviceCacheKeyHash::operator()(const DeviceCacheKey& ke
37
40
std::size_t h2 = std::hash<bool >{}(key.enableValidation );
38
41
std::size_t h3 = std::hash<bool >{}(key.enableRayTracingValidation );
39
42
std::size_t h4 = std::hash<std::string>{}(key.profileName );
40
-
43
+
41
44
std::size_t h5 = 0 ;
42
45
for (const auto & feature : key.requiredFeatures )
43
46
{
44
47
h5 ^= std::hash<std::string>{}(feature) + 0x9e3779b9 + (h5 << 6 ) + (h5 >> 2 );
45
48
}
46
-
49
+
47
50
return h1 ^ (h2 << 1 ) ^ (h3 << 2 ) ^ (h4 << 3 ) ^ (h5 << 4 );
48
51
}
49
52
50
- DeviceCache::CachedDevice::CachedDevice ()
53
+ DeviceCache::CachedDevice::CachedDevice ()
51
54
: creationOrder(0 )
52
55
{
53
56
}
@@ -57,11 +60,11 @@ void DeviceCache::evictOldestDeviceIfNeeded()
57
60
auto & deviceCache = getDeviceCache ();
58
61
if (deviceCache.size () < MAX_CACHED_DEVICES)
59
62
return ;
60
-
63
+
61
64
// Find the oldest device to evict
62
65
auto oldestIt = deviceCache.end ();
63
66
uint64_t oldestCreationOrder = UINT64_MAX;
64
-
67
+
65
68
for (auto it = deviceCache.begin (); it != deviceCache.end (); ++it)
66
69
{
67
70
if (it->second .creationOrder < oldestCreationOrder)
@@ -70,7 +73,7 @@ void DeviceCache::evictOldestDeviceIfNeeded()
70
73
oldestIt = it;
71
74
}
72
75
}
73
-
76
+
74
77
// Remove the oldest device - ComPtr will handle the actual device release
75
78
if (oldestIt != deviceCache.end ())
76
79
{
@@ -89,49 +92,49 @@ Slang::ComPtr<rhi::IDevice> DeviceCache::acquireDevice(const rhi::DeviceDesc& de
89
92
return device;
90
93
return nullptr ;
91
94
}
92
-
95
+
93
96
std::lock_guard<std::mutex> lock (getMutex ());
94
97
auto & deviceCache = getDeviceCache ();
95
98
auto & nextCreationOrder = getNextCreationOrder ();
96
-
99
+
97
100
// Create cache key
98
101
DeviceCacheKey key;
99
102
key.deviceType = desc.deviceType ;
100
103
key.enableValidation = desc.enableValidation ;
101
104
key.enableRayTracingValidation = desc.enableRayTracingValidation ;
102
105
key.profileName = desc.slang .targetProfile ? desc.slang .targetProfile : " " ;
103
-
106
+
104
107
// Add required features to key
105
108
for (int i = 0 ; i < desc.requiredFeatureCount ; ++i)
106
109
{
107
110
key.requiredFeatures .push_back (desc.requiredFeatures [i]);
108
111
}
109
112
std::sort (key.requiredFeatures .begin (), key.requiredFeatures .end ());
110
-
113
+
111
114
// Evict oldest device if we've reached the limit
112
115
evictOldestDeviceIfNeeded ();
113
-
116
+
114
117
// Check if we have a cached device
115
118
auto it = deviceCache.find (key);
116
119
if (it != deviceCache.end ())
117
120
{
118
121
// Return the cached device - COM reference counting handles the references
119
122
return it->second .device ;
120
123
}
121
-
124
+
122
125
// Create new device
123
126
Slang::ComPtr<rhi::IDevice> device;
124
127
auto result = rhi::getRHI ()->createDevice (desc, device.writeRef ());
125
128
if (SLANG_FAILED (result))
126
129
{
127
130
return nullptr ;
128
131
}
129
-
132
+
130
133
// Cache the device
131
134
CachedDevice& cached = deviceCache[key];
132
135
cached.device = device;
133
136
cached.creationOrder = nextCreationOrder++;
134
-
137
+
135
138
return device;
136
139
}
137
140
0 commit comments