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 testScriptGroupSingleKernel()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 testScriptGroupDisconnectedKernel()71 public void testScriptGroupDisconnectedKernel() { 72 ScriptGroup group; 73 74 Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create(); 75 76 ScriptIntrinsicColorMatrix mColorMatrix, mColorMatrix2; 77 78 mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); 79 mColorMatrix2 = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); 80 81 Allocation a1_copy, a2_copy; 82 83 a1_copy = Allocation.createTyped(mRS, connect); 84 a2_copy = Allocation.createTyped(mRS, connect); 85 86 Matrix4f m = new Matrix4f(); 87 m.set(1, 0, 0.2f); 88 m.set(1, 1, 0.9f); 89 m.set(1, 2, 0.2f); 90 mColorMatrix.setColorMatrix(m); 91 mColorMatrix2.setColorMatrix(m); 92 93 ScriptGroup.Builder b = new ScriptGroup.Builder(mRS); 94 b.addKernel(mColorMatrix.getKernelID()); 95 b.addKernel(mColorMatrix2.getKernelID()); 96 try { 97 group = b.create(); 98 fail("should throw RSInvalidStateException."); 99 } catch (RSInvalidStateException e) { 100 101 } 102 } 103 104 testScriptGroupFieldConnection()105 public void testScriptGroupFieldConnection() { 106 ScriptGroup group; 107 108 Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create(); 109 110 ScriptIntrinsicConvolve3x3 mConvolve3x3; 111 ScriptIntrinsicColorMatrix mColorMatrix; 112 113 mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS)); 114 mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); 115 116 Allocation a1_copy, a2_copy; 117 a1_copy = Allocation.createTyped(mRS, connect); 118 a2_copy = Allocation.createTyped(mRS, connect); 119 120 float f[] = new float[9]; 121 f[0] = 0.f; f[1] = -1.f; f[2] = 0.f; 122 f[3] = -1.f; f[4] = 5.f; f[5] = -1.f; 123 f[6] = 0.f; f[7] = -1.f; f[8] = 0.f; 124 125 mConvolve3x3.setCoefficients(f); 126 127 Matrix4f m = new Matrix4f(); 128 m.set(1, 0, 0.2f); 129 m.set(1, 1, 0.9f); 130 m.set(1, 2, 0.2f); 131 mColorMatrix.setColorMatrix(m); 132 133 ScriptGroup.Builder b = new ScriptGroup.Builder(mRS); 134 b.addKernel(mColorMatrix.getKernelID()); 135 b.addKernel(mConvolve3x3.getKernelID()); 136 b.addConnection(connect, mColorMatrix.getKernelID(), mConvolve3x3.getFieldID_Input()); 137 group = b.create(); 138 139 group.setInput(mColorMatrix.getKernelID(), a1_copy); 140 group.setOutput(mConvolve3x3.getKernelID(), a2_copy); 141 142 group.execute(); 143 144 } 145 testScriptGroupDisconnectedDAG()146 public void testScriptGroupDisconnectedDAG() { 147 ScriptGroup group; 148 149 Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(bDimX).setY(bDimY).create(); 150 151 ScriptIntrinsicConvolve3x3 mConvolve3x3, mConvolve3x32; 152 ScriptIntrinsicColorMatrix mColorMatrix, mColorMatrix2; 153 154 mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS)); 155 mConvolve3x32 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS)); 156 mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); 157 mColorMatrix2 = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS)); 158 159 Allocation a1_copy, a2_copy; 160 a1_copy = Allocation.createTyped(mRS, connect); 161 a2_copy = Allocation.createTyped(mRS, connect); 162 163 float f[] = new float[9]; 164 f[0] = 0.f; f[1] = -1.f; f[2] = 0.f; 165 f[3] = -1.f; f[4] = 5.f; f[5] = -1.f; 166 f[6] = 0.f; f[7] = -1.f; f[8] = 0.f; 167 168 mConvolve3x3.setCoefficients(f); 169 mConvolve3x32.setCoefficients(f); 170 171 Matrix4f m = new Matrix4f(); 172 m.set(1, 0, 0.2f); 173 m.set(1, 1, 0.9f); 174 m.set(1, 2, 0.2f); 175 mColorMatrix.setColorMatrix(m); 176 mColorMatrix2.setColorMatrix(m); 177 178 ScriptGroup.Builder b = new ScriptGroup.Builder(mRS); 179 b.addKernel(mColorMatrix.getKernelID()); 180 b.addKernel(mColorMatrix2.getKernelID()); 181 b.addKernel(mConvolve3x3.getKernelID()); 182 b.addKernel(mConvolve3x32.getKernelID()); 183 b.addConnection(connect, mColorMatrix.getKernelID(), mConvolve3x3.getFieldID_Input()); 184 b.addConnection(connect, mColorMatrix2.getKernelID(), mConvolve3x32.getFieldID_Input()); 185 try { 186 group = b.create(); 187 fail("RSInvalidStateException expected"); 188 } catch (RSInvalidStateException e) { 189 190 } 191 192 } 193 testScriptGroupTorture()194 public void testScriptGroupTorture() { 195 ScriptGroup group; 196 197 int[] result = new int[1]; 198 199 bDimX = 1; 200 201 Type connect = new Type.Builder(mRS, Element.I32(mRS)).setX(bDimX).create(); 202 Type compareType = new Type.Builder(mRS, Element.I32(mRS)).create(); 203 204 ScriptC_scriptgroup node1, node2, node3, node4, node5, compare; 205 node1 = new ScriptC_scriptgroup(mRS); 206 node2 = new ScriptC_scriptgroup(mRS); 207 node3 = new ScriptC_scriptgroup(mRS); 208 node4 = new ScriptC_scriptgroup(mRS); 209 node5 = new ScriptC_scriptgroup(mRS); 210 211 compare = new ScriptC_scriptgroup(mRS); 212 213 Allocation in1, in2, out, resultAlloc; 214 in1 = Allocation.createTyped(mRS, connect); 215 in2 = Allocation.createTyped(mRS, connect); 216 217 out = Allocation.createTyped(mRS, connect); 218 resultAlloc = Allocation.createTyped(mRS, compareType); 219 220 node1.set_memset_toValue(1); 221 node1.forEach_memset(in1); 222 node1.set_memset_toValue(2); 223 node1.forEach_memset(in2); 224 225 node1.set_arith_operation(2); 226 node2.set_arith_operation(1); 227 node3.set_arith_operation(0); 228 node4.set_arith_operation(0); 229 node5.set_arith_operation(1); 230 231 node3.set_arith_use_rs_allocation(1); 232 node4.set_arith_use_rs_allocation(1); 233 234 node1.set_arith_value(5); 235 node2.set_arith_value(3); 236 node5.set_arith_value(7); 237 238 ScriptGroup.Builder b = new ScriptGroup.Builder(mRS); 239 b.addKernel(node1.getKernelID_arith()); 240 b.addKernel(node2.getKernelID_arith()); 241 b.addKernel(node3.getKernelID_arith()); 242 b.addKernel(node4.getKernelID_arith()); 243 b.addKernel(node5.getKernelID_arith()); 244 245 b.addConnection(connect, node1.getKernelID_arith(), node2.getKernelID_arith()); 246 b.addConnection(connect, node1.getKernelID_arith(), node3.getFieldID_arith_rs_input()); 247 b.addConnection(connect, node2.getKernelID_arith(), node4.getFieldID_arith_rs_input()); 248 b.addConnection(connect, node3.getKernelID_arith(), node4.getKernelID_arith()); 249 b.addConnection(connect, node4.getKernelID_arith(), node5.getKernelID_arith()); 250 251 group = b.create(); 252 group.setInput(node1.getKernelID_arith(), in1); 253 group.setInput(node3.getKernelID_arith(), in2); 254 255 group.setOutput(node5.getKernelID_arith(), out); 256 257 group.execute(); 258 259 mRS.finish(); 260 261 compare.set_compare_value(2); 262 compare.forEach_compare(out); 263 compare.forEach_getCompareResult(resultAlloc); 264 resultAlloc.copyTo(result); 265 assertTrue(result[0] == 2); 266 } 267 268 /** 269 * Tests a case where a shared global variable is updated by the first kernel in a group, 270 * but then read by a subsequent kernel. 271 * 272 * The test ensures that we don't accidentally apply any fusion optimizations to the kernel 273 * pair, since there is a potential dependency that crosses the kernel cell boundary. 274 */ testScriptGroupSharedGlobal()275 public void testScriptGroupSharedGlobal() { 276 Type i32 = new Type.Builder(mRS, Element.I32(mRS)).setX(1).create(); 277 Type u32 = new Type.Builder(mRS, Element.U32(mRS)).setX(2).create(); 278 279 Allocation aFailed = Allocation.createTyped(mRS, i32); 280 Allocation aSharedInt = Allocation.createTyped(mRS, i32); 281 282 ScriptC_group1 mG1 = new ScriptC_group1(mRS); 283 ScriptC_group2 mG2 = new ScriptC_group2(mRS); 284 285 mG1.set_aSharedInt(aSharedInt); 286 mG2.set_aSharedInt(aSharedInt); 287 mG2.set_aFailed(aFailed); 288 289 int [] Failed = new int [1]; 290 Failed[0] = 0; 291 aFailed.copyFrom(Failed); 292 293 ScriptGroup.Builder b = new ScriptGroup.Builder(mRS); 294 295 // Writes to aSharedInt[x] in the kernel. 296 b.addKernel(mG1.getKernelID_setSharedInt()); 297 // Reads aSharedInt[1] to verify it is -5. 298 b.addKernel(mG2.getKernelID_getSharedInt()); 299 // If we fuse mG1/mG2, we won't see the update to the aSharedInt[1] during mG2 for x == 0. 300 // The update is only visible if we correctly identify the dependency and execute all of 301 // mG1 before starting on mG2. 302 b.addConnection(u32, mG1.getKernelID_setSharedInt(), mG2.getKernelID_getSharedInt()); 303 ScriptGroup group = b.create(); 304 group.execute(); 305 306 mG2.invoke_verify(); 307 aFailed.copyTo(Failed); 308 if (Failed[0] != 0) { 309 FoundError = true; 310 } 311 312 checkForErrors(); 313 } 314 315 /** 316 * Tests that kernel-to-kernel dependency via input/output is handled correctly 317 */ testBuilder2PointWiseKernelToKernelDependency()318 public void testBuilder2PointWiseKernelToKernelDependency() { 319 ScriptC_increment s_inc = new ScriptC_increment(mRS); 320 ScriptC_double s_double = new ScriptC_double(mRS); 321 mRS.setMessageHandler(mRsMessage); 322 323 int[] array = new int[ARRAY_SIZE * 4]; 324 325 for (int i = 0; i < ARRAY_SIZE * 4; i++) { 326 array[i] = i; 327 } 328 329 Allocation input = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE); 330 input.copyFrom(array); 331 332 ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS); 333 334 ScriptGroup.Input unbound = builder.addInput(); 335 336 Type connectType = Type.createX(mRS, Element.I32_4(mRS), ARRAY_SIZE); 337 338 ScriptGroup.Closure c0 = 339 builder.addKernel(s_inc.getKernelID_increment(), 340 connectType, 341 unbound); 342 343 ScriptGroup.Closure c1 = 344 builder.addKernel(s_double.getKernelID_doubleKernel(), 345 connectType, 346 c0.getReturn()); 347 348 ScriptGroup group = builder.create("IncAndDbl", c1.getReturn()); 349 350 int[] a = new int[ARRAY_SIZE * 4]; 351 ((Allocation)group.execute(input)[0]).copyTo(a); 352 353 mRS.finish(); 354 355 boolean failed = false; 356 for (int i = 0; i < ARRAY_SIZE * 4; i++) { 357 if (a[i] != (i+1) * 2) { 358 Log.e(TAG, "a["+i+"]="+a[i]+", should be "+ ((i+1) * 2)); 359 failed = true; 360 } 361 } 362 363 assertTrue(!failed); 364 } 365 366 /** 367 * Tests that kernel-to-kernel dependency via global allocations is handled correctly 368 */ testBuilder2GatherScatterAcrossKernelsViaGlobals()369 public void testBuilder2GatherScatterAcrossKernelsViaGlobals() { 370 ScriptC_reduction s = new ScriptC_reduction(mRS); 371 372 int[] array = new int[ARRAY_SIZE * 4]; 373 374 for (int i = 0; i < ARRAY_SIZE; i++) { 375 array[i*4] = i * 7; 376 array[i*4 + 1] = i * 7; 377 array[i*4 + 2] = i * 7; 378 array[i*4 + 3] = i * 7; 379 } 380 381 Allocation input = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE); 382 input.copyFrom(array); 383 384 ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS); 385 386 ScriptGroup.Input unbound = builder.addInput(); 387 388 ScriptGroup.Closure c = null; 389 ScriptGroup.Binding b2 = new ScriptGroup.Binding(s.getFieldID_a(), unbound); 390 for (int stride = ARRAY_SIZE / 2; stride >= 1; stride >>= 1) { 391 ScriptGroup.Binding b1 = new ScriptGroup.Binding(s.getFieldID_reduction_stride(), 392 stride); 393 c = builder.addKernel(s.getKernelID_add(), 394 Type.createX(mRS, Element.I32_4(mRS), stride), 395 b1, b2); 396 b2 = new ScriptGroup.Binding(s.getFieldID_a(), c.getReturn()); 397 } 398 399 if (c == null) { 400 return; 401 } 402 403 ScriptGroup group = builder.create("Summation", c.getReturn()); 404 405 int[] a = new int[4]; 406 ((Allocation)group.execute(input)[0]).copyTo(a); 407 408 mRS.finish(); 409 410 boolean failed = false; 411 for (int i = 0; i < 4; i++) { 412 if (failed == false && a[i] != ARRAY_SIZE * (ARRAY_SIZE - 1) * 7 / 2) { 413 Log.e(TAG, 414 "a["+i+"]="+a[i]+", should be "+ (ARRAY_SIZE * (ARRAY_SIZE - 1) * 7 / 2)); 415 failed = true; 416 } 417 } 418 419 assertTrue(!failed); 420 } 421 422 /** 423 * Tests that the kernel output to a global can be used as a future 424 */ testBuilder2KernelOutputToGlobal()425 public void testBuilder2KernelOutputToGlobal() { 426 ScriptC_reduction s = new ScriptC_reduction(mRS); 427 428 int[] array = new int[ARRAY_SIZE * 4]; 429 430 for (int i = 0; i < ARRAY_SIZE; i++) { 431 array[i*4] = i; 432 array[i*4 + 1] = i; 433 array[i*4 + 2] = i; 434 array[i*4 + 3] = i; 435 } 436 437 Allocation input = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE); 438 input.copyFrom(array); 439 Allocation input1 = Allocation.createSized(mRS, Element.I32_4(mRS), ARRAY_SIZE); 440 441 ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS); 442 443 ScriptGroup.Input unbound = builder.addInput(); 444 445 ScriptGroup.Closure c = null; 446 ScriptGroup.Binding b2 = new ScriptGroup.Binding(s.getFieldID_a(), unbound); 447 for (int stride = ARRAY_SIZE / 2; stride >= 1; stride >>= 1) { 448 ScriptGroup.Binding b1 = new ScriptGroup.Binding(s.getFieldID_reduction_stride(), 449 stride); 450 c = builder.addKernel(s.getKernelID_add2(), 451 Type.createX(mRS, Element.I32_4(mRS), stride), 452 b1, b2); 453 b2 = new ScriptGroup.Binding(s.getFieldID_a(), 454 c.getGlobal(s.getFieldID_a())); 455 } 456 457 if (c == null) { 458 return; 459 } 460 461 ScriptGroup group = builder.create("SummationGlobal", c.getGlobal(s.getFieldID_a())); 462 463 int[] a = new int[4 * ARRAY_SIZE]; 464 ((Allocation)group.execute(input, input1)[0]).copyTo(a); 465 466 mRS.finish(); 467 468 boolean failed = false; 469 for (int i = 0; i < 4; i++) { 470 if (failed == false && a[i] != ARRAY_SIZE * (ARRAY_SIZE - 1) / 2) { 471 Log.e(TAG, 472 "a["+i+"]="+a[i]+", should be "+ (ARRAY_SIZE * (ARRAY_SIZE - 1) / 2)); 473 failed = true; 474 } 475 } 476 477 assertTrue(!failed); 478 } 479 480 /** 481 * Tests that invoke-to-kernel dependency is handled correctly 482 */ testBuilder2InvokeToKernelDependency()483 public void testBuilder2InvokeToKernelDependency() { 484 ScriptC_matrix s = new ScriptC_matrix(mRS); 485 486 float[] array = new float[ARRAY_SIZE * 4]; 487 488 for (int i = 0; i < ARRAY_SIZE; i++) { 489 array[i * 4] = i * 4 * 7; 490 array[i * 4 + 1] = (i * 4 + 1) * 7; 491 array[i * 4 + 2] = (i * 4 + 2) * 7; 492 array[i * 4 + 3] = (i * 4 + 3) * 7; 493 } 494 495 Allocation input = Allocation.createSized(mRS, Element.F32_4(mRS), ARRAY_SIZE); 496 input.copyFrom(array); 497 498 ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(mRS); 499 500 ScriptGroup.Input unbound = builder.addInput(); 501 502 Matrix4f mat = new Matrix4f(); 503 504 mat.set(0, 0, 0.0f); 505 mat.set(0, 1, 0.0f); 506 mat.set(0, 2, 0.0f); 507 mat.set(0, 3, 1.0f); 508 509 mat.set(1, 0, 1.0f); 510 mat.set(1, 1, 0.0f); 511 mat.set(1, 2, 0.0f); 512 mat.set(1, 3, 0.0f); 513 514 mat.set(2, 0, 0.0f); 515 mat.set(2, 1, 1.0f); 516 mat.set(2, 2, 0.0f); 517 mat.set(2, 3, 0.0f); 518 519 mat.set(3, 0, 0.0f); 520 mat.set(3, 1, 0.0f); 521 mat.set(3, 2, 1.0f); 522 mat.set(3, 3, 0.0f); 523 524 ScriptGroup.Closure c1 = 525 builder.addInvoke(s.getInvokeID_setMatrix(), mat); 526 527 ScriptGroup.Closure c2 = 528 builder.addKernel(s.getKernelID_multiply(), 529 Type.createX(mRS, Element.F32_4(mRS), ARRAY_SIZE), 530 unbound); 531 532 ScriptGroup group = builder.create("Multiply", c2.getReturn()); 533 534 float[] a = new float[ARRAY_SIZE * 4]; 535 ((Allocation)group.execute(input)[0]).copyTo(a); 536 537 mRS.finish(); 538 539 boolean failed = false; 540 for (int i = 0; i < ARRAY_SIZE; i++) { 541 for (int j = 0; j < 4; j++) { 542 float expected = (i*4+((j+1)%4))*7; 543 if (failed == false && a[i * 4 + j] != expected) { 544 Log.e(TAG, "a["+i+"]="+a[i]+", should be "+ expected); 545 failed = true; 546 } 547 } 548 } 549 550 assertTrue(!failed); 551 } 552 } 553