/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include "memcpy2d_tests_common.hh" #include #include #include #include HIP_TEST_CASE(Unit_hipMemcpy2DAsync_Positive_Basic) { using namespace std::placeholders; constexpr bool async = true; const auto stream_type = isQuickLevel() ? Streams::created : GENERATE(Streams::nullstream, Streams::perThread, Streams::created); const StreamGuard stream_guard(stream_type); const hipStream_t stream = stream_guard.stream(); SECTION("Device to Host") { Memcpy2DDeviceToHostShell( std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, stream), stream); } SECTION("Device to Device") { SECTION("Peer access disabled") { Memcpy2DDeviceToDeviceShell( std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, stream), stream); } SECTION("Peer access enabled") { Memcpy2DDeviceToDeviceShell( std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, stream), stream); } } SECTION("Host to Device") { Memcpy2DHostToDeviceShell( std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, stream), stream); } SECTION("Host to Host") { Memcpy2DHostToHostShell(std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, stream), stream); } } HIP_TEST_CASE(Unit_hipMemcpy2DAsync_Positive_Synchronization_Behavior) { using namespace std::placeholders; HIP_CHECK(hipDeviceSynchronize()); SECTION("Host to Device") { Memcpy2DHtoDSyncBehavior(std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, nullptr), false); } #if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-233 SECTION("Device to Pageable Host") { Memcpy2DDtoHPageableSyncBehavior( std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, nullptr), true); } #endif SECTION("Device to Pinned Host") { Memcpy2DDtoHPinnedSyncBehavior(std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, nullptr), false); } SECTION("Device to Device") { Memcpy2DDtoDSyncBehavior(std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, nullptr), false); } #if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-233 SECTION("Host to Host") { Memcpy2DHtoHSyncBehavior(std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, nullptr), true); } #endif } HIP_TEST_CASE(Unit_hipMemcpy2DAsync_Positive_Parameters) { using namespace std::placeholders; constexpr bool async = true; Memcpy2DZeroWidthHeight(std::bind(hipMemcpy2DAsync, _1, _2, _3, _4, _5, _6, _7, nullptr)); } HIP_TEST_CASE(Unit_hipMemcpy2DAsync_Negative_Parameters) { constexpr size_t cols = 128; constexpr size_t rows = 128; constexpr auto NegativeTests = [](void* dst, size_t dpitch, const void* src, size_t spitch, size_t width, size_t height, hipMemcpyKind kind) { SECTION("dst == nullptr") { HIP_CHECK_ERROR(hipMemcpy2DAsync(nullptr, dpitch, src, spitch, width, height, kind, nullptr), hipErrorInvalidValue); } SECTION("src == nullptr") { HIP_CHECK_ERROR(hipMemcpy2DAsync(dst, dpitch, nullptr, spitch, width, height, kind, nullptr), hipErrorInvalidValue); } SECTION("dpitch < width") { HIP_CHECK_ERROR(hipMemcpy2DAsync(dst, width - 1, src, spitch, width, height, kind, nullptr), hipErrorInvalidPitchValue); } SECTION("spitch < width") { HIP_CHECK_ERROR(hipMemcpy2DAsync(dst, dpitch, src, width - 1, width, height, kind, nullptr), hipErrorInvalidPitchValue); } SECTION("dpitch > max pitch") { int attr = 0; HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); HIP_CHECK_ERROR(hipMemcpy2DAsync(dst, static_cast(attr) + 1, src, spitch, width, height, kind, nullptr), hipErrorInvalidValue); } SECTION("spitch > max pitch") { int attr = 0; HIP_CHECK(hipDeviceGetAttribute(&attr, hipDeviceAttributeMaxPitch, 0)); HIP_CHECK_ERROR(hipMemcpy2DAsync(dst, dpitch, src, static_cast(attr) + 1, width, height, kind, nullptr), hipErrorInvalidValue); } #if HT_NVIDIA // Disabled on AMD due to defect - EXSWHTEC-234 SECTION("Invalid MemcpyKind") { HIP_CHECK_ERROR(hipMemcpy2DAsync(dst, dpitch, src, spitch, width, height, static_cast(-1), nullptr), hipErrorInvalidMemcpyDirection); } #endif }; SECTION("Host to device") { LinearAllocGuard2D device_alloc(cols, rows); LinearAllocGuard host_alloc(LinearAllocs::hipHostMalloc, device_alloc.pitch() * rows); NegativeTests(device_alloc.ptr(), device_alloc.pitch(), host_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), device_alloc.height(), hipMemcpyHostToDevice); } SECTION("Device to host") { LinearAllocGuard2D device_alloc(cols, rows); LinearAllocGuard host_alloc(LinearAllocs::hipHostMalloc, device_alloc.pitch() * rows); NegativeTests(host_alloc.ptr(), device_alloc.pitch(), device_alloc.ptr(), device_alloc.pitch(), device_alloc.width(), device_alloc.height(), hipMemcpyDeviceToHost); } SECTION("Host to host") { LinearAllocGuard src_alloc(LinearAllocs::hipHostMalloc, cols * rows * sizeof(int)); LinearAllocGuard dst_alloc(LinearAllocs::hipHostMalloc, cols * rows * sizeof(int)); NegativeTests(dst_alloc.ptr(), cols * sizeof(int), src_alloc.ptr(), cols * sizeof(int), cols * sizeof(int), rows, hipMemcpyHostToHost); } SECTION("Device to device") { LinearAllocGuard2D src_alloc(cols, rows); LinearAllocGuard2D dst_alloc(cols, rows); NegativeTests(dst_alloc.ptr(), dst_alloc.pitch(), src_alloc.ptr(), src_alloc.pitch(), dst_alloc.width(), dst_alloc.height(), hipMemcpyDeviceToDevice); } } /** * Test Description * ------------------------ * - Basic scenario to trigger capturehipMemcpy2DAsync internal api for * improved code coverage * Test source * ------------------------ * - unit/memory/hipMemcpy2DAsync.cc * Test requirements * ------------------------ * - HIP_VERSION >= 6.0 */ HIP_TEMPLATE_TEST_CASE(Unit_hipMemcpy2DAsync_Capture, int, float, double) { using ValueType = TestType; constexpr int kNumRowsOptions[] = {3, 4, 100}; constexpr int kNumColsOptions[] = {3, 4, 100}; int num_rows = GENERATE_REF(from_range(std::begin(kNumRowsOptions), std::end(kNumRowsOptions))); int num_cols = GENERATE_REF(from_range(std::begin(kNumColsOptions), std::end(kNumColsOptions))); hipStream_t stream = nullptr; size_t device_pitch = 0; auto host_matrix_a = std::make_unique(num_rows * num_cols); auto host_matrix_b = std::make_unique(num_rows * num_cols); ValueType* device_matrix_a = nullptr; HIP_CHECK(hipStreamCreate(&stream)); for (int row = 0; row < num_rows; ++row) { for (int col = 0; col < num_cols; ++col) { host_matrix_b[row * num_cols + col] = static_cast(row * num_cols + col); } } HIP_CHECK(hipMallocPitch(reinterpret_cast(&device_matrix_a), &device_pitch, sizeof(ValueType) * num_cols, num_rows)); HIP_CHECK(hipMemcpy2D(device_matrix_a, device_pitch, host_matrix_b.get(), sizeof(ValueType) * num_cols, sizeof(ValueType) * num_cols, num_rows, hipMemcpyHostToDevice)); HIP_CHECK(hipDeviceSynchronize()); GENERATE_CAPTURE(); BEGIN_CAPTURE(stream); HIP_CHECK(hipMemcpy2DAsync(host_matrix_a.get(), num_cols * sizeof(ValueType), device_matrix_a, device_pitch, num_cols * sizeof(ValueType), num_rows, hipMemcpyDeviceToHost, stream)); END_CAPTURE(stream); HIP_CHECK(hipDeviceSynchronize()); HIP_CHECK(hipStreamSynchronize(stream)); for (int row = 0; row < num_rows; ++row) { for (int col = 0; col < num_cols; ++col) { REQUIRE(host_matrix_a[row * num_cols + col] == host_matrix_b[row * num_cols + col]); } } HIP_CHECK(hipStreamDestroy(stream)); HIP_CHECK(hipFree(device_matrix_a)); }