/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include #include #include #include /** * @addtogroup hipDrvGraphMemcpyNodeSetParams hipDrvGraphMemcpyNodeSetParams * @{ * @ingroup GraphTest * `hipDrvGraphMemcpyNodeSetParams(hipGraphNode_t hNode, const HIP_MEMCPY3D* nodeParams)` - Sets a * memcpy node's parameters */ /** * Test Description * ------------------------ * - Verify that node parameters get updated correctly by creating a node with valid but * incorrect parameters, and then setting them to the correct values after which the graph is * executed and the results of the memcpy verified. * The test is run for all possible memcpy directions, with both the corresponding memcpy * kind and hipMemcpyDefault, as well as half page and full page allocation sizes. * Test source * ------------------------ * - unit/graph/hipDrvGraphMemcpyNodeSetParams.cc * Test requirements * ------------------------ * - HIP_VERSION >= 6.0 */ HIP_TEST_CASE(Unit_hipDrvGraphMemcpyNodeSetParams_Positive_Basic) { using namespace std::placeholders; constexpr bool async = false; HIP_CHECK(hipInit(0)); hipDevice_t device; hipCtx_t context; HIP_CHECK(hipDeviceGet(&device, 0)); HIP_CHECK(hipCtxCreate(&context, 0, device)); SECTION("Device to host") { Memcpy3DDeviceToHostShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } SECTION("Host to device") { Memcpy3DHostToDeviceShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } SECTION("Host to host") { Memcpy3DHostToHostShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } SECTION("Device to device") { SECTION("Peer access enabled") { Memcpy3DDeviceToDeviceShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } SECTION("Peer access disabled") { Memcpy3DDeviceToDeviceShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } /* * Setting back the old context, since in the Memcpy3DDeviceToDeviceShell * function the current context is getting modified with hipSetDevice calls */ HIP_CHECK(hipCtxSetCurrent(context)); } HIP_CHECK(hipCtxPopCurrent(&context)); HIP_CHECK(hipCtxDestroy(context)); } HIP_TEST_CASE(Unit_hipDrvGraphMemcpyNodeSetParams_Positive_Array) { CHECK_IMAGE_SUPPORT using namespace std::placeholders; constexpr bool async = false; HIP_CHECK(hipInit(0)); hipDevice_t device; hipCtx_t context; HIP_CHECK(hipDeviceGet(&device, 0)); HIP_CHECK(hipCtxCreate(&context, 0, device)); SECTION("Array from/to Host") { DrvMemcpy3DArrayHostShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } SECTION("Array from/to Device") { DrvMemcpy3DArrayDeviceShell( std::bind(DrvMemcpy3DGraphWrapper, _1, _2, _3, _4, _5, _6, context, _7)); } HIP_CHECK(hipCtxPopCurrent(&context)); HIP_CHECK(hipCtxDestroy(context)); } /** * Test Description * ------------------------ * - Verify API behaviour with invalid arguments: * -# node is nullptr * -# dst is nullptr * -# src is nullptr * -# dstPitch < width * -# srcPitch < width * -# dstPitch > max pitch * -# srcPitch > max pitch * -# WidthInBytes + dstXInBytes > dstPitch * -# WidthInBytes + srcXInBytes > srcPitch * -# dstY out of bounds * -# srcY out of bounds * -# dstZ out of bounds * -# srcZ out of bounds * Test source * ------------------------ * - unit/graph/hipDrvGraphMemcpyNodeSetParams.cc * Test requirements * ------------------------ * - HIP_VERSION >= 6.0 */ HIP_TEST_CASE(Unit_hipDrvGraphMemcpyNodeSetParams_Negative_Parameters) { using namespace std::placeholders; HIP_CHECK(hipInit(0)); hipDevice_t device; hipCtx_t context; HIP_CHECK(hipDeviceGet(&device, 0)); HIP_CHECK(hipCtxCreate(&context, 0, device)); constexpr hipExtent extent{128 * sizeof(int), 128, 8}; constexpr auto NegativeTests = [](hipPitchedPtr dst_ptr, hipPos dst_pos, hipPitchedPtr src_ptr, hipPos src_pos, hipExtent extent, hipMemcpyKind kind, hipCtx_t context) { hipGraph_t graph = nullptr; HIP_CHECK(hipGraphCreate(&graph, 0)); hipGraphNode_t node = nullptr; auto params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, src_ptr, src_pos, extent, kind); HIP_CHECK(hipDrvGraphAddMemcpyNode(&node, graph, nullptr, 0, ¶ms, context)); SECTION("node == nullptr") { HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(nullptr, ¶ms), hipErrorInvalidValue); } SECTION("dst_ptr.ptr == nullptr") { hipPitchedPtr invalid_ptr = dst_ptr; invalid_ptr.ptr = nullptr; auto invalid_params = GetDrvMemcpy3DParms(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("src_ptr.ptr == nullptr") { hipPitchedPtr invalid_ptr = src_ptr; invalid_ptr.ptr = nullptr; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("dstPitch < width") { hipPitchedPtr invalid_ptr = dst_ptr; invalid_ptr.pitch = extent.width - 1; auto invalid_params = GetDrvMemcpy3DParms(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("srcPitch < width") { hipPitchedPtr invalid_ptr = src_ptr; invalid_ptr.pitch = extent.width - 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("dstPitch > max pitch") { int attr = 0; HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); hipPitchedPtr invalid_ptr = dst_ptr; invalid_ptr.pitch = attr; auto invalid_params = GetDrvMemcpy3DParms(invalid_ptr, dst_pos, src_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("srcPitch > max pitch") { int attr = 0; HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); hipPitchedPtr invalid_ptr = src_ptr; invalid_ptr.pitch = attr; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, invalid_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("WidthInBytes + dstXInBytes > dstPitch") { hipPos invalid_pos = dst_pos; invalid_pos.x = dst_ptr.pitch - extent.width + 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("WidthInBytes + srcXInBytes > srcPitch") { hipPos invalid_pos = src_pos; invalid_pos.x = src_ptr.pitch - extent.width + 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("dstY out of bounds") { hipPos invalid_pos = dst_pos; invalid_pos.y = 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("srcY out of bounds") { hipPos invalid_pos = src_pos; invalid_pos.y = 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("dstZ out of bounds") { hipPos invalid_pos = dst_pos; invalid_pos.z = 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, invalid_pos, src_ptr, src_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } SECTION("srcZ out of bounds") { hipPos invalid_pos = src_pos; invalid_pos.z = 1; auto invalid_params = GetDrvMemcpy3DParms(dst_ptr, dst_pos, src_ptr, invalid_pos, extent, kind); HIP_CHECK_ERROR(hipDrvGraphMemcpyNodeSetParams(node, &invalid_params), hipErrorInvalidValue); } HIP_CHECK(hipGraphDestroy(graph)); }; SECTION("Host to Device") { LinearAllocGuard3D device_alloc(extent); LinearAllocGuard host_alloc( LinearAllocs::hipHostMalloc, device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); NegativeTests(device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), device_alloc.height()), make_hipPos(0, 0, 0), extent, hipMemcpyHostToDevice, context); } SECTION("Device to Host") { LinearAllocGuard3D device_alloc(extent); LinearAllocGuard host_alloc( LinearAllocs::hipHostMalloc, device_alloc.pitch() * device_alloc.height() * device_alloc.depth()); NegativeTests(make_hipPitchedPtr(host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), device_alloc.height()), make_hipPos(0, 0, 0), device_alloc.pitched_ptr(), make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToHost, context); } SECTION("Host to Host") { LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, extent.width * extent.height * extent.depth); LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, extent.width * extent.height * extent.depth); NegativeTests(make_hipPitchedPtr(dst_alloc.ptr(), extent.width, extent.width, extent.height), make_hipPos(0, 0, 0), make_hipPitchedPtr(src_alloc.ptr(), extent.width, extent.width, extent.height), make_hipPos(0, 0, 0), extent, hipMemcpyHostToHost, context); } SECTION("Device to Device") { LinearAllocGuard3D src_alloc(extent); LinearAllocGuard3D dst_alloc(extent); NegativeTests(dst_alloc.pitched_ptr(), make_hipPos(0, 0, 0), src_alloc.pitched_ptr(), make_hipPos(0, 0, 0), extent, hipMemcpyDeviceToDevice, context); } HIP_CHECK(hipCtxPopCurrent(&context)); HIP_CHECK(hipCtxDestroy(context)); } /** * End doxygen group GraphTest. * @} */