blob: 28a952805efd5b3ed18b60f9c86f7f1e54c96ec9 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.renderscript.cts;
import android.renderscript.Allocation;
import android.renderscript.Float4;
import android.renderscript.RenderScript;
import java.lang.reflect.Method;
/*
* This checks that small structs (<= 64 bytes) are passed and
* returned correctly by forEach_* style kernels.
*
* There are three steps to each test: (a) setup, (b) modify, (c) verify.
* (a) the setup stage initializes the Allocation of structs
* (b) modify calls a forEach_* kernel with the Allocation
* (c) verify checks that the forEach_* kernel accessed the data as expected
*/
public class SmallStructsTest extends RSBaseCompute {
static final int sAllocationElements = 1024;
static final int sLargestCharArrayStructSize = 64;
static final String sTwoElementStructTypes[] =
{"i8", "i16", "i32", "i64", "f32", "f64", "v128"};
static final byte sInitialValue_int8_t = (byte) 0x7;
static final short sInitialValue_int16_t = (short) 0x1234;
static final int sInitialValue_int32_t = 0x12345678;
static final long sInitialValue_int64_t = 0x12345678abcdef1L;
static final float sInitialValue_float = 10473.f;
static final double sInitialValue_double = 35353143.25;
static final Float4 sInitialValue_float4 = new Float4(10473.f, 353541.5f, -5433.75f, 78394.f);
ScriptC_small_structs mScript;
@Override
protected void setUp() throws Exception {
super.setUp();
mScript = new ScriptC_small_structs(mRS);
}
void checkForErrorsInScript() {
mRS.finish();
mScript.invoke_checkError();
waitForMessage();
checkForErrors();
}
/**
* Returns the class associated with the given type. For primitive types, the unwrapped class is
* returned.
*/
Class<?> getUnwrappedClassForType(String type) {
if (type.equals("i8")) {
return byte.class;
} else if (type.equals("i16")) {
return short.class;
} else if (type.equals("i32")) {
return int.class;
} else if (type.equals("i64")) {
return long.class;
} else if (type.equals("f32")) {
return float.class;
} else if (type.equals("f64")) {
return double.class;
} else if (type.equals("v128")) {
return Float4.class;
} else {
fail("Unknown type tag: " + type);
return null;
}
}
/**
* Returns a ScriptC_small_structs setter associated with the global of the given type.
*/
Method getInitialValueSetter(String type) throws Exception {
String name = "set_initial_value_";
if (type.equals("i8")) {
name += "int8_t";
} else if (type.equals("i16")) {
name += "int16_t";
} else if (type.equals("i32")) {
name += "int32_t";
} else if (type.equals("i64")) {
name += "int64_t";
} else if (type.equals("f32")) {
name += "float";
} else if (type.equals("f64")) {
name += "double";
} else if (type.equals("v128")) {
name += "float4";
} else {
fail("unknown type tag: " + type);
}
return ScriptC_small_structs.class.getMethod(name, getUnwrappedClassForType(type));
}
/**
* Returns the (possibly wrapped) initial value associated with the global of the given type.
*/
Object getInitialValue(String type) {
if (type.equals("i8")) {
return (Object) sInitialValue_int8_t;
} else if (type.equals("i16")) {
return (Object) sInitialValue_int16_t;
} else if (type.equals("i32")) {
return (Object) sInitialValue_int32_t;
} else if (type.equals("i64")) {
return (Object) sInitialValue_int64_t;
} else if (type.equals("f32")) {
return (Object) sInitialValue_float;
} else if (type.equals("f64")) {
return (Object) sInitialValue_double;
} else if (type.equals("v128")) {
return (Object) sInitialValue_float4;
} else {
fail("unknown type tag: " + type);
return null;
}
}
/**
* Structs in this test are of the form
* struct char_array_N { char bytes[N]; };
*/
public void testSmallStructsOfCharArray() throws Exception {
for (int size = 1; size <= sLargestCharArrayStructSize; ++size) {
// Make the input allocation.
Class<?> scriptFieldClass = Class.forName(
"android.renderscript.cts.ScriptField_char_array_" + size);
Object field = scriptFieldClass.getConstructor(RenderScript.class, int.class)
.newInstance(mRS, sAllocationElements);
Allocation alloc = (Allocation) scriptFieldClass.getMethod("getAllocation")
.invoke(field);
// void set_bytes(int index, byte[] bytes, boolean copyNow)
Method set_bytes = scriptFieldClass.getMethod("set_bytes",
int.class, byte[].class, boolean.class);
byte[] bytes = new byte[size];
for (int i = 0; i < size; ++i) {
bytes[i] = (byte) (1 + i);
}
for (int elem = 0; elem < sAllocationElements; ++elem) {
set_bytes.invoke(field, elem, bytes, true);
}
// Get methods used in testing.
Method modify = ScriptC_small_structs.class.getMethod(
"forEach_modify_char_array_" + size,
Allocation.class, Allocation.class);
Method verify = ScriptC_small_structs.class.getMethod(
"invoke_verify_char_array_" + size,
Allocation.class);
// Run the test.
modify.invoke(mScript, alloc, alloc);
verify.invoke(mScript, alloc);
}
checkForErrorsInScript();
// Check that all tests were run.
mScript.invoke_checkNumberOfCharArrayTestsRun();
waitForMessage();
checkForErrors();
}
/**
* Structs in this test are of the form
* struct two_element_struct_X { TYPE1 a; TYPE2 b };
*/
public void testSmallStructsOfHeterogeneousTypes() throws Exception {
// Initialize script globals.
for (String type: sTwoElementStructTypes) {
getInitialValueSetter(type).invoke(mScript, getInitialValue(type));
}
for (String type1: sTwoElementStructTypes) {
for (String type2: sTwoElementStructTypes) {
// Build the input allocation.
String tag = type1 + "_" + type2;
Class<?> scriptFieldClass = Class.forName(
"android.renderscript.cts.ScriptField_two_element_struct_" + tag);
Object field = scriptFieldClass.getConstructor(RenderScript.class, int.class)
.newInstance(mRS, sAllocationElements);
Allocation alloc = (Allocation) scriptFieldClass.getMethod("getAllocation")
.invoke(field);
// Set the structure fields of the input.
for (int elem = 0; elem < sAllocationElements; ++elem) {
Object initialValueA = getInitialValue(type1);
// void set_a(int index, Ty val, boolean copyNow)
Method fieldASetter = scriptFieldClass.getMethod("set_a",
int.class, getUnwrappedClassForType(type1), boolean.class);
fieldASetter.invoke(field, elem, initialValueA, true);
Object initialValueB = getInitialValue(type2);
// void set_b(int index, Ty val, boolean copyNow)
Method fieldBSetter = scriptFieldClass.getMethod("set_b",
int.class, getUnwrappedClassForType(type2), boolean.class);
fieldBSetter.invoke(field, elem, initialValueB, true);
}
// Get methods used in testing.
Method modify = ScriptC_small_structs.class.getMethod(
"forEach_modify_two_element_struct_" + tag,
Allocation.class, Allocation.class);
Method verify = ScriptC_small_structs.class.getMethod(
"invoke_verify_two_element_struct_" + tag,
Allocation.class);
// Run the test.
modify.invoke(mScript, alloc, alloc);
verify.invoke(mScript, alloc);
}
}
checkForErrorsInScript();
// Check that all tests were run.
mScript.invoke_checkNumberOfTwoElementStructTestsRun();
waitForMessage();
checkForErrors();
}
}