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 setUp()34 protected void setUp() throws Exception { 35 super.setUp(); 36 mRS = RenderScript.create(mCtx); 37 mRS.setMessageHandler(mRsMessage); 38 } 39 40 @Override tearDown()41 protected void tearDown() throws Exception { 42 super.tearDown(); 43 } 44 checkArray(float[] ref, float[] out, int height, int refStride, int outStride, float ulpCount)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 checkArray(int[] ref, int[] out, int height, int refStride, int outStride)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 getElement(RenderScript rs, Element.DataType dataType, int size)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 createRandomAllocation(RenderScript rs, Element.DataType dataType, int size, long seed, boolean includeExtremes)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 createRandomFloatAllocation(RenderScript rs, Element.DataType dataType, int size, long seed, double minValue, double maxValue)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 createRandomIntegerAllocation(RenderScript rs, Element.DataType dataType, int size, long seed, boolean signed, int numberOfBits)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 enforceOrdering( Allocation minAlloc, Allocation maxAlloc)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 forEach(int testId, Allocation mIn, Allocation mOut)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 forEach(int testId, Allocation mIn)412 public void forEach(int testId, Allocation mIn) throws RSRuntimeException { 413 // Intentionally empty... subclass will likely define only one, but not both 414 } 415 appendVariableToMessage(StringBuilder message, int value)416 protected void appendVariableToMessage(StringBuilder message, int value) { 417 message.append(String.format("%d {%x}", value, value)); 418 } 419 appendVariableToMessage(StringBuilder message, float value)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 appendVariableToMessage(StringBuilder message, double value)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 appendVariableToMessage(StringBuilder message, Target.Floaty value)430 protected void appendVariableToMessage(StringBuilder message, Target.Floaty value) { 431 message.append(value.toString()); 432 } 433 } 434