From 88736010fb45cccbc959af133175fb95a1d0c121 Mon Sep 17 00:00:00 2001 From: Ajay Date: Tue, 7 Feb 2023 22:33:18 +0000 Subject: [PATCH] SWDEV-381627 - adding cl interop files to vdi Change-Id: Ic40363587a2bc56f977a148eba386dfb73d6286e --- rocclr/cmake/ROCclr.cmake | 5 + rocclr/device/pal/palmemory.cpp | 8 +- rocclr/device/pal/palvirtual.cpp | 6 +- rocclr/device/rocm/rocmemory.cpp | 2 +- rocclr/platform/context.cpp | 2 +- rocclr/platform/interop_d3d10.cpp | 871 ++++++++++++++++++++++++++ rocclr/platform/interop_d3d10.hpp | 303 ++++++++++ rocclr/platform/interop_d3d11.cpp | 976 ++++++++++++++++++++++++++++++ rocclr/platform/interop_d3d11.hpp | 305 ++++++++++ rocclr/platform/interop_d3d9.cpp | 570 +++++++++++++++++ rocclr/platform/interop_d3d9.hpp | 190 ++++++ rocclr/platform/interop_gl.cpp | 803 ++++++++++++++++++++++++ rocclr/platform/interop_gl.hpp | 396 ++++++++++++ rocclr/platform/runtime.cpp | 2 +- 14 files changed, 4429 insertions(+), 10 deletions(-) create mode 100644 rocclr/platform/interop_d3d10.cpp create mode 100644 rocclr/platform/interop_d3d10.hpp create mode 100644 rocclr/platform/interop_d3d11.cpp create mode 100644 rocclr/platform/interop_d3d11.hpp create mode 100644 rocclr/platform/interop_d3d9.cpp create mode 100644 rocclr/platform/interop_d3d9.hpp create mode 100644 rocclr/platform/interop_gl.cpp create mode 100644 rocclr/platform/interop_gl.hpp diff --git a/rocclr/cmake/ROCclr.cmake b/rocclr/cmake/ROCclr.cmake index 18ed07321a..6d6d17c125 100644 --- a/rocclr/cmake/ROCclr.cmake +++ b/rocclr/cmake/ROCclr.cmake @@ -84,6 +84,7 @@ target_sources(rocclr PRIVATE ${ROCCLR_SRC_DIR}/platform/ndrange.cpp ${ROCCLR_SRC_DIR}/platform/program.cpp ${ROCCLR_SRC_DIR}/platform/runtime.cpp + ${ROCCLR_SRC_DIR}/platform/interop_gl.cpp ${ROCCLR_SRC_DIR}/thread/monitor.cpp ${ROCCLR_SRC_DIR}/thread/semaphore.cpp ${ROCCLR_SRC_DIR}/thread/thread.cpp @@ -91,6 +92,10 @@ target_sources(rocclr PRIVATE ${ROCCLR_SRC_DIR}/utils/flags.cpp) if(WIN32) + target_sources(rocclr PRIVATE + ${ROCCLR_SRC_DIR}/platform/interop_d3d9.cpp + ${ROCCLR_SRC_DIR}/platform/interop_d3d10.cpp + ${ROCCLR_SRC_DIR}/platform/interop_d3d11.cpp) target_compile_definitions(rocclr PUBLIC ATI_OS_WIN) else() target_compile_definitions(rocclr PUBLIC ATI_OS_LINUX) diff --git a/rocclr/device/pal/palmemory.cpp b/rocclr/device/pal/palmemory.cpp index 6259df9f58..d7c086b488 100644 --- a/rocclr/device/pal/palmemory.cpp +++ b/rocclr/device/pal/palmemory.cpp @@ -29,11 +29,11 @@ #ifdef _WIN32 #include -#include "amdocl/cl_d3d9_amd.hpp" -#include "amdocl/cl_d3d10_amd.hpp" -#include "amdocl/cl_d3d11_amd.hpp" +#include "platform/interop_d3d9.hpp" +#include "platform/interop_d3d10.hpp" +#include "platform/interop_d3d11.hpp" #endif //_WIN32 -#include "amdocl/cl_gl_amd.hpp" +#include "platform/interop_gl.hpp" #include "amdocl/cl_vk_amd.hpp" #include diff --git a/rocclr/device/pal/palvirtual.cpp b/rocclr/device/pal/palvirtual.cpp index 624379d104..4b899748a5 100644 --- a/rocclr/device/pal/palvirtual.cpp +++ b/rocclr/device/pal/palvirtual.cpp @@ -45,9 +45,9 @@ #ifdef _WIN32 #include -#include "amdocl/cl_d3d9_amd.hpp" -#include "amdocl/cl_d3d10_amd.hpp" -#include "amdocl/cl_d3d11_amd.hpp" +#include "platform/interop_d3d9.hpp" +#include "platform/interop_d3d10.hpp" +#include "platform/interop_d3d11.hpp" #endif // _WIN32 namespace pal { diff --git a/rocclr/device/rocm/rocmemory.cpp b/rocclr/device/rocm/rocmemory.cpp index d267e0d03f..664bc62b63 100644 --- a/rocclr/device/rocm/rocmemory.cpp +++ b/rocclr/device/rocm/rocmemory.cpp @@ -35,7 +35,7 @@ #include "thread/monitor.hpp" #include "platform/memory.hpp" #include "platform/sampler.hpp" -#include "amdocl/cl_gl_amd.hpp" +#include "platform/interop_gl.hpp" #include "amdocl/cl_vk_amd.hpp" namespace roc { diff --git a/rocclr/platform/context.cpp b/rocclr/platform/context.cpp index 965269e8c7..6d0bc27288 100644 --- a/rocclr/platform/context.cpp +++ b/rocclr/platform/context.cpp @@ -19,7 +19,7 @@ THE SOFTWARE. */ #include "platform/context.hpp" -#include "amdocl/cl_gl_amd.hpp" +#include "platform/interop_gl.hpp" #include "vdi_common.hpp" #include "platform/commandqueue.hpp" diff --git a/rocclr/platform/interop_d3d10.cpp b/rocclr/platform/interop_d3d10.cpp new file mode 100644 index 0000000000..75760c5a46 --- /dev/null +++ b/rocclr/platform/interop_d3d10.cpp @@ -0,0 +1,871 @@ +/* Copyright (c) 2009 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#ifdef _WIN32 + +#include "top.hpp" + +#include "cl_common.hpp" +#include "platform/interop_d3d10.hpp" +#include "platform/command.hpp" + +#include +#include + +namespace amd { + +size_t D3D10Object::getElementBytes(DXGI_FORMAT dxgiFmt) { + size_t bytesPerPixel; + + switch (dxgiFmt) { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + bytesPerPixel = 16; + break; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + bytesPerPixel = 12; + break; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + bytesPerPixel = 8; + break; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + bytesPerPixel = 4; + break; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + bytesPerPixel = 2; + break; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R1_UNORM: + bytesPerPixel = 1; + break; + + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + // Less than 1 byte per pixel - needs special consideration + bytesPerPixel = 0; + break; + + default: + bytesPerPixel = 0; + _ASSERT(FALSE); + break; + } + return bytesPerPixel; +} + +cl_image_format D3D10Object::getCLFormatFromDXGI(DXGI_FORMAT dxgiFmt) { + cl_image_format fmt; + + //! @todo [odintsov]: add real fmt conversion from DXGI to CL + fmt.image_channel_order = 0; // CL_RGBA; + fmt.image_channel_data_type = 0; // CL_UNSIGNED_INT8; + + switch (dxgiFmt) { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32G32B32A32_UINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32B32A32_SINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + fmt.image_channel_order = CL_RGB; + break; + + case DXGI_FORMAT_R32G32B32_FLOAT: + fmt.image_channel_order = CL_RGB; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32G32B32_UINT: + fmt.image_channel_order = CL_RGB; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32B32_SINT: + fmt.image_channel_order = CL_RGB; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case DXGI_FORMAT_R16G16B16A16_UNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16G16B16A16_UINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + break; + + case DXGI_FORMAT_R16G16B16A16_SNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SNORM_INT16; + break; + + case DXGI_FORMAT_R16G16B16A16_SINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SIGNED_INT16; + break; + + case DXGI_FORMAT_R32G32_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_R32G32_FLOAT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32G32_UINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32_SINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R32G8X24_TYPELESS: + break; + + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + break; + + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + break; + + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + break; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R10G10B10A2_UINT: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R11G11B10_FLOAT: + fmt.image_channel_order = CL_RGB; + break; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_UINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_SNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SNORM_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_SINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SIGNED_INT8; + break; + + case DXGI_FORMAT_R16G16_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_R16G16_FLOAT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case DXGI_FORMAT_R16G16_UNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16G16_UINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + break; + + case DXGI_FORMAT_R16G16_SNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SNORM_INT16; + break; + + case DXGI_FORMAT_R16G16_SINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SIGNED_INT16; + break; + + case DXGI_FORMAT_R32_TYPELESS: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_D32_FLOAT: + break; + + case DXGI_FORMAT_R32_FLOAT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32_UINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32_SINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R24G8_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + break; + + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + break; + + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + break; + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_G8R8_G8B8_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + fmt.image_channel_order = CL_BGRA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_R8G8_UNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8_UINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + + case DXGI_FORMAT_R8G8_SNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SNORM_INT8; + break; + + case DXGI_FORMAT_R8G8_SINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SIGNED_INT8; + break; + + case DXGI_FORMAT_R16_TYPELESS: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_R16_FLOAT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case DXGI_FORMAT_D16_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16_UNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16_UINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + break; + + case DXGI_FORMAT_R16_SNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SNORM_INT16; + break; + + case DXGI_FORMAT_R16_SINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SIGNED_INT16; + break; + + case DXGI_FORMAT_B5G6R5_UNORM: + fmt.image_channel_data_type = CL_UNORM_SHORT_565; + break; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + fmt.image_channel_order = CL_BGRA; + break; + + case DXGI_FORMAT_R8_TYPELESS: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_R8_UNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8_UINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + + case DXGI_FORMAT_R8_SNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SNORM_INT8; + break; + + case DXGI_FORMAT_R8_SINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SIGNED_INT8; + break; + + case DXGI_FORMAT_A8_UNORM: + fmt.image_channel_order = CL_A; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R1_UNORM: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + break; + + default: + _ASSERT(FALSE); + break; + } + + return fmt; +} + +size_t D3D10Object::getResourceByteSize() { + size_t bytes = 1; + + //! @todo [odintsov]: take into consideration the mip level?! + + switch (objDesc_.objDim_) { + case D3D10_RESOURCE_DIMENSION_BUFFER: + bytes = objDesc_.objSize_.ByteWidth; + break; + + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: + bytes = objDesc_.objSize_.Depth; + + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: + bytes *= objDesc_.objSize_.Height; + + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: + bytes *= objDesc_.objSize_.Width * getElementBytes(); + break; + + default: + LogError("getResourceByteSize: unknown type of D3D10 resource"); + bytes = 0; + break; + } + return bytes; +} + +int D3D10Object::initD3D10Object(const Context& amdContext, ID3D10Resource* pRes, UINT subres, + D3D10Object& obj) { + ID3D10Device* pDev; + HRESULT hr; + ScopedLock sl(resLock_); + + // Check if this ressource has already been used for interop + for (const auto& it : resources_) { + if (it.first == (void*)pRes && it.second == subres) { + return CL_INVALID_D3D10_RESOURCE_KHR; + } + } + + (obj.pD3D10Res_ = pRes)->GetDevice(&pDev); + + if (!pDev) { + return CL_INVALID_D3D10_DEVICE_KHR; + } + + D3D10_QUERY_DESC desc = {D3D10_QUERY_EVENT, 0}; + pDev->CreateQuery(&desc, &obj.pQuery_); + +#define SET_SHARED_FLAGS() \ + { \ + obj.pD3D10ResOrig_ = obj.pD3D10Res_; \ + memcpy(&obj.objDescOrig_, &obj.objDesc_, sizeof(D3D10ObjDesc_t)); \ + /* @todo - Check device type and select right usage for resource */ \ + /* For now get only DPU path, CPU path for buffers */ \ + /* will not worl on DEFAUL resources */ \ + /*desc.Usage = D3D10_USAGE_STAGING;*/ \ + desc.Usage = D3D10_USAGE_DEFAULT; \ + desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED; \ + desc.CPUAccessFlags = 0; \ + } + +#define STORE_SHARED_FLAGS(restype) \ + { \ + if (S_OK == hr && obj.pD3D10Res_) { \ + obj.objDesc_.objFlags_.d3d10Usage_ = desc.Usage; \ + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; \ + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; \ + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; \ + } else { \ + LogError("\nCannot create shared " #restype "\n"); \ + return CL_INVALID_D3D10_RESOURCE_KHR; \ + } \ + } + +#define SET_BINDING() \ + { \ + switch (desc.Format) { \ + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: \ + case DXGI_FORMAT_D32_FLOAT: \ + case DXGI_FORMAT_D24_UNORM_S8_UINT: \ + case DXGI_FORMAT_D16_UNORM: \ + desc.BindFlags = D3D10_BIND_DEPTH_STENCIL; \ + break; \ + default: \ + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; \ + break; \ + } \ + } + + pRes->GetType(&obj.objDesc_.objDim_); + + // Init defaults + obj.objDesc_.objSize_.Height = 1; + obj.objDesc_.objSize_.Depth = 1; + obj.objDesc_.mipLevels_ = 1; + obj.objDesc_.arraySize_ = 1; + obj.objDesc_.dxgiFormat_ = DXGI_FORMAT_UNKNOWN; + obj.objDesc_.dxgiSampleDesc_ = dxgiSampleDescDefault; + + switch (obj.objDesc_.objDim_) { + case D3D10_RESOURCE_DIMENSION_BUFFER: // = 1, + { + D3D10_BUFFER_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + obj.objDesc_.objSize_.ByteWidth = desc.ByteWidth; + obj.objDesc_.objFlags_.d3d10Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + // Handle D3D10Buffer without shared handle - create + // a duplicate with shared handle to provide for CAL + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D10_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET; + hr = pDev->CreateBuffer(&desc, nullptr, (ID3D10Buffer**)&obj.pD3D10Res_); + STORE_SHARED_FLAGS(ID3D10Buffer); + } + } break; + + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: // = 2, + { + D3D10_TEXTURE1D_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + + if (subres) { + // Calculate correct size of the subresource + UINT miplevel = subres; + if (desc.ArraySize > 1) { + miplevel = subres % desc.ArraySize; + } + if (miplevel >= desc.MipLevels) { + LogWarning("\nMiplevel >= number of miplevels\n"); + } + if (subres >= desc.MipLevels * desc.ArraySize) { + return CL_INVALID_VALUE; + } + desc.Width >>= miplevel; + if (!desc.Width) { + desc.Width = 1; + } + } + obj.objDesc_.objSize_.Width = desc.Width; + obj.objDesc_.mipLevels_ = desc.MipLevels; + obj.objDesc_.arraySize_ = desc.ArraySize; + obj.objDesc_.dxgiFormat_ = desc.Format; + obj.objDesc_.objFlags_.d3d10Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + // Handle D3D10Texture1D without shared handle - create + // a duplicate with shared handle and provide it for CAL + // Workaround for subresource > 0 in shared resource + if (subres) obj.objDesc_.objFlags_.miscFlags_ &= ~(D3D10_RESOURCE_MISC_SHARED); + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D10_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + SET_BINDING(); + obj.objDesc_.mipLevels_ = desc.MipLevels = 1; + obj.objDesc_.arraySize_ = desc.ArraySize = 1; + hr = pDev->CreateTexture1D(&desc, nullptr, (ID3D10Texture1D**)&obj.pD3D10Res_); + STORE_SHARED_FLAGS(ID3D10Texture1D); + } + } break; + + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: // = 3, + { + D3D10_TEXTURE2D_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + + if (subres) { + // Calculate correct size of the subresource + UINT miplevel = subres; + if (desc.ArraySize > 1) { + miplevel = subres % desc.MipLevels; + } + if (miplevel >= desc.MipLevels) { + LogWarning("\nMiplevel >= number of miplevels\n"); + } + if (subres >= desc.MipLevels * desc.ArraySize) { + return CL_INVALID_VALUE; + } + desc.Width >>= miplevel; + if (!desc.Width) { + desc.Width = 1; + } + desc.Height >>= miplevel; + if (!desc.Height) { + desc.Height = 1; + } + } + obj.objDesc_.objSize_.Width = desc.Width; + obj.objDesc_.objSize_.Height = desc.Height; + obj.objDesc_.mipLevels_ = desc.MipLevels; + obj.objDesc_.arraySize_ = desc.ArraySize; + obj.objDesc_.dxgiFormat_ = desc.Format; + obj.objDesc_.dxgiSampleDesc_ = desc.SampleDesc; + obj.objDesc_.objFlags_.d3d10Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + // Handle D3D10Texture2D without shared handle - create + // a duplicate with shared handle and provide it for CAL + // Workaround for subresource > 0 in shared resource + if (subres) obj.objDesc_.objFlags_.miscFlags_ &= ~(D3D10_RESOURCE_MISC_SHARED); + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D10_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + SET_BINDING(); + obj.objDesc_.mipLevels_ = desc.MipLevels = 1; + obj.objDesc_.arraySize_ = desc.ArraySize = 1; + hr = pDev->CreateTexture2D(&desc, nullptr, (ID3D10Texture2D**)&obj.pD3D10Res_); + STORE_SHARED_FLAGS(ID3D10Texture2D); + } + } break; + + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: // = 4 + { + D3D10_TEXTURE3D_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + + if (subres) { + // Calculate correct size of the subresource + UINT miplevel = subres; + if (miplevel >= desc.MipLevels) { + LogWarning("\nMiplevel >= number of miplevels\n"); + } + if (subres >= desc.MipLevels) { + return CL_INVALID_VALUE; + } + desc.Width >>= miplevel; + if (!desc.Width) { + desc.Width = 1; + } + desc.Height >>= miplevel; + if (!desc.Height) { + desc.Height = 1; + } + desc.Depth >>= miplevel; + if (!desc.Depth) { + desc.Depth = 1; + } + } + obj.objDesc_.objSize_.Width = desc.Width; + obj.objDesc_.objSize_.Height = desc.Height; + obj.objDesc_.objSize_.Depth = desc.Depth; + obj.objDesc_.mipLevels_ = desc.MipLevels; + obj.objDesc_.dxgiFormat_ = desc.Format; + obj.objDesc_.objFlags_.d3d10Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + // Handle D3D10Texture3D without shared handle - create + // a duplicate with shared handle and provide it for CAL + // Workaround for subresource > 0 in shared resource + if (obj.objDesc_.mipLevels_ > 1) + obj.objDesc_.objFlags_.miscFlags_ &= ~(D3D10_RESOURCE_MISC_SHARED); + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D10_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + SET_BINDING(); + obj.objDesc_.mipLevels_ = desc.MipLevels = 1; + hr = pDev->CreateTexture3D(&desc, nullptr, (ID3D10Texture3D**)&obj.pD3D10Res_); + STORE_SHARED_FLAGS(ID3D10Texture3D); + } + } break; + + default: + LogError("unknown type of D3D10 resource"); + return CL_INVALID_D3D10_RESOURCE_KHR; + } + obj.subRes_ = subres; + pDev->Release(); + // Check for CL format compatibilty + if (obj.objDesc_.objDim_ != D3D10_RESOURCE_DIMENSION_BUFFER) { + cl_image_format clFmt = obj.getCLFormatFromDXGI(obj.objDesc_.dxgiFormat_); + amd::Image::Format imageFormat(clFmt); + if (!imageFormat.isSupported(amdContext)) { + return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR; + } + } + resources_.push_back({pRes, subres}); + return CL_SUCCESS; +} + +bool D3D10Object::copyOrigToShared() { + // Don't copy if there is no orig + if (nullptr == getD3D10ResOrig()) return true; + + ID3D10Device* d3dDev; + pD3D10Res_->GetDevice(&d3dDev); + if (!d3dDev) { + LogError("\nCannot get D3D10 device from D3D10 resource\n"); + return false; + } + // Any usage source can be read by GPU + d3dDev->CopySubresourceRegion(pD3D10Res_, 0, 0, 0, 0, pD3D10ResOrig_, subRes_, nullptr); + + // Flush D3D queues and make sure D3D stuff is finished + d3dDev->Flush(); + pQuery_->End(); + BOOL data = FALSE; + while ((S_OK != pQuery_->GetData(&data, sizeof(BOOL), 0)) || (data != TRUE)) { + } + + d3dDev->Release(); + return true; +} + +bool D3D10Object::copySharedToOrig() { + // Don't copy if there is no orig + if (nullptr == getD3D10ResOrig()) return true; + + ID3D10Device* d3dDev; + pD3D10Res_->GetDevice(&d3dDev); + if (!d3dDev) { + LogError("\nCannot get D3D10 device from D3D10 resource\n"); + return false; + } + + d3dDev->CopySubresourceRegion(pD3D10ResOrig_, subRes_, 0, 0, 0, pD3D10Res_, 0, nullptr); + + d3dDev->Release(); + return true; +} + +std::vector> D3D10Object::resources_; +Monitor D3D10Object::resLock_; + +void BufferD3D10::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(BufferD3D10)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +void Image1DD3D10::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image1DD3D10)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +void Image2DD3D10::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image2DD3D10)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +void Image3DD3D10::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image3DD3D10)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +} // namespace amd + +#endif //_WIN32 diff --git a/rocclr/platform/interop_d3d10.hpp b/rocclr/platform/interop_d3d10.hpp new file mode 100644 index 0000000000..0d7b230849 --- /dev/null +++ b/rocclr/platform/interop_d3d10.hpp @@ -0,0 +1,303 @@ +/* Copyright (c) 2008 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#pragma once + +#include "cl_common.hpp" + +#include "platform/context.hpp" +#include "platform/memory.hpp" + +#include + +namespace amd +{ + +typedef struct +{ + union + { + UINT ByteWidth; + UINT Width; + }; + UINT Height; + UINT Depth; +} D3D10ObjSize_t; + +typedef struct +{ + D3D10_USAGE d3d10Usage_; + UINT bindFlags_; + UINT cpuAccessFlags_; + UINT miscFlags_; +} D3D10Flags_t; + +typedef struct +{ + D3D10_RESOURCE_DIMENSION objDim_; + D3D10ObjSize_t objSize_; + D3D10Flags_t objFlags_; + UINT mipLevels_; + UINT arraySize_; + DXGI_FORMAT dxgiFormat_; + DXGI_SAMPLE_DESC dxgiSampleDesc_; +} D3D10ObjDesc_t; + +const DXGI_SAMPLE_DESC dxgiSampleDescDefault = {1, 0}; + +//! Class D3D10Object keeps all the info about the D3D10 object +//! from which the CL object is created +class D3D10Object : public InteropObject +{ +private: + ID3D10Resource* pD3D10Aux_; + + bool releaseResources_; + + static std::vector> resources_; + //! Global lock. + static Monitor resLock_; + +protected: + ID3D10Resource* pD3D10Res_; + ID3D10Resource* pD3D10ResOrig_; + ID3D10Query* pQuery_; + D3D10ObjDesc_t objDesc_; + D3D10ObjDesc_t objDescOrig_; + UINT subRes_; + +public: + // Default constructor + D3D10Object() + :pD3D10Aux_(nullptr) + ,releaseResources_(false) + ,pD3D10Res_(nullptr) + ,pD3D10ResOrig_(nullptr) + ,pQuery_(nullptr) + ,subRes_(0) + { + memset(&objDesc_,0,sizeof(objDesc_)); + memset(&objDescOrig_,0,sizeof(objDescOrig_)); + } + // Copy constructor + D3D10Object(D3D10Object& d3d10obj) + : pQuery_(nullptr) + { + *this = d3d10obj; + this->releaseResources_ = true; + // Add reference to the D3D10 resource to prevent its disappearance + if(pD3D10ResOrig_) { + pD3D10ResOrig_->AddRef(); + } + else if(pD3D10Res_) { + pD3D10Res_->AddRef(); + } + } + + //! Virtual destructor + virtual ~D3D10Object() + { + ScopedLock sl(resLock_); + if(releaseResources_) { + // Decrement reference to the D3D10 objects + if(pD3D10Res_) pD3D10Res_->Release(); + if(pD3D10Aux_) pD3D10Aux_->Release(); + if(pD3D10ResOrig_) pD3D10ResOrig_->Release(); + if(pQuery_) pQuery_->Release(); + // Check if this resource has already been used for interop + if(resources_.size()) { + for(auto& it = resources_.cbegin(); it != resources_.cend(); it++) { + if(((pD3D10ResOrig_ && (*it).first == (void*) pD3D10ResOrig_) + || ((*it).first == (void*) pD3D10Res_)) + && (*it).second == subRes_) { + resources_.erase(it); + break; + } + } + } + } + } + + static int initD3D10Object(const Context& amdContext, ID3D10Resource* pRes, UINT subresource, + D3D10Object& obj); + + D3D10Object* asD3D10Object() { return this; } + +//! D3D10Object query functions to get D3D10 info from member variables + ID3D10Resource* getD3D10Resource() const {return pD3D10Res_;} + ID3D10Resource* getD3D10ResOrig() const {return pD3D10ResOrig_;} + ID3D10Query* getQuery() const {return pQuery_;} + + UINT getWidth() const {return objDesc_.objSize_.Width;} + UINT getHeight() const {return objDesc_.objSize_.Height;} + UINT getDepth() const {return objDesc_.objSize_.Depth;} + size_t getElementBytes(DXGI_FORMAT dxgiFomat); + size_t getElementBytes() {return getElementBytes(objDesc_.dxgiFormat_);} + DXGI_FORMAT getDxgiFormat() {return objDesc_.dxgiFormat_;} + UINT getSubresource() const {return subRes_;} + const D3D10ObjDesc_t* getObjDesc() const { return &objDesc_; } + + //! Returns bytes per pixel > 0 if conversion successful, 0 otherwise; + //! if formats are not compatible, cl format channel + //! order and type are set to 0 + cl_image_format getCLFormatFromDXGI(DXGI_FORMAT dxgiFmt); + cl_image_format getCLFormatFromDXGI() + { + return getCLFormatFromDXGI(objDesc_.dxgiFormat_); + } + size_t getResourceByteSize(); + + // 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(); +}; + +//! Class BufferD3D10 is derived from classes Buffer and D3D10Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D10 object +class BufferD3D10 : public D3D10Object, public Buffer +{ +protected: + //! Initializes the device memory array which is nested + // after 'BufferD3D10' object in memory layout. + virtual void initDeviceMemory(); +public: + //! BufferD3D10 constructor just calls constructors of base classes + //! to pass down the parameters + BufferD3D10( + Context& amdContext, + cl_mem_flags clFlags, + D3D10Object& d3d10obj) + : // Call base classes constructors + D3D10Object(d3d10obj), + Buffer( + amdContext, + clFlags, + d3d10obj.getResourceByteSize()) + { + setInteropObj(this); + } + virtual ~BufferD3D10() {} +}; + +//! Class Image1DD3D10 is derived from classes Image1D and D3D10Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D10 object +class Image1DD3D10 : public D3D10Object, public Image +{ +protected: + //! Initializes the device memory array which is nested + // after'Image1DD3D10' object in memory layout. + virtual void initDeviceMemory(); +public: + //! Image1DD3D10 constructor just calls constructors of base classes + //! to pass down the parameters + Image1DD3D10( + Context& amdContext, + cl_mem_flags clFlags, + D3D10Object& d3d10obj) + : // Call base classes constructors + D3D10Object(d3d10obj), + Image( + amdContext, + CL_MEM_OBJECT_IMAGE1D, + clFlags, + getCLFormatFromDXGI(d3d10obj.getDxgiFormat()), //format, + d3d10obj.getWidth(), + 1, + 1, + d3d10obj.getWidth() * d3d10obj.getElementBytes(), //rowPitch), + 0) + { + setInteropObj(this); + } + virtual ~Image1DD3D10() {} +}; + +//! Class Image2DD3D10 is derived from classes Image2D and D3D10Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D10 object +class Image2DD3D10 : public D3D10Object, public Image +{ +protected: + //! Initializes the device memory array which is nested + // after'Image2DD3D10' object in memory layout. + virtual void initDeviceMemory(); +public: + //! Image2DD3D10 constructor just calls constructors of base classes + //! to pass down the parameters + Image2DD3D10( + Context& amdContext, + cl_mem_flags clFlags, + D3D10Object& d3d10obj) + : // Call base classes constructors + D3D10Object(d3d10obj), + Image( + amdContext, + CL_MEM_OBJECT_IMAGE2D, + clFlags, + getCLFormatFromDXGI(d3d10obj.getDxgiFormat()), //format, + d3d10obj.getWidth(), + d3d10obj.getHeight(), + 1, + d3d10obj.getWidth() * d3d10obj.getElementBytes(), //rowPitch), + 0) + { + setInteropObj(this); + } + virtual ~Image2DD3D10() {} +}; + +//! Class Image3DD3D10 is derived from classes Image3D and D3D10Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D10 object +class Image3DD3D10 : public D3D10Object, public Image +{ +protected: + //! Initializes the device memory array which is nested + // after'Image3DD3D10' object in memory layout. + virtual void initDeviceMemory(); +public: +//! Image2DD3D10 constructor just calls constructors of base classes +//! to pass down the parameters + Image3DD3D10( + Context& amdContext, + cl_mem_flags clFlags, + D3D10Object& d3d10obj) + : // Call base classes constructors + D3D10Object(d3d10obj), + Image( + amdContext, + CL_MEM_OBJECT_IMAGE3D, + clFlags, + getCLFormatFromDXGI(d3d10obj.getDxgiFormat()), //format, + d3d10obj.getWidth(), + d3d10obj.getHeight(), + d3d10obj.getDepth(), + d3d10obj.getWidth() * d3d10obj.getElementBytes(), //rowPitch), + d3d10obj.getWidth() * d3d10obj.getHeight() * d3d10obj.getElementBytes()) + { + setInteropObj(this); + } + virtual ~Image3DD3D10() {} +}; + +} //namespace amd diff --git a/rocclr/platform/interop_d3d11.cpp b/rocclr/platform/interop_d3d11.cpp new file mode 100644 index 0000000000..9da0c032c8 --- /dev/null +++ b/rocclr/platform/interop_d3d11.cpp @@ -0,0 +1,976 @@ +/* Copyright (c) 2009 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#ifdef _WIN32 + +#include "top.hpp" + +#include "platform/interop_d3d11.hpp" +#include "platform/command.hpp" + +#include +#include + +namespace amd { + +size_t D3D11Object::getResourceByteSize() { + size_t bytes = 1; + + //! @todo [odintsov]: take into consideration the mip level?! + + switch (objDesc_.objDim_) { + case D3D11_RESOURCE_DIMENSION_BUFFER: + bytes = objDesc_.objSize_.ByteWidth; + break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + bytes = objDesc_.objSize_.Depth; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + bytes *= objDesc_.objSize_.Height; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + bytes *= objDesc_.objSize_.Width * getElementBytes(); + break; + + default: + LogError("getResourceByteSize: unknown type of D3D11 resource"); + bytes = 0; + break; + } + return bytes; +} + +cl_uint D3D11Object::getMiscFlag() { + if ((objDesc_.dxgiFormat_ == DXGI_FORMAT_NV12) || + (objDesc_.dxgiFormat_ == DXGI_FORMAT_P010)) { + return 1; + } + else if (objDesc_.dxgiFormat_ == DXGI_FORMAT_YUY2) { + return 3; + } + return 0; +} + +int D3D11Object::initD3D11Object(const Context& amdContext, ID3D11Resource* pRes, UINT subres, + D3D11Object& obj, INT plane) { + ID3D11Device* pDev; + HRESULT hr; + ScopedLock sl(resLock_); + + // Check if this ressource has already been used for interop + for (const auto& it : resources_) { + if (it.first == (void*)pRes && it.second.first == subres && + it.second.second == plane) { + return CL_INVALID_D3D11_RESOURCE_KHR; + } + } + + (obj.pD3D11Res_ = pRes)->GetDevice(&pDev); + + if (!pDev) { + return CL_INVALID_D3D11_DEVICE_KHR; + } + + D3D11_QUERY_DESC desc = {D3D11_QUERY_EVENT, 0}; + pDev->CreateQuery(&desc, &obj.pQuery_); + +#define SET_SHARED_FLAGS() \ + { \ + obj.pD3D11ResOrig_ = obj.pD3D11Res_; \ + /* @todo - Check device type and select right usage for resource */ \ + /* For now get only DPU path, CPU path for buffers */ \ + /* will not worl on DEFAUL resources */ \ + /*desc.Usage = D3D11_USAGE_STAGING;*/ \ + desc.Usage = D3D11_USAGE_DEFAULT; \ + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; \ + desc.CPUAccessFlags = 0; \ + } + +#define STORE_SHARED_FLAGS_BUFFER(restype) \ + { \ + if (S_OK == hr && obj.pD3D11Res_) { \ + obj.objDesc_.objFlags_.d3d11Usage_ = desc.Usage; \ + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; \ + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; \ + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; \ + obj.objDesc_.objFlags_.structureByteStride_ = desc.StructureByteStride; \ + } else { \ + LogError("\nCannot create shared " #restype "\n"); \ + return CL_INVALID_D3D11_RESOURCE_KHR; \ + } \ + } + +#define STORE_SHARED_FLAGS(restype) \ + { \ + if (S_OK == hr && obj.pD3D11Res_) { \ + obj.objDesc_.objFlags_.d3d11Usage_ = desc.Usage; \ + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; \ + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; \ + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; \ + } else { \ + LogError("\nCannot create shared " #restype "\n"); \ + return CL_INVALID_D3D11_RESOURCE_KHR; \ + } \ + } + +#define SET_BINDING() \ + { \ + switch (desc.Format) { \ + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: \ + case DXGI_FORMAT_D32_FLOAT: \ + case DXGI_FORMAT_D24_UNORM_S8_UINT: \ + case DXGI_FORMAT_D16_UNORM: \ + desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; \ + break; \ + default: \ + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; \ + break; \ + } \ + } + + pRes->GetType(&obj.objDesc_.objDim_); + + // Init defaults + obj.objDesc_.objSize_.Height = 1; + obj.objDesc_.objSize_.Depth = 1; + obj.objDesc_.mipLevels_ = 1; + obj.objDesc_.arraySize_ = 1; + obj.objDesc_.dxgiFormat_ = DXGI_FORMAT_UNKNOWN; + obj.objDesc_.dxgiSampleDesc_ = dxgiSampleDescDefault; + + switch (obj.objDesc_.objDim_) { + case D3D11_RESOURCE_DIMENSION_BUFFER: // = 1, + { + D3D11_BUFFER_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + obj.objDesc_.objSize_.ByteWidth = desc.ByteWidth; + obj.objDesc_.objFlags_.d3d11Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + obj.objDesc_.objFlags_.structureByteStride_ = desc.StructureByteStride; + // Handle D3D11Buffer without shared handle - create + // a duplicate with shared handle to provide for CAL + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D11_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + hr = pDev->CreateBuffer(&desc, nullptr, (ID3D11Buffer**)&obj.pD3D11Res_); + STORE_SHARED_FLAGS_BUFFER(ID3D11Buffer); + } + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: // = 2, + { + D3D11_TEXTURE1D_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + + if (subres) { + // Calculate correct size of the subresource + UINT miplevel = subres; + if (desc.ArraySize > 1) { + miplevel = subres % desc.ArraySize; + } + if (miplevel >= desc.MipLevels) { + LogWarning("\nMiplevel >= number of miplevels\n"); + } + if (subres >= desc.MipLevels * desc.ArraySize) { + return CL_INVALID_VALUE; + } + desc.Width >>= miplevel; + if (!desc.Width) { + desc.Width = 1; + } + } + obj.objDesc_.objSize_.Width = desc.Width; + obj.objDesc_.mipLevels_ = desc.MipLevels; + obj.objDesc_.arraySize_ = desc.ArraySize; + obj.objDesc_.dxgiFormat_ = desc.Format; + obj.objDesc_.objFlags_.d3d11Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + // Handle D3D11Texture1D without shared handle - create + // a duplicate with shared handle and provide it for CAL + // Workaround for subresource > 0 in shared resource + if (subres) obj.objDesc_.objFlags_.miscFlags_ &= ~(D3D11_RESOURCE_MISC_SHARED); + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D11_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + SET_BINDING(); + obj.objDesc_.mipLevels_ = desc.MipLevels = 1; + obj.objDesc_.arraySize_ = desc.ArraySize = 1; + hr = pDev->CreateTexture1D(&desc, nullptr, (ID3D11Texture1D**)&obj.pD3D11Res_); + STORE_SHARED_FLAGS(ID3D11Texture1D); + } + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: // = 3, + { + D3D11_TEXTURE2D_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + + if (subres) { + // Calculate correct size of the subresource + UINT miplevel = subres; + if (desc.ArraySize > 1) { + miplevel = subres % desc.MipLevels; + } + if (miplevel >= desc.MipLevels) { + LogWarning("\nMiplevel >= number of miplevels\n"); + } + if (subres >= desc.MipLevels * desc.ArraySize) { + return CL_INVALID_VALUE; + } + desc.Width >>= miplevel; + if (!desc.Width) { + desc.Width = 1; + } + desc.Height >>= miplevel; + if (!desc.Height) { + desc.Height = 1; + } + } + obj.objDesc_.objSize_.Width = desc.Width; + obj.objDesc_.objSize_.Height = desc.Height; + obj.objDesc_.mipLevels_ = desc.MipLevels; + obj.objDesc_.arraySize_ = desc.ArraySize; + obj.objDesc_.dxgiFormat_ = desc.Format; + obj.objDesc_.dxgiSampleDesc_ = desc.SampleDesc; + obj.objDesc_.objFlags_.d3d11Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + + // Handle D3D11Texture2D without shared handle - create + // a duplicate with shared handle and provide it for CAL + // Workaround for subresource > 0 in shared resource + if (subres) obj.objDesc_.objFlags_.miscFlags_ &= ~(D3D11_RESOURCE_MISC_SHARED); + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D11_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + SET_BINDING(); + obj.objDesc_.mipLevels_ = desc.MipLevels = 1; + obj.objDesc_.arraySize_ = desc.ArraySize = 1; + hr = pDev->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**)&obj.pD3D11Res_); + STORE_SHARED_FLAGS(ID3D11Texture2D); + } + + if ((desc.Format == DXGI_FORMAT_NV12) || (desc.Format == DXGI_FORMAT_P010)) { + if (plane == -1) { + obj.objDesc_.objSize_.Height += obj.objDesc_.objSize_.Height / 2; + } + if (plane == 1) { + obj.objDesc_.objSize_.Width /= 2; + obj.objDesc_.objSize_.Height /= 2; + } + } + // RGBA8 covers 2 pixels, thus divide width by 2 + if (desc.Format == DXGI_FORMAT_YUY2) { + obj.objDesc_.objSize_.Width /= 2; + } + } break; + + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: // = 4 + { + D3D11_TEXTURE3D_DESC desc; + (reinterpret_cast(pRes))->GetDesc(&desc); + + if (subres) { + // Calculate correct size of the subresource + UINT miplevel = subres; + if (miplevel >= desc.MipLevels) { + LogWarning("\nMiplevel >= number of miplevels\n"); + } + if (subres >= desc.MipLevels) { + return CL_INVALID_VALUE; + } + desc.Width >>= miplevel; + if (!desc.Width) { + desc.Width = 1; + } + desc.Height >>= miplevel; + if (!desc.Height) { + desc.Height = 1; + } + desc.Depth >>= miplevel; + if (!desc.Depth) { + desc.Depth = 1; + } + } + obj.objDesc_.objSize_.Width = desc.Width; + obj.objDesc_.objSize_.Height = desc.Height; + obj.objDesc_.objSize_.Depth = desc.Depth; + obj.objDesc_.mipLevels_ = desc.MipLevels; + obj.objDesc_.dxgiFormat_ = desc.Format; + obj.objDesc_.objFlags_.d3d11Usage_ = desc.Usage; + obj.objDesc_.objFlags_.bindFlags_ = desc.BindFlags; + obj.objDesc_.objFlags_.cpuAccessFlags_ = desc.CPUAccessFlags; + obj.objDesc_.objFlags_.miscFlags_ = desc.MiscFlags; + // Handle D3D11Texture3D without shared handle - create + // a duplicate with shared handle and provide it for CAL + // Workaround for subresource > 0 in shared resource + if (obj.objDesc_.mipLevels_ > 1) + obj.objDesc_.objFlags_.miscFlags_ &= ~(D3D11_RESOURCE_MISC_SHARED); + if (!(obj.objDesc_.objFlags_.miscFlags_ & D3D11_RESOURCE_MISC_SHARED)) { + SET_SHARED_FLAGS(); + SET_BINDING(); + obj.objDesc_.mipLevels_ = desc.MipLevels = 1; + hr = pDev->CreateTexture3D(&desc, nullptr, (ID3D11Texture3D**)&obj.pD3D11Res_); + STORE_SHARED_FLAGS(ID3D11Texture3D); + } + } break; + + default: + LogError("unknown type of D3D11 resource"); + return CL_INVALID_D3D11_RESOURCE_KHR; + } + obj.subRes_ = subres; + obj.plane_ = plane; + pDev->Release(); + // Check for CL format compatibilty + if (obj.objDesc_.objDim_ != D3D11_RESOURCE_DIMENSION_BUFFER) { + cl_image_format clFmt = obj.getCLFormatFromDXGI(obj.objDesc_.dxgiFormat_, plane); + amd::Image::Format imageFormat(clFmt); + if (!imageFormat.isSupported(amdContext)) { + return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR; + } + } + resources_.push_back({pRes, {subres, plane}}); + return CL_SUCCESS; +} + +bool D3D11Object::copyOrigToShared() { + // Don't copy if there is no orig + if (nullptr == getD3D11ResOrig()) return true; + + ID3D11Device* d3dDev; + pD3D11Res_->GetDevice(&d3dDev); + if (!d3dDev) { + LogError("\nCannot get D3D11 device from D3D11 resource\n"); + return false; + } + ID3D11DeviceContext* pImmediateContext = nullptr; + d3dDev->GetImmediateContext(&pImmediateContext); + if (!pImmediateContext) { + LogError("\nCannot get D3D11 device context"); + return false; + } + assert(pD3D11ResOrig_ != nullptr); + // Any usage source can be read by GPU + pImmediateContext->CopySubresourceRegion(pD3D11Res_, 0, 0, 0, 0, pD3D11ResOrig_, subRes_, nullptr); + + // Flush D3D queues and make sure D3D stuff is finished + { + ScopedLock sl(resLock_); // protect from multiple + pImmediateContext->Flush(); + pImmediateContext->End(pQuery_); + BOOL data = FALSE; + while (S_OK != pImmediateContext->GetData(pQuery_, &data, sizeof(BOOL), 0)) { + } + } + + pImmediateContext->Release(); + d3dDev->Release(); + return true; +} + +bool D3D11Object::copySharedToOrig() { + // Don't copy if there is no orig + if (nullptr == getD3D11ResOrig()) return true; + + ID3D11Device* d3dDev; + pD3D11Res_->GetDevice(&d3dDev); + if (!d3dDev) { + LogError("\nCannot get D3D11 device from D3D11 resource\n"); + return false; + } + ID3D11DeviceContext* pImmediateContext = nullptr; + d3dDev->GetImmediateContext(&pImmediateContext); + if (!pImmediateContext) { + LogError("\nCannot get D3D11 device context"); + return false; + } + assert(pD3D11ResOrig_); + pImmediateContext->CopySubresourceRegion(pD3D11ResOrig_, subRes_, 0, 0, 0, pD3D11Res_, 0, nullptr); + pImmediateContext->Release(); + + d3dDev->Release(); + return true; +} + +std::vector>> D3D11Object::resources_; +Monitor D3D11Object::resLock_; + +// +// Class BufferD3D11 implementation +// +void BufferD3D11::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(BufferD3D11)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +// +// Class Image1DD3D11 implementation +// +void Image1DD3D11::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image1DD3D11)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +// +// Class Image2DD3D11 implementation +// + +void Image2DD3D11::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image2DD3D11)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +// +// Class Image3DD3D11 implementation +// +void Image3DD3D11::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(Image3DD3D11)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + + + +// +// Class D3D11Object implementation +// +size_t D3D11Object::getElementBytes(DXGI_FORMAT dxgiFmt, cl_uint plane) { + size_t bytesPerPixel; + + switch (dxgiFmt) { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + bytesPerPixel = 16; + break; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + bytesPerPixel = 12; + break; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + bytesPerPixel = 8; + break; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + + case DXGI_FORMAT_YUY2: + bytesPerPixel = 4; + break; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + bytesPerPixel = 2; + break; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R1_UNORM: + bytesPerPixel = 1; + break; + + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + // Less than 1 byte per pixel - needs special consideration + bytesPerPixel = 0; + break; + case DXGI_FORMAT_NV12: + bytesPerPixel = 1; + if (plane == 1) { + bytesPerPixel = 2; + } + break; + case DXGI_FORMAT_P010: + bytesPerPixel = 2; + if (plane == 1) { + bytesPerPixel = 4; + } + break; + default: + bytesPerPixel = 0; + _ASSERT(FALSE); + break; + } + return bytesPerPixel; +} + +cl_image_format D3D11Object::getCLFormatFromDXGI(DXGI_FORMAT dxgiFmt, cl_uint plane) { + cl_image_format fmt; + + //! @todo [odintsov]: add real fmt conversion from DXGI to CL + fmt.image_channel_order = 0; // CL_RGBA; + fmt.image_channel_data_type = 0; // CL_UNSIGNED_INT8; + + switch (dxgiFmt) { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32G32B32A32_UINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32B32A32_SINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + fmt.image_channel_order = CL_RGB; + break; + + case DXGI_FORMAT_R32G32B32_FLOAT: + fmt.image_channel_order = CL_RGB; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32G32B32_UINT: + fmt.image_channel_order = CL_RGB; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32B32_SINT: + fmt.image_channel_order = CL_RGB; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case DXGI_FORMAT_R16G16B16A16_UNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16G16B16A16_UINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + break; + + case DXGI_FORMAT_R16G16B16A16_SNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SNORM_INT16; + break; + + case DXGI_FORMAT_R16G16B16A16_SINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SIGNED_INT16; + break; + + case DXGI_FORMAT_R32G32_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_R32G32_FLOAT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32G32_UINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32G32_SINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R32G8X24_TYPELESS: + break; + + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + break; + + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + break; + + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + break; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R10G10B10A2_UNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT_101010; + break; + + case DXGI_FORMAT_R10G10B10A2_UINT: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R11G11B10_FLOAT: + fmt.image_channel_order = CL_RGB; + break; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + fmt.image_channel_order = CL_RGBA; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_YUY2: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_SNORM: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SNORM_INT8; + break; + + case DXGI_FORMAT_R8G8B8A8_SINT: + fmt.image_channel_order = CL_RGBA; + fmt.image_channel_data_type = CL_SIGNED_INT8; + break; + + case DXGI_FORMAT_R16G16_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_R16G16_FLOAT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case DXGI_FORMAT_R16G16_UNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16G16_UINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + break; + + case DXGI_FORMAT_R16G16_SNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SNORM_INT16; + break; + + case DXGI_FORMAT_R16G16_SINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SIGNED_INT16; + break; + + case DXGI_FORMAT_R32_TYPELESS: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_D32_FLOAT: + break; + + case DXGI_FORMAT_R32_FLOAT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_FLOAT; + break; + + case DXGI_FORMAT_R32_UINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT32; + break; + + case DXGI_FORMAT_R32_SINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SIGNED_INT32; + break; + + case DXGI_FORMAT_R24G8_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + break; + + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + break; + + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + break; + + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + break; + + case DXGI_FORMAT_R8G8_B8G8_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_G8R8_G8B8_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + fmt.image_channel_order = CL_BGRA; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_B8G8R8X8_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8_TYPELESS: + fmt.image_channel_order = CL_RG; + break; + + case DXGI_FORMAT_R8G8_UNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8G8_UINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + + case DXGI_FORMAT_R8G8_SNORM: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SNORM_INT8; + break; + + case DXGI_FORMAT_R8G8_SINT: + fmt.image_channel_order = CL_RG; + fmt.image_channel_data_type = CL_SIGNED_INT8; + break; + + case DXGI_FORMAT_R16_TYPELESS: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_R16_FLOAT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_HALF_FLOAT; + break; + + case DXGI_FORMAT_D16_UNORM: + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16_UNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT16; + break; + + case DXGI_FORMAT_R16_UINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + break; + + case DXGI_FORMAT_R16_SNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SNORM_INT16; + break; + + case DXGI_FORMAT_R16_SINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SIGNED_INT16; + break; + + case DXGI_FORMAT_B5G6R5_UNORM: + fmt.image_channel_data_type = CL_UNORM_SHORT_565; + break; + + case DXGI_FORMAT_B5G5R5A1_UNORM: + fmt.image_channel_order = CL_BGRA; + break; + + case DXGI_FORMAT_R8_TYPELESS: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_R8_UNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R8_UINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + break; + + case DXGI_FORMAT_R8_SNORM: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SNORM_INT8; + break; + + case DXGI_FORMAT_R8_SINT: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_SIGNED_INT8; + break; + + case DXGI_FORMAT_A8_UNORM: + fmt.image_channel_order = CL_A; + fmt.image_channel_data_type = CL_UNORM_INT8; + break; + + case DXGI_FORMAT_R1_UNORM: + fmt.image_channel_order = CL_R; + break; + + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + break; + case DXGI_FORMAT_NV12: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT8; + if (plane == 1) { + fmt.image_channel_order = CL_RG; + } + break; + case DXGI_FORMAT_P010: + fmt.image_channel_order = CL_R; + fmt.image_channel_data_type = CL_UNSIGNED_INT16; + if (plane == 1) { + fmt.image_channel_order = CL_RG; + } + break; + default: + _ASSERT(FALSE); + break; + } + + return fmt; +} + +} // namespace amd + +#endif //_WIN32 diff --git a/rocclr/platform/interop_d3d11.hpp b/rocclr/platform/interop_d3d11.hpp new file mode 100644 index 0000000000..2d82bbd36c --- /dev/null +++ b/rocclr/platform/interop_d3d11.hpp @@ -0,0 +1,305 @@ +/* Copyright (c) 2008 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#pragma once + +#include "interop_d3d10.hpp" +#include "platform/context.hpp" +#include "platform/memory.hpp" + +#include + +namespace amd +{ + +typedef struct +{ + union + { + UINT ByteWidth; + UINT Width; + }; + UINT Height; + UINT Depth; +} D3D11ObjSize_t; + +typedef struct +{ + D3D11_USAGE d3d11Usage_; + UINT bindFlags_; + UINT cpuAccessFlags_; + UINT miscFlags_; + UINT structureByteStride_; +} D3D11Flags_t; + +typedef struct +{ + D3D11_RESOURCE_DIMENSION objDim_; + D3D11ObjSize_t objSize_; + D3D11Flags_t objFlags_; + UINT mipLevels_; + UINT arraySize_; + DXGI_FORMAT dxgiFormat_; + DXGI_SAMPLE_DESC dxgiSampleDesc_; +} D3D11ObjDesc_t; + +//! Class D3D11Object keeps all the info about the D3D11 object +//! from which the CL object is created +class D3D11Object : public InteropObject +{ +private: + ID3D11Resource* pD3D11Aux_; + + bool releaseResources_; + + static std::vector>> resources_; +protected: + //! Global lock. + static Monitor resLock_; + + ID3D11Resource* pD3D11Res_; + ID3D11Resource* pD3D11ResOrig_; + ID3D11Query* pQuery_; + D3D11ObjDesc_t objDesc_; + UINT subRes_; + INT plane_; + +public: + // Default constructor + D3D11Object() + :pD3D11Aux_(nullptr) + ,releaseResources_(false) + ,pD3D11Res_(nullptr) + ,pD3D11ResOrig_(nullptr) + ,pQuery_(nullptr) + ,subRes_(NULL) + ,plane_(NULL) + { + memset(&objDesc_,0,sizeof(objDesc_)); + } + // Copy constructor + D3D11Object(D3D11Object& d3d11obj) + : pQuery_(NULL) + { + *this = d3d11obj; + this->releaseResources_ = true; + // Add reference to the D3D11 resource to prevent its disappearance + if(pD3D11ResOrig_) { + pD3D11ResOrig_->AddRef(); + } + else if(pD3D11Res_) { + pD3D11Res_->AddRef(); + } + assert(pD3D11Res_ != pD3D11ResOrig_); + } + + //! Virtual destructor + virtual ~D3D11Object() + { + ScopedLock sl(resLock_); + if(releaseResources_) { + // Decrement reference to the D3D11 objects + if(pD3D11Res_) pD3D11Res_->Release(); + if(pD3D11Aux_) pD3D11Aux_->Release(); + if(pD3D11ResOrig_) pD3D11ResOrig_->Release(); + if(pQuery_) pQuery_->Release(); + // Check if this resource has already been used for interop + if(resources_.size()) { + for(auto& it = resources_.cbegin(); it != resources_.cend(); it++) { + if(((pD3D11ResOrig_ && (*it).first == (void*) pD3D11ResOrig_) + || ((*it).first == (void*) pD3D11Res_)) + && (*it).second.first == subRes_ + && (*it).second.second == plane_) { + resources_.erase(it); + break; + } + } + } + } + } + + static int initD3D11Object(const Context& amdContext, ID3D11Resource* pRes, UINT subresource, + D3D11Object& obj, INT plane = -1); + + D3D11Object* asD3D11Object() { return this; } + +//! D3D11Object query functions to get D3D11 info from member variables + ID3D11Resource* getD3D11Resource() const {return pD3D11Res_;} + ID3D11Resource* getD3D11ResOrig() const {return pD3D11ResOrig_;} + ID3D11Query* getQuery() const {return pQuery_;} + Monitor& getResLock() { return resLock_;} + UINT getWidth() const {return objDesc_.objSize_.Width;} + UINT getHeight() const {return objDesc_.objSize_.Height;} + UINT getDepth() const {return objDesc_.objSize_.Depth;} + size_t getElementBytes(DXGI_FORMAT dxgiFomat, cl_uint plane); + size_t getElementBytes() {return getElementBytes(objDesc_.dxgiFormat_, plane_);} + DXGI_FORMAT getDxgiFormat() {return objDesc_.dxgiFormat_;} + UINT getSubresource() const {return subRes_;} + INT getPlane() const {return plane_;} + const D3D11ObjDesc_t* getObjDesc() const { return &objDesc_; } + + cl_uint getMiscFlag(void); + //! Returns bytes per pixel > 0 if conversion successful, 0 otherwise; + //! if formats are not compatible, cl format channel + //! order and type are set to 0 + cl_image_format getCLFormatFromDXGI(DXGI_FORMAT dxgiFmt, cl_uint plane); + cl_image_format getCLFormatFromDXGI() + { + return getCLFormatFromDXGI(objDesc_.dxgiFormat_, plane_); + } + size_t getResourceByteSize(); + + // 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(); +}; + +//! Class BufferD3D11 is derived from classes Buffer and D3D11Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D11 object +class BufferD3D11 : public D3D11Object, public Buffer +{ +protected: + //! Initializes the device memory array which is nested + // after'BufferD3D11' object in memory layout. + virtual void initDeviceMemory(); +public: +//! BufferD3D11 constructor just calls constructors of base classes +//! to pass down the parameters + BufferD3D11( + Context& amdContext, + cl_mem_flags clFlags, + D3D11Object& d3d11obj) + : // Call base classes constructors + D3D11Object(d3d11obj), + Buffer( + amdContext, + clFlags, + d3d11obj.getResourceByteSize()) + { + setInteropObj(this); + } + virtual ~BufferD3D11() {} +}; + +//! Class Image1DD3D11 is derived from classes Image1D and D3D11Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D11 object +class Image1DD3D11 : public D3D11Object, public Image +{ +protected: + //! Initializes the device memory array which is nested + // after'Image1DD3D11' object in memory layout. + virtual void initDeviceMemory(); +public: +//! Image1DD3D11 constructor just calls constructors of base classes +//! to pass down the parameters + Image1DD3D11( + Context& amdContext, + cl_mem_flags clFlags, + D3D11Object& d3d11obj) + : // Call base classes constructors + D3D11Object(d3d11obj), + Image( + amdContext, + CL_MEM_OBJECT_IMAGE1D, + clFlags, + getCLFormatFromDXGI(d3d11obj.getDxgiFormat(), d3d11obj.getPlane()), //format, + d3d11obj.getWidth(), + 1, + 1, + d3d11obj.getWidth() * d3d11obj.getElementBytes(), //rowPitch), + 0) + { + setInteropObj(this); + } + virtual ~Image1DD3D11() {} +}; + +//! Class Image2DD3D11 is derived from classes Image2D and D3D11Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D11 object +class Image2DD3D11 : public Image, public D3D11Object +{ +protected: + //! Initializes the device memory array which is nested + // after'Image2DD3D11' object in memory layout. + virtual void initDeviceMemory(); +public: +//! Image2DD3D11 constructor just calls constructors of base classes +//! to pass down the parameters + Image2DD3D11( + Context& amdContext, + cl_mem_flags clFlags, + D3D11Object& d3d11obj) + : // Call base classes constructors + D3D11Object(d3d11obj), + Image( + amdContext, + CL_MEM_OBJECT_IMAGE2D, + clFlags, + getCLFormatFromDXGI(d3d11obj.getDxgiFormat(), d3d11obj.getPlane()), //format, + d3d11obj.getWidth(), + d3d11obj.getHeight(), + 1, + d3d11obj.getWidth() * d3d11obj.getElementBytes(), //rowPitch), + 0) + { + setInteropObj(this); + } + virtual ~Image2DD3D11() {} +}; + +//! Class Image3DD3D11 is derived from classes Image3D and D3D11Object +//! where the former keeps all data for CL object and +//! the latter keeps all data for D3D11 object +class Image3DD3D11 : public D3D11Object, public Image +{ +protected: + //! Initializes the device memory array which is nested + // after'Image3DD3D11' object in memory layout. + virtual void initDeviceMemory(); +public: +//! Image2DD3D11 constructor just calls constructors of base classes +//! to pass down the parameters + Image3DD3D11( + Context& amdContext, + cl_mem_flags clFlags, + D3D11Object& d3d11obj) + : // Call base classes constructors + D3D11Object(d3d11obj), + Image( + amdContext, + CL_MEM_OBJECT_IMAGE3D, + clFlags, + getCLFormatFromDXGI(d3d11obj.getDxgiFormat(), d3d11obj.getPlane()), //format, + d3d11obj.getWidth(), + d3d11obj.getHeight(), + d3d11obj.getDepth(), + d3d11obj.getWidth() * d3d11obj.getElementBytes(), //rowPitch), + d3d11obj.getWidth() * d3d11obj.getHeight() * d3d11obj.getElementBytes()) + { + setInteropObj(this); + } + virtual ~Image3DD3D11() {} +}; + +} //namespace amd diff --git a/rocclr/platform/interop_d3d9.cpp b/rocclr/platform/interop_d3d9.cpp new file mode 100644 index 0000000000..7678837836 --- /dev/null +++ b/rocclr/platform/interop_d3d9.cpp @@ -0,0 +1,570 @@ +/* Copyright (c) 2012 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#ifdef _WIN32 + +#include "top.hpp" + +#include "platform/interop_d3d9.hpp" +#include "platform/command.hpp" + +#include +#include + +namespace amd { +std::vector> D3D9Object::resources_; +Monitor D3D9Object::resLock_; + +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 = nullptr; + 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 nullptr + // first check if the format is NV12 or YV12, which we need special handling + if (nullptr == 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_ = nullptr; + 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 (nullptr == 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, nullptr, dstSurf, nullptr, 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 (nullptr == 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(), nullptr, getD3D9ResOrig(), nullptr, 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 diff --git a/rocclr/platform/interop_d3d9.hpp b/rocclr/platform/interop_d3d9.hpp new file mode 100644 index 0000000000..d53fe9466d --- /dev/null +++ b/rocclr/platform/interop_d3d9.hpp @@ -0,0 +1,190 @@ +/* Copyright (c) 2010 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#pragma once + +#include "cl_common.hpp" +#include "platform/context.hpp" +#include "platform/memory.hpp" + +#include + +/* cl_amd_d3d9_sharing error codes */ +#define CL_INVALID_D3D9_RESOURCE_KHR -1022 +#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')) + +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; + + +//typedef std::pair TD3D9OBJINFO; + +//! Class D3D9Object keeps all the info about the D3D9 object +//! from which the CL object is created +class D3D9Object : public InteropObject +{ +private: + IDirect3DSurface9* pD3D9Aux_; + bool releaseResources_; + static std::vector> resources_; + + //!Global lock + static Monitor resLock_; + cl_uint surfPlane_; + cl_dx9_surface_info_khr surfInfo_; + +protected: + IDirect3DSurface9* pD3D9Res_; + IDirect3DSurface9* pD3D9ResOrig_; + IDirect3DQuery9* pQuery_; + D3D9ObjDesc_t objDesc_; + D3D9ObjDesc_t objDescOrig_; + HANDLE handleShared_; + cl_dx9_media_adapter_type_khr adapterType_; + +public: +//! D3D9Object constructor initializes memeber variables + D3D9Object() + : releaseResources_(false), + pQuery_(nullptr) + { + // @todo Incorrect initialization!!! + memset(this, 0, sizeof(D3D9Object)); + } + //copy constructor + D3D9Object(D3D9Object& d3d9obj) + :pQuery_(nullptr) + { + *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; + } + } + } + } + } + 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_;} + 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_);} + 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(); +}; + +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); + } + virtual ~Image2DD3D9() {} +}; + +} //namespace amd diff --git a/rocclr/platform/interop_gl.cpp b/rocclr/platform/interop_gl.cpp new file mode 100644 index 0000000000..5ff0bb6d74 --- /dev/null +++ b/rocclr/platform/interop_gl.cpp @@ -0,0 +1,803 @@ +/* Copyright (c) 2010 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#include "top.hpp" + +#ifdef _WIN32 +#include +#include +#include +#endif //_WIN32 + +#include +#include + +#include +#include +#include + +#include "cl_common.hpp" + +#include "device/device.hpp" +#include "platform/command.hpp" +#include "platform/interop_gl.hpp" + +/* The pixel internal format for DOPP texture defined in gl_enum.h */ +#define GL_BGR8_ATI 0x8083 +#define GL_BGRA8_ATI 0x8088 + +#include +#include + +// Placed here as opposed to command.cpp, as glext.h and cl_gl_amd.hpp will have +// to be included because of the GL calls +bool amd::ClGlEvent::waitForFence() { + GLenum ret; + // get fence id associated with fence event + GLsync gs = reinterpret_cast(command().data()); + if (!gs) return false; + +// Try to use DC and GLRC of current thread, if it doesn't exist +// create a new GL context on this thread, which is shared with the original context + +#ifdef _WIN32 + HDC tempDC_ = wglGetCurrentDC(); + HGLRC tempGLRC_ = wglGetCurrentContext(); + // Set DC and GLRC + if (tempDC_ && tempGLRC_) { + ret = context().glenv()->glClientWaitSync_(gs, GL_SYNC_FLUSH_COMMANDS_BIT, + static_cast(-1)); + if (!(ret == GL_ALREADY_SIGNALED || ret == GL_CONDITION_SATISFIED)) return false; + } else { + tempDC_ = context().glenv()->getDC(); + tempGLRC_ = context().glenv()->getIntGLRC(); + if (!context().glenv()->init(reinterpret_cast(tempDC_), + reinterpret_cast(tempGLRC_))) + return false; + + // Make the newly created GL context current to this thread + context().glenv()->setIntEnv(); + // If fence has not yet executed, wait till it finishes + ret = context().glenv()->glClientWaitSync_(gs, GL_SYNC_FLUSH_COMMANDS_BIT, + static_cast(-1)); + if (!(ret == GL_ALREADY_SIGNALED || ret == GL_CONDITION_SATISFIED)) return false; + // Since we're done making GL calls, restore whatever context was previously current to this + // thread + context().glenv()->restoreEnv(); + } +#else // Lnx + Display* tempDpy_ = context().glenv()->glXGetCurrentDisplay_(); + GLXDrawable tempDrawable_ = context().glenv()->glXGetCurrentDrawable_(); + GLXContext tempCtx_ = context().glenv()->glXGetCurrentContext_(); + // Set internal Display and GLXContext + if (tempDpy_ && tempCtx_) { + ret = context().glenv()->glClientWaitSync_(gs, GL_SYNC_FLUSH_COMMANDS_BIT, + static_cast(-1)); + if (!(ret == GL_ALREADY_SIGNALED || ret == GL_CONDITION_SATISFIED)) return false; + } else { + if (!context().glenv()->init(reinterpret_cast(context().glenv()->getIntDpy()), + reinterpret_cast(context().glenv()->getIntCtx()))) + return false; + + // Make the newly created GL context current to this thread + context().glenv()->setIntEnv(); + // If fence has not yet executed, wait till it finishes + ret = context().glenv()->glClientWaitSync_(gs, GL_SYNC_FLUSH_COMMANDS_BIT, + static_cast(-1)); + if (!(ret == GL_ALREADY_SIGNALED || ret == GL_CONDITION_SATISFIED)) return false; + // Since we're done making GL calls, restore whatever context was previously current to this + // thread + context().glenv()->restoreEnv(); + } +#endif + // If we reach this point, fence should have completed + setStatus(CL_COMPLETE); + return true; +} + + +void amd::BufferGL::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(BufferGL)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +void amd::ImageGL::initDeviceMemory() { + deviceMemories_ = + reinterpret_cast(reinterpret_cast(this) + sizeof(ImageGL)); + memset(deviceMemories_, 0, context_().devices().size() * sizeof(DeviceMemory)); +} + +#ifdef _WIN32 +#define CONVERT_CHAR_GLUBYTE +#else //!_WIN32 +#define CONVERT_CHAR_GLUBYTE (GLubyte*) +#endif //!_WIN32 + +#define GLPREFIX(rtype, fcn, dclargs) \ + if (!(fcn##_ = (PFN_##fcn)GETPROCADDRESS(libHandle_, #fcn))) { \ + if (!(fcn##_ = (PFN_##fcn)GetProcAddress_(reinterpret_cast(#fcn)))) ++missed_; \ + } + +amd::GLFunctions::SetIntEnv::SetIntEnv(GLFunctions* env) : env_(env) { + env_->getLock().lock(); + + // Set environment (DC and GLRC) + isValid_ = env_->setIntEnv(); +} + +amd::GLFunctions::SetIntEnv::~SetIntEnv() { + // Restore environment (CL DC and CL GLRC) + env_->restoreEnv(); + + env_->getLock().unlock(); +} + +amd::GLFunctions::GLFunctions(HMODULE h, bool isEGL) + : libHandle_(h), + missed_(0), + eglDisplay_(EGL_NO_DISPLAY), + eglOriginalContext_(EGL_NO_CONTEXT), + eglInternalContext_(EGL_NO_CONTEXT), + eglTempContext_(EGL_NO_CONTEXT), + isEGL_(isEGL), +#ifdef _WIN32 + hOrigGLRC_(0), + hDC_(0), + hIntGLRC_(0) +#else //!_WIN32 + Dpy_(0), + Drawable_(0), + origCtx_(0), + intDpy_(0), + intDrawable_(0), + intCtx_(0), + XOpenDisplay_(nullptr), + XCloseDisplay_(nullptr), + glXGetCurrentDrawable_(nullptr), + glXGetCurrentDisplay_(nullptr), + glXGetCurrentContext_(nullptr), + glXChooseVisual_(nullptr), + glXCreateContext_(nullptr), + glXDestroyContext_(nullptr), + glXMakeCurrent_(nullptr) +#endif //!_WIN32 +{ +#define VERIFY_POINTER(p) \ + if (nullptr == p) { \ + missed_++; \ + } + + if (isEGL_) { + GetProcAddress_ = (PFN_xxxGetProcAddress)GETPROCADDRESS(h, "eglGetProcAddress"); + } else { + GetProcAddress_ = (PFN_xxxGetProcAddress)GETPROCADDRESS(h, API_GETPROCADDR); + } +#ifndef _WIN32 + // Initialize pointers to X11/GLX functions + // We can not link with these functions on compile time since we need to support + // console mode. In console mode X server and X server components may be absent. + // Hence linking with X11 or libGL will fail module image loading in console mode.-tzachi cohen + + if (!isEGL_) { + glXGetCurrentDrawable_ = (PFNglXGetCurrentDrawable)GETPROCADDRESS(h, "glXGetCurrentDrawable"); + VERIFY_POINTER(glXGetCurrentDrawable_) + glXGetCurrentDisplay_ = (PFNglXGetCurrentDisplay)GETPROCADDRESS(h, "glXGetCurrentDisplay"); + VERIFY_POINTER(glXGetCurrentDisplay_) + glXGetCurrentContext_ = (PFNglXGetCurrentContext)GETPROCADDRESS(h, "glXGetCurrentContext"); + VERIFY_POINTER(glXGetCurrentContext_) + glXChooseVisual_ = (PFNglXChooseVisual)GETPROCADDRESS(h, "glXChooseVisual"); + VERIFY_POINTER(glXChooseVisual_) + glXCreateContext_ = (PFNglXCreateContext)GETPROCADDRESS(h, "glXCreateContext"); + VERIFY_POINTER(glXCreateContext_) + glXDestroyContext_ = (PFNglXDestroyContext)GETPROCADDRESS(h, "glXDestroyContext"); + VERIFY_POINTER(glXDestroyContext_) + glXMakeCurrent_ = (PFNglXMakeCurrent)GETPROCADDRESS(h, "glXMakeCurrent"); + VERIFY_POINTER(glXMakeCurrent_) + + HMODULE hXModule = (HMODULE)Os::loadLibrary("libX11.so.6"); + if (nullptr != hXModule) { + XOpenDisplay_ = (PFNXOpenDisplay)GETPROCADDRESS(hXModule, "XOpenDisplay"); + VERIFY_POINTER(XOpenDisplay_) + XCloseDisplay_ = (PFNXCloseDisplay)GETPROCADDRESS(hXModule, "XCloseDisplay"); + VERIFY_POINTER(XCloseDisplay_) + } else { + missed_ += 2; + } + } +// Initialize pointers to GL functions +#include "gl_functions.hpp" +#else + if (!isEGL_) { + wglCreateContext_ = (PFN_wglCreateContext)GETPROCADDRESS(h, "wglCreateContext"); + VERIFY_POINTER(wglCreateContext_) + wglGetCurrentContext_ = (PFN_wglGetCurrentContext)GETPROCADDRESS(h, "wglGetCurrentContext"); + VERIFY_POINTER(wglGetCurrentContext_) + wglGetCurrentDC_ = (PFN_wglGetCurrentDC)GETPROCADDRESS(h, "wglGetCurrentDC"); + VERIFY_POINTER(wglGetCurrentDC_) + wglDeleteContext_ = (PFN_wglDeleteContext)GETPROCADDRESS(h, "wglDeleteContext"); + VERIFY_POINTER(wglDeleteContext_) + wglMakeCurrent_ = (PFN_wglMakeCurrent)GETPROCADDRESS(h, "wglMakeCurrent"); + VERIFY_POINTER(wglMakeCurrent_) + wglShareLists_ = (PFN_wglShareLists)GETPROCADDRESS(h, "wglShareLists"); + VERIFY_POINTER(wglShareLists_) + } +#endif +} + +amd::GLFunctions::~GLFunctions() { +#ifdef _WIN32 + if (hIntGLRC_) { + if (!wglDeleteContext_(hIntGLRC_)) { + DWORD dwErr = GetLastError(); + LogWarning("Cannot delete GLRC"); + } + } +#else //!_WIN32 + if (intDpy_) { + if (intCtx_) { + glXDestroyContext_(intDpy_, intCtx_); + intCtx_ = nullptr; + } + XCloseDisplay_(intDpy_); + intDpy_ = nullptr; + } +#endif //!_WIN32 +} +// in case of HIP GL interop we want to make sure we have the updated context +bool amd::GLFunctions::update(intptr_t hglrc) { +#ifdef _WIN32 + DWORD err; + if (hOrigGLRC_ == (HGLRC)hglrc) { + return true; + } + hOrigGLRC_ = (HGLRC)hglrc; + if (hIntGLRC_ != nullptr) { + wglDeleteContext_(hIntGLRC_); + } + if (!(hIntGLRC_ = wglCreateContext_(wglGetCurrentDC_()))) { + err = GetLastError(); + return false; + } + if (!wglShareLists_(hOrigGLRC_, hIntGLRC_)) { + err = GetLastError(); + return false; + } +#else //!_WIN32 + Dpy_ = glXGetCurrentDisplay_(); + Drawable_ = glXGetCurrentDrawable_(); + if (origCtx_ == (GLXContext)hglrc) { + return true; + } + + origCtx_ = (GLXContext)hglrc; + if (intCtx_ != nullptr) { + glXDestroyContext_(Dpy_,intCtx_); + } + + int attribList[] = {GLX_RGBA, None}; + XVisualInfo* vis; + int defaultScreen = DefaultScreen(intDpy_); + if (!(vis = glXChooseVisual_(intDpy_, defaultScreen, attribList))) { + return false; + } + if (!(intCtx_ = glXCreateContext_(intDpy_, vis, origCtx_, true))) { + return false; + } +#endif + return true; +} + +void amd::GLFunctions::WaitCurrentGlContext(const amd::Context::Info& info) const { + if (IsCurrentGlContext(info)) { + glFinish_(); + } +} + + +bool amd::GLFunctions::init(intptr_t hdc, intptr_t hglrc) { + if (isEGL_) { + eglDisplay_ = (EGLDisplay)hdc; + eglOriginalContext_ = (EGLContext)hglrc; + return true; + } + +#ifdef _WIN32 + DWORD err; + + if (missed_) { + return false; + } + + if (!hdc) { + hDC_ = wglGetCurrentDC_(); + } else { + hDC_ = (HDC)hdc; + } + hOrigGLRC_ = (HGLRC)hglrc; + if (!(hIntGLRC_ = wglCreateContext_(hDC_))) { + err = GetLastError(); + return false; + } + if (!wglShareLists_(hOrigGLRC_, hIntGLRC_)) { + err = GetLastError(); + return false; + } + + bool makeCurrentNull = false; + + if (wglGetCurrentContext_() == nullptr) { + wglMakeCurrent_(hDC_, hIntGLRC_); + + makeCurrentNull = true; + } + +// Initialize pointers to GL functions +#include "gl_functions.hpp" + + if (makeCurrentNull) { + wglMakeCurrent_(nullptr, nullptr); + } + + if (missed_ == 0) { + return true; + } +#else //!_WIN32 + if (!missed_) { + if (!hdc) { + Dpy_ = glXGetCurrentDisplay_(); + } else { + Dpy_ = (Display*)hdc; + } + Drawable_ = glXGetCurrentDrawable_(); + origCtx_ = (GLXContext)hglrc; + + int attribList[] = {GLX_RGBA, None}; + if (!(intDpy_ = XOpenDisplay_(DisplayString(Dpy_)))) { +#if defined(ATI_ARCH_X86) + asm("int $3"); +#endif + } + intDrawable_ = DefaultRootWindow(intDpy_); + + XVisualInfo* vis; + int defaultScreen = DefaultScreen(intDpy_); + if (!(vis = glXChooseVisual_(intDpy_, defaultScreen, attribList))) { + return false; + } + if (!(intCtx_ = glXCreateContext_(intDpy_, vis, origCtx_, true))) { + return false; + } + return true; + } +#endif //!_WIN32 + return false; +} + +bool amd::GLFunctions::setIntEnv() { + if (isEGL_) { + return true; + } +#ifdef _WIN32 + // Save current DC and GLRC + tempDC_ = wglGetCurrentDC_(); + tempGLRC_ = wglGetCurrentContext_(); + // Set internal DC and GLRC + if (tempDC_ != getDC() || tempGLRC_ != getIntGLRC()) { + if (!wglMakeCurrent_(getDC(), getIntGLRC())) { + DWORD err = GetLastError(); + LogWarning("cannot set internal GL environment"); + return false; + } + } +#else //!_WIN32 + tempDpy_ = glXGetCurrentDisplay_(); + tempDrawable_ = glXGetCurrentDrawable_(); + tempCtx_ = glXGetCurrentContext_(); + // Set internal Display and GLXContext + if (tempDpy_ != getDpy() || tempCtx_ != getIntCtx()) { + if (!glXMakeCurrent_(getIntDpy(), getIntDrawable(), getIntCtx())) { + LogWarning("cannot set internal GL environment"); + return false; + } + } +#endif //!_WIN32 + + return true; +} + +bool amd::GLFunctions::restoreEnv() { + if (isEGL_) { + // eglMakeCurrent( ); + return true; + } +#ifdef _WIN32 + // Restore original DC and GLRC + if (!wglMakeCurrent_(tempDC_, tempGLRC_)) { + DWORD err = GetLastError(); + LogWarning("cannot restore original GL environment"); + return false; + } +#else //!_WIN32 + // Restore Display and GLXContext + if (tempDpy_) { + if (!glXMakeCurrent_(tempDpy_, tempDrawable_, tempCtx_)) { + LogWarning("cannot restore original GL environment"); + return false; + } + } else { + // Just release internal context + if (!glXMakeCurrent_(getIntDpy(), None, nullptr)) { + LogWarning("cannot reelase internal GL environment"); + return false; + } + } +#endif //!_WIN32 + + return true; +} + + + + + +//! Function getCLFormatFromGL returns "true" if GL format +//! is compatible with CL format, "false" otherwise. +bool amd::getCLFormatFromGL(const amd::Context& amdContext, GLint gliInternalFormat, + cl_image_format* pclImageFormat, int* piBytesPerPixel, cl_mem_flags flags) { + bool bRetVal = false; + + /* + Available values for "image_channel_order" + ========================================== + CL_R + CL_A + CL_INTENSITY + CL_LUMINANCE + CL_RG + CL_RA + CL_RGB + CL_RGBA + CL_ARGB + CL_BGRA + + Available values for "image_channel_data_type" + ============================================== + CL_SNORM_INT8 + CL_SNORM_INT16 + CL_UNORM_INT8 + CL_UNORM_INT16 + CL_UNORM_SHORT_565 + CL_UNORM_SHORT_555 + CL_UNORM_INT_101010 + CL_SIGNED_INT8 + CL_SIGNED_INT16 + CL_SIGNED_INT32 + CL_UNSIGNED_INT8 + CL_UNSIGNED_INT16 + CL_UNSIGNED_INT32 + CL_HALF_FLOAT + CL_FLOAT + */ + + switch (gliInternalFormat) { + case GL_RGB10_EXT: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_UNORM_INT_101010; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_RGB10_A2: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_UNORM_INT_101010; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_BGR8_ATI: + case GL_BGRA8_ATI: + pclImageFormat->image_channel_order = CL_BGRA; + pclImageFormat->image_channel_data_type = CL_UNORM_INT8; // CL_UNSIGNED_INT8; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_ALPHA8: + pclImageFormat->image_channel_order = CL_A; + pclImageFormat->image_channel_data_type = CL_UNORM_INT8; // CL_UNSIGNED_INT8; + *piBytesPerPixel = 1; + bRetVal = true; + break; + + case GL_R8: + case GL_R8UI: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_R8) ? CL_UNORM_INT8 : CL_UNSIGNED_INT8; + *piBytesPerPixel = 1; + bRetVal = true; + break; + + case GL_R8I: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT8; + *piBytesPerPixel = 1; + bRetVal = true; + break; + + case GL_RG8: + case GL_RG8UI: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_RG8) ? CL_UNORM_INT8 : CL_UNSIGNED_INT8; + *piBytesPerPixel = 2; + bRetVal = true; + break; + + case GL_RG8I: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT8; + *piBytesPerPixel = 2; + bRetVal = true; + break; + + case GL_RGB8: + case GL_RGB8UI: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_RGB8) ? CL_UNORM_INT8 : CL_UNSIGNED_INT8; + *piBytesPerPixel = 3; + bRetVal = true; + break; + + case GL_RGB8I: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT8; + *piBytesPerPixel = 3; + bRetVal = true; + break; + + case GL_RGBA: + case GL_RGBA8: + case GL_RGBA8UI: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_RGBA8UI) ? CL_UNSIGNED_INT8 : CL_UNORM_INT8; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_RGBA8I: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT8; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_R16: + case GL_R16UI: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_R16) ? CL_UNORM_INT16 : CL_UNSIGNED_INT16; + bRetVal = true; + *piBytesPerPixel = 2; + break; + + case GL_R16I: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT16; + *piBytesPerPixel = 2; + bRetVal = true; + break; + + case GL_R16F: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = CL_HALF_FLOAT; + *piBytesPerPixel = 2; + bRetVal = true; + break; + + case GL_RG16: + case GL_RG16UI: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_RG16) ? CL_UNORM_INT16 : CL_UNSIGNED_INT16; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_RG16I: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT16; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_RG16F: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = CL_HALF_FLOAT; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_RGB16: + case GL_RGB16UI: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_RGB16) ? CL_UNORM_INT16 : CL_UNSIGNED_INT16; + *piBytesPerPixel = 6; + bRetVal = true; + break; + + case GL_RGB16I: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT16; + *piBytesPerPixel = 6; + bRetVal = true; + break; + + case GL_RGB16F: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_HALF_FLOAT; + *piBytesPerPixel = 6; + bRetVal = true; + break; + + case GL_RGBA16: + case GL_RGBA16UI: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = + (gliInternalFormat == GL_RGBA16) ? CL_UNORM_INT16 : CL_UNSIGNED_INT16; + *piBytesPerPixel = 8; + bRetVal = true; + break; + + case GL_RGBA16I: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT16; + *piBytesPerPixel = 8; + bRetVal = true; + break; + + case GL_RGBA16F: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_HALF_FLOAT; + *piBytesPerPixel = 8; + bRetVal = true; + break; + + case GL_R32I: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT32; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_R32UI: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_R32F: + pclImageFormat->image_channel_order = CL_R; + pclImageFormat->image_channel_data_type = CL_FLOAT; + *piBytesPerPixel = 4; + bRetVal = true; + break; + + case GL_RG32I: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT32; + *piBytesPerPixel = 8; + bRetVal = true; + break; + + case GL_RG32UI: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + *piBytesPerPixel = 8; + bRetVal = true; + break; + + case GL_RG32F: + pclImageFormat->image_channel_order = CL_RG; + pclImageFormat->image_channel_data_type = CL_FLOAT; + *piBytesPerPixel = 8; + bRetVal = true; + break; + + case GL_RGB32I: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT32; + *piBytesPerPixel = 12; + bRetVal = true; + break; + + case GL_RGB32UI: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + *piBytesPerPixel = 12; + bRetVal = true; + break; + + case GL_RGB32F: + pclImageFormat->image_channel_order = CL_RGB; + pclImageFormat->image_channel_data_type = CL_FLOAT; + *piBytesPerPixel = 12; + bRetVal = true; + break; + + case GL_RGBA32I: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_SIGNED_INT32; + *piBytesPerPixel = 16; + bRetVal = true; + break; + + case GL_RGBA32UI: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_UNSIGNED_INT32; + *piBytesPerPixel = 16; + bRetVal = true; + break; + + case GL_RGBA32F: + pclImageFormat->image_channel_order = CL_RGBA; + pclImageFormat->image_channel_data_type = CL_FLOAT; + *piBytesPerPixel = 16; + bRetVal = true; + break; + case GL_DEPTH_COMPONENT32F: + pclImageFormat->image_channel_order = CL_DEPTH; + pclImageFormat->image_channel_data_type = CL_FLOAT; + *piBytesPerPixel = 4; + bRetVal = true; + break; + case GL_DEPTH_COMPONENT16: + pclImageFormat->image_channel_order = CL_DEPTH; + pclImageFormat->image_channel_data_type = CL_UNORM_INT16; + *piBytesPerPixel = 2; + bRetVal = true; + break; + case GL_DEPTH24_STENCIL8: + pclImageFormat->image_channel_order = CL_DEPTH_STENCIL; + pclImageFormat->image_channel_data_type = CL_UNORM_INT24; + *piBytesPerPixel = 4; + bRetVal = true; + break; + case GL_DEPTH32F_STENCIL8: + pclImageFormat->image_channel_order = CL_DEPTH_STENCIL; + pclImageFormat->image_channel_data_type = CL_FLOAT; + *piBytesPerPixel = 5; + bRetVal = true; + break; + default: + LogWarning("unsupported GL internal format"); + break; + } + amd::Image::Format imageFormat(*pclImageFormat); + if (bRetVal && !imageFormat.isSupported(amdContext, 0, flags)) { + bRetVal = false; + } + return bRetVal; +} diff --git a/rocclr/platform/interop_gl.hpp b/rocclr/platform/interop_gl.hpp new file mode 100644 index 0000000000..646d2e0c0d --- /dev/null +++ b/rocclr/platform/interop_gl.hpp @@ -0,0 +1,396 @@ +/* Copyright (c) 2010 - 2023 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 + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ + +#pragma once + +#ifdef _WIN32 +#include +#else //!_WIN32 +#include +#endif //!_WIN32 + +#include +#include +#include "CL/cl_gl.h" +#ifndef _WIN32 +#include +#endif //!_WIN32 + +#include +#include +#include + +#include "platform/context.hpp" +#include "platform/command.hpp" + +namespace amd +{ + +//! Class GLObject keeps all the info about the GL object +//! from which the CL object is created +class GLObject : public InteropObject +{ +protected: + cl_gl_object_type clGLType_; //!< CL GL object type + GLenum glTarget_; + GLuint gluiName_; + GLint gliMipLevel_; + GLenum glInternalFormat_; + GLint gliWidth_; + GLint gliHeight_; + GLint gliDepth_; + GLenum glCubemapFace_; + GLsizei glNumSamples_; + +public: +//! GLObject constructor initializes member variables + GLObject( + GLenum glTarget, + GLuint gluiName, + GLint gliMipLevel, + GLenum glInternalFormat, + GLint gliWidth, + GLint gliHeight, + GLint gliDepth, + cl_gl_object_type clGLType, + GLenum glCubemapFace, + GLsizei glNumSamples + ): // Initialization of member variables + clGLType_(clGLType), + glTarget_(glTarget), + gluiName_(gluiName), + gliMipLevel_(gliMipLevel), + glInternalFormat_(glInternalFormat), + gliWidth_(gliWidth), + gliHeight_(gliHeight), + gliDepth_(gliDepth), + glCubemapFace_(glCubemapFace), + glNumSamples_(glNumSamples) + { + } + + virtual ~GLObject() {} + virtual GLObject* asGLObject() {return this;} + +//! GLObject query functions to get GL info from member variables + GLenum getGLTarget() const {return glTarget_;} + GLuint getGLName() const {return gluiName_;} + GLint getGLMipLevel() const {return gliMipLevel_;} + GLenum getGLInternalFormat() const {return glInternalFormat_;} + GLint getGLSize() const {return gliWidth_;} + GLint getGLWidth() const {return gliWidth_;} + GLint getGLHeight() const {return gliHeight_;} + GLint getGLDepth() const {return gliDepth_;} + cl_gl_object_type getCLGLObjectType() const { return clGLType_; } + GLenum getCubemapFace() const {return glCubemapFace_;} + GLsizei getNumSamples() const { return glNumSamples_;} +}; + + +//! Class BufferGL is drived from classes Buffer and GLObject +//! where the former keeps all data for CL object and +//! the latter keeps all data for GL object +class BufferGL : public Buffer, public GLObject +{ +protected: + //! Initializes the device memory array which is nested + // after'BufferGL' object in memory layout. + virtual void initDeviceMemory(); +public: +//! BufferGL constructor just calls constructors of base classes +//! to pass down the parameters + BufferGL( + Context& amdContext, + cl_mem_flags clFlags, + size_t uiSizeInBytes, + GLenum glTarget, + GLuint gluiName) + : // Call base classes constructors + Buffer( + amdContext, + clFlags, + uiSizeInBytes + ), + GLObject( + glTarget, + gluiName, + 0, // Mipmap level default + GL_ARRAY_BUFFER, // Just init to some value + (GLint) uiSizeInBytes, + 1, + 1, + CL_GL_OBJECT_BUFFER, + 0, + 0 + ) + { + setInteropObj(this); + } + virtual ~BufferGL() {} + + virtual BufferGL* asBufferGL() { return this; } +}; + + +//! Class ImageGL is derived from classes Image and GLObject +//! where the former keeps all data for CL object and +//! the latter keeps all data for GL object +class ImageGL : public Image, public GLObject +{ +public: + //! ImageGL constructor just calls constructors of base classes + //! to pass down the parameters + ImageGL( + Context& amdContext, + cl_mem_object_type clType, + cl_mem_flags clFlags, + const Format& format, + size_t width, + size_t height, + size_t depth, + GLenum glTarget, + GLuint gluiName, + GLint gliMipLevel, + GLenum glInternalFormat, + cl_gl_object_type clGLType, + GLsizei numSamples, + GLenum glCubemapFace = 0) + : Image(amdContext, clType, clFlags, format, width, height, depth, + Format(format).getElementSize() * width, + Format(format).getElementSize() * width * height) + , GLObject(glTarget, gluiName, gliMipLevel, glInternalFormat, + static_cast(width), static_cast(height), + static_cast(depth), clGLType, glCubemapFace,numSamples) + { + setInteropObj(this); + } + + virtual ~ImageGL() {} + +protected: + //! Initializes the device memory array which is nested + // after'BufferGL' object in memory layout. + virtual void initDeviceMemory(); +}; + + typedef EGLContext (*PFN_eglGetCurrentContext) (); +#ifdef _WIN32 +#define APICALL WINAPI +#define GETPROCADDRESS GetProcAddress +#define API_GETPROCADDR "wglGetProcAddress" +#define FCN_STR_TYPE LPCSTR + typedef PROC (WINAPI* PFN_xxxGetProcAddress) (LPCSTR fcnName); + typedef HGLRC (APICALL* PFN_wglCreateContext) (HDC hdc); + typedef HGLRC (APICALL* PFN_wglGetCurrentContext) (void); + typedef HDC (APICALL* PFN_wglGetCurrentDC) (void); + typedef BOOL (APICALL* PFN_wglDeleteContext) (HGLRC hglrc); + typedef BOOL (APICALL* PFN_wglMakeCurrent) (HDC hdc, HGLRC hglrc); + typedef BOOL (APICALL* PFN_wglShareLists) (HGLRC hglrc1, HGLRC hglrc2); +#else //!_WIN32 +#define APICALL // __stdcall //??? todo odintsov +#define API_GETPROCADDR "glXGetProcAddress" +#define GETPROCADDRESS dlsym +#define FCN_STR_TYPE const GLubyte* +#define WINAPI +#define PROC void* + typedef void* (*PFN_xxxGetProcAddress) (const GLubyte* procName); + // X11 typedef + typedef Display* (*PFNXOpenDisplay)(_Xconst char* display_name ); + typedef int (*PFNXCloseDisplay)(Display* display ); + + //glx typedefs + typedef GLXDrawable (*PFNglXGetCurrentDrawable)(); + typedef Display* (*PFNglXGetCurrentDisplay)(); + typedef GLXContext (*PFNglXGetCurrentContext)( void ); + typedef XVisualInfo* (*PFNglXChooseVisual)(Display *dpy, int screen, int *attribList); + typedef GLXContext(*PFNglXCreateContext)(Display* dpy,XVisualInfo* vis,GLXContext shareList,Bool direct); + typedef void(*PFNglXDestroyContext)(Display* dpy, GLXContext ctx); + typedef Bool(*PFNglXMakeCurrent)( Display* dpy, GLXDrawable drawable, GLXContext ctx); + typedef void* HMODULE; +#endif //!_WIN32 + +#define GLPREFIX(rtype, fcn, dclargs) \ + typedef rtype (APICALL* PFN_##fcn) dclargs; + +// Declare prototypes for GL functions +#include "gl_functions.hpp" + +class GLFunctions +{ +public: + //! Locks any access to the virtual GPUs + class SetIntEnv : public amd::StackObject { + public: + //! Default constructor + SetIntEnv(GLFunctions* env); + + //! Destructor + ~SetIntEnv(); + + //! Checks if the environment setup was successful + bool isValid() const { return isValid_; } + + private: + GLFunctions* env_; //!< GL environment + bool isValid_; //!< If TRUE, then it's a valid setup + }; + +private: + HMODULE libHandle_; + int missed_; // Indicates how many GL functions not init'ed, if any + + amd::Monitor lock_; + + EGLDisplay eglDisplay_; + EGLContext eglOriginalContext_; + EGLContext eglInternalContext_; + EGLContext eglTempContext_; + bool isEGL_; + PFN_eglGetCurrentContext eglGetCurrentContext_; + +#ifdef _WIN32 + HGLRC hOrigGLRC_; + HDC hDC_; + HGLRC hIntGLRC_; // handle for internal GLRC to access shared context + HDC tempDC_; + HGLRC tempGLRC_; + +public: + PFN_wglCreateContext wglCreateContext_; + PFN_wglGetCurrentContext wglGetCurrentContext_; + PFN_wglGetCurrentDC wglGetCurrentDC_; + PFN_wglDeleteContext wglDeleteContext_; + PFN_wglMakeCurrent wglMakeCurrent_; + PFN_wglShareLists wglShareLists_; +#else +public: + Display* Dpy_; + GLXDrawable Drawable_; + GLXContext origCtx_; + Display* intDpy_; + Window intDrawable_; + GLXContext intCtx_; + Display* tempDpy_; + GLXDrawable tempDrawable_; + GLXContext tempCtx_; + + //pointers to X11 functions + PFNXOpenDisplay XOpenDisplay_; + PFNXCloseDisplay XCloseDisplay_; + + //pointers to GLX functions + PFNglXGetCurrentDrawable glXGetCurrentDrawable_; + PFNglXGetCurrentDisplay glXGetCurrentDisplay_; + PFNglXGetCurrentContext glXGetCurrentContext_; + PFNglXChooseVisual glXChooseVisual_; + PFNglXCreateContext glXCreateContext_; + PFNglXDestroyContext glXDestroyContext_; + PFNglXMakeCurrent glXMakeCurrent_; +#endif +public: + + GLFunctions(HMODULE h, bool isEGL); + ~GLFunctions(); + + bool update(intptr_t hglrc); + bool IsCurrentGlContext(const amd::Context::Info& info) const { + if (isEGL_) { + return ((info.hCtx_ != nullptr) && (eglGetCurrentContext_ != nullptr) && + (info.hCtx_ == eglGetCurrentContext_())); + } else { +#ifdef _WIN32 + return ((info.hCtx_ != nullptr) && (info.hCtx_ == wglGetCurrentContext_())); +#else + return ((info.hCtx_ != nullptr) && (info.hCtx_ == glXGetCurrentContext_())); +#endif // _WIN32 + } + } + + void WaitCurrentGlContext(const amd::Context::Info& info) const; + + // Query CL-GL context association + bool isAssociated() const + { + if (isEGL_ && eglDisplay_ && eglOriginalContext_) return true; +#ifdef _WIN32 + if(hDC_ && hOrigGLRC_) return true; +#else //!_WIN32 + if(Dpy_ && origCtx_) return true; +#endif //!_WIN32 + return false; + } + bool isEGL() const + { + return isEGL_; + } + // Accessor methods +#ifdef _WIN32 + HGLRC getOrigGLRC() const {return hOrigGLRC_;} + HDC getDC() const {return hDC_;} + HGLRC getIntGLRC() const {return hIntGLRC_;} +#else //!_WIN32 + Display* getDpy() const {return Dpy_;} + GLXDrawable getDrawable() const {return Drawable_;} + GLXContext getOrigCtx() const {return origCtx_;} + + Display* getIntDpy() const {return intDpy_;} + GLXDrawable getIntDrawable() const {return intDrawable_;} + GLXContext getIntCtx() const {return intCtx_;} + + EGLDisplay getEglDpy() const { return eglDisplay_; } + EGLContext getEglOrigCtx() const { return eglOriginalContext_; } +#endif //!_WIN32 + + // Initialize GL dynamic library and function pointers + bool init(intptr_t hdc, intptr_t hglrc); + + // Return true if successful, false - if error occurred + bool setIntEnv(); + bool restoreEnv(); + + amd::Monitor& getLock() { return lock_; } + + PFN_xxxGetProcAddress GetProcAddress_; + +#define GLPREFIX(rtype, fcn, dclargs) \ + PFN_##fcn fcn##_; +// Declare pointers to GL functions +#include "gl_functions.hpp" +}; + +//! Functions for executing the GL related stuff +cl_mem clCreateFromGLBufferAMD(Context& amdContext, cl_mem_flags flags, + GLuint bufobj, cl_int* errcode_ret); +cl_mem clCreateFromGLTextureAMD(Context& amdContext, cl_mem_flags flags, + GLenum target, GLint miplevel, GLuint texture, int* errcode_ret); +cl_mem clCreateFromGLRenderbufferAMD(Context& amdContext, cl_mem_flags flags, + GLuint renderbuffer, int* errcode_ret); + +bool +getCLFormatFromGL( + const Context& amdContext, + GLint gliInternalFormat, + cl_image_format* pclImageFormat, + int* piBytesPerPixel, + cl_mem_flags flags +); + +} //namespace amd + diff --git a/rocclr/platform/runtime.cpp b/rocclr/platform/runtime.cpp index 2096399944..7b475293a0 100644 --- a/rocclr/platform/runtime.cpp +++ b/rocclr/platform/runtime.cpp @@ -27,7 +27,7 @@ #include "platform/context.hpp" #include "platform/agent.hpp" -#include "amdocl/cl_gl_amd.hpp" +#include "platform/interop_gl.hpp" #ifdef _WIN32 #include