Gelişmiş RenderScript

RenderScript'i kullanan uygulamalar hâlâ Android sanal makinesi içinde çalıştığından, aşina olduğunuz tüm çerçeve API'lerine erişebilirsiniz ancak ve uygun durumlarda RenderScript'i kullanmalısınız. Proje yöneticileri arasındaki bu etkileşimi kolaylaştırmak çerçeveyi ve RenderScript çalışma zamanını, ara kod katmanını da iki kod düzeyi arasındaki iletişimi ve bellek yönetimini kolaylaştırmak için kullanılır. Bu belgede, bu riskler hakkında ve belleğin Android sanal makinesi ile Android sanal makinesi arasında nasıl RenderScript çalışma zamanı.

RenderScript Çalışma Zamanı Katmanı

RenderScript kodunuz derlenir ve iyi tanımlanmış bir çalışma zamanı katmanında yürütülmesini sağlar. RenderScript çalışma zamanı API'leri, yoğun hesaplama imkanı sunar. mevcut çekirdek sayısını ifade eder.

Not: NDK'daki standart C işlevleri CPU üzerinde çalışacağı garanti edildiği için RenderScript bu kitaplıklara erişemez. çünkü RenderScript farklı işlemci türlerinde çalışacak şekilde tasarlanmıştır.

RenderScript kodunuzu .rs içinde tanımlarsınız ve Android projenizin src/ dizininde .rsh dosya yer alıyor. Kod tarafından ara bayt koduna Android derlemesinin parçası olarak çalışan llvm derleyici. Uygulamanız çalıştırıldığında, bayt kodu başka bir cihaz tarafından makine koduna derlenir (tam zamanında) Cihazda bulunan llvm derleyicisi. Makine kodu, varsayılan olarak hem de önbelleğe alınmış bir uygulamadır. Böylece, RenderScript kullanan uygulamanın sonraki kullanımlarında bayt kodunu yeniden derleyin.

RenderScript çalışma zamanı kitaplıklarının bazı temel özellikleri şunlardır:

  • Bellek ayırma isteği özellikleri
  • Hem skaler hem de vektör türünde aşırı yüklenmiş sürümlere sahip büyük bir matematik fonksiyonları koleksiyonu vazgeçilmez bir parçasıdır. Toplama, çarpma, nokta çarpımı ve çapraz çarpım gibi işlemler atomik aritmetik ve karşılaştırma fonksiyonlarının yanı sıra mevcuttur.
  • Temel veri türleri ve vektörler, matris rutinleri ile tarih ve saat için dönüşüm rutinleri rutinler
  • RenderScript sistemini destekleyecek veri türleri ve yapıları (örneğin, iki, üç veya dört vektörü tanımladık.
  • İşlevleri günlüğe kaydetme

Kullanılabilir işlevler hakkında daha fazla bilgi için RenderScript çalışma zamanı API'si referansına bakın.

Yansıtılan Katman

Yansıtılan katman, Android derleme araçlarının erişime izin vermek için oluşturduğu sınıf kümesidir Android çerçevesinden RenderScript çalışma zamanına geçireceğiz. Bu katman aynı zamanda, ve oluşturucuları kullanarak, burada tanımlanan işaretçiler için bellek ayırmanıza ve bu bellekle çalışmanıza olanak bir kod snippet'i ekleyin. Aşağıdaki listede en önemli yansıtılan bileşenler:

  • Oluşturduğunuz her .rs dosyası, project_root/gen/package/name/ScriptC_renderscript_filename / ScriptC yazın. Bu dosya, .java .rs dosyası oluşturun. Bu dosyayı Android çerçevesinden çağırabilirsiniz. Bu sınıf şunu içeriyor: .rs dosyasından yansıtılan şu öğeler:
    • Statik olmayan işlevler
    • Statik olmayan, genel RenderScript değişkenleri. Erişen yöntem oluşturulur. Böylece, bu verileri okuyabilir ve Android'deki RenderScript değişkenlerini bahsedeceğim. Bir genel değişken RenderScript çalışma zamanı katmanında, bu değerler kullanılarak Android çerçevesinde karşılık gelen değerleri başlat katmanıdır. Genel değişkenler const olarak işaretlenirse set yöntemi elde edilir. Buraya bakın inceleyebilirsiniz.

    • Global işaretçiler
  • Bir struct, adlı kendi sınıfına yansıtılır project_root/gen/package/name/ScriptField_struct_name, Script.FieldBase uzatılır. Bu sınıf, struct, bu değer, bu öğenin bir veya daha fazla örneği için bellek ayırmanızı sağlar struct

Fonksiyonlar

İşlevler komut dosyası sınıfının kendisine yansıtılır: project_root/gen/package/name/ScriptC_renderscript_filename Örneğin, Örneğin, RenderScript kodunuzda aşağıdaki işlevi tanımlarsanız:

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;
}

aşağıdaki Java kodu oluşturulur:

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);
}

RenderScript sistemi şunu kullanacak şekilde tasarlandığından, işlevlerin döndürülen değerleri olamaz: eşzamansız. Android çerçeve kodunuz RenderScript'i çağırdığında, çağrı sıraya alınır ve yürütmelerini de sağlar. Bu kısıtlama, RenderScript sisteminin sabit değer olmadan çalışmasına olanak sağlar kesintilere neden olur ve verimliliği artırır. İşlevlerin değer döndürmesine izin verildiyse çağrı olması için değer döndürülene kadar engellenir.

RenderScript kodunun Android çerçevesine geri bir değer göndermesini isterseniz rsSendToClient() işlevini kullanın.

Değişkenler

Desteklenen türlerin değişkenleri, project_root/gen/package/name/ScriptC_renderscript_filename Erişimci grubu yöntem oluşturulur. Örneğin, aşağıdaki değişkeni RenderScript kodunuz:

uint32_t unsignedInteger = 1;

aşağıdaki Java kodu oluşturulur:

private long mExportVar_unsignedInteger;
public void set_unsignedInteger(long v){
    mExportVar_unsignedInteger = v;
    setVar(mExportVarIdx_unsignedInteger, v);
}

public long get_unsignedInteger(){
    return mExportVar_unsignedInteger;
}
  

Yapılar

Yapılar kendi sınıflarına yansıtılır: <project_root>/gen/com/example/renderscript/ScriptField_struct_name Bu class, bir struct dizisini temsil eder ve bir öğe için bellek ayırmanıza belirtilen sayıda struct. Örneğin, aşağıdaki struct'ı tanımlarsanız:

typedef struct Point {
    float2 position;
    float size;
} Point_t;

aşağıdaki kod ScriptField_Point.java içinde oluşturulur:

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 */);
    }
}

Oluşturulan kod, istenen struct'lar için bellek tahsisi sağlamak amacıyla size sağlanır ve structs ile etkileşim kurmak için RenderScript çalışma zamanına göre inceleyebilirsiniz. Her struct sınıfı, aşağıdaki yöntemleri ve oluşturucuları tanımlar:

  • Bellek ayırmanızı sağlayan aşırı yüklenmiş oluşturucular. İlgili içeriği oluşturmak için kullanılan ScriptField_struct_name(RenderScript rs, int count) oluşturucu kullanarak bellek ayırmak istediğiniz yapıların sayısını count parametresinden yararlanın. ScriptField_struct_name(RenderScript rs, int count, int usages) oluşturucusu, ek bir parametre (usages) tanımlar. bu bellek ayırmanın bellek alanını belirtmenizi sağlar. Dört bellek alanı vardır olanaklar:

    Bit tabanlı OR operatörünü kullanarak birden fazla bellek alanı belirtebilirsiniz. İşlem devam ediyor içindeki verilere erişmeyi düşündüğünüz RenderScript çalışma zamanını bildirir. belirtilen bellek alanları. Aşağıdaki örnek, özel bir veri türü için bellek ayırıyor hem komut dosyası hem de tepe noktası bellek alanlarında kullanabilirsiniz:

    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);
    
  • İç içe yerleştirilmiş statik bir sınıf (Item), struct, bir nesne biçimindedir. İç içe yerleştirilmiş bu sınıf, çalışmak daha mantıklı olduğunda kullanışlıdır. Android kodunuzdaki struct ile. Nesneyi değiştirmeyi tamamladığınızda, set(Item i, int index, boolean copyNow) öğesini çağırıp Item öğesini gösterir. RenderScript çalışma zamanı, yeni yazılan belleğe otomatik olarak erişir.
  • Bir struct'taki her alanın değerlerini almak ve ayarlamak için kullanılan erişimci yöntemleri. Bunların her biri erişimci yöntemlerinde struct belirtmek için bir index parametresi bulunur diziyi seçebilirsiniz. Her belirleme yöntemi aynı zamanda Bu belleğin hemen senkronize edilip edilmeyeceğini belirten copyNow parametresi gönderir. Senkronize edilmemiş herhangi bir hafızayı senkronize etmek için şu numarayı arayın: copyAll()
  • createElement() yöntemi, bellekteki struct'ın bir açıklamasını oluşturur. Bu açıklama, bir veya daha fazla öğeden oluşan belleği ayırmak için kullanılır.
  • resize(), C dilindeki realloc() işlevine çok benzer. önceki değerleri koruyarak önceden ayrılmış belleği genişlet oluşturuldu.
  • copyAll(), çerçeve düzeyinde ayarlanan belleği RenderScript çalışma zamanı. Bir üyede ayarlanan erişimci yöntemini çağırırken isteğe bağlı bir Belirtebileceğiniz copyNow boole parametresi. Belirtme true, yöntemi çağırdığınızda belleği senkronize eder. Yanlış değerini belirtirseniz copyAll() öğesini bir kez çağırabilirsiniz. Bu çağrı, tüm özellikleri olabilir.

İşaretçiler

Genel işaretçiler, buradaki komut dosyası sınıfının kendisine yansıtılır: project_root/gen/package/name/ScriptC_renderscript_filename Siz bir struct veya desteklenen RenderScript türlerinden herhangi birine işaretçiler tanımlayabilir, ancak struct, işaretçiler veya iç içe yerleştirilmiş diziler içeremez. Örneğin, aşağıdaki işaretçileri struct ve int32_t

typedef struct Point {
    float2 position;
    float size;
} Point_t;

Point_t *touchPoints;
int32_t *intPointer;

aşağıdaki Java kodu oluşturulur:

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;
}
  

Bir get yöntemi ve bind_pointer_name adlı özel bir yöntem (set() yöntemi yerine) oluşturulur. bind_pointer_name yöntemi, belleği bağlamanızı sağlar RenderScript çalışma zamanına ayrılmış ( hafızaya (.rs dosyanız) ekleyin. Daha fazla bilgi için bkz. Çalışmalar içe aktarılmalıdır.

Bellek Ayırma API'leri

RenderScript kullanan uygulamalar yine Android sanal makinesinde çalışır. Ancak gerçek RenderScript kodu yerel olarak çalışır ve Android sanal makinesinde ayrılan belleğe erişmesi gerekir. Bunu başarmak için şunları yapmanız gerekir: sanal makinede ayrılan belleği RenderScript çalışma zamanına ekler. Bu işlemi, RenderScript çalışma zamanının mevcut bellekle sorunsuz bir şekilde ancak açıkça tahsis edilemez. Nihai sonuç, daha önce C dilinde malloc olarak adlandırıldı. Ek avantaj, Android sanal makinesinin hem atık toplama hem de ilgili bellekten yararlanılabilir. Bağlama işlemi yalnızca dinamik olarak ayrılmış bellek için gereklidir. Statik olarak oluşturulan bellek derleme sırasında RenderScript kodunuz için otomatik olarak oluşturulur. Bkz. Şekil 1 bakın.

Bu bellek ayırma sistemini desteklemek için Android sanal makinesinin şunları yapmasına olanak tanıyan bir dizi API vardır: Belleği ayırabilir ve malloc çağrısına benzer işlevler sunabilir. Bu sınıflar belleğin nasıl ayrılması gerektiğini açıklar ve ayırma yapar. Daha iyi nasıl çalıştığını anlamak için bu sınıfları, basit bir model yerine malloc çağrısı şöyle görünebilir:

array = (int *)malloc(sizeof(int)*10);

malloc çağrısı iki bölüme ayrılabilir: Ayrılan belleğin boyutu (sizeof(int)), ve o belleğin kaç birimin ayrılması gerektiğini (10) gösterir. Android çerçevesi bu iki bölüm için aşağıdaki sınıfları sağlar: ve malloc kendisini temsil edecek bir sınıf içerir.

Element sınıfı, (sizeof(int)) bölümünü temsil eder. malloc çağrısının örneğidir ve bellek ayırmanın bir hücresini (örneğin, tek bir kayan noktalı değer veya struct. Type sınıfı Element etiketini kapsar ve ayrılacak öğe miktarı (örneğimizde 10). Type kavramını Element dizisidir. Allocation sınıfı şunları yapar: belirli bir Type öğesine göre bellek tahsisi ve ayrılan gerçek belleği temsil eder.

Çoğu durumda bu bellek ayırma API'lerini doğrudan çağırmanız gerekmez. Yansıtılan katman sınıfları, bu API'leri otomatik olarak kullanmak için kod oluşturur. Bellek tahsis etmek için tek yapmanız gereken, yansıtılan katman sınıflarından birinde bildirilen ve ardından bağlayan kurucu oluşturulan belleği RenderScript'e Allocation. Bazı durumlarda, doğrudan depolama alanınızda bellek tahsisi için bu sınıfları mesela bir kaynaktan bit eşlem yüklediğinizde veya işaretçiler için temel türler. Bunu nasıl yapacağınızı RenderScript'e bellek ayırma ve bağlama bölümü. Aşağıdaki tabloda üç bellek yönetimi sınıfı daha ayrıntılı olarak açıklanmaktadır:

Android Nesne Türü Açıklama
Element

Bir öğe, bellek ayırmadaki bir hücreyi tanımlar ve iki biçimde olabilir: temel veya karmaşıktır.

Temel öğe, herhangi bir geçerli RenderScript veri türünün tek bir veri bileşenini içerir. Temel öğe veri türlerine örnek olarak tek bir float değeri, float4 vektörü veya tek RGB-565 rengi.

Karmaşık öğeler, temel öğelerin bir listesini içerir ve aşağıdakilerden oluşturulur struct öğeleri. Örneğin, projenin bellekte sıralı olarak birden fazla struct içerebilir. Her struct, öğesini kullanın.

Type

Tür, bir bellek ayırma şablonudur ve bir öğe ile bir veya daha fazla öğeden oluşur seçin. Belleğin düzenini (temel olarak Element sn. dizisi) açıklar ancak bellekteki veriler için ayırmaz. anlatacağım.

Bir tür, beş boyuttan oluşur: X, Y, Z, LOD (ayrıntı seviyesi) ve Yüzler (bir küpün) haritası). X,Y,Z boyutlarını kısıtlanabilir. Tek boyut ayırmanın X boyutu şudur: değeri sıfırdan büyük, Y ve Z boyutları ise sıfır olarak ayarlanır. Örneğin, Örneğin, x=10, y=1 ayırması iki boyutlu olarak kabul edilir ve x=10, y=0 ise tek boyutlu kabul edilir. LOD ve Yüzler boyutları, mevcut olduğunu gösteren boole değerleridir olup olmadığını kontrol edin.

Allocation

Ayırma, belleğin açıklamasına göre uygulamalar için bellek sağlar Type ile temsil edilir. Ayrılan bellek şurada bulunabilir: aynı anda çok sayıda bellek alanından yararlanabilirsiniz. Bir alanda bellek değiştirilirse belleği senkronize ederek, bulunduğu diğer tüm alanlarda güncellenmesini sağlar.

Ayırma verileri iki temel yöntemden biriyle yüklenir: Tür işaretli ve tür işareti kaldırıldı. Basit diziler içincopyFrom() oluşturup yerel katman bellek deposuna kopyalayın. İşaretlenmemiş varyantlar desteklemediği için Android sisteminin yapı dizilerini kopyalamasına birlikte çalışır. Örneğin, n kayan noktalı bir ayırma varsa veriler float[n] dizisi veya byte[n*4] dizisinde bulunan veriler kopyalanabilir.

Bellek ile Çalışma

RenderScript'inizde bildirdiğiniz statik olmayan, genel değişkenlere derleme sırasında bellek ayrılır. Bu değişkenlerle herhangi bir ayırma işlemi yapmanıza gerek kalmadan doğrudan RenderScript kodunuzda çalışabilirsiniz. Android çerçevesi düzeyinde yapabilirsiniz. Android çerçeve katmanı da bu değişkenlere erişebilir işlemini, yansıtılan katman sınıflarında oluşturulan sağlanan erişimci yöntemleriyle değiştirin. Bu değişkenler ilk kullanıma sunulduğunda bu değerler, ilgili komut dosyasını değerlerini daha iyi anlatacağım. Genel değişkenler const olarak işaretlenirse set yöntemi oluşturulmadı. Daha fazla bilgi için buraya bakın.

Not: Örneğin, rs_program_fragment ve rs_allocation için öğenin bir nesnesini edinmeniz Bunun için önce karşılık gelen Android çerçeve sınıfını, ardından set yöntemini çağırın gereken temel yapıyı kullandığınızdan emin olun. Bu yapılara doğrudan müdahale edemezsiniz iki kat daha fazla belirlenebilir. Bu kısıtlama, kullanıcı tanımlı yapılar için geçerli değildir içeren bir katmandır. Çünkü bunlar, yansıtılan bir katman sınıfına aktarılamaz en başta sunun. Statik olmayan, global bir kod bildirmeye çalışırsanız derleyici hatası oluşur. struct'ı içerir.

RenderScript'in işaretçiler de desteği vardır ancak işaretleyiciyi Android çerçeve kodu. .rs dosyanızda global işaretçi bildirdiğinizde yansıtılan uygun katman sınıfı aracılığıyla belleği ayırmak ve belleği RenderScript katmanını kullanın. Bu bellekle Android çerçeve katmanından ve RenderScript katmanını kullanarak, değişkenleri en hızlı şekilde değiştirme esnekliğine katmanız gerekir.

Dinamik bellek ayırma ve RenderScript'e bağlama

Dinamik bellek ayırmak için Script.FieldBase sınıfını kullanır. Bu, en sık kullanılan yöntemdir. Alternatif olarak, Allocation manuel olarak oluşturulur. Bu, temel türden işaretçiler gibi işlemler için gereklidir. Şunları yapmalısınız: kullanım kolaylığı sağlamak için Script.FieldBase sınıf oluşturucusu kullanın. Bir bellek tahsisi elde ettikten sonra, ayrılan belleğibind RenderScript çalışma zamanı.

Aşağıdaki örnekte, bellek hem temel tür bir işaretçi hem de intPointer ve bir struct'ın işaretçisi touchPoints. Bu ayrıca belleği 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);

   ...
}

Okuma ve hafızaya yazma

Hem RenderScript çalışma zamanında statik ve dinamik olarak ayrılmış bellek üzerinde okuma hem de yazma işlemi yapabilirsiniz. çerçeve katmanı içerir.

Statik olarak ayrılmış bellek tek yönlü iletişim kısıtlamasıyla birlikte gelir aynı işlemi yapabilirsiniz. RenderScript kodu bir değişkenin değerini değiştirdiğinde, tekrar Android'in çerçeve katmanına iletilecek. Son değer Android çerçevesinden ayarlanan bir kod, get çağrısı sırasında her zaman döndürülür yöntemidir. Bununla birlikte, Android çerçevesi kodu bir değişkeni değiştirdiğinde bu değişiklik otomatik olarak veya daha sonra senkronize edilir. Veri göndermeniz gerekiyorsa farklı içerik türleri oluşturmak için rsSendToClient() işlevi üzerine eğilmeniz gerek.

Dinamik olarak ayrılmış bellekle çalışırken RenderScript çalışma zamanı katmanındaki tüm değişiklikler bellek ayırmayı ilişkili işaretçisini kullanarak değiştirdiyseniz Android çerçeve katmanına geri dönebilirsiniz. Android çerçeve katmanındaki bir nesnede değişiklik yapıldığında, bu değişiklik hemen RenderScript'e geri döndürülür çalışma zamanı katmanı.

Genel değişkenlere okuma ve yazma

Global değişkenlere okuma ve yazma işlemleri basit bir süreçtir. Erişimci yöntemlerini kullanabilirsiniz veya bunları doğrudan RenderScript kodunda ayarlamanız gerekir. Herhangi bir RenderScript kodunuzda yaptığınız değişiklikler dağıtılmaz Android çerçeve katmanına dön (buraya bakın bakın).

Örneğin, aşağıdaki struct'ın rsfile.rs adlı bir dosyada tanımlandığını varsayalım:

typedef struct Point {
    int x;
    int y;
} Point_t;

Point_t point;

struct'a doğrudan rsfile.rs içinde bunun gibi değerler atayabilirsiniz. Bu değerler Android çerçevesi düzeyine geri yayıldı:

point.x = 1;
point.y = 1;

Android çerçeve katmanında struct'a değerler atayabilirsiniz. Bu değerler, RenderScript çalışma zamanı düzeyine eşzamansız olarak geri uygulanır:

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);

RenderScript kodunuzdaki değerleri şu şekilde okuyabilirsiniz:

rsDebug("Printing out a Point", point.x, point.y);

Android çerçevesi katmanındaki değerleri aşağıdaki kodla okuyabilirsiniz. Bu kodu yalnızca Android çerçevesi düzeyinde ayarlanmışsa değer döndürür. Boş bir işaretçi alacaksınız Örneğin, değeri yalnızca RenderScript çalışma zamanı düzeyinde ayarladıysanız:

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());

Global işaretçileri okuma ve yazma

Belleğin Android çerçevesi düzeyinde ayrıldığı ve RenderScript çalışma zamanına bağlı olduğu varsayıldığında, söz konusu işaretçi için get ve set yöntemlerini kullanarak Android çerçevesi düzeyinden belleği okuyabilir ve yazabilirsiniz. RenderScript çalışma zamanı katmanında, işaretçileri kullanarak belleğe normal bir şekilde okuma ve yazma işlemi yapabilirsiniz ve değişiklikler yayılır. istatistiksel olarak ayrılmış belleğin aksine Android çerçeve katmanına geri dönebilir.

Örneğin, aşağıdaki işaretçi rsfile.rs adlı bir dosyadaki struct öğesinin üzerine getirildiğinde:

typedef struct Point {
    int x;
    int y;
} Point_t;

Point_t *point;

Android çerçeve katmanında bellek ayırdığınızı varsayarsak değerlere struct her zamanki gibi. struct'ta işaretçi değişkeni aracılığıyla yaptığınız değişiklikler otomatik olarak Android çerçeve katmanında kullanılabilir:

Kotlin

point[index].apply {
    x = 1
    y = 1
}

Java

point[index].x = 1;
point[index].y = 1;

Ayrıca, Android çerçeve katmanındaki işaretçiye değer yazabilir ve yazabilirsiniz:

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);

Bellek halihazırda bağlandıktan sonra, belleği RenderScript'e yeniden bağlamanız gerekmez değeri her değiştirdiğinizde çalışma zamanı oluşturur.