Da Anwendungen, die RenderScript nutzen, immer noch innerhalb der Android-VM ausgeführt werden, haben Sie Zugriff auf alle Framework-APIs, mit denen Sie vertraut sind, gegebenenfalls RenderScript verwenden. Um diese Interaktion zwischen dem Framework und der RenderScript-Laufzeit, ist auch eine Zwischenschicht mit Code vorhanden. um die Kommunikation und Speicherverwaltung zwischen den beiden Codeebenen zu erleichtern. In diesem Dokument werden diese verschiedene Codeebenen und die gemeinsame Nutzung des Arbeitsspeichers durch die Android-VM und RenderScript-Laufzeit
RenderScript-Laufzeitebene
Ihr RenderScript-Code wurde kompiliert die in einer kompakten und klar definierten Laufzeitebene ausgeführt wird. Die RenderScript-Laufzeit-APIs bieten Unterstützung für rechenintensiven, portierbaren und automatisch skalierbaren Anzahl der auf einem Prozessor verfügbaren Kerne.
Hinweis:Die Standard-C-Funktionen im NDK müssen ausgeführt wird, sodass RenderScript nicht auf diese Bibliotheken zugreifen kann. da RenderScript auf verschiedenen Prozessortypen ausgeführt werden kann.
Sie definieren Ihren RenderScript-Code in .rs
und .rsh
im Verzeichnis src/
Ihres Android-Projekts. Der Code
von der Funktion in den Zwischen-Bytecode
Compiler llvm
, der als Teil eines Android-Builds ausgeführt wird. Wenn Ihre Anwendung
auf einem Gerät ausgeführt wird, wird der Bytecode dann (Just-in-Time) von einem anderen Gerät in Maschinencode kompiliert.
Compiler llvm
, der sich auf dem Gerät befindet. Der Maschinencode ist für den
Gerät und auch im Cache gespeichert, sodass spätere Nutzungen der RenderScript-fähigen Anwendung
den Bytecode neu zu kompilieren.
Zu den Hauptfunktionen der RenderScript-Laufzeitbibliotheken gehören:
- Funktionen für Anfragen zur Arbeitsspeicherzuweisung
- Große Sammlung mathematischer Funktionen mit überlasteten skalaren und vektortypisierten Versionen häufig vorkommenden Routinen. Operationen wie Addieren, Multiplizieren, Punktprodukt und Kreuzprodukt sowie atomare arithmetische und Vergleichsfunktionen.
- Konvertierungsroutinen für primitive Datentypen und Vektoren, Matrixroutinen sowie Datum und Uhrzeit Abläufe
- Datentypen und -strukturen zur Unterstützung des RenderScript-Systems wie Vektortypen für zwei-, drei- oder vier-Vektoren definieren.
- Logging-Funktionen
Weitere Informationen zu den verfügbaren Funktionen finden Sie in der Referenz zur RenderScript RunScript Runtime API.
Reflektierte Ebene
Die widergespiegelte Ebene besteht aus einer Reihe von Klassen, die von den Android-Build-Tools generiert werden, um den Zugriff zu ermöglichen zur RenderScript-Laufzeit aus dem Android-Framework. Diese Ebene bietet auch Methoden, und Konstruktoren, die es Ihnen ermöglichen, Zeiger, die in Ihren RenderScript-Code. In der folgenden Liste werden die wichtigsten Komponenten, die sich spiegeln:
- Jede von Ihnen erstellte
.rs
-Datei wird in einer Klasse namensproject_root/gen/package/name/ScriptC_renderscript_filename
von Geben SieScriptC
ein. Diese Datei ist die.java
-Version von.rs
-Datei, die Sie aus dem Android-Framework aufrufen können. Diese Klasse enthält die Die folgenden Elemente spiegeln sich in der Datei.rs
wider: <ph type="x-smartling-placeholder">- </ph>
- Nicht statische Funktionen
- Nicht statische, globale RenderScript-Variablen. Accessor
für jede Variable generiert, sodass Sie lesen und
die RenderScript-Variablen aus der Android-App
Framework. Wenn eine globale Variable bei der
RenderScript-Laufzeitebene, werden diese Werte für
Initialisieren der entsprechenden Werte im Android-Framework
Ebene. Wenn globale Variablen als
const
gekennzeichnet sind, ist dieset
-Methode nicht generiert. Hier ansehen . - Globale Zeiger
- Ein
struct
wird in einer eigenen Klasse namensproject_root/gen/package/name/ScriptField_struct_name
, die sich überScript.FieldBase
erstreckt. Diese Klasse stellt ein Array derstruct
, mit dem Sie einer oder mehreren Instanzen dieses Speichers Arbeitsspeicher zuweisen könnenstruct
Funktionen
Funktionen spiegeln sich in der Skriptklasse selbst wider,
project_root/gen/package/name/ScriptC_renderscript_filename
Für
Beispiel, wenn Sie die folgende Funktion in Ihrem RenderScript-Code definieren:
void touch(float x, float y, float pressure, int id) { if (id >= 10) { return; } touchPos[id].x = x; touchPos[id].y = y; touchPressure[id] = pressure; }
wird der folgende Java-Code generiert:
public void invoke_touch(float x, float y, float pressure, int id) { FieldPacker touch_fp = new FieldPacker(16); touch_fp.addF32(x); touch_fp.addF32(y); touch_fp.addF32(pressure); touch_fp.addI32(id); invoke(mExportFuncIdx_touch, touch_fp); }
Funktionen können keine Rückgabewerte aufweisen, da das RenderScript-System asynchron. Wenn Ihr Android-Framework-Code RenderScript aufruft, wird der Aufruf in die Warteschlange gestellt und durchgeführt werden. Durch diese Einschränkung kann das RenderScript-System ohne konstante und erhöht die Effizienz. Wenn Funktionen Rückgabewerte haben dürfen, wird der Aufruf bis der Wert zurückgegeben wird.
Wenn der RenderScript-Code einen Wert an das Android-Framework zurücksenden soll, verwenden Sie die Methode
rsSendToClient()
.
Variablen
Variablen der unterstützten Typen werden in der Skriptklasse selbst wiedergegeben. Sie finden sie im
project_root/gen/package/name/ScriptC_renderscript_filename
Eine Zugriffsfunktion
für jede Variable generiert. Wenn Sie beispielsweise die folgende Variable in
Ihrem RenderScript-Code:
uint32_t unsignedInteger = 1;
wird der folgende Java-Code generiert:
private long mExportVar_unsignedInteger; public void set_unsignedInteger(long v){ mExportVar_unsignedInteger = v; setVar(mExportVarIdx_unsignedInteger, v); } public long get_unsignedInteger(){ return mExportVar_unsignedInteger; }
Strukturen
Structs werden in ihren eigenen Klassen widergespiegelt, die sich
<project_root>/gen/com/example/renderscript/ScriptField_struct_name
Dieses
Klasse stellt ein Array von struct
dar und ermöglicht das Zuweisen von Arbeitsspeicher
angegebene Anzahl von struct
s Angenommen, Sie definieren die folgende Struktur:
typedef struct Point { float2 position; float size; } Point_t;
wird der folgende Code in ScriptField_Point.java
generiert:
package com.example.android.rs.hellocompute; import android.renderscript.*; import android.content.res.Resources; /** * @hide */ public class ScriptField_Point extends android.renderscript.Script.FieldBase { static public class Item { public static final int sizeof = 12; Float2 position; float size; Item() { position = new Float2(); } } private Item mItemArray[]; private FieldPacker mIOBuffer; public static Element createElement(RenderScript rs) { Element.Builder eb = new Element.Builder(rs); eb.add(Element.F32_2(rs), "position"); eb.add(Element.F32(rs), "size"); return eb.create(); } public ScriptField_Point(RenderScript rs, int count) { mItemArray = null; mIOBuffer = null; mElement = createElement(rs); init(rs, count); } public ScriptField_Point(RenderScript rs, int count, int usages) { mItemArray = null; mIOBuffer = null; mElement = createElement(rs); init(rs, count, usages); } private void copyToArray(Item i, int index) { if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */); mIOBuffer.reset(index * Item.sizeof); mIOBuffer.addF32(i.position); mIOBuffer.addF32(i.size); } public void set(Item i, int index, boolean copyNow) { if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */]; mItemArray[index] = i; if (copyNow) { copyToArray(i, index); mAllocation.setFromFieldPacker(index, mIOBuffer); } } public Item get(int index) { if (mItemArray == null) return null; return mItemArray[index]; } public void set_position(int index, Float2 v, boolean copyNow) { if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */); if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */]; if (mItemArray[index] == null) mItemArray[index] = new Item(); mItemArray[index].position = v; if (copyNow) { mIOBuffer.reset(index * Item.sizeof); mIOBuffer.addF32(v); FieldPacker fp = new FieldPacker(8); fp.addF32(v); mAllocation.setFromFieldPacker(index, 0, fp); } } public void set_size(int index, float v, boolean copyNow) { if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */); if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */]; if (mItemArray[index] == null) mItemArray[index] = new Item(); mItemArray[index].size = v; if (copyNow) { mIOBuffer.reset(index * Item.sizeof + 8); mIOBuffer.addF32(v); FieldPacker fp = new FieldPacker(4); fp.addF32(v); mAllocation.setFromFieldPacker(index, 1, fp); } } public Float2 get_position(int index) { if (mItemArray == null) return null; return mItemArray[index].position; } public float get_size(int index) { if (mItemArray == null) return 0; return mItemArray[index].size; } public void copyAll() { for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct); mAllocation.setFromFieldPacker(0, mIOBuffer); } public void resize(int newSize) { if (mItemArray != null) { int oldSize = mItemArray.length; int copySize = Math.min(oldSize, newSize); if (newSize == oldSize) return; Item ni[] = new Item[newSize]; System.arraycopy(mItemArray, 0, ni, 0, copySize); mItemArray = ni; } mAllocation.resize(newSize); if (mIOBuffer != null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */); } }
Der generierte Code wird Ihnen zur Verfügung gestellt, damit Sie Arbeitsspeicher für die angeforderten Structs zuweisen können.
durch die RenderScript-Laufzeit aus und interagieren mit struct
s.
im Gedächtnis gespeichert. In jeder struct
-Klasse werden die folgenden Methoden und Konstruktoren definiert:
- Überlastete Konstruktoren, mit denen Sie Arbeitsspeicher zuweisen können. Die
Der
ScriptField_struct_name(RenderScript rs, int count)
-Konstruktor ermöglicht definieren Sie die Anzahl der Strukturen, der Sie Arbeitsspeicher zuweisen möchten,count
-Parameter. DerScriptField_struct_name(RenderScript rs, int count, int usages)
-Konstruktor definiert den zusätzlichen Parameterusages
, der können Sie den Arbeitsspeicherbereich dieser Arbeitsspeicherzuweisung angeben. Es gibt vier Speicherbereiche, Möglichkeiten: <ph type="x-smartling-placeholder">- </ph>
USAGE_SCRIPT
: Weist dem Skriptspeicher zu Leerzeichen. Dies ist der Standardarbeitsspeicher, wenn Sie keinen Speicherplatz angeben.USAGE_GRAPHICS_TEXTURE
: Zuweisungen in der Texturarbeitsspeicher der GPU.USAGE_GRAPHICS_VERTEX
: Weist im Scheitelpunkt zu Arbeitsspeicher der GPU.USAGE_GRAPHICS_CONSTANTS
: Zuweisungen in der der von den verschiedenen Programmobjekten verwendet wird.
Mit dem bitweisen Operator
OR
können Sie mehrere Speicherbereiche angeben. Vorgehensweise benachrichtigt die RenderScript-Laufzeit, dass Sie auf die Daten im angegebenen Speicherbereichen. Im folgenden Beispiel wird Arbeitsspeicher für einen benutzerdefinierten Datentyp zugewiesen sowohl im Skript- als auch im Scheitelpunktspeicherbereich:Kotlin
val touchPoints: ScriptField_Point = ScriptField_Point( myRenderScript, 2, Allocation.USAGE_SCRIPT or Allocation.USAGE_GRAPHICS_VERTEX )
Java
ScriptField_Point touchPoints = new ScriptField_Point(myRenderScript, 2, Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_VERTEX);
- Mit der statischen verschachtelten Klasse
Item
können Sie eine Instanz derstruct
in Form eines Objekts. Diese verschachtelte Klasse ist nützlich, durch diestruct
in Ihrem Android-Code. Wenn Sie mit der Bearbeitung des Objekts fertig sind, können Sie das Objekt in den zugewiesenen Speicher übertragen, indem Sieset(Item i, int index, boolean copyNow)
aufrufen undItem
an die gewünschte Position im das Array. Die RenderScript-Laufzeit hat automatisch Zugriff auf den neu geschriebenen Arbeitsspeicher. - Zugriffsmethoden zum Abrufen und Festlegen der Werte der einzelnen Felder in einer Struktur. Jede dieser Optionen
Zugriffsmethode auf Methoden hat einen
index
-Parameter, um diestruct
in das Array, in das Sie schreiben oder lesen möchten. Jede Setter-Methode hat auch eincopyNow
-Parameter, der angibt, ob diese Erinnerung sofort synchronisiert werden soll in die RenderScript-Laufzeit ein. Um Erinnerungen zu synchronisieren, die nicht synchronisiert wurden, rufecopyAll()
- Die Methode
createElement()
erstellt eine Beschreibung der Struktur im Arbeitsspeicher. Dieses description wird verwendet, um Speicher zuzuweisen, der aus einem oder mehreren Elementen besteht. resize()
funktioniert ähnlich wie einrealloc()
in C, sodass Sie den zuvor zugewiesenen Speicher erweitern und die aktuellen Werte beibehalten, erstellt.copyAll()
synchronisiert den auf Framework-Ebene festgelegten Arbeitsspeicher mit dem RenderScript-Laufzeit Wenn Sie für ein Mitglied eine Zugriffsmethode festlegen, gibt es eine optionale Funktion. Boolescher ParametercopyNow
, den Sie angeben können. Angabetrue
synchronisiert den Arbeitsspeicher, wenn Sie die Methode aufrufen. Wenn Sie „false“ angeben, können SiecopyAll()
einmal aufrufen, um den Speicher für alle Eigenschaften, die noch nicht synchronisiert wurden.
Mauszeiger
Globale Verweise werden in der Skriptklasse selbst widergespiegelt, die sich im
project_root/gen/package/name/ScriptC_renderscript_filename
Ich
kann Zeiger auf ein struct
oder einen der unterstützten RenderScript-Typen deklarieren, aber ein
struct
darf keine Zeiger oder verschachtelten Arrays enthalten. Wenn Sie beispielsweise die
Folgende Verweise auf struct
und int32_t
typedef struct Point { float2 position; float size; } Point_t; Point_t *touchPoints; int32_t *intPointer;
wird der folgende Java-Code generiert:
private ScriptField_Point mExportVar_touchPoints; public void bind_touchPoints(ScriptField_Point v) { mExportVar_touchPoints = v; if (v == null) bindAllocation(null, mExportVarIdx_touchPoints); else bindAllocation(v.getAllocation(), mExportVarIdx_touchPoints); } public ScriptField_Point get_touchPoints() { return mExportVar_touchPoints; } private Allocation mExportVar_intPointer; public void bind_intPointer(Allocation v) { mExportVar_intPointer = v; if (v == null) bindAllocation(null, mExportVarIdx_intPointer); else bindAllocation(v, mExportVarIdx_intPointer); } public Allocation get_intPointer() { return mExportVar_intPointer; }
Eine get
-Methode und eine spezielle Methode namens bind_pointer_name
(anstelle einer set()
-Methode) generiert werden. Mit der Methode bind_pointer_name
können Sie den Arbeitsspeicher binden
das in der Android-VM der RenderScript-Laufzeit zugewiesen ist. Sie können
Arbeitsspeicher in der Datei .rs
). Weitere Informationen finden Sie unter Arbeiten
mit „Alised Memory“.
APIs zur Arbeitsspeicherzuweisung
Anwendungen, die RenderScript verwenden, werden weiterhin auf der Android-VM ausgeführt. Der eigentliche RenderScript-Code wird jedoch nativ ausgeführt und
benötigt Zugriff auf den Arbeitsspeicher, der in der Android-VM zugewiesen ist. Um dies zu erreichen, müssen Sie
Der Arbeitsspeicher, der in der VM zugewiesen ist,
wird der RenderScript-Laufzeit zugeordnet. Dieses
-Vorgang (Bindung) ermöglicht der RenderScript-Laufzeit, nahtlos mit dem Speicher zu arbeiten,
-Anfragen aber nicht explizit zuweisen. Das Endergebnis ist im Wesentlichen das gleiche,
mit dem Namen malloc
in C. Der zusätzliche Vorteil besteht darin, dass die Android-VM
die automatische Speicherbereinigung ausführen kann,
Arbeitsspeicher gemeinsam mit der RenderScript-Laufzeitebene nutzen. Das Binden ist nur für dynamisch zugewiesenen Arbeitsspeicher erforderlich. Statisch
Der zugewiesene Speicher wird für den RenderScript-Code bei der Kompilierung automatisch erstellt. Siehe Abbildung 1
finden Sie weitere Informationen
zur Speicherzuweisung.
Zur Unterstützung dieses Arbeitsspeicherzuweisungssystems gibt es eine Reihe von APIs, mit denen die Android-VM
Arbeitsspeicher zuweisen und bieten ähnliche Funktionen wie ein malloc
-Aufruf. Diese Kurse
beschreiben, wie der Arbeitsspeicher
zugewiesen werden sollte, und führen auch die Zuordnung durch. Damit Sie
wie diese Klassen funktionieren, ist es hilfreich, sie in Bezug
malloc
-Aufruf, der so aussehen kann:
array = (int *)malloc(sizeof(int)*10);
Der Aufruf malloc
kann in zwei Teile unterteilt werden: die Größe des zugewiesenen Arbeitsspeichers (sizeof(int)
),
sowie die Anzahl der Speichereinheiten, die zugewiesen werden sollen (10). Das Android-Framework stellt Klassen für diese beiden Teile
sowie eine Klasse, die malloc
selbst darstellt.
Die Klasse Element
stellt den Teil (sizeof(int)
) dar
des malloc
-Aufrufs und kapselt eine Zelle einer Arbeitsspeicherzuweisung, z. B. eine einzelne
Gleitkommawert oder eine Struktur. Die Klasse Type
kapselt das Element
und die Menge der zuzuweisenden Elemente (in unserem Beispiel 10). Sie können sich einen Type
als
Ein Array mit Element
-Werten. Die Klasse Allocation
übernimmt die
Arbeitsspeicherzuweisung basierend auf einem bestimmten Type
und stellt den tatsächlich zugewiesenen Arbeitsspeicher dar.
In den meisten Fällen müssen Sie diese APIs zur Arbeitsspeicherzuweisung nicht direkt aufrufen. Die reflektierte Schicht
Klassen generieren Code zur Verwendung dieser APIs. Zum Zuweisen von Arbeitsspeicher müssen Sie lediglich eine
-Konstruktor an, der in einer der Klassen für reflektierte Ebenen deklariert ist, und binden Sie
den resultierenden Allocation
-Speicher an das RenderScript.
Es gibt Situationen, in denen Sie diese Klassen direkt verwenden möchten, um Speicher
zum Beispiel das Laden einer Bitmap aus einer Ressource oder das Zuweisen von Arbeitsspeicher für Verweise auf
primitiven Typen. Eine Anleitung dazu finden Sie
Speicher dem RenderScript-Abschnitt zuweisen und ihn binden
In der folgenden Tabelle werden die drei Arbeitsspeicherverwaltungsklassen ausführlicher beschrieben:
Android-Objekttyp | Beschreibung |
---|---|
Element |
Ein Element beschreibt eine Zelle einer Arbeitsspeicherzuweisung und kann in zwei Formen auftreten: einfach oder komplex sind. Ein Basiselement enthält eine einzelne Datenkomponente eines beliebigen gültigen RenderScript-Datentyps.
Beispiele für grundlegende Elementdatentypen sind ein einzelner Komplexe Elemente enthalten eine Liste grundlegender Elemente und werden aus
|
Type |
Ein Typ ist eine Vorlage für die Arbeitsspeicherzuweisung und besteht aus einem Element und mindestens einem
Dimensionen. Sie beschreibt das Layout des Arbeitsspeichers (im Grunde ein Array von Ein Typ besteht aus fünf Dimensionen: X, Y, Z, Detailebene (Detailebene) und Flächen (eines Würfels). Karte). Sie können die Dimensionen X, Y und Z auf eine beliebige positive Ganzzahl innerhalb des des verfügbaren Arbeitsspeichers. Eine einzelne Dimensionszuweisung hat die x-Dimension größer als null sind, während die Dimensionen Y und Z null sind, um anzuzeigen, dass das Element nicht vorhanden ist. Für Beispiel: Eine Zuordnung von x=10, y=1 wird als zweidimensional angesehen, und x=10, y=0 ist als eindimensional betrachtet. Die Dimensionen „LOD“ und „Faces“ sind boolesche Werte zur Angabe, oder nicht vorhanden ist. |
Allocation |
Eine Zuordnung stellt den Arbeitsspeicher für Anwendungen basierend auf einer Beschreibung des Arbeitsspeichers bereit
der durch ein Zuordnungsdaten werden hauptsächlich auf zwei Arten hochgeladen: mit einem Häkchen und mit dem ohne Häkchen.
Für einfache Arrays gibt es |
Mit Memory arbeiten
Nicht statische, globale Variablen, die Sie in Ihrem RenderScript deklarieren, werden zum Zeitpunkt der Kompilierung zugewiesen.
Sie können diese Variablen direkt in Ihrem RenderScript-Code verwenden, ohne
auf der Ebene des Android-Frameworks. Auch die Android-Framework-Ebene hat Zugriff auf diese Variablen.
mit den bereitgestellten Zugriffsmethoden, die in den Klassen der reflektierten Ebenen generiert werden. Wenn diese Variablen
die auf der RenderScript-Laufzeitebene initialisiert wurden, werden diese Werte zur Initialisierung der entsprechenden
auf der Android-Framework-Ebene. Wenn globale Variablen als const gekennzeichnet sind, ist eine set
-Methode
nicht generiert. Weitere Informationen
Hinweis:Wenn Sie bestimmte RenderScript-Strukturen verwenden, die Verweise enthalten, z. B.
rs_program_fragment
und rs_allocation
müssen Sie ein Objekt des
entsprechenden Android-Framework-Klasse und rufen dann dafür die Methode set
auf.
-Struktur fest, um den Speicher an die RenderScript-Laufzeit zu binden. Sie können diese Strukturen nicht direkt bearbeiten
auf der RenderScript-Laufzeitebene. Diese Einschränkung gilt nicht für benutzerdefinierte Strukturen
die Zeiger enthalten, da diese nicht in eine Klasse für reflektierte Ebenen exportiert werden können
überhaupt erst. Ein Compiler-Fehler wird generiert, wenn Sie versuchen, eine nicht-statische, globale
Struktur, die einen Zeiger enthält.
RenderScript unterstützt auch Pointer, aber Sie müssen den Speicher explizit in Ihrem
Android-Framework-Code Wenn Sie einen globalen Zeiger in Ihrer .rs
-Datei deklarieren,
Ordnen Sie Arbeitsspeicher über die entsprechende reflektierte Schichtklasse zu und binden Sie diesen Speicher an die native
RenderScript-Ebene. Sie können über die Android-Framework-Ebene
mit diesem Memory interagieren
der RenderScript-Ebene, die Ihnen die Flexibilität bietet, Variablen so weit wie möglich
entsprechenden Layers.
Dynamischen Speicher dem RenderScript zuordnen und an ihn binden
Um dynamischen Arbeitsspeicher zuzuweisen, müssen Sie den Konstruktor eines
Script.FieldBase
, die gängigste Methode. Alternativ können Sie auch
Allocation
manuell. Dies ist z. B. für Zeiger primitiver Typen erforderlich. Sie sollten
Verwenden Sie der Einfachheit halber nach Möglichkeit einen Script.FieldBase
-Klassenkonstruktor.
Nachdem Sie eine Arbeitsspeicherzuweisung erhalten haben, rufen Sie die reflektierte bind
-Methode des Zeigers auf, um den zugewiesenen Speicher an den
RenderScript-Laufzeit
Im folgenden Beispiel wird Speicher sowohl
für einen primitiven Zeiger zugewiesen,
intPointer
und einem Zeiger auf die Struktur touchPoints
. Außerdem wird der Speicher mit dem
RenderScript:
Kotlin
private lateinit var myRenderScript: RenderScript private lateinit var script: ScriptC_example private lateinit var resources: Resources public fun init(rs: RenderScript, res: Resources) { myRenderScript = rs resources = res // allocate memory for the struct pointer, calling the constructor val touchPoints = ScriptField_Point(myRenderScript, 2) // Create an element manually and allocate memory for the int pointer val intPointer: Allocation = Allocation.createSized(myRenderScript, Element.I32(myRenderScript), 2) // create an instance of the RenderScript, pointing it to the bytecode resource script = ScriptC_point(myRenderScript/*, resources, R.raw.example*/) // bind the struct and int pointers to the RenderScript script.bind_touchPoints(touchPoints) script.bind_intPointer(intPointer) ... }
Java
private RenderScript myRenderScript; private ScriptC_example script; private Resources resources; public void init(RenderScript rs, Resources res) { myRenderScript = rs; resources = res; // allocate memory for the struct pointer, calling the constructor ScriptField_Point touchPoints = new ScriptField_Point(myRenderScript, 2); // Create an element manually and allocate memory for the int pointer intPointer = Allocation.createSized(myRenderScript, Element.I32(myRenderScript), 2); // create an instance of the RenderScript, pointing it to the bytecode resource script = new ScriptC_example(myRenderScript, resources, R.raw.example); // bind the struct and int pointers to the RenderScript script.bind_touchPoints(touchPoints); script.bind_intPointer(intPointer); ... }
Lesen und Schreiben in den Arbeitsspeicher
Sie können in der RenderScript-Laufzeit statisch und dynamisch zugewiesenen Speicher lesen und schreiben. und Android-Framework-Ebene.
Statisch zugewiesener Arbeitsspeicher unterliegt einer Einwegkommunikationseinschränkung
auf der RenderScript-Laufzeitebene. Wenn der RenderScript-Code den Wert einer Variablen ändert, ist dies
zur Steigerung der Effizienz an die Android-Framework-Ebene zurückgesendet. Der letzte Wert
die vom Android-Framework festgelegt wird, wird bei einem Aufruf von get
immer zurückgegeben.
. Wenn jedoch der Android-Framework-Code eine Variable ändert, kann diese Änderung
die RenderScript-Laufzeit automatisch
oder zu einem späteren Zeitpunkt synchronisiert. Wenn Sie Daten senden müssen
von der RenderScript-Laufzeit zur Android-Framework-Ebene übertragen, können Sie die Methode
rsSendToClient()
-Funktion
diese Begrenzung zu überwinden.
Bei der Arbeit mit dynamisch zugewiesenem Arbeitsspeicher werden alle Änderungen an der RenderScript-Laufzeitebene weitergegeben zurück zur Android-Framework-Ebene, wenn Sie die Arbeitsspeicherzuweisung mithilfe des zugehörigen Zeigers geändert haben. Wird ein Objekt auf der Android-Framework-Ebene geändert, wird diese Änderung sofort in das RenderScript-Format übernommen. Laufzeitebene.
Globale Variablen lesen und schreiben
Das Lesen und Schreiben von globalen Variablen ist ein einfacher Vorgang. Sie können die Zugriffsmethoden auf Android-Framework-Ebene ausführen oder sie direkt im RenderScript-Code festlegen. Denken Sie daran, dass alle Änderungen am RenderScript-Code werden nicht übernommen. zurück zur Android-Framework-Ebene, Hier finden Sie weitere Informationen. .
Beispiel: Bei der folgenden Struktur, die in einer Datei mit dem Namen rsfile.rs
deklariert wurde:
typedef struct Point { int x; int y; } Point_t; Point_t point;
Du kannst der Struktur direkt in rsfile.rs
Werte zuweisen. Diese Werte sind nicht
auf die Android-Framework-Ebene übergeben:
point.x = 1; point.y = 1;
Sie können der Struktur auf der Ebene des Android-Frameworks auf folgende Weise Werte zuweisen. Diese Werte sind asynchron an die RenderScript-Laufzeitebene zurückgegeben:
Kotlin
val script: ScriptC_rsfile = ... ... script._point = ScriptField_Point.Item().apply { x = 1 y = 1 }
Java
ScriptC_rsfile script; ... Item i = new ScriptField_Point.Item(); i.x = 1; i.y = 1; script.set_point(i);
Sie können die Werte in Ihrem RenderScript-Code wie folgt lesen:
rsDebug("Printing out a Point", point.x, point.y);
Mit dem folgenden Code können Sie die Werte in der Android-Framework-Ebene lesen. Beachten Sie, dass dies Code gibt nur dann einen Wert zurück, wenn einer auf Android-Framework-Ebene festgelegt wurde. Sie erhalten einen Nullzeiger, Ausnahme, wenn Sie den Wert nur auf der RenderScript-Laufzeitebene festlegen:
Kotlin
Log.i("TAGNAME", "Printing out a Point: ${mScript._point.x} ${mScript._point.y}") println("${point.x} ${point.y}")
Java
Log.i("TAGNAME", "Printing out a Point: " + script.get_point().x + " " + script.get_point().y); System.out.println(point.get_x() + " " + point.get_y());
Globale Hinweise lesen und schreiben
Unter der Annahme, dass Arbeitsspeicher auf Android-Framework-Ebene zugewiesen und an die RenderScript-Laufzeit gebunden ist,
Sie können Arbeitsspeicher auf Android-Framework-Ebene mit den Methoden get
und set
für diesen Zeiger lesen und schreiben.
Auf der RenderScript-Laufzeitebene können Sie wie gewohnt mit Zeigern lesen und schreiben und die Änderungen werden übernommen.
im Gegensatz zum statisch zugewiesenen Speicher zurück in die
Android-Framework-Ebene.
Im folgenden Beispiel wird auf eine struct
in einer Datei namens rsfile.rs
verwiesen:
typedef struct Point { int x; int y; } Point_t; Point_t *point;
Wenn Sie bereits Arbeitsspeicher auf Android-Framework-Ebene zugewiesen haben, können Sie auf Werte in
struct
wie gewohnt. Alle Änderungen, die Sie über die Zeigervariable der Struktur vornehmen
sind automatisch für die Android-Framework-Ebene verfügbar:
Kotlin
point[index].apply { x = 1 y = 1 }
Java
point[index].x = 1; point[index].y = 1;
Sie können auch Werte auf der Android-Framework-Ebene lesen und schreiben:
Kotlin
val i = ScriptField_Point.Item().apply { x = 100 y = 100 } val p = ScriptField_Point(rs, 1).apply { set(i, 0, true) } script.bind_point(p) p.get_x(0) //read x and y from index 0 p.get_y(0)
Java
ScriptField_Point p = new ScriptField_Point(rs, 1); Item i = new ScriptField_Point.Item(); i.x=100; i.y = 100; p.set(i, 0, true); script.bind_point(p); p.get_x(0); //read x and y from index 0 p.get_y(0);
Sobald der Arbeitsspeicher bereits gebunden ist, müssen Sie den Arbeitsspeicher nicht noch einmal an das RenderScript-Objekt binden. Laufzeit, wenn Sie einen Wert ändern.