/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #ifdef _WIN32 #include "top.hpp" #include "cl_d3d9_amd.hpp" #include "platform/command.hpp" #include #include RUNTIME_ENTRY(cl_int, clGetDeviceIDsFromDX9MediaAdapterKHR, (cl_platform_id platform, cl_uint num_media_adapters, cl_dx9_media_adapter_type_khr* media_adapters_type, void* media_adapters, cl_dx9_media_adapter_set_khr media_adapter_set, cl_uint num_entries, cl_device_id* devices, cl_uint* num_devices)) { cl_int errcode; // Accept an array of DX9 devices here as the spec mention of array of num_media_adapters size. IDirect3DDevice9Ex** d3d9_device = static_cast(media_adapters); cl_device_id* gpu_devices = NULL; cl_uint num_gpu_devices = 0; static const bool VALIDATE_ONLY = true; if (platform != NULL && platform != AMD_PLATFORM) { LogWarning("\"platform\" is not a valid AMD platform"); return CL_INVALID_PLATFORM; } // check if input parameter are correct if ((num_media_adapters == 0) || (media_adapters_type == NULL) || (media_adapters == NULL) || (media_adapter_set != CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR && media_adapter_set != CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR) || (num_entries == 0 && devices != NULL)) { return CL_INVALID_VALUE; } // Get GPU devices errcode = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 0, NULL, &num_gpu_devices); if (errcode != CL_SUCCESS && errcode != CL_DEVICE_NOT_FOUND) { return CL_INVALID_VALUE; } if (!num_gpu_devices) { *not_null(num_devices) = 0; return CL_DEVICE_NOT_FOUND; } switch (media_adapter_set) { case CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR: case CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR: { gpu_devices = new cl_device_id[num_gpu_devices]; errcode = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, num_gpu_devices, gpu_devices, NULL); if (errcode != CL_SUCCESS) { break; } std::vector compatible_devices; for (cl_uint i = 0; i < num_gpu_devices; ++i) { cl_device_id device = gpu_devices[i]; amd::Context::Flags context_flag; amd::Context::DeviceFlagIdx devIdx; switch (media_adapters_type[i]) { case CL_ADAPTER_D3D9_KHR: context_flag = amd::Context::Flags::D3D9DeviceKhr; devIdx = amd::Context::DeviceFlagIdx::D3D9DeviceKhrIdx; break; case CL_ADAPTER_D3D9EX_KHR: context_flag = amd::Context::Flags::D3D9DeviceEXKhr; devIdx = amd::Context::DeviceFlagIdx::D3D9DeviceEXKhrIdx; break; case CL_ADAPTER_DXVA_KHR: context_flag = amd::Context::Flags::D3D9DeviceVAKhr; devIdx = amd::Context::DeviceFlagIdx::D3D9DeviceVAKhrIdx; break; } for (cl_uint j = 0; j < num_media_adapters; ++j) { // Since there can be multiple DX9 adapters passed in the array we need to validate // interopability with each. void* external_device[amd::Context::DeviceFlagIdx::LastDeviceFlagIdx] = {}; external_device[devIdx] = d3d9_device[j]; if (is_valid(device) && (media_adapters_type[j] == CL_ADAPTER_D3D9EX_KHR) && as_amd(device)->bindExternalDevice(context_flag, external_device, NULL, VALIDATE_ONLY)) { compatible_devices.push_back(as_amd(device)); } } } if (compatible_devices.size() == 0) { *not_null(num_devices) = 0; errcode = CL_DEVICE_NOT_FOUND; break; } auto it = compatible_devices.cbegin(); cl_uint compatible_count = std::min(num_entries, (cl_uint)compatible_devices.size()); while (compatible_count--) { *devices++ = as_cl(*it++); --num_entries; } while (num_entries--) { *devices++ = (cl_device_id)0; } *not_null(num_devices) = (cl_uint)compatible_devices.size(); } break; default: LogWarning("\"d3d9_device_set\" is invalid"); errcode = CL_INVALID_VALUE; } delete[] gpu_devices; return errcode; } RUNTIME_EXIT RUNTIME_ENTRY_RET(cl_mem, clCreateFromDX9MediaSurfaceKHR, (cl_context context, cl_mem_flags flags, cl_dx9_media_adapter_type_khr adapter_type, void* surface_info, cl_uint plane, cl_int* errcode_ret)) { cl_mem clMemObj = NULL; cl_dx9_surface_info_khr* cl_surf_info = NULL; if (!is_valid(context)) { *not_null(errcode_ret) = CL_INVALID_CONTEXT; LogWarning("invalid parameter \"context\""); return clMemObj; } if (!flags) flags = CL_MEM_READ_WRITE; if (!(((flags & CL_MEM_READ_ONLY) == CL_MEM_READ_ONLY) || ((flags & CL_MEM_WRITE_ONLY) == CL_MEM_WRITE_ONLY) || ((flags & CL_MEM_READ_WRITE) == CL_MEM_READ_WRITE))) { *not_null(errcode_ret) = CL_INVALID_VALUE; LogWarning("invalid parameter \"flags\""); return clMemObj; } if ((adapter_type != CL_ADAPTER_D3D9_KHR) && (adapter_type != CL_ADAPTER_D3D9EX_KHR) && (adapter_type != CL_ADAPTER_DXVA_KHR)) { *not_null(errcode_ret) = CL_INVALID_VALUE; return clMemObj; } if (!surface_info) { *not_null(errcode_ret) = CL_INVALID_VALUE; LogWarning("parameter \"pD3DResource\" is a NULL pointer"); return clMemObj; } cl_surf_info = (cl_dx9_surface_info_khr*)surface_info; IDirect3DSurface9* pD3D9Resource = cl_surf_info->resource; HANDLE shared_handle = cl_surf_info->shared_handle; if (!pD3D9Resource) { *not_null(errcode_ret) = CL_INVALID_VALUE; LogWarning("parameter \"surface_info\" is a NULL pointer"); return clMemObj; } D3DSURFACE_DESC Desc; pD3D9Resource->GetDesc(&Desc); if ((Desc.Format != D3DFMT_NV_12) && (Desc.Format != D3DFMT_P010) && (Desc.Format != D3DFMT_YV_12) && (plane != 0)) { *not_null(errcode_ret) = CL_INVALID_VALUE; LogWarning("The plane has to be Zero if the surface format is non-planar !"); return clMemObj; } // Check for image support const std::vector& devices = as_amd(context)->devices(); bool supportPass = false; bool sizePass = false; for (const auto& it : devices) { if (it->info().imageSupport_) { supportPass = true; } } if (!supportPass) { *not_null(errcode_ret) = CL_INVALID_OPERATION; LogWarning("there are no devices in context to support images"); return (cl_mem)0; } // Verify the resource is a 2D image return amd::clCreateImage2DFromD3D9ResourceAMD(*as_amd(context), flags, adapter_type, cl_surf_info, plane, errcode_ret); } RUNTIME_EXIT RUNTIME_ENTRY(cl_int, clEnqueueAcquireDX9MediaSurfacesKHR, (cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event)) { return amd::clDXTranslateErrorCode(amd::clEnqueueAcquireExtObjectsAMD( command_queue, num_objects, mem_objects, num_events_in_wait_list, event_wait_list, event, CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR)); } RUNTIME_EXIT RUNTIME_ENTRY(cl_int, clEnqueueReleaseDX9MediaSurfacesKHR, (cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event)) { return amd::clDXTranslateErrorCode(amd::clEnqueueReleaseExtObjectsAMD( command_queue, num_objects, mem_objects, num_events_in_wait_list, event_wait_list, event, CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR)); } RUNTIME_EXIT // // clCreateImage2DFromD3D9ResourceAMD // cl_mem amd::clCreateImage2DFromD3D9ResourceAMD(amd::Context& amdContext, cl_mem_flags flags, cl_dx9_media_adapter_type_khr adapter_type, cl_dx9_surface_info_khr* surface_info, cl_uint plane, int* errcode_ret) { cl_dx9_surface_info_khr* cl_surf_info = reinterpret_cast(surface_info); IDirect3DSurface9* pD3D9Resource = cl_surf_info->resource; HANDLE shared_handle = cl_surf_info->shared_handle; amd::D3D9Object obj; cl_int errcode = amd::D3D9Object::initD3D9Object(amdContext, adapter_type, surface_info, plane, obj); if (CL_SUCCESS != errcode) { *not_null(errcode_ret) = errcode; return (cl_mem)0; } amd::Image2DD3D9* pImage2DD3D9 = new (amdContext) amd::Image2DD3D9(amdContext, flags, obj); if (!pImage2DD3D9) { *not_null(errcode_ret) = CL_OUT_OF_HOST_MEMORY; return (cl_mem)0; } if (!pImage2DD3D9->create()) { *not_null(errcode_ret) = CL_MEM_OBJECT_ALLOCATION_FAILURE; pImage2DD3D9->release(); return (cl_mem)0; } *not_null(errcode_ret) = CL_SUCCESS; return as_cl(pImage2DD3D9); } // // Helper function SyncD3D9Objects // void amd::SyncD3D9Objects(std::vector& memObjects) { amd::Memory*& mem = memObjects.front(); if (!mem) { LogWarning("\nNULL memory object\n"); return; } amd::InteropObject* interop = mem->getInteropObj(); if (!interop) { LogWarning("\nNULL interop object\n"); return; } amd::D3D9Object* d3d9Obj = interop->asD3D9Object(); if (!d3d9Obj) { LogWarning("\nNULL D3D9 object\n"); return; } IDirect3DQuery9* query = d3d9Obj->getQuery(); if (!query) { LogWarning("\nNULL IDirect3DQuery9\n"); return; } amd::ScopedLock sl(d3d9Obj->getResLock()); query->Issue(D3DISSUE_END); BOOL data = FALSE; while (S_OK != query->GetData(&data, sizeof(BOOL), D3DGETDATA_FLUSH)) { } } #endif //_WIN32