Add AHB sub buffer test (#2592)

Add test for clCreateSubBuffer using a buffer created from a
AHardwareBuffer

Signed-off-by: Alex Davicenko <alex.davicenko@arm.com>
Co-authored-by: Alex Davicenko <alex.davicenko@arm.com>
This commit is contained in:
Ahmed Hesham
2025-12-16 17:25:44 +00:00
committed by GitHub
parent 6b20272159
commit b460aae39d
2 changed files with 193 additions and 17 deletions

View File

@@ -20,4 +20,4 @@ int main(int argc, const char *argv[])
{ {
return runTestHarness(argc, argv, test_registry::getInstance().num_tests(), return runTestHarness(argc, argv, test_registry::getInstance().num_tests(),
test_registry::getInstance().definitions(), false, 0); test_registry::getInstance().definitions(), false, 0);
} }

View File

@@ -23,9 +23,32 @@
#include <android/hardware_buffer.h> #include <android/hardware_buffer.h>
#include "debug_ahb.h" #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 struct ahb_format_table
@@ -50,6 +73,32 @@ ahb_image_size_table test_sizes[] = {
{ 64, 64 }, { 128, 128 }, { 256, 256 }, { 512, 512 } { 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_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
| AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY
| AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) },
{ static_cast<AHardwareBuffer_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
| AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY
| AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) },
{ static_cast<AHardwareBuffer_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
| AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN
| AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) },
{ static_cast<AHardwareBuffer_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
| AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN
| AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA) },
{ static_cast<AHardwareBuffer_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
| AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY) },
{ static_cast<AHardwareBuffer_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN) }
};
ahb_usage_table test_usages[] = { ahb_usage_table test_usages[] = {
{ static_cast<AHardwareBuffer_UsageFlags>( { static_cast<AHardwareBuffer_UsageFlags>(
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
@@ -234,8 +283,9 @@ REGISTER_TEST(images_read)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageWritableHost(usage.usageFlags)
&& isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -529,8 +579,9 @@ REGISTER_TEST(enqueue_read_image)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageWritableHost(usage.usageFlags)
&& isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -707,8 +758,9 @@ REGISTER_TEST(enqueue_copy_image)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageWritableHost(usage.usageFlags)
&& isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -1010,8 +1062,9 @@ REGISTER_TEST(enqueue_copy_image_to_buffer)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageWritableHost(usage.usageFlags)
&& isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -1198,8 +1251,8 @@ REGISTER_TEST(enqueue_copy_buffer_to_image)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -1393,8 +1446,8 @@ REGISTER_TEST(enqueue_write_image)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -1585,8 +1638,8 @@ REGISTER_TEST(enqueue_fill_image)
aHardwareBufferDesc.format = format.aHardwareBufferFormat; aHardwareBufferDesc.format = format.aHardwareBufferFormat;
for (auto usage : test_usages) for (auto usage : test_usages)
{ {
// Filter out usage flags that are not readable on device if (!(isAHBUsageReadableHost(usage.usageFlags)
if (!isAHBUsageReadable(usage.usageFlags)) && isAHBUsageReadableDevice(usage.usageFlags)))
{ {
continue; continue;
} }
@@ -2160,3 +2213,126 @@ REGISTER_TEST(lifetime_image)
} }
return TEST_PASS; 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<uint8_t> 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, &region, &err);
test_error(err, "clCreateSubBuffer failed");
std::vector<uint8_t> 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;
}