Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2011-2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.renderscript.cts;
     18 
     19 import android.graphics.Bitmap;
     20 import android.renderscript.Allocation;
     21 import android.renderscript.AllocationAdapter;
     22 import android.renderscript.Allocation.MipmapControl;
     23 import android.renderscript.Element;
     24 import android.renderscript.RSIllegalArgumentException;
     25 import android.renderscript.RSInvalidStateException;
     26 import android.renderscript.Type;
     27 import android.renderscript.Type.Builder;
     28 
     29 import android.renderscript.ScriptIntrinsicColorMatrix;
     30 import android.renderscript.ScriptIntrinsicConvolve3x3;
     31 import android.renderscript.ScriptGroup;
     32 import android.renderscript.Matrix4f;
     33 import android.util.Log;
     34 
     35 public class ScriptGroupTest extends RSBaseCompute {
     36 
     37     private static final String TAG = "ScriptGroupTest";
     38     private static final int ARRAY_SIZE = 256;
     39     static int bDimX = 48;
     40     static int bDimY = 8;
     41 
     42     public void testScriptGroupSingleKernel() {
     43         ScriptGroup group;
     44 
     45         Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create();
     46 
     47         ScriptIntrinsicColorMatrix mColorMatrix;
     48 
     49         mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
     50 
     51         Allocation a1_copy, a2_copy;
     52         a1_copy = Allocation.createTyped(mRS, connect);
     53         a2_copy = Allocation.createTyped(mRS, connect);
     54 
     55         Matrix4f m = new Matrix4f();
     56         m.set(1, 0, 0.2f);
     57         m.set(1, 1, 0.9f);
     58         m.set(1, 2, 0.2f);
     59         mColorMatrix.setColorMatrix(m);
     60 
     61         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
     62         b.addKernel(mColorMatrix.getKernelID());
     63         group = b.create();
     64 
     65         group.setInput(mColorMatrix.getKernelID(), a1_copy);
     66         group.setOutput(mColorMatrix.getKernelID(), a2_copy);
     67 
     68         group.execute();
     69 
     70         mColorMatrix.destroy();
     71         a1_copy.destroy();
     72         a2_copy.destroy();
     73         group.destroy();
     74     }
     75 
     76     public void testScriptGroupDisconnectedKernel() {
     77         ScriptGroup group = null;
     78 
     79         Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create();
     80 
     81         ScriptIntrinsicColorMatrix mColorMatrix, mColorMatrix2;
     82 
     83         mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
     84         mColorMatrix2 = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
     85 
     86         Allocation a1_copy, a2_copy;
     87 
     88         a1_copy = Allocation.createTyped(mRS, connect);
     89         a2_copy = Allocation.createTyped(mRS, connect);
     90 
     91         Matrix4f m = new Matrix4f();
     92         m.set(1, 0, 0.2f);
     93         m.set(1, 1, 0.9f);
     94         m.set(1, 2, 0.2f);
     95         mColorMatrix.setColorMatrix(m);
     96         mColorMatrix2.setColorMatrix(m);
     97 
     98         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
     99         b.addKernel(mColorMatrix.getKernelID());
    100         b.addKernel(mColorMatrix2.getKernelID());
    101         try {
    102             group = b.create();
    103             fail("should throw RSInvalidStateException.");
    104         } catch (RSInvalidStateException e) {
    105 
    106         }
    107 
    108         mColorMatrix.destroy();
    109         mColorMatrix2.destroy();
    110         a1_copy.destroy();
    111         a2_copy.destroy();
    112         if (group != null) {
    113             group.destroy();
    114         }
    115     }
    116 
    117 
    118     public void testScriptGroupFieldConnection() {
    119         ScriptGroup group;
    120 
    121         Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create();
    122 
    123         ScriptIntrinsicConvolve3x3 mConvolve3x3;
    124         ScriptIntrinsicColorMatrix mColorMatrix;
    125 
    126         mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
    127         mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
    128 
    129         Allocation a1_copy, a2_copy;
    130         a1_copy = Allocation.createTyped(mRS, connect);
    131         a2_copy = Allocation.createTyped(mRS, connect);
    132 
    133         float f[] = new float[9];
    134         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
    135         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
    136         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
    137 
    138         mConvolve3x3.setCoefficients(f);
    139 
    140         Matrix4f m = new Matrix4f();
    141         m.set(1, 0, 0.2f);
    142         m.set(1, 1, 0.9f);
    143         m.set(1, 2, 0.2f);
    144         mColorMatrix.setColorMatrix(m);
    145 
    146         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
    147         b.addKernel(mColorMatrix.getKernelID());
    148         b.addKernel(mConvolve3x3.getKernelID());
    149         b.addConnection(connect, mColorMatrix.getKernelID(), mConvolve3x3.getFieldID_Input());
    150         group = b.create();
    151 
    152         group.setInput(mColorMatrix.getKernelID(), a1_copy);
    153         group.setOutput(mConvolve3x3.getKernelID(), a2_copy);
    154 
    155         group.execute();
    156 
    157         mConvolve3x3.destroy();
    158         mColorMatrix.destroy();
    159         a1_copy.destroy();
    160         a2_copy.destroy();
    161         group.destroy();
    162     }
    163 
    164     public void testScriptGroupDisconnectedDAG() {
    165         ScriptGroup group = null;
    166 
    167         Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create();
    168 
    169         ScriptIntrinsicConvolve3x3 mConvolve3x3, mConvolve3x32;
    170         ScriptIntrinsicColorMatrix mColorMatrix, mColorMatrix2;
    171 
    172         mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
    173         mConvolve3x32 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
    174         mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
    175         mColorMatrix2 = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
    176 
    177         Allocation a1_copy, a2_copy;
    178         a1_copy = Allocation.createTyped(mRS, connect);
    179         a2_copy = Allocation.createTyped(mRS, connect);
    180 
    181         float f[] = new float[9];
    182         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
    183         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
    184         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
    185 
    186         mConvolve3x3.setCoefficients(f);
    187         mConvolve3x32.setCoefficients(f);
    188 
    189         Matrix4f m = new Matrix4f();
    190         m.set(1, 0, 0.2f);
    191         m.set(1, 1, 0.9f);
    192         m.set(1, 2, 0.2f);
    193         mColorMatrix.setColorMatrix(m);
    194         mColorMatrix2.setColorMatrix(m);
    195 
    196         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
    197         b.addKernel(mColorMatrix.getKernelID());
    198         b.addKernel(mColorMatrix2.getKernelID());
    199         b.addKernel(mConvolve3x3.getKernelID());
    200         b.addKernel(mConvolve3x32.getKernelID());
    201         b.addConnection(connect, mColorMatrix.getKernelID(), mConvolve3x3.getFieldID_Input());
    202         b.addConnection(connect, mColorMatrix2.getKernelID(), mConvolve3x32.getFieldID_Input());
    203         try {
    204             group = b.create();
    205             fail("RSInvalidStateException expected");
    206         } catch (RSInvalidStateException e) {
    207 
    208         }
    209 
    210         mConvolve3x3.destroy();
    211         mConvolve3x32.destroy();
    212         mColorMatrix.destroy();
    213         mColorMatrix2.destroy();
    214         a1_copy.destroy();
    215         a2_copy.destroy();
    216         if (group != null) {
    217             group.destroy();
    218         }
    219     }
    220 
    221     public void testScriptGroupTorture() {
    222         ScriptGroup group;
    223 
    224         int[] result = new int[1];
    225 
    226         bDimX = 1;
    227 
    228         Type connect = new Type.Builder(mRS, Element.I32(mRS)).setX(bDimX).create();
    229         Type compareType = new Type.Builder(mRS, Element.I32(mRS)).create();
    230 
    231         ScriptC_scriptgroup node1, node2, node3, node4, node5, compare;
    232         node1 = new ScriptC_scriptgroup(mRS);
    233         node2 = new ScriptC_scriptgroup(mRS);
    234         node3 = new ScriptC_scriptgroup(mRS);
    235         node4 = new ScriptC_scriptgroup(mRS);
    236         node5 = new ScriptC_scriptgroup(mRS);
    237 
    238         compare = new ScriptC_scriptgroup(mRS);
    239 
    240         Allocation in1, in2, out, resultAlloc;
    241         in1 = Allocation.createTyped(mRS, connect);
    242         in2 = Allocation.createTyped(mRS, connect);
    243 
    244         out = Allocation.createTyped(mRS, connect);
    245         resultAlloc = Allocation.createTyped(mRS, compareType);
    246 
    247         node1.set_memset_toValue(1);
    248         node1.forEach_memset(in1);
    249         node1.set_memset_toValue(2);
    250         node1.forEach_memset(in2);
    251 
    252         node1.set_arith_operation(2);
    253         node2.set_arith_operation(1);
    254         node3.set_arith_operation(0);
    255         node4.set_arith_operation(0);
    256         node5.set_arith_operation(1);
    257 
    258         node3.set_arith_use_rs_allocation(1);
    259         node4.set_arith_use_rs_allocation(1);
    260 
    261         node1.set_arith_value(5);
    262         node2.set_arith_value(3);
    263         node5.set_arith_value(7);
    264 
    265         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
    266         b.addKernel(node1.getKernelID_arith());
    267         b.addKernel(node2.getKernelID_arith());
    268         b.addKernel(node3.getKernelID_arith());
    269         b.addKernel(node4.getKernelID_arith());
    270         b.addKernel(node5.getKernelID_arith());
    271 
    272         b.addConnection(connect, node1.getKernelID_arith(), node2.getKernelID_arith());
    273         b.addConnection(connect, node1.getKernelID_arith(), node3.getFieldID_arith_rs_input());
    274         b.addConnection(connect, node2.getKernelID_arith(), node4.getFieldID_arith_rs_input());
    275         b.addConnection(connect, node3.getKernelID_arith(), node4.getKernelID_arith());
    276         b.addConnection(connect, node4.getKernelID_arith(), node5.getKernelID_arith());
    277 
    278         group = b.create();
    279         group.setInput(node1.getKernelID_arith(), in1);
    280         group.setInput(node3.getKernelID_arith(), in2);
    281 
    282         group.setOutput(node5.getKernelID_arith(), out);
    283 
    284         group.execute();
    285 
    286         mRS.finish();
    287 
    288         compare.set_compare_value(2);
    289         compare.forEach_compare(out);
    290         compare.forEach_getCompareResult(resultAlloc);
    291         resultAlloc.copyTo(result);
    292 
    293         node1.destroy();
    294         node2.destroy();
    295         node3.destroy();
    296         node4.destroy();
    297         node5.destroy();
    298         in1.destroy();
    299         in2.destroy();
    300         out.destroy();
    301         resultAlloc.destroy();
    302 
    303         assertTrue(result[0] == 2);
    304     }
    305 
    306     /**
    307      * Tests a case where a shared global variable is updated by the first kernel in a group,
    308      * but then read by a subsequent kernel.
    309      *
    310      * The test ensures that we don't accidentally apply any fusion optimizations to the kernel
    311      * pair, since there is a potential dependency that crosses the kernel cell boundary.
    312      */
    313     public void testScriptGroupSharedGlobal() {
    314         Type i32 = new Type.Builder(mRS, Element.I32(mRS)).setX(1).create();
    315         Type u32 = new Type.Builder(mRS, Element.U32(mRS)).setX(2).create();
    316 
    317         Allocation aFailed = Allocation.createTyped(mRS, i32);
    318         Allocation aSharedInt = Allocation.createTyped(mRS, i32);
    319 
    320         ScriptC_group1 mG1 = new ScriptC_group1(mRS);
    321         ScriptC_group2 mG2 = new ScriptC_group2(mRS);
    322 
    323         mG1.set_aSharedInt(aSharedInt);
    324         mG2.set_aSharedInt(aSharedInt);
    325         mG2.set_aFailed(aFailed);
    326 
    327         int [] Failed = new int [1];
    328         Failed[0] = 0;
    329         aFailed.copyFrom(Failed);
    330 
    331         ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
    332 
    333         // Writes to aSharedInt[x] in the kernel.
    334         b.addKernel(mG1.getKernelID_setSharedInt());
    335         // Reads aSharedInt[1] to verify it is -5.
    336         b.addKernel(mG2.getKernelID_getSharedInt());
    337         // If we fuse mG1/mG2, we won't see the update to the aSharedInt[1] during mG2 for x == 0.
    338         // The update is only visible if we correctly identify the dependency and execute all of
    339         // mG1 before starting on mG2.
    340         b.addConnection(u32, mG1.getKernelID_setSharedInt(), mG2.getKernelID_getSharedInt());
    341         ScriptGroup group = b.create();
    342         group.execute();
    343 
    344         mG2.invoke_verify();
    345         aFailed.copyTo(Failed);
    346         if (Failed[0] != 0) {
    347             FoundError = true;
    348         }
    349 
    350         aFailed.destroy();
    351         aSharedInt.destroy();
    352         mG1.destroy();
    353         mG2.destroy();
    354         group.destroy();
    355 
    356         checkForErrors();
    357     }
    358 
    359     /**
    360      * Tests that kernel-to-kernel dependency via input/output is handled correctly
    361      */
    362     public void testBuilder2PointWiseKernelToKernelDependency() {
    363         ScriptC_increment s_inc = new ScriptC_increment(mRS);
    364         ScriptC_double s_double = new ScriptC_double(mRS);
    365         mRS.setMessageHandler(mRsMessage);
    366 
    367         int[] array = new int[ARRAY_SIZE * 4];
    368 
    369         for (int i = 0; i < ARRAY_SIZE * 4; i++) {
    370             array[i] = i;
    371         }
    372 
    373         Allocation input = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE);
    374         input.copyFrom(array);
    375 
    376         ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS);
    377 
    378         ScriptGroup.Input unbound = builder.addInput();
    379 
    380         Type connectType = Type.createX(mRS, Element.I32_4(mRS), ARRAY_SIZE);
    381 
    382         ScriptGroup.Closure c0 =
    383                 builder.addKernel(s_inc.getKernelID_increment(),
    384                                   connectType,
    385                                   unbound);
    386 
    387         ScriptGroup.Closure c1 =
    388                 builder.addKernel(s_double.getKernelID_doubleKernel(),
    389                                   connectType,
    390                                   c0.getReturn());
    391 
    392         ScriptGroup group = builder.create("IncAndDbl", c1.getReturn());
    393 
    394         int[] a = new int[ARRAY_SIZE * 4];
    395         ((Allocation)group.execute(input)[0]).copyTo(a);
    396 
    397         mRS.finish();
    398 
    399         input.destroy();
    400         group.destroy();
    401 
    402         boolean failed = false;
    403         for (int i = 0; i < ARRAY_SIZE * 4; i++) {
    404             if (a[i] != (i+1) * 2) {
    405                 Log.e(TAG, "a["+i+"]="+a[i]+", should be "+ ((i+1) * 2));
    406                 failed = true;
    407             }
    408         }
    409 
    410         assertTrue(!failed);
    411     }
    412 
    413     /**
    414      * Tests that kernel-to-kernel dependency via global allocations is handled correctly
    415      */
    416     public void testBuilder2GatherScatterAcrossKernelsViaGlobals() {
    417         ScriptC_reduction s = new ScriptC_reduction(mRS);
    418 
    419         int[] array = new int[ARRAY_SIZE * 4];
    420 
    421         for (int i = 0; i < ARRAY_SIZE; i++) {
    422             array[i*4] = i * 7;
    423             array[i*4 + 1] = i * 7;
    424             array[i*4 + 2] = i * 7;
    425             array[i*4 + 3] = i * 7;
    426         }
    427 
    428         Allocation input = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE);
    429         input.copyFrom(array);
    430 
    431         ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS);
    432 
    433         ScriptGroup.Input unbound = builder.addInput();
    434 
    435         ScriptGroup.Closure c = null;
    436         ScriptGroup.Binding b2 = new ScriptGroup.Binding(s.getFieldID_a(), unbound);
    437         for (int stride = ARRAY_SIZE / 2; stride >= 1; stride >>= 1) {
    438             ScriptGroup.Binding b1 = new ScriptGroup.Binding(s.getFieldID_reduction_stride(),
    439                                                              stride);
    440             c = builder.addKernel(s.getKernelID_add(),
    441                                   Type.createX(mRS, Element.I32_4(mRS), stride),
    442                                   b1, b2);
    443             b2 = new ScriptGroup.Binding(s.getFieldID_a(), c.getReturn());
    444         }
    445 
    446         if (c == null) {
    447             return;
    448         }
    449 
    450         ScriptGroup group = builder.create("Summation", c.getReturn());
    451 
    452         int[] a = new int[4];
    453         ((Allocation)group.execute(input)[0]).copyTo(a);
    454 
    455         mRS.finish();
    456 
    457         input.destroy();
    458         group.destroy();
    459 
    460         boolean failed = false;
    461         for (int i = 0; i < 4; i++) {
    462             if (failed == false && a[i] != ARRAY_SIZE * (ARRAY_SIZE - 1) * 7 / 2) {
    463                 Log.e(TAG,
    464                       "a["+i+"]="+a[i]+", should be "+ (ARRAY_SIZE * (ARRAY_SIZE - 1) * 7 / 2));
    465                 failed = true;
    466             }
    467         }
    468 
    469         assertTrue(!failed);
    470     }
    471 
    472     /**
    473      * Tests that the kernel output to a global can be used as a future
    474      */
    475     public void testBuilder2KernelOutputToGlobal() {
    476         ScriptC_reduction s = new ScriptC_reduction(mRS);
    477 
    478         int[] array = new int[ARRAY_SIZE * 4];
    479 
    480         for (int i = 0; i < ARRAY_SIZE; i++) {
    481             array[i*4] = i;
    482             array[i*4 + 1] = i;
    483             array[i*4 + 2] = i;
    484             array[i*4 + 3] = i;
    485         }
    486 
    487         Allocation input = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE);
    488         input.copyFrom(array);
    489         Allocation input1 = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE);
    490 
    491         ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS);
    492 
    493         ScriptGroup.Input unbound = builder.addInput();
    494 
    495         ScriptGroup.Closure c = null;
    496         ScriptGroup.Binding b2 = new ScriptGroup.Binding(s.getFieldID_a(), unbound);
    497         for (int stride = ARRAY_SIZE / 2; stride >= 1; stride >>= 1) {
    498             ScriptGroup.Binding b1 = new ScriptGroup.Binding(s.getFieldID_reduction_stride(),
    499                                                              stride);
    500             c = builder.addKernel(s.getKernelID_add2(),
    501                                   Type.createX(mRS, Element.I32_4(mRS), stride),
    502                                   b1, b2);
    503             b2 = new ScriptGroup.Binding(s.getFieldID_a(),
    504                                          c.getGlobal(s.getFieldID_a()));
    505         }
    506 
    507         if (c == null) {
    508             return;
    509         }
    510 
    511         ScriptGroup group = builder.create("SummationGlobal", c.getGlobal(s.getFieldID_a()));
    512 
    513         int[] a = new int[4 * ARRAY_SIZE];
    514         ((Allocation)group.execute(input, input1)[0]).copyTo(a);
    515 
    516         mRS.finish();
    517 
    518         input.destroy();
    519         input1.destroy();
    520         group.destroy();
    521 
    522         boolean failed = false;
    523         for (int i = 0; i < 4; i++) {
    524             if (failed == false && a[i] != ARRAY_SIZE * (ARRAY_SIZE - 1) / 2) {
    525                 Log.e(TAG,
    526                       "a["+i+"]="+a[i]+", should be "+ (ARRAY_SIZE * (ARRAY_SIZE - 1) / 2));
    527                 failed = true;
    528             }
    529         }
    530 
    531         assertTrue(!failed);
    532     }
    533 
    534     /**
    535      * Tests that invoke-to-kernel dependency is handled correctly
    536      */
    537     public void testBuilder2InvokeToKernelDependency() {
    538         ScriptC_matrix s = new ScriptC_matrix(mRS);
    539 
    540         float[] array = new float[ARRAY_SIZE * 4];
    541 
    542         for (int i = 0; i < ARRAY_SIZE; i++) {
    543             array[i * 4] = i * 4 * 7;
    544             array[i * 4 + 1] = (i * 4 + 1) * 7;
    545             array[i * 4 + 2] = (i * 4 + 2) * 7;
    546             array[i * 4 + 3] = (i * 4 + 3) * 7;
    547         }
    548 
    549         Allocation input = Allocation.createSized(mRS, Element.F32_4(mRS), ARRAY_SIZE);
    550         input.copyFrom(array);
    551 
    552         ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS);
    553 
    554         ScriptGroup.Input unbound = builder.addInput();
    555 
    556         Matrix4f mat = new Matrix4f();
    557 
    558         mat.set(0, 0, 0.0f);
    559         mat.set(0, 1, 0.0f);
    560         mat.set(0, 2, 0.0f);
    561         mat.set(0, 3, 1.0f);
    562 
    563         mat.set(1, 0, 1.0f);
    564         mat.set(1, 1, 0.0f);
    565         mat.set(1, 2, 0.0f);
    566         mat.set(1, 3, 0.0f);
    567 
    568         mat.set(2, 0, 0.0f);
    569         mat.set(2, 1, 1.0f);
    570         mat.set(2, 2, 0.0f);
    571         mat.set(2, 3, 0.0f);
    572 
    573         mat.set(3, 0, 0.0f);
    574         mat.set(3, 1, 0.0f);
    575         mat.set(3, 2, 1.0f);
    576         mat.set(3, 3, 0.0f);
    577 
    578         ScriptGroup.Closure c1 =
    579                 builder.addInvoke(s.getInvokeID_setMatrix(), mat);
    580 
    581         ScriptGroup.Closure c2 =
    582                 builder.addKernel(s.getKernelID_multiply(),
    583                                   Type.createX(mRS, Element.F32_4(mRS), ARRAY_SIZE),
    584                                   unbound);
    585 
    586         ScriptGroup group = builder.create("Multiply", c2.getReturn());
    587 
    588         float[] a = new float[ARRAY_SIZE * 4];
    589         ((Allocation)group.execute(input)[0]).copyTo(a);
    590 
    591         mRS.finish();
    592 
    593         input.destroy();
    594         group.destroy();
    595 
    596         boolean failed = false;
    597         for (int i = 0; i < ARRAY_SIZE; i++) {
    598             for (int j = 0; j < 4; j++) {
    599                 float expected = (i*4+((j+1)%4))*7;
    600                 if (failed == false && a[i * 4 + j] != expected) {
    601                     Log.e(TAG, "a["+i+"]="+a[i]+", should be "+ expected);
    602                     failed = true;
    603                 }
    604             }
    605         }
    606 
    607         assertTrue(!failed);
    608     }
    609 }
    610