diff --git a/catch/include/hip_test_checkers.hh b/catch/include/hip_test_checkers.hh index bd1fa62610..1a6df666c7 100644 --- a/catch/include/hip_test_checkers.hh +++ b/catch/include/hip_test_checkers.hh @@ -22,6 +22,7 @@ THE SOFTWARE. #pragma once #include "hip_test_common.hh" +#include "hip_array_common.hh" #include #include #include @@ -79,9 +80,9 @@ bool checkArray(T* hData, T* hOutputData, size_t width, size_t height, size_t de for (size_t j = 0; j < height; j++) { for (size_t k = 0; k < width; k++) { int offset = i * width * height + j * width + k; - if (hData[offset] != hOutputData[offset]) { - INFO("Mismatch at [" << i << "," << j << "," << k << "]:" << hData[offset] << "----" - << hOutputData[offset]); + if (!isEqual(hData[offset], hOutputData[offset])) { + INFO("Mismatch at [" << i << "," << j << "," << k << "]:" << getString(hData[offset]) + << "----" << getString(hOutputData[offset])); CHECK(false); return false; } diff --git a/catch/stress/stream/CMakeLists.txt b/catch/stress/stream/CMakeLists.txt index d3d6fd8644..609b494f33 100644 --- a/catch/stress/stream/CMakeLists.txt +++ b/catch/stress/stream/CMakeLists.txt @@ -7,4 +7,4 @@ set(TEST_SRC hip_add_exe_to_target(NAME stream_stress TEST_SRC ${TEST_SRC} TEST_TARGET_NAME stress_test - COMPILE_OPTIONS -std=c++14) + COMPILE_OPTIONS -std=c++17) diff --git a/catch/unit/device/CMakeLists.txt b/catch/unit/device/CMakeLists.txt index 2cb03d0575..a876d86694 100644 --- a/catch/unit/device/CMakeLists.txt +++ b/catch/unit/device/CMakeLists.txt @@ -46,7 +46,7 @@ add_executable(hipDeviceGetP2PAttribute_exe EXCLUDE_FROM_ALL hipDeviceGetP2PAttr hip_add_exe_to_target(NAME DeviceTest TEST_SRC ${TEST_SRC} TEST_TARGET_NAME build_tests - COMPILE_OPTIONS -std=c++14) + COMPILE_OPTIONS -std=c++17) add_dependencies(build_tests getDeviceCount) add_dependencies(build_tests hipDeviceGetP2PAttribute_exe) diff --git a/catch/unit/errorHandling/CMakeLists.txt b/catch/unit/errorHandling/CMakeLists.txt index 5df11b5d1c..7dcdb52f4c 100644 --- a/catch/unit/errorHandling/CMakeLists.txt +++ b/catch/unit/errorHandling/CMakeLists.txt @@ -11,4 +11,4 @@ set(TEST_SRC hip_add_exe_to_target(NAME ErrorHandlingTest TEST_SRC ${TEST_SRC} TEST_TARGET_NAME build_tests - COMPILE_OPTIONS -std=c++14) \ No newline at end of file + COMPILE_OPTIONS -std=c++17) \ No newline at end of file diff --git a/catch/unit/texture/CMakeLists.txt b/catch/unit/texture/CMakeLists.txt index c4760d1e69..0b18379c7b 100644 --- a/catch/unit/texture/CMakeLists.txt +++ b/catch/unit/texture/CMakeLists.txt @@ -29,6 +29,7 @@ set(TEST_SRC hipTextureObj2D.cc hipSimpleTexture3D.cc hipTextureRef2D.cc + hipSimpleTexture1DLayered.cc hipSimpleTexture2DLayered.cc hipBindTex2DPitch.cc hipBindTexRef1DFetch.cc diff --git a/catch/unit/texture/hipSimpleTexture1DLayered.cc b/catch/unit/texture/hipSimpleTexture1DLayered.cc new file mode 100644 index 0000000000..7b3de8d235 --- /dev/null +++ b/catch/unit/texture/hipSimpleTexture1DLayered.cc @@ -0,0 +1,324 @@ +/* +Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +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 clang diagnostic ignored "-Wunused-parameter" +#include +#include +#include +#include +//#define DEBUG_DATA + +template +__global__ void simpleKernelLayered1DArray(hipTextureObject_t tex, TestType* outputData, + unsigned int width, unsigned int layer) { +#if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT + unsigned int x = blockIdx.x * blockDim.x + threadIdx.x; + outputData[layer * width + x] = tex1DLayered(tex, x, layer); +#endif +} + +/** + * Test Description + * ------------------------ + * - The suite will test host buffer copied to/from layered 1D array in following steps, + allocating a host buffer, + creating layered array, + copying host buffer to the layered array in two ways, + copying whole host buffer to the layered array, + copying host buffer layer by layer to the layered array and then + copying & verifying layer data, + creating a texture object on the layered array, + getting the data from the texture object in kernel, + verifing the data in host + * Test source + * ------------------------ + * - catch\unit\texture\hipSimpleTexture1DLayered.cc + * Test requirements + * ------------------------ + * - Host specific (WINDOWS and LINUX) + * - Layered 1D array supported on device + * - Textures supported on device + * - HIP_VERSION >= 6.0 + */ +TEMPLATE_TEST_CASE("Unit_Layered1DTexture_Check_HostBufferToFromLayered1DArray", "", + char, unsigned char, short, ushort, int, uint, float, + char1, uchar1, short1, ushort1, int1, uint1, float1, + char2, uchar2, short2, ushort2, int2, uint2, float2, + char4, uchar4, short4, ushort4, int4, uint4, float4) { + CHECK_IMAGE_SUPPORT + constexpr int SIZE = 512; + constexpr int num_layers = 5; + constexpr unsigned int width = SIZE; + constexpr unsigned int size = width * num_layers * sizeof(TestType); + TestType* hData = reinterpret_cast(malloc(size)); + REQUIRE(hData != nullptr); + memset(hData, 0, size); + for (unsigned int layer = 0; layer < num_layers; layer++) { + for (unsigned int i = 0; i < width; i++) { + initVal(hData[layer * width + i]); + } + } + hipChannelFormatDesc channelDesc; + // Allocate array and copy image data + channelDesc = hipCreateChannelDesc(); + hipArray_t arr; + HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, + make_hipExtent(width, 0, num_layers), hipArrayLayered)); + hipMemcpy3DParms myparms{}; + + SECTION("hipMemcpy3D whole layers") { + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(TestType), width, 1); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, 1, num_layers); + myparms.kind = hipMemcpyHostToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + } + + SECTION("hipMemcpy3D layer by layer") { + constexpr unsigned int layerSize = width * sizeof(TestType); + TestType* hLayerData = reinterpret_cast(malloc(layerSize)); + REQUIRE(hLayerData != nullptr); + for (unsigned int layer = 0; layer < num_layers; layer++) { + // Copy buffer layer to image layer + memset(hLayerData, 0, layerSize); + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, layer); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(TestType), width, 1); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, 1, 1); + myparms.kind = hipMemcpyHostToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + + // Copy image layer to buffer layer + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcArray = arr; + myparms.dstPtr = make_hipPitchedPtr(hLayerData, width * sizeof(TestType), width, 1); + myparms.extent = make_hipExtent(width, 1, 1); + myparms.kind = hipMemcpyDeviceToHost; + HIP_CHECK(hipMemcpy3D(&myparms)); + + // Compare layer +#ifdef DEBUG_DATA + for (unsigned int i = 0; i < width; i++) { + fprintf(stderr, "%4u: %u: %s -- %s\n", layer, i, getString(hData[layer * width + i]), + getString(hLayerData[i])); + } +#endif + REQUIRE(HipTest::checkArray(hData + layer * width, hLayerData, width, 1, 1)); + } + free(hLayerData); + } + + hipTextureObject_t tex; + hipResourceDesc texRes; + memset(&texRes, 0, sizeof(hipResourceDesc)); + texRes.resType = hipResourceTypeArray; + texRes.res.array.array = arr; + + hipTextureDesc texDescr; + memset(&texDescr, 0, sizeof(hipTextureDesc)); + texDescr.normalizedCoords = 0; + texDescr.filterMode = hipFilterModePoint; + texDescr.addressMode[0] = hipAddressModeClamp; + texDescr.addressMode[1] = hipAddressModeClamp; + texDescr.addressMode[2] = hipAddressModeClamp; + texDescr.readMode = hipReadModeElementType; + HIP_CHECK(hipCreateTextureObject(&tex, &texRes, &texDescr, NULL)); + + // Allocate device memory for result + TestType* dData = nullptr; + HIP_CHECK(hipMalloc(&dData, size)); + + dim3 dimBlock(8); + dim3 dimGrid((width + dimBlock.x - 1) / dimBlock.x); + for (unsigned int layer = 0; layer < num_layers; layer++) { + hipLaunchKernelGGL(simpleKernelLayered1DArray, dimGrid, dimBlock, 0, 0, + tex, dData, width, layer); + HIP_CHECK(hipGetLastError()); + } + HIP_CHECK(hipDeviceSynchronize()); + + // Allocate mem for the result on host side + TestType *hOutputData = reinterpret_cast(malloc(size)); + REQUIRE(hOutputData != nullptr); + + // Copy result from device to host + HIP_CHECK(hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost)); + REQUIRE(HipTest::checkArray(hData, hOutputData, width, 1, num_layers)); + + HIP_CHECK(hipFree(dData)); + HIP_CHECK(hipFreeArray(arr)); + free(hData); + free(hOutputData); + HIP_CHECK(hipDestroyTextureObject(tex)); +} + +/** + * Test Description + * ------------------------ + * - The suite will test device buffer copied to/from layered 1D array in following steps, + allocating host buffer, + allocating device buffer, + copying host buffer to device buffer, + creating layered array, + copying device buffer to the layered array in two ways, + copying whole device buffer to the layered array, + copying device buffer layer by layer to the layered array and then + copying & verifying layer data, + creating a texture object on the layered array, + getting the data from the texture object in kernel, + verifing the data in host + * Test source + * ------------------------ + * - catch\unit\texture\hipSimpleTexture1DLayered.cc + * Test requirements + * ------------------------ + * - Host specific (WINDOWS and LINUX) + * - Layered 1D array supported on device + * - Textures supported on device + * - HIP_VERSION >= 6.0 + */ +TEMPLATE_TEST_CASE("Unit_Layered1DTexture_Check_DeviceBufferToFromLayered1DArray", "", + char, unsigned char, short, ushort, int, uint, float, + char1, uchar1, short1, ushort1, int1, uint1, float1, + char2, uchar2, short2, ushort2, int2, uint2, float2, + char4, uchar4, short4, ushort4, int4, uint4, float4) { + CHECK_IMAGE_SUPPORT + constexpr int SIZE = 512; + constexpr int num_layers = 5; + constexpr unsigned int width = SIZE; + constexpr unsigned int size = width * num_layers * sizeof(TestType); + TestType* hData = reinterpret_cast(malloc(size)); + memset(hData, 0, size); + for (unsigned int layer = 0; layer < num_layers; layer++) { + for (unsigned int i = 0; i < width; i++) { + initVal(hData[layer * width + i]); + } + } + + TestType* dData = nullptr; + HIP_CHECK(hipMalloc(&dData, size)); + + HIP_CHECK(hipMemcpy(dData, hData, size, hipMemcpyHostToDevice)); + + hipChannelFormatDesc channelDesc; + // Allocate array and copy image data + channelDesc = hipCreateChannelDesc(); + hipArray_t arr; + HIP_CHECK( + hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, 0, num_layers), hipArrayLayered)); + hipMemcpy3DParms myparms{}; + + SECTION("hipMemcpy3D whole layers") { + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcPtr = make_hipPitchedPtr(dData, width * sizeof(TestType), width, 1); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, 1, num_layers); + myparms.kind = hipMemcpyDeviceToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + } + + SECTION("hipMemcpy3D layer by layer") { + constexpr unsigned int layerSize = width * sizeof(TestType); + TestType* hLayerData = reinterpret_cast(malloc(layerSize)); + REQUIRE(hLayerData != nullptr); + TestType* dData1 = nullptr; + HIP_CHECK(hipMalloc(&dData1, size)); + HIP_CHECK(hipMemset(dData1, 0, size)); + for (unsigned int layer = 0; layer < num_layers; layer++) { + // Copy buffer layer to image layer + memset(hLayerData, 0, layerSize); + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, layer); + myparms.srcPtr = make_hipPitchedPtr(dData, width * sizeof(TestType), width, 1); + myparms.kind = hipMemcpyDeviceToDevice; + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, 1, 1); + HIP_CHECK(hipMemcpy3D(&myparms)); + + // Copy image layer to buffer layer + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, layer); + myparms.srcArray = arr; + myparms.dstPtr = make_hipPitchedPtr(dData1, width * sizeof(TestType), width, 1); + myparms.extent = make_hipExtent(width, 1, 1); + myparms.kind = hipMemcpyDeviceToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + HIP_CHECK(hipMemcpy(hLayerData, dData1 + layer * width, layerSize, hipMemcpyDeviceToHost)); + // Compare layer +#ifdef DEBUG_DATA + for (unsigned int i = 0; i < width; i++) { + fprintf(stderr, "%4u: %u: %s -- %s\n", layer, i, + getString(hData[layer * width + i]).c_str(), getString(hLayerData[i]).c_str()); + } +#endif + REQUIRE(HipTest::checkArray(hData + layer * width, hLayerData, width, 1, 1)); + } + free(hLayerData); + HIP_CHECK(hipFree(dData1)); + } + + hipTextureObject_t tex; + hipResourceDesc texRes; + memset(&texRes, 0, sizeof(hipResourceDesc)); + texRes.resType = hipResourceTypeArray; + texRes.res.array.array = arr; + + hipTextureDesc texDescr; + memset(&texDescr, 0, sizeof(hipTextureDesc)); + texDescr.normalizedCoords = 0; + texDescr.filterMode = hipFilterModePoint; + texDescr.addressMode[0] = hipAddressModeClamp; + texDescr.addressMode[1] = hipAddressModeClamp; + texDescr.addressMode[2] = hipAddressModeClamp; + texDescr.readMode = hipReadModeElementType; + HIP_CHECK(hipCreateTextureObject(&tex, &texRes, &texDescr, NULL)); + HIP_CHECK(hipMemset(dData, 0, size)); + + dim3 dimBlock(8); + dim3 dimGrid((width + dimBlock.x - 1) / dimBlock.x); + for (unsigned int layer = 0; layer < num_layers; layer++) { + hipLaunchKernelGGL(simpleKernelLayered1DArray, dimGrid, dimBlock, 0, 0, tex, dData, + width, layer); + HIP_CHECK(hipGetLastError()); + } + HIP_CHECK(hipDeviceSynchronize()); + + // Allocate mem for the result on host side + TestType* hOutputData = reinterpret_cast(malloc(size)); + REQUIRE(hOutputData != nullptr); + + // Copy result from device to host + HIP_CHECK(hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost)); + REQUIRE(HipTest::checkArray(hData, hOutputData, width, 1, num_layers)); + + HIP_CHECK(hipFree(dData)); + HIP_CHECK(hipFreeArray(arr)); + free(hData); + free(hOutputData); + HIP_CHECK(hipDestroyTextureObject(tex)); +} diff --git a/catch/unit/texture/hipSimpleTexture2DLayered.cc b/catch/unit/texture/hipSimpleTexture2DLayered.cc index c80a77787f..5075a73d9a 100644 --- a/catch/unit/texture/hipSimpleTexture2DLayered.cc +++ b/catch/unit/texture/hipSimpleTexture2DLayered.cc @@ -19,97 +19,316 @@ THE SOFTWARE. #pragma clang diagnostic ignored "-Wunused-parameter" #include +#include #include +#include +//#define DEBUG_DATA -#if CUDA_VERSION < CUDA_12000 - -typedef float T; - -// Texture reference for 2D Layered texture -texture tex2DL; - -__global__ void simpleKernelLayeredArray(T* outputData, - int width, int height, int layer) { +template +__global__ void simpleKernelLayered2DArray(hipTextureObject_t tex, TestType* outputData, + unsigned int width, unsigned int height, + unsigned int layer) { #if !defined(__HIP_NO_IMAGE_SUPPORT) || !__HIP_NO_IMAGE_SUPPORT unsigned int x = blockIdx.x * blockDim.x + threadIdx.x; unsigned int y = blockIdx.y * blockDim.y + threadIdx.y; - outputData[layer * width * height + y * width + x] = tex2DLayered(tex2DL, - x, y, layer); + outputData[layer * width * height + y * width + x] = tex2DLayered(tex, x, y, layer); #endif } -TEST_CASE("Unit_hipSimpleTexture2DLayered_Check") { +/** + * Test Description + * ------------------------ + * - The suite will test host buffer copied to/from layered 2D array in following steps, + allocating a host buffer, + creating layered array, + copying host buffer to the layered array in two ways, + copying whole host buffer to the layered array, + copying host buffer layer by layer to the layered array and then + copying & verifying layer data, + creating a texture object on the layered array, + getting the data from the texture object in kernel, + verifing the data in host + * Test source + * ------------------------ + * - catch\unit\texture\hipSimpleTexture2DLayered.cc + * Test requirements + * ------------------------ + * - Host specific (WINDOWS and LINUX) + * - Layered 2D array supported on device + * - Textures supported on device + * - HIP_VERSION >= 6.0 + */ +TEMPLATE_TEST_CASE("Unit_Layered2DTexture_Check_HostBufferToFromLayered2DArray", "", + char, unsigned char, short, ushort, int, uint, float, + char1, uchar1, short1, ushort1, int1, uint1, float1, + char2, uchar2, short2, ushort2, int2, uint2, float2, + char4, uchar4, short4, ushort4, int4, uint4, float4) { CHECK_IMAGE_SUPPORT - constexpr int SIZE = 512; constexpr int num_layers = 5; constexpr unsigned int width = SIZE; constexpr unsigned int height = SIZE; - constexpr unsigned int size = width * height * num_layers * sizeof(T); - - T* hData = reinterpret_cast(malloc(size)); + constexpr unsigned int size = width * height * num_layers * sizeof(TestType); + TestType* hData = reinterpret_cast(malloc(size)); REQUIRE(hData != nullptr); memset(hData, 0, size); for (unsigned int layer = 0; layer < num_layers; layer++) { - for (int i = 0; i < static_cast(width * height); i++) { - hData[layer * width * height + i] = i; + for (unsigned int i = 0; i < width * height; i++) { + initVal(hData[layer * width * height + i]); } } hipChannelFormatDesc channelDesc; // Allocate array and copy image data - channelDesc = hipCreateChannelDesc(sizeof(T)*8, 0, 0, 0, - hipChannelFormatKindFloat); + channelDesc = hipCreateChannelDesc(); hipArray_t arr; - HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, num_layers), hipArrayLayered)); hipMemcpy3DParms myparms{}; - myparms.srcPos = make_hipPos(0, 0, 0); - myparms.dstPos = make_hipPos(0, 0, 0); - myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height); - myparms.dstArray = arr; - myparms.extent = make_hipExtent(width , height, num_layers); - // myparms.kind = hipMemcpyHostToDevice; - HIP_CHECK(hipMemcpy3D(&myparms)); + SECTION("hipMemcpy3D whole layers") { + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(TestType), width, height); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, height, num_layers); + myparms.kind = hipMemcpyHostToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + } - // set texture parameters - tex2DL.addressMode[0] = hipAddressModeWrap; - tex2DL.addressMode[1] = hipAddressModeWrap; - tex2DL.filterMode = hipFilterModePoint; - tex2DL.normalized = false; + SECTION("hipMemcpy3D layer by layer") { + constexpr unsigned int layerSize = width * height * sizeof(TestType); + TestType* hLayerData = reinterpret_cast(malloc(layerSize)); + REQUIRE(hLayerData != nullptr); + for (unsigned int layer = 0; layer < num_layers; layer++) { + // Copy buffer layer to image layer + memset(hLayerData, 0, layerSize); + memset(&myparms, 0, sizeof(myparms)); + //myparms.srcPos = make_hipPos(layerSize * layer, 0, 0); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, layer); + myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(TestType), width, height); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, height, 1); + myparms.kind = hipMemcpyHostToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); - // Bind the array to the texture - HIP_CHECK(hipBindTextureToArray(tex2DL, arr, channelDesc)); + // Copy image layer to buffer layer + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcArray = arr; + myparms.dstPtr = make_hipPitchedPtr(hLayerData, width * sizeof(TestType), width, height); + myparms.extent = make_hipExtent(width, height, 1); + myparms.kind = hipMemcpyDeviceToHost; + HIP_CHECK(hipMemcpy3D(&myparms)); + + // Compare layer +#ifdef DEBUG_DATA + for (unsigned int i = 0; i < width * height; i++) { + fprintf(stderr, "%4u: %u: %s -- %s\n", layer, i, getString(hData[layer * width * height + i]), + getString(hLayerData[i])); + } +#endif + REQUIRE(HipTest::checkArray(hData + layer * width * height, hLayerData, width, height, 1)); + } + free(hLayerData); + } + + hipTextureObject_t tex; + hipResourceDesc texRes; + memset(&texRes, 0, sizeof(hipResourceDesc)); + texRes.resType = hipResourceTypeArray; + texRes.res.array.array = arr; + + hipTextureDesc texDescr; + memset(&texDescr, 0, sizeof(hipTextureDesc)); + texDescr.normalizedCoords = 0; + texDescr.filterMode = hipFilterModePoint; + texDescr.addressMode[0] = hipAddressModeClamp; + texDescr.addressMode[1] = hipAddressModeClamp; + texDescr.addressMode[2] = hipAddressModeClamp; + texDescr.readMode = hipReadModeElementType; + HIP_CHECK(hipCreateTextureObject(&tex, &texRes, &texDescr, NULL)); // Allocate device memory for result - T* dData = nullptr; + TestType* dData = nullptr; HIP_CHECK(hipMalloc(&dData, size)); - REQUIRE(dData != nullptr); - dim3 dimBlock(8, 8, 1); - dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1); + dim3 dimBlock(32, 32); + dim3 dimGrid((width + dimBlock.x - 1) / dimBlock.x, (height + dimBlock.y -1)/ dimBlock.y); for (unsigned int layer = 0; layer < num_layers; layer++) { - hipLaunchKernelGGL(simpleKernelLayeredArray, dimGrid, dimBlock, 0, 0, - dData, width, height, layer); - HIP_CHECK(hipGetLastError()); + hipLaunchKernelGGL(simpleKernelLayered2DArray, dimGrid, dimBlock, 0, 0, tex, dData, + width, height, layer); + HIP_CHECK(hipGetLastError()); } HIP_CHECK(hipDeviceSynchronize()); // Allocate mem for the result on host side - T *hOutputData = reinterpret_cast(malloc(size)); + TestType *hOutputData = reinterpret_cast(malloc(size)); REQUIRE(hOutputData != nullptr); memset(hOutputData, 0, size); - // copy result from device to host + // Copy result from device to host HIP_CHECK(hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost)); - HipTest::checkArray(hData, hOutputData, width, height, num_layers); + REQUIRE(HipTest::checkArray(hData, hOutputData, width, height, num_layers) == true); HIP_CHECK(hipFree(dData)); HIP_CHECK(hipFreeArray(arr)); free(hData); free(hOutputData); + HIP_CHECK(hipDestroyTextureObject(tex)); } -#endif // CUDA_VERSION < CUDA_12000 +/** + * Test Description + * ------------------------ + * - The suite will test device buffer copied to/from layered 2D array in following steps, + allocating host buffer, + allocating device buffer, + copying host buffer to device buffer, + creating layered array, + copying device buffer to the layered array in two ways, + copying whole device buffer to the layered array, + copying device buffer layer by layer to the layered array and then + copying & verifying layer data, + creating a texture object on the layered array, + getting the data from the texture object in kernel, + verifing the data in host + * Test source + * ------------------------ + * - catch\unit\texture\hipSimpleTexture2DLayered.cc + * Test requirements + * ------------------------ + * - Host specific (WINDOWS and LINUX) + * - Layered 2D array supported on device + * - Textures supported on device + * - HIP_VERSION >= 6.0 + */ +TEMPLATE_TEST_CASE("Unit_Layered2DTexture_Check_DeviceBufferToFromLayered2DArray", "", + char, unsigned char, short, ushort, int, uint, float, + char1, uchar1, short1, ushort1, int1, uint1, float1, + char2, uchar2, short2, ushort2, int2, uint2, float2, + char4, uchar4, short4, ushort4, int4, uint4, float4) { + CHECK_IMAGE_SUPPORT + constexpr int SIZE = 512; + constexpr int num_layers = 5; + constexpr unsigned int width = SIZE; + constexpr unsigned int height = SIZE; + constexpr unsigned int size = width * height * num_layers * sizeof(TestType); + TestType* hData = reinterpret_cast(malloc(size)); + REQUIRE(hData != nullptr); + memset(hData, 0, size); + for (unsigned int layer = 0; layer < num_layers; layer++) { + for (unsigned int i = 0; i < width * height; i++) { + initVal(hData[layer * width * height + i]); + } + } + + TestType* dData = nullptr; + HIP_CHECK(hipMalloc(&dData, size)); + + HIP_CHECK(hipMemcpy(dData, hData, size, hipMemcpyHostToDevice)); + + hipChannelFormatDesc channelDesc; + // Allocate array and copy image data + channelDesc = hipCreateChannelDesc(); + hipArray_t arr; + HIP_CHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, num_layers), + hipArrayLayered)); + hipMemcpy3DParms myparms{}; + SECTION("hipMemcpy3D whole layers") { + myparms.srcPos = make_hipPos(0, 0, 0); + myparms.dstPos = make_hipPos(0, 0, 0); + myparms.srcPtr = make_hipPitchedPtr(dData, width * sizeof(TestType), width, height); + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, height, num_layers); + myparms.kind = hipMemcpyDeviceToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + } + + SECTION("hipMemcpy3D layer by layer") { + constexpr unsigned int layerSize = width * height * sizeof(TestType); + TestType* hLayerData = reinterpret_cast(malloc(layerSize)); + REQUIRE(hLayerData != nullptr); + TestType* dData1 = nullptr; + HIP_CHECK(hipMalloc(&dData1, size)); + HIP_CHECK(hipMemset(dData1, 0, size)); + for (unsigned int layer = 0; layer < num_layers; layer++) { + // Copy buffer layer to image layer + memset(hLayerData, 0, layerSize); + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, layer); + myparms.srcPtr = make_hipPitchedPtr(dData, width * sizeof(TestType), width, height); + myparms.kind = hipMemcpyDeviceToDevice; + myparms.dstArray = arr; + myparms.extent = make_hipExtent(width, height, 1); + HIP_CHECK(hipMemcpy3D(&myparms)); + + // Copy image layer to buffer layer + memset(&myparms, 0, sizeof(myparms)); + myparms.srcPos = make_hipPos(0, 0, layer); + myparms.dstPos = make_hipPos(0, 0, layer); + myparms.srcArray = arr; + myparms.dstPtr = make_hipPitchedPtr(dData1, width * sizeof(TestType), width, height); + myparms.extent = make_hipExtent(width, height, 1); + myparms.kind = hipMemcpyDeviceToDevice; + HIP_CHECK(hipMemcpy3D(&myparms)); + HIP_CHECK(hipMemcpy(hLayerData, dData1 + layer * width * height, layerSize, + hipMemcpyDeviceToHost)); + // Compare layer +#ifdef DEBUG_DATA + for (unsigned int i = 0; i < width * height; i++) { + fprintf(stderr, "%4u: %u: %s -- %s\n", layer, i, + getString(hData[layer * width * height + i]).c_str(), + getString(hLayerData[i]).c_str()); + } +#endif + REQUIRE(HipTest::checkArray(hData + layer * width * height, hLayerData, width, height, 1)); + } + free(hLayerData); + HIP_CHECK(hipFree(dData1)); + } + + hipTextureObject_t tex; + hipResourceDesc texRes; + memset(&texRes, 0, sizeof(hipResourceDesc)); + texRes.resType = hipResourceTypeArray; + texRes.res.array.array = arr; + + hipTextureDesc texDescr; + memset(&texDescr, 0, sizeof(hipTextureDesc)); + texDescr.normalizedCoords = 0; + texDescr.filterMode = hipFilterModePoint; + texDescr.addressMode[0] = hipAddressModeClamp; + texDescr.addressMode[1] = hipAddressModeClamp; + texDescr.addressMode[2] = hipAddressModeClamp; + texDescr.readMode = hipReadModeElementType; + HIP_CHECK(hipCreateTextureObject(&tex, &texRes, &texDescr, NULL)); + HIP_CHECK(hipMemset(dData, 0, size)); + + dim3 dimBlock(32, 32); + dim3 dimGrid((width + dimBlock.x - 1) / dimBlock.x, (height + dimBlock.y - 1) / dimBlock.y); + for (unsigned int layer = 0; layer < num_layers; layer++) { + hipLaunchKernelGGL(simpleKernelLayered2DArray, dimGrid, dimBlock, 0, 0, tex, dData, + width, height, layer); + HIP_CHECK(hipGetLastError()); + } + HIP_CHECK(hipDeviceSynchronize()); + + // Allocate mem for the result on host side + TestType* hOutputData = reinterpret_cast(malloc(size)); + REQUIRE(hOutputData != nullptr); + memset(hOutputData, 0, size); + + // Copy result from device to host + HIP_CHECK(hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost)); + REQUIRE(HipTest::checkArray(hData, hOutputData, width, height, num_layers) == true); + + HIP_CHECK(hipFree(dData)); + HIP_CHECK(hipFreeArray(arr)); + free(hData); + free(hOutputData); + HIP_CHECK(hipDestroyTextureObject(tex)); +}