Eine Einführung in RenderScript

In diesem Leitfaden wird RenderScript eingeführt und erläutert, wie die systeminternen RenderScript-APIs in einer Xamarin.Android-Anwendung verwendet werden, die auf API-Ebene 17 oder höher ausgerichtet ist.

Überblick

RenderScript ist ein von Google erstelltes Programmierframework zum Verbessern der Leistung von Android-Anwendungen, die umfangreiche Rechenressourcen erfordern. Es handelt sich um eine leistungsstarke Low-Level-API, die auf C99 basiert. Da es sich um eine Low-Level-API handelt, die auf CPUs, GPUs oder DSPs ausgeführt wird, eignet sich RenderScript gut für Android-Apps, die möglicherweise eine der folgenden Aktionen ausführen müssen:

  • Grafiken
  • Bildverarbeitung
  • Verschlüsselung
  • Signalverarbeitung
  • Mathematische Routinen

RenderScript verwendet clang und kompiliert die Skripts in LLVM-Bytecode, der im APK gebündelt ist. Wenn die App zum ersten Mal ausgeführt wird, wird der LLVM-Bytecode für die Prozessoren auf dem Gerät in Computercode kompiliert. Diese Architektur ermöglicht einer Android-Anwendung, die Vorteile von Computercode auszunutzen, ohne dass die Entwickler ihn für jeden Prozessor auf dem Gerät selbst schreiben müssen.

Eine RenderScript-Routine umfasst zwei Komponenten:

  1. Die Renderscript-Laufzeit – Dies sind die systemeigenen APIs, die für die Ausführung des Renderscripts verantwortlich sind. Dies schließt alle RenderScripts ein, die für die Anwendung geschrieben wurden.

  2. Managed Wrapper from the Android Framework – Managed classes that allow an Android app to control and interact with the Renderscript runtime and scripts. Zusätzlich zu den vom Framework bereitgestellten Klassen zum Steuern der RenderScript-Runtime untersucht die Android-Toolkette den RenderScript-Quellcode und generiert verwaltete Wrapperklassen zur Verwendung durch die Android-Anwendung.

Das folgende Diagramm veranschaulicht, wie diese Komponenten miteinander in Beziehung stehen:

Diagram illustrating how the Android Framework interacts with the Renderscript Runtime

Es gibt drei wichtige Konzepte für die Verwendung von RenderScripts in einer Android-Anwendung:

  1. Ein Kontext – eine vom Android SDK bereitgestellte verwaltete API, die Ressourcen zu Renderscript zuordnet und der Android-App das Übergeben und Empfangen von Daten aus dem Renderscript ermöglicht.

  2. Ein Compute-Kernel – auch als Stammkernkern oder Kernel bezeichnet – dies ist eine Routine, die die Arbeit ausführt. Der Kernel ähnelt stark einer C-Funktion. Dabei handelt es sich um eine parallelisierbare Routine, die für alle Daten im zugeordneten Arbeitsspeicher ausgeführt wird.

  3. Zugewiesener Speicher – Daten werden über eine Zuordnung an und von einem Kernel übergeben. Ein Kernel kann über eine Eingabe- und/oder Ausgabezuordnung verfügen.

Der Android.Renderscripts-Namespace enthält die Klassen für die Interaktion mit der RenderScript-Runtime. Insbesondere die Renderscript-Klasse verwaltet den Lebenszyklus und die Ressourcen der RenderScript-Engine. Initialisieren muss die Android-App ein oder mehrere Android.Renderscripts.Allocation Objekte. Eine Zuordnung ist eine verwaltete API, die für die Zuordnung von Arbeitsspeicher, der von der Android-App und der RenderScript-Runtime gemeinsam genutzt wird, und den Zugriff darauf verantwortlich ist. In der Regel wird eine Zuordnung für die Eingabe erstellt, und optional wird eine andere Zuordnung erstellt, um die Ausgabe des Kernel zu speichern. Das RenderScript-Runtimemodul und die zugehörigen verwalteten Wrapperklassen verwalten den Zugriff auf den Arbeitsspeicher, der von den Zuordnungen belegt wird. Es ist nicht erforderlich, dass ein Android-App-Entwickler zusätzliche Aufgaben ausführt.

Eine Zuordnung enthält ein oder mehrere Android.Renderscripts.Elements. Elemente sind ein spezieller Typ, der Daten in jeder Zuordnung beschreibt. Die Elementtypen der Ausgabezuordnung müssen mit den Typen des Eingabeelements identisch sein. Bei der Ausführung durchläuft ein RenderScript alle Elemente in der Eingabezuordnung parallel und schreibt die Ergebnisse in die Ausgabezuordnung. Es gibt zwei Typen von Elementen:

  • einfacher Typ – Konzeptionell ist dies identisch mit einem C-Datentyp float oder einem char.

  • komplexer Typ – Dieser Typ ähnelt einem C struct.

Die RenderScript-Engine führt eine Runtimeüberprüfung durch, um sicherzustellen, dass die Elemente in den einzelnen Zuordnungen mit den für den Kernel erforderlichen Informationen kompatibel sind. Wenn der Datentyp der Elemente in der Zuordnung nicht mit dem Datentyp, der vom Kernel erwartet wird, identisch ist, wird eine Ausnahme ausgelöst.

Der Typ, der alle RenderScript-Kernel umschließt, ist ein Nachfolger der Android.Renderscripts.Script -Klasse. Die Script-Klasse wird verwendet, um Parameter für ein RenderScript festzulegen, die entsprechenden Allocations festzulegen und RenderScript auszuführen. Im Android SDK gibt es zwei Script-Unterklassen:

  • Android.Renderscripts.ScriptIntrinsic – Einige der gängigeren Renderscript-Aufgaben werden im Android SDK gebündelt und können von einer Unterklasse der ScriptIntrinsic-Klasse aufgerufen werden. Ein Entwickler muss keine zusätzlichen Schritte durchführen, um diese Skripts in seiner Anwendung zu verwenden, da sie bereits bereitgestellt wurden.

  • ScriptC_XXXXX – Auch als Benutzerskripts bezeichnet, sind dies Skripts, die von Entwicklern geschrieben und in der APK verpackt werden. Zum Zeitpunkt der Kompilierung generiert die Android-Toolkette verwaltete Wrapperklassen, mit denen die Skripts in der Android-App verwendet werden können. Der Name dieser generierten Klassen ist der Name der RenderScript-Datei mit dem Präfix ScriptC_. Das Schreiben und Einbinden von Benutzerskripts wird von Xamarin.Android nicht offiziell unterstützt und überschreitet den Rahmen dieses Handbuchs.

Von diesen beiden Typen wird nur StringIntrinsic von Xamarin.Android unterstützt. In diesem Handbuch wird erläutert, wie systeminterne Skripts in einer Xamarin.Android-Anwendung verwendet werden.

Anforderungen

Dieses Handbuch behandelt Xamarin.Android-Anwendungen, die auf API-Ebene 17 oder höher abzielen. Die Verwendung von Benutzerskripts wird in diesem Handbuch nicht behandelt.

Die Xamarin.Android V8-Unterstützungsbibliothek erledigt die Rückportierung der internen RenderScript-APIs für Apps, die auf ältere Versionen des Android SDK abzielen. Das Hinzufügen dieses Pakets zu einem Xamarin.Android-Projekt soll Apps, die auf ältere Versionen des Android SDK abzielen, die Nutzung systeminterner Skripts ermöglichen.

Verwenden von systeminternen RenderScripts in Xamarin.Android

Die systeminternen Skripts eignen sich hervorragend zum Durchführen intensiver Rechenaufgaben mit minimalem zusätzlichem Code. Sie wurden individuell angepasst, um auf einem großen Querschnitt von Geräten optimale Leistung zu ermöglichen. Es ist nicht ungewöhnlich, dass ein systeminternes Skript zehnmal schneller als verwalteter Code und 2-3 Mal nach einer benutzerdefinierten C-Implementierung ausgeführt wird. Viele typische Verarbeitungsszenarien werden durch die systeminternen Skripts abgedeckt. In dieser Liste der systeminternen Skripts werden die aktuellen Skripts in Xamarin.Android beschrieben:

Ausführliche Informationen zu den einzelnen systeminternen Skripts finden Sie in der API-Dokumentation.

Im Folgenden werden die grundlegenden Schritte zum Verwenden von RenderScript in einer Android-Anwendung beschrieben.

Erstellen eines Renderscript-Kontexts – Die RenderscriptKlasse ist ein verwalteter Wrapper um den Renderscript-Kontext und steuert initialisierung, Ressourcenverwaltung und sauber nach oben. Das RenderScript-Objekt wird mit der RenderScript.Create-Factorymethode erstellt, die einen Android-Kontext (z. B. eine Aktivität) als Parameter annimmt. Die folgende Codezeile veranschaulicht, wie der RenderScript-Kontext initialisiert wird:

Android.Renderscripts.RenderScript renderScript = RenderScript.Create(this);

Erstellen von Zuordnungen – Je nach systeminternen Skript kann es erforderlich sein, ein oder zwei Allocations zu erstellen. Der Android.Renderscripts.Allocation Die Klasse verfügt über mehrere Factorymethoden, um eine Zuordnung für eine systeminterne Instanziierung zu instanziieren. Als Beispiel wird im folgenden Codeausschnitt die Vorgehensweise zum Erstellen einer Zuordnung für Bitmaps veranschaulicht.

Android.Graphics.Bitmap originalBitmap;
Android.Renderscripts.Allocation inputAllocation = Allocation.CreateFromBitmap(renderScript,
                                                     originalBitmap,
                                                     Allocation.MipmapControl.MipmapFull,
                                                     AllocationUsage.Script);

Häufig muss eine Allocation erstellt werden, um die Ausgabedaten eines Skripts zu speichern. Der folgende Codeausschnitt zeigt, wie Sie das Allocation.CreateTyped-Hilfsprogramm verwenden, um eine zweite Allocation zu instanziieren, die den gleichen Typ wie das Original hat:

Android.Renderscripts.Allocation outputAllocation = Allocation.CreateTyped(renderScript, inputAllocation.Type);

Instanziieren Sie den Skriptwrapper – Jede der systeminternen Skriptwrapperklassen sollte Hilfsmethoden (in der Regel als ")" bezeichnet Createhaben, um ein Wrapperobjekt für dieses Skript zu instanziieren. Der folgende Codeausschnitt ist ein Beispiel für das Instanziieren eines ScriptIntrinsicBlur-Weichzeichnerobjekts. Die Element.U8_4-Hilfsprogrammmethode erstellt ein Element, das einen 4 Felder mit ganzzahligen 8-Bit-Werten ohne Vorzeichen enthaltenden Datentyp beschreibt, der zur Speicherung der Daten eines Bitmap-Objekts geeignet ist:

Android.Renderscripts.ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.Create(renderScript, Element.U8_4(renderScript));

Zuweisen von Zuordnungen, Festlegen von Parametern und Run Script – Die Script Klasse stellt eine ForEach Methode bereit, um das Renderscript tatsächlich auszuführen. Diese Methode durchläuft jedes Element in der Allocation, die die Eingabedaten speichert. In einigen Fällen kann es erforderlich sein, eine Allocation bereitzustellen, die die Ausgabe speichert. ForEach überschreibt den Inhalt der Ausgabezuordnung. Um mit den Codeausschnitten aus den vorherigen Schritten fortzufahren, wird in diesem Beispiel gezeigt, wie Sie eine Eingabezuordnung zuweisen, einen Parameter festlegen und schließlich das Skript ausführen (Kopieren der Ergebnisse in die Ausgabezuordnung):

blurScript.SetInput(inputAllocation);
blurScript.SetRadius(25);  // Set a pamaeter
blurScript.ForEach(outputAllocation);

Vielleicht möchten Sie das Rezept Blur an Image with Renderscript (Weichzeichnen eines Bilds mit Renderscript) ausprobieren. Es ist ein vollständiges Beispiel für die Verwendung eines systeminternen Skripts in Xamarin.Android.

Zusammenfassung

In diesem Handbuch wurde RenderScript eingeführt und erläutert, wie Sie es in einer Xamarin.Android-Anwendung verwenden. Es wurde kurz erläutert, was RenderScript ist, und wie es in einer Android-Anwendung funktioniert. Es wurden einige der Hauptkomponenten in RenderScript und der Unterschied zwischen Benutzerskripts und systeminternen Skripts beschrieben. Schließlich wurden in diesem Handbuch die Schritte zur Verwendung eines systeminternen Skripts in einer Xamarin.Android-Anwendung beschrieben.