बेहतर रेंडर स्क्रिप्ट

RenderScript का इस्तेमाल करने वाले ऐप्लिकेशन अब भी Android वीएम के अंदर चलते हैं, आपके पास उन सभी फ़्रेमवर्क के एपीआई का ऐक्सेस होता है जिनके बारे में आपको जानकारी है. हालांकि, जब सही हो, तब RenderScript का इस्तेमाल करें. इस इंटरैक्शन को आसान बनाने के लिए फ़्रेमवर्क और RenderScript रनटाइम, दोनों के साथ काम करता है, तो कोड की एक इंटरमीडिएट लेयर भी इसका इस्तेमाल, कोड के दो लेवल के बीच कम्यूनिकेशन और मेमोरी मैनेजमेंट की सुविधा देने के लिए किया जा सकता है. इस दस्तावेज़ में इनके बारे में ज़्यादा जानकारी दी गई है कोड की अलग-अलग लेयर पर सेट किया गया है. साथ ही, यह भी बताया गया है कि Android वीएम और RenderScript रनटाइम.

RenderScript रनटाइम लेयर

आपका RenderScript कोड कंपाइल किया जाता है और एक छोटी और अच्छी तरह तय की गई रनटाइम लेयर में चलाया जाता है. RenderScript रनटाइम एपीआई, इंटेंसिव कंप्यूटेशन की सेवा एक प्रोसेसर पर उपलब्ध कोर की मात्रा होती है.

ध्यान दें: एनडीके में स्टैंडर्ड C फ़ंक्शन ऐसे होने चाहिए सीपीयू पर चलने की गारंटी देता है, इसलिए RenderScript इन लाइब्रेरी को ऐक्सेस नहीं कर सकता, क्योंकि RenderScript को अलग-अलग तरह के प्रोसेसर पर चलने के लिए डिज़ाइन किया गया है.

आपने .rs में अपना RenderScript कोड तय किया है और आपके Android प्रोजेक्ट की src/ डायरेक्ट्री में .rsh फ़ाइलें हैं. कोड को इंटरमीडिएट बाइटकोड में llvm कंपाइलर, जो Android बिल्ड के हिस्से के तौर पर चलता है. जब आपका आवेदन एक डिवाइस पर चलता है, फिर बाइट कोड को दूसरे डिवाइस से, मशीन कोड में कंपाइल (जस्ट-इन-टाइम) किया जाता है llvm कंपाइलर, जो डिवाइस में रहता है. मशीन कोड को डिवाइस और कैश मेमोरी में भी सेव किया जाता है, इसलिए RenderScript की मदद से चालू किए गए ऐप्लिकेशन का बाद में इस्तेमाल बाइट कोड को फिर से कंपाइल करना होगा.

RenderScript रनटाइम लाइब्रेरी की कुछ मुख्य सुविधाओं में ये शामिल हैं:

  • मेमोरी के बंटवारे के अनुरोध की सुविधाएं
  • स्केलर और वेक्टर, दोनों टाइप के ओवरलोडेड वर्शन के साथ गणित के फ़ंक्शन का एक बड़ा संग्रह में कर सकते हैं. जोड़ना, गुणा करना, डॉट प्रॉडक्ट, और क्रॉस प्रॉडक्ट जैसे ऑपरेशन साथ ही, परमाणु अंकगणित और तुलना करने वाले फ़ंक्शन उपलब्ध हैं.
  • प्रिमिटिव डेटा टाइप और वेक्टर, मैट्रिक्स रूटीन, और तारीख और समय के लिए कन्वर्ज़न रूटीन रूटीन
  • RenderScript सिस्टम के साथ काम करने के लिए डेटा टाइप और स्ट्रक्चर, जैसे कि वेक्टर टाइप दो, तीन या चार वेक्टर का पता लगाएं.
  • फ़ंक्शन लॉग करने का तरीका

उपलब्ध फ़ंक्शन के बारे में ज़्यादा जानने के लिए, RenderScript रनटाइम एपीआई का रेफ़रंस देखें.

रिफ़्लेक्टेड लेयर

परावर्तित लेयर, क्लास का एक सेट है. इसे ऐक्सेस देने के लिए, Android बिल्ड टूल जनरेट करते हैं को Android फ़्रेमवर्क से RenderScript रनटाइम में एक्सपोर्ट कर दिया जाएगा. यह लेयर, तरीके भी देती है और ऐसे कंस्ट्रक्टर जिनकी मदद से, आपको आपका RenderScript कोड. नीचे दी गई सूची में प्रमुख इसमें दिखने वाले कॉम्पोनेंट:

  • आपकी बनाई जाने वाली हर .rs फ़ाइल, में से project_root/gen/package/name/ScriptC_renderscript_filename ScriptC टाइप करें. यह फ़ाइल आपके ऐप्लिकेशन का .java वर्शन है .rs फ़ाइल डाउनलोड की जा सकती है, जिसे Android फ़्रेमवर्क से कॉल किया जा सकता है. इस क्लास में .rs फ़ाइल से ये आइटम दिखते हैं:
    • नॉन-स्टैटिक फ़ंक्शन
    • नॉन-स्टैटिक, ग्लोबल RenderScript वैरिएबल. ऐक्सेसर तरीके हर वैरिएबल के लिए जनरेट किए जाते हैं, ताकि आप इन्हें पढ़ सकें और Android से RenderScript वैरिएबल लिखें फ़्रेमवर्क शामिल है. अगर कोई ग्लोबल वैरिएबल RenderScript रनटाइम लेयर, उन वैल्यू का इस्तेमाल इन कामों के लिए किया जाता है Android फ़्रेमवर्क में, उससे जुड़ी वैल्यू को शुरू करना लेयर. अगर ग्लोबल वैरिएबल को const के तौर पर मार्क किया गया है, तो तो set तरीका जनरेट किया गया. यहां देखें देखें.

    • ग्लोबल पॉइंटर
  • struct, इसकी अपनी नाम वाली क्लास में दिखता है project_root/gen/package/name/ScriptField_struct_name, जो Script.FieldBase तक बढ़ाएं. यह क्लास, struct, जो आपको इसके एक या ज़्यादा इंस्टेंस के लिए मेमोरी बांटने की अनुमति देता है struct.

फ़ंक्शन

फ़ंक्शन, स्क्रिप्ट क्लास में ही दिखते हैं. ये क्लास में project_root/gen/package/name/ScriptC_renderscript_filename. इसके लिए उदाहरण के लिए, अगर आप अपने 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;
}

तो यह 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);
}

फ़ंक्शन में रिटर्न वैल्यू नहीं हो सकतीं, क्योंकि RenderScript सिस्टम को इस तरह डिज़ाइन किया गया है कि एसिंक्रोनस. जब आपका Android फ़्रेमवर्क कोड RenderScript में कॉल करता है, तो कॉल सूची में होता है और लागू किया जाता है. इस पाबंदी की मदद से, RenderScript सिस्टम बिना किसी कॉन्सटैंट वैल्यू के काम कर सकता है और क्षमता को बढ़ाता है. अगर फ़ंक्शन को रिटर्न वैल्यू की अनुमति होती है, तो तब तक ब्लॉक रहेगा, जब तक वैल्यू नहीं दिखाई जाती.

अगर आप चाहते हैं कि RenderScript कोड किसी मान को वापस Android फ़्रेमवर्क को भेजे, तो rsSendToClient() फ़ंक्शन का इस्तेमाल करना होगा.

वैरिएबल

समर्थित प्रकार के वैरिएबल स्क्रिप्ट क्लास में ही दिखाई देते हैं, जो यहां मौजूद हैं project_root/gen/package/name/ScriptC_renderscript_filename. ऐक्सेसर का सेट हर वैरिएबल के लिए तरीके जनरेट किए जाते हैं. उदाहरण के लिए, अगर नीचे दिए गए वैरिएबल को आपका RenderScript कोड:

uint32_t unsignedInteger = 1;

तो यह 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;
}
  

स्ट्रक्चर

संरचनाएं अपनी ही क्लास में प्रतिबिंबित होती हैं, जो <project_root>/gen/com/example/renderscript/ScriptField_struct_name. यह क्लास, struct का कलेक्शन दिखाती है. साथ ही, इससे आपको struct की बताई गई संख्या. उदाहरण के लिए, अगर नीचे दिए गए स्ट्रक्चर को तय किया जाता है:

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

तो ScriptField_Point.java में यह कोड जनरेट होता है:

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

जनरेट किया गया कोड, अनुरोध किए गए स्ट्रक्चर के लिए मेमोरी बांटने में आपकी सुविधा के तौर पर दिया जाता है RenderScript रनटाइम के ज़रिए और structs के साथ इंटरैक्ट करने के लिए मेमोरी में सेव किया जा सकता है. हर struct की क्लास इन तरीकों और कंस्ट्रक्टर के बारे में बताती है:

  • ओवरलोडेड कंस्ट्रक्टर, जो आपको मेमोरी असाइन करने की अनुमति देते हैं. कॉन्टेंट बनाने ScriptField_struct_name(RenderScript rs, int count) कंस्ट्रक्टर की अनुमति है आप उन स्ट्रक्चर की संख्या परिभाषित कर सकते हैं जिनके लिए आप count पैरामीटर. ScriptField_struct_name(RenderScript rs, int count, int usages) कंस्ट्रक्टर, उस अतिरिक्त पैरामीटर usages के बारे में बताता है जो आपको इस मेमोरी के बंटवारे के लिए मेमोरी स्पेस तय करने की सुविधा देता है. स्टोरेज में चार जगह होती है संभावनाएं:
    • USAGE_SCRIPT: स्क्रिप्ट मेमोरी में असाइन करता है स्पेस. अगर आप मेमोरी स्पेस तय नहीं करते हैं, तो यह डिफ़ॉल्ट मेमोरी स्पेस होता है.
    • USAGE_GRAPHICS_TEXTURE: इसमें असाइन किया जाता है जीपीयू का टेक्सचर मेमोरी स्पेस.
    • USAGE_GRAPHICS_VERTEX: शीर्ष में तय करता है जीपीयू का मेमोरी स्पेस.
    • USAGE_GRAPHICS_CONSTANTS: इसमें असाइन किया जाता है जीपीयू का स्थायी मेमोरी स्पेस, जिसका इस्तेमाल प्रोग्राम के अलग-अलग ऑब्जेक्ट में किया जाता है.

    बिट के अनुसार OR ऑपरेटर का इस्तेमाल करके, एक से ज़्यादा मेमोरी स्पेस तय किए जा सकते हैं. ऐसा करना यह RenderScript रनटाइम की सूचना देता है कि आप तय मेमोरी स्पेस. नीचे दिए गए उदाहरण में, कस्टम डेटा टाइप के लिए मेमोरी असाइन की गई है स्क्रिप्ट और वर्टेक्स मेमोरी स्पेस, दोनों में:

    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);
    
  • स्टैटिक नेस्ट की गई क्लास, Item की मदद से, struct. अगर काम करना ज़्यादा सही लगता है, तो नेस्ट की गई यह क्लास काम की है अपने Android कोड में struct से. ऑब्जेक्ट में बदलाव करने के बाद, ऑब्जेक्ट को असाइन की गई मेमोरी में पुश किया जा सकता है. इसके लिए, set(Item i, int index, boolean copyNow) को कॉल करें और Item को अपनी पसंद की जगह पर सेट करें श्रेणी को चुनना होगा. RenderScript रनटाइम को अपने-आप नई मेमोरी का ऐक्सेस मिल जाता है.
  • किसी स्ट्रक्चर में हर फ़ील्ड की वैल्यू पाने और सेट करने के लिए, ऐक्सेसर के तरीके. इनमें से सभी ऐक्सेसर के तरीकों में struct की जानकारी देने के लिए, एक index पैरामीटर होता है वह कलेक्शन होता है जिसे आपको पढ़ना या लिखना है. हर सेटर विधि में copyNow पैरामीटर से तय होता है कि इस मेमोरी को तुरंत सिंक करना है या नहीं को RenderScript रनटाइम में एक्सपोर्ट कर सकता है. जो मेमोरी सिंक नहीं की गई है उसे सिंक करने के लिए, कॉल करें copyAll().
  • createElement() तरीका, मेमोरी में स्ट्रक्चर की जानकारी बनाता है. यह ब्यौरे का इस्तेमाल एक या कई एलिमेंट वाली मेमोरी तय करने के लिए किया जाता है.
  • resize(), C में मौजूद realloc() की तरह काम करता है. इसकी मदद से, ये काम किए जा सकते हैं पहले असाइन की गई मेमोरी को बड़ा करें, ताकि मौजूदा वैल्यू में कोई बदलाव न हो बनाया गया.
  • copyAll(), फ़्रेमवर्क लेवल पर सेट की गई मेमोरी को RenderScript रनटाइम. जब किसी सदस्य पर, ऐक्सेसर के सेट किए गए तरीके को कॉल किया जाता है, तो copyNow बूलियन पैरामीटर, जिसे तय किया जा सकता है. तय किया जा रहा है तरीके को कॉल करने पर, true मेमोरी को सिंक करता है. अगर गलत वैल्यू दी जाती है, आप copyAll() को एक बार कॉल कर सकते हैं और यह सभी ऐसी प्रॉपर्टी जिन्हें अभी तक सिंक नहीं किया गया है.

पॉइंटर

ग्लोबल पॉइंटर, स्क्रिप्ट क्लास में दिखते हैं project_root/gen/package/name/ScriptC_renderscript_filename. आपने लोगों तक पहुंचाया मुफ़्त में किसी struct या इस्तेमाल किए जा सकने वाले किसी भी RenderScript टाइप के लिए पॉइंटर एलान कर सकता है, लेकिन struct में पॉइंटर या नेस्ट किए गए अरे नहीं हो सकते. उदाहरण के लिए, यदि आप struct और int32_t पर ले जाने वाले पॉइंटर

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

Point_t *touchPoints;
int32_t *intPointer;

तो यह 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;
}
  

एक get तरीका और bind_pointer_name नाम का एक खास तरीका (set() तरीके के बजाय) जनरेट किए जाते हैं. bind_pointer_name तरीका, आपको मेमोरी को बाइंड करने की अनुमति देता है जिसे Android वीएम में RenderScript रनटाइम में असाइन किया गया हो (आप मेमोरी) .rs फ़ाइल में सेव की जाती है). ज़्यादा जानकारी के लिए, देखें काम कर रहा है तय मेमोरी के साथ.

मेमोरी ऐलोकेशन एपीआई

RenderScript का इस्तेमाल करने वाले ऐप्लिकेशन अब भी Android वीएम में चलते हैं. हालांकि, वास्तविक RenderScript कोड स्थानीय तौर पर चलता है और को Android वीएम में असाइन की गई मेमोरी का ऐक्सेस चाहिए. ऐसा करने के लिए, वीएम में तय की गई मेमोरी को RenderScript रनटाइम में अटैच करें. यह प्रोसेस, जिसे बाइंडिंग कहा जाता है, से RenderScript रनटाइम को उस मेमोरी के साथ बिना किसी रुकावट के काम करने में मदद मिलती है अनुरोध करते हैं, लेकिन स्पष्ट रूप से आवंटित नहीं कर सकते. नतीजा कुछ ऐसा ही होता है जैसे कि सी में malloc कहा जाता है. Android वीएम का अतिरिक्त फ़ायदा यह है कि इसकी मदद से, कूड़ा इकट्ठा करने का काम भी किया जा सकता है RenderScript रनटाइम लेयर के साथ मेमोरी शेयर करें. बाइंडिंग की ज़रूरत सिर्फ़ डाइनैमिक तरीके से असाइन की गई मेमोरी के लिए होती है. स्टैटिक तरीके से असाइन की गई मेमोरी, कंपाइल करते समय आपके RenderScript कोड के लिए अपने-आप बन जाती है. पहली इमेज देखें देखें.

मेमोरी के इस ऐलोकेशन सिस्टम पर काम करने के लिए, एपीआई का एक सेट उपलब्ध है. इसकी मदद से Android वीएम को मेमोरी का बंटवारा किया जा सकता है और malloc कॉल जैसी ही सुविधाएं दी जा सकती हैं. ये क्लास साफ़ तौर पर यह बताएं कि मेमोरी किस तरह असाइन की जानी चाहिए. साथ ही, बंटवारे की सुविधा का पूरा इस्तेमाल कैसे किया जाना चाहिए. बेहतर करने के लिए इन क्लास के काम करने का तरीका समझने के लिए, इन्हें एक आसान malloc कॉल, जो कुछ ऐसा दिख सकता है:

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

malloc कॉल को दो हिस्सों में बांटा जा सकता है: असाइन की जा रही मेमोरी का साइज़ (sizeof(int)), साथ ही, उस मेमोरी की कितनी यूनिट असाइन की जानी चाहिए (10). Android फ़्रेमवर्क, इन दो हिस्सों के लिए क्लास देता है और malloc को दर्शाने वाली क्लास.

Element क्लास, (sizeof(int)) वाला हिस्सा दिखाती है यह malloc कॉल का हिस्सा होता है और मेमोरी के बंटवारे का एक सेल इनकैप्सुलेट करता है, जैसे कि कोई सिंगल फ़्लोट वैल्यू या स्ट्रक्चर शामिल करें. Type क्लास में Element शामिल होता है और असाइन किए जाने वाले एलिमेंट की संख्या (हमारे उदाहरण में 10). Type को ऐसा समझा जा सकता है Element का कलेक्शन. Allocation क्लास दिए गए Type के हिसाब से मेमोरी का बंटवारा और असल में असाइन की गई मेमोरी का पता चलता है.

ज़्यादातर मामलों में, आपको इन मेमोरी ऐलोकेशन एपीआई को सीधे कॉल करने की ज़रूरत नहीं होती. परावर्तित परत क्लास अपने आप इन API का इस्तेमाल करने के लिए कोड जनरेट करती हैं और मेमोरी असाइन करने के लिए आपको बस एक कंस्ट्रक्टर जिसका एलान किसी एक प्रतिबिंब लेयर क्लास में किया जाता है और फिर बाइंड करता है इससे बनने वाली मेमोरी Allocation को RenderScript में बदलें. कुछ ऐसी स्थितियां हैं जिनमें आपको इन क्लास का इस्तेमाल सीधे तौर पर, अपने जैसे कि किसी संसाधन से बिटमैप लोड करना या जब आपको पॉइंटर के लिए मेमोरी असाइन करनी हो, प्रिमिटिव टाइप. इसका तरीका यहां देखें: RenderScript में मेमोरी असाइन करना और बाइंड करना सेक्शन. इस टेबल में, मेमोरी मैनेजमेंट के तीन क्लास के बारे में ज़्यादा जानकारी दी गई है:

Android ऑब्जेक्ट टाइप ब्यौरा
Element

एलिमेंट, मेमोरी के बंटवारे के एक सेल के बारे में बताता है और इसके दो रूप हो सकते हैं: बेसिक या जटिल.

बेसिक एलिमेंट में किसी भी मान्य RenderScript डेटा टाइप के डेटा का एक कॉम्पोनेंट होता है. बेसिक एलिमेंट डेटा टाइप के उदाहरणों में एक float वैल्यू, float4 वेक्टर या एक RGB-565 रंग.

कॉम्प्लेक्स एलिमेंट में बुनियादी एलिमेंट की एक सूची होती है. इन्हें इन एलिमेंट से बनाया जाता है struct, जिनका एलान आपने अपने RenderScript कोड में किया है. उदाहरण के लिए, बजट असाइन करना इसमें मेमोरी के क्रम में व्यवस्थित किए गए कई struct शामिल हो सकते हैं. प्रत्येक संरचना को उस संरचना में मौजूद हर डेटा टाइप के बजाय एक ही एलिमेंट का इस्तेमाल करें.

Type

टाइप, मेमोरी ऐलोकेशन टेंप्लेट होता है. इसमें एक एलिमेंट और एक या उससे ज़्यादा एलिमेंट होते हैं डाइमेंशन. यह मेमोरी के लेआउट के बारे में बताता है (मूल रूप से Element की एक कलेक्शन). हालांकि, यह मेमोरी के डेटा के लिए इसका इस्तेमाल नहीं करता बताता है.

एक टाइप के पांच डाइमेंशन होते हैं: X, Y, Z, LOD (जानकारी का लेवल), और फ़ेस (एक क्यूब के) मैप) पर क्लिक करें. X,Y,Z के डाइमेंशन को उपलब्ध मेमोरी की सीमाएं तय करना. एक डाइमेंशन के बंटवारे का X डाइमेंशन शून्य से ज़्यादा है, जबकि Y और Z डाइमेंशन शून्य हैं. इसका मतलब है कि कोई वैल्यू मौजूद नहीं है. इसके लिए जैसे, x=10 का बंटवारा. y=1 को दो डाइमेंशन और x=10 के बीच माना जाता है. y=0 को माना जाता है. मौजूद दिखाने के लिए एलओडी और चेहरे के डाइमेंशन बूलियन हैं या मौजूद न हो.

Allocation

असाइन करने से, ऐप्लिकेशन के लिए मेमोरी उपलब्ध होती है. यह मेमोरी के ब्यौरे के आधार पर तय होती है जिसे Type से दिखाया जाता है. असाइन की गई मेमोरी इसमें मौजूद हो सकती है एक साथ कई मेमोरी स्पेस अगर किसी एक स्पेस में मेमोरी में बदलाव किया गया है, तो आपको साफ़ तौर पर मेमोरी को सिंक करें, ताकि यह उन अन्य सभी स्पेस में अपडेट हो जाए जिनमें वह मौजूद है.

आवंटन डेटा को मुख्य रूप से इन दो में से किसी एक तरीके से अपलोड किया जाता है: टाइप को चुना गया और टाइप नहीं किया गया. सामान्य सरणियों के लिए, copyFrom() फ़ंक्शन हैं जो और उसे नेटिव लेयर वाले मेमोरी स्टोर में कॉपी करें. सही का निशान हटाए गए वैरिएंट आपको इस्तेमाल करने की अनुमति देते हैं स्ट्रक्चर के अरे को कॉपी करने के लिए, Android सिस्टम को चुना जा सकता है, क्योंकि यह स्ट्रक्चर. उदाहरण के लिए, अगर कोई ऐलोकेशन है जो n फ़्लोट का कलेक्शन है, तो डेटा किसी float[n] कलेक्शन में मौजूद या byte[n*4] कलेक्शन को कॉपी किया जा सकता है.

मेमोरी के साथ काम करना

आपने रेंडर स्क्रिप्ट में, नॉन-स्टैटिक, ग्लोबल वैरिएबल के बारे में जानकारी दी है. वैरिएबल को कंपाइल करते समय मेमोरी असाइन की जाती है. आप इन वैरिएबल के साथ सीधे अपने RenderScript कोड में काम कर सकते हैं. इसके लिए आपको मेमोरी की ज़रूरत नहीं होती. Android फ़्रेमवर्क लेयर के पास इन वैरिएबल का ऐक्सेस भी होता है को ऐक्सेस करने के लिए दिए गए उन तरीकों का इस्तेमाल करना चाहिए जो दिखाई गई लेयर क्लास में जनरेट होते हैं. अगर ये वैरिएबल RenderScript रनटाइम लेयर पर शुरू किया जाता है, तो उन वैल्यू का इस्तेमाल संबंधित में मौजूदा वैल्यू शामिल होती हैं. अगर ग्लोबल वैरिएबल को कॉन्स्ट के तौर पर मार्क किया गया है, तो set तरीका होगा जनरेट नहीं हुआ. ज़्यादा जानकारी के लिए यहां देखें.

ध्यान दें: अगर आप ऐसे कुछ RenderScript स्ट्रक्चर का इस्तेमाल कर रहे हैं जिनमें पॉइंटर मौजूद हैं, जैसे कि rs_program_fragment और rs_allocation, आपको पहले संबंधित Android फ़्रेमवर्क क्लास और फिर उसके लिए set मेथड को कॉल करें स्ट्रक्चर को रेंडर करने में मदद करता है. आप इन स्ट्रक्चर में सीधे तौर पर बदलाव नहीं कर सकते RenderScript रनटाइम लेयर पर. यह प्रतिबंध उपयोगकर्ता-तय स्ट्रक्चर पर लागू नहीं है जिनमें पॉइंटर होते हैं, क्योंकि उन्हें किसी प्रतिबिंब लेयर क्लास में एक्सपोर्ट नहीं किया जा सकता पहले स्थान पर हैं. किसी नॉन-स्टैटिक, ग्लोबल एलान का एलान करने पर कंपाइलर गड़बड़ी जनरेट होती है ऐसी संरचना जिसमें पॉइंटर हो.

RenderScript में भी पॉइंटर के लिए समर्थन मौजूद है, लेकिन आपको अपने Android फ़्रेमवर्क कोड. अपनी .rs फ़ाइल में ग्लोबल पॉइंटर का एलान करने पर, उचित परावर्तित लेयर क्लास के ज़रिए मेमोरी असाइन करें और उस मेमोरी को नेटिव से बाइंड करें RenderScript लेयर. इस मेमोरी के साथ, Android फ़्रेमवर्क लेयर के ज़रिए भी इंटरैक्ट किया जा सकता है RenderScript लेयर, जो आपको ज़्यादा से ज़्यादा वैरिएबल को बदलने की सुविधा देती है उचित लेयर.

RenderScript में डाइनैमिक मेमोरी तय करना और जोड़ना

डाइनैमिक मेमोरी असाइन करने के लिए, आपको Script.FieldBase क्लास, जो सबसे सामान्य तरीका है. इसका एक विकल्प यह है कि मैन्युअल रूप से Allocation, जो कि प्रिमिटिव टाइप पॉइंटर जैसी चीज़ों के लिए ज़रूरी है. आपको ऐसा करना चाहिए जहां भी आसानी से काम करने के लिए उपलब्ध हो, Script.FieldBase क्लास कंस्ट्रक्टर का इस्तेमाल करें. मेमोरी असाइन करने के बाद, पॉइंटर के दिखाए गए bind तरीके को कॉल करें, ताकि असाइन की गई मेमोरी से RenderScript रनटाइम.

नीचे दिया गया उदाहरण, प्रिमिटिव टाइप पॉइंटर, दोनों के लिए मेमोरी बांटता है, intPointer और स्ट्रक्चर के लिए पॉइंटर, touchPoints. यह मेमोरी को रेंडर स्क्रिप्ट:

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

   ...
}

यादों को पढ़ना और लिखना

आपके पास RenderScript रनटाइम, दोनों में स्टैटिक और डाइनैमिक तौर पर असाइन की गई मेमोरी को पढ़ने और उसमें बदलाव करने का विकल्प होता है और Android फ़्रेमवर्क लेयर.

स्टैटिक रूप से असाइन की गई मेमोरी, एकतरफ़ा कम्यूनिकेशन से जुड़ी पाबंदी के साथ मिलती है RenderScript रनटाइम लेवल पर. जब RenderScript कोड किसी वैरिएबल की वैल्यू में बदलाव करता है, तो ऐसा नहीं होता बेहतर परफ़ॉर्मेंस के लिए, Android फ़्रेमवर्क लेयर को वापस भेजा जाता है. आखिरी वैल्यू जो Android फ़्रेमवर्क से सेट किया गया है, वह get पर कॉल के दौरान हमेशा दिखता है तरीका. हालांकि, जब Android फ़्रेमवर्क कोड किसी वैरिएबल में बदलाव करता है, तो उस बदलाव को RenderScript रनटाइम अपने-आप या बाद में सिंक होता है. अगर आपको डेटा भेजने की ज़रूरत हो RenderScript रनटाइम से लेकर Android फ़्रेमवर्क लेयर तक, आप rsSendToClient() फ़ंक्शन इस सीमा को पार करने के लिए.

डाइनैमिक तौर पर असाइन की गई मेमोरी के साथ काम करते समय, RenderScript रनटाइम लेयर में कोई भी बदलाव लागू होता है Android फ़्रेमवर्क लेयर पर वापस जाएं. Android फ़्रेमवर्क लेयर में किसी ऑब्जेक्ट में बदलाव करने से, वह तुरंत RenderScript में बदल जाता है रनटाइम लेयर.

ग्लोबल वैरिएबल के हिसाब से पढ़ना और लिखना

ग्लोबल वैरिएबल के हिसाब से पढ़ना और लिखना, एक आसान प्रोसेस है. ऐक्सेसर के तरीके इस्तेमाल किए जा सकते हैं पर सेट कर सकते हैं या उन्हें सीधे RenderScript कोड में सेट कर सकते हैं. ध्यान रखें कि किसी आपने अपने RenderScript कोड में जो बदलाव किए हैं वे लागू नहीं होते हैं Android फ़्रेमवर्क लेयर पर वापस जाएँ (यहां देखें देखें).

उदाहरण के लिए, rsfile.rs नाम की फ़ाइल में दिए गए इस स्ट्रक्चर का एलान किया गया है:

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

Point_t point;

इस तरह के स्ट्रक्चर के लिए, सीधे rsfile.rs में वैल्यू असाइन की जा सकती हैं. ये मान नहीं हैं इसे Android फ़्रेमवर्क लेवल पर वापस लागू किया जाएगा:

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

इस तरह, Android फ़्रेमवर्क लेयर पर स्ट्रक्चर के लिए वैल्यू असाइन की जा सकती हैं. ये वैल्यू हैं: RenderScript रनटाइम लेवल पर एसिंक्रोनस तरीके से वापस लागू किया जाता है:

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

आप अपने रेंडर स्क्रिप्ट कोड में वैल्यू को इस तरह पढ़ सकते हैं:

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

नीचे दिए गए कोड की मदद से, Android फ़्रेमवर्क लेयर में वैल्यू पढ़ी जा सकती हैं. ध्यान रखें कि इस कोड सिर्फ़ तब वैल्यू दिखाता है, जब Android फ़्रेमवर्क लेवल पर सेट किया गया हो. आपको एक शून्य पॉइंटर मिलेगा अपवाद के तौर पर, अगर आपने वैल्यू को सिर्फ़ 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());

ग्लोबल पॉइंटर पढ़ना और लिखना

यह मानते हुए कि मेमोरी को Android फ़्रेमवर्क लेवल में बांटा गया है और यह RenderScript रनटाइम से जुड़ा हुआ है, उस पॉइंटर के लिए get और set तरीकों का इस्तेमाल करके, Android फ़्रेमवर्क लेवल से मेमोरी को पढ़ा और लिखा जा सकता है. RenderScript रनटाइम लेयर में, आप सामान्य रूप से पॉइंटर के साथ मेमोरी में पढ़ और लिख सकते हैं और बदलाव लागू हो जाते हैं इसमें हम Android फ़्रेमवर्क लेयर पर वापस जा सकते हैं. यह स्टैटिक तरीके से असाइन की गई मेमोरी से अलग होता है.

उदाहरण के लिए, rsfile.rs नाम की फ़ाइल में struct का यह पॉइंटर दिया गया है:

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

Point_t *point;

मान लें कि आपने Android फ़्रेमवर्क लेयर में पहले ही मेमोरी असाइन कर दी है, तो struct सामान्य रूप से. इसके पॉइंटर वैरिएबल की मदद से, स्ट्रक्चर में किया जाने वाला कोई भी बदलाव ये टूल, Android फ़्रेमवर्क लेयर में अपने-आप उपलब्ध हो जाते हैं:

Kotlin

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

Java

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

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

जब मेमोरी पहले ही बाउंड हो जाए, तो आपको मेमोरी को RenderScript के साथ फिर से बाइंड करने की ज़रूरत नहीं है हर बार वैल्यू में बदलाव करने पर, रनटाइम दिखता है.