blob: 86359a1bed65944a611d2125d4050f4cb1aba719 [file] [log] [blame]
//
// Copyright 2025 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "test_utils/ANGLETestCL.h"
#include <angle_cl.h>
#include "util/test_utils.h"
using namespace angle;
namespace
{
void CL_CALLBACK ContextCreated(const char *errinfo,
const void *private_info,
size_t cb,
void *user_data)
{
std::cout << "Context created";
}
class CapturedTestCL : public ANGLETestCL<>
{
protected:
CapturedTestCL() : ANGLETestCL(this->GetParam()) {}
};
class MultiFrameCL
{
public:
MultiFrameCL() {}
void testSetUp()
{
// Get platform
cl_platform_id platform;
clGetPlatformIDs(1, &platform, nullptr);
// Get device
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
// Create context
context = clCreateContext(nullptr, 1, &device, ContextCreated, nullptr, nullptr);
assert(context != nullptr);
// Create command queue
queue = clCreateCommandQueue(context, device, 0, nullptr);
assert(queue != nullptr);
// Create and build program
const char *kernelSource = R"(
__kernel void frame1(__global float *output)
{
int gid = get_global_id(0);
output[gid] = gid * 2.0f;
}
__kernel void frame2(__global float *output)
{
int gid = get_global_id(0);
output[gid] = gid * gid;
}
__kernel void frame3(__global float *output)
{
int gid = get_global_id(0);
output[gid] = gid + 100.0f;
}
__kernel void frame4(__global float *output)
{
int gid = get_global_id(0);
output[gid] = gid;
if (gid == 0)
{
printf("Frame 4!\n");
}
}
__kernel void frame5(__global float *output)
{
int gid = get_global_id(0);
output[gid] = gid/gid;
}
)";
program = clCreateProgramWithSource(context, 1, &kernelSource, nullptr, nullptr);
clBuildProgram(program, 0, nullptr, nullptr, nullptr, nullptr);
cl_build_status status;
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS, sizeof(cl_build_status),
&status, nullptr);
std::cout << "Build status: " << status << "\n";
}
void testTearDown()
{
clReleaseProgram(program);
clReleaseCommandQueue(queue);
clReleaseContext(context);
}
void frame1() { executeKernel("frame1"); }
void frame2() { executeKernel("frame2"); }
void frame3() { executeKernel("frame3"); }
void frame4() { executeKernel("frame4"); }
void frame5() { executeKernel("frame5"); }
private:
void executeKernel(const char *kernelName)
{
// Create buffer
outputBuffer =
clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * 128, nullptr, nullptr);
// Get CL_MEM_SIZE
size_t memSize;
clGetMemObjectInfo(outputBuffer, CL_MEM_SIZE, sizeof(size_t), &memSize, nullptr);
std::cout << "Buffer size: " << memSize << ":\n";
// Create kernel
cl_kernel kernel = clCreateKernel(program, kernelName, nullptr);
assert(kernel != nullptr);
// Set kernel arguments
clSetKernelArg(kernel, 0, sizeof(cl_mem), &outputBuffer);
// Execute kernel
size_t globalWorkSize = 128;
clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, &globalWorkSize, nullptr, 0, nullptr,
nullptr);
// Read and verify results
std::vector<float> results(128);
clEnqueueReadBuffer(queue, outputBuffer, CL_TRUE, 0, sizeof(float) * 128, results.data(), 0,
nullptr, nullptr);
// Print the results
std::cout << "Results from " << kernelName << ":\n";
for (size_t i = 0; i < results.size(); ++i)
{
std::cout << results[i] << " ";
}
std::cout << "\n";
// Cleanup kernel
clReleaseKernel(kernel);
// Cleanup buffer
clReleaseMemObject(outputBuffer);
}
cl_context context;
cl_command_queue queue;
cl_program program;
cl_mem outputBuffer;
};
// OpenCL test captured by capture_tests.py
TEST_P(CapturedTestCL, MultiFrameCL)
{
MultiFrameCL test;
test.testSetUp();
// Execute multiple frames
test.frame1();
test.frame2();
test.frame3();
test.frame4();
test.frame5();
test.testTearDown();
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CapturedTestCL);
// Capture is only supported on the Vulkan backend
ANGLE_INSTANTIATE_TEST(CapturedTestCL, ES3_VULKAN());
} // anonymous namespace