Hantera ström och värme

När HoloLens 2 körs i varma miljöer eller med höga prestandakrav (cpu-/GPU-användning, kringutrustningsanvändning osv.) kan det bli tillräckligt varmt för att det ska vidta åtgärder automatiskt för att förhindra överhettning. Dessa åtgärder omfattar bland annat följande:

  • Justera laddningsprestanda
  • Ge användarfeedback
  • Stänga program

... och i värsta fall:

  • Stänga av HoloLens 2

Om ditt program kräver hög kringutrustningsprestanda bör du överväga att använda PowerThermalNotification Software Development Kit (SDK) för att prenumerera på meddelandehändelser och implementera dina egna anpassade åtgärder. Detta kan göra att enheten kan fungera längre i situationer när ett program annars kan avslutas av systemet.

Anteckning

Stöd för Microsoft.MixedReality.PowerThermalNotification SDK ingår i 22H1-versionen.

Den här artikeln beskriver PowerThermalNotification SDK och dess grundläggande användning för att komma igång.

Var hämtar jag SDK:t?

PowerThermalNotification SDK kan laddas ned via Mixed Reality funktionsverktyget.

PowerThermalNotification SDK stöder språkprojektioner för C# och C++, vilket gör det möjligt för utvecklare att utveckla program för Win32- eller UWP-plattformar.

Begreppsmässig översikt

Den ström som förbrukas av HoloLens 2 avleds i värme. En traditionell datorenhet skulle ha en fläkt för att åtgärda detta, men en bärbar enhet måste vara enkel. På grund av detta är kyllösningen mer komplex. HoloLens 2 har inbyggda säkerhetsfunktioner för maskinvara och programvara för att säkerställa att headsetet inte blir för varmt för användaren, men dessa funktioner måste också balanseras med användarupplevelsen. Om vi till exempel vet vilken del av HoloLens 2 värms upp kan vi välja att begränsa kringutrustningen som ansvarar för denna värme. Som en sista utväg kan vi stänga ett program som tros vara ansvarig för den kraft som ledde till denna värme.

HoloLens 2 hanterar värmeproblem med hjälp av temperatursensorer. Ett termiskt ramverk kopplar grupper av sensorer till olika kringutrustning på enheten. Sensorerna är grupperade eftersom det kan vara omöjligt att avgöra vilken kringutrustning i ett fysiskt område som ansvarar för strömdragningen som värmer upp HoloLens 2.

PowerThermalNotification SDK exponerar de API:er som krävs för att övervaka dessa grupper av sensorer. SDK-händelser utlöses när en kringutrustning som används av programmet visar tecken på att en åtgärd kan krävas. Programmet kan sedan anpassa sin kundupplevelse för att minska den termiska påverkan. Att minska påverkan innebär mindre risk för systemåtgärder som program- eller enhetsavstängning.

Ett enkelt exempel är ett program som använder processorn för att bearbeta en stor mängd videodata. Programmet kan prenumerera på ett prestandameddelande för CPU-komponenten. När programmet får ett meddelande kan det minska CPU-arbetsbelastningen. Om en annan händelse tas emot som anger att ingen ytterligare åtgärd krävs kan CPU-arbetsbelastningen återställas.

Plattformssvar

Följande tabell är en uppdelning av systemåtgärder efter kringutrustning. Åtgärder som beskrivs nedan kan ignoreras med hjälp av SDK: et. Se Utelämna standardsystemreduceringar

Perifera MinimumUserImpact MediumUserImpact MaximumUserImpact Sista utväg Avstängning av programvara Felsäker
GPU Begränsa MRC-kvalitet
Justera VSYNC-intervall
Skärm Djup FPS-minskning
Kringutrustning Visningsvarning
Stäng program
Stoppa MRC-avbildning
Avstängning av operativsystem Maskinvaruavstängning

Anteckning

Åtgärder i kolumnerna "Last Resort", "Software Shutdown" och "Failsafe" kan inte ignoreras.

Förslag på programsvar

Följande är en uppdelning av föreslagna åtgärder som ett program kan vidta baserat på vilken kringutrustning som behöver åtgärdas. Det är upp till programutvecklaren att avgöra vilka av dessa åtgärder som kan ha en mer betydande effekt på varje kringutrustning eftersom varje program skiljer sig åt. Utvecklare bör prioritera åtgärder som de vidtar baserat på effekten för slutanvändaren.

Föreslagna åtgärder efter kringutrustning

Processor

GPU

DRAM

Nätverk

Batteri

Skärm

  • Öka antalet svarta bildpunkter i scenen
  • Använd lågeffektfärger (till exempel grönt)
  • Tona ned skärmen

Foto/videokamera

  • Översikt
  • Minska kameraupplösningen
  • Minska kameraramhastigheten
  • Minska appens efterbearbetning av kamerabilder
  • Sluta använda foto-/videokameran

Användningsfall för implementering

SDK är utformat för att stödja två standardanvändningsfall för att få information:

  • Händelsebaserad
  • Avsökningsbaserad

Händelsebaserade meddelanden ger den snabbaste feedbacksökvägen till programmet om den behöver vidta åtgärder. I vissa fall kan det dock vara enklare för utvecklaren att använda avsökning.

Anteckning

Tillståndsinformationen uppdateras som mest med några sekunders mellanrum för varje kringutrustning, så avsökningen går snabbare än så kan slösa cpu-cykler.

Händelsebaserad API-användning

Registrera för händelser

Det finns tre krav för att få meddelanden:

Du får inte händelser om programmet inte uppfyller dessa krav.

Det första objektet kan kontrolleras med hjälp av funktionen IsSupported . Om systemet stöder meddelanden för minst en av kringutrustningen i masken returnerar funktionen true. Du kan välja att inte kontrollera stödet med den här funktionen så länge programmet inte uttryckligen är beroende av PowerThermalNotification SDK-händelser.

När du uppfyller de tre kraven ovan får du inledande meddelanden för all KringutrustningOfInterest som stöds. Om du senare ändrar PeripheralsOfInterest eller någon av händelsehanterarna får du en annan uppsättning meddelanden baserat på aktuell status.

Här är ett kodfragment för att ta tag i PowerThermalNotification-klassinstansen och konfigurera den för meddelanden för både PowerThermalPeripheralFlags.Cpu och PowerThermalPeripheralFlags.PhotoVideoCamera:

using Microsoft.MixedReality.PowerThermalNotification;

private void NotificationHandler(object sender, PowerThermalEventArgs args)
{
    //  Notification handling can be done here using information contained in args
}

private void InitializeThermalNotifications()
{
    PowerThermalNotification p = PowerThermalNotification.GetForCurrentProcess();
    
    PowerThermalPeripheralFlags requestedFlags = PowerThermalPeripheralFlags.Cpu | PowerThermalPeripheralFlags.PhotoVideoCamera;
     if (PowerThermalNotification.IsSupported(requestedFlags))
    {
        //At least one of these peripherals is supported by the system
        p.PeripheralsOfInterest = requestedFlags;
        p.PowerThermalMitigationLevelChanged += NotificationHandler;
    }  
}

Hantera händelser

När händelsen PowerThermalMitigationLevelChanged utlöses medföljer PowerThermalEventArgs. Dessa bör användas för att förstå händelsen.

När händelsen PowerThermalThermalScoreChanged utlöses kommer den på samma sätt med PowerThermalScoreArgs.

När en händelse tas emot bör händelsehanteraren inspektera args. ImpactedPeripherals, som identifierar vilken eller vilka kringutrustning som påverkas (det kan finnas fler än en).

För PowerThermalMitigationLevelChanged-händelser, args. MitigationLevel anger hur allvarlig riskreducering som rekommenderas för den angivna kringutrustningen. Om args. MitigationLevel är PowerThermalMitigationLevel.NoUserImpact . Då bör eventuella åtgärder som är associerade med den angivna kringutrustningen tas bort.

För PowerThermalThermalScoreChanged-händelser, args. ThermalScore anger en poäng från 100 till 0 som återspeglar en linjär skala som närmar sig en programavstängningshändelse (noll). Intervallet termisk poäng börjar utanför riskreduceringsrapporteringsintervallet för att tillåta tidigare meddelanden till programmet när behovet av åtgärder närmar sig.

Här är en exempelhanterare:

bool doCpuThrottle = false;

private void NotificationHandler(object sender, PowerThermalEventArgs args)
{
    if (args.ImpactedPeripherals.HasFlag(PowerThermalPeripheralFlags.Cpu))
    {
        if(args.MitigationLevel = PowerThermalMitigationLevel.NoUserImpact)
        {
            doCpuThrottle = false;
        }
        else if(args.MitigationLevel >= PowerThermalMitigationLevel.MinimumUserImpact)
        {
            // Note that this only kicks in at MinimumUserImpact and does not get released until NoUserImpact
            doCpuThrottle = true;
        }
    }

    if (args.ImpactedPeripherals.HasFlag(PowerThermalPeripheralFlags.PhotoVideoCamera))
    {
        SetMitigationStatus(PhotoVideoCameraStatusText, PhotoVideoRectangle, args.MitigationLevel);
    }
}

Anteckning

Parametern ImpactedPeripherals för args identifierar bara den kringutrustning som både påverkades och en del av PeripheralsOfInterest. Annan berörd kringutrustning som inte ingick i PeripheralsOfInterest identifieras inte.

Anteckning

Riskreduceringsnivåer för kringutrustning har hysteres. När nivån ökar minskar den inte förrän den släpps. Versionen är en händelse med args. MitigationLevel inställd på PowerThermalMitigationLevel.NoUserImpact.

Sätta ihop den (händelsebaserad modell)

Här är ett enkelt exempel på en uppsättning skript som kan användas i Unity för att aktivera den här funktionen. Klassen NotificationComponent kan läggas till i valfritt spelobjekt och det spelobjektet kan spåra riskreduceringsnivån för den tilldelade kringutrustningen. Klassen NotificationManager hanterar SDK:n som hanterar prenumerationer via den enskilda instansen av klassen PowerThermalNotification .

Här är klassen NotificationManager:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

using Microsoft.MixedReality.PowerThermalNotification;

public class NotificationManager
{
    private static readonly object listLock = new object();
    private static List<NotificationComponent> components = new List<NotificationComponent>();
    private static PowerThermalNotification p = PowerThermalNotification.GetForCurrentProcess();
    private static bool FirstTime = true;

    private static void NotificationHandler(object sender, PowerThermalEventArgs args)
    {
        lock (listLock)
        {
            foreach (NotificationComponent c in components)
            {
                UnityEngine.WSA.Application.InvokeOnAppThread(() =>
                {
                    c.SetMitigationLevel(args.ImpactedPeripherals, args.MitigationLevel);
                }, false);
            }
        } 
    }

    public static void ChangeSuppression(PowerThermalPeripheralFlags peripherals, bool suppress)
    {
        p.SuppressPlatformMitigation(peripherals, suppress);
    }

    public static void AddNotification(NotificationComponent component, PowerThermalPeripheralFlags peripheralsOfInterest)
    {
        if (FirstTime)
        {
            p.PowerThermalMitigationLevelChanged += NotificationHandler;
            FirstTime = false;
        }
        
        if (PowerThermalNotification.IsSupported(peripheralsOfInterest))
        {
            lock (listLock)
            {
                component.SetMitigationLevel(peripheralsOfInterest, (PowerThermalMitigationLevel)0);
                components.Add(component);
            }
            p.PeripheralsOfInterest |= peripheralsOfInterest;
        }
    }
}

Här är klassen NotificationComponent:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using Microsoft.MixedReality.PowerThermalNotification;

public class NotificationComponent : MonoBehaviour
{
    //Note that this could be multiple peripherals, just need to make sure to look at impactedPeripherals in the handler
    public PowerThermalPeripheralFlags monitoredPeripheral = (PowerThermalPeripheralFlags) 0;
    public bool isSuppressed = false;

    public void SetMitigationLevel(PowerThermalMitigationLevel level)
    {
        Color newColor = Color.white;

        if (level == PowerThermalMitigationLevel.NoUserImpact)
        {
            newColor = Color.green;
        }
        else if (level == PowerThermalMitigationLevel.MinimumUserImpact)
        {
            newColor = Color.yellow;
        }
        else if (level == PowerThermalMitigationLevel.MediumUserImpact)
        {
            newColor = new Color32(255, 127, 37, 255);//Orange
        }
        else
        {
            newColor = Color.red;
        }

        MaterialPropertyBlock props = new MaterialPropertyBlock();
        props.SetColor("_Color", newColor);
        GetComponent<Renderer>().SetPropertyBlock(props);
    }

    public void SetMitigationLevel(PowerThermalPeripheralFlags impactedPeripherals, PowerThermalMitigationLevel level)
    {
        if (impactedPeripherals.HasFlag(monitoredPeripheral))
        {
            SetMitigationLevel(level);
        }
    }

    void Start()
    {
        NotificationManager.AddNotification(this, monitoredPeripheral);
        NotificationManager.ChangeSuppression(monitoredPeripheral, isSuppressed);
    }

}

Avsökningsbaserad API-användning

Uppdatera kringutrustning av intresse

På samma sätt som med händelsebaserad användning krävs det att du anger egenskapen PeripheralsOfInterest för att avsöka en viss kringutrustning.

Varning

Om du försöker anropa GetLastPeripheralState för en viss kringutrustning utan att först ange flaggan i PeripheralsOfInterest genereras ett undantag. På samma sätt genereras ett undantag om du försöker använda GetLastPeripheralState med ett ogiltigt värde (flera angivna flaggbitar eller en bit som inte stöds).

Anropa avsöknings-API:erna

När PeripheralsOfInterest har de kringutrustningsbitar som du vill avsöka kan du anropa GetLastPeripheralState.

Den returnerade PowerThermalPeripheralState innehåller de senaste värdena för termisk poäng och riskreduceringsnivå för den angivna kringutrustningen.

Anteckning

Det är möjligt att vissa kringutrustningar kanske inte stöds i framtida plattformar. I dessa fall returnerar API:et termisk poäng på 100 och riskreduceringsnivån NoUserImpact. Programmet kan kontrollera isSupportedPeripheral-fältet i strukturen för att kontrollera om så är fallet för en viss kringutrustning.

Mer information om hantering av termisk poäng och MitigationLevel som returneras av PowerThermalPeripheralState finns i Hantera händelser.

Här är ett litet kodfragment som visar avsökning:

private async void timerCallback(object state)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        PowerThermalNotification p = PowerThermalNotification.GetForCurrentProcess();

        PowerThermalPeripheralState CpuState = p.GetLatestPeripheralState(PowerThermalPeripheralFlags.Cpu);
        PowerThermalPeripheralState PhotoVideoCameraState = p.GetLatestPeripheralState(PowerThermalPeripheralFlags.PhotoVideoCamera);
        
        CpuScoreText.Text = CpuState.ThermalScore.ToString();
        PhotoVideoScoreText.Text = PhotoVideoCameraState.ThermalScore.ToString();
    });
}

private void InitializeThermalNotifications()
{
    PowerThermalNotification p = PowerThermalNotification.GetForCurrentProcess();

    PowerThermalPeripheralFlags requestedFlags = PowerThermalPeripheralFlags.Cpu | PowerThermalPeripheralFlags.PhotoVideoCamera;
    p.SuppressedPlatformMitigationForPeripherals = requestedFlags;//Suppress any platform mitigation on CPU or PhotoVideoCamera

    if (PowerThermalNotification.IsSupported(requestedFlags))
    {
        p.PeripheralsOfInterest = requestedFlags;

        Timer timer = new Timer(timerCallback, null, 0, 3000);
    }
    else
    {
        TitleLabel.Text = "Not Supported";
    }
}

Förhindra systemminskningar som är standard

Om du inte vill att systemet ska försöka minimera viss kringutrustning kan du ignorera dem. Det gör du genom att uppdatera egenskapen SuppressedPlatformMitigationForPeripherals eller anropa funktionen SuppressPlatformMitigation .

Här är ett litet kodfragment:

PowerThermalNotification p = PowerThermalNotification.GetForCurrentProcess();
PowerThermalPeripheralFlags requestedFlags = PowerThermalPeripheralFlags.Cpu | PowerThermalPeripheralFlags.PhotoVideoCamera;

//You can do this to set the property explicitly
p.SuppressedPlatformMitigationForPeripherals = requestedFlags;

//Or you can do this to manipulate the property mask. 
//This specific example clears the CPU, leaving the PhotoVideoCamera suppressed
p.SuppressPlatformMitigation(PowerThermalPeripheralFlags.Cpu, false);

Anteckning

Undertrycknings-API:erna fungerar bara om processen som använder klassen PowerThermalNotification är i förgrunden. Bakgrundsprocesser kan fortfarande prenumerera på händelser men kan inte inaktivera HoloLens 2 åtgärder.

Testning

När du har integrerat SDK:et i ditt program bör du testa det. För HoloLens 2 operativsystem som stöder SDK finns en utvecklarsida i enhetsportalen. På den här sidan kan du styra riskreduceringsnivåer och termiska poäng för varje kringutrustning. Du kan också övervaka vilken kringutrustning som aktivt undertrycks.

Du kan också använda REST API:er för att övervaka/testa riskreduceringsnivåer och termiska poäng från en annan enhet. Mer information finns i API-referensen för enhetsportalen