diff --git a/test_conformance/extensions/cl_khr_external_memory_ahb/main.cpp b/test_conformance/extensions/cl_khr_external_memory_ahb/main.cpp index 8900e6ff..c1079a4d 100644 --- a/test_conformance/extensions/cl_khr_external_memory_ahb/main.cpp +++ b/test_conformance/extensions/cl_khr_external_memory_ahb/main.cpp @@ -20,4 +20,4 @@ int main(int argc, const char *argv[]) { return runTestHarness(argc, argv, test_registry::getInstance().num_tests(), test_registry::getInstance().definitions(), false, 0); -} \ No newline at end of file +} diff --git a/test_conformance/extensions/cl_khr_external_memory_ahb/test_ahb.cpp b/test_conformance/extensions/cl_khr_external_memory_ahb/test_ahb.cpp index 303eace7..6220a87e 100644 --- a/test_conformance/extensions/cl_khr_external_memory_ahb/test_ahb.cpp +++ b/test_conformance/extensions/cl_khr_external_memory_ahb/test_ahb.cpp @@ -23,9 +23,32 @@ #include #include "debug_ahb.h" -static bool isAHBUsageReadable(const AHardwareBuffer_UsageFlags usage) +static bool isAHBUsageReadableHost(AHardwareBuffer_UsageFlags usage) { - return (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE & usage) != 0; + return (AHARDWAREBUFFER_USAGE_CPU_READ_MASK & usage) != 0; +} + +static bool isAHBUsageWritableHost(AHardwareBuffer_UsageFlags usage) +{ + return (AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK & usage) != 0; +} + +static bool isAHBUsageReadableDevice(const AHardwareBuffer_UsageFlags usage) +{ + return ((AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE + | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER + | AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) + & usage) + != 0; +} + +static cl_ulong getMaxAllocSize(cl_device_id device) +{ + cl_ulong ret; + cl_int err = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, + sizeof(cl_ulong), &ret, nullptr); + test_error(err, "clGetDeviceInfo failed"); + return ret; } struct ahb_format_table @@ -50,6 +73,32 @@ ahb_image_size_table test_sizes[] = { { 64, 64 }, { 128, 128 }, { 256, 256 }, { 512, 512 } }; +uint32_t test_buffer_sizes[] = { 2, 8, 32, 128, 512, 2048, 16384, 65536 }; + +ahb_usage_table test_buffer_usages[] = { + { static_cast( + AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN + | AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY + | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) }, + { static_cast( + AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN + | AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY + | AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) }, + { static_cast( + AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN + | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN + | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) }, + { static_cast( + AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN + | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN + | AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) }, + { static_cast( + AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN + | AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY) }, + { static_cast( + AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN) } +}; + ahb_usage_table test_usages[] = { { static_cast( AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN @@ -234,8 +283,9 @@ REGISTER_TEST(images_read) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageWritableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -529,8 +579,9 @@ REGISTER_TEST(enqueue_read_image) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageWritableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -707,8 +758,9 @@ REGISTER_TEST(enqueue_copy_image) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageWritableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -1010,8 +1062,9 @@ REGISTER_TEST(enqueue_copy_image_to_buffer) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageWritableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -1198,8 +1251,8 @@ REGISTER_TEST(enqueue_copy_buffer_to_image) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -1393,8 +1446,8 @@ REGISTER_TEST(enqueue_write_image) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -1585,8 +1638,8 @@ REGISTER_TEST(enqueue_fill_image) aHardwareBufferDesc.format = format.aHardwareBufferFormat; for (auto usage : test_usages) { - // Filter out usage flags that are not readable on device - if (!isAHBUsageReadable(usage.usageFlags)) + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) { continue; } @@ -2160,3 +2213,126 @@ REGISTER_TEST(lifetime_image) } return TEST_PASS; } + + +/* Testing clCreateSubBuffer + * Create AHB + * Write to AHB + * Create CL buffer from AHB + * Create a sub buffer into half of the buffer + * Read & verify sub buffer + */ +REGISTER_TEST(sub_buffer) +{ + cl_int err; + RandomSeed seed(gRandomSeed); + + if (!is_extension_available( + device, "cl_khr_external_memory_android_hardware_buffer")) + { + log_info("cl_khr_external_memory_android_hardware_buffer is not " + "supported on this platform. " + "Skipping test.\n"); + return TEST_SKIPPED_ITSELF; + } + + AHardwareBuffer_Desc aHardwareBufferDesc = { 0 }; + aHardwareBufferDesc.format = AHARDWAREBUFFER_FORMAT_BLOB; + for (auto usage : test_buffer_usages) + { + if (!(isAHBUsageReadableHost(usage.usageFlags) + && isAHBUsageWritableHost(usage.usageFlags) + && isAHBUsageReadableDevice(usage.usageFlags))) + { + continue; + } + + aHardwareBufferDesc.usage = usage.usageFlags; + for (uint32_t buffer_size : test_buffer_sizes) + { + if (buffer_size > getMaxAllocSize(device)) + { + continue; + } + + aHardwareBufferDesc.width = buffer_size; + aHardwareBufferDesc.height = 1; + aHardwareBufferDesc.layers = 1; + if (!AHardwareBuffer_isSupported(&aHardwareBufferDesc)) + { + log_unsupported_ahb_format(aHardwareBufferDesc); + continue; + } + + AHardwareBufferWrapper aHardwareBuffer(&aHardwareBufferDesc); + + log_info("Testing usage: %s, buffer size: %u\n", + ahardwareBufferDecodeUsageFlagsToString(usage.usageFlags) + .c_str(), + buffer_size); + + void *hardware_buffer_data = nullptr; + int ahb_result = AHardwareBuffer_lock( + aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1, + nullptr, &hardware_buffer_data); + if (ahb_result != 0) + { + log_error("AHardwareBuffer_lock failed with code %d\n", + ahb_result); + return TEST_FAIL; + } + + std::vector host_buffer(buffer_size); + + generate_random_data(ExplicitType::kUnsignedChar, buffer_size, seed, + host_buffer.data()); + + memcpy(hardware_buffer_data, host_buffer.data(), buffer_size); + + ahb_result = AHardwareBuffer_unlock(aHardwareBuffer, nullptr); + if (ahb_result != 0) + { + log_error("AHardwareBuffer_unlock failed with code %d\n", + ahb_result); + return TEST_FAIL; + } + + cl_mem_properties props[] = { + CL_EXTERNAL_MEMORY_HANDLE_ANDROID_HARDWARE_BUFFER_KHR, + aHardwareBuffer.get_props(), 0 + }; + + clMemWrapper buffer = clCreateBufferWithProperties( + context, props, CL_MEM_READ_WRITE, 0, nullptr, &err); + test_error(err, "Failed to create CL buffer from AHardwareBuffer"); + + cl_uint sub_buffer_size = buffer_size / 2; + cl_buffer_region region = { 0 }; + region.origin = 0; + region.size = sub_buffer_size; + + clMemWrapper sub_buffer = + clCreateSubBuffer(buffer, CL_MEM_READ_WRITE, + CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err); + test_error(err, "clCreateSubBuffer failed"); + + std::vector host_sub_buffer(sub_buffer_size); + err = clEnqueueReadBuffer(queue, sub_buffer, true, 0, + sub_buffer_size, host_sub_buffer.data(), + 0, nullptr, nullptr); + test_error(err, "clEnqueueReadBuffer failed"); + + for (size_t i = 0; i < sub_buffer_size; ++i) + { + if (host_buffer[i] != host_sub_buffer[i]) + { + log_error( + "At position i=%zu expected value %u but got %u\n", i, + host_buffer[i], host_sub_buffer[i]); + return TEST_FAIL; + } + } + } + } + return TEST_PASS; +}