|
3 | 3 | using System.Collections.Generic; |
4 | 4 | using System.Linq; |
5 | 5 | using Unity.Collections; |
| 6 | +using Unity.Profiling; |
6 | 7 | using UnityEngine.InputSystem.Utilities; |
7 | 8 |
|
8 | 9 | ////REVIEW: given we have the global ActionPerformed callback, do we really need the per-map callback? |
@@ -313,6 +314,11 @@ public event Action<InputAction.CallbackContext> actionTriggered |
313 | 314 | remove => m_ActionCallbacks.RemoveCallback(value); |
314 | 315 | } |
315 | 316 |
|
| 317 | + /// <summary> |
| 318 | + /// ProfilerMarker to measure how long it takes to resolve bindings. |
| 319 | + /// </summary> |
| 320 | + static readonly ProfilerMarker k_ResolveBindingsProfilerMarker = new ProfilerMarker("InputActionMap.ResolveBindings"); |
| 321 | + |
316 | 322 | /// <summary> |
317 | 323 | /// Construct an action map with default values. |
318 | 324 | /// </summary> |
@@ -1299,100 +1305,104 @@ internal bool ResolveBindingsIfNecessary() |
1299 | 1305 | /// </remarks> |
1300 | 1306 | internal void ResolveBindings() |
1301 | 1307 | { |
1302 | | - // Make sure that if we trigger callbacks as part of disabling and re-enabling actions, |
1303 | | - // we don't trigger a re-resolve while we're already resolving bindings. |
1304 | | - using (InputActionRebindingExtensions.DeferBindingResolution()) |
| 1308 | + using (k_ResolveBindingsProfilerMarker.Auto()) |
1305 | 1309 | { |
1306 | | - // In case we have actions that are currently enabled, we temporarily retain the |
1307 | | - // UnmanagedMemory of our InputActionState so that we can sync action states after |
1308 | | - // we have re-resolved bindings. |
1309 | | - var oldMemory = new InputActionState.UnmanagedMemory(); |
1310 | | - try |
| 1310 | + // Make sure that if we trigger callbacks as part of disabling and re-enabling actions, |
| 1311 | + // we don't trigger a re-resolve while we're already resolving bindings. |
| 1312 | + using (InputActionRebindingExtensions.DeferBindingResolution()) |
1311 | 1313 | { |
1312 | | - OneOrMore<InputActionMap, ReadOnlyArray<InputActionMap>> actionMaps; |
| 1314 | + // In case we have actions that are currently enabled, we temporarily retain the |
| 1315 | + // UnmanagedMemory of our InputActionState so that we can sync action states after |
| 1316 | + // we have re-resolved bindings. |
| 1317 | + var oldMemory = new InputActionState.UnmanagedMemory(); |
| 1318 | + try |
| 1319 | + { |
| 1320 | + OneOrMore<InputActionMap, ReadOnlyArray<InputActionMap>> actionMaps; |
1313 | 1321 |
|
1314 | | - // Start resolving. |
1315 | | - var resolver = new InputBindingResolver(); |
| 1322 | + // Start resolving. |
| 1323 | + var resolver = new InputBindingResolver(); |
1316 | 1324 |
|
1317 | | - // If we're part of an asset, we share state and thus binding resolution with |
1318 | | - // all maps in the asset. |
1319 | | - var needFullResolve = m_State == null; |
1320 | | - if (m_Asset != null) |
1321 | | - { |
1322 | | - actionMaps = m_Asset.actionMaps; |
1323 | | - Debug.Assert(actionMaps.Count > 0, "Asset referred to by action map does not have action maps"); |
| 1325 | + // If we're part of an asset, we share state and thus binding resolution with |
| 1326 | + // all maps in the asset. |
| 1327 | + var needFullResolve = m_State == null; |
| 1328 | + if (m_Asset != null) |
| 1329 | + { |
| 1330 | + actionMaps = m_Asset.actionMaps; |
| 1331 | + Debug.Assert(actionMaps.Count > 0, "Asset referred to by action map does not have action maps"); |
1324 | 1332 |
|
1325 | | - // If there's a binding mask set on the asset, apply it. |
1326 | | - resolver.bindingMask = m_Asset.m_BindingMask; |
| 1333 | + // If there's a binding mask set on the asset, apply it. |
| 1334 | + resolver.bindingMask = m_Asset.m_BindingMask; |
1327 | 1335 |
|
1328 | | - foreach (var map in actionMaps) |
| 1336 | + foreach (var map in actionMaps) |
| 1337 | + { |
| 1338 | + needFullResolve |= map.bindingResolutionNeedsFullReResolve; |
| 1339 | + map.needToResolveBindings = false; |
| 1340 | + map.bindingResolutionNeedsFullReResolve = false; |
| 1341 | + map.controlsForEachActionInitialized = false; |
| 1342 | + } |
| 1343 | + } |
| 1344 | + else |
1329 | 1345 | { |
1330 | | - needFullResolve |= map.bindingResolutionNeedsFullReResolve; |
1331 | | - map.needToResolveBindings = false; |
1332 | | - map.bindingResolutionNeedsFullReResolve = false; |
1333 | | - map.controlsForEachActionInitialized = false; |
| 1346 | + // Standalone action map (possibly a hidden one created for a singleton action). |
| 1347 | + // Gets its own private state. |
| 1348 | + |
| 1349 | + actionMaps = this; |
| 1350 | + needFullResolve |= bindingResolutionNeedsFullReResolve; |
| 1351 | + needToResolveBindings = false; |
| 1352 | + bindingResolutionNeedsFullReResolve = false; |
| 1353 | + controlsForEachActionInitialized = false; |
1334 | 1354 | } |
1335 | | - } |
1336 | | - else |
1337 | | - { |
1338 | | - // Standalone action map (possibly a hidden one created for a singleton action). |
1339 | | - // Gets its own private state. |
1340 | | - |
1341 | | - actionMaps = this; |
1342 | | - needFullResolve |= bindingResolutionNeedsFullReResolve; |
1343 | | - needToResolveBindings = false; |
1344 | | - bindingResolutionNeedsFullReResolve = false; |
1345 | | - controlsForEachActionInitialized = false; |
1346 | | - } |
1347 | 1355 |
|
1348 | | - // If we already have a state, re-use the arrays we have already allocated. |
1349 | | - // NOTE: We will install the arrays on the very same InputActionState instance below. In the |
1350 | | - // case where we didn't have to grow the arrays, we should end up with zero GC allocations |
1351 | | - // here. |
1352 | | - var hasEnabledActions = false; |
1353 | | - InputControlList<InputControl> activeControls = default; |
1354 | | - if (m_State != null) |
1355 | | - { |
1356 | | - // Grab a clone of the current memory. We clone because disabling all the actions |
1357 | | - // in the map will alter the memory state and we want the state before we start |
1358 | | - // touching it. |
1359 | | - oldMemory = m_State.memory.Clone(); |
| 1356 | + // If we already have a state, re-use the arrays we have already allocated. |
| 1357 | + // NOTE: We will install the arrays on the very same InputActionState instance below. In the |
| 1358 | + // case where we didn't have to grow the arrays, we should end up with zero GC allocations |
| 1359 | + // here. |
| 1360 | + var hasEnabledActions = false; |
| 1361 | + InputControlList<InputControl> activeControls = default; |
| 1362 | + if (m_State != null) |
| 1363 | + { |
| 1364 | + // Grab a clone of the current memory. We clone because disabling all the actions |
| 1365 | + // in the map will alter the memory state and we want the state before we start |
| 1366 | + // touching it. |
| 1367 | + oldMemory = m_State.memory.Clone(); |
1360 | 1368 |
|
1361 | | - m_State.PrepareForBindingReResolution(needFullResolve, ref activeControls, ref hasEnabledActions); |
| 1369 | + m_State.PrepareForBindingReResolution(needFullResolve, ref activeControls, ref hasEnabledActions); |
1362 | 1370 |
|
1363 | | - // Reuse the arrays we have so that we can avoid managed memory allocations, if possible. |
1364 | | - resolver.StartWithPreviousResolve(m_State, isFullResolve: needFullResolve); |
| 1371 | + // Reuse the arrays we have so that we can avoid managed memory allocations, if possible. |
| 1372 | + resolver.StartWithPreviousResolve(m_State, isFullResolve: needFullResolve); |
1365 | 1373 |
|
1366 | | - // Throw away old memory. |
1367 | | - m_State.memory.Dispose(); |
1368 | | - } |
| 1374 | + // Throw away old memory. |
| 1375 | + m_State.memory.Dispose(); |
| 1376 | + } |
1369 | 1377 |
|
1370 | | - // Resolve all maps in the asset. |
1371 | | - foreach (var map in actionMaps) |
1372 | | - resolver.AddActionMap(map); |
| 1378 | + // Resolve all maps in the asset. |
| 1379 | + foreach (var map in actionMaps) |
| 1380 | + resolver.AddActionMap(map); |
1373 | 1381 |
|
1374 | | - // Install state. |
1375 | | - if (m_State == null) |
1376 | | - { |
1377 | | - m_State = new InputActionState(); |
1378 | | - m_State.Initialize(resolver); |
1379 | | - } |
1380 | | - else |
1381 | | - { |
1382 | | - m_State.ClaimDataFrom(resolver); |
| 1382 | + // Install state. |
| 1383 | + if (m_State == null) |
| 1384 | + { |
| 1385 | + m_State = new InputActionState(); |
| 1386 | + m_State.Initialize(resolver); |
| 1387 | + } |
| 1388 | + else |
| 1389 | + { |
| 1390 | + m_State.ClaimDataFrom(resolver); |
| 1391 | + } |
| 1392 | + |
| 1393 | + if (m_Asset != null) |
| 1394 | + { |
| 1395 | + foreach (var map in actionMaps) |
| 1396 | + map.m_State = m_State; |
| 1397 | + m_Asset.m_SharedStateForAllMaps = m_State; |
| 1398 | + } |
| 1399 | + |
| 1400 | + m_State.FinishBindingResolution(hasEnabledActions, oldMemory, activeControls, isFullResolve: needFullResolve); |
1383 | 1401 | } |
1384 | | - if (m_Asset != null) |
| 1402 | + finally |
1385 | 1403 | { |
1386 | | - foreach (var map in actionMaps) |
1387 | | - map.m_State = m_State; |
1388 | | - m_Asset.m_SharedStateForAllMaps = m_State; |
| 1404 | + oldMemory.Dispose(); |
1389 | 1405 | } |
1390 | | - |
1391 | | - m_State.FinishBindingResolution(hasEnabledActions, oldMemory, activeControls, isFullResolve: needFullResolve); |
1392 | | - } |
1393 | | - finally |
1394 | | - { |
1395 | | - oldMemory.Dispose(); |
1396 | 1406 | } |
1397 | 1407 | } |
1398 | 1408 | } |
|
0 commit comments