Ponieważ aplikacje korzystające z metody RenderScript nadal działają w maszynie wirtualnej z Androidem, masz dostęp do wszystkich interfejsów API platformy, które znasz, ale możesz używać w razie potrzeby metody RenderScript. Aby ułatwić tę interakcję środowiska wykonawczego RenderScript i platformy RenderScript, warstwa pośrednia kodu to także w celu ułatwienia komunikacji i zarządzania pamięcią między dwoma poziomami kodu. W tym dokumencie znajdziesz więcej informacji na ten temat różne warstwy kodu oraz sposób współdzielenia pamięci między maszyną wirtualną z Androidem Środowisko wykonawcze RenderScript.
Warstwa środowiska wykonawczego RenderScript
Kod RenderScript jest skompilowany w kompaktowej i dobrze zdefiniowanej warstwie środowiska wykonawczego. Interfejsy API środowiska wykonawczego RenderScript obsługują przy użyciu zaawansowanych funkcji obliczeniowych, które można przenosić i skalować automatycznie liczby rdzeni dostępnych w procesorze.
Uwaga: standardowe funkcje C w NDK muszą być na procesorach, przez co skrypt RenderScript nie ma dostępu do tych bibliotek, bo kod RenderScript został zaprojektowany do działania na różnych typach procesorów.
Definiujesz kod RenderScript w .rs
i .rsh
w katalogu src/
projektu Android. Kod
jest skompilowany do pośredniego kodu bajtowego przez
Kompilator llvm
, który działa w ramach kompilacji Androida. Kiedy aplikacja
działa na urządzeniu, kod bajtowy jest następnie skompilowany (dokładnie we właściwym czasie) do kodu
kompilator llvm
zainstalowany na urządzeniu. Kod maszynowy jest zoptymalizowany pod kątem
urządzenia i pamięci podręcznej, więc późniejsze użycie aplikacji z włączoną obsługą RenderScriptu
ponownie skompilować kod bajtowy.
Najważniejsze funkcje bibliotek środowiska wykonawczego RenderScript to:
- Funkcje żądania alokacji pamięci
- Duży zbiór funkcji matematycznych z przeciążonymi wersjami skalarnymi i wektorowymi z wielu popularnych rutyn. Operacje takie jak dodawanie, mnożenie, iloczyn skalarny i iloczyn wektorowy jak również funkcje arytmetyczne i porównawcze.
- Procedury konwersji podstawowych typów danych i wektorów, rutyn macierzy oraz daty i godziny rutyny
- Typy i struktury danych obsługujące system RenderScript, takie jak typy wektorowe dwóch, trzech lub czterech wektorów.
- Funkcje logowania
Więcej informacji o dostępnych funkcjach znajdziesz w dokumentacji interfejsu API środowiska wykonawczego RenderScript.
Odbita warstwa
Odzwierciedlona warstwa to zbiór klas generowanych przez narzędzia do kompilacji na Androida, które umożliwiają dostęp do środowiska wykonawczego RenderScript ze platformy Androida. Ta warstwa zawiera też metody i konstruktory, które umożliwiają przydzielanie i pracę z pamięcią wskaźników zdefiniowanych w kod RenderScript. Poniższa lista opisuje główne takie komponenty, jak:
- Każdy utworzony przez Ciebie plik
.rs
zostanie wygenerowany w klasie o nazwieproject_root/gen/package/name/ScriptC_renderscript_filename
z wpiszScriptC
. Ten plik to wersja.java
Twojego pliku danych.rs
, który można wywołać z platformy Androida. Te zajęcia zawierają: następujące elementy z pliku.rs
:- Funkcje niestatyczne
- Niestatyczne, globalne zmienne RenderScript. akcesor
dla każdej zmiennej są generowane metody, dzięki czemu możesz odczytywać
zapisz zmienne RenderScript na urządzeniach z Androidem
platformy. Jeśli zmienna globalna zostanie zainicjowana w
w środowisku wykonawczym RenderScript, wartości te są wykorzystywane do
zainicjuj odpowiednie wartości w platformie Androida
warstwę. Jeśli zmienne globalne są oznaczone jako
const
, metodaset
nie jest . Zajrzyj tutaj . - Wskaźniki globalne
- Element
struct
jest odzwierciedlony w własnej klasie o nazwieproject_root/gen/package/name/ScriptField_struct_name
o długościScript.FieldBase
. Ta klasa reprezentuje tablicę funkcjistruct
, która umożliwia przydzielenie pamięci na 1 lub więcej instancji tej instancjistruct
Funkcje
Funkcje są odzwierciedlane w samej klasie skryptu znajdującej się w
project_root/gen/package/name/ScriptC_renderscript_filename
Dla:
na przykład jeśli zdefiniujesz następującą funkcję w kodzie 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; }
zostanie wygenerowany następujący kod 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); }
Funkcje nie mogą zwracać wartości, ponieważ system RenderScript został zaprojektowany tak, asynchroniczny. Gdy kod platformy Androida wywołuje skrypt RenderScript, wywołanie jest umieszczane w kolejce, gdy to możliwe. To ograniczenie umożliwia działanie systemu RenderScript bez wartości stałych i zwiększa wydajność. Jeśli funkcje mogą mieć zwracane wartości, wywołanie będzie blokowane do czasu zwrócenia wartości.
Jeśli chcesz, by kod RenderScript wysyłał wartość z powrotem do platformy Androida, użyj parametru
rsSendToClient()
.
Zmienne
Zmienne obsługiwanych typów są odzwierciedlane w samej klasie skryptu znajdującej się w
project_root/gen/package/name/ScriptC_renderscript_filename
Zbiór akcesorów
jest generowany dla każdej zmiennej. Jeśli na przykład zdefiniujesz tę zmienną w parametrze
Twój kod RenderScript:
uint32_t unsignedInteger = 1;
zostanie wygenerowany następujący kod 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; }
Struktura
Jednostki są odzwierciedlane w osobnych klasach, które znajdują się w
<project_root>/gen/com/example/renderscript/ScriptField_struct_name
Ten
klasa reprezentuje tablicę obiektu struct
i pozwala przydzielić pamięć dla
określoną liczbę struct
s. Jeśli na przykład zdefiniujesz taką strukturę:
typedef struct Point { float2 position; float size; } Point_t;
w ScriptField_Point.java
zostanie wygenerowany ten kod:
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 */); } }
Wygenerowany kod jest udostępniany, aby ułatwić Ci przydzielenie pamięci dla żądanych elementów struct
przez środowisko wykonawcze RenderScript i do interakcji z modułami struct
w pamięci. Każda klasa struct
definiuje te metody i konstruktory:
- Przeciążone konstruktory, które umożliwiają przydzielanie pamięci.
Zezwolenia konstruktora
ScriptField_struct_name(RenderScript rs, int count)
zdefiniować liczbę struktur, dla których chcesz przydzielić pamięć za pomocącount
. KonstruktorScriptField_struct_name(RenderScript rs, int count, int usages)
definiuje dodatkowy parametrusages
, który pozwala określić miejsce w ramach tego przydziału pamięci. Dostępne są 4 miejsce w pamięci możliwości:USAGE_SCRIPT
: przydziela w pamięci skryptu kosmosu. Jest to domyślne miejsce w pamięci, jeśli nie określisz miejsca w pamięci.USAGE_GRAPHICS_TEXTURE
: przydziela w w ramach procesora graficznego.USAGE_GRAPHICS_VERTEX
: przydziela w wierzchołku ilość miejsca w pamięci GPU.USAGE_GRAPHICS_CONSTANTS
: przydziela w stałe miejsce w pamięci GPU wykorzystywanej przez różne obiekty programu.
Możesz określić wiele obszarów w pamięci, używając operatora bitowego
OR
. Robię to powiadamia środowisko wykonawcze RenderScript, by uzyskać dostęp do danych w określone miejsca w pamięci. Ten przykład przydziela pamięć do niestandardowego typu danych w przestrzeniach pamięci skryptów i wierzchołków pamięci: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);
- Statyczna zagnieżdżona klasa (
Item
) umożliwia utworzenie instancjistruct
w formie obiektu. Ta zagnieżdżona klasa jest przydatna, jeśli warto pracowaćstruct
w kodzie Androida. Gdy skończysz manipulować obiektem, możesz przekazać obiekt do przydzielonej pamięci, wywołując funkcjęset(Item i, int index, boolean copyNow)
i ustawiającItem
w żądanej pozycji tablicę. Środowisko wykonawcze RenderScript automatycznie ma dostęp do nowo zapisanej pamięci. - Metody metody dostępu do pobierania i ustawiania wartości każdego pola w elemencie struct. Każda z tych opcji
metody akcesora mają parametr
index
określającystruct
w tablicę, w której chcesz odczytywać dane lub w niej zapisywać. Każda metoda ustawiająca ma również ParametrcopyNow
, który określa, czy należy natychmiast synchronizować tę pamięć do środowiska wykonawczego RenderScript. Aby zsynchronizować wspomnienie, które nie zostało zsynchronizowane, wywołajcopyAll()
- Metoda
createElement()
tworzy opis struktury w pamięci. Ten Opis służy do przydzielania pamięci składającej się z jednego lub wielu elementów. resize()
działa prawie jakrealloc()
w C, pozwalając rozszerzać wcześniej przydzieloną pamięć przy zachowaniu obecnych wartości Utworzono.copyAll()
synchronizuje pamięć ustawioną na poziomie platformy z Środowisko wykonawcze RenderScript. Gdy wywołujesz metodę ustawiania akcesora dla użytkownika, pojawia sięcopyNow
parametr logiczny, który możesz określić. Określanietrue
synchronizuje pamięć, gdy wywołujesz tę metodę. Jeśli wybierzesz wartość Fałsz, możesz wywołać funkcjęcopyAll()
raz, by zsynchronizować pamięć dla wszystkich właściwości, które nie są jeszcze zsynchronizowane.
Wskaźniki
Wskaźniki globalne są odzwierciedlane w samej klasie skryptu znajdującej się w
project_root/gen/package/name/ScriptC_renderscript_filename
Ty
może zadeklarować wskaźniki do struct
lub dowolnego z obsługiwanych typów RenderScriptu, ale
Pole struct
nie może zawierać wskaźników ani zagnieżdżonych tablic. Jeśli na przykład zdefiniujesz parametr
następujące wskaźniki do struct
i int32_t
typedef struct Point { float2 position; float size; } Point_t; Point_t *touchPoints; int32_t *intPointer;
zostanie wygenerowany następujący kod 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; }
Metoda get
i specjalna o nazwie bind_pointer_name
(zamiast metody set()
). Metoda bind_pointer_name
umożliwia powiązanie pamięci
która jest przydzielona w maszynie wirtualnej z Androidem do środowiska wykonawczego RenderScript (nie możesz przydzielić
pamięci w pliku .rs
). Więcej informacji znajdziesz w sekcji Praca
dzięki przydzielonej pamięci.
Interfejsy API alokacji pamięci
Aplikacje korzystające z metody RenderScript nadal będą działać w maszynie wirtualnej z Androidem. Rzeczywisty kod RenderScript działa natomiast natywnie,
potrzebuje dostępu do pamięci przydzielonej w maszynie wirtualnej z Androidem. W tym celu musisz
dołącza pamięć przydzieloną w maszynie wirtualnej do środowiska wykonawczego RenderScript. Ten
umożliwia środowisko wykonawcze RenderScript bezproblemowo współpracuje z pamięcią,
żądań, ale nie można ich jawnie przydzielać. Efekt końcowy jest taki sam, jak w przypadku
pod tytułem malloc
w języku C. Dodatkową zaletą jest to, że maszyna wirtualna z Androidem może uruchamiać czyszczenie pamięci, a także
współdzielą pamięć z warstwą środowiska wykonawczego RenderScript. Powiązanie jest konieczne tylko w przypadku pamięci alokowanej dynamicznie. Statycznie
przydzielona pamięć dla kodu RenderScript jest tworzona automatycznie podczas kompilacji. Zobacz Rysunek 1.
.
Do obsługi tego systemu przydzielania pamięci istnieje zestaw interfejsów API, które umożliwiają maszynie wirtualnej z Androidem
przydzielać pamięć i udostępniać funkcje podobne do wywołania malloc
. Te zajęcia
zasadniczo opisują sposób przydzielania pamięci i przeprowadzanie tego procesu. Na lepsze
zrozumieć, jak działają te zajęcia. Warto myśleć o nich w odniesieniu do prostego
malloc
może wyglądać tak:
array = (int *)malloc(sizeof(int)*10);
Wywołanie malloc
można podzielić na 2 części: rozmiar przydzielonej pamięci (sizeof(int)
),
oraz liczbę jednostek tej pamięci, które powinny zostać przydzielone (10). Platforma Androida udostępnia klasyfikacje dla tych 2 części:
oraz klasę reprezentującą samą malloc
.
Klasa Element
reprezentuje część (sizeof(int)
)
wywołania malloc
i zakrywa 1 komórkę przydziału pamięci, np.
wartość zmiennoprzecinkową lub typ elementu. Klasa Type
zawiera obiekt Element
.
oraz liczbę elementów do przydzielenia (w tym przykładzie 10). Możesz określić Type
jako
tablica Element
s. Klasa Allocation
wykonuje funkcję
alokacja pamięci na podstawie danej wartości Type
i reprezentuje rzeczywistą przydzieloną pamięć.
W większości przypadków nie trzeba bezpośrednio wywoływać tych interfejsów API alokacji pamięci. Odbita warstwa
klasy generują kod umożliwiający automatyczne korzystanie z tych interfejsów API, a aby przydzielić pamięć, wystarczy wywołać
konstruktora zadeklarowanego w jednej z odbitych klas warstwy, a następnie powiązać
wynikową pamięć Allocation
do RenderScriptu.
W niektórych sytuacjach warto używać tych zajęć bezpośrednio, aby przydzielać pamięć
własne, np. wczytywanie bitmapy z zasobu lub gdy chcesz przydzielić pamięć na potrzeby wskaźników
podstawowych typów. Aby to zrobić, zobacz
Przypisywanie i wiązanie pamięci do sekcji RenderScript.
W tej tabeli bardziej szczegółowo opisano 3 klasy zarządzania pamięcią:
Typ obiektu na Androidzie | Opis |
---|---|
Element |
Element opisuje jedną komórkę alokacji pamięci i może mieć 2 postacie: podstawowy lub złożone. Element podstawowy zawiera pojedynczy komponent danych dowolnego prawidłowego typu danych RenderScript.
Przykładami podstawowych typów danych elementów są pojedyncza wartość Elementy złożone zawierają listę podstawowych elementów i są tworzone na podstawie
|
Type |
Typ to szablon alokacji pamięci, który składa się z elementu oraz co najmniej jednego elementu
wymiarów. Opisuje układ pamięci (zasadniczo tablica Typ składa się z pięciu wymiarów: X, Y, Z, LOD (poziom szczegółowości) i ścianek (sześcianu). mapy). Wymiary X,Y,Z możesz ustawić na dowolną dodatnią liczbę całkowitą w parze klucz-wartość z ograniczeniami dostępnej pamięci. Przydział według jednego wymiaru ma wymiar X równy jest większa od 0, a wymiary Y i Z mają wartość 0, co wskazuje, że nie występuje. Dla: Na przykład przydział x=10, y=1 jest uważany za dwuwymiarowy, a x=10, y=0 to uznawane za jednowymiarowe. Wymiary LOD i Faces są wartościami logicznymi, które wskazują obecność lub brak obecności. |
Allocation |
Przydział udostępnia pamięć dla aplikacji na podstawie opisu pamięci
reprezentowany przez Dane alokacji są przesyłane na jeden z dwóch głównych sposobów: typ jest zaznaczony, a typ niezaznaczony.
W przypadku prostych tablic dostępne są funkcje |
Praca z pamięcią
Niestatyczne, globalne zmienne zadeklarowane w kodzie RenderScript to przydzielona pamięć podczas kompilacji.
Możesz z nich korzystać bezpośrednio w kodzie RenderScript bez konieczności przydzielania
pamięci na poziomie platformy Androida. Warstwa platformy Androida również ma dostęp do tych zmiennych.
z podanymi metodami akcesoriów, które są generowane w odbitych klasach warstwy. Jeśli te zmienne są
zainicjowanych w warstwie środowiska wykonawczego RenderScript, wartości te służą do inicjowania
w warstwie platformy Androida. Jeśli zmienne globalne są oznaczone jako stałe, metoda set
jest
nie wygenerowano. Więcej informacji znajdziesz tutaj.
Uwaga: jeśli używasz określonych struktur RenderScript zawierających wskaźniki, na przykład
rs_program_fragment
i rs_allocation
, musisz uzyskać obiekt
najpierw odpowiednią klasę platformy Androida, a następnie wywołaj dla niej metodę set
powiązać pamięć ze środowiskiem wykonawczym RenderScript. Nie możesz bezpośrednio manipulować tymi obiektami
w warstwie środowiska wykonawczego RenderScript. To ograniczenie nie dotyczy struktur zdefiniowanych przez użytkownika
które zawierają wskaźniki, ponieważ nie można ich wyeksportować do odzwierciedlonej klasy warstwy
po pierwsze. Jeśli spróbujesz zadeklarować niestatyczny, globalny błąd kompilatora
struct zawierającego wskaźnik.
RenderScript obsługuje też wskaźniki, ale musisz jawnie przydzielić pamięć w parametrze
Kod platformy Androida. Gdy zadeklarujesz w pliku .rs
wskaźnik globalny,
Przydziel pamięć za pomocą odpowiedniej odbitej klasy warstwy i powiąż ją z natywną
Warstwa RenderScript. Możesz korzystać z tej pamięci w warstwie platformy Androida, a także
warstwa RenderScript, która umożliwia modyfikowanie zmiennych
odpowiednią warstwę.
Przydzielanie i wiązanie pamięci dynamicznej do skryptu RenderScript
Aby przydzielić pamięć dynamiczną, musisz wywołać konstruktora
Script.FieldBase
, czyli najpopularniejszy sposób. Alternatywnym rozwiązaniem jest utworzenie
Allocation
ręcznie, co jest wymagane w przypadku takich elementów jak wskaźniki typu podstawowego. Zalecenia
dla uproszczenia używaj konstruktora klas Script.FieldBase
.
Po uzyskaniu przydziału pamięci wywołaj odzwierciedloną metodę bind
wskaźnika, aby powiązać przydzieloną pamięć z
Środowisko wykonawcze RenderScript.
Poniższy przykład przydziela pamięć zarówno dla wskaźnika typu podstawowego,
intPointer
i wskaźnik do struktury (struct) touchPoints
. Wiąże również pamięć z
Skrypt renderowania:
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); ... }
Czytanie i zapisywanie w pamięci
Możesz odczytywać oraz zapisywać statycznie i dynamicznie alokowaną pamięć zarówno w środowisku wykonawczym RenderScript, jak i w pamięci alokowanej dynamicznie. i warstwy platformy Androida.
Statycznie przydzielona pamięć podlega ograniczeniom komunikacji jednokierunkowej
na poziomie środowiska wykonawczego RenderScript. Gdy kod RenderScript zmienia wartość zmiennej, nie zmienia się ona
przekazywane z powrotem do warstwy platformy Androida w celu zwiększenia wydajności. Ostatnia wartość
ustawiona na platformie Android jest zawsze zwracana podczas wywołania funkcji get
.
. Jeśli jednak kod platformy Androida modyfikuje zmienną, można o tym poinformować
w środowisku wykonawczym RenderScript lub na później. Jeśli chcesz wysłać dane
od środowiska wykonawczego RenderScript po warstwę platformy Androida, możesz użyć funkcji
Funkcja rsSendToClient()
do przezwyciężenia.
Podczas pracy z dynamicznie alokowaną pamięcią wszelkie zmiany w warstwie środowiska wykonawczego RenderScript są rozpowszechniane z powrotem do warstwy platformy Androida, jeśli przydział pamięci został zmodyfikowany za pomocą powiązanego z nią wskaźnika. Zmodyfikowanie obiektu w warstwie platformy Androida powoduje natychmiastowe propagowanie tej zmiany z powrotem do skryptu RenderScript warstwa środowiska wykonawczego.
Odczyt i zapis zmiennych globalnych
Odczyt i zapis zmiennych globalnych to prosty proces. Możesz używać metod akcesora na poziomie platformy Androida lub ustawić je bezpośrednio w kodzie RenderScript. Pamiętaj, że wszystkie zmiany wprowadzone w kodzie RenderScript nie są rozpowszechniane powrót do warstwy platformy Androida (kliknij tutaj) ).
Na przykład przy tej strukturze zadeklarowanej w pliku o nazwie rsfile.rs
:
typedef struct Point { int x; int y; } Point_t; Point_t point;
Możesz przypisać wartości do tego typu struktury bezpośrednio w rsfile.rs
. Te wartości nie są
i rozpowszechniane z powrotem na poziom platformy Androida:
point.x = 1; point.y = 1;
Możesz w ten sposób przypisać wartości do struktury w warstwie platformy Androida. Wartości te są przekazywane z powrotem do środowiska wykonawczego RenderScript asynchronicznie:
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);
Wartości w kodzie RenderScript możesz odczytać w ten sposób:
rsDebug("Printing out a Point", point.x, point.y);
Wartości możesz odczytać w warstwie platformy Androida za pomocą poniższego kodu. Pamiętaj, że ten krok kod zwraca wartość tylko wtedy, gdy została ona ustawiona na poziomie platformy Androida. Otrzymasz wskaźnik o wartości null wyjątkiem, jeśli ustawisz wartość tylko na poziomie środowiska wykonawczego 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());
Odczytywanie i zapisywanie wskaźników globalnych
Zakładając, że pamięć została przydzielona na poziomie platformy Androida i powiązana ze środowiskiem wykonawczym RenderScript,
możesz odczytywać i zapisywać pamięć na poziomie platformy Androida przy użyciu metod get
i set
dla tego wskaźnika.
W warstwie środowiska wykonawczego RenderScript możesz w zwykły sposób odczytywać i zapisywać w pamięci za pomocą wskaźników, a zmiany są rozpowszechniane.
do warstwy platformy Androida – w przeciwieństwie do pamięci przydzielonej statycznie.
Na przykład ten wskaźnik do pola struct
w pliku o nazwie rsfile.rs
:
typedef struct Point { int x; int y; } Point_t; Point_t *point;
Zakładając, że pamięć została już przydzielona w warstwie platformy Androida, możesz uzyskać dostęp do wartości w
struct
. Wszelkie zmiany wprowadzone w strukturze za pomocą jej zmiennej wskaźnika
są automatycznie dostępne w warstwie platformy Androida:
Kotlin
point[index].apply { x = 1 y = 1 }
Java
point[index].x = 1; point[index].y = 1;
Wartości wskaźnika możesz odczytywać i zapisywać również w warstwie platformy Androida:
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);
Gdy pamięć będzie już powiązana, nie musisz ponownie tworzyć jej dla kodu RenderScript w czasie działania po każdej zmianie wartości.