diff --git a/projects/clr/hipamd/rocclr/CMakeLists.txt b/projects/clr/hipamd/rocclr/CMakeLists.txt index 9e489abbc1..bfa136fccc 100755 --- a/projects/clr/hipamd/rocclr/CMakeLists.txt +++ b/projects/clr/hipamd/rocclr/CMakeLists.txt @@ -115,7 +115,7 @@ endif() if(BUILD_SHARED_LIBS) if(WIN32) - target_sources(amdhip PRIVATE amdhip.def) + target_sources(amdhip PRIVATE hip_hcc.def.in) else() set_target_properties(amdhip PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/hip_hcc.map.in") endif() diff --git a/projects/clr/hipamd/rocclr/cl_d3d9.cpp b/projects/clr/hipamd/rocclr/cl_d3d9.cpp index bab6deb9ab..3291e76c8e 100644 --- a/projects/clr/hipamd/rocclr/cl_d3d9.cpp +++ b/projects/clr/hipamd/rocclr/cl_d3d9.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-present Advanced Micro Devices, Inc. +/* Copyright (c) 2012-present Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,201 +18,838 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $Revision$ on $Date$ */ +#ifdef _WIN32 -#ifndef __OPENCL_CL_D3D9_AMD_H -#define __OPENCL_CL_D3D9_AMD_H +#include "top.hpp" -#include "cl_common.hpp" -#include "platform/context.hpp" -#include "platform/memory.hpp" +#include "cl_d3d9_amd.hpp" +#include "platform/command.hpp" +#include #include -/* cl_amd_d3d9_sharing extension */ -#define cl_amd_d3d9_sharing 1 - -/* cl_amd_d3d9_sharing error codes */ -#define CL_INVALID_D3D9_DEVICE_KHR -1021 -#define CL_INVALID_D3D9_RESOURCE_KHR -1022 - -/* cl_amd_d3d9_sharing enumerations */ -#define CL_CONTEXT_D3D9_DEVICE_KHR 0x4039 - -namespace amd -{ -typedef struct -{ - union - { - UINT ByteWidth; - UINT Width; - }; - UINT Height; - UINT Depth; -} D3D9ObjSize_t; - -typedef struct -{ - D3D9ObjSize_t objSize_; - D3DFORMAT d3dFormat_; - D3DRESOURCETYPE resType_; - UINT usage_; - D3DPOOL d3dPool_; - D3DMULTISAMPLE_TYPE msType_; - UINT msQuality_; - UINT mipLevels_; - UINT fvf_; - RECT surfRect_; -} D3D9ObjDesc_t; - -typedef struct d3d9ResInfo { - cl_dx9_surface_info_khr surfInfo; - cl_uint surfPlane; -} TD3D9RESINFO; +#define D3DFMT_NV_12 static_cast(MAKEFOURCC('N', 'V', '1', '2')) +#define D3DFMT_P010 static_cast(MAKEFOURCC('P', '0', '1', '0')) +#define D3DFMT_YV_12 static_cast(MAKEFOURCC('Y', 'V', '1', '2')) +#define D3DFMT_YUY2 static_cast(MAKEFOURCC('Y', 'U', 'Y', '2')) -//typedef std::pair TD3D9OBJINFO; +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; -//! Class D3D9Object keeps all the info about the D3D9 object -//! from which the CL object is created -class D3D9Object : public InteropObject -{ -private: - IDirect3DSurface9* pD3D9Aux_; - cl_int cliChecksum_; - bool releaseResources_; - static bool createSharedResource(D3D9Object& obj); - static std::vector> resources_; + if (platform != NULL && platform != AMD_PLATFORM) { + LogWarning("\"platrform\" 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; + } - //!Global lock - static Monitor resLock_; - cl_uint surfPlane_; - cl_dx9_surface_info_khr surfInfo_; + if (!num_gpu_devices) { + *not_null(num_devices) = 0; + return CL_DEVICE_NOT_FOUND; + } -protected: - IDirect3DSurface9* pD3D9Res_; - IDirect3DSurface9* pD3D9ResOrig_; - IDirect3DQuery9* pQuery_; - D3D9ObjDesc_t objDesc_; - D3D9ObjDesc_t objDescOrig_; - HANDLE handleOrig_; - HANDLE handleShared_; - RECT srcSurfRect; - RECT SharedSurfRect; - cl_dx9_media_adapter_type_khr adapterType_; + 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; + } -public: -//! D3D9Object constructor initializes memeber variables - D3D9Object() - : releaseResources_(false), - pQuery_(NULL) - { - // @todo Incorrect initialization!!! - memset(this, 0, sizeof(D3D9Object)); - } - //copy constructor - D3D9Object(D3D9Object& d3d9obj) - :pQuery_(NULL) - { - *this = d3d9obj; - this->releaseResources_ = true; - } - - //virtual destructor - virtual ~D3D9Object() - { - ScopedLock sl(resLock_); - if(releaseResources_) { - if(pD3D9ResOrig_) pD3D9ResOrig_->Release(); - if(pD3D9Res_) pD3D9Res_->Release(); - if(pD3D9Aux_) pD3D9Aux_->Release(); - if(pQuery_) pQuery_->Release(); - //if the resouce is being used - if(resources_.size()) { - for(auto& it = resources_.cbegin(); it != resources_.cend(); it++) { - if( surfInfo_.resource && - ((*it).first.surfInfo.resource == surfInfo_.resource) && - ((*it).first.surfPlane == surfPlane_)) { - resources_.erase(it); - 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; } - } - static int initD3D9Object(const Context& amdContext, cl_dx9_media_adapter_type_khr adapter_type, - cl_dx9_surface_info_khr* cl_surf_info, cl_uint plane, D3D9Object& obj); - cl_uint getMiscFlag(void); - D3D9Object* asD3D9Object() {return this;} - IDirect3DSurface9* getD3D9Resource() const {return pD3D9Res_;} - HANDLE getD3D9SharedHandle() const {return handleShared_;} - IDirect3DSurface9* getD3D9ResOrig() const {return pD3D9ResOrig_;} - RECT* getSrcSurfRect() {return &objDesc_.surfRect_;} - RECT* getSharedSurfRect() {return &objDescOrig_.surfRect_;} - void setD3D9AuxRes(IDirect3DSurface9* pAux) {pD3D9Aux_ = pAux;} - IDirect3DSurface9* getD3D9AuxRes() {return pD3D9Aux_;} - IDirect3DQuery9* getQuery() const {return pQuery_;} - Monitor & getResLock() { return resLock_;} - UINT getWidth() const {return objDesc_.objSize_.Width;} - UINT getHeight() const {return objDesc_.objSize_.Height;} - cl_uint getPlane() const {return surfPlane_;} - cl_dx9_media_adapter_type_khr getAdapterType() const { return adapterType_;}; - const cl_dx9_surface_info_khr& getSurfInfo() const {return surfInfo_;}; - size_t getElementBytes(D3DFORMAT d3d9Format, cl_uint plane); - size_t getElementBytes() {return getElementBytes(objDesc_.d3dFormat_, surfPlane_);} - D3DFORMAT getD3D9Format() {return objDesc_.d3dFormat_;} - D3D9ObjDesc_t* getObjDesc() {return &objDesc_;} - cl_image_format getCLFormatFromD3D9(); - cl_image_format getCLFormatFromD3D9(D3DFORMAT d3d9Fmt, cl_uint plane); - // On acquire copy data from original resource to shared resource - virtual bool copyOrigToShared(); - // On release copy data from shared copy to the original resource - virtual bool copySharedToOrig(); -}; + 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]; -class Image2DD3D9 : public D3D9Object , public Image -{ -protected: - //! Initializes the device memory array which is nested - // after'Image2DD3D9' object in memory layout. - virtual void initDeviceMemory(); -public: -//! Image2DD3D9 constructor just calls constructors of base classes -//! to pass down the parameters - Image2DD3D9( - Context& amdContext, - cl_mem_flags clFlags, - D3D9Object& d3d9obj) - : // Call base classes constructors - D3D9Object(d3d9obj), - Image( - amdContext, - CL_MEM_OBJECT_IMAGE2D, - clFlags, - d3d9obj.getCLFormatFromD3D9(), - d3d9obj.getWidth(), - d3d9obj.getHeight(), - 1, - d3d9obj.getWidth() * d3d9obj.getElementBytes(), //rowPitch), - 0) - { - setInteropObj(this); + 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)); + } } - virtual ~Image2DD3D9() {} -}; + } + if (compatible_devices.size() == 0) { + *not_null(num_devices) = 0; + errcode = CL_DEVICE_NOT_FOUND; + break; + } -cl_mem clCreateImage2DFromD3D9ResourceAMD( - 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); + auto it = compatible_devices.cbegin(); + cl_uint compatible_count = std::min(num_entries, (cl_uint)compatible_devices.size()); -void SyncD3D9Objects(std::vector& memObjects); + while (compatible_count--) { + *devices++ = as_cl(*it++); + --num_entries; + } + while (num_entries--) { + *devices++ = (cl_device_id)0; + } -} //namespace amd + *not_null(num_devices) = (cl_uint)compatible_devices.size(); + } break; -#endif /* __OPENCL_CL_D3D9_AMD_H */ + 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::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::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 + +// +// +// namespace amd +// +// +namespace amd { +/*! @} + * \addtogroup CL-D3D9 interop helper functions + * @{ + */ +// +// Class D3D9Object implementation +// +std::vector> D3D9Object::resources_; +Monitor D3D9Object::resLock_; + +// +// clCreateImage2DFromD3D9ResourceAMD +// +cl_mem clCreateImage2DFromD3D9ResourceAMD(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; + + D3D9Object obj; + cl_int errcode = D3D9Object::initD3D9Object(amdContext, adapter_type, surface_info, plane, obj); + if (CL_SUCCESS != errcode) { + *not_null(errcode_ret) = errcode; + return (cl_mem)0; + } + + Image2DD3D9* pImage2DD3D9 = new (amdContext) 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 SyncD3D9Objects(std::vector& memObjects) { + Memory*& mem = memObjects.front(); + if (!mem) { + LogWarning("\nNULL memory object\n"); + return; + } + InteropObject* interop = mem->getInteropObj(); + if (!interop) { + LogWarning("\nNULL interop object\n"); + return; + } + D3D9Object* d3d9Obj = interop->asD3D9Object(); + if (!d3d9Obj) { + LogWarning("\nNULL D3D9 object\n"); + return; + } + IDirect3DQuery9* query = d3d9Obj->getQuery(); + if (!query) { + LogWarning("\nNULL IDirect3DQuery9\n"); + return; + } + ScopedLock sl(d3d9Obj->getResLock()); + query->Issue(D3DISSUE_END); + BOOL data = FALSE; + while (S_OK != query->GetData(&data, sizeof(BOOL), D3DGETDATA_FLUSH)) { + } +} + +// +// Class D3D10Object implementation +// +size_t D3D9Object::getElementBytes(D3DFORMAT d3d9Format, cl_uint plane) { + size_t bytesPerPixel; + + switch (d3d9Format) { + case D3DFMT_UNKNOWN: + case D3DFMT_UYVY: + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + case D3DFMT_VERTEXDATA: + case D3DFMT_D32: + case D3DFMT_D15S1: + case D3DFMT_D24S8: + case D3DFMT_D24X8: + case D3DFMT_D24X4S4: + case D3DFMT_D16: + case D3DFMT_INDEX16: + case D3DFMT_INDEX32: + case D3DFMT_MULTI2_ARGB8: + case D3DFMT_CxV8U8: + // Less than 1 byte per pixel - needs special consideration + bytesPerPixel = 0; + break; + + case D3DFMT_R3G3B2: + case D3DFMT_P8: + case D3DFMT_A8: + case D3DFMT_L8: + case D3DFMT_A4L4: + bytesPerPixel = 1; + break; + + case D3DFMT_R16F: + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_A8R3G3B2: + case D3DFMT_X4R4G4B4: + case D3DFMT_A8P8: + case D3DFMT_A8L8: + case D3DFMT_V8U8: + case D3DFMT_L6V5U5: + case D3DFMT_D16_LOCKABLE: + case D3DFMT_L16: + bytesPerPixel = 2; + break; + + case D3DFMT_R8G8B8: + case D3DFMT_D24FS8: + bytesPerPixel = 3; + break; + + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_A8R8G8B8: + case D3DFMT_R32F: + case D3DFMT_X8R8G8B8: + case D3DFMT_A2B10G10R10: + case D3DFMT_A8B8G8R8: + case D3DFMT_X8B8G8R8: + case D3DFMT_G16R16: + case D3DFMT_A2R10G10B10: + case D3DFMT_Q8W8V8U8: + case D3DFMT_X8L8V8U8: + case D3DFMT_V16U16: + case D3DFMT_A2W10V10U10: + case D3DFMT_R8G8_B8G8: + case D3DFMT_G8R8_G8B8: + case D3DFMT_G16R16F: + case D3DFMT_YUY2: + bytesPerPixel = 4; + break; + + case D3DFMT_G32R32F: + case D3DFMT_A16B16G16R16: + case D3DFMT_A16B16G16R16F: + case D3DFMT_Q16W16V16U16: + bytesPerPixel = 8; + break; + case D3DFMT_A32B32G32R32F: + bytesPerPixel = 16; + break; + //#if !defined(D3D_DISABLE_9EX) + // case D3DFMT_D32_LOCKABLE: + // case D3DFMT_S8_LOCKABLE: + //#endif // !D3D_DISABLE_9EX + case D3DFMT_NV_12: + if (plane == 0) { + bytesPerPixel = 1; + } else if (plane == 1) { + bytesPerPixel = 2; + } // plane != 0 or != 1 shouldn't happen here + break; + case D3DFMT_P010: + if (plane == 0) { + bytesPerPixel = 2; + } else if (plane == 1) { + bytesPerPixel = 4; + } // plane != 0 or != 1 shouldn't happen here + break; + case D3DFMT_YV_12: + bytesPerPixel = 1; + break; + + default: + bytesPerPixel = 0; + _ASSERT(FALSE); + break; + } + return bytesPerPixel; +} + +void setObjDesc(amd::D3D9ObjDesc_t& objDesc, D3DSURFACE_DESC& resDesc, cl_uint plane) { + objDesc.d3dPool_ = resDesc.Pool; + objDesc.resType_ = resDesc.Type; + objDesc.usage_ = resDesc.Usage; + objDesc.d3dFormat_ = resDesc.Format; + switch (resDesc.Format) { + case D3DFMT_NV_12: + case D3DFMT_P010: + objDesc.surfRect_.left = 0; + objDesc.surfRect_.top = 0; + if (plane == 0) { + objDesc.objSize_.Height = resDesc.Height; + objDesc.objSize_.Width = resDesc.Width; + objDesc.surfRect_.right = resDesc.Width; // resDesc.Width/2-1; + objDesc.surfRect_.bottom = 3 * resDesc.Height / 2; + ; // 3*resDesc.Height/2-1; + } else if (plane == 1) { + objDesc.objSize_.Height = resDesc.Height / 2; + objDesc.objSize_.Width = resDesc.Width / 2; + objDesc.surfRect_.right = resDesc.Width; // resDesc.Width/2-1; + objDesc.surfRect_.bottom = 3 * resDesc.Height / 2; + ; // 3*resDesc.Height/2-1; + } // plane != 0 or != 1 shouldn't happen here + break; + case D3DFMT_YV_12: + objDesc.surfRect_.left = 0; + if (plane == 0) { + objDesc.objSize_.Height = resDesc.Height; + objDesc.objSize_.Width = resDesc.Width; + objDesc.surfRect_.top = 0; + objDesc.surfRect_.right = resDesc.Width - 1; + objDesc.surfRect_.bottom = resDesc.Height - 1; + } else if (plane == 1) { + objDesc.objSize_.Height = resDesc.Height / 2; + objDesc.objSize_.Width = resDesc.Width / 2; + objDesc.surfRect_.top = resDesc.Height; + objDesc.surfRect_.right = resDesc.Width / 2 - 1; + objDesc.surfRect_.bottom = 3 * resDesc.Height / 2 - 1; + } else if (plane == 2) { + objDesc.objSize_.Height = resDesc.Height / 2; + objDesc.objSize_.Width = resDesc.Width / 2; + objDesc.surfRect_.top = 3 * resDesc.Height / 2; + objDesc.surfRect_.right = resDesc.Width / 2 - 1; + objDesc.surfRect_.bottom = 2 * resDesc.Height - 1; + } // plane > 0 or > 2 shouldn't happen here + break; + default: + objDesc.objSize_.Height = resDesc.Height; + objDesc.objSize_.Width = resDesc.Width; + objDesc.surfRect_.left = 0; + objDesc.surfRect_.top = 0; + objDesc.surfRect_.right = resDesc.Width - 1; + objDesc.surfRect_.bottom = resDesc.Height - 1; + if (resDesc.Format == D3DFMT_YUY2) { + objDesc.objSize_.Width >>= 1; + } + break; + } +} + +int D3D9Object::initD3D9Object(const Context& amdContext, + cl_dx9_media_adapter_type_khr adapter_type, + cl_dx9_surface_info_khr* cl_surf_info, cl_uint plane, + D3D9Object& obj) { + ScopedLock sl(resLock_); + + IDirect3DDevice9Ex* pDev9Ex = NULL; + cl_int errcode = CL_SUCCESS; + + // Check if this ressource has already been used for interop + IDirect3DSurface9* pD3D9res = cl_surf_info->resource; + HANDLE shared_handle = cl_surf_info->shared_handle; + + if ((adapter_type == CL_ADAPTER_D3D9_KHR) || (adapter_type == CL_ADAPTER_DXVA_KHR)) { + return CL_INVALID_DX9_MEDIA_ADAPTER_KHR; // Not supported yet + } + + for (const auto& it : resources_) { + if (it.first.surfInfo.resource == cl_surf_info->resource && it.first.surfPlane == plane) { + return CL_INVALID_D3D9_RESOURCE_KHR; + } + } + + HRESULT hr; + D3DQUERYTYPE desc = D3DQUERYTYPE_EVENT; + + D3DSURFACE_DESC resDesc; + if (D3D_OK != pD3D9res->GetDesc(&resDesc)) { + return CL_INVALID_D3D9_RESOURCE_KHR; + } + + hr = pD3D9res->GetContainer(IID_IDirect3DDevice9Ex, (void**)&pDev9Ex); + if (hr == D3D_OK) { + pDev9Ex->CreateQuery(desc, &(obj.pQuery_)); + } else { + return CL_INVALID_D3D9_RESOURCE_KHR; // d3d9ex should be supported + } + + obj.handleShared_ = shared_handle; + obj.surfPlane_ = plane; + obj.surfInfo_ = *cl_surf_info; + obj.adapterType_ = adapter_type; + + // Init defaults + setObjDesc(obj.objDescOrig_, resDesc, plane); + obj.objDesc_ = obj.objDescOrig_; + + // shared handle cases if the shared_handle is NULL + // first check if the format is NV12 or YV12, which we need special handling + if (NULL == shared_handle) { + bool found = false; + for (const auto& it : resources_) { + if (it.first.surfInfo.resource == cl_surf_info->resource && + it.first.surfPlane != plane) { + obj.handleShared_ = it.second.surfInfo.shared_handle; + obj.pD3D9Res_ = it.second.surfInfo.resource; + obj.pD3D9Res_->AddRef(); + obj.objDesc_ = obj.objDescOrig_; + found = true; + break; + } + } + if (!found) { + obj.handleShared_ = 0; + hr = pDev9Ex->CreateOffscreenPlainSurface(resDesc.Width, resDesc.Height, resDesc.Format, + resDesc.Pool, &obj.pD3D9Res_, &obj.handleShared_); + + if (D3D_OK != hr) { + errcode = CL_INVALID_D3D9_RESOURCE_KHR; + } + } + + // put the original info into the obj + obj.pD3D9ResOrig_ = pD3D9res; + obj.pD3D9ResOrig_->AddRef(); // addRef in case lost the resource + } else { + // Share the original resource + obj.pD3D9ResOrig_ = NULL; + obj.pD3D9Res_ = pD3D9res; + obj.pD3D9Res_->AddRef(); + } + + // Release the Ex interface + if (pDev9Ex) pDev9Ex->Release(); + + // Check for CL format compatibilty + if (obj.objDesc_.resType_ == D3DRTYPE_SURFACE) { + cl_image_format clFmt = obj.getCLFormatFromD3D9(obj.objDesc_.d3dFormat_, plane); + amd::Image::Format imageFormat(clFmt); + if (!imageFormat.isSupported(amdContext)) { + return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR; + } + } + + TD3D9RESINFO d3d9ObjOri = {*cl_surf_info, plane}; + TD3D9RESINFO d3d9ObjShared = {{obj.pD3D9Res_, obj.handleShared_}, plane}; + + if (errcode == CL_SUCCESS) { + resources_.push_back({d3d9ObjOri, d3d9ObjShared}); + } + + return errcode; +} +cl_uint D3D9Object::getMiscFlag() { + switch (objDescOrig_.d3dFormat_) { + case D3DFMT_NV_12: + case D3DFMT_P010: + return 1; + break; + case D3DFMT_YV_12: + return 2; + break; + case D3DFMT_YUY2: + return 3; + break; + default: + return 0; + break; + } +} + +cl_image_format D3D9Object::getCLFormatFromD3D9() { + return getCLFormatFromD3D9(objDesc_.d3dFormat_, surfPlane_); +} + +cl_image_format D3D9Object::getCLFormatFromD3D9(D3DFORMAT d3d9Fmt, cl_uint plane) { + cl_image_format fmt; + + fmt.image_channel_order = 0; // CL_RGBA; + fmt.image_channel_data_type = 0; // CL_UNSIGNED_INT8; + + switch (d3d9Fmt) { + case D3DFMT_R32F: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case D3DFMT_R16F: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case D3DFMT_L16: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case D3DFMT_A8: + fmt.image_channel_order = CL_A; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case D3DFMT_L8: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case D3DFMT_G32R32F: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case D3DFMT_G16R16F: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case D3DFMT_G16R16: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case D3DFMT_A8L8: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case D3DFMT_A32B32G32R32F: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case D3DFMT_A16B16G16R16F: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case D3DFMT_A16B16G16R16: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case D3DFMT_A8B8G8R8: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case D3DFMT_X8B8G8R8: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case D3DFMT_A8R8G8B8: + fmt.image_channel_order = CL_BGRA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case D3DFMT_X8R8G8B8: + fmt.image_channel_order = CL_BGRA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + case D3DFMT_NV_12: + fmt.image_channel_data_type = CL_UNORM_INT8; + if (plane == 0) { + fmt.image_channel_order = CL_R; + } else if (plane == 1) { + fmt.image_channel_order = CL_RG; + } + break; + case D3DFMT_P010: + fmt.image_channel_data_type = CL_UNORM_INT16; + if (plane == 0) { + fmt.image_channel_order = CL_R; + } else if (plane == 1) { + fmt.image_channel_order = CL_RG; + } + break; + case D3DFMT_YV_12: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + case D3DFMT_YUY2: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + case D3DFMT_UNKNOWN: + case D3DFMT_R8G8B8: + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_R3G3B2: + case D3DFMT_A8R3G3B2: + case D3DFMT_X4R4G4B4: + case D3DFMT_A2B10G10R10: + case D3DFMT_A2R10G10B10: + case D3DFMT_A8P8: + case D3DFMT_P8: + case D3DFMT_A4L4: + case D3DFMT_V8U8: + case D3DFMT_L6V5U5: + case D3DFMT_X8L8V8U8: + case D3DFMT_Q8W8V8U8: + case D3DFMT_V16U16: + case D3DFMT_A2W10V10U10: + case D3DFMT_UYVY: + case D3DFMT_R8G8_B8G8: + case D3DFMT_G8R8_G8B8: + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D32: + case D3DFMT_D15S1: + case D3DFMT_D24S8: + case D3DFMT_D24X8: + case D3DFMT_D24X4S4: + case D3DFMT_D16: + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D24FS8: + //#if !defined(D3D_DISABLE_9EX) + case D3DFMT_D32_LOCKABLE: + case D3DFMT_S8_LOCKABLE: + //#endif // !D3D_DISABLE_9EX + case D3DFMT_VERTEXDATA: + case D3DFMT_INDEX16: + case D3DFMT_INDEX32: + case D3DFMT_Q16W16V16U16: + case D3DFMT_MULTI2_ARGB8: + case D3DFMT_CxV8U8: + //#if !defined(D3D_DISABLE_9EX) + case D3DFMT_A1: + case D3DFMT_A2B10G10R10_XR_BIAS: + case D3DFMT_BINARYBUFFER: + _ASSERT(FALSE); // NOT SURPPORTED + break; + //#endif // !D3D_DISABLE_9EX + default: + _ASSERT(FALSE); + break; + } + + return fmt; +} + +bool D3D9Object::copyOrigToShared() { + // Don't copy if there is no orig + if (NULL == getD3D9ResOrig()) return true; + + IDirect3DDevice9Ex* d3dDev; + HRESULT hr; + ScopedLock sl(getResLock()); + + IDirect3DSurface9* srcSurf = getD3D9ResOrig(); + IDirect3DSurface9* dstSurf = getD3D9Resource(); + + hr = getD3D9Resource()->GetContainer(IID_IDirect3DDevice9Ex, (void**)&d3dDev); + if (hr != D3D_OK || !d3dDev) { + LogError("\nCannot get D3D9 device from D3D9 surface\n"); + return false; + } + + hr = d3dDev->StretchRect(srcSurf, NULL, dstSurf, NULL, D3DTEXF_NONE); + if (hr != D3D_OK) { + LogError("\ncopy original surface to shared surface failed\n"); + return false; + } + // Flush D3D queues and make sure D3D stuff is finished + pQuery_->Issue(D3DISSUE_END); + BOOL data; + while ((D3D_OK != pQuery_->GetData(&data, sizeof(BOOL), D3DGETDATA_FLUSH)) && (data != TRUE)) { + } + + if (d3dDev) d3dDev->Release(); + return true; +} + +bool D3D9Object::copySharedToOrig() { + // Don't copy if there is no orig + if (NULL == getD3D9ResOrig()) return true; + + IDirect3DDevice9Ex* d3dDev; + HRESULT hr; + ScopedLock sl(getResLock()); + + hr = getD3D9Resource()->GetContainer(IID_IDirect3DDevice9Ex, (void**)&d3dDev); + if (hr != D3D_OK || !d3dDev) { + LogError("\nCannot get D3D9 device from D3D9 surface\n"); + return false; + } + + hr = d3dDev->StretchRect(getD3D9Resource(), NULL, getD3D9ResOrig(), NULL, D3DTEXF_NONE); + if (hr != D3D_OK) { + LogError("\ncopy shared surface to original surface failed\n"); + return false; + } + + if (d3dDev) d3dDev->Release(); + return true; +} + +void Image2DD3D9::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image2DD3D9)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +} // namespace amd + +#endif //_WIN32