// // Copyright (c) 2017 The Khronos Group Inc. // // 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 #include #include "procs.h" #include "harness/errorHelpers.h" #define MAX_SUB_DEVICES 16 // Limit the sub-devices to ensure no out of resource errors. #define MEM_OBJ_SIZE 1024 #define IMAGE_DIM 16 // Kernel source code static const char *image_migrate_kernel_code = "__kernel void test_image_migrate(write_only image2d_t dst, read_only image2d_t src1,\n" " read_only image2d_t src2, sampler_t sampler, uint x)\n" "{\n" " int tidX = get_global_id(0), tidY = get_global_id(1);\n" " int2 coords = (int2) {tidX, tidY};\n" " uint4 val = read_imageui(src1, sampler, coords) ^\n" " read_imageui(src2, sampler, coords) ^\n" " x;\n" " write_imageui(dst, coords, val);\n" "}\n"; enum migrations { MIGRATE_PREFERRED, // migrate to the preferred sub-device MIGRATE_NON_PREFERRED, // migrate to a randomly chosen non-preferred sub-device MIGRATE_RANDOM, // migrate to a randomly chosen sub-device with randomly chosen flags NUMBER_OF_MIGRATIONS }; static cl_mem init_image(cl_command_queue cmd_q, cl_mem image, cl_uint *data) { cl_int err; size_t origin[3] = {0, 0, 0}; size_t region[3] = {IMAGE_DIM, IMAGE_DIM, 1}; if (image) { if ((err = clEnqueueWriteImage(cmd_q, image, CL_TRUE, origin, region, 0, 0, data, 0, NULL, NULL)) != CL_SUCCESS) { print_error(err, "Failed on enqueue write of image data."); } } return image; } static cl_int migrateMemObject(enum migrations migrate, cl_command_queue *queues, cl_mem *mem_objects, cl_uint num_devices, cl_mem_migration_flags *flags, MTdata d) { cl_uint i, j; cl_int err = CL_SUCCESS; for (i=0; i 1)) j = (j+1) % num_devices; break; case MIGRATE_RANDOM: // Choose a random set of flags flags[i] = (cl_mem_migration_flags)(genrand_int32(d) & (CL_MIGRATE_MEM_OBJECT_HOST | CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED)); break; default: log_error("Unhandled migration type: %d\n", migrate); return -1; } if ((err = clEnqueueMigrateMemObjects(queues[j], 1, (const cl_mem *)(&mem_objects[i]), flags[i], 0, NULL, NULL)) != CL_SUCCESS) { print_error(err, "Failed migrating memory object."); } } return err; } static cl_int restoreImage(cl_command_queue *queues, cl_mem *mem_objects, cl_uint num_devices, cl_mem_migration_flags *flags, cl_uint *buffer) { cl_uint i; cl_int err; const size_t origin[3] = {0, 0, 0}; const size_t region[3] = {IMAGE_DIM, IMAGE_DIM, 1}; // If the image was previously migrated with undefined content, reload the content. for (i=0; i 1) { // Create each of the sub-devices and a corresponding context. if ((err = clCreateSubDevices(deviceID, (const cl_device_partition_property *)property, num_devices, devices, &num_devices)) != CL_SUCCESS) { print_error(err, "Failed creating sub devices."); failed = 1; goto cleanup; } // Create a context containing all the sub-devices ctx = clCreateContext(NULL, num_devices, devices, notify_callback, NULL, &err); if (ctx == NULL) { print_error(err, "Failed creating context containing the sub-devices."); failed = 1; goto cleanup; } // Create a command queue for each sub-device for (i=0; i 1) { // Command queue cleanup if (queues[i]) { if ((err = clReleaseCommandQueue(queues[i])) != CL_SUCCESS) { print_error(err, "Failed releasing command queue."); failed = 1; } } // Sub-device cleanup if (devices[i]) { if ((err = clReleaseDevice(devices[i])) != CL_SUCCESS) { print_error(err, "Failed releasing sub device."); failed = 1; } } devices[i] = 0; } } // Sampler cleanup if (sampler) { if ((err = clReleaseSampler(sampler)) != CL_SUCCESS) { print_error(err, "Failed releasing sampler."); failed = 1; } sampler = NULL; } // Context, program, and kernel cleanup if (program) { if ((err = clReleaseProgram(program)) != CL_SUCCESS) { print_error(err, "Failed releasing program."); failed = 1; } program = NULL; } if (kernel) { if ((err = clReleaseKernel(kernel)) != CL_SUCCESS) { print_error(err, "Failed releasing kernel."); failed = 1; } kernel = NULL; } if (ctx && (ctx != context)) { if ((err = clReleaseContext(ctx)) != CL_SUCCESS) { print_error(err, "Failed releasing context."); failed = 1; } } ctx = NULL; if (failed) goto cleanup_allocations; } while (domains); cleanup_allocations: if (devices) free(devices); if (queues) free(queues); if (flagsA) free(flagsA); if (flagsB) free(flagsB); if (flagsC) free(flagsC); if (imageA) free(imageA); if (imageB) free(imageB); if (imageC) free(imageC); return ((failed) ? -1 : 0); }