Le applicazioni che utilizzano RenderScript continuano a essere eseguite all'interno della VM Android, hai accesso a tutte le API del framework che conosci, ma che utilizzare RenderScript quando opportuno. Per facilitare questa interazione tra il framework e il runtime RenderScript, anche un livello intermedio di codice è presenti per facilitare la comunicazione e la gestione della memoria tra i due livelli di codice. Questo documento approfondisce questi diversi livelli di codice, nonché le modalità di condivisione della memoria tra la VM Android Runtime RenderScript.
Livello di runtime di RenderScript
Il codice RenderScript è compilato e eseguito in un livello di runtime compatto e ben definito. Le API di runtime RenderScript offrono supporto per ad alta intensità di calcolo, portabile e automaticamente scalabile di core disponibili su un processore.
Nota: le funzioni C standard nell'NDK devono essere l'esecuzione su una CPU è garantita, perciò RenderScript non può accedere a queste librerie, poiché RenderScript è progettato per essere eseguito su diversi tipi di processori.
Definisci il tuo codice RenderScript in .rs
e .rsh
nella directory src/
del tuo progetto Android. Il codice
è compilato in bytecode intermedio
Compilatore llvm
che viene eseguito come parte di una build Android. Quando la tua applicazione
viene eseguito su un dispositivo, il bytecode viene quindi compilato (just-in-time) nel codice macchina da un altro
Compilatore llvm
che risiede sul dispositivo. Il codice macchina è ottimizzato
dispositivo e anche memorizzati nella cache, quindi gli utilizzi successivi dell'applicazione abilitata per RenderScript
ricompilare il bytecode.
Alcune funzionalità chiave delle librerie di runtime di RenderScript includono:
- Funzionalità di richiesta di allocazione della memoria
- Un'ampia raccolta di funzioni matematiche con versioni sovraccaricate sia scalare che vettoriale. di molte routine comuni. Operazioni come l'aggiunta, la moltiplicazione, il prodotto scalare e il prodotto incrociato nonché le funzioni di aritmetica atomica e di confronto.
- Routine di conversione per tipi e vettori di dati primitivi, routine matriciali e data e ora routine
- Tipi di dati e strutture per supportare il sistema RenderScript come i tipi Vector per definire due, tre o quattro vettori.
- Funzioni di logging
Per ulteriori informazioni sulle funzioni disponibili, consulta il riferimento dell'API runtime RenderScript.
Strato riflesso
Il livello riflesso è un insieme di classi generate dagli strumenti di build Android per consentire l'accesso al runtime RenderScript dal framework Android. Questo livello fornisce anche che consentono di allocare e lavorare con la memoria per i puntatori definiti il tuo codice RenderScript. Nell'elenco che segue vengono descritti i principali componenti che si riflettono:
- Ogni file
.rs
che crei viene generato in una classe denominataproject_root/gen/package/name/ScriptC_renderscript_filename
di digitaScriptC
. Questo file è la versione.java
del tuo.rs
, che puoi richiamare dal framework Android. Questo corso contiene seguenti elementi riportati dal file.rs
:- Funzioni non statiche
- Variabili RenderScript globali non statiche. Funzione di accesso
vengono generati per ogni variabile, in modo che tu possa leggere
scrivere le variabili RenderScript dall'interfaccia
il modello di machine learning. Se una variabile globale viene inizializzata
RenderScript, questi valori vengono utilizzati per
inizializzare i valori corrispondenti nel framework Android
livello di sicurezza. Se le variabili globali sono contrassegnate come
const
, un metodoset
non è generati. Guarda qui per ulteriori informazioni. - Cursori globali
- Un
struct
si riflette nella propria classe denominataproject_root/gen/package/name/ScriptField_struct_name
, che estendeScript.FieldBase
. Questa classe rappresenta un arraystruct
, che consente di allocare memoria per una o più istanze di questostruct
.
Funzioni
Le funzioni si riflettono nella classe script stessa, situata in
project_root/gen/package/name/ScriptC_renderscript_filename
. Per
esempio, se definisci la funzione seguente nel codice RenderScript:
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; }
viene generato il seguente codice Java:
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); }
Le funzioni non possono avere valori restituiti perché il sistema RenderScript è progettato per asincrone. Quando il codice del framework Android chiama a RenderScript, la chiamata viene accodata e viene quando è possibile. Questa restrizione consente al sistema RenderScript di funzionare senza e aumenta l'efficienza. Se alle funzioni è consentito avere valori restituiti, la chiamata viene bloccato finché non viene restituito il valore.
Se desideri che il codice RenderScript invii un valore al framework Android, utilizza la classe
rsSendToClient()
personalizzata.
Variabili
Le variabili dei tipi supportati si riflettono nella classe script stessa, situata in
project_root/gen/package/name/ScriptC_renderscript_filename
. Un insieme di funzioni di accesso
vengono generati per ogni variabile. Ad esempio, se definisci la seguente variabile in
il codice RenderScript:
uint32_t unsignedInteger = 1;
viene generato il seguente codice Java:
private long mExportVar_unsignedInteger; public void set_unsignedInteger(long v){ mExportVar_unsignedInteger = v; setVar(mExportVarIdx_unsignedInteger, v); } public long get_unsignedInteger(){ return mExportVar_unsignedInteger; }
Structs
Gli struct si riflettono nelle proprie classi, che si trovano in
<project_root>/gen/com/example/renderscript/ScriptField_struct_name
. Questo
rappresenta un array di struct
e consente di allocare memoria per
il numero specificato di struct
s. Ad esempio, se definisci il seguente struct:
typedef struct Point { float2 position; float size; } Point_t;
in ScriptField_Point.java
viene generato il seguente codice:
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 */); } }
Il codice generato ti viene fornito per comodità di allocare la memoria per gli struct richiesti
dal runtime RenderScript e di interagire con i struct
in memoria. Ogni classe di struct
definisce i seguenti metodi e costruttori:
- Costruttori sovraccarichi che consentono di allocare la memoria. La
Il costruttore
ScriptField_struct_name(RenderScript rs, int count)
consente definire il numero di strutture per le quali allocare la memoria concount
. Il costruttoreScriptField_struct_name(RenderScript rs, int count, int usages)
definisce un parametro aggiuntivo,usages
, che consente di specificare lo spazio di memoria dell'allocazione. Lo spazio di memoria è quattro possibili:USAGE_SCRIPT
: alloca nella memoria dello script spazio. Questo è lo spazio di memoria predefinito se non specifichi uno spazio di memoria.USAGE_GRAPHICS_TEXTURE
: alloca nell'area spazio di memoria della texture della GPU.USAGE_GRAPHICS_VERTEX
: l'allocazione nel vertice di memoria della GPU.USAGE_GRAPHICS_CONSTANTS
: alloca nell'area spazio di memoria costante della GPU utilizzato dai vari oggetti del programma.
Puoi specificare più spazi di memoria utilizzando l'operatore
OR
bit a bit. In questo modo comunica al runtime RenderScript che intendi accedere ai dati in spazi di memoria specificati. L'esempio seguente alloca la memoria per un tipo di dati personalizzato nello script e negli spazi di memoria Vertex: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);
- Una classe nidificata statica,
Item
, ti consente di creare un'istanza delstruct
, sotto forma di oggetto. Questa classe nidificata è utile se ha più senso funzionare con ilstruct
nel tuo codice Android. Quando hai finito di manipolare l'oggetto, puoi eseguire il push dell'oggetto nella memoria allocata chiamandoset(Item i, int index, boolean copyNow)
e impostandoItem
sulla posizione desiderata in l'array. Il runtime RenderScript ha automaticamente accesso alla memoria appena scritta. - Metodi della funzione di accesso per recuperare e impostare i valori di ciascun campo in uno struct. Ciascuno di questi
metodi della funzione di accesso hanno un parametro
index
per specificarestruct
in l'array su cui si vuole leggere o scrivere. Ogni metodo di impostazione ha anche ParametrocopyNow
che specifica se sincronizzare immediatamente questa memoria al runtime RenderScript. Per sincronizzare qualsiasi informazione che non è stata sincronizzata, chiamacopyAll()
. - Il metodo
createElement()
crea una descrizione dello struct in memoria. Questo descrizione viene utilizzata per allocare una memoria composta da uno o più elementi. - Il formato
resize()
funziona in modo molto simile arealloc()
in C, permettendoti di espandere la memoria allocata in precedenza, mantenendo i valori attuali che erano in precedenza è stato creato. copyAll()
sincronizza la memoria impostata a livello di framework con la Runtime RenderScript. Quando chiami un metodo della funzione di accesso impostato su un membro, è disponibile una classe facoltativacopyNow
parametro booleano che puoi specificare. Specificaretrue
sincronizza la memoria quando chiami il metodo. Se specifichi false, puoi chiamarecopyAll()
una volta e sincronizza la memoria per tutti che non sono ancora state sincronizzate.
Puntatori
I puntatori globali si riflettono nella classe dello script stessa, situata in
project_root/gen/package/name/ScriptC_renderscript_filename
. Tu
può dichiarare i puntatori a un struct
o a uno qualsiasi dei tipi di RenderScript supportati, ma
struct
non può contenere puntatori o array nidificati. Ad esempio, se definisci
seguire i puntatori a struct
e int32_t
typedef struct Point { float2 position; float size; } Point_t; Point_t *touchPoints; int32_t *intPointer;
viene generato il seguente codice Java:
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; }
Un metodo get
e un metodo speciale denominato bind_pointer_name
(anziché un metodo set()
). Il metodo bind_pointer_name
ti consente di associare la memoria
allocato nella VM Android al runtime RenderScript (non puoi allocare
memoria nel file .rs
). Per ulteriori informazioni, vedi Utilizzo
con la memoria allocata.
API di allocazione della memoria
Le applicazioni che utilizzano RenderScript continuano a essere eseguite nella VM Android. L'effettivo codice RenderScript, tuttavia, viene eseguito in modo nativo
deve accedere alla memoria allocata nella VM Android. A questo scopo, devi
collegare la memoria allocata nella VM al runtime di RenderScript. Questo
di processo, detto associazione, consente al runtime RenderScript di lavorare senza problemi con la memoria
ma non possono allocare esplicitamente. Il risultato finale è essenzialmente lo stesso che avresti ottenuto
chiamata malloc
in Do. Il vantaggio aggiuntivo è che la VM Android può eseguire la garbage collection,
con il livello di runtime RenderScript. L'associazione è necessaria solo per la memoria allocata dinamicamente. In modo statico
la memoria allocata viene creata automaticamente per il codice RenderScript al momento della compilazione. Vedi la Figura 1
per ulteriori informazioni sull'allocazione della memoria.
Per supportare questo sistema di allocazione della memoria, è disponibile una serie di API che consentono alla VM Android di
allocano memoria e offrono funzionalità simili a quelle di una chiamata malloc
. Questi corsi
descrivono essenzialmente come allocare la memoria e anche eseguire l'allocazione. Per migliorare
capire come funzionano queste classi, è utile considerarli in relazione a una
malloc
chiamata che può avere il seguente aspetto:
array = (int *)malloc(sizeof(int)*10);
La chiamata malloc
può essere suddivisa in due parti: la dimensione della memoria allocata (sizeof(int)
),
insieme al numero di unità di quella memoria da allocare (10). Il framework di Android fornisce classi per queste due parti,
e una classe che rappresenta malloc
stesso.
La classe Element
rappresenta la parte (sizeof(int)
)
della chiamata malloc
e incapsula una cella di un'allocazione di memoria, come un
in un valore in virgola mobile o in uno struct. La classe Type
racchiude il Element
e il numero di elementi da allocare (10 nel nostro esempio). Puoi considerare Type
come
un array di Element
. La classe Allocation
esegue effettivamente
all'allocazione della memoria in base a un determinato Type
e rappresenta la memoria allocata effettiva.
Nella maggior parte dei casi, non è necessario chiamare direttamente queste API di allocazione della memoria. Il livello riflesso
generano il codice per utilizzare automaticamente queste API. Per allocare la memoria basta chiamare
dichiarato in una delle classi di strati riflessi e poi vincolare
la memoria risultante Allocation
al RenderScript.
In alcune situazioni potrebbe essere utile utilizzare direttamente queste classi per allocare la memoria sul
come il caricamento di una bitmap da una risorsa o quando si desidera allocare memoria per i puntatori a
tipi primitivi. Puoi scoprire come farlo nel
Allocazione e associazione della memoria alla sezione RenderScript.
Nella tabella seguente vengono descritte in modo più dettagliato le tre classi di gestione della memoria:
Tipo di oggetto Android | Descrizione |
---|---|
Element |
Un elemento descrive una cella di allocazione di memoria e può avere due forme: di base o complessi. Un elemento di base contiene un singolo componente dei dati di qualsiasi tipo di dati RenderScript valido.
Esempi di tipi di dati degli elementi di base includono un singolo valore Gli elementi complessi contengono un elenco di elementi di base e vengono creati
|
Type |
Un tipo è un modello di allocazione della memoria ed è composto da un elemento e da uno o più
dimensioni. Descrive il layout della memoria (praticamente un array di Un tipo è costituito da cinque dimensioni: X, Y, Z, livello di dettaglio (livello di dettaglio) e Volti (di un cubo). mappa). Puoi impostare le dimensioni X,Y,Z su qualsiasi valore intero positivo all'interno dei i vincoli della memoria disponibile. L'allocazione a dimensione singola ha una dimensione X di maggiore di zero, mentre le dimensioni Y e Z sono pari a zero per indicare che non è presente. Per Ad esempio, un'allocazione di x=10, y=1 è considerata bidimensionale e x=10, y=0 è sono considerati monodimensionali. Le dimensioni LOD e Volti sono booleani per indicare la presenza di o meno. |
Allocation |
Un'allocazione fornisce la memoria per le applicazioni in base a una descrizione della memoria
rappresentato da un I dati di allocazione vengono caricati in uno dei due modi principali: tipo selezionato e tipo deselezionato.
Per gli array semplici, ci sono funzioni |
Utilizzo della memoria
Le variabili globali non statiche dichiarate in RenderScript sono memoria allocata al momento della compilazione.
Puoi lavorare con queste variabili direttamente nel codice RenderScript senza dover allocare
a livello di framework Android. Anche il livello del framework Android ha accesso a queste variabili
con i metodi della funzione di accesso forniti che vengono generati nelle classi degli strati riflessi. Se queste variabili sono
inizializzati al livello di runtime di RenderScript, tali valori vengono utilizzati per inizializzare i corrispondenti
nel livello framework Android. Se le variabili globali sono contrassegnate come const, viene utilizzato un metodo set
non generati. Per ulteriori dettagli, fai clic qui.
Nota: se utilizzi determinate strutture di RenderScript che contengono puntatori, come
rs_program_fragment
e rs_allocation
, devi ottenere un oggetto
la classe framework Android corrispondente, quindi chiama il metodo set
.
per associare la memoria al runtime di RenderScript. Non puoi manipolare direttamente queste strutture
a livello di runtime di RenderScript. Questa limitazione non è applicabile alle strutture definite dall'utente
che contengono puntatori, perché non possono essere esportati in una classe di livello riflessa
in primo luogo. Se tenti di dichiarare un ambiente globale non statico, viene generato un errore del compilatore
che contiene un puntatore.
Anche RenderScript supporta i puntatori, ma devi allocare esplicitamente la memoria nel tuo
Codice framework Android. Quando dichiari un puntatore globale nel file .rs
,
alloca la memoria tramite l'appropriata classe di strato riflessa e associala
il livello RenderScript. Puoi interagire con questa memoria dal livello del framework Android, nonché
il livello RenderScript, che offre la flessibilità di modificare le variabili
livello appropriato.
Allocazione e associazione della memoria dinamica a RenderScript
Per allocare la memoria dinamica, devi chiamare il costruttore di un
Script.FieldBase
, che è il modo più comune. Un'alternativa è creare un
Allocation
manualmente, che è necessaria per elementi come i puntatori di tipo primitivi. Dovresti
Per semplicità, utilizza un costruttore di classe Script.FieldBase
, quando disponibile.
Dopo aver ottenuto un'allocazione della memoria, chiama il metodo bind
riflesso del puntatore per associare la memoria allocata alla
Runtime RenderScript.
L'esempio seguente alloca la memoria per un puntatore di tipo primitivo,
intPointer
e un puntatore a uno struct, touchPoints
. Inoltre, lega la memoria
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); ... }
Lettura e scrittura in memoria
Puoi leggere e scrivere su memoria allocata in modo statico e dinamico sia nel runtime di RenderScript e Android.
La memoria allocata in modo statico è fornita con una limitazione della comunicazione unidirezionale
a livello di runtime di RenderScript. Quando il codice RenderScript cambia il valore di una variabile,
al livello del framework Android a fini di efficienza. L'ultimo valore
impostato dal framework Android viene sempre restituito durante una chiamata a un get
. Tuttavia, quando il codice del framework Android modifica una variabile, tale modifica può essere comunicata a
il runtime di RenderScript automaticamente o sincronizzato in un secondo momento. Se devi inviare dati
dal runtime RenderScript al livello del framework Android, puoi utilizzare
Funzione rsSendToClient()
per superare questa limitazione.
Quando si lavora con memoria allocata dinamicamente, qualsiasi modifica al livello di runtime di RenderScript viene propagata al livello del framework Android se hai modificato l'allocazione della memoria utilizzando il puntatore associato. La modifica di un oggetto a livello del framework Android propaga immediatamente il cambiamento a RenderScript il livello di runtime.
Lettura e scrittura su variabili globali
La lettura e la scrittura nelle variabili globali è un processo semplice. Puoi usare i metodi della funzione di accesso a livello di framework Android o impostarle direttamente nel codice RenderScript. Tieni presente che ogni le modifiche apportate nel codice RenderScript non vengono propagate torna al livello framework Android (guarda qui per ulteriori informazioni).
Ad esempio, dato il seguente struct dichiarato in un file denominato rsfile.rs
:
typedef struct Point { int x; int y; } Point_t; Point_t point;
Puoi assegnare valori allo struct in questo modo direttamente in rsfile.rs
. Questi valori non sono
propagata di nuovo al livello del framework Android:
point.x = 1; point.y = 1;
Puoi assegnare valori allo struct a livello del framework Android in questo modo. Questi valori sono propagati di nuovo al livello di runtime di RenderScript in modo asincrono:
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);
Puoi leggere i valori nel codice RenderScript in questo modo:
rsDebug("Printing out a Point", point.x, point.y);
Puoi leggere i valori nel livello del framework Android con il seguente codice. Tieni presente che restituisce un valore solo se ne è stato impostato uno a livello di framework Android. Verrà visualizzato un puntatore nullo se imposti il valore solo al livello di runtime di RenderScript:
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());
Lettura e scrittura di cursori globali
Supponendo che la memoria sia stata allocata a livello del framework Android e legata al runtime di RenderScript,
puoi leggere e scrivere la memoria a livello di framework Android utilizzando i metodi get
e set
per il puntatore.
Nel livello di runtime di RenderScript, puoi leggere e scrivere nella memoria con i puntatori come di consueto e le modifiche vengono propagate
al livello del framework Android, a differenza della memoria allocata in modo statico.
Ad esempio, dato il seguente puntatore a un struct
in un file denominato rsfile.rs
:
typedef struct Point { int x; int y; } Point_t; Point_t *point;
Supponendo che tu abbia già allocato la memoria a livello del framework Android, puoi accedere ai valori in
struct
come di consueto. Qualsiasi modifica apportata allo struct mediante la variabile puntatore
sono automaticamente disponibili per il livello framework Android:
Kotlin
point[index].apply { x = 1 y = 1 }
Java
point[index].x = 1; point[index].y = 1;
Puoi leggere e scrivere valori sul puntatore anche a livello di framework Android:
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);
Quando la memoria è già associata, non è necessario associarla nuovamente a RenderScript ogni volta che modifichi un valore.