Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2011 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.renderscript.RenderScript;
     20 import android.renderscript.Allocation;
     21 import android.renderscript.Element;
     22 import android.renderscript.RSRuntimeException;
     23 import android.util.Log;
     24 
     25 /**
     26  * Base RenderScript test class. This class provides a message handler and a
     27  * convenient way to wait for compute scripts to complete their execution.
     28  */
     29 public class RSBaseCompute extends RSBase {
     30     RenderScript mRS;
     31     protected int INPUTSIZE = 512;
     32 
     33     @Override
     34     protected void setUp() throws Exception {
     35         super.setUp();
     36         mRS = RenderScript.create(mCtx);
     37         mRS.setMessageHandler(mRsMessage);
     38     }
     39 
     40     @Override
     41     protected void tearDown() throws Exception {
     42         super.tearDown();
     43     }
     44 
     45     public void checkArray(float[] ref, float[] out, int height, int refStride,
     46              int outStride, float ulpCount) {
     47         int minStride = refStride > outStride ? outStride : refStride;
     48         for (int i = 0; i < height; i++) {
     49             for (int j = 0; j < minStride; j++) {
     50                 int refIdx = i * refStride + j;
     51                 int outIdx = i * outStride + j;
     52                 float ulp = Math.ulp(ref[refIdx]) * ulpCount;
     53                 assertEquals("Incorrect value @ idx = " + i + " |",
     54                         ref[refIdx],
     55                         out[outIdx],
     56                         ulp);
     57             }
     58         }
     59     }
     60 
     61     public void checkArray(int[] ref, int[] out, int height, int refStride,
     62              int outStride) {
     63         int minStride = refStride > outStride ? outStride : refStride;
     64         for (int i = 0; i < height; i++) {
     65             for (int j = 0; j < minStride; j++) {
     66                 int refIdx = i * refStride + j;
     67                 int outIdx = i * outStride + j;
     68                 assertEquals("Incorrect value @ idx = " + i + " |",
     69                         ref[refIdx],
     70                         out[outIdx]);
     71             }
     72         }
     73     }
     74 
     75     // TODO Is there a better way to do this
     76     protected Element getElement(RenderScript rs, Element.DataType dataType, int size) {
     77         Element element = null;
     78         if (size == 1) {
     79             if (dataType == Element.DataType.FLOAT_64) {
     80                 element = Element.F64(rs);
     81             } else if (dataType == Element.DataType.FLOAT_32) {
     82                 element = Element.F32(rs);
     83             } else if (dataType == Element.DataType.FLOAT_16) {
     84                 element = Element.F16(rs);
     85             } else if (dataType == Element.DataType.SIGNED_64) {
     86                 element = Element.I64(rs);
     87             } else if (dataType == Element.DataType.UNSIGNED_64) {
     88                 element = Element.U64(rs);
     89             } else if (dataType == Element.DataType.SIGNED_32) {
     90                 element = Element.I32(rs);
     91             } else if (dataType == Element.DataType.UNSIGNED_32) {
     92                 element = Element.U32(rs);
     93             } else if (dataType == Element.DataType.SIGNED_16) {
     94                 element = Element.I16(rs);
     95             } else if (dataType == Element.DataType.UNSIGNED_16) {
     96                 element = Element.U16(rs);
     97             } else if (dataType == Element.DataType.SIGNED_8) {
     98                 element = Element.I8(rs);
     99             } else if (dataType == Element.DataType.UNSIGNED_8) {
    100                 element = Element.U8(rs);
    101             } else {
    102                 android.util.Log.e("RenderscriptCTS", "Don't know how to create allocation of type" +
    103                         dataType.toString());
    104             }
    105         } else {
    106             element = Element.createVector(rs, dataType, size);
    107         }
    108         return element;
    109     }
    110 
    111     protected Allocation createRandomAllocation(RenderScript rs, Element.DataType dataType,
    112             int size, long seed, boolean includeExtremes) {
    113         Element element = getElement(rs, dataType, size);
    114         Allocation alloc = Allocation.createSized(rs, element, INPUTSIZE);
    115         int width = (size == 3) ? 4 : size;
    116         if (dataType == Element.DataType.FLOAT_64) {
    117             double[] inArray = new double[INPUTSIZE * width];
    118             // TODO The ranges for float is too small.  We need to accept a wider range of values.
    119             double min = -4.0 * Math.PI;
    120             double max = 4.0 * Math.PI;
    121             RSUtils.genRandomDoubles(seed, min, max, inArray, includeExtremes);
    122             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    123         } else if (dataType == Element.DataType.FLOAT_32) {
    124             float[] inArray = new float[INPUTSIZE * width];
    125             // TODO The ranges for float is too small.  We need to accept a wider range of values.
    126             float min = -4.0f * (float) Math.PI;
    127             float max = 4.0f * (float) Math.PI;
    128             RSUtils.genRandomFloats(seed, min, max, inArray, includeExtremes);
    129             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    130         } else if (dataType == Element.DataType.FLOAT_16) {
    131             short[] inArray = new short[INPUTSIZE * width];
    132             double min = -4.0 * Math.PI;
    133             double max = 4.0 * Math.PI;
    134             RSUtils.genRandomFloat16s(seed, min, max, inArray, includeExtremes);
    135             alloc.copyFrom(inArray);
    136         } else if (dataType == Element.DataType.SIGNED_64) {
    137             long[] inArray = new long[INPUTSIZE * width];
    138             RSUtils.genRandomLongs(seed, inArray, true, 63);
    139             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    140         } else if (dataType == Element.DataType.UNSIGNED_64) {
    141             long[] inArray = new long[INPUTSIZE * width];
    142             RSUtils.genRandomLongs(seed, inArray, false, 64);
    143             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    144         } else if (dataType == Element.DataType.SIGNED_32) {
    145             int[] inArray = new int[INPUTSIZE * width];
    146             RSUtils.genRandomInts(seed, inArray, true, 31);
    147             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    148         } else if (dataType == Element.DataType.UNSIGNED_32) {
    149             int[] inArray = new int[INPUTSIZE * width];
    150             RSUtils.genRandomInts(seed, inArray, false, 32);
    151             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    152         } else if (dataType == Element.DataType.SIGNED_16) {
    153             short[] inArray = new short[INPUTSIZE * width];
    154             RSUtils.genRandomShorts(seed, inArray, true, 15);
    155             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    156         } else if (dataType == Element.DataType.UNSIGNED_16) {
    157             short[] inArray = new short[INPUTSIZE * width];
    158             RSUtils.genRandomShorts(seed, inArray, false, 16);
    159             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    160         } else if (dataType == Element.DataType.SIGNED_8) {
    161             byte[] inArray = new byte[INPUTSIZE * width];
    162             RSUtils.genRandomBytes(seed, inArray, true, 7);
    163             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    164         } else if (dataType == Element.DataType.UNSIGNED_8) {
    165             byte[] inArray = new byte[INPUTSIZE * width];
    166             RSUtils.genRandomBytes(seed, inArray, true, 8);
    167             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    168         } else {
    169             android.util.Log.e("RenderscriptCTS", "Don't know how to create allocation of type" +
    170                     dataType.toString());
    171         }
    172         return alloc;
    173     }
    174 
    175     protected Allocation createRandomFloatAllocation(RenderScript rs, Element.DataType dataType,
    176             int size, long seed, double minValue, double maxValue) {
    177         Element element = getElement(rs, dataType, size);
    178         Allocation alloc = Allocation.createSized(rs, element, INPUTSIZE);
    179         int width = (size == 3) ? 4 : size;
    180         if (dataType == Element.DataType.FLOAT_64) {
    181             double[] inArray = new double[INPUTSIZE * width];
    182             RSUtils.genRandomDoubles(seed, minValue, maxValue, inArray, false);
    183             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    184         } else if (dataType == Element.DataType.FLOAT_32) {
    185             float[] inArray = new float[INPUTSIZE * width];
    186             RSUtils.genRandomFloats(seed, (float) minValue, (float) maxValue, inArray, false);
    187             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    188         } else if (dataType == Element.DataType.FLOAT_16) {
    189             short[] inArray = new short[INPUTSIZE * width];
    190             RSUtils.genRandomFloat16s(seed, minValue, maxValue, inArray, false);
    191             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    192         } else {
    193             android.util.Log.e("RenderscriptCTS",
    194                                "Don't know how to create a random float allocation for " +
    195                                            dataType.toString());
    196         }
    197         return alloc;
    198     }
    199 
    200     protected Allocation createRandomIntegerAllocation(RenderScript rs, Element.DataType dataType,
    201             int size, long seed, boolean signed, int numberOfBits) {
    202         Element element = getElement(rs, dataType, size);
    203         Allocation alloc = Allocation.createSized(rs, element, INPUTSIZE);
    204         int width = (size == 3) ? 4 : size;
    205         if (dataType == Element.DataType.SIGNED_64 ||
    206                 dataType == Element.DataType.UNSIGNED_64) {
    207             long[] inArray = new long[INPUTSIZE * width];
    208             RSUtils.genRandomLongs(seed, inArray, signed, numberOfBits);
    209             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    210         } else
    211         if (dataType == Element.DataType.SIGNED_32 ||
    212                 dataType == Element.DataType.UNSIGNED_32) {
    213             int[] inArray = new int[INPUTSIZE * width];
    214             RSUtils.genRandomInts(seed, inArray, signed, numberOfBits);
    215             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    216         } else if (dataType == Element.DataType.SIGNED_16 ||
    217                 dataType == Element.DataType.UNSIGNED_16) {
    218             short[] inArray = new short[INPUTSIZE * width];
    219             RSUtils.genRandomShorts(seed, inArray, signed, numberOfBits);
    220             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    221         } else if (dataType == Element.DataType.SIGNED_8 ||
    222                 dataType == Element.DataType.UNSIGNED_8) {
    223             byte[] inArray = new byte[INPUTSIZE * width];
    224             RSUtils.genRandomBytes(seed, inArray, signed, numberOfBits);
    225             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
    226         } else {
    227             android.util.Log.e("RenderscriptCTS",
    228                                "Don't know how to create an integer allocation of type" +
    229                                            dataType.toString());
    230         }
    231         return alloc;
    232     }
    233 
    234     protected <T> void enforceOrdering(/*RenderScript rs,*/ Allocation minAlloc, Allocation maxAlloc) {
    235         Element element = minAlloc.getElement();
    236         int stride = element.getVectorSize();
    237         if (stride == 3) {
    238             stride = 4;
    239         }
    240         int size = INPUTSIZE * stride;
    241         Element.DataType dataType = element.getDataType();
    242         if (dataType == Element.DataType.FLOAT_64) {
    243             double[] minArray = new double[size];
    244             double[] maxArray = new double[size];
    245             minAlloc.copyTo(minArray);
    246             maxAlloc.copyTo(maxArray);
    247             for (int i = 0; i < size; i++) {
    248                 if (minArray[i] > maxArray[i]) {
    249                     double temp = minArray[i];
    250                     minArray[i] = maxArray[i];
    251                     maxArray[i] = temp;
    252                 }
    253             }
    254             minAlloc.copyFrom(minArray);
    255             maxAlloc.copyFrom(maxArray);
    256         } else
    257         if (dataType == Element.DataType.FLOAT_32) {
    258             float[] minArray = new float[size];
    259             float[] maxArray = new float[size];
    260             minAlloc.copyTo(minArray);
    261             maxAlloc.copyTo(maxArray);
    262             for (int i = 0; i < size; i++) {
    263                 if (minArray[i] > maxArray[i]) {
    264                     float temp = minArray[i];
    265                     minArray[i] = maxArray[i];
    266                     maxArray[i] = temp;
    267                 }
    268             }
    269             minAlloc.copyFrom(minArray);
    270             maxAlloc.copyFrom(maxArray);
    271         } else if (dataType == Element.DataType.FLOAT_16) {
    272             short[] minArray = new short[size];
    273             short[] maxArray = new short[size];
    274             minAlloc.copyTo(minArray);
    275             maxAlloc.copyTo(maxArray);
    276             for (int i = 0; i < size; i++) {
    277                 double minValue = Float16Utils.convertFloat16ToDouble(minArray[i]);
    278                 double maxValue = Float16Utils.convertFloat16ToDouble(maxArray[i]);
    279                 if (minValue > maxValue) {
    280                     short temp = minArray[i];
    281                     minArray[i] = maxArray[i];
    282                     maxArray[i] = temp;
    283                 }
    284             }
    285             minAlloc.copyFrom(minArray);
    286             maxAlloc.copyFrom(maxArray);
    287         } else if (dataType == Element.DataType.SIGNED_64) {
    288             long[] minArray = new long[size];
    289             long[] maxArray = new long[size];
    290             minAlloc.copyTo(minArray);
    291             maxAlloc.copyTo(maxArray);
    292             for (int i = 0; i < size; i++) {
    293                 if (minArray[i] > maxArray[i]) {
    294                     long temp = minArray[i];
    295                     minArray[i] = maxArray[i];
    296                     maxArray[i] = temp;
    297                 }
    298             }
    299             minAlloc.copyFrom(minArray);
    300             maxAlloc.copyFrom(maxArray);
    301         } else if (dataType == Element.DataType.UNSIGNED_64) {
    302             long[] minArray = new long[size];
    303             long[] maxArray = new long[size];
    304             minAlloc.copyTo(minArray);
    305             maxAlloc.copyTo(maxArray);
    306             for (int i = 0; i < size; i++) {
    307                 if (RSUtils.compareUnsignedLong(minArray[i], maxArray[i]) > 0) {
    308                     long temp = minArray[i];
    309                     minArray[i] = maxArray[i];
    310                     maxArray[i] = temp;
    311                 }
    312             }
    313             minAlloc.copyFrom(minArray);
    314             maxAlloc.copyFrom(maxArray);
    315         } else if (dataType == Element.DataType.SIGNED_32) {
    316             int[] minArray = new int[size];
    317             int[] maxArray = new int[size];
    318             minAlloc.copyTo(minArray);
    319             maxAlloc.copyTo(maxArray);
    320             for (int i = 0; i < size; i++) {
    321                 if (minArray[i] > maxArray[i]) {
    322                     int temp = minArray[i];
    323                     minArray[i] = maxArray[i];
    324                     maxArray[i] = temp;
    325                 }
    326             }
    327             minAlloc.copyFrom(minArray);
    328             maxAlloc.copyFrom(maxArray);
    329         } else if (dataType == Element.DataType.UNSIGNED_32) {
    330             int[] minArray = new int[size];
    331             int[] maxArray = new int[size];
    332             minAlloc.copyTo(minArray);
    333             maxAlloc.copyTo(maxArray);
    334             for (int i = 0; i < size; i++) {
    335                 long min = minArray[i] &0xffffffffl;
    336                 long max = maxArray[i] &0xffffffffl;
    337                 if (min > max) {
    338                     minArray[i] = (int) max;
    339                     maxArray[i] = (int) min;
    340                 }
    341             }
    342             minAlloc.copyFrom(minArray);
    343             maxAlloc.copyFrom(maxArray);
    344         } else if (dataType == Element.DataType.SIGNED_16) {
    345             short[] minArray = new short[size];
    346             short[] maxArray = new short[size];
    347             minAlloc.copyTo(minArray);
    348             maxAlloc.copyTo(maxArray);
    349             for (int i = 0; i < size; i++) {
    350                 if (minArray[i] > maxArray[i]) {
    351                     short temp = minArray[i];
    352                     minArray[i] = maxArray[i];
    353                     maxArray[i] = temp;
    354                 }
    355             }
    356             minAlloc.copyFrom(minArray);
    357             maxAlloc.copyFrom(maxArray);
    358         } else if (dataType == Element.DataType.UNSIGNED_16) {
    359             short[] minArray = new short[size];
    360             short[] maxArray = new short[size];
    361             minAlloc.copyTo(minArray);
    362             maxAlloc.copyTo(maxArray);
    363             for (int i = 0; i < size; i++) {
    364                 int min = minArray[i] &0xffff;
    365                 int max = maxArray[i] &0xffff;
    366                 if (min > max) {
    367                     minArray[i] = (short) max;
    368                     maxArray[i] = (short) min;
    369                 }
    370             }
    371             minAlloc.copyFrom(minArray);
    372             maxAlloc.copyFrom(maxArray);
    373         } else if (dataType == Element.DataType.SIGNED_8) {
    374             byte[] minArray = new byte[size];
    375             byte[] maxArray = new byte[size];
    376             minAlloc.copyTo(minArray);
    377             maxAlloc.copyTo(maxArray);
    378             for (int i = 0; i < size; i++) {
    379                 if (minArray[i] > maxArray[i]) {
    380                     byte temp = minArray[i];
    381                     minArray[i] = maxArray[i];
    382                     maxArray[i] = temp;
    383                 }
    384             }
    385             minAlloc.copyFrom(minArray);
    386             maxAlloc.copyFrom(maxArray);
    387         } else if (dataType == Element.DataType.UNSIGNED_8) {
    388             byte[] minArray = new byte[size];
    389             byte[] maxArray = new byte[size];
    390             minAlloc.copyTo(minArray);
    391             maxAlloc.copyTo(maxArray);
    392             for (int i = 0; i < size; i++) {
    393                 int min = minArray[i] &0xff;
    394                 int max = maxArray[i] &0xff;
    395                 if (min > max) {
    396                     minArray[i] = (byte) max;
    397                     maxArray[i] = (byte) min;
    398                 }
    399             }
    400             minAlloc.copyFrom(minArray);
    401             maxAlloc.copyFrom(maxArray);
    402         } else {
    403             android.util.Log.e("RenderscriptCTS", "Ordering not supported for " +
    404                     dataType.toString());
    405         }
    406     }
    407 
    408     public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
    409         // Intentionally empty... subclass will likely define only one, but not both
    410     }
    411 
    412     public void forEach(int testId, Allocation mIn) throws RSRuntimeException {
    413         // Intentionally empty... subclass will likely define only one, but not both
    414     }
    415 
    416     protected void appendVariableToMessage(StringBuilder message, int value) {
    417         message.append(String.format("%d {%x}", value, value));
    418     }
    419 
    420     protected void appendVariableToMessage(StringBuilder message, float value) {
    421         message.append(String.format("%14.8g {%8x} %15a", value,
    422                         Float.floatToRawIntBits(value), value));
    423     }
    424 
    425     protected void appendVariableToMessage(StringBuilder message, double value) {
    426         message.append(String.format("%24.8g {%16x} %31a", value,
    427                         Double.doubleToRawLongBits(value), value));
    428     }
    429 
    430     protected void appendVariableToMessage(StringBuilder message, Target.Floaty value) {
    431         message.append(value.toString());
    432     }
    433 }
    434