blob: 2575d54294ed15e9560a5eac1e7bfc522d2aee31 [file] [log] [blame]
/*
* Copyright (C) 2015-2016 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.
*/
#include "shared.rsh"
int gDimX;
int gDimY;
int gDimZ;
int gStart;
static bool failed = false;
// For each type, define 4 kernels, one per vector variant, that walk an
// allocation and validate each cell. The value in a cell must be gStart +
// "index-of-the-cell-starting-from-zero". For vector types, the 'x' field
// must have this value. The expected values for 'y', 'z' and 'w' follow the
// 'x' value in increments of one.
//
// 'z' will be zero for 2D and 1D allocations. 'y' will be zero for 1D
// allocations.
#define VERIFY_KERNEL(CT) \
void RS_KERNEL verify_##CT(CT in, int x, int y, int z) { \
int val = (gStart + x + y * gDimX + z * gDimY * gDimX); \
_RS_ASSERT_EQU(in, (CT) val); \
} \
void RS_KERNEL verify_##CT##2(CT##2 in, int x, int y, int z) { \
int val = (gStart + x + y * gDimX + z * gDimY * gDimX); \
_RS_ASSERT_EQU(in.x, (CT) val); \
_RS_ASSERT_EQU(in.y, (CT) (val + 1)); \
} \
void RS_KERNEL verify_##CT##3(CT##3 in, int x, int y, int z) { \
int val = (gStart + x + y * gDimX + z * gDimY * gDimX); \
_RS_ASSERT_EQU(in.x, (CT) val); \
_RS_ASSERT_EQU(in.y, (CT) (val + 1)); \
_RS_ASSERT_EQU(in.z, (CT) (val + 2)); \
} \
void RS_KERNEL verify_##CT##4(CT##4 in, int x, int y, int z) { \
int val = (gStart + x + y * gDimX + z * gDimY * gDimX); \
_RS_ASSERT_EQU(in.x, (CT) val); \
_RS_ASSERT_EQU(in.y, (CT) (val + 1)); \
_RS_ASSERT_EQU(in.z, (CT) (val + 2)); \
_RS_ASSERT_EQU(in.w, (CT) (val + 3)); \
} \
VERIFY_KERNEL(float)
VERIFY_KERNEL(double)
VERIFY_KERNEL(char)
VERIFY_KERNEL(short)
VERIFY_KERNEL(int)
VERIFY_KERNEL(long)
VERIFY_KERNEL(uchar)
VERIFY_KERNEL(ushort)
VERIFY_KERNEL(uint)
VERIFY_KERNEL(ulong)
// Store to an allocation based on the vector size and dimensionality being
// tested. SETELEMENTAT, STORE_TO_ALLOC capture the following variables from
// the context where they get instantiated:
// vecSize, gAlloc, val, x, y, z
#define SETELEMENTAT(CT) \
if (gDimZ != 0) { \
rsSetElementAt_##CT(gAlloc, storeVal, x, y, z); \
} \
else if (gDimY != 0) { \
rsSetElementAt_##CT(gAlloc, storeVal, x, y); \
} \
else { \
rsSetElementAt_##CT(gAlloc, storeVal, x); \
}
#define STORE_TO_ALLOC(RST, CT) \
case RST: \
switch (vecSize) { \
case 1: { \
CT storeVal = (CT) val; \
SETELEMENTAT(CT); \
} \
break; \
case 2: { \
CT##2 storeVal = {(CT) val, (CT) (val + 1)}; \
SETELEMENTAT(CT##2); \
} \
break; \
case 3: { \
CT##3 storeVal = {(CT) val, (CT) (val + 1), (CT) (val + 2)}; \
SETELEMENTAT(CT##3); \
} \
break; \
case 4: { \
CT##4 storeVal = {(CT) val, (CT) (val + 1), (CT) (val + 2), \
(CT) (val + 3)}; \
SETELEMENTAT(CT##4); \
} \
break; \
} \
break; \
// Launch the verify_kernel based on the appropriate type and vector size.
#define LAUNCH_VERIFY_KERNEL(RST, CT) \
case RST: \
if (vecSize == 1) rsForEach(verify_##CT, gAlloc); \
else if (vecSize == 2) rsForEach(verify_##CT##2, gAlloc); \
else if (vecSize == 3) rsForEach(verify_##CT##3, gAlloc); \
else if (vecSize == 4) rsForEach(verify_##CT##4, gAlloc); \
break;
void checkAndSendResult() {
if (failed) {
rsDebug("Single Source Alloc Test Failed", 0);
rsSendToClientBlocking(RS_MSG_TEST_FAILED);
}
else {
rsDebug("Single Source Alloc Test Passed", 0);
rsSendToClientBlocking(RS_MSG_TEST_PASSED);
}
}
static void CreateAndTestAlloc(rs_data_type dt, int vecSize, int dimX, int dimY, int dimZ) {
failed = false;
if (dimZ != 0 && dimY == 0) {
_RS_ASSERT(false); // Invalid test
return;
}
if (dimX == 0) {
_RS_ASSERT(false); // Invalid test
return;
}
rs_element element;
rs_type type;
rs_allocation gAlloc;
// Create and validate the rs_element object
if (vecSize == 1)
element = rsCreateElement((rs_data_type) dt);
else
element = rsCreateVectorElement((rs_data_type) dt, vecSize);
_RS_ASSERT(rsIsObject(element));
if (!rsIsObject(element)) {
return;
}
// Create and validate the rs_type object
type = rsCreateType(element, dimX, dimY, dimZ);
_RS_ASSERT(rsIsObject(type));
if (!rsIsObject(type)) {
return;
}
// Create and validate the rs_allocation object
gAlloc = rsCreateAllocation(type);
if (!rsIsObject(gAlloc)) {
return;
}
// Handle RenderScript's distinction between Y or Z dimension being absent
// and having a size of 1
int zEnd = (dimZ != 0) ? dimZ: 1;
int yEnd = (dimY != 0) ? dimY: 1;
for (int z = 0; z < zEnd; z ++) {
for (int y = 0; y < yEnd; y ++) {
for (int x = 0; x < dimX; x ++) {
int val = gStart + (x + y * dimX + z * dimY * dimX);
// Store to a cell based on the type, vector size and
// dimensionality
switch (dt) {
STORE_TO_ALLOC(RS_TYPE_FLOAT_32, float);
STORE_TO_ALLOC(RS_TYPE_FLOAT_64, double);
STORE_TO_ALLOC(RS_TYPE_SIGNED_8, char);
STORE_TO_ALLOC(RS_TYPE_SIGNED_16, short);
STORE_TO_ALLOC(RS_TYPE_SIGNED_32, int);
STORE_TO_ALLOC(RS_TYPE_SIGNED_64, long);
STORE_TO_ALLOC(RS_TYPE_UNSIGNED_8, uchar);
STORE_TO_ALLOC(RS_TYPE_UNSIGNED_16, ushort);
STORE_TO_ALLOC(RS_TYPE_UNSIGNED_32, uint);
STORE_TO_ALLOC(RS_TYPE_UNSIGNED_64, ulong);
default:
// Invalid test
_RS_ASSERT(false);
break;
}
}
}
}
// Launch the appropriate verify_ kernel
switch (dt) {
LAUNCH_VERIFY_KERNEL(RS_TYPE_FLOAT_32, float);
LAUNCH_VERIFY_KERNEL(RS_TYPE_FLOAT_64, double);
LAUNCH_VERIFY_KERNEL(RS_TYPE_SIGNED_8, char);
LAUNCH_VERIFY_KERNEL(RS_TYPE_SIGNED_16, short);
LAUNCH_VERIFY_KERNEL(RS_TYPE_SIGNED_32, int);
LAUNCH_VERIFY_KERNEL(RS_TYPE_SIGNED_64, long);
LAUNCH_VERIFY_KERNEL(RS_TYPE_UNSIGNED_8, uchar);
LAUNCH_VERIFY_KERNEL(RS_TYPE_UNSIGNED_16, ushort);
LAUNCH_VERIFY_KERNEL(RS_TYPE_UNSIGNED_32, uint);
LAUNCH_VERIFY_KERNEL(RS_TYPE_UNSIGNED_64, ulong);
default:
// Invalid test
_RS_ASSERT(false);
break;
}
}
void TestAllocationCreationAndAccess() {
rs_data_type all_types[] = {
RS_TYPE_BOOLEAN,
// Bug 24862914: Uncomment the following line to add half once the bug is fixed
// RS_TYPE_FLOAT_16,
RS_TYPE_FLOAT_32,
RS_TYPE_FLOAT_64,
RS_TYPE_SIGNED_8,
RS_TYPE_SIGNED_16,
RS_TYPE_SIGNED_32,
RS_TYPE_SIGNED_64,
RS_TYPE_UNSIGNED_8,
RS_TYPE_UNSIGNED_16,
RS_TYPE_UNSIGNED_32,
RS_TYPE_UNSIGNED_64,
};
for (int i = 0; i < sizeof(all_types) / sizeof(all_types[0]); i++) {
for (int vecSize = 1; vecSize <= 4; vecSize ++) {
for (int nDims = 1; nDims <= 3; nDims ++) {
int dimY = nDims > 1 ? gDimY : 0;
int dimZ = nDims > 2 ? gDimZ : 0;
CreateAndTestAlloc(all_types[i], vecSize, gDimX, dimY, dimZ);
}
}
}
checkAndSendResult();
}
#define TEST_DATA_TYPE(dt, allowSimple, allowVector, allowPixel) { \
if (allowSimple) \
_RS_ASSERT(rsIsObject(rsCreateElement(dt))); \
else \
_RS_ASSERT(!rsIsObject(rsCreateElement(dt))); \
if (allowVector) \
_RS_ASSERT(rsIsObject(rsCreateVectorElement(dt, 3))); \
else \
_RS_ASSERT(!rsIsObject(rsCreateVectorElement(dt, 3))); \
if (allowPixel) \
_RS_ASSERT(rsIsObject(rsCreatePixelElement(dt, RS_KIND_PIXEL_DEPTH))); \
else \
_RS_ASSERT(!rsIsObject(rsCreatePixelElement(dt, RS_KIND_PIXEL_DEPTH)));\
}
#define TEST_SUPPORTED_PIXEL(dt, dk) { \
_RS_ASSERT(rsIsObject(rsCreatePixelElement(dt, dk))); \
}
#define TEST_UNSUPPORTED_PIXEL(dt, dk) { \
_RS_ASSERT(!rsIsObject(rsCreatePixelElement(dt, dk))); \
}
#define TEST_HELPER(suffix) { \
_RS_ASSERT(rsIsObject(rsCreateAllocation_##suffix(3))); \
_RS_ASSERT(rsIsObject(rsCreateAllocation_##suffix(3, 4))); \
_RS_ASSERT(rsIsObject(rsCreateAllocation_##suffix(3, 4, 5))); \
}
#define TEST_HELPERS(CT) { \
TEST_HELPER(CT); \
TEST_HELPER(CT##2); \
TEST_HELPER(CT##3); \
TEST_HELPER(CT##4); \
}
void TestElementCreation() {
failed = false;
// vector_width must be at least 2
rs_element oneElt = rsCreateVectorElement(RS_TYPE_SIGNED_32, 1);
_RS_ASSERT(!rsIsObject(oneElt));
// vector_width must be at most 4
rs_element fiveElt = rsCreateVectorElement(RS_TYPE_SIGNED_32, 5);
_RS_ASSERT(!rsIsObject(fiveElt));
/////////////////////////////////////////////////////////////////
// Element validation
/////////////////////////////////////////////////////////////////
// These types are valid for scalar and vectors, but don't support pixel
TEST_DATA_TYPE(RS_TYPE_BOOLEAN, true, true, false);
TEST_DATA_TYPE(RS_TYPE_FLOAT_32, true, true, false);
TEST_DATA_TYPE(RS_TYPE_FLOAT_64, true, true, false);
TEST_DATA_TYPE(RS_TYPE_SIGNED_8, true, true, false);
TEST_DATA_TYPE(RS_TYPE_SIGNED_16, true, true, false);
TEST_DATA_TYPE(RS_TYPE_SIGNED_32, true, true, false);
TEST_DATA_TYPE(RS_TYPE_SIGNED_64, true, true, false);
TEST_DATA_TYPE(RS_TYPE_UNSIGNED_32, true, true, false);
TEST_DATA_TYPE(RS_TYPE_UNSIGNED_64, true, true, false);
// These types are valid only for scalars
TEST_DATA_TYPE(RS_TYPE_MATRIX_4X4, true, false, false);
TEST_DATA_TYPE(RS_TYPE_MATRIX_3X3, true, false, false);
TEST_DATA_TYPE(RS_TYPE_MATRIX_2X2, true, false, false);
TEST_DATA_TYPE(RS_TYPE_ELEMENT, true, false, false);
TEST_DATA_TYPE(RS_TYPE_TYPE, true, false, false);
TEST_DATA_TYPE(RS_TYPE_ALLOCATION, true, false, false);
TEST_DATA_TYPE(RS_TYPE_SCRIPT, true, false, false);
// U8, U16 are valid for scalar, vector and pixel
TEST_DATA_TYPE(RS_TYPE_UNSIGNED_8, true, true, true);
TEST_DATA_TYPE(RS_TYPE_UNSIGNED_16, true, true, true);
// These data types are only for pixels and a particular data_kind
TEST_SUPPORTED_PIXEL (RS_TYPE_UNSIGNED_5_6_5, RS_KIND_PIXEL_RGB);
TEST_UNSUPPORTED_PIXEL(RS_TYPE_UNSIGNED_5_6_5, RS_KIND_PIXEL_L);
TEST_SUPPORTED_PIXEL (RS_TYPE_UNSIGNED_5_5_5_1, RS_KIND_PIXEL_RGBA);
TEST_UNSUPPORTED_PIXEL(RS_TYPE_UNSIGNED_5_5_5_1, RS_KIND_PIXEL_L);
TEST_SUPPORTED_PIXEL (RS_TYPE_UNSIGNED_4_4_4_4, RS_KIND_PIXEL_RGBA);
TEST_UNSUPPORTED_PIXEL(RS_TYPE_UNSIGNED_4_4_4_4, RS_KIND_PIXEL_L);
TEST_SUPPORTED_PIXEL (RS_TYPE_UNSIGNED_16, RS_KIND_PIXEL_DEPTH);
TEST_UNSUPPORTED_PIXEL(RS_TYPE_UNSIGNED_4_4_4_4, RS_KIND_PIXEL_L);
// These data types are not supported from single-source
TEST_DATA_TYPE(RS_TYPE_NONE, false, false, false);
TEST_DATA_TYPE(RS_TYPE_SAMPLER, false, false, false);
TEST_DATA_TYPE(RS_TYPE_MESH, false, false, false);
TEST_DATA_TYPE(RS_TYPE_PROGRAM_FRAGMENT, false, false, false);
TEST_DATA_TYPE(RS_TYPE_PROGRAM_VERTEX, false, false, false);
TEST_DATA_TYPE(RS_TYPE_PROGRAM_RASTER, false, false, false);
TEST_DATA_TYPE(RS_TYPE_PROGRAM_STORE, false, false, false);
TEST_DATA_TYPE(RS_TYPE_FONT, false, false, false);
TEST_DATA_TYPE(RS_TYPE_INVALID, false, false, false);
checkAndSendResult();
}
void TestTypeCreation() {
failed = false;
/////////////////////////////////////////////////////////////////
// Test rs_type creation
/////////////////////////////////////////////////////////////////
rs_element I32_3 = rsCreateVectorElement(RS_TYPE_SIGNED_32, 3);
// Create 1D, 2D, 3D types
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3)));
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3, 4)));
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3, 4, 5)));
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 0))); // x = 0 is allowed
// Invalid dimensionality
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 0, 4))); // x is 0 but y isn't
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 0, 4, 5))); // x is 0 but z isn't
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 0, 5))); // y is 0 but z isn't
// shape attributes
// Valid yuv_format
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3, 4, 0, false, false,
RS_YUV_NONE)));
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3, 4, 0, false, false,
RS_YUV_YV12)));
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3, 4, 0, false, false,
RS_YUV_NV21)));
_RS_ASSERT(rsIsObject(rsCreateType(I32_3, 3, 4, 0, false, false,
RS_YUV_420_888)));
// Invalid yuv_format
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 4, 5, false, false, 1024)));
// yuv_format with 1D or 3D is invalid
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 0, 0, false, false,
RS_YUV_YV12)));
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 4, 5, false, false,
RS_YUV_YV12)));
// yuv_format with mipmaps or cubemap is invalid
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 4, 0, false, true,
RS_YUV_YV12)));
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 4, 0, true, false,
RS_YUV_YV12)));
// mipmaps with 1D or 3D is invalid
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 0, 0, true, false,
RS_YUV_NONE)));
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 4, 5, true, false,
RS_YUV_NONE)));
// cubemap with 1D or 3D is invalid
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 0, 0, false, true,
RS_YUV_NONE)));
_RS_ASSERT(!rsIsObject(rsCreateType(I32_3, 3, 4, 5, false, true,
RS_YUV_NONE)));
checkAndSendResult();
}
void TestAllocationCreationWithUsage() {
failed = false;
/////////////////////////////////////////////////////////////////
// Test rs_allocation creation
/////////////////////////////////////////////////////////////////
rs_element I32_3 = rsCreateVectorElement(RS_TYPE_SIGNED_32, 3);
rs_type I32_3_2D = rsCreateType(I32_3, 3, 4);
// Valid uses
_RS_ASSERT(rsIsObject(rsCreateAllocation(I32_3_2D)));
_RS_ASSERT(rsIsObject(rsCreateAllocation(I32_3_2D,\
(uint32_t) RS_ALLOCATION_USAGE_SCRIPT)));
_RS_ASSERT(rsIsObject(rsCreateAllocation(I32_3_2D,\
(uint32_t) RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE)));
_RS_ASSERT(rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
RS_ALLOCATION_USAGE_SCRIPT)));
// Invalid uses
_RS_ASSERT(!rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_GRAPHICS_VERTEX)));
_RS_ASSERT(!rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)));
_RS_ASSERT(!rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET)));
_RS_ASSERT(!rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_IO_INPUT)));
_RS_ASSERT(!rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_IO_OUTPUT)));
_RS_ASSERT(!rsIsObject(rsCreateAllocation(I32_3_2D,
(uint32_t) RS_ALLOCATION_USAGE_SHARED)));
checkAndSendResult();
}
void TestHelperFunctions() {
failed = false;
// Bug: 24862914: Add half once the bug is fixed
TEST_HELPERS(float);
TEST_HELPERS(double);
TEST_HELPERS(char);
TEST_HELPERS(short);
TEST_HELPERS(int);
TEST_HELPERS(long);
TEST_HELPERS(uchar);
TEST_HELPERS(ushort);
TEST_HELPERS(uint);
TEST_HELPERS(ulong);
checkAndSendResult();
}