Compare commits
258 commits
main
...
upstream/p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e74df8fd4 | ||
|
|
8d866579e9 | ||
|
|
1f70f04517 | ||
|
|
9409f2b94b | ||
|
|
743cdeb246 | ||
|
|
9de56b0a37 | ||
|
|
80589acfb1 | ||
|
|
1b27089209 | ||
|
|
2be2d4eb1d | ||
|
|
dd8d4ee975 | ||
|
|
dcfbded1d6 | ||
|
|
dee329fe05 | ||
|
|
0fd00e02ee | ||
|
|
b46d0af7a9 | ||
|
|
8ba80e7556 | ||
|
|
509469aa5b | ||
|
|
fe79541984 | ||
|
|
d21716af8f | ||
|
|
c2505b412d | ||
|
|
2163913274 | ||
|
|
3f87c48b53 | ||
|
|
e0d4c5c680 | ||
|
|
a0c14eb819 | ||
|
|
b7c9f6a656 | ||
|
|
fa4c14fcbe | ||
|
|
00a35fa4c4 | ||
|
|
f46cca0f8f | ||
|
|
2318cedb21 | ||
|
|
691a45d605 | ||
|
|
68fcb5904f | ||
|
|
2cc8e2e593 | ||
|
|
9eec8f3352 | ||
|
|
afdd8b0058 | ||
|
|
ea49084976 | ||
|
|
4759159a50 | ||
|
|
77e4fe5588 | ||
|
|
487dbd292e | ||
|
|
1eeb10296f | ||
|
|
896f43615d | ||
|
|
4278d544dc | ||
|
|
8066e69b11 | ||
|
|
59a1198e5f | ||
|
|
884c736525 | ||
|
|
fb949f9256 | ||
|
|
f48dd72da8 | ||
|
|
a25b9c4948 | ||
|
|
3cadff7115 | ||
|
|
58eb3d776d | ||
|
|
ed27a90775 | ||
|
|
73c6955068 | ||
|
|
1c2c4581bd | ||
|
|
ab338569aa | ||
|
|
0d24c6f69d | ||
|
|
6ecf824122 | ||
|
|
e9d2abf705 | ||
|
|
c6bb15c289 | ||
|
|
9137cb66ed | ||
|
|
def23dd6e6 | ||
|
|
640f6e66c7 | ||
|
|
18dbf2f1c1 | ||
|
|
fc4260bdae | ||
|
|
2110e45cce | ||
|
|
524fcab7f3 | ||
|
|
191fd0f9e5 | ||
|
|
77049a3a0f | ||
|
|
aad303074c | ||
|
|
133834615e | ||
|
|
f29ebf0d59 | ||
|
|
a61fa63054 | ||
|
|
9794aaef04 | ||
|
|
bb54c435dc | ||
|
|
8bb69ef665 | ||
|
|
fb1e8fcf9b | ||
|
|
63274f97b7 | ||
|
|
44fe72c2b9 | ||
|
|
babed4c175 | ||
|
|
90a5183ec4 | ||
|
|
5e116e7b0d | ||
|
|
f6a963a583 | ||
|
|
4b39b59469 | ||
|
|
35cab9c85b | ||
|
|
9e0ce2ba80 | ||
|
|
f6e37b17d2 | ||
|
|
d285ebe5be | ||
|
|
d9a938b698 | ||
|
|
07b055cd68 | ||
|
|
6659a1b6b8 | ||
|
|
dbd33bc9cf | ||
|
|
30cc3db4ec | ||
|
|
18825769e5 | ||
|
|
28e76e532a | ||
|
|
a3294d4c95 | ||
|
|
73f51ccff7 | ||
|
|
c69f6eec47 | ||
|
|
9bf6486352 | ||
|
|
9b21e9f06b | ||
|
|
30500fba06 | ||
|
|
c014122742 | ||
|
|
2012c6cadd | ||
|
|
180adef84c | ||
|
|
92285f7c9d | ||
|
|
86d5ee5414 | ||
|
|
75edf2a881 | ||
|
|
76bd9d3674 | ||
|
|
8f9c1960ff | ||
|
|
a87e686757 | ||
|
|
7859a33182 | ||
|
|
c0a10f4e12 | ||
|
|
426097cf7c | ||
|
|
d42b3dcfb6 | ||
|
|
5d5bffba13 | ||
|
|
1d74c85ff3 | ||
|
|
d928ac059c | ||
|
|
00f21739e5 | ||
|
|
89c8d87963 | ||
|
|
6554c49018 | ||
|
|
fec9d9a238 | ||
|
|
388944c01c | ||
|
|
7caa4c4421 | ||
|
|
9ad4899862 | ||
|
|
2dc2533130 | ||
|
|
f94c135755 | ||
|
|
8f5a2f0ae8 | ||
|
|
f4eb852b6d | ||
|
|
afe4ef8b8f | ||
|
|
c82dabd4bb | ||
|
|
9666ca3c70 | ||
|
|
e52a97e4e9 | ||
|
|
d647529fec | ||
|
|
38639f229d | ||
|
|
4ee8022230 | ||
|
|
c12bff46c6 | ||
|
|
c44b5b6ae3 | ||
|
|
cdf5a105fc | ||
|
|
bd03e17a56 | ||
|
|
017f514c21 | ||
|
|
b06ccc6cd9 | ||
|
|
0a5a8f90c9 | ||
|
|
2cf24e63b7 | ||
|
|
a37884fe44 | ||
|
|
8d9d1f3e9d | ||
|
|
e3e1786761 | ||
|
|
1c19a4cbdb | ||
|
|
0b7118186a | ||
|
|
67ac6c8d2d | ||
|
|
f1c051afb1 | ||
|
|
c2aca7d8e6 | ||
|
|
7c65afc4e7 | ||
|
|
3bf46004ef | ||
|
|
f32f1aeaa2 | ||
|
|
d54954c7cf | ||
|
|
6e6249fb48 | ||
|
|
5149de2277 | ||
|
|
3662d17447 | ||
|
|
5d6ca3e9d1 | ||
|
|
35c21a8e06 | ||
|
|
13d1b01f65 | ||
|
|
03da14d6a9 | ||
|
|
d533472c27 | ||
|
|
7a0e7e767a | ||
|
|
2fcdde96d2 | ||
|
|
e121b9d1bf | ||
|
|
93f4f6a548 | ||
|
|
c42cf518da | ||
|
|
f6dbc5b9b5 | ||
|
|
0f4dc3166c | ||
|
|
bbc7ccfc58 | ||
|
|
3c4a1a3ce6 | ||
|
|
ae217e8bd2 | ||
|
|
e437acd908 | ||
|
|
d36196b662 | ||
|
|
279803abab | ||
|
|
2d93b122c3 | ||
|
|
6b14d408dc | ||
|
|
60471a5208 | ||
|
|
656886030b | ||
|
|
06415f8b79 | ||
|
|
51c6d97d2f | ||
|
|
f91daf3d06 | ||
|
|
b71c204794 | ||
|
|
c2facedfa0 | ||
|
|
1161d788dd | ||
|
|
73d71b6a76 | ||
|
|
8ffecf27c2 | ||
|
|
e106be14f9 | ||
|
|
f8ec235d3c | ||
|
|
7625011b66 | ||
|
|
6f50623ba8 | ||
|
|
6dff4fdffa | ||
|
|
3eb0f50d85 | ||
|
|
c25709f396 | ||
|
|
3cd906aa9b | ||
|
|
1c6dbc23e7 | ||
|
|
1116a71ba2 | ||
|
|
e9cd9a446e | ||
|
|
410f46f49f | ||
|
|
7147d072c7 | ||
|
|
92844bead1 | ||
|
|
903f1bf65d | ||
|
|
2b770c4f34 | ||
|
|
4fb5deeec1 | ||
|
|
ddca0f802b | ||
|
|
02bf24d2b1 | ||
|
|
1f26e1d8ba | ||
|
|
34e47322db | ||
|
|
0601c6f765 | ||
|
|
995c7dbfbb | ||
|
|
e27a97fbd8 | ||
|
|
7cfd3a6033 | ||
|
|
39fdb462be | ||
|
|
070f8c0c0e | ||
|
|
6c3c7e5266 | ||
|
|
43e1397468 | ||
|
|
6da9c6b68f | ||
|
|
1aa930957a | ||
|
|
4759e5cae0 | ||
|
|
cc0b46e457 | ||
|
|
79f692d8e5 | ||
|
|
12637114ac | ||
|
|
b500da5fbc | ||
|
|
433974fd28 | ||
|
|
4a03bb79cb | ||
|
|
236cd73fa1 | ||
|
|
69f0054001 | ||
|
|
80a4a833be | ||
|
|
277d029608 | ||
|
|
76ace61314 | ||
|
|
315998511a | ||
|
|
bd3135dd01 | ||
|
|
0876ea10be | ||
|
|
ed839ebf10 | ||
|
|
a08cacc673 | ||
|
|
ba9312e4a2 | ||
|
|
ce1687a408 | ||
|
|
01aa55029d | ||
|
|
de49d59c8d | ||
|
|
6c8045911a | ||
|
|
17a0d09567 | ||
|
|
6572837994 | ||
|
|
e7c5694cf5 | ||
|
|
02c2a424f7 | ||
|
|
db939bbb20 | ||
|
|
71e2681414 | ||
|
|
a43d96de69 | ||
|
|
ad8ab3fe90 | ||
|
|
d7f87492bd | ||
|
|
06f7661fdc | ||
|
|
59a12047a8 | ||
|
|
3dd6d4137d | ||
|
|
3dab3df48d | ||
|
|
5daca107ad | ||
|
|
01497c402e | ||
|
|
cba7a8a537 | ||
|
|
edc36b5d53 | ||
|
|
b8d1ea9962 | ||
|
|
7542ae2443 | ||
|
|
6683fa91a9 | ||
|
|
7286e06a94 |
571 changed files with 51512 additions and 69831 deletions
|
|
@ -1,54 +0,0 @@
|
|||
os:
|
||||
- Visual Studio 2017
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
platform:
|
||||
- Win32
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- SETARCH: i686
|
||||
- SETARCH: x86_64
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- platform: Win32
|
||||
SETARCH: x86_64
|
||||
- platform: x64
|
||||
SETARCH: i686
|
||||
|
||||
before_build:
|
||||
# Setup environment:
|
||||
- ps: $env:TOP = $env:APPVEYOR_BUILD_FOLDER
|
||||
- ps: $env:TOP
|
||||
- echo %TOP%
|
||||
# Get the OpenCL Headers:
|
||||
- git clone --depth=1 https://github.com/KhronosGroup/OpenCL-Headers OpenCL-Headers
|
||||
# Get and build the OpenCL ICD Loader:
|
||||
- git clone --depth=1 https://github.com/KhronosGroup/OpenCL-ICD-Loader.git
|
||||
- ps: cd OpenCL-ICD-Loader
|
||||
- ps: mkdir build
|
||||
- ps: cd build
|
||||
- cmake -A%PLATFORM% -DENABLE_OPENCL30_PROVISIONAL=1 -DOPENCL_ICD_LOADER_HEADERS_DIR=%TOP%/OpenCL-Headers/ ..
|
||||
- cmake --build . --config %CONFIGURATION%
|
||||
- ps: cd $env:TOP
|
||||
# Get the libclcxx standard library:
|
||||
- git clone --depth=1 https://github.com/KhronosGroup/libclcxx.git libclcxx
|
||||
# Generate the CTS solution file:
|
||||
- cmake -DCL_INCLUDE_DIR=%TOP%/OpenCL-Headers
|
||||
-DCL_LIB_DIR=%TOP%/OpenCL-ICD-Loader/build
|
||||
-DCL_LIBCLCXX_DIR=%TOP%/libclcxx
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=./bin
|
||||
-DOPENCL_LIBRARIES="OpenCL"
|
||||
-H. -Bbuild_win -A%PLATFORM%
|
||||
-DD3D10_IS_SUPPORTED=ON -DD3D11_IS_SUPPORTED=ON -DARCH=%SETARCH%
|
||||
|
||||
build:
|
||||
project: build_win\CLConform.sln
|
||||
parallel: true
|
||||
verbosity: normal
|
||||
35
.github/workflows/presubmit.yml
vendored
35
.github/workflows/presubmit.yml
vendored
|
|
@ -3,37 +3,62 @@ on: [push, pull_request]
|
|||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.os }} ${{ matrix.name }}
|
||||
name: Build ${{ matrix.os }} ${{ matrix.arch }}${{ matrix.extra }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
JOB_ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_ENABLE_GL: ${{ matrix.gl }}
|
||||
JOB_ENABLE_DEBUG: ${{ matrix.debug }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mainmatrix: [true]
|
||||
os: [ubuntu-20.04, macos-11.0]
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
mainmatrix: true
|
||||
gl: 1
|
||||
extra: " gl"
|
||||
- os: ubuntu-20.04
|
||||
mainmatrix: false
|
||||
name: Arm
|
||||
arch: arm
|
||||
- os: ubuntu-20.04
|
||||
mainmatrix: false
|
||||
name: AArch64
|
||||
arch: aarch64
|
||||
debug: 1
|
||||
extra: " debug"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- name: Setup OpenGL build dependencies
|
||||
if: ${{ matrix.gl }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install libglu1-mesa-dev freeglut3-dev mesa-common-dev libglew-dev
|
||||
- name: Setup MSVC with Ninja
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ matrix.os }}-${{ matrix.arch }}
|
||||
- name: Fetch OpenCL Headers
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/KhronosGroup/OpenCL-Headers.git
|
||||
cd OpenCL-Headers
|
||||
ln -s CL OpenCL # For OSX builds
|
||||
cd ..
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: ./presubmit.sh
|
||||
formatcheck:
|
||||
name: Check code format
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: sudo apt install -y clang-format
|
||||
run: sudo apt install -y clang-format clang-format-9
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
|
|
|||
131
CMakeLists.txt
131
CMakeLists.txt
|
|
@ -10,12 +10,6 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
|||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
set (BUILD_FLAVOR "release")
|
||||
else(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
set (BUILD_FLAVOR "debug")
|
||||
endif(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
|
||||
add_definitions(-DCL_TARGET_OPENCL_VERSION=300)
|
||||
add_definitions(-DCL_USE_DEPRECATED_OPENCL_2_2_APIS=1)
|
||||
add_definitions(-DCL_USE_DEPRECATED_OPENCL_2_1_APIS=1)
|
||||
|
|
@ -29,14 +23,6 @@ if(USE_CL_EXPERIMENTAL)
|
|||
add_definitions(-DCL_EXPERIMENTAL)
|
||||
endif(USE_CL_EXPERIMENTAL)
|
||||
|
||||
# Support both VS2008 and VS2012.
|
||||
set(BUILD_DIR "$ENV{ADRENO_DRIVER}/build")
|
||||
if(MSVC90)
|
||||
set(VS_BUILD_DIR "${BUILD_DIR}/vs2008")
|
||||
else(MSVC110)
|
||||
set(VS_BUILD_DIR "${BUILD_DIR}/vs2012")
|
||||
endif(MSVC90)
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# Default Configurable Test Set
|
||||
#-----------------------------------------------------------
|
||||
|
|
@ -44,6 +30,7 @@ option(D3D10_IS_SUPPORTED "Run DirectX 10 interop tests" OFF)
|
|||
option(D3D11_IS_SUPPORTED "Run DirectX 11 interop tests" OFF)
|
||||
option(GL_IS_SUPPORTED "Run OpenGL interop tests" OFF)
|
||||
option(GLES_IS_SUPPORTED "Run OpenGL ES interop tests" OFF)
|
||||
option(VULKAN_IS_SUPPORTED "Run Vulkan interop tests" OFF)
|
||||
|
||||
|
||||
#-----------------------------------------------------------
|
||||
|
|
@ -62,58 +49,13 @@ set(CONFORMANCE_SUFFIX "" )
|
|||
#build driver as a dependency of the conformance tests, or other such CMake customization
|
||||
include(CMakeVendor.txt OPTIONAL)
|
||||
|
||||
#-----------------------------------------------------------
|
||||
# Development options for OpenCL C++ tests
|
||||
#-----------------------------------------------------------
|
||||
# Use OpenCL C kernels instead of OpenCL C++ kernels
|
||||
option(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS "Use OpenCL C kernels in OpenCL C++ tests" OFF)
|
||||
if(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS)
|
||||
set(CLPP_DEVELOPMENT_OPTIONS ${CLPP_DEVELOPMENT_OPTIONS} -DCLPP_DEVELOPMENT_USE_OPENCLC_KERNELS)
|
||||
endif(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS)
|
||||
# Only check if OpenCL C++ kernels compile to SPIR-V
|
||||
option(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION "Only check if OpenCL C++ kernels compile to SPIR-V" OFF)
|
||||
if(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION)
|
||||
if(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS)
|
||||
message(FATAL_ERROR "Can't use OpenCL C kernels and compile to SPIR-V.")
|
||||
endif(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS)
|
||||
set(CLPP_DEVELOPMENT_OPTIONS ${CLPP_DEVELOPMENT_OPTIONS} -DCLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION)
|
||||
endif(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION)
|
||||
#
|
||||
if(CLPP_DEVELOPMENT_OPTIONS)
|
||||
add_definitions(-DCLPP_DEVELOPMENT_OPTIONS)
|
||||
add_definitions(${CLPP_DEVELOPMENT_OPTIONS})
|
||||
endif(CLPP_DEVELOPMENT_OPTIONS)
|
||||
|
||||
# Offline OpenCL C/C++ compiler provided by Khronos is the only supported
|
||||
# offline compiler.
|
||||
#
|
||||
# Path to offline OpenCL C/C++ compiler provided by Khronos.
|
||||
# See https://github.com/KhronosGroup/SPIR/ (spirv-1.1 branch or newer SPIR-V-ready
|
||||
# branch should be used).
|
||||
if(KHRONOS_OFFLINE_COMPILER)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DKHRONOS_OFFLINE_COMPILER=${KHRONOS_OFFLINE_COMPILER}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKHRONOS_OFFLINE_COMPILER=${KHRONOS_OFFLINE_COMPILER}")
|
||||
# Additional OpenCL C/C++ compiler option.
|
||||
if(KHRONOS_OFFLINE_COMPILER_OPTIONS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DKHRONOS_OFFLINE_COMPILER_OPTIONS=${KHRONOS_OFFLINE_COMPILER_OPTIONS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKHRONOS_OFFLINE_COMPILER_OPTIONS=${KHRONOS_OFFLINE_COMPILER_OPTIONS}")
|
||||
endif(KHRONOS_OFFLINE_COMPILER_OPTIONS)
|
||||
else(KHRONOS_OFFLINE_COMPILER)
|
||||
message(WARNING "KHRONOS_OFFLINE_COMPILER is not defined!")
|
||||
message(WARNING "Running CL C++ tests will not be possible.")
|
||||
endif(KHRONOS_OFFLINE_COMPILER)
|
||||
|
||||
# CL_LIBCLCXX_DIR - path to dir with OpenCL C++ STL (libclcxx)
|
||||
# CL_INCLUDE_DIR - path to dir with OpenCL headers
|
||||
# CL_LIBCLCXX_DIR - path to dir with OpenCL library
|
||||
if(CL_INCLUDE_DIR AND CL_LIB_DIR AND CL_LIBCLCXX_DIR)
|
||||
if(CL_INCLUDE_DIR AND CL_LIB_DIR)
|
||||
link_directories(${CL_LIB_DIR})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCL_LIBCLCXX_DIR=${CL_LIBCLCXX_DIR}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCL_LIBCLCXX_DIR=${CL_LIBCLCXX_DIR}")
|
||||
else(CL_INCLUDE_DIR AND CL_LIB_DIR AND CL_LIBCLCXX_DIR)
|
||||
else(CL_INCLUDE_DIR AND CL_LIB_DIR)
|
||||
message(STATUS "OpenCL hasn't been found!")
|
||||
message(FATAL_ERROR "Either install OpenCL or pass -DCL_INCLUDE_DIR, -DCL_LIB_DIR and -DCL_LIBCLCXX_DIR")
|
||||
endif(CL_INCLUDE_DIR AND CL_LIB_DIR AND CL_LIBCLCXX_DIR)
|
||||
message(FATAL_ERROR "Either install OpenCL or pass -DCL_INCLUDE_DIR and -DCL_LIB_DIR")
|
||||
endif(CL_INCLUDE_DIR AND CL_LIB_DIR)
|
||||
|
||||
# CLConform_GL_LIBRARIES_DIR - path to OpenGL libraries
|
||||
if(GL_IS_SUPPORTED AND CLConform_GL_LIBRARIES_DIR)
|
||||
|
|
@ -147,14 +89,15 @@ macro(add_cxx_flag_if_supported flag)
|
|||
endmacro(add_cxx_flag_if_supported)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?Clang")
|
||||
add_cxx_flag_if_supported(-Wmisleading-indentation)
|
||||
add_cxx_flag_if_supported(-Wunused-function)
|
||||
add_cxx_flag_if_supported(-Wunused-variable)
|
||||
add_cxx_flag_if_supported(-Wno-narrowing)
|
||||
add_cxx_flag_if_supported(-Wno-format)
|
||||
add_cxx_flag_if_supported(-Werror)
|
||||
add_cxx_flag_if_supported(-Wno-error=cpp) # Allow #warning directive
|
||||
add_cxx_flag_if_supported(-Wno-error=absolute-value) # Issue 783
|
||||
add_cxx_flag_if_supported(-Wno-error=unknown-pragmas) # Issue #785
|
||||
add_cxx_flag_if_supported(-Wno-error=asm-operand-widths) # Issue #784
|
||||
add_cxx_flag_if_supported(-Wno-error=overflow) # Fixed by #699
|
||||
|
||||
# -msse -mfpmath=sse to force gcc to use sse for float math,
|
||||
# avoiding excess precision problems that cause tests like int2float
|
||||
|
|
@ -172,9 +115,30 @@ else()
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D__SSE__")
|
||||
endif()
|
||||
|
||||
# Set a module's COMPILE_FLAGS if using gcc or clang.
|
||||
macro(set_gnulike_module_compile_flags flags)
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?Clang")
|
||||
SET_SOURCE_FILES_PROPERTIES(
|
||||
${${MODULE_NAME}_SOURCES}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS ${flags}
|
||||
)
|
||||
endif()
|
||||
endmacro(set_gnulike_module_compile_flags)
|
||||
|
||||
# Xcode 14.1 deprecated functions such as sprintf.
|
||||
# Suppress such warnings for now, see Issue #1626
|
||||
if(APPLE)
|
||||
add_cxx_flag_if_supported(-Wno-deprecated-declarations)
|
||||
endif(APPLE)
|
||||
|
||||
if(MSVC)
|
||||
# Don't warn when using standard non-secure functions.
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
# Don't warn about using the portable "strdup" function.
|
||||
add_compile_definitions(_CRT_NONSTDC_NO_DEPRECATE)
|
||||
# Fix std::min and std::max handling with windows.harness.
|
||||
add_compile_definitions(NOMINMAX)
|
||||
endif()
|
||||
|
||||
if( WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" )
|
||||
|
|
@ -197,10 +161,6 @@ if(LINK_PTHREAD)
|
|||
list(APPEND CLConform_LIBRARIES pthread)
|
||||
endif()
|
||||
|
||||
if(DEFINED USE_GLES3)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLES3")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
find_library(corefoundation CoreFoundation)
|
||||
find_library(iokit IOKit)
|
||||
|
|
@ -214,38 +174,5 @@ include_directories(${CLConform_SOURCE_DIR}/test_common/harness
|
|||
${CLConform_SOURCE_DIR}/test_common/gl
|
||||
${CLConform_SOURCE_DIR}/test_common)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
set (BUILD_FLAVOR "release")
|
||||
elseif (CMAKE_BUILD_TYPE STREQUAL "debug")
|
||||
set (BUILD_FLAVOR "debug")
|
||||
endif(CMAKE_BUILD_TYPE STREQUAL "release")
|
||||
|
||||
|
||||
add_subdirectory(test_common)
|
||||
add_subdirectory(test_conformance)
|
||||
|
||||
# Support both VS2008 and VS2012.
|
||||
set (DLL_FILES "${VS_BUILD_DIR}/Debug/*.dll")
|
||||
set (DST_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/")
|
||||
|
||||
if (WIN32)
|
||||
set (COPY "echo")
|
||||
add_custom_target(COPY_DLL${CONFORMANCE_SUFFIX} ALL
|
||||
COMMAND ${COPY} "${DLL_FILES}" "${DST_DIR}"
|
||||
COMMENT "Copying dll files.. ")
|
||||
else (WIN32)
|
||||
set (COPY cp)
|
||||
add_custom_target(COPY_DLL${CONFORMANCE_SUFFIX})
|
||||
endif(WIN32)
|
||||
|
||||
set_property(TARGET COPY_DLL${CONFORMANCE_SUFFIX} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}")
|
||||
|
||||
if(WIN32)
|
||||
add_custom_target( COPY_FILES${CONFORMANCE_SUFFIX} ALL
|
||||
COMMAND ${COPY} ${DLL_FILES} ${DST_DIR}
|
||||
COMMENT "Copying other files to output folder..." )
|
||||
else(WIN32)
|
||||
add_custom_target( COPY_FILES${CONFORMANCE_SUFFIX} )
|
||||
endif(WIN32)
|
||||
|
||||
set_property(TARGET COPY_FILES${CONFORMANCE_SUFFIX} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}")
|
||||
|
|
|
|||
117
README.md
117
README.md
|
|
@ -1,2 +1,115 @@
|
|||
# OpenCL-CTS [](https://travis-ci.org/KhronosGroup/OpenCL-CTS/branches)
|
||||
The OpenCL Conformance Tests
|
||||
# OpenCL Conformance Test Suite (CTS)
|
||||
|
||||
This it the OpenCL CTS for all versions of the Khronos
|
||||
[OpenCL](https://www.khronos.org/opencl/) standard.
|
||||
|
||||
## Building the CTS
|
||||
|
||||
The CTS supports Linux, Windows, macOS, and Android platforms. In particular,
|
||||
GitHub Actions CI builds against Ubuntu 20.04, Windows-latest, and
|
||||
macos-latest.
|
||||
|
||||
Compiling the CTS requires the following CMake configuration options to be set:
|
||||
|
||||
* `CL_INCLUDE_DIR` Points to the unified
|
||||
[OpenCL-Headers](https://github.com/KhronosGroup/OpenCL-Headers).
|
||||
* `CL_LIB_DIR` Directory containing the OpenCL library to build against.
|
||||
* `OPENCL_LIBRARIES` Name of the OpenCL library to link.
|
||||
|
||||
It is advised that the [OpenCL ICD-Loader](https://github.com/KhronosGroup/OpenCL-ICD-Loader)
|
||||
is used as the OpenCL library to build against. Where `CL_LIB_DIR` points to a
|
||||
build of the ICD loader and `OPENCL_LIBRARIES` is "OpenCL".
|
||||
|
||||
### Example Build
|
||||
|
||||
Steps on a Linux platform to clone dependencies from GitHub sources, configure
|
||||
a build, and compile.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/KhronosGroup/OpenCL-CTS.git
|
||||
git clone https://github.com/KhronosGroup/OpenCL-Headers.git
|
||||
git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader.git
|
||||
|
||||
mkdir OpenCL-ICD-Loader/build
|
||||
cmake -S OpenCL-ICD-Loader -B OpenCL-ICD-Loader/build \
|
||||
-DOPENCL_ICD_LOADER_HEADERS_DIR=$PWD/OpenCL-Headers
|
||||
cmake --build ./OpenCL-ICD-Loader/build --config Release
|
||||
|
||||
mkdir OpenCL-CTS/build
|
||||
cmake -S OpenCL-CTS -B OpenCL-CTS/build \
|
||||
-DCL_INCLUDE_DIR=$PWD/OpenCL-Headers \
|
||||
-DCL_LIB_DIR=$PWD/OpenCL-ICD-Loader/build \
|
||||
-DOPENCL_LIBRARIES=OpenCL
|
||||
cmake --build OpenCL-CTS/build --config Release
|
||||
```
|
||||
|
||||
## Running the CTS
|
||||
|
||||
A build of the CTS contains multiple executables representing the directories in
|
||||
the `test_conformance` folder. Each of these executables contains sub-tests, and
|
||||
possibly smaller granularities of testing within the sub-tests.
|
||||
|
||||
See the `--help` output on each executable for the list of sub-tests available,
|
||||
as well as other options for configuring execution.
|
||||
|
||||
If the OpenCL library built against is the ICD Loader, and the vendor library to
|
||||
be tested is not registered in the
|
||||
[default ICD Loader location](https://github.com/KhronosGroup/OpenCL-ICD-Loader#registering-icds)
|
||||
then the [OCL_ICD_FILENAMES](https://github.com/KhronosGroup/OpenCL-ICD-Loader#table-of-debug-environment-variables)
|
||||
environment variable will need to be set for the ICD Loader to detect the OpenCL
|
||||
library to use at runtime. For example, to run the basic tests on a Linux
|
||||
platform:
|
||||
|
||||
```sh
|
||||
OCL_ICD_FILENAMES=/path/to/vendor_lib.so ./test_basic
|
||||
```
|
||||
|
||||
### Offline Compilation
|
||||
|
||||
Testing OpenCL drivers which do not have a runtime compiler can be done by using
|
||||
additional command line arguments provided by the test harness for tests which
|
||||
require compilation, these are:
|
||||
|
||||
* `--compilation-mode` Selects if OpenCL-C source code should be compiled using
|
||||
an external tool before being passed on to the OpenCL driver in that form for
|
||||
testing. Online is the default mode, but also accepts the values `spir-v`, and
|
||||
`binary`.
|
||||
|
||||
* `--compilation-cache-mode` Controls how the compiled OpenCL-C source code
|
||||
should be cached on disk.
|
||||
|
||||
* `--compilation-cache-path` Accepts a path to a directory where the compiled
|
||||
binary cache should be stored on disk.
|
||||
|
||||
* `--compilation-program` Accepts a path to an executable (default:
|
||||
cl_offline_compiler) invoked by the test harness to perform offline
|
||||
compilation of OpenCL-C source code. This executable must match the
|
||||
[interface description](test_common/harness/cl_offline_compiler-interface.txt).
|
||||
|
||||
## Generating a Conformance Report
|
||||
|
||||
The Khronos [Conformance Process Document](https://members.khronos.org/document/dl/911)
|
||||
details the steps required for a conformance submissions.
|
||||
In this repository [opencl_conformance_tests_full.csv](test_conformance/submission_details_template.txt)
|
||||
defines the full list of tests which must be run for conformance. The output log
|
||||
of which must be included alongside a filled in
|
||||
[submission details template](test_conformance/submission_details_template.txt).
|
||||
|
||||
Utility script [run_conformance.py](test_conformance/run_conformance.py) can be
|
||||
used to help generating the submission log, although it is not required.
|
||||
|
||||
Git [tags](https://github.com/KhronosGroup/OpenCL-CTS/tags) are used to define
|
||||
the version of the repository conformance submissions are made against.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome to the project from Khronos members and non-members
|
||||
alike via GitHub Pull Requests (PR). Alternatively, if you've found a bug or have
|
||||
a questions please file an issue in the GitHub project. First time contributors
|
||||
will be required to sign the Khronos Contributor License Agreement (CLA) before
|
||||
their PR can be merged.
|
||||
|
||||
PRs to the repository are required to be `clang-format` clean to pass CI.
|
||||
Developers can either use the `git-clang-format` tool locally to verify this
|
||||
before contributing, or update their PR based on the diff provided by a failing
|
||||
CI job.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Arg used to specify non-'origin/master' comparison branch
|
||||
ORIGIN_BRANCH=${1:-"origin/master"}
|
||||
# Arg used to specify non-'origin/main' comparison branch
|
||||
ORIGIN_BRANCH=${1:-"origin/main"}
|
||||
CLANG_BINARY=${2:-"`which clang-format-9`"}
|
||||
|
||||
# Run git-clang-format to check for violations
|
||||
|
|
|
|||
69
presubmit.sh
69
presubmit.sh
|
|
@ -13,9 +13,13 @@ TOOLCHAIN_PREFIX_aarch64=aarch64-linux-gnu
|
|||
TOOLCHAIN_FILE=${TOP}/toolchain.cmake
|
||||
touch ${TOOLCHAIN_FILE}
|
||||
BUILD_OPENGL_TEST="OFF"
|
||||
BUILD_VULKAN_TEST="ON"
|
||||
|
||||
cmake --version
|
||||
echo
|
||||
|
||||
# Prepare toolchain if needed
|
||||
if [[ ${JOB_ARCHITECTURE} != "" ]]; then
|
||||
if [[ ${JOB_ARCHITECTURE} != "" && ${RUNNER_OS} != "Windows" ]]; then
|
||||
TOOLCHAIN_URL_VAR=TOOLCHAIN_URL_${JOB_ARCHITECTURE}
|
||||
TOOLCHAIN_URL=${!TOOLCHAIN_URL_VAR}
|
||||
wget ${TOOLCHAIN_URL}
|
||||
|
|
@ -38,39 +42,68 @@ fi
|
|||
|
||||
if [[ ( ${JOB_ARCHITECTURE} == "" && ${JOB_ENABLE_GL} == "1" ) ]]; then
|
||||
BUILD_OPENGL_TEST="ON"
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install libglu1-mesa-dev freeglut3-dev mesa-common-dev libglew-dev
|
||||
fi
|
||||
# Prepare headers
|
||||
git clone https://github.com/KhronosGroup/OpenCL-Headers.git
|
||||
cd OpenCL-Headers
|
||||
ln -s CL OpenCL # For OSX builds
|
||||
cd ..
|
||||
|
||||
if [[ ${JOB_ENABLE_DEBUG} == 1 ]]; then
|
||||
BUILD_CONFIG="Debug"
|
||||
else
|
||||
BUILD_CONFIG="Release"
|
||||
fi
|
||||
|
||||
#Vulkan Headers
|
||||
git clone https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||
|
||||
# Get and build loader
|
||||
git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader.git
|
||||
cd ${TOP}/OpenCL-ICD-Loader
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DOPENCL_ICD_LOADER_HEADERS_DIR=${TOP}/OpenCL-Headers/ ..
|
||||
make
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \
|
||||
-DOPENCL_ICD_LOADER_HEADERS_DIR=${TOP}/OpenCL-Headers/
|
||||
cmake --build . -j2
|
||||
|
||||
# Get libclcxx
|
||||
#Vulkan Loader
|
||||
cd ${TOP}
|
||||
git clone https://github.com/KhronosGroup/libclcxx.git
|
||||
git clone https://github.com/KhronosGroup/Vulkan-Loader.git
|
||||
cd Vulkan-Loader
|
||||
mkdir build
|
||||
cd build
|
||||
python3 ../scripts/update_deps.py
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \
|
||||
-DBUILD_WSI_XLIB_SUPPORT=OFF \
|
||||
-DBUILD_WSI_XCB_SUPPORT=OFF \
|
||||
-DBUILD_WSI_WAYLAND_SUPPORT=OFF \
|
||||
-DUSE_GAS=OFF \
|
||||
-C helper.cmake ..
|
||||
cmake --build . -j2
|
||||
|
||||
# Build CTS
|
||||
cd ${TOP}
|
||||
ls -l
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCL_INCLUDE_DIR=${TOP}/OpenCL-Headers \
|
||||
if [[ ${RUNNER_OS} == "Windows" ]]; then
|
||||
CMAKE_OPENCL_LIBRARIES_OPTION="OpenCL"
|
||||
CMAKE_CACHE_OPTIONS=""
|
||||
else
|
||||
CMAKE_OPENCL_LIBRARIES_OPTION="-lOpenCL -lpthread"
|
||||
CMAKE_CACHE_OPTIONS="-DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache"
|
||||
fi
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_CONFIG}" \
|
||||
${CMAKE_CACHE_OPTIONS} \
|
||||
-DCL_INCLUDE_DIR=${TOP}/OpenCL-Headers \
|
||||
-DCL_LIB_DIR=${TOP}/OpenCL-ICD-Loader/build \
|
||||
-DCL_LIBCLCXX_DIR=${TOP}/libclcxx \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=./bin \
|
||||
-DOPENCL_LIBRARIES="-lOpenCL -lpthread" \
|
||||
-DOPENCL_LIBRARIES="${CMAKE_OPENCL_LIBRARIES_OPTION}" \
|
||||
-DUSE_CL_EXPERIMENTAL=ON \
|
||||
-DGL_IS_SUPPORTED=${BUILD_OPENGL_TEST} \
|
||||
..
|
||||
make -j2
|
||||
|
||||
-DVULKAN_IS_SUPPORTED=${BUILD_VULKAN_TEST} \
|
||||
-DVULKAN_INCLUDE_DIR=${TOP}/Vulkan-Headers/include/ \
|
||||
-DVULKAN_LIB_DIR=${TOP}/Vulkan-Loader/build/loader/
|
||||
cmake --build . -j3
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
set(HARNESS_SOURCES
|
||||
harness/threadTesting.cpp
|
||||
harness/typeWrappers.cpp
|
||||
harness/mt19937.cpp
|
||||
harness/conversions.cpp
|
||||
|
|
@ -22,4 +21,3 @@ set(HARNESS_SOURCES
|
|||
)
|
||||
|
||||
add_library(harness STATIC ${HARNESS_SOURCES})
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,11 @@ namespace detail {
|
|||
|
||||
struct test_case_registration
|
||||
{
|
||||
test_case_registration(const std::string& name, const basefn ptr)
|
||||
test_case_registration(const std::string& name,
|
||||
const test_function_pointer ptr)
|
||||
{
|
||||
::autotest::test_suite::global_test_suite().add(test_definition({ptr, strdup(name.c_str())}));
|
||||
::autotest::test_suite::global_test_suite().add(
|
||||
test_definition({ ptr, strdup(name.c_str()) }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1381,7 +1381,6 @@ void * CreateGLTexture2DArrayMultisample(size_t width, size_t height,
|
|||
|
||||
//calculating colors
|
||||
double color_delta = 1.0 / (total_layers * samples);
|
||||
double color = color_delta;
|
||||
|
||||
if (attachment != GL_DEPTH_ATTACHMENT && attachment != GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#include "harness/errorHelpers.h"
|
||||
#include "harness/kernelHelpers.h"
|
||||
#include "harness/threadTesting.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
#include "harness/conversions.h"
|
||||
#include "harness/mt19937.h"
|
||||
|
|
|
|||
|
|
@ -13,14 +13,11 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include "setup.h"
|
||||
#include "testBase.h"
|
||||
#include "harness/errorHelpers.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)(
|
||||
|
|
|
|||
|
|
@ -13,16 +13,11 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include "setup.h"
|
||||
#include "testBase.h"
|
||||
#include "harness/errorHelpers.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/freeglut.h>
|
||||
#include <GL/glx.h>
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
|
|
@ -90,10 +85,17 @@ public:
|
|||
}
|
||||
|
||||
for (int i=0; i<(int)num_of_devices; i++) {
|
||||
if (!is_extension_available(devices[i], "cl_khr_gl_sharing ")) {
|
||||
log_info("Device %d of %d does not support required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
|
||||
} else {
|
||||
log_info("Device %d of %d supports required extension cl_khr_gl_sharing.\n", i+1, num_of_devices);
|
||||
if (!is_extension_available(devices[i], "cl_khr_gl_sharing"))
|
||||
{
|
||||
log_info("Device %d of %d does not support required extension "
|
||||
"cl_khr_gl_sharing.\n",
|
||||
i + 1, num_of_devices);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("Device %d of %d supports required extension "
|
||||
"cl_khr_gl_sharing.\n",
|
||||
i + 1, num_of_devices);
|
||||
found_valid_device = 1;
|
||||
m_devices[m_device_count++] = devices[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
{GLint __error = glGetError(); if(__error) {log_error( "GL ERROR: %s!\n", gluErrorString( err ));}}
|
||||
|
||||
#if defined(__linux__) || defined(GL_ES_VERSION_2_0)
|
||||
// On linux we dont link to GLU library to avoid comaptibility issues with
|
||||
// On linux we don't link to GLU library to avoid compatibility issues with
|
||||
// libstdc++
|
||||
// FIXME: Implement this
|
||||
const GLubyte* gluErrorString (GLenum error)
|
||||
|
|
@ -271,8 +271,6 @@ void * ReadGLTexture( GLenum glTarget, GLuint glTexture,
|
|||
// Read results from the GL texture
|
||||
glBindTexture(get_base_gl_target(glTarget), glTexture);
|
||||
|
||||
GLint realWidth, realHeight;
|
||||
GLint realInternalFormat;
|
||||
GLenum readBackFormat = GL_RGBA;
|
||||
GLenum readBackType = glType;
|
||||
glFramebufferWrapper glFramebuffer;
|
||||
|
|
@ -301,7 +299,7 @@ void * ReadGLTexture( GLenum glTarget, GLuint glTexture,
|
|||
GetGLFormatName(readBackFormat),
|
||||
GetGLTypeName(readBackType));
|
||||
|
||||
DumpGLBuffer(readBackType, realWidth, realHeight, (void*)outBuffer);
|
||||
DumpGLBuffer(readBackType, outWidth, outHeight, (void *)outBuffer);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -30,15 +30,13 @@
|
|||
|
||||
#if !defined (__APPLE__)
|
||||
#include <CL/cl.h>
|
||||
#include "gl_headers.h"
|
||||
#include <CL/cl_gl.h>
|
||||
#else
|
||||
#include "gl_headers.h"
|
||||
#include <CL/cl_half.h>
|
||||
#endif
|
||||
#include "gl_headers.h"
|
||||
|
||||
#include "harness/errorHelpers.h"
|
||||
#include "harness/kernelHelpers.h"
|
||||
#include "harness/threadTesting.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
#include "harness/conversions.h"
|
||||
#include "harness/mt19937.h"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
#if defined(__APPLE__) || defined(__linux__) || defined(_WIN32)
|
||||
// or any other POSIX system
|
||||
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#if defined(_MSC_VER)
|
||||
|
|
@ -56,6 +59,12 @@ CRITICAL_SECTION gAtomicLock;
|
|||
pthread_mutex_t gAtomicLock;
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
// Keep track of pthread_t's created in ThreadPool_Init() so they can be joined
|
||||
// in ThreadPool_Exit() and avoid thread leaks.
|
||||
static std::vector<pthread_t> pthreads;
|
||||
#endif
|
||||
|
||||
// Atomic add operator with mem barrier. Mem barrier needed to protect state
|
||||
// modified by the worker functions.
|
||||
cl_int ThreadPool_AtomicAdd(volatile cl_int *a, cl_int b)
|
||||
|
|
@ -241,7 +250,7 @@ pthread_cond_t cond_var;
|
|||
// Condition variable state. How many iterations on the function left to run,
|
||||
// set to CL_INT_MAX to cause worker threads to exit. Note: this value might
|
||||
// go negative.
|
||||
volatile cl_int gRunCount = 0;
|
||||
std::atomic<cl_int> gRunCount{ 0 };
|
||||
|
||||
// State that only changes when the threadpool is not working.
|
||||
volatile TPFuncPtr gFunc_ptr = NULL;
|
||||
|
|
@ -261,19 +270,20 @@ pthread_cond_t caller_cond_var;
|
|||
|
||||
// # of threads intended to be running. Running threads will decrement this
|
||||
// as they discover they've run out of work to do.
|
||||
volatile cl_int gRunning = 0;
|
||||
std::atomic<cl_int> gRunning{ 0 };
|
||||
|
||||
// The total number of threads launched.
|
||||
volatile cl_int gThreadCount = 0;
|
||||
std::atomic<cl_int> gThreadCount{ 0 };
|
||||
|
||||
#ifdef _WIN32
|
||||
void ThreadPool_WorkerFunc(void *p)
|
||||
#else
|
||||
void *ThreadPool_WorkerFunc(void *p)
|
||||
#endif
|
||||
{
|
||||
cl_uint threadID = ThreadPool_AtomicAdd((volatile cl_int *)p, 1);
|
||||
cl_int item = ThreadPool_AtomicAdd(&gRunCount, -1);
|
||||
// log_info( "ThreadPool_WorkerFunc start: gRunning = %d\n", gRunning );
|
||||
auto &tid = *static_cast<std::atomic<cl_uint> *>(p);
|
||||
cl_uint threadID = tid++;
|
||||
cl_int item = gRunCount--;
|
||||
|
||||
while (MAX_COUNT > item)
|
||||
{
|
||||
|
|
@ -282,8 +292,6 @@ void *ThreadPool_WorkerFunc(void *p)
|
|||
// check for more work to do
|
||||
if (0 >= item)
|
||||
{
|
||||
// log_info("Thread %d has run out of work.\n", threadID);
|
||||
|
||||
// No work to do. Attempt to block waiting for work
|
||||
#if defined(_WIN32)
|
||||
EnterCriticalSection(cond_lock);
|
||||
|
|
@ -298,9 +306,7 @@ void *ThreadPool_WorkerFunc(void *p)
|
|||
}
|
||||
#endif // !_WIN32
|
||||
|
||||
cl_int remaining = ThreadPool_AtomicAdd(&gRunning, -1);
|
||||
// log_info("ThreadPool_WorkerFunc: gRunning = %d\n",
|
||||
// remaining - 1);
|
||||
cl_int remaining = gRunning--;
|
||||
if (1 == remaining)
|
||||
{ // last thread out signal the main thread to wake up
|
||||
#if defined(_WIN32)
|
||||
|
|
@ -350,7 +356,7 @@ void *ThreadPool_WorkerFunc(void *p)
|
|||
#endif // !_WIN32
|
||||
|
||||
// try again to get a valid item id
|
||||
item = ThreadPool_AtomicAdd(&gRunCount, -1);
|
||||
item = gRunCount--;
|
||||
if (MAX_COUNT <= item) // exit if we are done
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
|
@ -362,8 +368,7 @@ void *ThreadPool_WorkerFunc(void *p)
|
|||
}
|
||||
}
|
||||
|
||||
ThreadPool_AtomicAdd(&gRunning, 1);
|
||||
// log_info("Thread %d has found work.\n", threadID);
|
||||
gRunning++;
|
||||
|
||||
#if defined(_WIN32)
|
||||
LeaveCriticalSection(cond_lock);
|
||||
|
|
@ -447,12 +452,12 @@ void *ThreadPool_WorkerFunc(void *p)
|
|||
}
|
||||
|
||||
// get the next item
|
||||
item = ThreadPool_AtomicAdd(&gRunCount, -1);
|
||||
item = gRunCount--;
|
||||
}
|
||||
|
||||
exit:
|
||||
log_info("ThreadPool: thread %d exiting.\n", threadID);
|
||||
ThreadPool_AtomicAdd(&gThreadCount, -1);
|
||||
gThreadCount--;
|
||||
#if !defined(_WIN32)
|
||||
return NULL;
|
||||
#endif
|
||||
|
|
@ -487,7 +492,7 @@ void ThreadPool_Init(void)
|
|||
{
|
||||
cl_int i;
|
||||
int err;
|
||||
volatile cl_uint threadID = 0;
|
||||
std::atomic<cl_uint> threadID{ 0 };
|
||||
|
||||
// Check for manual override of multithreading code. We add this for better
|
||||
// debuggability.
|
||||
|
|
@ -523,7 +528,7 @@ void ThreadPool_Init(void)
|
|||
{
|
||||
// Count the number of bits in ProcessorMask (number of
|
||||
// logical cores)
|
||||
ULONG mask = ptr->ProcessorMask;
|
||||
ULONG_PTR mask = ptr->ProcessorMask;
|
||||
while (mask)
|
||||
{
|
||||
++gThreadCount;
|
||||
|
|
@ -624,7 +629,7 @@ void ThreadPool_Init(void)
|
|||
}
|
||||
#endif // !_WIN32
|
||||
|
||||
gRunning = gThreadCount;
|
||||
gRunning = gThreadCount.load();
|
||||
// init threads
|
||||
for (i = 0; i < gThreadCount; i++)
|
||||
{
|
||||
|
|
@ -644,6 +649,9 @@ void ThreadPool_Init(void)
|
|||
gThreadCount = i;
|
||||
break;
|
||||
}
|
||||
#if !defined(_WIN32)
|
||||
pthreads.push_back(tid);
|
||||
#endif // !_WIN32
|
||||
}
|
||||
|
||||
atexit(ThreadPool_Exit);
|
||||
|
|
@ -688,7 +696,6 @@ static BOOL CALLBACK _ThreadPool_Init(_PINIT_ONCE InitOnce, PVOID Parameter,
|
|||
|
||||
void ThreadPool_Exit(void)
|
||||
{
|
||||
int err, count;
|
||||
gRunCount = CL_INT_MAX;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
|
@ -702,13 +709,13 @@ void ThreadPool_Exit(void)
|
|||
#endif
|
||||
|
||||
// spin waiting for threads to die
|
||||
for (count = 0; 0 != gThreadCount && count < 1000; count++)
|
||||
for (int count = 0; 0 != gThreadCount && count < 1000; count++)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
_WakeAllConditionVariable(cond_var);
|
||||
Sleep(1);
|
||||
#else // !_WIN32
|
||||
if ((err = pthread_cond_broadcast(&cond_var)))
|
||||
if (int err = pthread_cond_broadcast(&cond_var))
|
||||
{
|
||||
log_error("Error %d from pthread_cond_broadcast. Unable to wake up "
|
||||
"work threads. ThreadPool_Exit failed.\n",
|
||||
|
|
@ -722,9 +729,22 @@ void ThreadPool_Exit(void)
|
|||
if (gThreadCount)
|
||||
log_error("Error: Thread pool timed out after 1 second with %d threads "
|
||||
"still active.\n",
|
||||
gThreadCount);
|
||||
gThreadCount.load());
|
||||
else
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
for (pthread_t pthread : pthreads)
|
||||
{
|
||||
if (int err = pthread_join(pthread, nullptr))
|
||||
{
|
||||
log_error("Error from %d from pthread_join. Unable to join "
|
||||
"work threads. ThreadPool_Exit failed.\n",
|
||||
err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
log_info("Thread pool exited in a orderly fashion.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -738,7 +758,9 @@ void ThreadPool_Exit(void)
|
|||
// all available then it would make more sense to use those features.
|
||||
cl_int ThreadPool_Do(TPFuncPtr func_ptr, cl_uint count, void *userInfo)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
cl_int newErr;
|
||||
#endif
|
||||
cl_int err = 0;
|
||||
// Lazily set up our threads
|
||||
#if defined(_MSC_VER) && (_WIN32_WINNT >= 0x600)
|
||||
|
|
@ -913,7 +935,9 @@ cl_int ThreadPool_Do(TPFuncPtr func_ptr, cl_uint count, void *userInfo)
|
|||
|
||||
err = jobError;
|
||||
|
||||
#ifndef _WIN32
|
||||
exit:
|
||||
#endif
|
||||
// exit critical region
|
||||
#if defined(_WIN32)
|
||||
LeaveCriticalSection(gThreadPoolLock);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "mingw_compat.h"
|
||||
#endif
|
||||
|
||||
static void* align_malloc(size_t size, size_t alignment)
|
||||
inline void* align_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
return _aligned_malloc(size, alignment);
|
||||
|
|
@ -53,7 +53,7 @@ static void* align_malloc(size_t size, size_t alignment)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void align_free(void* ptr)
|
||||
inline void align_free(void* ptr)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
_aligned_free(ptr);
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
#define EXTERN_C
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
|
|
@ -309,13 +309,6 @@ EXTERN_C int __builtin_clz(unsigned int pattern);
|
|||
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
WARNING: DO NOT USE THESE MACROS:
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
#include "conversions.h"
|
||||
#include <cinttypes>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
|
@ -50,10 +51,10 @@ void print_type_to_string(ExplicitType type, void *data, char *string)
|
|||
case kInt: sprintf(string, "%d", *((cl_int *)data)); return;
|
||||
case kUInt:
|
||||
case kUnsignedInt: sprintf(string, "%u", *((cl_uint *)data)); return;
|
||||
case kLong: sprintf(string, "%lld", *((cl_long *)data)); return;
|
||||
case kLong: sprintf(string, "%" PRId64 "", *((cl_long *)data)); return;
|
||||
case kULong:
|
||||
case kUnsignedLong:
|
||||
sprintf(string, "%llu", *((cl_ulong *)data));
|
||||
sprintf(string, "%" PRIu64 "", *((cl_ulong *)data));
|
||||
return;
|
||||
case kFloat: sprintf(string, "%f", *((cl_float *)data)); return;
|
||||
case kHalf: sprintf(string, "half"); return;
|
||||
|
|
@ -181,8 +182,8 @@ static ULong sUpperLimits[kNumExplicitTypes] = {
|
|||
0xffffffffLL,
|
||||
0xffffffffLL,
|
||||
0x7fffffffffffffffLL,
|
||||
0xffffffffffffffffLL,
|
||||
0xffffffffffffffffLL,
|
||||
0xffffffffffffffffULL,
|
||||
0xffffffffffffffffULL,
|
||||
0,
|
||||
0
|
||||
}; // Last two values aren't stored here
|
||||
|
|
|
|||
|
|
@ -63,6 +63,40 @@ int is_extension_available(cl_device_id device, const char *extensionName)
|
|||
return false;
|
||||
}
|
||||
|
||||
cl_version get_extension_version(cl_device_id device, const char *extensionName)
|
||||
{
|
||||
cl_int err;
|
||||
size_t size;
|
||||
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS_WITH_VERSION, 0, nullptr,
|
||||
&size);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("clGetDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_"
|
||||
"VERSION) failed to return size\n");
|
||||
}
|
||||
|
||||
std::vector<cl_name_version> extensions(size / sizeof(cl_name_version));
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS_WITH_VERSION, size,
|
||||
extensions.data(), &size);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("clGetDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_"
|
||||
"VERSION) failed to return value\n");
|
||||
}
|
||||
|
||||
for (auto &ext : extensions)
|
||||
{
|
||||
if (!strcmp(extensionName, ext.name))
|
||||
{
|
||||
return ext.version;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Extension " + std::string(extensionName)
|
||||
+ " not supported by device!");
|
||||
}
|
||||
|
||||
/* Returns a string containing the supported extensions list for a device. */
|
||||
std::string get_device_extensions_string(cl_device_id device)
|
||||
{
|
||||
|
|
@ -86,3 +120,15 @@ std::string get_device_name(cl_device_id device)
|
|||
{
|
||||
return get_device_info_string(device, CL_DEVICE_NAME);
|
||||
}
|
||||
|
||||
size_t get_max_param_size(cl_device_id device)
|
||||
{
|
||||
size_t ret(0);
|
||||
if (clGetDeviceInfo(device, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(ret), &ret,
|
||||
nullptr)
|
||||
!= CL_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("clGetDeviceInfo failed\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ std::string get_device_info_string(cl_device_id device,
|
|||
/* Determines if an extension is supported by a device. */
|
||||
int is_extension_available(cl_device_id device, const char *extensionName);
|
||||
|
||||
/* Returns the version of the extension the device supports or throws an
|
||||
* exception if the extension is not supported by the device. */
|
||||
cl_version get_extension_version(cl_device_id device,
|
||||
const char *extensionName);
|
||||
|
||||
/* Returns a string containing the supported extensions list for a device. */
|
||||
std::string get_device_extensions_string(cl_device_id device);
|
||||
|
||||
|
|
@ -42,4 +47,8 @@ std::string get_device_version_string(cl_device_id device);
|
|||
|
||||
/* Returns a string containing the device name. */
|
||||
std::string get_device_name(cl_device_id device);
|
||||
|
||||
// Returns the maximum size in bytes for Kernel Parameters
|
||||
size_t get_max_param_size(cl_device_id device);
|
||||
|
||||
#endif // _deviceInfo_h
|
||||
|
|
|
|||
|
|
@ -18,9 +18,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "errorHelpers.h"
|
||||
|
||||
#include "parseParameters.h"
|
||||
#include "testHarness.h"
|
||||
|
||||
#include <CL/cl_half.h>
|
||||
|
||||
|
|
@ -300,10 +303,6 @@ const char *GetQueuePropertyName(cl_command_queue_properties property)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define scalbnf(_a, _i) ldexpf(_a, _i)
|
||||
#define scalbn(_a, _i) ldexp(_a, _i)
|
||||
|
|
@ -356,7 +355,7 @@ static float Ulp_Error_Half_Float(float test, double reference)
|
|||
|
||||
// The unbiased exponent of the ulp unit place
|
||||
int ulp_exp =
|
||||
HALF_MANT_DIG - 1 - MAX(ilogb(reference), HALF_MIN_EXP - 1);
|
||||
HALF_MANT_DIG - 1 - std::max(ilogb(reference), HALF_MIN_EXP - 1);
|
||||
|
||||
// Scale the exponent of the error
|
||||
return (float)scalbn(testVal - reference, ulp_exp);
|
||||
|
|
@ -364,7 +363,7 @@ static float Ulp_Error_Half_Float(float test, double reference)
|
|||
|
||||
// reference is a normal power of two or a zero
|
||||
int ulp_exp =
|
||||
HALF_MANT_DIG - 1 - MAX(ilogb(reference) - 1, HALF_MIN_EXP - 1);
|
||||
HALF_MANT_DIG - 1 - std::max(ilogb(reference) - 1, HALF_MIN_EXP - 1);
|
||||
|
||||
// Scale the exponent of the error
|
||||
return (float)scalbn(testVal - reference, ulp_exp);
|
||||
|
|
@ -436,7 +435,8 @@ float Ulp_Error(float test, double reference)
|
|||
return 0.0f; // if we are expecting a NaN, any NaN is fine
|
||||
|
||||
// The unbiased exponent of the ulp unit place
|
||||
int ulp_exp = FLT_MANT_DIG - 1 - MAX(ilogb(reference), FLT_MIN_EXP - 1);
|
||||
int ulp_exp =
|
||||
FLT_MANT_DIG - 1 - std::max(ilogb(reference), FLT_MIN_EXP - 1);
|
||||
|
||||
// Scale the exponent of the error
|
||||
return (float)scalbn(testVal - reference, ulp_exp);
|
||||
|
|
@ -444,7 +444,8 @@ float Ulp_Error(float test, double reference)
|
|||
|
||||
// reference is a normal power of two or a zero
|
||||
// The unbiased exponent of the ulp unit place
|
||||
int ulp_exp = FLT_MANT_DIG - 1 - MAX(ilogb(reference) - 1, FLT_MIN_EXP - 1);
|
||||
int ulp_exp =
|
||||
FLT_MANT_DIG - 1 - std::max(ilogb(reference) - 1, FLT_MIN_EXP - 1);
|
||||
|
||||
// Scale the exponent of the error
|
||||
return (float)scalbn(testVal - reference, ulp_exp);
|
||||
|
|
@ -512,7 +513,7 @@ float Ulp_Error_Double(double test, long double reference)
|
|||
|
||||
// The unbiased exponent of the ulp unit place
|
||||
int ulp_exp =
|
||||
DBL_MANT_DIG - 1 - MAX(ilogbl(reference), DBL_MIN_EXP - 1);
|
||||
DBL_MANT_DIG - 1 - std::max(ilogbl(reference), DBL_MIN_EXP - 1);
|
||||
|
||||
// Scale the exponent of the error
|
||||
float result = (float)scalbnl(testVal - reference, ulp_exp);
|
||||
|
|
@ -528,7 +529,7 @@ float Ulp_Error_Double(double test, long double reference)
|
|||
// reference is a normal power of two or a zero
|
||||
// The unbiased exponent of the ulp unit place
|
||||
int ulp_exp =
|
||||
DBL_MANT_DIG - 1 - MAX(ilogbl(reference) - 1, DBL_MIN_EXP - 1);
|
||||
DBL_MANT_DIG - 1 - std::max(ilogbl(reference) - 1, DBL_MIN_EXP - 1);
|
||||
|
||||
// Scale the exponent of the error
|
||||
float result = (float)scalbnl(testVal - reference, ulp_exp);
|
||||
|
|
@ -564,7 +565,7 @@ cl_int OutputBuildLogs(cl_program program, cl_uint num_devices,
|
|||
error = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL,
|
||||
&size_ret);
|
||||
test_error(error, "Unable to query context's device size");
|
||||
num_devices = size_ret / sizeof(cl_device_id);
|
||||
num_devices = static_cast<cl_uint>(size_ret / sizeof(cl_device_id));
|
||||
device_list = (cl_device_id *)malloc(size_ret);
|
||||
if (device_list == NULL)
|
||||
{
|
||||
|
|
@ -623,7 +624,6 @@ cl_int OutputBuildLogs(cl_program program, cl_uint num_devices,
|
|||
|
||||
const char *subtests_to_skip_with_offline_compiler[] = {
|
||||
"get_kernel_arg_info",
|
||||
"get_kernel_arg_info_compatibility",
|
||||
"binary_create",
|
||||
"load_program_source",
|
||||
"load_multistring_source",
|
||||
|
|
@ -691,21 +691,19 @@ const char *subtests_to_skip_with_offline_compiler[] = {
|
|||
"library_function"
|
||||
};
|
||||
|
||||
int check_functions_for_offline_compiler(const char *subtestname,
|
||||
cl_device_id device)
|
||||
bool check_functions_for_offline_compiler(const char *subtestname)
|
||||
{
|
||||
if (gCompilationMode != kOnline)
|
||||
{
|
||||
int nNotRequiredWithOfflineCompiler =
|
||||
sizeof(subtests_to_skip_with_offline_compiler) / sizeof(char *);
|
||||
size_t i;
|
||||
for (i = 0; i < nNotRequiredWithOfflineCompiler; ++i)
|
||||
size_t nNotRequiredWithOfflineCompiler =
|
||||
ARRAY_SIZE(subtests_to_skip_with_offline_compiler);
|
||||
for (size_t i = 0; i < nNotRequiredWithOfflineCompiler; ++i)
|
||||
{
|
||||
if (!strcmp(subtestname, subtests_to_skip_with_offline_compiler[i]))
|
||||
{
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,17 +56,13 @@ static int vlog_win32(const char *format, ...);
|
|||
#define vlog printf
|
||||
#endif
|
||||
|
||||
#define ct_assert(b) ct_assert_i(b, __LINE__)
|
||||
#define ct_assert_i(b, line) ct_assert_ii(b, line)
|
||||
#define ct_assert_ii(b, line) \
|
||||
int _compile_time_assertion_on_line_##line[b ? 1 : -1];
|
||||
|
||||
#define test_fail(msg, ...) \
|
||||
{ \
|
||||
log_error(msg, ##__VA_ARGS__); \
|
||||
return TEST_FAIL; \
|
||||
}
|
||||
#define test_error(errCode, msg) test_error_ret(errCode, msg, errCode)
|
||||
#define test_error_fail(errCode, msg) test_error_ret(errCode, msg, TEST_FAIL)
|
||||
#define test_error_ret(errCode, msg, retValue) \
|
||||
{ \
|
||||
auto errCodeResult = errCode; \
|
||||
|
|
@ -97,21 +93,6 @@ static int vlog_win32(const char *format, ...);
|
|||
"the device version! (from %s:%d)\n", \
|
||||
msg, __FILE__, __LINE__);
|
||||
|
||||
#define test_missing_support_offline_cmpiler(errCode, msg) \
|
||||
test_missing_support_offline_cmpiler_ret(errCode, msg, errCode)
|
||||
// this macro should always return CL_SUCCESS, but print the skip message on
|
||||
// test not supported with offline compiler
|
||||
#define test_missing_support_offline_cmpiler_ret(errCode, msg, retValue) \
|
||||
{ \
|
||||
if (errCode != CL_SUCCESS) \
|
||||
{ \
|
||||
log_info("INFO: Subtest %s tests is not supported in offline " \
|
||||
"compiler execution path! (from %s:%d)\n", \
|
||||
msg, __FILE__, __LINE__); \
|
||||
return TEST_SKIP; \
|
||||
} \
|
||||
}
|
||||
|
||||
// expected error code vs. what we got
|
||||
#define test_failure_error(errCode, expectedErrCode, msg) \
|
||||
test_failure_error_ret(errCode, expectedErrCode, msg, \
|
||||
|
|
@ -172,6 +153,21 @@ static int vlog_win32(const char *format, ...);
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define test_assert_event_status(comparison_operator, event) \
|
||||
do \
|
||||
{ \
|
||||
cl_int status; \
|
||||
cl_int err = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, \
|
||||
sizeof(status), &status, nullptr); \
|
||||
test_error(err, "Could not get " #event " info"); \
|
||||
test_assert_error(status comparison_operator CL_COMPLETE, \
|
||||
"Unexpected status for " #event); \
|
||||
} while (false)
|
||||
|
||||
#define test_assert_event_inprogress(event) test_assert_event_status(>, event)
|
||||
#define test_assert_event_terminated(event) test_assert_event_status(<, event)
|
||||
#define test_assert_event_complete(event) test_assert_event_status(==, event)
|
||||
|
||||
extern const char *IGetErrorString(int clErrorCode);
|
||||
|
||||
extern float Ulp_Error_Half(cl_half test, float reference);
|
||||
|
|
@ -186,8 +182,7 @@ extern const char *GetAddressModeName(cl_addressing_mode mode);
|
|||
extern const char *GetQueuePropertyName(cl_command_queue_properties properties);
|
||||
|
||||
extern const char *GetDeviceTypeName(cl_device_type type);
|
||||
int check_functions_for_offline_compiler(const char *subtestname,
|
||||
cl_device_id device);
|
||||
bool check_functions_for_offline_compiler(const char *subtestname);
|
||||
cl_int OutputBuildLogs(cl_program program, cl_uint num_devices,
|
||||
cl_device_id *device_list);
|
||||
|
||||
|
|
|
|||
36
test_common/harness/extensionHelpers.h
Normal file
36
test_common/harness/extensionHelpers.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef _extensionHelpers_h
|
||||
#define _extensionHelpers_h
|
||||
|
||||
// Load a specific function that is part of an OpenCL extension
|
||||
#define GET_PFN(device, fn_name) \
|
||||
fn_name##_fn fn_name = reinterpret_cast<fn_name##_fn>( \
|
||||
clGetExtensionFunctionAddressForPlatform( \
|
||||
getPlatformFromDevice(device), #fn_name)); \
|
||||
do \
|
||||
{ \
|
||||
if (!fn_name) \
|
||||
{ \
|
||||
log_error( \
|
||||
"ERROR: Failed to get function pointer for %s at %s:%d\n", \
|
||||
#fn_name, __FILE__, __LINE__); \
|
||||
return TEST_FAIL; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
|
||||
#endif // _extensionHelpers_h
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
#ifndef _fpcontrol_h
|
||||
#define _fpcontrol_h
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// In order to get tests for correctly rounded operations (e.g. multiply) to
|
||||
// work properly we need to be able to set the reference hardware to FTZ mode if
|
||||
// the device hardware is running in that mode. We have explored all other
|
||||
|
|
@ -30,7 +32,11 @@
|
|||
// that rounding mode.
|
||||
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__linux__) \
|
||||
|| defined(__MINGW32__)
|
||||
#ifdef _MSC_VER
|
||||
typedef int FPU_mode_type;
|
||||
#else
|
||||
typedef int64_t FPU_mode_type;
|
||||
#endif
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_MSC_VER) \
|
||||
|| defined(__MINGW32__)
|
||||
#include <xmmintrin.h>
|
||||
|
|
@ -39,7 +45,7 @@ typedef int FPU_mode_type;
|
|||
extern __thread fpu_control_t fpu_control;
|
||||
#endif
|
||||
// Set the reference hardware floating point unit to FTZ mode
|
||||
static inline void ForceFTZ(FPU_mode_type *mode)
|
||||
inline void ForceFTZ(FPU_mode_type *mode)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_MSC_VER) \
|
||||
|| defined(__MINGW32__)
|
||||
|
|
@ -55,7 +61,7 @@ static inline void ForceFTZ(FPU_mode_type *mode)
|
|||
__asm__ volatile("fmxr fpscr, %0" ::"r"(fpscr | (1U << 24)));
|
||||
// Add 64 bit support
|
||||
#elif defined(__aarch64__)
|
||||
unsigned fpscr;
|
||||
uint64_t fpscr;
|
||||
__asm__ volatile("mrs %0, fpcr" : "=r"(fpscr));
|
||||
*mode = fpscr;
|
||||
__asm__ volatile("msr fpcr, %0" ::"r"(fpscr | (1U << 24)));
|
||||
|
|
@ -65,7 +71,7 @@ static inline void ForceFTZ(FPU_mode_type *mode)
|
|||
}
|
||||
|
||||
// Disable the denorm flush to zero
|
||||
static inline void DisableFTZ(FPU_mode_type *mode)
|
||||
inline void DisableFTZ(FPU_mode_type *mode)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_MSC_VER) \
|
||||
|| defined(__MINGW32__)
|
||||
|
|
@ -81,7 +87,7 @@ static inline void DisableFTZ(FPU_mode_type *mode)
|
|||
__asm__ volatile("fmxr fpscr, %0" ::"r"(fpscr & ~(1U << 24)));
|
||||
// Add 64 bit support
|
||||
#elif defined(__aarch64__)
|
||||
unsigned fpscr;
|
||||
uint64_t fpscr;
|
||||
__asm__ volatile("mrs %0, fpcr" : "=r"(fpscr));
|
||||
*mode = fpscr;
|
||||
__asm__ volatile("msr fpcr, %0" ::"r"(fpscr & ~(1U << 24)));
|
||||
|
|
@ -91,7 +97,7 @@ static inline void DisableFTZ(FPU_mode_type *mode)
|
|||
}
|
||||
|
||||
// Restore the reference hardware to floating point state indicated by *mode
|
||||
static inline void RestoreFPState(FPU_mode_type *mode)
|
||||
inline void RestoreFPState(FPU_mode_type *mode)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_MSC_VER) \
|
||||
|| defined(__MINGW32__)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <malloc.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <iterator>
|
||||
#if !defined(_WIN32)
|
||||
#include <cmath>
|
||||
|
|
@ -421,7 +422,7 @@ void print_first_pixel_difference_error(size_t where, const char *sourcePixel,
|
|||
(int)thirdDim, (int)imageInfo->rowPitch,
|
||||
(int)imageInfo->rowPitch
|
||||
- (int)imageInfo->width * (int)pixel_size);
|
||||
log_error("Failed at column: %ld ", where);
|
||||
log_error("Failed at column: %zu ", where);
|
||||
|
||||
switch (pixel_size)
|
||||
{
|
||||
|
|
@ -454,7 +455,7 @@ void print_first_pixel_difference_error(size_t where, const char *sourcePixel,
|
|||
((cl_ushort *)destPixel)[1], ((cl_ushort *)destPixel)[2]);
|
||||
break;
|
||||
case 8:
|
||||
log_error("*0x%16.16llx vs. 0x%16.16llx\n",
|
||||
log_error("*0x%16.16" PRIx64 " vs. 0x%16.16" PRIx64 "\n",
|
||||
((cl_ulong *)sourcePixel)[0], ((cl_ulong *)destPixel)[0]);
|
||||
break;
|
||||
case 12:
|
||||
|
|
@ -473,12 +474,53 @@ void print_first_pixel_difference_error(size_t where, const char *sourcePixel,
|
|||
((cl_uint *)destPixel)[2], ((cl_uint *)destPixel)[3]);
|
||||
break;
|
||||
default:
|
||||
log_error("Don't know how to print pixel size of %ld\n",
|
||||
log_error("Don't know how to print pixel size of %zu\n",
|
||||
pixel_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t compare_scanlines(const image_descriptor *imageInfo, const char *aPtr,
|
||||
const char *bPtr)
|
||||
{
|
||||
size_t pixel_size = get_pixel_size(imageInfo->format);
|
||||
size_t column;
|
||||
|
||||
for (column = 0; column < imageInfo->width; column++)
|
||||
{
|
||||
switch (imageInfo->format->image_channel_data_type)
|
||||
{
|
||||
// If the data type is 101010, then ignore bits 31 and 32 when
|
||||
// comparing the row
|
||||
case CL_UNORM_INT_101010: {
|
||||
cl_uint aPixel = *(cl_uint *)aPtr;
|
||||
cl_uint bPixel = *(cl_uint *)bPtr;
|
||||
if ((aPixel & 0x3fffffff) != (bPixel & 0x3fffffff))
|
||||
return column;
|
||||
}
|
||||
break;
|
||||
|
||||
// If the data type is 555, ignore bit 15 when comparing the row
|
||||
case CL_UNORM_SHORT_555: {
|
||||
cl_ushort aPixel = *(cl_ushort *)aPtr;
|
||||
cl_ushort bPixel = *(cl_ushort *)bPtr;
|
||||
if ((aPixel & 0x7fff) != (bPixel & 0x7fff)) return column;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (memcmp(aPtr, bPtr, pixel_size) != 0) return column;
|
||||
break;
|
||||
}
|
||||
|
||||
aPtr += pixel_size;
|
||||
bPtr += pixel_size;
|
||||
}
|
||||
|
||||
// If we didn't find a difference, return the width of the image
|
||||
return column;
|
||||
}
|
||||
|
||||
int random_log_in_range(int minV, int maxV, MTdata d)
|
||||
{
|
||||
double v = log2(((double)genrand_int32(d) / (double)0xffffffff) + 1);
|
||||
|
|
@ -554,8 +596,8 @@ struct AddressingTable
|
|||
{
|
||||
AddressingTable()
|
||||
{
|
||||
ct_assert((CL_ADDRESS_MIRRORED_REPEAT - CL_ADDRESS_NONE < 6));
|
||||
ct_assert(CL_FILTER_NEAREST - CL_FILTER_LINEAR < 2);
|
||||
static_assert(CL_ADDRESS_MIRRORED_REPEAT - CL_ADDRESS_NONE < 6, "");
|
||||
static_assert(CL_FILTER_NEAREST - CL_FILTER_LINEAR < 2, "");
|
||||
|
||||
mTable[CL_ADDRESS_NONE - CL_ADDRESS_NONE]
|
||||
[CL_FILTER_NEAREST - CL_FILTER_NEAREST] = NoAddressFn;
|
||||
|
|
@ -649,9 +691,6 @@ int has_alpha(const cl_image_format *format)
|
|||
_b ^= _a; \
|
||||
_a ^= _b; \
|
||||
} while (0)
|
||||
#ifndef MAX
|
||||
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
#endif
|
||||
|
||||
void get_max_sizes(
|
||||
size_t *numberOfSizes, const int maxNumberOfSizes, size_t sizes[][3],
|
||||
|
|
@ -719,7 +758,7 @@ void get_max_sizes(
|
|||
if (usingMaxPixelSizeBuffer || raw_pixel_size == 12) raw_pixel_size = 16;
|
||||
size_t max_pixels = (size_t)maxAllocSize / raw_pixel_size;
|
||||
|
||||
log_info("Maximums: [%ld x %ld x %ld], raw pixel size %lu bytes, "
|
||||
log_info("Maximums: [%zu x %zu x %zu], raw pixel size %zu bytes, "
|
||||
"per-allocation limit %gMB.\n",
|
||||
maxWidth, maxHeight, isArray ? maxArraySize : maxDepth,
|
||||
raw_pixel_size, (maxAllocSize / (1024.0 * 1024.0)));
|
||||
|
|
@ -760,10 +799,10 @@ void get_max_sizes(
|
|||
if (image_type == CL_MEM_OBJECT_IMAGE1D)
|
||||
{
|
||||
|
||||
double M = maximum_sizes[0];
|
||||
size_t M = maximum_sizes[0];
|
||||
|
||||
// Store the size
|
||||
sizes[(*numberOfSizes)][0] = (size_t)M;
|
||||
sizes[(*numberOfSizes)][0] = M;
|
||||
sizes[(*numberOfSizes)][1] = 1;
|
||||
sizes[(*numberOfSizes)][2] = 1;
|
||||
++(*numberOfSizes);
|
||||
|
|
@ -777,17 +816,17 @@ void get_max_sizes(
|
|||
{
|
||||
|
||||
// Determine the size of the fixed dimension
|
||||
double M = maximum_sizes[fixed_dim];
|
||||
double A = max_pixels;
|
||||
size_t M = maximum_sizes[fixed_dim];
|
||||
size_t A = max_pixels;
|
||||
|
||||
int x0_dim = !fixed_dim;
|
||||
double x0 =
|
||||
size_t x0 = static_cast<size_t>(
|
||||
fmin(fmin(other_sizes[(other_size++) % num_other_sizes], A / M),
|
||||
maximum_sizes[x0_dim]);
|
||||
maximum_sizes[x0_dim]));
|
||||
|
||||
// Store the size
|
||||
sizes[(*numberOfSizes)][fixed_dim] = (size_t)M;
|
||||
sizes[(*numberOfSizes)][x0_dim] = (size_t)x0;
|
||||
sizes[(*numberOfSizes)][fixed_dim] = M;
|
||||
sizes[(*numberOfSizes)][x0_dim] = x0;
|
||||
sizes[(*numberOfSizes)][2] = 1;
|
||||
++(*numberOfSizes);
|
||||
}
|
||||
|
|
@ -802,16 +841,17 @@ void get_max_sizes(
|
|||
{
|
||||
|
||||
// Determine the size of the fixed dimension
|
||||
double M = maximum_sizes[fixed_dim];
|
||||
double A = max_pixels;
|
||||
size_t M = maximum_sizes[fixed_dim];
|
||||
size_t A = max_pixels;
|
||||
|
||||
// Find two other dimensions, x0 and x1
|
||||
int x0_dim = (fixed_dim == 0) ? 1 : 0;
|
||||
int x1_dim = (fixed_dim == 2) ? 1 : 2;
|
||||
|
||||
// Choose two other sizes for these dimensions
|
||||
double x0 = fmin(fmin(A / M, maximum_sizes[x0_dim]),
|
||||
other_sizes[(other_size++) % num_other_sizes]);
|
||||
size_t x0 = static_cast<size_t>(
|
||||
fmin(fmin(A / M, maximum_sizes[x0_dim]),
|
||||
other_sizes[(other_size++) % num_other_sizes]));
|
||||
// GPUs have certain restrictions on minimum width (row alignment)
|
||||
// of images which has given us issues testing small widths in this
|
||||
// test (say we set width to 3 for testing, and compute size based
|
||||
|
|
@ -820,8 +860,9 @@ void get_max_sizes(
|
|||
// width of 16 which doesnt fit in vram). For this purpose we are
|
||||
// not testing width < 16 for this test.
|
||||
if (x0_dim == 0 && x0 < 16) x0 = 16;
|
||||
double x1 = fmin(fmin(A / M / x0, maximum_sizes[x1_dim]),
|
||||
other_sizes[(other_size++) % num_other_sizes]);
|
||||
size_t x1 = static_cast<size_t>(
|
||||
fmin(fmin(A / M / x0, maximum_sizes[x1_dim]),
|
||||
other_sizes[(other_size++) % num_other_sizes]));
|
||||
|
||||
// Valid image sizes cannot be below 1. Due to the workaround for
|
||||
// the xo_dim where x0 is overidden to 16 there might not be enough
|
||||
|
|
@ -834,9 +875,9 @@ void get_max_sizes(
|
|||
assert(x0 > 0 && M > 0);
|
||||
|
||||
// Store the size
|
||||
sizes[(*numberOfSizes)][fixed_dim] = (size_t)M;
|
||||
sizes[(*numberOfSizes)][x0_dim] = (size_t)x0;
|
||||
sizes[(*numberOfSizes)][x1_dim] = (size_t)x1;
|
||||
sizes[(*numberOfSizes)][fixed_dim] = M;
|
||||
sizes[(*numberOfSizes)][x0_dim] = x0;
|
||||
sizes[(*numberOfSizes)][x1_dim] = x1;
|
||||
++(*numberOfSizes);
|
||||
}
|
||||
}
|
||||
|
|
@ -847,20 +888,20 @@ void get_max_sizes(
|
|||
switch (image_type)
|
||||
{
|
||||
case CL_MEM_OBJECT_IMAGE1D:
|
||||
log_info(" size[%d] = [%ld] (%g MB image)\n", j, sizes[j][0],
|
||||
log_info(" size[%d] = [%zu] (%g MB image)\n", j, sizes[j][0],
|
||||
raw_pixel_size * sizes[j][0] * sizes[j][1]
|
||||
* sizes[j][2] / (1024.0 * 1024.0));
|
||||
break;
|
||||
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
|
||||
case CL_MEM_OBJECT_IMAGE2D:
|
||||
log_info(" size[%d] = [%ld %ld] (%g MB image)\n", j,
|
||||
log_info(" size[%d] = [%zu %zu] (%g MB image)\n", j,
|
||||
sizes[j][0], sizes[j][1],
|
||||
raw_pixel_size * sizes[j][0] * sizes[j][1]
|
||||
* sizes[j][2] / (1024.0 * 1024.0));
|
||||
break;
|
||||
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
|
||||
case CL_MEM_OBJECT_IMAGE3D:
|
||||
log_info(" size[%d] = [%ld %ld %ld] (%g MB image)\n", j,
|
||||
log_info(" size[%d] = [%zu %zu %zu] (%g MB image)\n", j,
|
||||
sizes[j][0], sizes[j][1], sizes[j][2],
|
||||
raw_pixel_size * sizes[j][0] * sizes[j][1]
|
||||
* sizes[j][2] / (1024.0 * 1024.0));
|
||||
|
|
@ -884,6 +925,8 @@ float get_max_absolute_error(const cl_image_format *format,
|
|||
#ifdef CL_SFIXED14_APPLE
|
||||
case CL_SFIXED14_APPLE: return 0x1.0p-14f;
|
||||
#endif
|
||||
case CL_UNORM_SHORT_555:
|
||||
case CL_UNORM_SHORT_565: return 1.0f / 31.0f;
|
||||
default: return 0.0f;
|
||||
}
|
||||
}
|
||||
|
|
@ -1124,12 +1167,13 @@ void escape_inf_nan_values(char *data, size_t allocSize)
|
|||
char *generate_random_image_data(image_descriptor *imageInfo,
|
||||
BufferOwningPtr<char> &P, MTdata d)
|
||||
{
|
||||
size_t allocSize = get_image_size(imageInfo);
|
||||
size_t allocSize = static_cast<size_t>(get_image_size(imageInfo));
|
||||
size_t pixelRowBytes = imageInfo->width * get_pixel_size(imageInfo->format);
|
||||
size_t i;
|
||||
|
||||
if (imageInfo->num_mip_levels > 1)
|
||||
allocSize = compute_mipmapped_image_size(*imageInfo);
|
||||
allocSize =
|
||||
static_cast<size_t>(compute_mipmapped_image_size(*imageInfo));
|
||||
|
||||
#if defined(__APPLE__)
|
||||
char *data = NULL;
|
||||
|
|
@ -1161,7 +1205,7 @@ char *generate_random_image_data(image_descriptor *imageInfo,
|
|||
|
||||
if (data == NULL)
|
||||
{
|
||||
log_error("ERROR: Unable to malloc %lu bytes for "
|
||||
log_error("ERROR: Unable to malloc %zu bytes for "
|
||||
"generate_random_image_data\n",
|
||||
allocSize);
|
||||
return 0;
|
||||
|
|
@ -1678,24 +1722,26 @@ bool get_integer_coords_offset(float x, float y, float z, float xAddressOffset,
|
|||
|
||||
// At this point, we're dealing with non-normalized coordinates.
|
||||
|
||||
outX = adFn(floorf(x), width);
|
||||
outX = adFn(static_cast<int>(floorf(x)), width);
|
||||
|
||||
// 1D and 2D arrays require special care for the index coordinate:
|
||||
|
||||
switch (imageInfo->type)
|
||||
{
|
||||
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
|
||||
outY = calculate_array_index(y, (float)imageInfo->arraySize - 1.0f);
|
||||
outZ = 0.0f; /* don't care! */
|
||||
outY = static_cast<int>(
|
||||
calculate_array_index(y, (float)imageInfo->arraySize - 1.0f));
|
||||
outZ = 0; /* don't care! */
|
||||
break;
|
||||
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
|
||||
outY = adFn(floorf(y), height);
|
||||
outZ = calculate_array_index(z, (float)imageInfo->arraySize - 1.0f);
|
||||
outY = adFn(static_cast<int>(floorf(y)), height);
|
||||
outZ = static_cast<int>(
|
||||
calculate_array_index(z, (float)imageInfo->arraySize - 1.0f));
|
||||
break;
|
||||
default:
|
||||
// legacy path:
|
||||
if (height != 0) outY = adFn(floorf(y), height);
|
||||
if (depth != 0) outZ = adFn(floorf(z), depth);
|
||||
if (height != 0) outY = adFn(static_cast<int>(floorf(y)), height);
|
||||
if (depth != 0) outZ = adFn(static_cast<int>(floorf(z)), depth);
|
||||
}
|
||||
|
||||
return !((int)refX == outX && (int)refY == outY && (int)refZ == outZ);
|
||||
|
|
@ -1766,7 +1812,7 @@ static float unnormalize_coordinate(const char *name, float coord, float offset,
|
|||
switch (addressing_mode)
|
||||
{
|
||||
case CL_ADDRESS_REPEAT:
|
||||
ret = RepeatNormalizedAddressFn(coord, extent);
|
||||
ret = RepeatNormalizedAddressFn(coord, static_cast<size_t>(extent));
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
|
|
@ -1790,7 +1836,8 @@ static float unnormalize_coordinate(const char *name, float coord, float offset,
|
|||
break;
|
||||
|
||||
case CL_ADDRESS_MIRRORED_REPEAT:
|
||||
ret = MirroredRepeatNormalizedAddressFn(coord, extent);
|
||||
ret = MirroredRepeatNormalizedAddressFn(
|
||||
coord, static_cast<size_t>(extent));
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
|
|
@ -1948,7 +1995,7 @@ FloatPixel sample_image_pixel_float_offset(
|
|||
break;
|
||||
case CL_MEM_OBJECT_IMAGE1D:
|
||||
case CL_MEM_OBJECT_IMAGE1D_BUFFER:
|
||||
log_info("Starting coordinate: %f\b", x);
|
||||
log_info("Starting coordinate: %f\n", x);
|
||||
break;
|
||||
case CL_MEM_OBJECT_IMAGE2D:
|
||||
log_info("Starting coordinate: %f, %f\n", x, y);
|
||||
|
|
@ -1968,13 +2015,13 @@ FloatPixel sample_image_pixel_float_offset(
|
|||
// coordinates. Note that the array cases again require special
|
||||
// care, per section 8.4 in the OpenCL 1.2 Specification.
|
||||
|
||||
ix = adFn(floorf(x), width_lod);
|
||||
ix = adFn(static_cast<int>(floorf(x)), width_lod);
|
||||
|
||||
switch (imageInfo->type)
|
||||
{
|
||||
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
|
||||
iy =
|
||||
calculate_array_index(y, (float)(imageInfo->arraySize - 1));
|
||||
iy = static_cast<int>(calculate_array_index(
|
||||
y, (float)(imageInfo->arraySize - 1)));
|
||||
iz = 0;
|
||||
if (verbose)
|
||||
{
|
||||
|
|
@ -1982,18 +2029,18 @@ FloatPixel sample_image_pixel_float_offset(
|
|||
}
|
||||
break;
|
||||
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
|
||||
iy = adFn(floorf(y), height_lod);
|
||||
iz =
|
||||
calculate_array_index(z, (float)(imageInfo->arraySize - 1));
|
||||
iy = adFn(static_cast<int>(floorf(y)), height_lod);
|
||||
iz = static_cast<int>(calculate_array_index(
|
||||
z, (float)(imageInfo->arraySize - 1)));
|
||||
if (verbose)
|
||||
{
|
||||
log_info("\tArray index %f evaluates to %d\n", z, iz);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
iy = adFn(floorf(y), height_lod);
|
||||
iy = adFn(static_cast<int>(floorf(y)), height_lod);
|
||||
if (depth_lod != 0)
|
||||
iz = adFn(floorf(z), depth_lod);
|
||||
iz = adFn(static_cast<int>(floorf(z)), depth_lod);
|
||||
else
|
||||
iz = 0;
|
||||
}
|
||||
|
|
@ -2047,16 +2094,16 @@ FloatPixel sample_image_pixel_float_offset(
|
|||
height = 1;
|
||||
}
|
||||
|
||||
int x1 = adFn(floorf(x - 0.5f), width);
|
||||
int x1 = adFn(static_cast<int>(floorf(x - 0.5f)), width);
|
||||
int y1 = 0;
|
||||
int x2 = adFn(floorf(x - 0.5f) + 1, width);
|
||||
int x2 = adFn(static_cast<int>(floorf(x - 0.5f) + 1), width);
|
||||
int y2 = 0;
|
||||
if ((imageInfo->type != CL_MEM_OBJECT_IMAGE1D)
|
||||
&& (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY)
|
||||
&& (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_BUFFER))
|
||||
{
|
||||
y1 = adFn(floorf(y - 0.5f), height);
|
||||
y2 = adFn(floorf(y - 0.5f) + 1, height);
|
||||
y1 = adFn(static_cast<int>(floorf(y - 0.5f)), height);
|
||||
y2 = adFn(static_cast<int>(floorf(y - 0.5f) + 1), height);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2105,14 +2152,6 @@ FloatPixel sample_image_pixel_float_offset(
|
|||
lowRight[2], lowRight[3]);
|
||||
}
|
||||
|
||||
bool printMe = false;
|
||||
if (x1 <= 0 || x2 <= 0 || x1 >= (int)width - 1
|
||||
|| x2 >= (int)width - 1)
|
||||
printMe = true;
|
||||
if (y1 <= 0 || y2 <= 0 || y1 >= (int)height - 1
|
||||
|| y2 >= (int)height - 1)
|
||||
printMe = true;
|
||||
|
||||
double weights[2][2];
|
||||
|
||||
weights[0][0] = weights[0][1] = 1.0 - frac(x - 0.5f);
|
||||
|
|
@ -2147,12 +2186,12 @@ FloatPixel sample_image_pixel_float_offset(
|
|||
else
|
||||
{
|
||||
// 3D linear filtering
|
||||
int x1 = adFn(floorf(x - 0.5f), width_lod);
|
||||
int y1 = adFn(floorf(y - 0.5f), height_lod);
|
||||
int z1 = adFn(floorf(z - 0.5f), depth_lod);
|
||||
int x2 = adFn(floorf(x - 0.5f) + 1, width_lod);
|
||||
int y2 = adFn(floorf(y - 0.5f) + 1, height_lod);
|
||||
int z2 = adFn(floorf(z - 0.5f) + 1, depth_lod);
|
||||
int x1 = adFn(static_cast<int>(floorf(x - 0.5f)), width_lod);
|
||||
int y1 = adFn(static_cast<int>(floorf(y - 0.5f)), height_lod);
|
||||
int z1 = adFn(static_cast<int>(floorf(z - 0.5f)), depth_lod);
|
||||
int x2 = adFn(static_cast<int>(floorf(x - 0.5f) + 1), width_lod);
|
||||
int y2 = adFn(static_cast<int>(floorf(y - 0.5f) + 1), height_lod);
|
||||
int z2 = adFn(static_cast<int>(floorf(z - 0.5f) + 1), depth_lod);
|
||||
|
||||
if (verbose)
|
||||
log_info("\tActual integer coords used (i = floor(x-.5)): "
|
||||
|
|
@ -2580,11 +2619,11 @@ void pack_image_pixel(int *srcVector, const cl_image_format *imageFormat,
|
|||
}
|
||||
}
|
||||
|
||||
int round_to_even(float v)
|
||||
cl_int round_to_even(float v)
|
||||
{
|
||||
// clamp overflow
|
||||
if (v >= -(float)INT_MIN) return INT_MAX;
|
||||
if (v <= (float)INT_MIN) return INT_MIN;
|
||||
if (v >= -(float)CL_INT_MIN) return CL_INT_MAX;
|
||||
if (v <= (float)CL_INT_MIN) return CL_INT_MIN;
|
||||
|
||||
// round fractional values to integer value
|
||||
if (fabsf(v) < MAKE_HEX_FLOAT(0x1.0p23f, 0x1L, 23))
|
||||
|
|
@ -2596,7 +2635,7 @@ int round_to_even(float v)
|
|||
v -= magicVal;
|
||||
}
|
||||
|
||||
return (int)v;
|
||||
return (cl_int)v;
|
||||
}
|
||||
|
||||
void pack_image_pixel(float *srcVector, const cl_image_format *imageFormat,
|
||||
|
|
@ -2721,10 +2760,7 @@ void pack_image_pixel(float *srcVector, const cl_image_format *imageFormat,
|
|||
case CL_SIGNED_INT32: {
|
||||
cl_int *ptr = (cl_int *)outData;
|
||||
for (unsigned int i = 0; i < channelCount; i++)
|
||||
ptr[i] = (int)CONVERT_INT(
|
||||
srcVector[i], MAKE_HEX_FLOAT(-0x1.0p31f, -1, 31),
|
||||
MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffe, 30 - 23),
|
||||
CL_INT_MAX);
|
||||
ptr[i] = round_to_even(srcVector[i]);
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT8: {
|
||||
|
|
@ -2888,26 +2924,25 @@ void pack_image_pixel_error(const float *srcVector,
|
|||
case CL_SIGNED_INT32: {
|
||||
const cl_int *ptr = (const cl_int *)results;
|
||||
for (unsigned int i = 0; i < channelCount; i++)
|
||||
errors[i] = (cl_float)(
|
||||
(cl_long)ptr[i]
|
||||
- (cl_long)CONVERT_INT(
|
||||
srcVector[i], MAKE_HEX_FLOAT(-0x1.0p31f, -1, 31),
|
||||
MAKE_HEX_FLOAT(0x1.fffffep30f, 0x1fffffe, 30 - 23),
|
||||
CL_INT_MAX));
|
||||
errors[i] = (cl_float)((cl_long)ptr[i]
|
||||
- (cl_long)round_to_even(srcVector[i]));
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT8: {
|
||||
const cl_uchar *ptr = (const cl_uchar *)results;
|
||||
for (unsigned int i = 0; i < channelCount; i++)
|
||||
errors[i] = (cl_int)ptr[i]
|
||||
- (cl_int)CONVERT_UINT(srcVector[i], 255.f, CL_UCHAR_MAX);
|
||||
errors[i] = static_cast<float>(
|
||||
(cl_int)ptr[i]
|
||||
- (cl_int)CONVERT_UINT(srcVector[i], 255.f, CL_UCHAR_MAX));
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT16: {
|
||||
const cl_ushort *ptr = (const cl_ushort *)results;
|
||||
for (unsigned int i = 0; i < channelCount; i++)
|
||||
errors[i] = (cl_int)ptr[i]
|
||||
- (cl_int)CONVERT_UINT(srcVector[i], 32767.f, CL_USHRT_MAX);
|
||||
errors[i] = static_cast<float>(
|
||||
(cl_int)ptr[i]
|
||||
- (cl_int)CONVERT_UINT(srcVector[i], 32767.f,
|
||||
CL_USHRT_MAX));
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT32: {
|
||||
|
|
@ -3228,7 +3263,7 @@ char *create_random_image_data(ExplicitType dataType,
|
|||
if (data == NULL)
|
||||
{
|
||||
log_error(
|
||||
"ERROR: Unable to malloc %lu bytes for create_random_image_data\n",
|
||||
"ERROR: Unable to malloc %zu bytes for create_random_image_data\n",
|
||||
allocSize);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -3988,7 +4023,8 @@ bool is_image_format_required(cl_image_format format, cl_mem_flags flags,
|
|||
|
||||
cl_uint compute_max_mip_levels(size_t width, size_t height, size_t depth)
|
||||
{
|
||||
cl_uint retMaxMipLevels = 0, max_dim = 0;
|
||||
cl_uint retMaxMipLevels = 0;
|
||||
size_t max_dim = 0;
|
||||
|
||||
max_dim = width;
|
||||
max_dim = height > max_dim ? height : max_dim;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ typedef struct
|
|||
bool normalized_coords;
|
||||
} image_sampler_data;
|
||||
|
||||
int round_to_even(float v);
|
||||
cl_int round_to_even(float v);
|
||||
|
||||
#define NORMALIZE(v, max) (v < 0 ? 0 : (v > 1.f ? max : round_to_even(v * max)))
|
||||
#define NORMALIZE_UNROUNDED(v, max) (v < 0 ? 0 : (v > 1.f ? max : v * max))
|
||||
|
|
@ -139,6 +139,9 @@ void print_first_pixel_difference_error(size_t where, const char *sourcePixel,
|
|||
image_descriptor *imageInfo, size_t y,
|
||||
size_t thirdDim);
|
||||
|
||||
size_t compare_scanlines(const image_descriptor *imageInfo, const char *aPtr,
|
||||
const char *bPtr);
|
||||
|
||||
void get_max_sizes(size_t *numberOfSizes, const int maxNumberOfSizes,
|
||||
size_t sizes[][3], size_t maxWidth, size_t maxHeight,
|
||||
size_t maxDepth, size_t maxArraySize,
|
||||
|
|
@ -479,6 +482,13 @@ void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
|
|||
outData[2] = tempData[3];
|
||||
outData[3] = tempData[0];
|
||||
}
|
||||
else if (format->image_channel_order == CL_ABGR)
|
||||
{
|
||||
outData[0] = tempData[3];
|
||||
outData[1] = tempData[2];
|
||||
outData[2] = tempData[1];
|
||||
outData[3] = tempData[0];
|
||||
}
|
||||
else if ((format->image_channel_order == CL_BGRA)
|
||||
|| (format->image_channel_order == CL_sBGRA))
|
||||
{
|
||||
|
|
@ -489,12 +499,14 @@ void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
|
|||
}
|
||||
else if (format->image_channel_order == CL_INTENSITY)
|
||||
{
|
||||
outData[0] = tempData[0];
|
||||
outData[1] = tempData[0];
|
||||
outData[2] = tempData[0];
|
||||
outData[3] = tempData[0];
|
||||
}
|
||||
else if (format->image_channel_order == CL_LUMINANCE)
|
||||
{
|
||||
outData[0] = tempData[0];
|
||||
outData[1] = tempData[0];
|
||||
outData[2] = tempData[0];
|
||||
}
|
||||
|
|
|
|||
92
test_common/harness/integer_ops_test_info.h
Normal file
92
test_common/harness/integer_ops_test_info.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// Copyright (c) 2021 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef INTEGER_OPS_TEST_INFO_H
|
||||
#define INTEGER_OPS_TEST_INFO_H
|
||||
|
||||
#include "conversions.h"
|
||||
#include "testHarness.h"
|
||||
|
||||
// TODO: expand usage to other tests.
|
||||
|
||||
template <typename T> struct TestInfo
|
||||
{
|
||||
};
|
||||
template <> struct TestInfo<cl_char>
|
||||
{
|
||||
static const ExplicitType explicitType = kChar;
|
||||
static constexpr const char* deviceTypeName = "char";
|
||||
static constexpr const char* deviceTypeNameSigned = "char";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "uchar";
|
||||
};
|
||||
template <> struct TestInfo<cl_uchar>
|
||||
{
|
||||
static const ExplicitType explicitType = kUChar;
|
||||
static constexpr const char* deviceTypeName = "uchar";
|
||||
static constexpr const char* deviceTypeNameSigned = "char";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "uchar";
|
||||
};
|
||||
template <> struct TestInfo<cl_short>
|
||||
{
|
||||
static const ExplicitType explicitType = kShort;
|
||||
static constexpr const char* deviceTypeName = "short";
|
||||
static constexpr const char* deviceTypeNameSigned = "short";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "ushort";
|
||||
};
|
||||
template <> struct TestInfo<cl_ushort>
|
||||
{
|
||||
static const ExplicitType explicitType = kUShort;
|
||||
static constexpr const char* deviceTypeName = "ushort";
|
||||
static constexpr const char* deviceTypeNameSigned = "short";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "ushort";
|
||||
};
|
||||
template <> struct TestInfo<cl_int>
|
||||
{
|
||||
static const ExplicitType explicitType = kInt;
|
||||
static constexpr const char* deviceTypeName = "int";
|
||||
static constexpr const char* deviceTypeNameSigned = "int";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "uint";
|
||||
};
|
||||
template <> struct TestInfo<cl_uint>
|
||||
{
|
||||
static const ExplicitType explicitType = kUInt;
|
||||
static constexpr const char* deviceTypeName = "uint";
|
||||
static constexpr const char* deviceTypeNameSigned = "int";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "uint";
|
||||
};
|
||||
template <> struct TestInfo<cl_long>
|
||||
{
|
||||
static const ExplicitType explicitType = kLong;
|
||||
static constexpr const char* deviceTypeName = "long";
|
||||
static constexpr const char* deviceTypeNameSigned = "long";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "ulong";
|
||||
};
|
||||
template <> struct TestInfo<cl_ulong>
|
||||
{
|
||||
static const ExplicitType explicitType = kULong;
|
||||
static constexpr const char* deviceTypeName = "ulong";
|
||||
static constexpr const char* deviceTypeNameSigned = "long";
|
||||
static constexpr const char* deviceTypeNameUnsigned = "ulong";
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static void fill_vector_with_random_data(std::vector<T>& v)
|
||||
{
|
||||
MTdataHolder d(gRandomSeed);
|
||||
generate_random_data(TestInfo<T>::explicitType, v.size(), d, v.data());
|
||||
}
|
||||
|
||||
#endif /* INTEGER_OPS_TEST_INFO_H */
|
||||
|
|
@ -312,57 +312,6 @@ get_compilation_mode_str(const CompilationMode compilationMode)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef KHRONOS_OFFLINE_COMPILER
|
||||
static std::string
|
||||
get_khronos_compiler_command(const cl_uint device_address_space_size,
|
||||
const bool openclCXX, const std::string &bOptions,
|
||||
const std::string &sourceFilename,
|
||||
const std::string &outputFilename)
|
||||
{
|
||||
// Set compiler options
|
||||
// Emit SPIR-V
|
||||
std::string compilerOptions = " -cc1 -emit-spirv";
|
||||
// <triple>: for 32 bit SPIR-V use spir-unknown-unknown, for 64 bit SPIR-V
|
||||
// use spir64-unknown-unknown.
|
||||
if (device_address_space_size == 32)
|
||||
{
|
||||
compilerOptions += " -triple=spir-unknown-unknown";
|
||||
}
|
||||
else
|
||||
{
|
||||
compilerOptions += " -triple=spir64-unknown-unknown";
|
||||
}
|
||||
// Set OpenCL C++ flag required by SPIR-V-ready clang (compiler provided by
|
||||
// Khronos)
|
||||
if (openclCXX)
|
||||
{
|
||||
compilerOptions = compilerOptions + " -cl-std=c++";
|
||||
}
|
||||
// Set correct includes
|
||||
if (openclCXX)
|
||||
{
|
||||
compilerOptions += " -I ";
|
||||
compilerOptions += STRINGIFY_VALUE(CL_LIBCLCXX_DIR);
|
||||
}
|
||||
else
|
||||
{
|
||||
compilerOptions += " -include opencl.h";
|
||||
}
|
||||
|
||||
#ifdef KHRONOS_OFFLINE_COMPILER_OPTIONS
|
||||
compilerOptions += STRINGIFY_VALUE(KHRONOS_OFFLINE_COMPILER_OPTIONS);
|
||||
#endif
|
||||
|
||||
// Add build options passed to this function
|
||||
compilerOptions += " " + bOptions;
|
||||
compilerOptions += " " + sourceFilename + " -o " + outputFilename;
|
||||
std::string runString =
|
||||
STRINGIFY_VALUE(KHRONOS_OFFLINE_COMPILER) + compilerOptions;
|
||||
|
||||
return runString;
|
||||
}
|
||||
#endif // KHRONOS_OFFLINE_COMPILER
|
||||
|
||||
static cl_int get_cl_device_info_str(const cl_device_id device,
|
||||
const cl_uint device_address_space_size,
|
||||
const CompilationMode compilationMode,
|
||||
|
|
@ -476,49 +425,27 @@ static int invoke_offline_compiler(const cl_device_id device,
|
|||
const CompilationMode compilationMode,
|
||||
const std::string &bOptions,
|
||||
const std::string &sourceFilename,
|
||||
const std::string &outputFilename,
|
||||
const bool openclCXX)
|
||||
const std::string &outputFilename)
|
||||
{
|
||||
std::string runString;
|
||||
if (openclCXX)
|
||||
std::string clDeviceInfoFilename;
|
||||
|
||||
// See cl_offline_compiler-interface.txt for a description of the
|
||||
// format of the CL device information file generated below, and
|
||||
// the internal command line interface for invoking the offline
|
||||
// compiler.
|
||||
|
||||
cl_int err = write_cl_device_info(device, device_address_space_size,
|
||||
compilationMode, clDeviceInfoFilename);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
#ifndef KHRONOS_OFFLINE_COMPILER
|
||||
log_error("CL C++ compilation is not possible: "
|
||||
"KHRONOS_OFFLINE_COMPILER was not defined.\n");
|
||||
return CL_INVALID_OPERATION;
|
||||
#else
|
||||
if (compilationMode != kSpir_v)
|
||||
{
|
||||
log_error("Compilation mode must be SPIR-V for Khronos compiler");
|
||||
return -1;
|
||||
}
|
||||
runString = get_khronos_compiler_command(
|
||||
device_address_space_size, openclCXX, bOptions, sourceFilename,
|
||||
outputFilename);
|
||||
#endif
|
||||
log_error("Failed writing CL device info file\n");
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string clDeviceInfoFilename;
|
||||
|
||||
// See cl_offline_compiler-interface.txt for a description of the
|
||||
// format of the CL device information file generated below, and
|
||||
// the internal command line interface for invoking the offline
|
||||
// compiler.
|
||||
|
||||
cl_int err =
|
||||
write_cl_device_info(device, device_address_space_size,
|
||||
compilationMode, clDeviceInfoFilename);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("Failed writing CL device info file\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
runString = get_offline_compilation_command(
|
||||
device_address_space_size, compilationMode, bOptions,
|
||||
sourceFilename, outputFilename, clDeviceInfoFilename);
|
||||
}
|
||||
runString = get_offline_compilation_command(
|
||||
device_address_space_size, compilationMode, bOptions, sourceFilename,
|
||||
outputFilename, clDeviceInfoFilename);
|
||||
|
||||
// execute script
|
||||
log_info("Executing command: %s\n", runString.c_str());
|
||||
|
|
@ -577,9 +504,8 @@ static cl_int get_device_address_bits(const cl_device_id device,
|
|||
|
||||
static int get_offline_compiler_output(
|
||||
std::ifstream &ifs, const cl_device_id device, cl_uint deviceAddrSpaceSize,
|
||||
const bool openclCXX, const CompilationMode compilationMode,
|
||||
const std::string &bOptions, const std::string &kernelPath,
|
||||
const std::string &kernelNamePrefix)
|
||||
const CompilationMode compilationMode, const std::string &bOptions,
|
||||
const std::string &kernelPath, const std::string &kernelNamePrefix)
|
||||
{
|
||||
std::string sourceFilename =
|
||||
get_cl_source_filename_with_path(kernelPath, kernelNamePrefix);
|
||||
|
|
@ -599,12 +525,12 @@ static int get_offline_compiler_output(
|
|||
}
|
||||
else
|
||||
{
|
||||
int error = invoke_offline_compiler(
|
||||
device, deviceAddrSpaceSize, compilationMode, bOptions,
|
||||
sourceFilename, outputFilename, openclCXX);
|
||||
int error = invoke_offline_compiler(device, deviceAddrSpaceSize,
|
||||
compilationMode, bOptions,
|
||||
sourceFilename, outputFilename);
|
||||
if (error != CL_SUCCESS) return error;
|
||||
|
||||
// read output file
|
||||
// open output file for reading
|
||||
ifs.open(outputFilename.c_str(), std::ios::binary);
|
||||
if (!ifs.good())
|
||||
{
|
||||
|
|
@ -614,14 +540,33 @@ static int get_offline_compiler_output(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (compilationMode == kSpir_v && !gDisableSPIRVValidation)
|
||||
{
|
||||
std::string runString = gSPIRVValidator + " " + outputFilename;
|
||||
|
||||
int returnCode = system(runString.c_str());
|
||||
if (returnCode == -1)
|
||||
{
|
||||
log_error("Error: failed to invoke SPIR-V validator\n");
|
||||
return CL_COMPILE_PROGRAM_FAILURE;
|
||||
}
|
||||
else if (returnCode != 0)
|
||||
{
|
||||
log_error(
|
||||
"Failed to validate SPIR-V file %s: system() returned 0x%x\n",
|
||||
outputFilename.c_str(), returnCode);
|
||||
return CL_COMPILE_PROGRAM_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
static int create_single_kernel_helper_create_program_offline(
|
||||
cl_context context, cl_device_id device, cl_program *outProgram,
|
||||
unsigned int numKernelLines, const char *const *kernelProgram,
|
||||
const char *buildOptions, const bool openclCXX,
|
||||
CompilationMode compilationMode)
|
||||
const char *buildOptions, CompilationMode compilationMode)
|
||||
{
|
||||
if (kCacheModeDumpCl == gCompilationCacheMode)
|
||||
{
|
||||
|
|
@ -649,24 +594,12 @@ static int create_single_kernel_helper_create_program_offline(
|
|||
|
||||
std::ifstream ifs;
|
||||
error = get_offline_compiler_output(ifs, device, device_address_space_size,
|
||||
openclCXX, compilationMode, bOptions,
|
||||
compilationMode, bOptions,
|
||||
gCompilationCachePath, kernelName);
|
||||
if (error != CL_SUCCESS) return error;
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT
|
||||
// ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Only OpenCL C++ to SPIR-V compilation
|
||||
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
|
||||
if (openclCXX)
|
||||
{
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
ifs.seekg(0, ifs.end);
|
||||
int length = ifs.tellg();
|
||||
size_t length = static_cast<size_t>(ifs.tellg());
|
||||
ifs.seekg(0, ifs.beg);
|
||||
|
||||
// treat modifiedProgram as input for clCreateProgramWithBinary
|
||||
|
|
@ -748,8 +681,7 @@ static int create_single_kernel_helper_create_program_offline(
|
|||
static int create_single_kernel_helper_create_program(
|
||||
cl_context context, cl_device_id device, cl_program *outProgram,
|
||||
unsigned int numKernelLines, const char **kernelProgram,
|
||||
const char *buildOptions, const bool openclCXX,
|
||||
CompilationMode compilationMode)
|
||||
const char *buildOptions, CompilationMode compilationMode)
|
||||
{
|
||||
std::lock_guard<std::mutex> compiler_lock(gCompilerMutex);
|
||||
|
||||
|
|
@ -787,37 +719,39 @@ static int create_single_kernel_helper_create_program(
|
|||
{
|
||||
return create_single_kernel_helper_create_program_offline(
|
||||
context, device, outProgram, numKernelLines, kernelProgram,
|
||||
buildOptions, openclCXX, compilationMode);
|
||||
buildOptions, compilationMode);
|
||||
}
|
||||
}
|
||||
|
||||
int create_single_kernel_helper_create_program(
|
||||
cl_context context, cl_program *outProgram, unsigned int numKernelLines,
|
||||
const char **kernelProgram, const char *buildOptions, const bool openclCXX)
|
||||
int create_single_kernel_helper_create_program(cl_context context,
|
||||
cl_program *outProgram,
|
||||
unsigned int numKernelLines,
|
||||
const char **kernelProgram,
|
||||
const char *buildOptions)
|
||||
{
|
||||
return create_single_kernel_helper_create_program(
|
||||
context, NULL, outProgram, numKernelLines, kernelProgram, buildOptions,
|
||||
openclCXX, gCompilationMode);
|
||||
gCompilationMode);
|
||||
}
|
||||
|
||||
int create_single_kernel_helper_create_program_for_device(
|
||||
cl_context context, cl_device_id device, cl_program *outProgram,
|
||||
unsigned int numKernelLines, const char **kernelProgram,
|
||||
const char *buildOptions, const bool openclCXX)
|
||||
const char *buildOptions)
|
||||
{
|
||||
return create_single_kernel_helper_create_program(
|
||||
context, device, outProgram, numKernelLines, kernelProgram,
|
||||
buildOptions, openclCXX, gCompilationMode);
|
||||
buildOptions, gCompilationMode);
|
||||
}
|
||||
|
||||
int create_single_kernel_helper_with_build_options(
|
||||
cl_context context, cl_program *outProgram, cl_kernel *outKernel,
|
||||
unsigned int numKernelLines, const char **kernelProgram,
|
||||
const char *kernelName, const char *buildOptions, const bool openclCXX)
|
||||
const char *kernelName, const char *buildOptions)
|
||||
{
|
||||
return create_single_kernel_helper(context, outProgram, outKernel,
|
||||
numKernelLines, kernelProgram,
|
||||
kernelName, buildOptions, openclCXX);
|
||||
kernelName, buildOptions);
|
||||
}
|
||||
|
||||
// Creates and builds OpenCL C/C++ program, and creates a kernel
|
||||
|
|
@ -826,7 +760,7 @@ int create_single_kernel_helper(cl_context context, cl_program *outProgram,
|
|||
unsigned int numKernelLines,
|
||||
const char **kernelProgram,
|
||||
const char *kernelName,
|
||||
const char *buildOptions, const bool openclCXX)
|
||||
const char *buildOptions)
|
||||
{
|
||||
// For the logic that automatically adds -cl-std it is much cleaner if the
|
||||
// build options have RAII. This buffer will store the potentially updated
|
||||
|
|
@ -865,51 +799,14 @@ int create_single_kernel_helper(cl_context context, cl_program *outProgram,
|
|||
build_options_internal += cl_std;
|
||||
buildOptions = build_options_internal.c_str();
|
||||
}
|
||||
int error;
|
||||
// Create OpenCL C++ program
|
||||
if (openclCXX)
|
||||
int error = create_single_kernel_helper_create_program(
|
||||
context, outProgram, numKernelLines, kernelProgram, buildOptions);
|
||||
if (error != CL_SUCCESS)
|
||||
{
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT
|
||||
// ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Only OpenCL C++ to SPIR-V compilation
|
||||
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
|
||||
// Save global variable
|
||||
bool tempgCompilationCacheMode = gCompilationCacheMode;
|
||||
// Force OpenCL C++ -> SPIR-V compilation on every run
|
||||
gCompilationCacheMode = kCacheModeOverwrite;
|
||||
#endif
|
||||
error = create_openclcpp_program(context, outProgram, numKernelLines,
|
||||
kernelProgram, buildOptions);
|
||||
if (error != CL_SUCCESS)
|
||||
{
|
||||
log_error("Create program failed: %d, line: %d\n", error, __LINE__);
|
||||
return error;
|
||||
}
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT
|
||||
// ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
|
||||
// Restore global variables
|
||||
gCompilationCacheMode = tempgCompilationCacheMode;
|
||||
log_info("WARNING: KERNEL %s WAS ONLY COMPILED TO SPIR-V\n",
|
||||
kernelName);
|
||||
log_error("Create program failed: %d, line: %d\n", error, __LINE__);
|
||||
return error;
|
||||
#endif
|
||||
}
|
||||
// Create OpenCL C program
|
||||
else
|
||||
{
|
||||
error = create_single_kernel_helper_create_program(
|
||||
context, outProgram, numKernelLines, kernelProgram, buildOptions);
|
||||
if (error != CL_SUCCESS)
|
||||
{
|
||||
log_error("Create program failed: %d, line: %d\n", error, __LINE__);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove offline-compiler-only build options
|
||||
std::string newBuildOptions;
|
||||
if (buildOptions != NULL)
|
||||
|
|
@ -930,18 +827,6 @@ int create_single_kernel_helper(cl_context context, cl_program *outProgram,
|
|||
kernelName, newBuildOptions.c_str());
|
||||
}
|
||||
|
||||
// Creates OpenCL C++ program
|
||||
int create_openclcpp_program(cl_context context, cl_program *outProgram,
|
||||
unsigned int numKernelLines,
|
||||
const char **kernelProgram,
|
||||
const char *buildOptions)
|
||||
{
|
||||
// Create program
|
||||
return create_single_kernel_helper_create_program(
|
||||
context, NULL, outProgram, numKernelLines, kernelProgram, buildOptions,
|
||||
true, kSpir_v);
|
||||
}
|
||||
|
||||
// Builds OpenCL C/C++ program and creates
|
||||
int build_program_create_kernel_helper(
|
||||
cl_context context, cl_program *outProgram, cl_kernel *outKernel,
|
||||
|
|
@ -1361,7 +1246,7 @@ int is_image_format_supported(cl_context context, cl_mem_flags flags,
|
|||
list = (cl_image_format *)malloc(count * sizeof(cl_image_format));
|
||||
if (NULL == list)
|
||||
{
|
||||
log_error("Error: unable to allocate %ld byte buffer for image format "
|
||||
log_error("Error: unable to allocate %zu byte buffer for image format "
|
||||
"list at %s:%d (err = %d)\n",
|
||||
count * sizeof(cl_image_format), __FILE__, __LINE__, err);
|
||||
return 0;
|
||||
|
|
@ -1776,8 +1661,10 @@ Version get_device_latest_cl_c_version(cl_device_id device)
|
|||
Version max_supported_cl_c_version{};
|
||||
for (const auto &name_version : name_versions)
|
||||
{
|
||||
Version current_version{ CL_VERSION_MAJOR(name_version.version),
|
||||
CL_VERSION_MINOR(name_version.version) };
|
||||
Version current_version{
|
||||
static_cast<int>(CL_VERSION_MAJOR(name_version.version)),
|
||||
static_cast<int>(CL_VERSION_MINOR(name_version.version))
|
||||
};
|
||||
max_supported_cl_c_version =
|
||||
(current_version > max_supported_cl_c_version)
|
||||
? current_version
|
||||
|
|
@ -1822,7 +1709,7 @@ Version get_max_OpenCL_C_for_context(cl_context context)
|
|||
else
|
||||
{
|
||||
current_version =
|
||||
(std::min)(device_version, current_version);
|
||||
std::min(device_version, current_version);
|
||||
}
|
||||
});
|
||||
return current_version;
|
||||
|
|
@ -1860,8 +1747,10 @@ bool device_supports_cl_c_version(cl_device_id device, Version version)
|
|||
|
||||
for (const auto &name_version : name_versions)
|
||||
{
|
||||
Version current_version{ CL_VERSION_MAJOR(name_version.version),
|
||||
CL_VERSION_MINOR(name_version.version) };
|
||||
Version current_version{
|
||||
static_cast<int>(CL_VERSION_MAJOR(name_version.version)),
|
||||
static_cast<int>(CL_VERSION_MINOR(name_version.version))
|
||||
};
|
||||
if (current_version == version)
|
||||
{
|
||||
return true;
|
||||
|
|
@ -1891,3 +1780,26 @@ bool poll_until(unsigned timeout_ms, unsigned interval_ms,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool device_supports_double(cl_device_id device)
|
||||
{
|
||||
if (is_extension_available(device, "cl_khr_fp64"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl_device_fp_config double_fp_config;
|
||||
cl_int err = clGetDeviceInfo(device, CL_DEVICE_DOUBLE_FP_CONFIG,
|
||||
sizeof(double_fp_config),
|
||||
&double_fp_config, nullptr);
|
||||
test_error(err,
|
||||
"clGetDeviceInfo for CL_DEVICE_DOUBLE_FP_CONFIG failed");
|
||||
return double_fp_config != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool device_supports_half(cl_device_id device)
|
||||
{
|
||||
return is_extension_available(device, "cl_khr_fp16");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,24 +72,21 @@ extern int
|
|||
create_single_kernel_helper(cl_context context, cl_program *outProgram,
|
||||
cl_kernel *outKernel, unsigned int numKernelLines,
|
||||
const char **kernelProgram, const char *kernelName,
|
||||
const char *buildOptions = NULL,
|
||||
const bool openclCXX = false);
|
||||
const char *buildOptions = NULL);
|
||||
|
||||
extern int create_single_kernel_helper_with_build_options(
|
||||
cl_context context, cl_program *outProgram, cl_kernel *outKernel,
|
||||
unsigned int numKernelLines, const char **kernelProgram,
|
||||
const char *kernelName, const char *buildOptions,
|
||||
const bool openclCXX = false);
|
||||
const char *kernelName, const char *buildOptions);
|
||||
|
||||
extern int create_single_kernel_helper_create_program(
|
||||
cl_context context, cl_program *outProgram, unsigned int numKernelLines,
|
||||
const char **kernelProgram, const char *buildOptions = NULL,
|
||||
const bool openclCXX = false);
|
||||
const char **kernelProgram, const char *buildOptions = NULL);
|
||||
|
||||
extern int create_single_kernel_helper_create_program_for_device(
|
||||
cl_context context, cl_device_id device, cl_program *outProgram,
|
||||
unsigned int numKernelLines, const char **kernelProgram,
|
||||
const char *buildOptions = NULL, const bool openclCXX = false);
|
||||
const char *buildOptions = NULL);
|
||||
|
||||
/* Creates OpenCL C++ program. This one must be used for creating OpenCL C++
|
||||
* program. */
|
||||
|
|
@ -181,7 +178,7 @@ cl_device_fp_config get_default_rounding_mode(cl_device_id device);
|
|||
}
|
||||
|
||||
#define PASSIVE_REQUIRE_FP16_SUPPORT(device) \
|
||||
if (!is_extension_available(device, "cl_khr_fp16")) \
|
||||
if (!device_supports_half(device)) \
|
||||
{ \
|
||||
log_info( \
|
||||
"\n\tNote: device does not support fp16. Skipping test...\n"); \
|
||||
|
|
@ -211,4 +208,10 @@ bool device_supports_cl_c_version(cl_device_id device, Version version);
|
|||
bool poll_until(unsigned timeout_ms, unsigned interval_ms,
|
||||
std::function<bool()> fn);
|
||||
|
||||
// Checks whether the device supports double data types
|
||||
bool device_supports_double(cl_device_id device);
|
||||
|
||||
// Checks whether the device supports half data types
|
||||
bool device_supports_half(cl_device_id device);
|
||||
|
||||
#endif // _kernelHelpers_h
|
||||
|
|
|
|||
|
|
@ -277,3 +277,5 @@ double genrand_res53(MTdata d)
|
|||
unsigned long a = genrand_int32(d) >> 5, b = genrand_int32(d) >> 6;
|
||||
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
|
||||
}
|
||||
|
||||
bool genrand_bool(MTdata d) { return ((cl_uint)genrand_int32(d) & 1); }
|
||||
|
|
|
|||
|
|
@ -90,24 +90,46 @@ double genrand_res53(MTdata /*data*/);
|
|||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <cassert>
|
||||
/* generates a random boolean */
|
||||
bool genrand_bool(MTdata /*data*/);
|
||||
|
||||
struct MTdataHolder
|
||||
{
|
||||
MTdataHolder(cl_uint seed)
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
class MTdataHolder {
|
||||
public:
|
||||
MTdataHolder() = default;
|
||||
explicit MTdataHolder(cl_uint seed)
|
||||
{
|
||||
m_mtdata = init_genrand(seed);
|
||||
assert(m_mtdata != nullptr);
|
||||
}
|
||||
|
||||
MTdataHolder(MTdata mtdata): m_mtdata(mtdata) {}
|
||||
// Forbid copy.
|
||||
MTdataHolder(const MTdataHolder&) = delete;
|
||||
MTdataHolder& operator=(const MTdataHolder&) = delete;
|
||||
|
||||
~MTdataHolder() { free_mtdata(m_mtdata); }
|
||||
// Support move semantics.
|
||||
MTdataHolder(MTdataHolder&& h) { std::swap(m_mtdata, h.m_mtdata); }
|
||||
MTdataHolder& operator=(MTdataHolder&& h)
|
||||
{
|
||||
std::swap(m_mtdata, h.m_mtdata);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator MTdata() const { return m_mtdata; }
|
||||
~MTdataHolder()
|
||||
{
|
||||
if (m_mtdata) free_mtdata(m_mtdata);
|
||||
}
|
||||
|
||||
operator MTdata() const
|
||||
{
|
||||
assert(m_mtdata && "Object wasn't initialised");
|
||||
return m_mtdata;
|
||||
}
|
||||
|
||||
private:
|
||||
MTdata m_mtdata;
|
||||
MTdata m_mtdata = nullptr;
|
||||
};
|
||||
|
||||
#endif // #ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ std::string exe_path()
|
|||
exit(2);
|
||||
}; // if
|
||||
|
||||
if (len < path.size())
|
||||
if (static_cast<size_t>(len) < path.size())
|
||||
{
|
||||
// We got the path.
|
||||
path.resize(len);
|
||||
|
|
@ -333,9 +333,6 @@ std::string exe_dir()
|
|||
|
||||
|
||||
#include <windows.h>
|
||||
#if defined(max)
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
|
@ -404,7 +401,8 @@ std::string exe_path()
|
|||
for (;;)
|
||||
{
|
||||
|
||||
DWORD len = GetModuleFileNameA(NULL, &path.front(), path.size());
|
||||
DWORD len = GetModuleFileNameA(NULL, &path.front(),
|
||||
static_cast<DWORD>(path.size()));
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,11 +28,14 @@
|
|||
using namespace std;
|
||||
|
||||
#define DEFAULT_COMPILATION_PROGRAM "cl_offline_compiler"
|
||||
#define DEFAULT_SPIRV_VALIDATOR "spirv-val"
|
||||
|
||||
CompilationMode gCompilationMode = kOnline;
|
||||
CompilationCacheMode gCompilationCacheMode = kCacheModeCompileIfAbsent;
|
||||
std::string gCompilationCachePath = ".";
|
||||
std::string gCompilationProgram = DEFAULT_COMPILATION_PROGRAM;
|
||||
bool gDisableSPIRVValidation = false;
|
||||
std::string gSPIRVValidator = DEFAULT_SPIRV_VALIDATOR;
|
||||
|
||||
void helpInfo()
|
||||
{
|
||||
|
|
@ -62,7 +65,14 @@ For offline compilation (binary and spir-v modes) only:
|
|||
Path for offline compiler output and CL source
|
||||
--compilation-program <prog>
|
||||
Program to use for offline compilation, defaults to:
|
||||
)" DEFAULT_COMPILATION_PROGRAM "\n\n");
|
||||
)" DEFAULT_COMPILATION_PROGRAM R"(
|
||||
|
||||
For spir-v mode only:
|
||||
--disable-spirv-validation
|
||||
Disable validation of SPIR-V using the SPIR-V validator
|
||||
--spirv-validator
|
||||
Path for SPIR-V validator, defaults to )" DEFAULT_SPIRV_VALIDATOR "\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
int parseCustomParam(int argc, const char *argv[], const char *ignore)
|
||||
|
|
@ -198,6 +208,26 @@ int parseCustomParam(int argc, const char *argv[], const char *ignore)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "--disable-spirv-validation"))
|
||||
{
|
||||
delArg++;
|
||||
gDisableSPIRVValidation = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--spirv-validator"))
|
||||
{
|
||||
delArg++;
|
||||
if ((i + 1) < argc)
|
||||
{
|
||||
delArg++;
|
||||
gSPIRVValidator = argv[i + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("Program argument for --spirv-validator was not "
|
||||
"specified.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// cleaning parameters from argv tab
|
||||
for (int j = i; j < argc - delArg; j++) argv[j] = argv[j + delArg];
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ extern CompilationMode gCompilationMode;
|
|||
extern CompilationCacheMode gCompilationCacheMode;
|
||||
extern std::string gCompilationCachePath;
|
||||
extern std::string gCompilationProgram;
|
||||
extern bool gDisableSPIRVValidation;
|
||||
extern std::string gSPIRVValidator;
|
||||
|
||||
extern int parseCustomParam(int argc, const char *argv[],
|
||||
const char *ignore = 0);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <vector>
|
||||
|
||||
static bool findProperty(const std::vector<cl_properties>& props,
|
||||
|
|
@ -97,14 +98,15 @@ int compareProperties(const std::vector<cl_properties>& queried,
|
|||
|
||||
if (!found)
|
||||
{
|
||||
log_error("ERROR: expected property 0x%x not found!\n",
|
||||
log_error("ERROR: expected property 0x%" PRIx64 " not found!\n",
|
||||
check_prop);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
else if (check_value != queried_value)
|
||||
{
|
||||
log_error("ERROR: mis-matched value for property 0x%x: wanted "
|
||||
"0x%x, got 0x%x\n",
|
||||
log_error("ERROR: mis-matched value for property 0x%" PRIx64
|
||||
": wanted "
|
||||
"0x%" PRIx64 ", got 0x%" PRIx64 "\n",
|
||||
check_prop, check_value, queried_value);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
|
@ -113,7 +115,7 @@ int compareProperties(const std::vector<cl_properties>& queried,
|
|||
if (queried.size() > check.size())
|
||||
{
|
||||
log_error("ERROR: all properties found but there are extra "
|
||||
"properties: expected %d, got %d.\n",
|
||||
"properties: expected %zu, got %zu.\n",
|
||||
check.size(), queried.size());
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ RoundingMode set_round(RoundingMode r, Type outType)
|
|||
const int *p = int_rounds;
|
||||
if (outType == kfloat || outType == kdouble) p = flt_rounds;
|
||||
|
||||
int fpscr = 0;
|
||||
int64_t fpscr = 0;
|
||||
RoundingMode oldRound = get_round();
|
||||
|
||||
_FPU_GETCW(fpscr);
|
||||
|
|
@ -59,7 +59,7 @@ RoundingMode set_round(RoundingMode r, Type outType)
|
|||
|
||||
RoundingMode get_round(void)
|
||||
{
|
||||
int fpscr;
|
||||
int64_t fpscr;
|
||||
int oldRound;
|
||||
|
||||
_FPU_GETCW(fpscr);
|
||||
|
|
@ -203,13 +203,13 @@ void *FlushToZero(void)
|
|||
#if defined(__APPLE__) || defined(__linux__) || defined(_WIN32)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_MSC_VER)
|
||||
union {
|
||||
int i;
|
||||
unsigned int i;
|
||||
void *p;
|
||||
} u = { _mm_getcsr() };
|
||||
_mm_setcsr(u.i | 0x8040);
|
||||
return u.p;
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
int fpscr;
|
||||
int64_t fpscr;
|
||||
_FPU_GETCW(fpscr);
|
||||
_FPU_SETCW(fpscr | FPSCR_FZ);
|
||||
return NULL;
|
||||
|
|
@ -239,7 +239,7 @@ void UnFlushToZero(void *p)
|
|||
} u = { p };
|
||||
_mm_setcsr(u.i);
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
int fpscr;
|
||||
int64_t fpscr;
|
||||
_FPU_GETCW(fpscr);
|
||||
_FPU_SETCW(fpscr & ~FPSCR_FZ);
|
||||
#elif defined(__PPC__)
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@
|
|||
#ifndef __ROUNDING_MODE_H__
|
||||
#define __ROUNDING_MODE_H__
|
||||
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#if (defined(_WIN32) && defined(_MSC_VER))
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include "threadTesting.h"
|
||||
#include "errorHelpers.h"
|
||||
#include "kernelHelpers.h"
|
||||
#include "fpcontrol.h"
|
||||
|
|
@ -60,6 +59,54 @@ bool gCoreILProgram = true;
|
|||
|
||||
#define DEFAULT_NUM_ELEMENTS 0x4000
|
||||
|
||||
static int saveResultsToJson(const char *suiteName, test_definition testList[],
|
||||
unsigned char selectedTestList[],
|
||||
test_status resultTestList[], int testNum)
|
||||
{
|
||||
char *fileName = getenv("CL_CONFORMANCE_RESULTS_FILENAME");
|
||||
if (fileName == nullptr)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
FILE *file = fopen(fileName, "w");
|
||||
if (NULL == file)
|
||||
{
|
||||
log_error("ERROR: Failed to open '%s' for writing results.\n",
|
||||
fileName);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char *save_map[] = { "success", "failure" };
|
||||
const char *result_map[] = { "pass", "fail", "skip" };
|
||||
const char *linebreak[] = { "", ",\n" };
|
||||
int add_linebreak = 0;
|
||||
|
||||
fprintf(file, "{\n");
|
||||
fprintf(file, "\t\"cmd\": \"%s\",\n", suiteName);
|
||||
fprintf(file, "\t\"results\": {\n");
|
||||
|
||||
for (int i = 0; i < testNum; ++i)
|
||||
{
|
||||
if (selectedTestList[i])
|
||||
{
|
||||
fprintf(file, "%s\t\t\"%s\": \"%s\"", linebreak[add_linebreak],
|
||||
testList[i].name, result_map[(int)resultTestList[i]]);
|
||||
add_linebreak = 1;
|
||||
}
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
|
||||
fprintf(file, "\t}\n");
|
||||
fprintf(file, "}\n");
|
||||
|
||||
int ret = fclose(file) ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
|
||||
log_info("Saving results to %s: %s!\n", fileName, save_map[ret]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int runTestHarness(int argc, const char *argv[], int testNum,
|
||||
test_definition testList[], int forceNoContextCreation,
|
||||
cl_command_queue_properties queueProps)
|
||||
|
|
@ -68,19 +115,28 @@ int runTestHarness(int argc, const char *argv[], int testNum,
|
|||
forceNoContextCreation, queueProps, NULL);
|
||||
}
|
||||
|
||||
int skip_init_info(int count)
|
||||
int suite_did_not_pass_init(const char *suiteName, test_status status,
|
||||
int testNum, test_definition testList[])
|
||||
{
|
||||
log_info("Test skipped while initialization\n");
|
||||
log_info("SKIPPED %d of %d tests.\n", count, count);
|
||||
return EXIT_SUCCESS;
|
||||
std::vector<unsigned char> selectedTestList(testNum, 1);
|
||||
std::vector<test_status> resultTestList(testNum, status);
|
||||
|
||||
int ret = saveResultsToJson(suiteName, testList, selectedTestList.data(),
|
||||
resultTestList.data(), testNum);
|
||||
|
||||
log_info("Test %s while initialization\n",
|
||||
status == TEST_SKIP ? "skipped" : "failed");
|
||||
log_info("%s %d of %d tests.\n", status == TEST_SKIP ? "SKIPPED" : "FAILED",
|
||||
testNum, testNum);
|
||||
|
||||
if (ret != EXIT_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return status == TEST_SKIP ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int fail_init_info(int count)
|
||||
{
|
||||
log_info("Test failed while initialization\n");
|
||||
log_info("FAILED %d of %d tests.\n", count, count);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
void version_expected_info(const char *test_name, const char *api_name,
|
||||
const char *expected_version,
|
||||
const char *device_version)
|
||||
|
|
@ -470,6 +526,7 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
log_error("Invalid device address bit size returned by device.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
const char *suiteName = argv[0];
|
||||
if (gCompilationMode == kSpir_v)
|
||||
{
|
||||
test_status spirv_readiness = check_spirv_compilation_readiness(device);
|
||||
|
|
@ -478,9 +535,15 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
switch (spirv_readiness)
|
||||
{
|
||||
case TEST_PASS: break;
|
||||
case TEST_FAIL: return fail_init_info(testNum);
|
||||
case TEST_SKIP: return skip_init_info(testNum);
|
||||
case TEST_SKIPPED_ITSELF: return skip_init_info(testNum);
|
||||
case TEST_FAIL:
|
||||
return suite_did_not_pass_init(suiteName, TEST_FAIL,
|
||||
testNum, testList);
|
||||
case TEST_SKIP:
|
||||
return suite_did_not_pass_init(suiteName, TEST_SKIP,
|
||||
testNum, testList);
|
||||
case TEST_SKIPPED_ITSELF:
|
||||
return suite_did_not_pass_init(suiteName, TEST_SKIP,
|
||||
testNum, testList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -492,9 +555,15 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
switch (status)
|
||||
{
|
||||
case TEST_PASS: break;
|
||||
case TEST_FAIL: return fail_init_info(testNum);
|
||||
case TEST_SKIP: return skip_init_info(testNum);
|
||||
case TEST_SKIPPED_ITSELF: return skip_init_info(testNum);
|
||||
case TEST_FAIL:
|
||||
return suite_did_not_pass_init(suiteName, TEST_FAIL, testNum,
|
||||
testList);
|
||||
case TEST_SKIP:
|
||||
return suite_did_not_pass_init(suiteName, TEST_SKIP, testNum,
|
||||
testList);
|
||||
case TEST_SKIPPED_ITSELF:
|
||||
return suite_did_not_pass_init(suiteName, TEST_SKIP, testNum,
|
||||
testList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -574,49 +643,6 @@ static int find_matching_tests(test_definition testList[],
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int saveResultsToJson(const char *fileName, const char *suiteName,
|
||||
test_definition testList[],
|
||||
unsigned char selectedTestList[],
|
||||
test_status resultTestList[], int testNum)
|
||||
{
|
||||
FILE *file = fopen(fileName, "w");
|
||||
if (NULL == file)
|
||||
{
|
||||
log_error("ERROR: Failed to open '%s' for writing results.\n",
|
||||
fileName);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char *save_map[] = { "success", "failure" };
|
||||
const char *result_map[] = { "pass", "fail", "skip" };
|
||||
const char *linebreak[] = { "", ",\n" };
|
||||
int add_linebreak = 0;
|
||||
|
||||
fprintf(file, "{\n");
|
||||
fprintf(file, "\t\"cmd\": \"%s\",\n", suiteName);
|
||||
fprintf(file, "\t\"results\": {\n");
|
||||
|
||||
for (int i = 0; i < testNum; ++i)
|
||||
{
|
||||
if (selectedTestList[i])
|
||||
{
|
||||
fprintf(file, "%s\t\t\"%s\": \"%s\"", linebreak[add_linebreak],
|
||||
testList[i].name, result_map[(int)resultTestList[i]]);
|
||||
add_linebreak = 1;
|
||||
}
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
|
||||
fprintf(file, "\t}\n");
|
||||
fprintf(file, "}\n");
|
||||
|
||||
int ret = fclose(file) ? 1 : 0;
|
||||
|
||||
log_info("Saving results to %s: %s!\n", fileName, save_map[ret]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void print_results(int failed, int count, const char *name)
|
||||
{
|
||||
if (count < failed)
|
||||
|
|
@ -658,7 +684,6 @@ int parseAndCallCommandLineTests(int argc, const char *argv[],
|
|||
int ret = EXIT_SUCCESS;
|
||||
|
||||
unsigned char *selectedTestList = (unsigned char *)calloc(testNum, 1);
|
||||
test_status *resultTestList = NULL;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
|
|
@ -697,24 +722,19 @@ int parseAndCallCommandLineTests(int argc, const char *argv[],
|
|||
|
||||
if (ret == EXIT_SUCCESS)
|
||||
{
|
||||
resultTestList =
|
||||
(test_status *)calloc(testNum, sizeof(*resultTestList));
|
||||
std::vector<test_status> resultTestList(testNum, TEST_PASS);
|
||||
|
||||
callTestFunctions(testList, selectedTestList, resultTestList, testNum,
|
||||
device, forceNoContextCreation, num_elements,
|
||||
callTestFunctions(testList, selectedTestList, resultTestList.data(),
|
||||
testNum, device, forceNoContextCreation, num_elements,
|
||||
queueProps);
|
||||
|
||||
print_results(gFailCount, gTestCount, "sub-test");
|
||||
print_results(gTestsFailed, gTestsFailed + gTestsPassed, "test");
|
||||
|
||||
char *filename = getenv("CL_CONFORMANCE_RESULTS_FILENAME");
|
||||
if (filename != NULL)
|
||||
{
|
||||
ret = saveResultsToJson(filename, argv[0], testList,
|
||||
selectedTestList, resultTestList, testNum);
|
||||
}
|
||||
ret = saveResultsToJson(argv[0], testList, selectedTestList,
|
||||
resultTestList.data(), testNum);
|
||||
|
||||
if (std::any_of(resultTestList, resultTestList + testNum,
|
||||
if (std::any_of(resultTestList.begin(), resultTestList.end(),
|
||||
[](test_status result) {
|
||||
switch (result)
|
||||
{
|
||||
|
|
@ -730,7 +750,6 @@ int parseAndCallCommandLineTests(int argc, const char *argv[],
|
|||
}
|
||||
|
||||
free(selectedTestList);
|
||||
free(resultTestList);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -783,6 +802,14 @@ test_status callSingleTestFunction(test_definition test,
|
|||
return TEST_SKIP;
|
||||
}
|
||||
|
||||
if (!check_functions_for_offline_compiler(test.name))
|
||||
{
|
||||
log_info("Subtest %s tests is not supported in offline compiler "
|
||||
"execution path!\n",
|
||||
test.name);
|
||||
return TEST_SKIP;
|
||||
}
|
||||
|
||||
/* Create a context to work with, unless we're told not to */
|
||||
if (!forceNoContextCreation)
|
||||
{
|
||||
|
|
@ -812,14 +839,12 @@ test_status callSingleTestFunction(test_definition test,
|
|||
if (queue == NULL)
|
||||
{
|
||||
print_error(error, "Unable to create testing command queue");
|
||||
clReleaseContext(context);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run the test and print the result */
|
||||
error = check_functions_for_offline_compiler(test.name, deviceToUse);
|
||||
test_missing_support_offline_cmpiler(error, test.name);
|
||||
|
||||
if (test.func == NULL)
|
||||
{
|
||||
// Skip unimplemented test, can happen when all of the tests are
|
||||
|
|
@ -861,7 +886,7 @@ test_status callSingleTestFunction(test_definition test,
|
|||
int error = clFinish(queue);
|
||||
if (error)
|
||||
{
|
||||
log_error("clFinish failed: %d", error);
|
||||
log_error("clFinish failed: %s\n", IGetErrorString(error));
|
||||
status = TEST_FAIL;
|
||||
}
|
||||
clReleaseCommandQueue(queue);
|
||||
|
|
@ -1172,7 +1197,7 @@ cl_platform_id getPlatformFromDevice(cl_device_id deviceID)
|
|||
|
||||
void PrintArch(void)
|
||||
{
|
||||
vlog("sizeof( void*) = %ld\n", sizeof(void *));
|
||||
vlog("sizeof( void*) = %zu\n", sizeof(void *));
|
||||
#if defined(__ppc__)
|
||||
vlog("ARCH:\tppc\n");
|
||||
#elif defined(__ppc64__)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#ifndef _testHarness_h
|
||||
#define _testHarness_h
|
||||
|
||||
#include "threadTesting.h"
|
||||
#include "clImageHelper.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
|
@ -67,9 +66,12 @@ Version get_device_cl_version(cl_device_id device);
|
|||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
typedef int (*test_function_pointer)(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
|
||||
typedef struct test_definition
|
||||
{
|
||||
basefn func;
|
||||
test_function_pointer func;
|
||||
const char *name;
|
||||
Version min_version;
|
||||
} test_definition;
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "compat.h"
|
||||
#include "threadTesting.h"
|
||||
#include "errorHelpers.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if 0 // Disabed for now
|
||||
|
||||
typedef struct
|
||||
{
|
||||
basefn mFunction;
|
||||
cl_device_id mDevice;
|
||||
cl_context mContext;
|
||||
int mNumElements;
|
||||
} TestFnArgs;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Thread-based testing. Spawns a new thread to run the given test function,
|
||||
// then waits for it to complete. The entire idea is that, if the thread crashes,
|
||||
// we can catch it and report it as a failure instead of crashing the entire suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void *test_thread_wrapper( void *data )
|
||||
{
|
||||
TestFnArgs *args;
|
||||
int retVal;
|
||||
cl_context context;
|
||||
|
||||
args = (TestFnArgs *)data;
|
||||
|
||||
/* Create a new context to use (contexts can't cross threads) */
|
||||
context = clCreateContext(NULL, args->mDeviceGroup);
|
||||
if( context == NULL )
|
||||
{
|
||||
log_error("clCreateContext failed for new thread\n");
|
||||
return (void *)(-1);
|
||||
}
|
||||
|
||||
/* Call function */
|
||||
retVal = args->mFunction( args->mDeviceGroup, args->mDevice, context, args->mNumElements );
|
||||
|
||||
clReleaseContext( context );
|
||||
|
||||
return (void *)retVal;
|
||||
}
|
||||
|
||||
int test_threaded_function( basefn fnToTest, cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
|
||||
{
|
||||
int error;
|
||||
pthread_t threadHdl;
|
||||
void *retVal;
|
||||
TestFnArgs args;
|
||||
|
||||
|
||||
args.mFunction = fnToTest;
|
||||
args.mDeviceGroup = deviceGroup;
|
||||
args.mDevice = device;
|
||||
args.mContext = context;
|
||||
args.mNumElements = numElements;
|
||||
|
||||
|
||||
error = pthread_create( &threadHdl, NULL, test_thread_wrapper, (void *)&args );
|
||||
if( error != 0 )
|
||||
{
|
||||
log_error( "ERROR: Unable to create thread for testing!\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Thread has been started, now just wait for it to complete (or crash) */
|
||||
error = pthread_join( threadHdl, &retVal );
|
||||
if( error != 0 )
|
||||
{
|
||||
log_error( "ERROR: Unable to join testing thread!\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)((intptr_t)retVal);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef _threadTesting_h
|
||||
#define _threadTesting_h
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenCL/opencl.h>
|
||||
#else
|
||||
#include <CL/opencl.h>
|
||||
#endif
|
||||
|
||||
typedef int (*basefn)(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_threaded_function(basefn fnToTest, cl_device_id device,
|
||||
cl_context context, cl_command_queue queue,
|
||||
int numElements);
|
||||
|
||||
#endif // _threadTesting_h
|
||||
|
|
@ -16,123 +16,135 @@
|
|||
#ifndef _typeWrappers_h
|
||||
#define _typeWrappers_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
#include <stdio.h>
|
||||
#include "mt19937.h"
|
||||
#include "errorHelpers.h"
|
||||
#include "kernelHelpers.h"
|
||||
|
||||
/* cl_context wrapper */
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
class clContextWrapper {
|
||||
public:
|
||||
clContextWrapper() { mContext = NULL; }
|
||||
clContextWrapper(cl_context program) { mContext = program; }
|
||||
~clContextWrapper()
|
||||
namespace wrapper_details {
|
||||
|
||||
// clRetain*() and clRelease*() functions share the same type.
|
||||
template <typename T> // T should be cl_context, cl_program, ...
|
||||
using RetainReleaseType = cl_int CL_API_CALL(T);
|
||||
|
||||
// A generic wrapper class that follows OpenCL retain/release semantics.
|
||||
//
|
||||
// This Wrapper class implement copy and move semantics, which makes it
|
||||
// compatible with standard containers for example.
|
||||
//
|
||||
// Template parameters:
|
||||
// - T is the cl_* type (e.g. cl_context, cl_program, ...)
|
||||
// - Retain is the clRetain* function (e.g. clRetainContext, ...)
|
||||
// - Release is the clRelease* function (e.g. clReleaseContext, ...)
|
||||
template <typename T, RetainReleaseType<T> Retain, RetainReleaseType<T> Release>
|
||||
class Wrapper {
|
||||
static_assert(std::is_pointer<T>::value, "T should be a pointer type.");
|
||||
T object = nullptr;
|
||||
|
||||
void retain()
|
||||
{
|
||||
if (mContext != NULL) clReleaseContext(mContext);
|
||||
if (!object) return;
|
||||
|
||||
auto err = Retain(object);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
print_error(err, "clRetain*() failed");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
clContextWrapper &operator=(const cl_context &rhs)
|
||||
void release()
|
||||
{
|
||||
mContext = rhs;
|
||||
if (!object) return;
|
||||
|
||||
auto err = Release(object);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
print_error(err, "clRelease*() failed");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Wrapper() = default;
|
||||
|
||||
// On initialisation, assume the object has a refcount of one.
|
||||
Wrapper(T object): object(object) {}
|
||||
|
||||
// On assignment, assume the object has a refcount of one.
|
||||
Wrapper &operator=(T rhs)
|
||||
{
|
||||
reset(rhs);
|
||||
return *this;
|
||||
}
|
||||
operator cl_context() const { return mContext; }
|
||||
|
||||
cl_context *operator&() { return &mContext; }
|
||||
|
||||
bool operator==(const cl_context &rhs) { return mContext == rhs; }
|
||||
|
||||
protected:
|
||||
cl_context mContext;
|
||||
};
|
||||
|
||||
/* cl_program wrapper */
|
||||
|
||||
class clProgramWrapper {
|
||||
public:
|
||||
clProgramWrapper() { mProgram = NULL; }
|
||||
clProgramWrapper(cl_program program) { mProgram = program; }
|
||||
~clProgramWrapper()
|
||||
// Copy semantics, increase retain count.
|
||||
Wrapper(Wrapper const &w) { *this = w; }
|
||||
Wrapper &operator=(Wrapper const &w)
|
||||
{
|
||||
if (mProgram != NULL) clReleaseProgram(mProgram);
|
||||
}
|
||||
|
||||
clProgramWrapper &operator=(const cl_program &rhs)
|
||||
{
|
||||
mProgram = rhs;
|
||||
reset(w.object);
|
||||
retain();
|
||||
return *this;
|
||||
}
|
||||
operator cl_program() const { return mProgram; }
|
||||
|
||||
cl_program *operator&() { return &mProgram; }
|
||||
|
||||
bool operator==(const cl_program &rhs) { return mProgram == rhs; }
|
||||
|
||||
protected:
|
||||
cl_program mProgram;
|
||||
};
|
||||
|
||||
/* cl_kernel wrapper */
|
||||
|
||||
class clKernelWrapper {
|
||||
public:
|
||||
clKernelWrapper() { mKernel = NULL; }
|
||||
clKernelWrapper(cl_kernel kernel) { mKernel = kernel; }
|
||||
~clKernelWrapper()
|
||||
// Move semantics, directly take ownership.
|
||||
Wrapper(Wrapper &&w) { *this = std::move(w); }
|
||||
Wrapper &operator=(Wrapper &&w)
|
||||
{
|
||||
if (mKernel != NULL) clReleaseKernel(mKernel);
|
||||
}
|
||||
|
||||
clKernelWrapper &operator=(const cl_kernel &rhs)
|
||||
{
|
||||
mKernel = rhs;
|
||||
reset(w.object);
|
||||
w.object = nullptr;
|
||||
return *this;
|
||||
}
|
||||
operator cl_kernel() const { return mKernel; }
|
||||
|
||||
cl_kernel *operator&() { return &mKernel; }
|
||||
~Wrapper() { reset(); }
|
||||
|
||||
bool operator==(const cl_kernel &rhs) { return mKernel == rhs; }
|
||||
|
||||
protected:
|
||||
cl_kernel mKernel;
|
||||
};
|
||||
|
||||
/* cl_mem (stream) wrapper */
|
||||
|
||||
class clMemWrapper {
|
||||
public:
|
||||
clMemWrapper() { mMem = NULL; }
|
||||
clMemWrapper(cl_mem mem) { mMem = mem; }
|
||||
~clMemWrapper()
|
||||
// Release the existing object, if any, and own the new one, if any.
|
||||
void reset(T new_object = nullptr)
|
||||
{
|
||||
if (mMem != NULL) clReleaseMemObject(mMem);
|
||||
release();
|
||||
object = new_object;
|
||||
}
|
||||
|
||||
clMemWrapper &operator=(const cl_mem &rhs)
|
||||
{
|
||||
mMem = rhs;
|
||||
return *this;
|
||||
}
|
||||
operator cl_mem() const { return mMem; }
|
||||
operator T() const { return object; }
|
||||
|
||||
cl_mem *operator&() { return &mMem; }
|
||||
|
||||
bool operator==(const cl_mem &rhs) { return mMem == rhs; }
|
||||
|
||||
protected:
|
||||
cl_mem mMem;
|
||||
// Ideally this function should not exist as it breaks encapsulation by
|
||||
// allowing external mutation of the Wrapper internal state. However, too
|
||||
// much code currently relies on this. For example, instead of using T* as
|
||||
// output parameters, existing code can be updated to use Wrapper& instead.
|
||||
T *operator&() { return &object; }
|
||||
};
|
||||
|
||||
} // namespace wrapper_details
|
||||
|
||||
using clContextWrapper =
|
||||
wrapper_details::Wrapper<cl_context, clRetainContext, clReleaseContext>;
|
||||
|
||||
using clProgramWrapper =
|
||||
wrapper_details::Wrapper<cl_program, clRetainProgram, clReleaseProgram>;
|
||||
|
||||
using clKernelWrapper =
|
||||
wrapper_details::Wrapper<cl_kernel, clRetainKernel, clReleaseKernel>;
|
||||
|
||||
using clMemWrapper =
|
||||
wrapper_details::Wrapper<cl_mem, clRetainMemObject, clReleaseMemObject>;
|
||||
|
||||
using clCommandQueueWrapper =
|
||||
wrapper_details::Wrapper<cl_command_queue, clRetainCommandQueue,
|
||||
clReleaseCommandQueue>;
|
||||
|
||||
using clSamplerWrapper =
|
||||
wrapper_details::Wrapper<cl_sampler, clRetainSampler, clReleaseSampler>;
|
||||
|
||||
using clEventWrapper =
|
||||
wrapper_details::Wrapper<cl_event, clRetainEvent, clReleaseEvent>;
|
||||
|
||||
class clProtectedImage {
|
||||
public:
|
||||
clProtectedImage()
|
||||
|
|
@ -183,92 +195,12 @@ public:
|
|||
|
||||
cl_mem *operator&() { return ℑ }
|
||||
|
||||
bool operator==(const cl_mem &rhs) { return image == rhs; }
|
||||
|
||||
protected:
|
||||
void *backingStore;
|
||||
size_t backingStoreSize;
|
||||
cl_mem image;
|
||||
};
|
||||
|
||||
/* cl_command_queue wrapper */
|
||||
class clCommandQueueWrapper {
|
||||
public:
|
||||
clCommandQueueWrapper() { mMem = NULL; }
|
||||
clCommandQueueWrapper(cl_command_queue mem) { mMem = mem; }
|
||||
~clCommandQueueWrapper()
|
||||
{
|
||||
if (mMem != NULL)
|
||||
{
|
||||
clReleaseCommandQueue(mMem);
|
||||
}
|
||||
}
|
||||
|
||||
clCommandQueueWrapper &operator=(const cl_command_queue &rhs)
|
||||
{
|
||||
mMem = rhs;
|
||||
return *this;
|
||||
}
|
||||
operator cl_command_queue() const { return mMem; }
|
||||
|
||||
cl_command_queue *operator&() { return &mMem; }
|
||||
|
||||
bool operator==(const cl_command_queue &rhs) { return mMem == rhs; }
|
||||
|
||||
protected:
|
||||
cl_command_queue mMem;
|
||||
};
|
||||
|
||||
/* cl_sampler wrapper */
|
||||
class clSamplerWrapper {
|
||||
public:
|
||||
clSamplerWrapper() { mMem = NULL; }
|
||||
clSamplerWrapper(cl_sampler mem) { mMem = mem; }
|
||||
~clSamplerWrapper()
|
||||
{
|
||||
if (mMem != NULL) clReleaseSampler(mMem);
|
||||
}
|
||||
|
||||
clSamplerWrapper &operator=(const cl_sampler &rhs)
|
||||
{
|
||||
mMem = rhs;
|
||||
return *this;
|
||||
}
|
||||
operator cl_sampler() const { return mMem; }
|
||||
|
||||
cl_sampler *operator&() { return &mMem; }
|
||||
|
||||
bool operator==(const cl_sampler &rhs) { return mMem == rhs; }
|
||||
|
||||
protected:
|
||||
cl_sampler mMem;
|
||||
};
|
||||
|
||||
/* cl_event wrapper */
|
||||
class clEventWrapper {
|
||||
public:
|
||||
clEventWrapper() { mMem = NULL; }
|
||||
clEventWrapper(cl_event mem) { mMem = mem; }
|
||||
~clEventWrapper()
|
||||
{
|
||||
if (mMem != NULL) clReleaseEvent(mMem);
|
||||
}
|
||||
|
||||
clEventWrapper &operator=(const cl_event &rhs)
|
||||
{
|
||||
mMem = rhs;
|
||||
return *this;
|
||||
}
|
||||
operator cl_event() const { return mMem; }
|
||||
|
||||
cl_event *operator&() { return &mMem; }
|
||||
|
||||
bool operator==(const cl_event &rhs) { return mMem == rhs; }
|
||||
|
||||
protected:
|
||||
cl_event mMem;
|
||||
};
|
||||
|
||||
/* Generic protected memory buffer, for verifying access within bounds */
|
||||
class clProtectedArray {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -50,11 +50,11 @@ add_subdirectory( subgroups )
|
|||
add_subdirectory( workgroups )
|
||||
add_subdirectory( pipes )
|
||||
add_subdirectory( device_timer )
|
||||
if(KHRONOS_OFFLINE_COMPILER)
|
||||
add_subdirectory( clcpp )
|
||||
endif()
|
||||
add_subdirectory( spirv_new )
|
||||
add_subdirectory( spir )
|
||||
if(VULKAN_IS_SUPPORTED)
|
||||
add_subdirectory( vulkan )
|
||||
endif()
|
||||
|
||||
file(GLOB CSV_FILES "opencl_conformance_tests_*.csv")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(MODULE_NAME SVM)
|
||||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ int test_svm_byte_granularity(cl_device_id deviceID, cl_context c, cl_command_qu
|
|||
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
cl_int rval = CL_SUCCESS;
|
||||
|
||||
err = create_cl_objects(deviceID, &byte_manipulation_kernels[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER);
|
||||
if(err == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing.
|
||||
|
|
|
|||
|
|
@ -162,7 +162,8 @@ int test_svm_cross_buffer_pointers_coarse_grain(cl_device_id deviceID, cl_contex
|
|||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
// this buffer holds the index into the nodes buffer that is used for node allocation
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(size_t), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
// this buffer holds the count of correct nodes which is computed by the verify kernel.
|
||||
|
|
|
|||
|
|
@ -78,9 +78,6 @@ int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue
|
|||
cl_uint amem[GLOBAL_SIZE];
|
||||
cl_uint bmem[GLOBAL_SIZE];
|
||||
cl_uint cmem[GLOBAL_SIZE];
|
||||
cl_uint ramem[GLOBAL_SIZE];
|
||||
cl_uint rbmem[GLOBAL_SIZE];
|
||||
cl_uint rcmem[GLOBAL_SIZE];
|
||||
cl_event evs[20];
|
||||
|
||||
const size_t global_size = GLOBAL_SIZE;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ cl_int create_linked_lists_on_device(int ci, cl_command_queue cmdq, cl_mem alloc
|
|||
cl_int error = CL_SUCCESS;
|
||||
log_info("SVM: creating linked list on device: %d ", ci);
|
||||
|
||||
size_t *pAllocator = (size_t*) clEnqueueMapBuffer(cmdq, allocator, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error);
|
||||
size_t *pAllocator = (size_t *)clEnqueueMapBuffer(
|
||||
cmdq, allocator, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(size_t),
|
||||
0, NULL, NULL, &error);
|
||||
test_error2(error, pAllocator, "clEnqueueMapBuffer failed");
|
||||
// reset allocator index
|
||||
*pAllocator = numLists; // the first numLists elements of the nodes array are already allocated (they hold the head of each list).
|
||||
|
|
@ -206,7 +208,9 @@ int shared_address_space_coarse_grain(cl_device_id deviceID, cl_context context2
|
|||
}
|
||||
|
||||
// this buffer holds an index into the nodes buffer, it is used for node allocation
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(size_t), NULL, &error);
|
||||
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
error = clGetMemObjectInfo(allocator, CL_MEM_USES_SVM_POINTER, sizeof(cl_bool), &usesSVMpointer, 0);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ int test_svm_shared_address_space_fine_grain(cl_device_id deviceID, cl_context c
|
|||
test_error2(error, pNodes, "malloc failed");
|
||||
|
||||
// this allocation holds an index into the nodes buffer, it is used for node allocation
|
||||
size_t* pAllocator = (size_t*) align_malloc(sizeof(cl_int), 128);
|
||||
size_t *pAllocator = (size_t *)align_malloc(sizeof(size_t), 128);
|
||||
test_error2(error, pAllocator, "malloc failed");
|
||||
|
||||
// this allocation holds the count of correct nodes, which is computed by the verify kernel.
|
||||
|
|
|
|||
|
|
@ -182,7 +182,8 @@ int test_svm_shared_sub_buffers(cl_device_id deviceID, cl_context context2, cl_c
|
|||
|
||||
|
||||
// this buffer holds the index into the nodes buffer that is used for node allocation
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(size_t), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
// this buffer holds the count of correct nodes which is computed by the verify kernel.
|
||||
|
|
|
|||
|
|
@ -200,8 +200,10 @@ int fill_image_with_data(cl_context context, cl_device_id device_id, cl_command_
|
|||
result = clFinish(*queue);
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
print_error(error, "clFinish failed after successful enquing filling buffer with data.");
|
||||
return result;
|
||||
print_error(error,
|
||||
"clFinish failed after successful enqueuing filling "
|
||||
"buffer with data.");
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_FALSE, origin, region, 0, 0, data, 0, NULL, &event);
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ int find_good_image_size(cl_device_id device_id, size_t size_to_allocate, size_t
|
|||
}
|
||||
|
||||
if (size_to_allocate == 0) {
|
||||
log_error("Trying to allcoate a zero sized image.\n");
|
||||
return FAILED_ABORT;
|
||||
log_error("Trying to allocate a zero sized image.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
error = clGetDeviceInfo( device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( max_width ), &max_width, NULL );
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ int doTest( cl_device_id device, cl_context context, cl_command_queue queue, All
|
|||
int number_of_mems_used;
|
||||
cl_ulong max_individual_allocation_size = g_max_individual_allocation_size;
|
||||
cl_ulong global_mem_size = g_global_mem_size ;
|
||||
const bool allocate_image =
|
||||
(alloc_type != BUFFER) && (alloc_type != BUFFER_NON_BLOCKING);
|
||||
|
||||
static const char* alloc_description[] = {
|
||||
"buffer(s)",
|
||||
|
|
@ -123,7 +125,7 @@ int doTest( cl_device_id device, cl_context context, cl_command_queue queue, All
|
|||
};
|
||||
|
||||
// Skip image tests if we don't support images on the device
|
||||
if( alloc_type > BUFFER && checkForImageSupport( device ) )
|
||||
if (allocate_image && checkForImageSupport(device))
|
||||
{
|
||||
log_info( "Can not test image allocation because device does not support images.\n" );
|
||||
return 0;
|
||||
|
|
@ -132,7 +134,7 @@ int doTest( cl_device_id device, cl_context context, cl_command_queue queue, All
|
|||
// This section was added in order to fix a bug in the test
|
||||
// If CL_DEVICE_MAX_MEM_ALLOC_SIZE is much grater than CL_DEVICE_IMAGE2D_MAX_WIDTH * CL_DEVICE_IMAGE2D_MAX_HEIGHT
|
||||
// The test will fail in image allocations as the size requested for the allocation will be much grater than the maximum size allowed for image
|
||||
if( ( alloc_type != BUFFER ) && ( alloc_type != BUFFER_NON_BLOCKING ) )
|
||||
if (allocate_image)
|
||||
{
|
||||
size_t max_width, max_height;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_api_min_max.cpp
|
||||
test_kernel_arg_changes.cpp
|
||||
test_kernel_arg_multi_setup.cpp
|
||||
test_kernel_attributes.cpp
|
||||
test_binary.cpp
|
||||
test_native_kernel.cpp
|
||||
test_mem_objects.cpp
|
||||
|
|
@ -21,7 +22,6 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_device_min_data_type_align_size_alignment.cpp
|
||||
test_platform.cpp
|
||||
test_kernel_arg_info.cpp
|
||||
test_kernel_arg_info_compatibility.cpp
|
||||
test_null_buffer_arg.cpp
|
||||
test_mem_object_info.cpp
|
||||
test_min_image_formats.cpp
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ test_definition test_list[] = {
|
|||
ADD_TEST(load_two_kernels_manually),
|
||||
ADD_TEST(get_program_info_kernel_names),
|
||||
ADD_TEST(get_kernel_arg_info),
|
||||
ADD_TEST(get_kernel_arg_info_compatibility),
|
||||
ADD_TEST(create_kernels_in_program),
|
||||
ADD_TEST(get_kernel_info),
|
||||
ADD_TEST(kernel_private_memory_size),
|
||||
|
|
@ -60,6 +59,7 @@ test_definition test_list[] = {
|
|||
ADD_TEST(set_kernel_arg_constant),
|
||||
ADD_TEST(set_kernel_arg_struct_array),
|
||||
ADD_TEST(kernel_global_constant),
|
||||
ADD_TEST(kernel_attributes),
|
||||
|
||||
ADD_TEST(min_max_thread_dimensions),
|
||||
ADD_TEST(min_max_work_items_sizes),
|
||||
|
|
|
|||
|
|
@ -42,26 +42,9 @@ int test_negative_get_platform_info(cl_device_id deviceID, cl_context context,
|
|||
{
|
||||
cl_platform_id platform = getPlatformFromDevice(deviceID);
|
||||
|
||||
cl_int err = clGetPlatformInfo(nullptr, CL_PLATFORM_VERSION, sizeof(char*),
|
||||
nullptr, nullptr);
|
||||
test_failure_error_ret(
|
||||
err, CL_INVALID_PLATFORM,
|
||||
"clGetPlatformInfo should return CL_INVALID_PLATFORM when: \"platform "
|
||||
"is not a valid platform\" using a nullptr",
|
||||
TEST_FAIL);
|
||||
|
||||
err =
|
||||
clGetPlatformInfo(reinterpret_cast<cl_platform_id>(deviceID),
|
||||
CL_PLATFORM_VERSION, sizeof(char*), nullptr, nullptr);
|
||||
test_failure_error_ret(
|
||||
err, CL_INVALID_PLATFORM,
|
||||
"clGetPlatformInfo should return CL_INVALID_PLATFORM when: \"platform "
|
||||
"is not a valid platform\" using a valid object which is NOT a "
|
||||
"platform",
|
||||
TEST_FAIL);
|
||||
|
||||
constexpr cl_platform_info INVALID_PARAM_VALUE = 0;
|
||||
err = clGetPlatformInfo(platform, INVALID_PARAM_VALUE, 0, nullptr, nullptr);
|
||||
cl_int err =
|
||||
clGetPlatformInfo(platform, INVALID_PARAM_VALUE, 0, nullptr, nullptr);
|
||||
test_failure_error_ret(
|
||||
err, CL_INVALID_VALUE,
|
||||
"clGetPlatformInfo should return CL_INVALID_VALUE when: \"param_name "
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ extern int test_get_image1d_info( cl_device_id deviceID, cl_context context
|
|||
extern int test_get_image1d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements );
|
||||
extern int test_get_image2d_array_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements );
|
||||
extern int test_get_kernel_arg_info( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_get_kernel_arg_info_compatibility( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_queue_hint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
|
@ -203,3 +202,5 @@ extern int test_negative_get_platform_ids(cl_device_id deviceID,
|
|||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_kernel_attributes(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -94,18 +94,6 @@ struct structArg
|
|||
float f;
|
||||
};
|
||||
|
||||
static unsigned char *
|
||||
generate_8888_image(int w, int h, MTdata d)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char*)malloc(w * h * 4);
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*4; i++)
|
||||
ptr[i] = (unsigned char)genrand_int32( d);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int test_image_arg_shallow_clone(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, void* pbufRes, clMemWrapper& bufOut)
|
||||
{
|
||||
int error;
|
||||
|
|
@ -323,6 +311,14 @@ int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
clKernelWrapper clonek = clCloneKernel(kernel, &error);
|
||||
test_error( error, "clCloneKernel failed." );
|
||||
|
||||
// enqueue the kernel before the last arg is set
|
||||
error = clEnqueueNDRangeKernel(queue, clonek, 1, NULL, &ndrange1, NULL, 0,
|
||||
NULL, NULL);
|
||||
test_failure_error(error, CL_INVALID_KERNEL_ARGS,
|
||||
"A kernel cloned before all args are set should return "
|
||||
"CL_INVALID_KERNEL_ARGS if enqueued before the "
|
||||
"remaining args are set");
|
||||
|
||||
// set the last arg and enqueue
|
||||
error = clSetKernelArg(clonek, 4, sizeof(cl_mem), &bufOut);
|
||||
test_error( error, "clSetKernelArg failed." );
|
||||
|
|
|
|||
|
|
@ -52,12 +52,7 @@ int test_context_destructor_callback(cl_device_id deviceID, cl_context context,
|
|||
test_error(error, "Unable to set destructor callback");
|
||||
|
||||
// Now release the context, which SHOULD call the callbacks
|
||||
error = clReleaseContext(localContext);
|
||||
test_error(error, "Unable to release local context");
|
||||
|
||||
// Note: since we manually released the context, we need to set it to NULL
|
||||
// to prevent a double-release
|
||||
localContext = NULL;
|
||||
localContext.reset();
|
||||
|
||||
// At this point, all three callbacks should have already been called
|
||||
int numErrors = 0;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
339
test_conformance/api/test_kernel_attributes.cpp
Normal file
339
test_conformance/api/test_kernel_attributes.cpp
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
//
|
||||
// Copyright (c) 2020 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include "procs.h"
|
||||
#include "harness/errorHelpers.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
#include "harness/parseParameters.h"
|
||||
|
||||
using KernelAttributes = std::vector<std::string>;
|
||||
|
||||
static std::string generate_kernel_source(const KernelAttributes& attributes)
|
||||
{
|
||||
std::string kernel;
|
||||
for (auto attribute : attributes)
|
||||
{
|
||||
kernel += "__attribute__((" + attribute + "))\n";
|
||||
}
|
||||
kernel += "__kernel void test_kernel(){}";
|
||||
return kernel;
|
||||
}
|
||||
|
||||
|
||||
using AttributePermutations = std::vector<KernelAttributes>;
|
||||
|
||||
// The following combinations have been chosen as they place each of the
|
||||
// attribute types in the different orders that they can occur. While distinct
|
||||
// permutations would provide a complete overview of the API the sheer number of
|
||||
// combinations increases the runtime of this test by an unreasonable amount
|
||||
AttributePermutations vect_tests;
|
||||
AttributePermutations work_tests;
|
||||
AttributePermutations reqd_tests;
|
||||
|
||||
AttributePermutations vect_reqd_tests;
|
||||
AttributePermutations work_vect_tests;
|
||||
AttributePermutations reqd_work_tests;
|
||||
|
||||
AttributePermutations vect_work_reqd_tests;
|
||||
AttributePermutations work_reqd_vect_tests;
|
||||
AttributePermutations reqd_vect_work_tests;
|
||||
|
||||
|
||||
// Generate a vector with vec_type_hint(<data_type>) so that it can be used to
|
||||
// generate different kernels
|
||||
static KernelAttributes generate_vec_type_hint_data(cl_device_id deviceID)
|
||||
{
|
||||
KernelAttributes vec_type_hint_data;
|
||||
// TODO Test for signed vectors (char/short/int/etc)
|
||||
std::vector<std::string> vector_types = { "uchar", "ushort", "uint",
|
||||
"float" };
|
||||
if (gHasLong)
|
||||
{
|
||||
vector_types.push_back("ulong");
|
||||
}
|
||||
if (device_supports_half(deviceID))
|
||||
{
|
||||
vector_types.push_back("half");
|
||||
}
|
||||
if (device_supports_double(deviceID))
|
||||
{
|
||||
vector_types.push_back("double");
|
||||
}
|
||||
|
||||
const auto vector_sizes = { "2", "3", "4", "8", "16" };
|
||||
for (auto type : vector_types)
|
||||
{
|
||||
for (auto size : vector_sizes)
|
||||
{
|
||||
vec_type_hint_data.push_back("vec_type_hint(" + type + size + ")");
|
||||
}
|
||||
}
|
||||
return vec_type_hint_data;
|
||||
}
|
||||
|
||||
|
||||
struct WorkGroupDimensions
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
// Generate vectors to store reqd_work_group_size(<dimensions>) and
|
||||
// work_group_size_hint(<dimensions>) so that they can be used to generate
|
||||
// different kernels
|
||||
static KernelAttributes generate_reqd_work_group_size_data(
|
||||
const std::vector<WorkGroupDimensions>& work_group_dimensions)
|
||||
{
|
||||
KernelAttributes reqd_work_group_size_data;
|
||||
for (auto dimension : work_group_dimensions)
|
||||
{
|
||||
reqd_work_group_size_data.push_back(
|
||||
"reqd_work_group_size(" + std::to_string(dimension.x) + ","
|
||||
+ std::to_string(dimension.y) + "," + std::to_string(dimension.z)
|
||||
+ ")");
|
||||
}
|
||||
return reqd_work_group_size_data;
|
||||
}
|
||||
|
||||
static KernelAttributes generate_work_group_size_data(
|
||||
const std::vector<WorkGroupDimensions>& work_group_dimensions)
|
||||
{
|
||||
KernelAttributes work_group_size_hint_data;
|
||||
for (auto dimension : work_group_dimensions)
|
||||
{
|
||||
work_group_size_hint_data.push_back(
|
||||
"work_group_size_hint(" + std::to_string(dimension.x) + ","
|
||||
+ std::to_string(dimension.y) + "," + std::to_string(dimension.z)
|
||||
+ ")");
|
||||
}
|
||||
return work_group_size_hint_data;
|
||||
}
|
||||
|
||||
// Populate the Global Vectors which store individual Kernel Attributes
|
||||
static void populate_single_attribute_tests(
|
||||
// Vectors to store the different data that fill the attributes
|
||||
const KernelAttributes& vec_type_hint_data,
|
||||
const KernelAttributes& work_group_size_hint_data,
|
||||
const KernelAttributes& reqd_work_group_size_data)
|
||||
{
|
||||
for (auto vector_test : vec_type_hint_data)
|
||||
{
|
||||
// Initialise vec_type_hint attribute tests
|
||||
vect_tests.push_back({ vector_test });
|
||||
}
|
||||
for (auto work_group_test : work_group_size_hint_data)
|
||||
{
|
||||
|
||||
// Initialise work_group_size_hint attribute test
|
||||
work_tests.push_back({ work_group_test });
|
||||
}
|
||||
for (auto reqd_work_group_test : reqd_work_group_size_data)
|
||||
{
|
||||
|
||||
// Initialise reqd_work_group_size attribute tests
|
||||
reqd_tests.push_back({ reqd_work_group_test });
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the Global Vectors which store the different permutations of 2
|
||||
// Kernel Attributes
|
||||
static void populate_double_attribute_tests(
|
||||
const KernelAttributes& vec_type_hint_data,
|
||||
const KernelAttributes& work_group_size_hint_data,
|
||||
const KernelAttributes& reqd_work_group_size_data)
|
||||
{
|
||||
for (auto vector_test : vec_type_hint_data)
|
||||
{
|
||||
for (auto work_group_test : work_group_size_hint_data)
|
||||
{
|
||||
// Initialise the tests for the permutation of work_group_size_hint
|
||||
// combined with vec_type_hint
|
||||
work_vect_tests.push_back({ work_group_test, vector_test });
|
||||
}
|
||||
for (auto reqd_work_group_test : reqd_work_group_size_data)
|
||||
{
|
||||
// Initialise the tests for the permutation of vec_type_hint and
|
||||
// reqd_work_group_size
|
||||
vect_reqd_tests.push_back({ vector_test, reqd_work_group_test });
|
||||
}
|
||||
}
|
||||
for (auto work_group_test : work_group_size_hint_data)
|
||||
{
|
||||
|
||||
for (auto reqd_work_group_test : reqd_work_group_size_data)
|
||||
{
|
||||
// Initialse the tests for the permutation of reqd_work_group_size
|
||||
// and work_group_size_hint
|
||||
reqd_work_tests.push_back(
|
||||
{ reqd_work_group_test, work_group_test });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the Global Vectors which store the different permutations of 3
|
||||
// Kernel Attributes
|
||||
static void populate_triple_attribute_tests(
|
||||
const KernelAttributes& vec_type_hint_data,
|
||||
const KernelAttributes& work_group_size_hint_data,
|
||||
const KernelAttributes& reqd_work_group_size_data)
|
||||
{
|
||||
for (auto vector_test : vec_type_hint_data)
|
||||
{
|
||||
for (auto work_group_test : work_group_size_hint_data)
|
||||
{
|
||||
for (auto reqd_work_group_test : reqd_work_group_size_data)
|
||||
{
|
||||
// Initialise the chosen permutations of 3 attributes
|
||||
vect_work_reqd_tests.push_back(
|
||||
{ vector_test, work_group_test, reqd_work_group_test });
|
||||
work_reqd_vect_tests.push_back(
|
||||
{ work_group_test, reqd_work_group_test, vector_test });
|
||||
reqd_vect_work_tests.push_back(
|
||||
{ reqd_work_group_test, vector_test, work_group_test });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const std::vector<AttributePermutations*>
|
||||
generate_attribute_tests(const KernelAttributes& vec_type_hint_data,
|
||||
const KernelAttributes& work_group_size_hint_data,
|
||||
const KernelAttributes& reqd_work_group_size_data)
|
||||
{
|
||||
populate_single_attribute_tests(vec_type_hint_data,
|
||||
work_group_size_hint_data,
|
||||
reqd_work_group_size_data);
|
||||
populate_double_attribute_tests(vec_type_hint_data,
|
||||
work_group_size_hint_data,
|
||||
reqd_work_group_size_data);
|
||||
populate_triple_attribute_tests(vec_type_hint_data,
|
||||
work_group_size_hint_data,
|
||||
reqd_work_group_size_data);
|
||||
|
||||
// Store all of the filled vectors in a single structure
|
||||
const std::vector<AttributePermutations*> all_tests = {
|
||||
&vect_tests, &work_tests, &reqd_tests,
|
||||
|
||||
&work_vect_tests, &vect_reqd_tests, &reqd_work_tests,
|
||||
|
||||
&vect_work_reqd_tests, &work_reqd_vect_tests, &reqd_vect_work_tests
|
||||
};
|
||||
return all_tests;
|
||||
}
|
||||
|
||||
static const std::vector<AttributePermutations*>
|
||||
initialise_attribute_data(cl_device_id deviceID)
|
||||
{
|
||||
// This vector stores different work group dimensions that can be used by
|
||||
// the reqd_work_group_size and work_group_size_hint attributes. It
|
||||
// currently only has a single value to minimise time complexity of the
|
||||
// overall test but can be easily changed.
|
||||
static const std::vector<WorkGroupDimensions> work_group_dimensions = {
|
||||
{ 1, 1, 1 }
|
||||
};
|
||||
KernelAttributes vec_type_hint_data = generate_vec_type_hint_data(deviceID);
|
||||
KernelAttributes work_group_size_hint_data =
|
||||
generate_work_group_size_data(work_group_dimensions);
|
||||
KernelAttributes reqd_work_group_size_data =
|
||||
generate_reqd_work_group_size_data(work_group_dimensions);
|
||||
|
||||
// Generate all the permutations of attributes to create different test
|
||||
// suites
|
||||
return generate_attribute_tests(vec_type_hint_data,
|
||||
work_group_size_hint_data,
|
||||
reqd_work_group_size_data);
|
||||
}
|
||||
|
||||
static bool run_test(cl_context context, cl_device_id deviceID,
|
||||
const AttributePermutations& permutations)
|
||||
{
|
||||
bool success = true;
|
||||
for (auto attribute_permutation : permutations)
|
||||
{
|
||||
|
||||
std::string kernel_source_string =
|
||||
generate_kernel_source(attribute_permutation);
|
||||
const char* kernel_src = kernel_source_string.c_str();
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
cl_int err = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
&kernel_src, "test_kernel");
|
||||
test_error_ret(err, "create_single_kernel_helper", false);
|
||||
|
||||
// Get the size of the kernel attribute string returned
|
||||
size_t size = 0;
|
||||
err = clGetKernelInfo(kernel, CL_KERNEL_ATTRIBUTES, 0, nullptr, &size);
|
||||
test_error_ret(err, "clGetKernelInfo", false);
|
||||
std::vector<char> attributes(size);
|
||||
err = clGetKernelInfo(kernel, CL_KERNEL_ATTRIBUTES, attributes.size(),
|
||||
attributes.data(), nullptr);
|
||||
test_error_ret(err, "clGetKernelInfo", false);
|
||||
std::string attribute_string(attributes.data());
|
||||
attribute_string.erase(
|
||||
std::remove(attribute_string.begin(), attribute_string.end(), ' '),
|
||||
attribute_string.end());
|
||||
if (gCompilationMode != kOnline)
|
||||
{
|
||||
if (!attribute_string.empty())
|
||||
{
|
||||
success = false;
|
||||
log_error("Error: Expected an empty string\n");
|
||||
log_error("Attribute string reported as: %s\n",
|
||||
attribute_string.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool permutation_success = true;
|
||||
for (auto attribute : attribute_permutation)
|
||||
{
|
||||
if (attribute_string.find(attribute) == std::string::npos)
|
||||
{
|
||||
success = false;
|
||||
permutation_success = false;
|
||||
log_error("ERROR: did not find expected attribute: '%s'\n",
|
||||
attribute.c_str());
|
||||
}
|
||||
}
|
||||
if (!permutation_success)
|
||||
{
|
||||
log_error("Attribute string reported as: %s\n",
|
||||
attribute_string.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int test_kernel_attributes(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
// Vector to store all of the tests
|
||||
const std::vector<AttributePermutations*> all_tests =
|
||||
initialise_attribute_data(deviceID);
|
||||
|
||||
for (auto permutations : all_tests)
|
||||
{
|
||||
success = success && run_test(context, deviceID, *permutations);
|
||||
}
|
||||
return success ? TEST_PASS : TEST_FAIL;
|
||||
}
|
||||
|
|
@ -348,14 +348,7 @@ int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_
|
|||
TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_ASSOCIATED_MEMOBJECT, origObj, (cl_mem)bufferObject, "associated mem object", "%p", void * )
|
||||
|
||||
TEST_MEM_OBJECT_PARAM( subBufferObject, CL_MEM_OFFSET, offset, (size_t)( addressAlign ), "offset", "%ld", size_t )
|
||||
|
||||
clReleaseMemObject( subBufferObject );
|
||||
subBufferObject = NULL;
|
||||
|
||||
}
|
||||
|
||||
clReleaseMemObject( bufferObject );
|
||||
bufferObject = NULL;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
|
@ -370,8 +363,6 @@ int test_get_imageObject_info( cl_mem * image, cl_mem_flags objectFlags, cl_imag
|
|||
cl_mem_flags flags;
|
||||
cl_uint mapCount;
|
||||
cl_uint refCount;
|
||||
size_t rowPitchMultiplier;
|
||||
size_t slicePitchMultiplier;
|
||||
cl_context otherCtx;
|
||||
size_t offset;
|
||||
size_t sz;
|
||||
|
|
|
|||
|
|
@ -48,12 +48,7 @@ int test_mem_object_destructor_callback_single(clMemWrapper &memObject)
|
|||
test_error(error, "Unable to set destructor callback");
|
||||
|
||||
// Now release the buffer, which SHOULD call the callbacks
|
||||
error = clReleaseMemObject(memObject);
|
||||
test_error(error, "Unable to release test buffer");
|
||||
|
||||
// Note: since we manually released the mem wrapper, we need to set it to
|
||||
// NULL to prevent a double-release
|
||||
memObject = NULL;
|
||||
memObject.reset();
|
||||
|
||||
// At this point, all three callbacks should have already been called
|
||||
int numErrors = 0;
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ int test_null_buffer_arg(cl_device_id device, cl_context context,
|
|||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
unsigned int test_success = 0;
|
||||
unsigned int i;
|
||||
unsigned int buffer_size;
|
||||
cl_int status;
|
||||
cl_program program;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
int test_get_platform_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
|
|
@ -345,87 +346,100 @@ int command_queue_param_test(cl_command_queue queue,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MIN_NUM_COMMAND_QUEUE_PROPERTIES 2
|
||||
#define OOO_NUM_COMMAND_QUEUE_PROPERTIES 4
|
||||
static cl_command_queue_properties property_options[] = {
|
||||
0,
|
||||
|
||||
CL_QUEUE_PROFILING_ENABLE,
|
||||
|
||||
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
|
||||
CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
|
||||
CL_QUEUE_ON_DEVICE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
|
||||
CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_ON_DEVICE
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
|
||||
CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
|
||||
CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
|
||||
};
|
||||
|
||||
int check_get_command_queue_info_params(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
bool is_compatibility)
|
||||
{
|
||||
int error;
|
||||
size_t size;
|
||||
const cl_command_queue_properties host_optional[] = {
|
||||
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
|
||||
};
|
||||
|
||||
cl_queue_properties host_queue_props, device_queue_props;
|
||||
cl_queue_properties queue_props[] = { CL_QUEUE_PROPERTIES, 0, 0 };
|
||||
const cl_command_queue_properties device_required[] = {
|
||||
CL_QUEUE_ON_DEVICE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_ON_DEVICE
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
|
||||
CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_ON_DEVICE
|
||||
| CL_QUEUE_ON_DEVICE_DEFAULT
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
|
||||
};
|
||||
|
||||
clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
|
||||
sizeof(host_queue_props), &host_queue_props, NULL);
|
||||
log_info("CL_DEVICE_QUEUE_ON_HOST_PROPERTIES is %d\n",
|
||||
(int)host_queue_props);
|
||||
clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES,
|
||||
sizeof(device_queue_props), &device_queue_props, NULL);
|
||||
log_info("CL_DEVICE_QUEUE_ON_HOST_PROPERTIES is %d\n",
|
||||
(int)device_queue_props);
|
||||
const size_t host_optional_size = ARRAY_SIZE(host_optional);
|
||||
const size_t device_required_size = ARRAY_SIZE(device_required);
|
||||
|
||||
auto version = get_device_cl_version(deviceID);
|
||||
Version version = get_device_cl_version(deviceID);
|
||||
|
||||
const cl_device_info host_queue_query = version >= Version(2, 0)
|
||||
? CL_DEVICE_QUEUE_ON_HOST_PROPERTIES
|
||||
: CL_DEVICE_QUEUE_PROPERTIES;
|
||||
|
||||
cl_queue_properties host_queue_props = 0;
|
||||
int error =
|
||||
clGetDeviceInfo(deviceID, host_queue_query, sizeof(host_queue_props),
|
||||
&host_queue_props, NULL);
|
||||
test_error(error, "clGetDeviceInfo failed");
|
||||
log_info("CL_DEVICE_QUEUE_ON_HOST_PROPERTIES is %d\n", host_queue_props);
|
||||
|
||||
cl_queue_properties device_queue_props = 0;
|
||||
if (version >= Version(2, 0))
|
||||
{
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES,
|
||||
sizeof(device_queue_props), &device_queue_props,
|
||||
NULL);
|
||||
test_error(error, "clGetDeviceInfo failed");
|
||||
log_info("CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES is %d\n",
|
||||
device_queue_props);
|
||||
}
|
||||
|
||||
bool out_of_order_supported =
|
||||
host_queue_props & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
|
||||
|
||||
// Are on device queues supported
|
||||
bool on_device_supported =
|
||||
(version >= Version(2, 0) && version < Version(3, 0))
|
||||
|| (version >= Version(3, 0) && device_queue_props != 0);
|
||||
|
||||
int num_test_options = MIN_NUM_COMMAND_QUEUE_PROPERTIES;
|
||||
if (host_queue_props & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)
|
||||
{
|
||||
// Test out-of-order queues properties if supported
|
||||
num_test_options = OOO_NUM_COMMAND_QUEUE_PROPERTIES;
|
||||
}
|
||||
if (on_device_supported && !is_compatibility)
|
||||
{
|
||||
// Test queue on device if supported (in this case out-of-order must
|
||||
// also be supported)
|
||||
num_test_options = ARRAY_SIZE(property_options);
|
||||
}
|
||||
// test device queues if the device and the API under test support it
|
||||
bool test_on_device = on_device_supported && !is_compatibility;
|
||||
|
||||
for (int i = 0; i < num_test_options; i++)
|
||||
std::vector<cl_queue_properties> queue_props{ 0,
|
||||
CL_QUEUE_PROFILING_ENABLE };
|
||||
|
||||
if (out_of_order_supported)
|
||||
{
|
||||
queue_props[1] = property_options[i];
|
||||
queue_props.insert(queue_props.end(), &host_optional[0],
|
||||
&host_optional[host_optional_size]);
|
||||
};
|
||||
|
||||
cl_queue_properties queue_props_arg[] = { CL_QUEUE_PROPERTIES, 0, 0 };
|
||||
|
||||
if (test_on_device)
|
||||
{
|
||||
queue_props.insert(queue_props.end(), &device_required[0],
|
||||
&device_required[device_required_size]);
|
||||
};
|
||||
|
||||
for (cl_queue_properties props : queue_props)
|
||||
{
|
||||
|
||||
queue_props_arg[1] = props;
|
||||
|
||||
clCommandQueueWrapper queue;
|
||||
|
||||
if (is_compatibility)
|
||||
{
|
||||
queue =
|
||||
clCreateCommandQueue(context, deviceID, queue_props[1], &error);
|
||||
queue = clCreateCommandQueue(context, deviceID, props, &error);
|
||||
test_error(error, "Unable to create command queue to test with");
|
||||
}
|
||||
else
|
||||
{
|
||||
queue = clCreateCommandQueueWithProperties(context, deviceID,
|
||||
&queue_props[0], &error);
|
||||
queue_props_arg, &error);
|
||||
test_error(error, "Unable to create command queue to test with");
|
||||
}
|
||||
|
||||
cl_uint refCount;
|
||||
size_t size;
|
||||
error = clGetCommandQueueInfo(queue, CL_QUEUE_REFERENCE_COUNT,
|
||||
sizeof(refCount), &refCount, &size);
|
||||
test_error(error, "Unable to get command queue reference count");
|
||||
|
|
@ -442,11 +456,12 @@ int check_get_command_queue_info_params(cl_device_id deviceID,
|
|||
test_error(error, "param checking failed");
|
||||
|
||||
error = command_queue_param_test(queue, CL_QUEUE_PROPERTIES,
|
||||
queue_props[1], "properties");
|
||||
queue_props_arg[1], "properties");
|
||||
test_error(error, "param checking failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_get_command_queue_info(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue ignoreQueue, int num_elements)
|
||||
{
|
||||
|
|
@ -511,26 +526,6 @@ void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data )
|
|||
free( data );
|
||||
}
|
||||
|
||||
// All possible combinations of valid cl_mem_flags.
|
||||
static cl_mem_flags all_flags[16] = {
|
||||
0,
|
||||
CL_MEM_READ_WRITE,
|
||||
CL_MEM_READ_ONLY,
|
||||
CL_MEM_WRITE_ONLY,
|
||||
CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR,
|
||||
CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR,
|
||||
CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR,
|
||||
CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR,
|
||||
CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,
|
||||
CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
|
||||
};
|
||||
|
||||
#define TEST_DEVICE_PARAM( device, paramName, val, name, type, cast ) \
|
||||
error = clGetDeviceInfo( device, paramName, sizeof( val ), &val, &size ); \
|
||||
test_error( error, "Unable to get device " name ); \
|
||||
|
|
@ -824,5 +819,3 @@ int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, c
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,11 +56,9 @@ cl_int get_sub_group_num(cl_command_queue queue, cl_kernel kernel, clMemWrapper&
|
|||
|
||||
int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
static const size_t gsize0 = 80;
|
||||
int i, error;
|
||||
int error;
|
||||
size_t realSize;
|
||||
size_t kernel_max_subgroup_size, kernel_subgroup_count;
|
||||
size_t global[] = {1,1,1};
|
||||
size_t max_local;
|
||||
|
||||
cl_platform_id platform;
|
||||
|
|
@ -129,7 +127,9 @@ int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_comman
|
|||
log_info("The CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE for the kernel is %d.\n", (int)kernel_subgroup_count);
|
||||
|
||||
if (realSize != sizeof(kernel_subgroup_count)) {
|
||||
log_error( "ERROR: Returned size of sub group count not valid! (Expected %d, got %d)\n", (int)sizeof(kernel_subgroup_count), (int)realSize );
|
||||
log_error("ERROR: Returned size of sub group count not valid! "
|
||||
"(Expected %d, got %d)\n",
|
||||
(int)sizeof(kernel_subgroup_count), (int)realSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +137,6 @@ int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_comman
|
|||
for (size_t i = kernel_subgroup_count; i > 0; --i)
|
||||
{
|
||||
// test all 3 different dimention of requested local size
|
||||
size_t expect_size = kernel_max_subgroup_size * i;
|
||||
size_t kernel_ret_size = 0;
|
||||
error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(i), &i, sizeof(ret_ndrange1d), &ret_ndrange1d, &realSize);
|
||||
test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT");
|
||||
|
|
@ -146,12 +145,6 @@ int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_comman
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (ret_ndrange1d != expect_size)
|
||||
{
|
||||
log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", (int)expect_size, (int)ret_ndrange1d );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = get_sub_group_num(queue, kernel, out, kernel_ret_size, ret_ndrange1d, 1);
|
||||
test_error(error, "Failed to query number of subgroups from kernel");
|
||||
if (i != kernel_ret_size)
|
||||
|
|
@ -168,12 +161,6 @@ int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_comman
|
|||
}
|
||||
|
||||
ret_ndrange2d_flattened = flatten_ndrange(ret_ndrange2d, 2);
|
||||
if (ret_ndrange2d_flattened != expect_size ||
|
||||
ret_ndrange2d[1] != 1)
|
||||
{
|
||||
log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", (int)expect_size, (int)ret_ndrange2d_flattened );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = get_sub_group_num(queue, kernel, out, kernel_ret_size, ret_ndrange2d_flattened, 2);
|
||||
test_error(error, "Failed to query number of subgroups from kernel");
|
||||
|
|
@ -191,13 +178,6 @@ int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_comman
|
|||
}
|
||||
|
||||
ret_ndrange3d_flattened = flatten_ndrange(ret_ndrange3d, 3);
|
||||
if (ret_ndrange3d_flattened != expect_size ||
|
||||
ret_ndrange3d[1] != 1 ||
|
||||
ret_ndrange3d[2] != 1)
|
||||
{
|
||||
log_error( "ERROR: Incorrect value returned for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT! (Expected %d, got %d)\n", (int)expect_size, (int)ret_ndrange3d_flattened );
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = get_sub_group_num(queue, kernel, out, kernel_ret_size, ret_ndrange3d_flattened, 3);
|
||||
test_error(error, "Failed to query number of subgroups from kernel");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
test_definition test_list[] = {
|
||||
ADD_TEST( atomic_add ),
|
||||
ADD_TEST( atomic_sub ),
|
||||
|
|
@ -40,11 +41,11 @@ test_definition test_list[] = {
|
|||
ADD_TEST( atomic_add_index ),
|
||||
ADD_TEST( atomic_add_index_bin ),
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const int test_num = ARRAY_SIZE( test_list );
|
||||
const int test_num = ARRAY_SIZE(test_list);
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
return runTestHarness(argc, argv, test_num, test_list, false, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -15,25 +15,37 @@
|
|||
//
|
||||
#include "harness/errorHelpers.h"
|
||||
#include "harness/kernelHelpers.h"
|
||||
#include "harness/threadTesting.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
|
||||
extern int create_program_and_kernel(const char *source, const char *kernel_name, cl_program *program_ret, cl_kernel *kernel_ret);
|
||||
|
||||
extern int test_atomic_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_xchg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_inc(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_dec(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_cmpxchg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_atomic_add_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_add_index_bin(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int create_program_and_kernel(const char *source,
|
||||
const char *kernel_name,
|
||||
cl_program *program_ret,
|
||||
cl_kernel *kernel_ret);
|
||||
|
||||
extern int test_atomic_add(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_sub(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_xchg(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_min(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_max(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_inc(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_dec(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_cmpxchg(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_and(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_or(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_xor(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_atomic_add_index(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_atomic_add_index_bin(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -26,6 +26,3 @@
|
|||
#include "procs.h"
|
||||
|
||||
#endif // _testBase_h
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -16,48 +16,55 @@
|
|||
#include "testBase.h"
|
||||
#include "harness/conversions.h"
|
||||
|
||||
const char * atomic_index_source =
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"// Counter keeps track of which index in counts we are using.\n"
|
||||
"// We get that value, increment it, and then set that index in counts to our thread ID.\n"
|
||||
"// At the end of this we should have all thread IDs in some random location in counts\n"
|
||||
"// exactly once. If atom_add failed then we will write over various thread IDs and we\n"
|
||||
"// will be missing some.\n"
|
||||
"\n"
|
||||
"__kernel void add_index_test(__global int *counter, __global int *counts) {\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
" \n"
|
||||
" int counter_to_use = atom_add(counter, 1);\n"
|
||||
" counts[counter_to_use] = tid;\n"
|
||||
"}";
|
||||
// clang-format off
|
||||
const char *atomic_index_source =
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"// Counter keeps track of which index in counts we are using.\n"
|
||||
"// We get that value, increment it, and then set that index in counts to our thread ID.\n"
|
||||
"// At the end of this we should have all thread IDs in some random location in counts\n"
|
||||
"// exactly once. If atom_add failed then we will write over various thread IDs and we\n"
|
||||
"// will be missing some.\n"
|
||||
"\n"
|
||||
"__kernel void add_index_test(__global int *counter, __global int *counts) {\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
" \n"
|
||||
" int counter_to_use = atom_add(counter, 1);\n"
|
||||
" counts[counter_to_use] = tid;\n"
|
||||
"}";
|
||||
// clang-format on
|
||||
|
||||
int test_atomic_add_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
int test_atomic_add_index(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
clMemWrapper counter, counters;
|
||||
size_t numGlobalThreads, numLocalThreads;
|
||||
int fail = 0, succeed = 0, err;
|
||||
int fail = 0, err;
|
||||
|
||||
/* Check if atomics are supported. */
|
||||
if (!is_extension_available(deviceID, "cl_khr_global_int32_base_atomics")) {
|
||||
log_info("Base atomics not supported (cl_khr_global_int32_base_atomics). Skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
/* Check if atomics are supported. */
|
||||
if (!is_extension_available(deviceID, "cl_khr_global_int32_base_atomics"))
|
||||
{
|
||||
log_info("Base atomics not supported "
|
||||
"(cl_khr_global_int32_base_atomics). Skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===== add_index test
|
||||
// The index test replicates what particles does.
|
||||
// It uses one memory location to keep track of the current index and then each thread
|
||||
// does an atomic add to it to get its new location. The threads then write to their
|
||||
// assigned location. At the end we check to make sure that each thread's ID shows up
|
||||
// exactly once in the output.
|
||||
// It uses one memory location to keep track of the current index and then
|
||||
// each thread does an atomic add to it to get its new location. The threads
|
||||
// then write to their assigned location. At the end we check to make sure
|
||||
// that each thread's ID shows up exactly once in the output.
|
||||
|
||||
numGlobalThreads = 2048;
|
||||
|
||||
if( create_single_kernel_helper( context, &program, &kernel, 1, &atomic_index_source, "add_index_test" ) )
|
||||
if (create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
&atomic_index_source, "add_index_test"))
|
||||
return -1;
|
||||
|
||||
if( get_max_common_work_group_size( context, kernel, numGlobalThreads, &numLocalThreads ) )
|
||||
if (get_max_common_work_group_size(context, kernel, numGlobalThreads,
|
||||
&numLocalThreads))
|
||||
return -1;
|
||||
|
||||
log_info("Execute global_threads:%d local_threads:%d\n",
|
||||
|
|
@ -72,103 +79,148 @@ int test_atomic_add_index(cl_device_id deviceID, cl_context context, cl_command_
|
|||
sizeof(cl_int) * numGlobalThreads, NULL, NULL);
|
||||
|
||||
// Reset all those locations to -1 to indciate they have not been used.
|
||||
cl_int *values = (cl_int*) malloc(sizeof(cl_int)*numGlobalThreads);
|
||||
if (values == NULL) {
|
||||
log_error("add_index_test FAILED to allocate memory for initial values.\n");
|
||||
fail = 1; succeed = -1;
|
||||
} else {
|
||||
cl_int *values = (cl_int *)malloc(sizeof(cl_int) * numGlobalThreads);
|
||||
if (values == NULL)
|
||||
{
|
||||
log_error(
|
||||
"add_index_test FAILED to allocate memory for initial values.\n");
|
||||
fail = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(values, -1, numLocalThreads);
|
||||
unsigned int i=0;
|
||||
for (i=0; i<numGlobalThreads; i++)
|
||||
values[i] = -1;
|
||||
int init=0;
|
||||
err = clEnqueueWriteBuffer(queue, counters, true, 0, numGlobalThreads*sizeof(cl_int), values, 0, NULL, NULL);
|
||||
err |= clEnqueueWriteBuffer(queue, counter, true, 0,1*sizeof(cl_int), &init, 0, NULL, NULL);
|
||||
if (err) {
|
||||
log_error("add_index_test FAILED to write initial values to arrays: %d\n", err);
|
||||
fail=1; succeed=-1;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
for (i = 0; i < numGlobalThreads; i++) values[i] = -1;
|
||||
int init = 0;
|
||||
err = clEnqueueWriteBuffer(queue, counters, true, 0,
|
||||
numGlobalThreads * sizeof(cl_int), values, 0,
|
||||
NULL, NULL);
|
||||
err |= clEnqueueWriteBuffer(queue, counter, true, 0, 1 * sizeof(cl_int),
|
||||
&init, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error(
|
||||
"add_index_test FAILED to write initial values to arrays: %d\n",
|
||||
err);
|
||||
fail = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = clSetKernelArg(kernel, 0, sizeof(counter), &counter);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof(counters), &counters);
|
||||
if (err) {
|
||||
log_error("add_index_test FAILED to set kernel arguments: %d\n", err);
|
||||
fail=1; succeed=-1;
|
||||
} else {
|
||||
err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, &numGlobalThreads, &numLocalThreads, 0, NULL, NULL );
|
||||
if (err) {
|
||||
log_error("add_index_test FAILED to execute kernel: %d\n", err);
|
||||
fail=1; succeed=-1;
|
||||
} else {
|
||||
err = clEnqueueReadBuffer( queue, counters, true, 0, sizeof(cl_int)*numGlobalThreads, values, 0, NULL, NULL );
|
||||
if (err) {
|
||||
log_error("add_index_test FAILED to read back results: %d\n", err);
|
||||
fail = 1; succeed=-1;
|
||||
} else {
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_test FAILED to set kernel arguments: %d\n",
|
||||
err);
|
||||
fail = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL,
|
||||
&numGlobalThreads,
|
||||
&numLocalThreads, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_test FAILED to execute kernel: %d\n",
|
||||
err);
|
||||
fail = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = clEnqueueReadBuffer(queue, counters, true, 0,
|
||||
sizeof(cl_int) * numGlobalThreads,
|
||||
values, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error(
|
||||
"add_index_test FAILED to read back results: %d\n",
|
||||
err);
|
||||
fail = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int looking_for, index;
|
||||
for (looking_for=0; looking_for<numGlobalThreads; looking_for++) {
|
||||
int instances_found=0;
|
||||
for (index=0; index<numGlobalThreads; index++) {
|
||||
if (values[index]==(int)looking_for)
|
||||
for (looking_for = 0; looking_for < numGlobalThreads;
|
||||
looking_for++)
|
||||
{
|
||||
int instances_found = 0;
|
||||
for (index = 0; index < numGlobalThreads; index++)
|
||||
{
|
||||
if (values[index] == (int)looking_for)
|
||||
instances_found++;
|
||||
}
|
||||
if (instances_found != 1) {
|
||||
log_error("add_index_test FAILED: wrong number of instances (%d!=1) for counter %d.\n", instances_found, looking_for);
|
||||
fail = 1; succeed=-1;
|
||||
if (instances_found != 1)
|
||||
{
|
||||
log_error(
|
||||
"add_index_test FAILED: wrong number of "
|
||||
"instances (%d!=1) for counter %d.\n",
|
||||
instances_found, looking_for);
|
||||
fail = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fail) {
|
||||
log_info("add_index_test passed. Each thread used exactly one index.\n");
|
||||
if (!fail)
|
||||
{
|
||||
log_info(
|
||||
"add_index_test passed. Each thread used exactly one index.\n");
|
||||
}
|
||||
free(values);
|
||||
}
|
||||
return fail;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const char *add_index_bin_kernel[] = {
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"// This test assigns a bunch of values to bins and then tries to put them in the bins in parallel\n"
|
||||
"// using an atomic add to keep track of the current location to write into in each bin.\n"
|
||||
"// This is the same as the memory update for the particles demo.\n"
|
||||
"\n"
|
||||
"__kernel void add_index_bin_test(__global int *bin_counters, __global int *bins, __global int *bin_assignments, int max_counts_per_bin) {\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" int location = bin_assignments[tid];\n"
|
||||
" int counter = atom_add(&bin_counters[location], 1);\n"
|
||||
" bins[location*max_counts_per_bin + counter] = tid;\n"
|
||||
"}" };
|
||||
"#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
|
||||
"// This test assigns a bunch of values to bins and then tries to put them in the bins in parallel\n"
|
||||
"// using an atomic add to keep track of the current location to write into in each bin.\n"
|
||||
"// This is the same as the memory update for the particles demo.\n"
|
||||
"\n"
|
||||
"__kernel void add_index_bin_test(__global int *bin_counters, __global int *bins, __global int *bin_assignments, int max_counts_per_bin) {\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" int location = bin_assignments[tid];\n"
|
||||
" int counter = atom_add(&bin_counters[location], 1);\n"
|
||||
" bins[location*max_counts_per_bin + counter] = tid;\n"
|
||||
"}" };
|
||||
// clang-format on
|
||||
|
||||
// This test assigns a bunch of values to bins and then tries to put them in the bins in parallel
|
||||
// using an atomic add to keep track of the current location to write into in each bin.
|
||||
// This is the same as the memory update for the particles demo.
|
||||
int add_index_bin_test(size_t *global_threads, cl_command_queue queue, cl_context context, MTdata d)
|
||||
// This test assigns a bunch of values to bins and then tries to put them in the
|
||||
// bins in parallel using an atomic add to keep track of the current location to
|
||||
// write into in each bin. This is the same as the memory update for the
|
||||
// particles demo.
|
||||
int add_index_bin_test(size_t *global_threads, cl_command_queue queue,
|
||||
cl_context context, MTdata d)
|
||||
{
|
||||
int number_of_items = (int)global_threads[0];
|
||||
size_t local_threads[1];
|
||||
int divisor = 12;
|
||||
int number_of_bins = number_of_items/divisor;
|
||||
int max_counts_per_bin = divisor*2;
|
||||
int number_of_bins = number_of_items / divisor;
|
||||
int max_counts_per_bin = divisor * 2;
|
||||
|
||||
int fail = 0;
|
||||
int succeed = 0;
|
||||
int err;
|
||||
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
// log_info("add_index_bin_test: %d items, into %d bins, with a max of %d items per bin (bins is %d long).\n",
|
||||
// number_of_items, number_of_bins, max_counts_per_bin, number_of_bins*max_counts_per_bin);
|
||||
// log_info("add_index_bin_test: %d items, into %d bins, with a max of %d
|
||||
// items per bin (bins is %d long).\n",
|
||||
// number_of_items, number_of_bins, max_counts_per_bin,
|
||||
// number_of_bins*max_counts_per_bin);
|
||||
|
||||
//===== add_index_bin test
|
||||
// The index test replicates what particles does.
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, add_index_bin_kernel, "add_index_bin_test" );
|
||||
test_error( err, "Unable to create testing kernel" );
|
||||
err =
|
||||
create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
add_index_bin_kernel, "add_index_bin_test");
|
||||
test_error(err, "Unable to create testing kernel");
|
||||
|
||||
if( get_max_common_work_group_size( context, kernel, global_threads[0], &local_threads[0] ) )
|
||||
if (get_max_common_work_group_size(context, kernel, global_threads[0],
|
||||
&local_threads[0]))
|
||||
return -1;
|
||||
|
||||
log_info("Execute global_threads:%d local_threads:%d\n",
|
||||
|
|
@ -185,152 +237,228 @@ int add_index_bin_test(size_t *global_threads, cl_command_queue queue, cl_contex
|
|||
clCreateBuffer(context, CL_MEM_READ_ONLY,
|
||||
sizeof(cl_int) * number_of_items, NULL, NULL);
|
||||
|
||||
if (bin_counters == NULL) {
|
||||
if (bin_counters == NULL)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate bin_counters.\n");
|
||||
return -1;
|
||||
}
|
||||
if (bins == NULL) {
|
||||
if (bins == NULL)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate bins.\n");
|
||||
return -1;
|
||||
}
|
||||
if (bin_assignments == NULL) {
|
||||
if (bin_assignments == NULL)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate bin_assignments.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize our storage
|
||||
cl_int *l_bin_counts = (cl_int*)malloc(sizeof(cl_int)*number_of_bins);
|
||||
if (!l_bin_counts) {
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for bin_counters.\n");
|
||||
cl_int *l_bin_counts = (cl_int *)malloc(sizeof(cl_int) * number_of_bins);
|
||||
if (!l_bin_counts)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for "
|
||||
"bin_counters.\n");
|
||||
return -1;
|
||||
}
|
||||
int i;
|
||||
for (i=0; i<number_of_bins; i++)
|
||||
l_bin_counts[i] = 0;
|
||||
err = clEnqueueWriteBuffer(queue, bin_counters, true, 0, sizeof(cl_int)*number_of_bins, l_bin_counts, 0, NULL, NULL);
|
||||
if (err) {
|
||||
log_error("add_index_bin_test FAILED to set initial values for bin_counters: %d\n", err);
|
||||
for (i = 0; i < number_of_bins; i++) l_bin_counts[i] = 0;
|
||||
err = clEnqueueWriteBuffer(queue, bin_counters, true, 0,
|
||||
sizeof(cl_int) * number_of_bins, l_bin_counts, 0,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to set initial values for "
|
||||
"bin_counters: %d\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cl_int *values = (cl_int*)malloc(sizeof(cl_int)*number_of_bins*max_counts_per_bin);
|
||||
if (!values) {
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for bins.\n");
|
||||
cl_int *values =
|
||||
(cl_int *)malloc(sizeof(cl_int) * number_of_bins * max_counts_per_bin);
|
||||
if (!values)
|
||||
{
|
||||
log_error(
|
||||
"add_index_bin_test FAILED to allocate initial values for bins.\n");
|
||||
return -1;
|
||||
}
|
||||
for (i=0; i<number_of_bins*max_counts_per_bin; i++)
|
||||
values[i] = -1;
|
||||
err = clEnqueueWriteBuffer(queue, bins, true, 0, sizeof(cl_int)*number_of_bins*max_counts_per_bin, values, 0, NULL, NULL);
|
||||
if (err) {
|
||||
log_error("add_index_bin_test FAILED to set initial values for bins: %d\n", err);
|
||||
for (i = 0; i < number_of_bins * max_counts_per_bin; i++) values[i] = -1;
|
||||
err = clEnqueueWriteBuffer(queue, bins, true, 0,
|
||||
sizeof(cl_int) * number_of_bins
|
||||
* max_counts_per_bin,
|
||||
values, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error(
|
||||
"add_index_bin_test FAILED to set initial values for bins: %d\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
free(values);
|
||||
|
||||
cl_int *l_bin_assignments = (cl_int*)malloc(sizeof(cl_int)*number_of_items);
|
||||
if (!l_bin_assignments) {
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for l_bin_assignments.\n");
|
||||
cl_int *l_bin_assignments =
|
||||
(cl_int *)malloc(sizeof(cl_int) * number_of_items);
|
||||
if (!l_bin_assignments)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for "
|
||||
"l_bin_assignments.\n");
|
||||
return -1;
|
||||
}
|
||||
for (i=0; i<number_of_items; i++) {
|
||||
int bin = random_in_range(0, number_of_bins-1, d);
|
||||
while (l_bin_counts[bin] >= max_counts_per_bin) {
|
||||
bin = random_in_range(0, number_of_bins-1, d);
|
||||
for (i = 0; i < number_of_items; i++)
|
||||
{
|
||||
int bin = random_in_range(0, number_of_bins - 1, d);
|
||||
while (l_bin_counts[bin] >= max_counts_per_bin)
|
||||
{
|
||||
bin = random_in_range(0, number_of_bins - 1, d);
|
||||
}
|
||||
if (bin >= number_of_bins)
|
||||
log_error("add_index_bin_test internal error generating bin assignments: bin %d >= number_of_bins %d.\n", bin, number_of_bins);
|
||||
if (l_bin_counts[bin]+1 > max_counts_per_bin)
|
||||
log_error("add_index_bin_test internal error generating bin assignments: bin %d has more entries (%d) than max_counts_per_bin (%d).\n", bin, l_bin_counts[bin], max_counts_per_bin);
|
||||
log_error("add_index_bin_test internal error generating bin "
|
||||
"assignments: bin %d >= number_of_bins %d.\n",
|
||||
bin, number_of_bins);
|
||||
if (l_bin_counts[bin] + 1 > max_counts_per_bin)
|
||||
log_error(
|
||||
"add_index_bin_test internal error generating bin assignments: "
|
||||
"bin %d has more entries (%d) than max_counts_per_bin (%d).\n",
|
||||
bin, l_bin_counts[bin], max_counts_per_bin);
|
||||
l_bin_counts[bin]++;
|
||||
l_bin_assignments[i] = bin;
|
||||
// log_info("item %d assigned to bin %d (%d items)\n", i, bin, l_bin_counts[bin]);
|
||||
// log_info("item %d assigned to bin %d (%d items)\n", i, bin,
|
||||
// l_bin_counts[bin]);
|
||||
}
|
||||
err = clEnqueueWriteBuffer(queue, bin_assignments, true, 0, sizeof(cl_int)*number_of_items, l_bin_assignments, 0, NULL, NULL);
|
||||
if (err) {
|
||||
log_error("add_index_bin_test FAILED to set initial values for bin_assignments: %d\n", err);
|
||||
err = clEnqueueWriteBuffer(queue, bin_assignments, true, 0,
|
||||
sizeof(cl_int) * number_of_items,
|
||||
l_bin_assignments, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to set initial values for "
|
||||
"bin_assignments: %d\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
// Setup the kernel
|
||||
err = clSetKernelArg(kernel, 0, sizeof(bin_counters), &bin_counters);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof(bins), &bins);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof(bin_assignments), &bin_assignments);
|
||||
err |= clSetKernelArg(kernel, 3, sizeof(max_counts_per_bin), &max_counts_per_bin);
|
||||
if (err) {
|
||||
log_error("add_index_bin_test FAILED to set kernel arguments: %d\n", err);
|
||||
fail=1; succeed=-1;
|
||||
err |= clSetKernelArg(kernel, 3, sizeof(max_counts_per_bin),
|
||||
&max_counts_per_bin);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to set kernel arguments: %d\n",
|
||||
err);
|
||||
fail = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL );
|
||||
if (err) {
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_threads,
|
||||
local_threads, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to execute kernel: %d\n", err);
|
||||
fail=1; succeed=-1;
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
cl_int *final_bin_assignments = (cl_int*)malloc(sizeof(cl_int)*number_of_bins*max_counts_per_bin);
|
||||
if (!final_bin_assignments) {
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for final_bin_assignments.\n");
|
||||
cl_int *final_bin_assignments =
|
||||
(cl_int *)malloc(sizeof(cl_int) * number_of_bins * max_counts_per_bin);
|
||||
if (!final_bin_assignments)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for "
|
||||
"final_bin_assignments.\n");
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueReadBuffer( queue, bins, true, 0, sizeof(cl_int)*number_of_bins*max_counts_per_bin, final_bin_assignments, 0, NULL, NULL );
|
||||
if (err) {
|
||||
err = clEnqueueReadBuffer(queue, bins, true, 0,
|
||||
sizeof(cl_int) * number_of_bins
|
||||
* max_counts_per_bin,
|
||||
final_bin_assignments, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to read back bins: %d\n", err);
|
||||
fail = 1; succeed=-1;
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
cl_int *final_bin_counts = (cl_int*)malloc(sizeof(cl_int)*number_of_bins);
|
||||
if (!final_bin_counts) {
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for final_bin_counts.\n");
|
||||
cl_int *final_bin_counts =
|
||||
(cl_int *)malloc(sizeof(cl_int) * number_of_bins);
|
||||
if (!final_bin_counts)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to allocate initial values for "
|
||||
"final_bin_counts.\n");
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueReadBuffer( queue, bin_counters, true, 0, sizeof(cl_int)*number_of_bins, final_bin_counts, 0, NULL, NULL );
|
||||
if (err) {
|
||||
log_error("add_index_bin_test FAILED to read back bin_counters: %d\n", err);
|
||||
fail = 1; succeed=-1;
|
||||
err = clEnqueueReadBuffer(queue, bin_counters, true, 0,
|
||||
sizeof(cl_int) * number_of_bins, final_bin_counts,
|
||||
0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to read back bin_counters: %d\n",
|
||||
err);
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
// Verification.
|
||||
int errors=0;
|
||||
int errors = 0;
|
||||
int current_bin;
|
||||
int search;
|
||||
// Print out all the contents of the bins.
|
||||
// for (current_bin=0; current_bin<number_of_bins; current_bin++)
|
||||
// for (search=0; search<max_counts_per_bin; search++)
|
||||
// log_info("[bin %d, entry %d] = %d\n", current_bin, search, final_bin_assignments[current_bin*max_counts_per_bin+search]);
|
||||
// log_info("[bin %d, entry %d] = %d\n", current_bin, search,
|
||||
// final_bin_assignments[current_bin*max_counts_per_bin+search]);
|
||||
|
||||
// First verify that there are the correct number in each bin.
|
||||
for (current_bin=0; current_bin<number_of_bins; current_bin++) {
|
||||
for (current_bin = 0; current_bin < number_of_bins; current_bin++)
|
||||
{
|
||||
int expected_number = l_bin_counts[current_bin];
|
||||
int actual_number = final_bin_counts[current_bin];
|
||||
if (expected_number != actual_number) {
|
||||
log_error("add_index_bin_test FAILED: bin %d reported %d entries when %d were expected.\n", current_bin, actual_number, expected_number);
|
||||
if (expected_number != actual_number)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED: bin %d reported %d entries "
|
||||
"when %d were expected.\n",
|
||||
current_bin, actual_number, expected_number);
|
||||
errors++;
|
||||
}
|
||||
for (search=0; search<expected_number; search++) {
|
||||
if (final_bin_assignments[current_bin*max_counts_per_bin+search] == -1) {
|
||||
log_error("add_index_bin_test FAILED: bin %d had no entry at position %d when it should have had %d entries.\n", current_bin, search, expected_number);
|
||||
for (search = 0; search < expected_number; search++)
|
||||
{
|
||||
if (final_bin_assignments[current_bin * max_counts_per_bin + search]
|
||||
== -1)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED: bin %d had no entry at "
|
||||
"position %d when it should have had %d entries.\n",
|
||||
current_bin, search, expected_number);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
for (search=expected_number; search<max_counts_per_bin; search++) {
|
||||
if (final_bin_assignments[current_bin*max_counts_per_bin+search] != -1) {
|
||||
log_error("add_index_bin_test FAILED: bin %d had an extra entry at position %d when it should have had only %d entries.\n", current_bin, search, expected_number);
|
||||
for (search = expected_number; search < max_counts_per_bin; search++)
|
||||
{
|
||||
if (final_bin_assignments[current_bin * max_counts_per_bin + search]
|
||||
!= -1)
|
||||
{
|
||||
log_error(
|
||||
"add_index_bin_test FAILED: bin %d had an extra entry at "
|
||||
"position %d when it should have had only %d entries.\n",
|
||||
current_bin, search, expected_number);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now verify that the correct ones are in each bin
|
||||
int index;
|
||||
for (index=0; index<number_of_items; index++) {
|
||||
for (index = 0; index < number_of_items; index++)
|
||||
{
|
||||
int expected_bin = l_bin_assignments[index];
|
||||
int found_it = 0;
|
||||
for (search=0; search<l_bin_counts[expected_bin]; search++) {
|
||||
if (final_bin_assignments[expected_bin*max_counts_per_bin+search] == index) {
|
||||
for (search = 0; search < l_bin_counts[expected_bin]; search++)
|
||||
{
|
||||
if (final_bin_assignments[expected_bin * max_counts_per_bin
|
||||
+ search]
|
||||
== index)
|
||||
{
|
||||
found_it = 1;
|
||||
}
|
||||
}
|
||||
if (found_it == 0) {
|
||||
log_error("add_index_bin_test FAILED: did not find item %d in bin %d.\n", index, expected_bin);
|
||||
if (found_it == 0)
|
||||
{
|
||||
log_error(
|
||||
"add_index_bin_test FAILED: did not find item %d in bin %d.\n",
|
||||
index, expected_bin);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
|
@ -341,41 +469,49 @@ int add_index_bin_test(size_t *global_threads, cl_command_queue queue, cl_contex
|
|||
clReleaseMemObject(bin_counters);
|
||||
clReleaseMemObject(bins);
|
||||
clReleaseMemObject(bin_assignments);
|
||||
if (errors == 0) {
|
||||
log_info("add_index_bin_test passed. Each item was put in the correct bin in parallel.\n");
|
||||
if (errors == 0)
|
||||
{
|
||||
log_info("add_index_bin_test passed. Each item was put in the correct "
|
||||
"bin in parallel.\n");
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("add_index_bin_test FAILED: %d errors.\n", errors);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int test_atomic_add_index_bin(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
int test_atomic_add_index_bin(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
//===== add_index_bin test
|
||||
size_t numGlobalThreads = 2048;
|
||||
int iteration=0;
|
||||
int iteration = 0;
|
||||
int err, failed = 0;
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
MTdata d = init_genrand(gRandomSeed);
|
||||
|
||||
/* Check if atomics are supported. */
|
||||
if (!is_extension_available(deviceID, "cl_khr_global_int32_base_atomics")) {
|
||||
log_info("Base atomics not supported (cl_khr_global_int32_base_atomics). Skipping test.\n");
|
||||
free_mtdata( d );
|
||||
return 0;
|
||||
}
|
||||
/* Check if atomics are supported. */
|
||||
if (!is_extension_available(deviceID, "cl_khr_global_int32_base_atomics"))
|
||||
{
|
||||
log_info("Base atomics not supported "
|
||||
"(cl_khr_global_int32_base_atomics). Skipping test.\n");
|
||||
free_mtdata(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(iteration=0; iteration<10; iteration++) {
|
||||
log_info("add_index_bin_test with %d elements:\n", (int)numGlobalThreads);
|
||||
err = add_index_bin_test(&numGlobalThreads, queue, context, d);
|
||||
if (err) {
|
||||
for (iteration = 0; iteration < 10; iteration++)
|
||||
{
|
||||
log_info("add_index_bin_test with %d elements:\n",
|
||||
(int)numGlobalThreads);
|
||||
err = add_index_bin_test(&numGlobalThreads, queue, context, d);
|
||||
if (err)
|
||||
{
|
||||
failed++;
|
||||
break;
|
||||
}
|
||||
numGlobalThreads*=2;
|
||||
numGlobalThreads *= 2;
|
||||
}
|
||||
free_mtdata( d );
|
||||
free_mtdata(d);
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@ set(MODULE_NAME BASIC)
|
|||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
main.cpp
|
||||
test_fpmath_float.cpp test_fpmath_float2.cpp test_fpmath_float4.cpp
|
||||
test_fpmath_float.cpp
|
||||
test_intmath.cpp
|
||||
test_hiloeo.cpp test_local.cpp test_pointercast.cpp
|
||||
test_if.cpp test_loop.cpp
|
||||
test_readimage.cpp test_readimage_int16.cpp test_readimage_fp32.cpp
|
||||
test_readimage3d.cpp test_readimage3d_int16.cpp test_readimage3d_fp32.cpp
|
||||
test_writeimage.cpp test_writeimage_int16.cpp test_writeimage_fp32.cpp
|
||||
test_readimage.cpp
|
||||
test_writeimage.cpp
|
||||
test_multireadimageonefmt.cpp test_multireadimagemultifmt.cpp
|
||||
test_imagedim.cpp
|
||||
test_vloadstore.cpp
|
||||
|
|
@ -31,7 +30,6 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_imagecopy.cpp
|
||||
test_imagerandomcopy.cpp
|
||||
test_arrayimagecopy.cpp
|
||||
test_arrayimagecopy3d.cpp
|
||||
test_imagecopy3d.cpp
|
||||
test_enqueue_map.cpp
|
||||
test_work_item_functions.cpp
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
#include "harness/conversions.h"
|
||||
#include "harness/rounding_mode.h"
|
||||
|
||||
extern void memset_pattern4(void *dest, const void *src_pattern, size_t bytes );
|
||||
|
||||
extern int test_hostptr(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_fpmath_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_fpmath_float2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
|
|
|||
|
|
@ -181,9 +181,8 @@ test_arraycopy(cl_device_id device, cl_context context, cl_command_queue queue,
|
|||
}
|
||||
}
|
||||
|
||||
// Keep track of multiple errors.
|
||||
if (error_count != 0)
|
||||
err = error_count;
|
||||
// Keep track of multiple errors.
|
||||
if (error_count != 0) err = error_count;
|
||||
|
||||
if (err)
|
||||
log_error("\tCL_MEM_USE_HOST_PTR buffer with kernel copy FAILED\n");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -14,134 +14,173 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
#include "harness/imageHelpers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
int test_arrayimagecopy_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format)
|
||||
int test_arrayimagecopy_single_format(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue,
|
||||
cl_mem_flags flags,
|
||||
cl_mem_object_type image_type,
|
||||
const cl_image_format *format)
|
||||
{
|
||||
cl_uchar *bufptr, *imgptr;
|
||||
clMemWrapper buffer, image;
|
||||
int img_width = 512;
|
||||
int img_height = 512;
|
||||
size_t elem_size;
|
||||
size_t buffer_size;
|
||||
int i;
|
||||
cl_int err;
|
||||
MTdata d;
|
||||
cl_event copyevent;
|
||||
cl_uchar *bufptr, *imgptr;
|
||||
clMemWrapper buffer, image;
|
||||
int img_width = 512;
|
||||
int img_height = 512;
|
||||
int img_depth = (image_type == CL_MEM_OBJECT_IMAGE3D) ? 32 : 1;
|
||||
size_t elem_size;
|
||||
size_t buffer_size;
|
||||
cl_int err;
|
||||
cl_event copyevent;
|
||||
|
||||
log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type));
|
||||
log_info("Testing %s %s\n",
|
||||
GetChannelOrderName(format->image_channel_order),
|
||||
GetChannelTypeName(format->image_channel_data_type));
|
||||
|
||||
image = create_image_2d(context, CL_MEM_READ_WRITE, format, img_width,
|
||||
img_height, 0, NULL, &err);
|
||||
test_error(err, "create_image_2d failed");
|
||||
|
||||
err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL);
|
||||
test_error(err, "clGetImageInfo failed");
|
||||
|
||||
buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height;
|
||||
|
||||
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_size, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
bufptr = (cl_uchar*)malloc(buffer_size);
|
||||
for (i=0; i<(int)buffer_size; i++) {
|
||||
bufptr[i] = (cl_uchar)genrand_int32(d);
|
||||
}
|
||||
free_mtdata(d); d = NULL;
|
||||
|
||||
size_t origin[3]={0,0,0}, region[3]={img_width,img_height,1};
|
||||
err = clEnqueueWriteBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
|
||||
err = clEnqueueCopyBufferToImage( queue, buffer, image, 0, origin, region, 0, NULL, ©event );
|
||||
test_error(err, "clEnqueueCopyImageToBuffer failed");
|
||||
|
||||
imgptr = (cl_uchar*)malloc(buffer_size);
|
||||
|
||||
err = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 1, ©event, NULL );
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
err = clReleaseEvent(copyevent);
|
||||
test_error(err, "clReleaseEvent failed");
|
||||
|
||||
if (memcmp(bufptr, imgptr, buffer_size) != 0) {
|
||||
log_error( "ERROR: Results did not validate!\n" );
|
||||
unsigned char * inchar = (unsigned char*)bufptr;
|
||||
unsigned char * outchar = (unsigned char*)imgptr;
|
||||
int failuresPrinted = 0;
|
||||
int i;
|
||||
for (i=0; i< (int)buffer_size; i+=(int)elem_size) {
|
||||
int failed = 0;
|
||||
int j;
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
if (inchar[i+j] != outchar[i+j])
|
||||
failed = 1;
|
||||
char values[4096];
|
||||
values[0] = 0;
|
||||
if (failed) {
|
||||
sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i);
|
||||
int j;
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", inchar[i+j]);
|
||||
sprintf(values + strlen(values), "] != expected [");
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", outchar[i+j]);
|
||||
sprintf(values + strlen(values), "]");
|
||||
log_error("%s\n", values);
|
||||
failuresPrinted++;
|
||||
}
|
||||
if (failuresPrinted > 5) {
|
||||
log_error("Not printing further failures...\n");
|
||||
break;
|
||||
}
|
||||
if (CL_MEM_OBJECT_IMAGE2D == image_type)
|
||||
{
|
||||
image = create_image_2d(context, flags, format, img_width, img_height,
|
||||
0, nullptr, &err);
|
||||
}
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
image = create_image_3d(context, flags, format, img_width, img_height,
|
||||
img_depth, 0, 0, nullptr, &err);
|
||||
}
|
||||
test_error(err, "create_image_xd failed");
|
||||
|
||||
free(bufptr);
|
||||
free(imgptr);
|
||||
err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t),
|
||||
&elem_size, NULL);
|
||||
test_error(err, "clGetImageInfo failed");
|
||||
|
||||
if (err)
|
||||
log_error("ARRAY to IMAGE copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n",
|
||||
(unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type);
|
||||
buffer_size =
|
||||
sizeof(cl_uchar) * elem_size * img_width * img_height * img_depth;
|
||||
|
||||
return err;
|
||||
buffer =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_size, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
RandomSeed seed(gRandomSeed);
|
||||
bufptr =
|
||||
static_cast<cl_uchar *>(create_random_data(kUChar, seed, buffer_size));
|
||||
|
||||
size_t origin[3] = { 0, 0, 0 },
|
||||
region[3] = { img_width, img_height, img_depth };
|
||||
err = clEnqueueWriteBuffer(queue, buffer, CL_TRUE, 0, buffer_size, bufptr,
|
||||
0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
|
||||
err = clEnqueueCopyBufferToImage(queue, buffer, image, 0, origin, region, 0,
|
||||
NULL, ©event);
|
||||
test_error(err, "clEnqueueCopyImageToBuffer failed");
|
||||
|
||||
imgptr = static_cast<cl_uchar *>(malloc(buffer_size));
|
||||
|
||||
err = clEnqueueReadImage(queue, image, CL_TRUE, origin, region, 0, 0,
|
||||
imgptr, 1, ©event, NULL);
|
||||
test_error(err, "clEnqueueReadImage failed");
|
||||
|
||||
err = clReleaseEvent(copyevent);
|
||||
test_error(err, "clReleaseEvent failed");
|
||||
|
||||
if (memcmp(bufptr, imgptr, buffer_size) != 0)
|
||||
{
|
||||
log_error("ERROR: Results did not validate!\n");
|
||||
auto inchar = static_cast<unsigned char *>(bufptr);
|
||||
auto outchar = static_cast<unsigned char *>(imgptr);
|
||||
int failuresPrinted = 0;
|
||||
for (int i = 0; i < (int)buffer_size; i += (int)elem_size)
|
||||
{
|
||||
if (memcmp(&inchar[i], &outchar[i], elem_size) != 0)
|
||||
{
|
||||
log_error("%d(0x%x) -> actual [", i, i);
|
||||
for (int j = 0; j < (int)elem_size; j++)
|
||||
log_error("0x%02x ", inchar[i + j]);
|
||||
log_error("] != expected [");
|
||||
for (int j = 0; j < (int)elem_size; j++)
|
||||
log_error("0x%02x ", outchar[i + j]);
|
||||
log_error("]\n");
|
||||
failuresPrinted++;
|
||||
}
|
||||
if (failuresPrinted > 5)
|
||||
{
|
||||
log_error("Not printing further failures...\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = -1;
|
||||
}
|
||||
|
||||
free(bufptr);
|
||||
free(imgptr);
|
||||
|
||||
if (err)
|
||||
log_error(
|
||||
"ARRAY to IMAGE copy test failed for image_channel_order=0x%lx and "
|
||||
"image_channel_data_type=0x%lx\n",
|
||||
(unsigned long)format->image_channel_order,
|
||||
(unsigned long)format->image_channel_data_type);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_arrayimagecopy(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
|
||||
int test_arrayimagecommon(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, cl_mem_flags flags,
|
||||
cl_mem_object_type image_type)
|
||||
{
|
||||
cl_int err;
|
||||
cl_image_format *formats;
|
||||
cl_uint num_formats;
|
||||
cl_uint i;
|
||||
cl_int err;
|
||||
cl_uint num_formats;
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT( device )
|
||||
err = clGetSupportedImageFormats(context, flags, image_type, 0, NULL,
|
||||
&num_formats);
|
||||
test_error(err, "clGetSupportedImageFormats failed");
|
||||
|
||||
err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &num_formats);
|
||||
test_error(err, "clGetSupportedImageFormats failed");
|
||||
std::vector<cl_image_format> formats(num_formats);
|
||||
|
||||
formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format));
|
||||
err = clGetSupportedImageFormats(context, flags, image_type, num_formats,
|
||||
formats.data(), NULL);
|
||||
test_error(err, "clGetSupportedImageFormats failed");
|
||||
|
||||
err = clGetSupportedImageFormats(context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, num_formats, formats, NULL);
|
||||
test_error(err, "clGetSupportedImageFormats failed");
|
||||
for (const auto &format : formats)
|
||||
{
|
||||
err |= test_arrayimagecopy_single_format(device, context, queue, flags,
|
||||
image_type, &format);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_formats; i++) {
|
||||
err |= test_arrayimagecopy_single_format(device, context, queue, &formats[i]);
|
||||
}
|
||||
if (err)
|
||||
log_error("ARRAY to IMAGE%s copy test failed\n",
|
||||
convert_image_type_to_string(image_type));
|
||||
else
|
||||
log_info("ARRAY to IMAGE%s copy test passed\n",
|
||||
convert_image_type_to_string(image_type));
|
||||
|
||||
free(formats);
|
||||
if (err)
|
||||
log_error("ARRAY to IMAGE copy test failed\n");
|
||||
else
|
||||
log_info("ARRAY to IMAGE copy test passed\n");
|
||||
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_arrayimagecopy(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT(device)
|
||||
|
||||
return test_arrayimagecommon(device, context, queue, CL_MEM_READ_WRITE,
|
||||
CL_MEM_OBJECT_IMAGE2D);
|
||||
}
|
||||
|
||||
|
||||
int test_arrayimagecopy3d(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(device)
|
||||
|
||||
return test_arrayimagecommon(device, context, queue, CL_MEM_READ_ONLY,
|
||||
CL_MEM_OBJECT_IMAGE3D);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,151 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
int test_arrayimagecopy3d_single_format(cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format)
|
||||
{
|
||||
cl_uchar *bufptr, *imgptr;
|
||||
clMemWrapper buffer, image;
|
||||
int img_width = 128;
|
||||
int img_height = 128;
|
||||
int img_depth = 32;
|
||||
size_t elem_size;
|
||||
size_t buffer_size;
|
||||
int i;
|
||||
cl_int err;
|
||||
MTdata d;
|
||||
cl_event copyevent;
|
||||
|
||||
log_info("Testing %s %s\n", GetChannelOrderName(format->image_channel_order), GetChannelTypeName(format->image_channel_data_type));
|
||||
|
||||
image = create_image_3d(context, CL_MEM_READ_ONLY, format, img_width,
|
||||
img_height, img_depth, 0, 0, NULL, &err);
|
||||
test_error(err, "create_image_3d failed");
|
||||
|
||||
err = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(size_t), &elem_size, NULL);
|
||||
test_error(err, "clGetImageInfo failed");
|
||||
|
||||
buffer_size = sizeof(cl_uchar) * elem_size * img_width * img_height * img_depth;
|
||||
|
||||
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_size, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
bufptr = (cl_uchar*)malloc(buffer_size);
|
||||
for (i=0; i<(int)buffer_size; i++) {
|
||||
bufptr[i] = (cl_uchar)genrand_int32(d);
|
||||
}
|
||||
free_mtdata(d); d = NULL;
|
||||
|
||||
size_t origin[3]={0,0,0}, region[3]={img_width,img_height,img_depth};
|
||||
err = clEnqueueWriteBuffer( queue, buffer, CL_TRUE, 0, buffer_size, bufptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
|
||||
err = clEnqueueCopyBufferToImage( queue, buffer, image, 0, origin, region, 0, NULL, ©event );
|
||||
test_error(err, "clEnqueueCopyImageToBuffer failed");
|
||||
|
||||
imgptr = (cl_uchar*)malloc(buffer_size);
|
||||
|
||||
err = clEnqueueReadImage( queue, image, CL_TRUE, origin, region, 0, 0, imgptr, 1, ©event, NULL );
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
err = clReleaseEvent(copyevent);
|
||||
test_error(err, "clReleaseEvent failed");
|
||||
|
||||
if (memcmp(bufptr, imgptr, buffer_size) != 0) {
|
||||
log_error( "ERROR: Results did not validate!\n" );
|
||||
unsigned char * inchar = (unsigned char*)bufptr;
|
||||
unsigned char * outchar = (unsigned char*)imgptr;
|
||||
int failuresPrinted = 0;
|
||||
int i;
|
||||
for (i=0; i< (int)buffer_size; i+=(int)elem_size) {
|
||||
int failed = 0;
|
||||
int j;
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
if (inchar[i+j] != outchar[i+j])
|
||||
failed = 1;
|
||||
char values[4096];
|
||||
values[0] = 0;
|
||||
if (failed) {
|
||||
sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i);
|
||||
int j;
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", inchar[i+j]);
|
||||
sprintf(values + strlen(values), "] != expected [");
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", outchar[i+j]);
|
||||
sprintf(values + strlen(values), "]");
|
||||
log_error("%s\n", values);
|
||||
failuresPrinted++;
|
||||
}
|
||||
if (failuresPrinted > 5) {
|
||||
log_error("Not printing further failures...\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
err = -1;
|
||||
}
|
||||
|
||||
free(bufptr);
|
||||
free(imgptr);
|
||||
|
||||
if (err)
|
||||
log_error("ARRAY to IMAGE3D copy test failed for image_channel_order=0x%lx and image_channel_data_type=0x%lx\n",
|
||||
(unsigned long)format->image_channel_order, (unsigned long)format->image_channel_data_type);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_arrayimagecopy3d(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_int err;
|
||||
cl_image_format *formats;
|
||||
cl_uint num_formats;
|
||||
cl_uint i;
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device )
|
||||
|
||||
err = clGetSupportedImageFormats(
|
||||
context, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, 0, NULL, &num_formats);
|
||||
test_error(err, "clGetSupportedImageFormats failed");
|
||||
|
||||
formats = (cl_image_format *)malloc(num_formats * sizeof(cl_image_format));
|
||||
|
||||
err = clGetSupportedImageFormats(context, CL_MEM_READ_ONLY,
|
||||
CL_MEM_OBJECT_IMAGE3D, num_formats, formats,
|
||||
NULL);
|
||||
test_error(err, "clGetSupportedImageFormats failed");
|
||||
|
||||
for (i = 0; i < num_formats; i++) {
|
||||
err |= test_arrayimagecopy3d_single_format(device, context, queue, &formats[i]);
|
||||
}
|
||||
|
||||
free(formats);
|
||||
if (err)
|
||||
log_error("ARRAY to IMAGE3D copy test failed\n");
|
||||
else
|
||||
log_info("ARRAY to IMAGE3D copy test passed\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -25,77 +25,81 @@
|
|||
#include "../../test_common/harness/conversions.h"
|
||||
#include "procs.h"
|
||||
|
||||
static const char *async_global_to_local_kernel2D =
|
||||
"#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable\n"
|
||||
"%s\n" // optional pragma string
|
||||
"__kernel void test_fn( const __global %s *src, __global %s *dst, __local "
|
||||
"%s *localBuffer, int numElementsPerLine, int lineCopiesPerWorkgroup, int "
|
||||
"lineCopiesPerWorkItem, int srcStride, int dstStride )\n"
|
||||
"{\n"
|
||||
" int i, j;\n"
|
||||
// Zero the local storage first
|
||||
" for(i=0; i<lineCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numElementsPerLine; j++)\n"
|
||||
" localBuffer[ (get_local_id( 0 "
|
||||
")*lineCopiesPerWorkItem+i)*(numElementsPerLine + dstStride)+j ] = "
|
||||
"(%s)(%s)0;\n"
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we
|
||||
// try the copy
|
||||
" barrier( CLK_LOCAL_MEM_FENCE );\n"
|
||||
" event_t event;\n"
|
||||
" event = async_work_group_copy_2D2D( (__local %s*)localBuffer, "
|
||||
"(__global const "
|
||||
"%s*)(src+lineCopiesPerWorkgroup*get_group_id(0)*(numElementsPerLine + "
|
||||
"srcStride)), (size_t)numElementsPerLine, (size_t)lineCopiesPerWorkgroup, "
|
||||
"srcStride, dstStride, 0 );\n"
|
||||
// Wait for the copy to complete, then verify by manually copying to the
|
||||
// dest
|
||||
" wait_group_events( 1, &event );\n"
|
||||
" for(i=0; i<lineCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numElementsPerLine; j++)\n"
|
||||
" dst[ (get_global_id( 0 "
|
||||
")*lineCopiesPerWorkItem+i)*(numElementsPerLine + dstStride)+j ] = "
|
||||
"localBuffer[ (get_local_id( 0 "
|
||||
")*lineCopiesPerWorkItem+i)*(numElementsPerLine + dstStride)+j ];\n"
|
||||
"}\n";
|
||||
static const char *async_global_to_local_kernel2D = R"OpenCLC(
|
||||
#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable
|
||||
%s // optional pragma string
|
||||
|
||||
static const char *async_local_to_global_kernel2D =
|
||||
"#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable\n"
|
||||
"%s\n" // optional pragma string
|
||||
"__kernel void test_fn( const __global %s *src, __global %s *dst, __local "
|
||||
"%s *localBuffer, int numElementsPerLine, int lineCopiesPerWorkgroup, int "
|
||||
"lineCopiesPerWorkItem, int srcStride, int dstStride )\n"
|
||||
"{\n"
|
||||
" int i, j;\n"
|
||||
// Zero the local storage first
|
||||
" for(i=0; i<lineCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numElementsPerLine; j++)\n"
|
||||
" localBuffer[ (get_local_id( 0 "
|
||||
")*lineCopiesPerWorkItem+i)*(numElementsPerLine + srcStride)+j ] = "
|
||||
"(%s)(%s)0;\n"
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we
|
||||
// try the copy
|
||||
" barrier( CLK_LOCAL_MEM_FENCE );\n"
|
||||
" for(i=0; i<lineCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numElementsPerLine; j++)\n"
|
||||
" localBuffer[ (get_local_id( 0 "
|
||||
")*lineCopiesPerWorkItem+i)*(numElementsPerLine + srcStride)+j ] = src[ "
|
||||
"(get_global_id( 0 )*lineCopiesPerWorkItem+i)*(numElementsPerLine + "
|
||||
"srcStride)+j ];\n"
|
||||
// Do this to verify all kernels are done copying to the local buffer before
|
||||
// we try the copy
|
||||
" barrier( CLK_LOCAL_MEM_FENCE );\n"
|
||||
" event_t event;\n"
|
||||
" event = async_work_group_copy_2D2D((__global "
|
||||
"%s*)(dst+lineCopiesPerWorkgroup*get_group_id(0)*(numElementsPerLine + "
|
||||
"dstStride)), (__local const %s*)localBuffer, (size_t)numElementsPerLine, "
|
||||
"(size_t)lineCopiesPerWorkgroup, srcStride, dstStride, 0 );\n"
|
||||
" wait_group_events( 1, &event );\n"
|
||||
"}\n";
|
||||
__kernel void test_fn(const __global %s *src, __global %s *dst,
|
||||
__local %s *localBuffer, int numElementsPerLine,
|
||||
int lineCopiesPerWorkgroup, int lineCopiesPerWorkItem,
|
||||
int srcStride, int dstStride) {
|
||||
// Zero the local storage first
|
||||
for (int i = 0; i < lineCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numElementsPerLine; j++) {
|
||||
const int index = (get_local_id(0) * lineCopiesPerWorkItem + i) * dstStride + j;
|
||||
localBuffer[index] = (%s)(%s)0;
|
||||
}
|
||||
}
|
||||
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we
|
||||
// try the copy
|
||||
barrier( CLK_LOCAL_MEM_FENCE );
|
||||
event_t event = async_work_group_copy_2D2D(localBuffer, 0, src,
|
||||
lineCopiesPerWorkgroup * get_group_id(0) * srcStride, sizeof(%s),
|
||||
(size_t)numElementsPerLine, (size_t)lineCopiesPerWorkgroup, srcStride, dstStride, 0);
|
||||
|
||||
// Wait for the copy to complete, then verify by manually copying to the dest
|
||||
wait_group_events(1, &event);
|
||||
|
||||
for (int i = 0; i < lineCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numElementsPerLine; j++) {
|
||||
const int local_index = (get_local_id(0) * lineCopiesPerWorkItem + i) * dstStride + j;
|
||||
const int global_index = (get_global_id(0) * lineCopiesPerWorkItem + i) * dstStride + j;
|
||||
dst[global_index] = localBuffer[local_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
)OpenCLC";
|
||||
|
||||
static const char *async_local_to_global_kernel2D = R"OpenCLC(
|
||||
#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable
|
||||
%s // optional pragma string
|
||||
|
||||
__kernel void test_fn(const __global %s *src, __global %s *dst, __local %s *localBuffer,
|
||||
int numElementsPerLine, int lineCopiesPerWorkgroup,
|
||||
int lineCopiesPerWorkItem, int srcStride, int dstStride) {
|
||||
// Zero the local storage first
|
||||
for (int i = 0; i < lineCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numElementsPerLine; j++) {
|
||||
const int index = (get_local_id(0) * lineCopiesPerWorkItem + i) * srcStride + j;
|
||||
localBuffer[index] = (%s)(%s)0;
|
||||
}
|
||||
}
|
||||
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we try the copy
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int i = 0; i < lineCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numElementsPerLine; j++) {
|
||||
const int local_index = (get_local_id(0) * lineCopiesPerWorkItem + i) * srcStride + j;
|
||||
const int global_index = (get_global_id(0)*lineCopiesPerWorkItem + i) * srcStride + j;
|
||||
localBuffer[local_index] = src[global_index];
|
||||
}
|
||||
}
|
||||
|
||||
// Do this to verify all kernels are done copying to the local buffer before we try the copy
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
event_t event = async_work_group_copy_2D2D(dst, lineCopiesPerWorkgroup * get_group_id(0) * dstStride,
|
||||
localBuffer, 0, sizeof(%s), (size_t)numElementsPerLine, (size_t)lineCopiesPerWorkgroup, srcStride,
|
||||
dstStride, 0 );
|
||||
|
||||
wait_group_events(1, &event);
|
||||
};
|
||||
)OpenCLC";
|
||||
|
||||
int test_copy2D(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, const char *kernelCode,
|
||||
ExplicitType vecType, int vecSize, int srcStride, int dstStride,
|
||||
ExplicitType vecType, int vecSize, int srcMargin, int dstMargin,
|
||||
bool localIsDst)
|
||||
{
|
||||
int error;
|
||||
|
|
@ -114,15 +118,8 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
vecSize);
|
||||
|
||||
size_t elementSize = get_explicit_type_size(vecType) * vecSize;
|
||||
log_info("Testing %s with srcStride = %d, dstStride = %d\n", vecNameString,
|
||||
srcStride, dstStride);
|
||||
|
||||
if (!is_extension_available(deviceID, "cl_khr_extended_async_copies"))
|
||||
{
|
||||
log_info(
|
||||
"Device does not support extended async copies. Skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
log_info("Testing %s with srcMargin = %d, dstMargin = %d\n", vecNameString,
|
||||
srcMargin, dstMargin);
|
||||
|
||||
cl_long max_local_mem_size;
|
||||
error =
|
||||
|
|
@ -160,7 +157,7 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"
|
||||
: "",
|
||||
vecNameString, vecNameString, vecNameString, vecNameString,
|
||||
get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
get_explicit_type_name(vecType), vecNameString);
|
||||
// log_info("program: %s\n", programSource);
|
||||
programPtr = programSource;
|
||||
|
||||
|
|
@ -187,12 +184,17 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
if (max_workgroup_size > max_local_workgroup_size[0])
|
||||
max_workgroup_size = max_local_workgroup_size[0];
|
||||
|
||||
size_t numElementsPerLine = 10;
|
||||
size_t lineCopiesPerWorkItem = 13;
|
||||
const size_t numElementsPerLine = 10;
|
||||
const cl_int dstStride = numElementsPerLine + dstMargin;
|
||||
const cl_int srcStride = numElementsPerLine + srcMargin;
|
||||
|
||||
elementSize =
|
||||
get_explicit_type_size(vecType) * ((vecSize == 3) ? 4 : vecSize);
|
||||
size_t localStorageSpacePerWorkitem = lineCopiesPerWorkItem * elementSize
|
||||
* (numElementsPerLine + (localIsDst ? dstStride : srcStride));
|
||||
|
||||
const size_t lineCopiesPerWorkItem = 13;
|
||||
const size_t localStorageSpacePerWorkitem = lineCopiesPerWorkItem
|
||||
* elementSize * (localIsDst ? dstStride : srcStride);
|
||||
|
||||
size_t maxLocalWorkgroupSize =
|
||||
(((int)max_local_mem_size / 2) / localStorageSpacePerWorkitem);
|
||||
|
||||
|
|
@ -206,34 +208,39 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
if (maxLocalWorkgroupSize > max_workgroup_size)
|
||||
localWorkgroupSize = max_workgroup_size;
|
||||
|
||||
size_t maxTotalLinesIn = (max_alloc_size / elementSize + srcStride)
|
||||
/ (numElementsPerLine + srcStride);
|
||||
size_t maxTotalLinesOut = (max_alloc_size / elementSize + dstStride)
|
||||
/ (numElementsPerLine + dstStride);
|
||||
size_t maxTotalLines = (std::min)(maxTotalLinesIn, maxTotalLinesOut);
|
||||
size_t maxLocalWorkgroups =
|
||||
|
||||
const size_t maxTotalLinesIn =
|
||||
(max_alloc_size / elementSize + srcMargin) / srcStride;
|
||||
const size_t maxTotalLinesOut =
|
||||
(max_alloc_size / elementSize + dstMargin) / dstStride;
|
||||
const size_t maxTotalLines = std::min(maxTotalLinesIn, maxTotalLinesOut);
|
||||
const size_t maxLocalWorkgroups =
|
||||
maxTotalLines / (localWorkgroupSize * lineCopiesPerWorkItem);
|
||||
|
||||
size_t localBufferSize = localWorkgroupSize * localStorageSpacePerWorkitem
|
||||
- (localIsDst ? dstStride : srcStride);
|
||||
size_t numberOfLocalWorkgroups = (std::min)(1111, (int)maxLocalWorkgroups);
|
||||
size_t totalLines =
|
||||
const size_t localBufferSize =
|
||||
localWorkgroupSize * localStorageSpacePerWorkitem
|
||||
- (localIsDst ? dstMargin : srcMargin);
|
||||
const size_t numberOfLocalWorkgroups =
|
||||
std::min(1111, (int)maxLocalWorkgroups);
|
||||
const size_t totalLines =
|
||||
numberOfLocalWorkgroups * localWorkgroupSize * lineCopiesPerWorkItem;
|
||||
size_t inBufferSize = elementSize
|
||||
* (totalLines * numElementsPerLine + (totalLines - 1) * srcStride);
|
||||
size_t outBufferSize = elementSize
|
||||
* (totalLines * numElementsPerLine + (totalLines - 1) * dstStride);
|
||||
size_t globalWorkgroupSize = numberOfLocalWorkgroups * localWorkgroupSize;
|
||||
const size_t inBufferSize = elementSize
|
||||
* (totalLines * numElementsPerLine + (totalLines - 1) * srcMargin);
|
||||
const size_t outBufferSize = elementSize
|
||||
* (totalLines * numElementsPerLine + (totalLines - 1) * dstMargin);
|
||||
const size_t globalWorkgroupSize =
|
||||
numberOfLocalWorkgroups * localWorkgroupSize;
|
||||
|
||||
inBuffer = (void *)malloc(inBufferSize);
|
||||
outBuffer = (void *)malloc(outBufferSize);
|
||||
outBufferCopy = (void *)malloc(outBufferSize);
|
||||
|
||||
cl_int lineCopiesPerWorkItemInt, numElementsPerLineInt,
|
||||
lineCopiesPerWorkgroup;
|
||||
lineCopiesPerWorkItemInt = (int)lineCopiesPerWorkItem;
|
||||
numElementsPerLineInt = (int)numElementsPerLine;
|
||||
lineCopiesPerWorkgroup = (int)(lineCopiesPerWorkItem * localWorkgroupSize);
|
||||
const cl_int lineCopiesPerWorkItemInt =
|
||||
static_cast<cl_int>(lineCopiesPerWorkItem);
|
||||
const cl_int numElementsPerLineInt =
|
||||
static_cast<cl_int>(numElementsPerLine);
|
||||
const cl_int lineCopiesPerWorkgroup =
|
||||
static_cast<cl_int>(lineCopiesPerWorkItem * localWorkgroupSize);
|
||||
|
||||
log_info(
|
||||
"Global: %d, local %d, local buffer %db, global in buffer %db, "
|
||||
|
|
@ -303,8 +310,8 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
for (int j = 0; j < (int)numElementsPerLine * elementSize;
|
||||
j += elementSize)
|
||||
{
|
||||
int inIdx = i * (numElementsPerLine + srcStride) + j;
|
||||
int outIdx = i * (numElementsPerLine + dstStride) + j;
|
||||
int inIdx = i * srcStride + j;
|
||||
int outIdx = i * dstStride + j;
|
||||
if (memcmp(((char *)inBuffer) + inIdx, ((char *)outBuffer) + outIdx,
|
||||
typeSize)
|
||||
!= 0)
|
||||
|
|
@ -339,11 +346,10 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
if (i < (int)(globalWorkgroupSize * lineCopiesPerWorkItem - 1)
|
||||
* elementSize)
|
||||
{
|
||||
int outIdx = i * (numElementsPerLine + dstStride)
|
||||
+ numElementsPerLine * elementSize;
|
||||
int outIdx = i * dstStride + numElementsPerLine * elementSize;
|
||||
if (memcmp(((char *)outBuffer) + outIdx,
|
||||
((char *)outBufferCopy) + outIdx,
|
||||
dstStride * elementSize)
|
||||
dstMargin * elementSize)
|
||||
!= 0)
|
||||
{
|
||||
if (failuresPrinted == 0)
|
||||
|
|
@ -380,12 +386,22 @@ int test_copy2D_all_types(cl_device_id deviceID, cl_context context,
|
|||
kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong,
|
||||
kULong, kFloat, kDouble, kNumExplicitTypes
|
||||
};
|
||||
// The margins below represent the number of elements between the end of
|
||||
// one line and the start of the next. The strides are equivalent to the
|
||||
// length of the line plus the chosen margin.
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int smallTypesStrideSizes[] = { 0, 10, 100 };
|
||||
unsigned int size, typeIndex, srcStride, dstStride;
|
||||
unsigned int smallTypesMarginSizes[] = { 0, 10, 100 };
|
||||
unsigned int size, typeIndex, srcMargin, dstMargin;
|
||||
|
||||
int errors = 0;
|
||||
|
||||
if (!is_extension_available(deviceID, "cl_khr_extended_async_copies"))
|
||||
{
|
||||
log_info(
|
||||
"Device does not support extended async copies. Skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (typeIndex = 0; vecType[typeIndex] != kNumExplicitTypes; typeIndex++)
|
||||
{
|
||||
if (vecType[typeIndex] == kDouble
|
||||
|
|
@ -401,19 +417,19 @@ int test_copy2D_all_types(cl_device_id deviceID, cl_context context,
|
|||
if (get_explicit_type_size(vecType[typeIndex]) * vecSizes[size]
|
||||
<= 2) // small type
|
||||
{
|
||||
for (srcStride = 0; srcStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
srcStride++)
|
||||
for (srcMargin = 0; srcMargin < sizeof(smallTypesMarginSizes)
|
||||
/ sizeof(smallTypesMarginSizes[0]);
|
||||
srcMargin++)
|
||||
{
|
||||
for (dstStride = 0;
|
||||
dstStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
dstStride++)
|
||||
for (dstMargin = 0;
|
||||
dstMargin < sizeof(smallTypesMarginSizes)
|
||||
/ sizeof(smallTypesMarginSizes[0]);
|
||||
dstMargin++)
|
||||
{
|
||||
if (test_copy2D(deviceID, context, queue, kernelCode,
|
||||
vecType[typeIndex], vecSizes[size],
|
||||
smallTypesStrideSizes[srcStride],
|
||||
smallTypesStrideSizes[dstStride],
|
||||
smallTypesMarginSizes[srcMargin],
|
||||
smallTypesMarginSizes[dstMargin],
|
||||
localIsDst))
|
||||
{
|
||||
errors++;
|
||||
|
|
|
|||
|
|
@ -25,96 +25,95 @@
|
|||
#include "../../test_common/harness/conversions.h"
|
||||
#include "procs.h"
|
||||
|
||||
static const char *async_global_to_local_kernel3D =
|
||||
"#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable\n"
|
||||
"%s\n" // optional pragma string
|
||||
"__kernel void test_fn( const __global %s *src, __global %s *dst, __local "
|
||||
"%s *localBuffer, int numElementsPerLine, int numLines, int "
|
||||
"planesCopiesPerWorkgroup, int planesCopiesPerWorkItem, int srcLineStride, "
|
||||
"int dstLineStride, int srcPlaneStride, int dstPlaneStride )\n"
|
||||
"{\n"
|
||||
" int i, j, k;\n"
|
||||
// Zero the local storage first
|
||||
" for(i=0; i<planesCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numLines; j++)\n"
|
||||
" for(k=0; k<numElementsPerLine; k++)\n"
|
||||
" localBuffer[ (get_local_id( 0 "
|
||||
")*planesCopiesPerWorkItem+i)*(numLines*numElementsPerLine + "
|
||||
"numLines*dstLineStride + dstPlaneStride) + j*(numElementsPerLine + "
|
||||
"dstLineStride) + k ] = (%s)(%s)0;\n"
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we
|
||||
// try the copy
|
||||
" barrier( CLK_LOCAL_MEM_FENCE );\n"
|
||||
" event_t event;\n"
|
||||
" event = async_work_group_copy_3D3D( (__local %s*)localBuffer, "
|
||||
"(__global const "
|
||||
"%s*)(src+planesCopiesPerWorkgroup*get_group_id(0)*(numLines*"
|
||||
"numElementsPerLine + numLines*srcLineStride + srcPlaneStride)), "
|
||||
"(size_t)numElementsPerLine, (size_t)numLines, srcLineStride, "
|
||||
"dstLineStride, planesCopiesPerWorkgroup, srcPlaneStride, dstPlaneStride, "
|
||||
"0 );\n"
|
||||
// Wait for the copy to complete, then verify by manually copying to the
|
||||
// dest
|
||||
" wait_group_events( 1, &event );\n"
|
||||
" for(i=0; i<planesCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numLines; j++)\n"
|
||||
" for(k=0; k<numElementsPerLine; k++)\n"
|
||||
" dst[ (get_global_id( 0 "
|
||||
")*planesCopiesPerWorkItem+i)*(numLines*numElementsPerLine + "
|
||||
"numLines*dstLineStride + dstPlaneStride) + j*(numElementsPerLine + "
|
||||
"dstLineStride) + k ] = localBuffer[ (get_local_id( 0 "
|
||||
")*planesCopiesPerWorkItem+i)*(numLines*numElementsPerLine + "
|
||||
"numLines*dstLineStride + dstPlaneStride) + j*(numElementsPerLine + "
|
||||
"dstLineStride) + k ];\n"
|
||||
"}\n";
|
||||
static const char *async_global_to_local_kernel3D = R"OpenCLC(
|
||||
#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable
|
||||
%s // optional pragma string
|
||||
|
||||
static const char *async_local_to_global_kernel3D =
|
||||
"#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable\n"
|
||||
"%s\n" // optional pragma string
|
||||
"__kernel void test_fn( const __global %s *src, __global %s *dst, __local "
|
||||
"%s *localBuffer, int numElementsPerLine, int numLines, int "
|
||||
"planesCopiesPerWorkgroup, int planesCopiesPerWorkItem, int srcLineStride, "
|
||||
"int dstLineStride, int srcPlaneStride, int dstPlaneStride )\n"
|
||||
"{\n"
|
||||
" int i, j, k;\n"
|
||||
// Zero the local storage first
|
||||
" for(i=0; i<planesCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numLines; j++)\n"
|
||||
" for(k=0; k<numElementsPerLine; k++)\n"
|
||||
" localBuffer[ (get_local_id( 0 "
|
||||
")*planesCopiesPerWorkItem+i)*(numLines*numElementsPerLine + "
|
||||
"numLines*srcLineStride + srcPlaneStride) + j*(numElementsPerLine + "
|
||||
"srcLineStride) + k ] = (%s)(%s)0;\n"
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we
|
||||
// try the copy
|
||||
" barrier( CLK_LOCAL_MEM_FENCE );\n"
|
||||
" for(i=0; i<planesCopiesPerWorkItem; i++)\n"
|
||||
" for(j=0; j<numLines; j++)\n"
|
||||
" for(k=0; k<numElementsPerLine; k++)\n"
|
||||
" localBuffer[ (get_local_id( 0 "
|
||||
")*planesCopiesPerWorkItem+i)*(numLines*numElementsPerLine + "
|
||||
"numLines*srcLineStride + srcPlaneStride) + j*(numElementsPerLine + "
|
||||
"srcLineStride) + k ] = src[ (get_global_id( 0 "
|
||||
")*planesCopiesPerWorkItem+i)*(numLines*numElementsPerLine + "
|
||||
"numLines*srcLineStride + srcPlaneStride) + j*(numElementsPerLine + "
|
||||
"srcLineStride) + k ];\n"
|
||||
// Do this to verify all kernels are done copying to the local buffer before
|
||||
// we try the copy
|
||||
" barrier( CLK_LOCAL_MEM_FENCE );\n"
|
||||
" event_t event;\n"
|
||||
" event = async_work_group_copy_3D3D((__global "
|
||||
"%s*)(dst+planesCopiesPerWorkgroup*get_group_id(0)*(numLines*"
|
||||
"numElementsPerLine + numLines*dstLineStride + dstPlaneStride)), (__local "
|
||||
"const %s*)localBuffer, (size_t)numElementsPerLine, (size_t)numLines, "
|
||||
"srcLineStride, dstLineStride, planesCopiesPerWorkgroup, srcPlaneStride, "
|
||||
"dstPlaneStride, 0 );\n"
|
||||
" wait_group_events( 1, &event );\n"
|
||||
"}\n";
|
||||
__kernel void test_fn(const __global %s *src, __global %s *dst, __local %s *localBuffer,
|
||||
int numElementsPerLine, int numLines, int planesCopiesPerWorkgroup,
|
||||
int planesCopiesPerWorkItem, int srcLineStride,
|
||||
int dstLineStride, int srcPlaneStride, int dstPlaneStride ) {
|
||||
// Zero the local storage first
|
||||
for (int i = 0; i < planesCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numLines; j++) {
|
||||
for (int k = 0; k < numElementsPerLine; k++) {
|
||||
const int index = (get_local_id(0) * planesCopiesPerWorkItem + i) * dstPlaneStride + j * dstLineStride + k;
|
||||
localBuffer[index] = (%s)(%s)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we try the copy
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
event_t event = async_work_group_copy_3D3D(localBuffer, 0, src,
|
||||
planesCopiesPerWorkgroup * get_group_id(0) * srcPlaneStride,
|
||||
sizeof(%s), (size_t)numElementsPerLine, (size_t)numLines,
|
||||
planesCopiesPerWorkgroup, srcLineStride, srcPlaneStride, dstLineStride,
|
||||
dstPlaneStride, 0);
|
||||
|
||||
// Wait for the copy to complete, then verify by manually copying to the dest
|
||||
wait_group_events(1, &event);
|
||||
|
||||
for (int i = 0; i < planesCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numLines; j++) {
|
||||
for(int k = 0; k < numElementsPerLine; k++) {
|
||||
const int local_index = (get_local_id(0) * planesCopiesPerWorkItem + i) * dstPlaneStride + j * dstLineStride + k;
|
||||
const int global_index = (get_global_id(0) * planesCopiesPerWorkItem + i) * dstPlaneStride + j * dstLineStride + k;
|
||||
dst[global_index] = localBuffer[local_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)OpenCLC";
|
||||
|
||||
static const char *async_local_to_global_kernel3D = R"OpenCLC(
|
||||
#pragma OPENCL EXTENSION cl_khr_extended_async_copies : enable
|
||||
%s // optional pragma string
|
||||
|
||||
__kernel void test_fn(const __global %s *src, __global %s *dst, __local %s *localBuffer,
|
||||
int numElementsPerLine, int numLines, int planesCopiesPerWorkgroup,
|
||||
int planesCopiesPerWorkItem, int srcLineStride,
|
||||
int dstLineStride, int srcPlaneStride, int dstPlaneStride) {
|
||||
// Zero the local storage first
|
||||
for (int i = 0; i < planesCopiesPerWorkItem; i++) {
|
||||
for (int j = 0; j < numLines; j++) {
|
||||
for (int k = 0; k < numElementsPerLine; k++) {
|
||||
const int index = (get_local_id(0) * planesCopiesPerWorkItem + i) * srcPlaneStride + j * srcLineStride + k;
|
||||
localBuffer[index] = (%s)(%s)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do this to verify all kernels are done zeroing the local buffer before we try the copy
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
for (int i=0; i < planesCopiesPerWorkItem; i++) {
|
||||
for (int j=0; j < numLines; j++) {
|
||||
for (int k=0; k < numElementsPerLine; k++) {
|
||||
const int local_index = (get_local_id(0) * planesCopiesPerWorkItem + i) * srcPlaneStride + j * srcLineStride + k;
|
||||
const int global_index = (get_global_id(0) * planesCopiesPerWorkItem + i) * srcPlaneStride + j*srcLineStride + k;
|
||||
localBuffer[local_index] = src[global_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do this to verify all kernels are done copying to the local buffer before we try the copy
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
event_t event = async_work_group_copy_3D3D(dst,
|
||||
planesCopiesPerWorkgroup * get_group_id(0) * dstPlaneStride, localBuffer, 0,
|
||||
sizeof(%s), (size_t)numElementsPerLine, (size_t)numLines, planesCopiesPerWorkgroup,
|
||||
srcLineStride, srcPlaneStride, dstLineStride, dstPlaneStride, 0);
|
||||
|
||||
wait_group_events(1, &event);
|
||||
}
|
||||
)OpenCLC";
|
||||
|
||||
int test_copy3D(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, const char *kernelCode,
|
||||
ExplicitType vecType, int vecSize, int srcLineStride,
|
||||
int dstLineStride, int srcPlaneStride, int dstPlaneStride,
|
||||
ExplicitType vecType, int vecSize, int srcLineMargin,
|
||||
int dstLineMargin, int srcPlaneMargin, int dstPlaneMargin,
|
||||
bool localIsDst)
|
||||
{
|
||||
int error;
|
||||
|
|
@ -133,17 +132,10 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
vecSize);
|
||||
|
||||
size_t elementSize = get_explicit_type_size(vecType) * vecSize;
|
||||
log_info("Testing %s with srcLineStride = %d, dstLineStride = %d, "
|
||||
"srcPlaneStride = %d, dstPlaneStride = %d\n",
|
||||
vecNameString, srcLineStride, dstLineStride, srcPlaneStride,
|
||||
dstPlaneStride);
|
||||
|
||||
if (!is_extension_available(deviceID, "cl_khr_extended_async_copies"))
|
||||
{
|
||||
log_info(
|
||||
"Device does not support extended async copies. Skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
log_info("Testing %s with srcLineMargin = %d, dstLineMargin = %d, "
|
||||
"srcPlaneMargin = %d, dstPlaneMargin = %d\n",
|
||||
vecNameString, srcLineMargin, dstLineMargin, srcPlaneMargin,
|
||||
dstPlaneMargin);
|
||||
|
||||
cl_long max_local_mem_size;
|
||||
error =
|
||||
|
|
@ -208,16 +200,20 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
if (max_workgroup_size > max_local_workgroup_size[0])
|
||||
max_workgroup_size = max_local_workgroup_size[0];
|
||||
|
||||
size_t numElementsPerLine = 10;
|
||||
size_t numLines = 13;
|
||||
size_t planesCopiesPerWorkItem = 2;
|
||||
const size_t numElementsPerLine = 10;
|
||||
const cl_int dstLineStride = numElementsPerLine + dstLineMargin;
|
||||
const cl_int srcLineStride = numElementsPerLine + srcLineMargin;
|
||||
|
||||
const size_t numLines = 13;
|
||||
const cl_int dstPlaneStride = (numLines * dstLineStride) + dstPlaneMargin;
|
||||
const cl_int srcPlaneStride = (numLines * srcLineStride) + srcPlaneMargin;
|
||||
|
||||
elementSize =
|
||||
get_explicit_type_size(vecType) * ((vecSize == 3) ? 4 : vecSize);
|
||||
size_t localStorageSpacePerWorkitem = elementSize
|
||||
* (planesCopiesPerWorkItem
|
||||
* (numLines * numElementsPerLine
|
||||
+ numLines * (localIsDst ? dstLineStride : srcLineStride)
|
||||
+ (localIsDst ? dstPlaneStride : srcPlaneStride)));
|
||||
const size_t planesCopiesPerWorkItem = 2;
|
||||
const size_t localStorageSpacePerWorkitem = elementSize
|
||||
* planesCopiesPerWorkItem
|
||||
* (localIsDst ? dstPlaneStride : srcPlaneStride);
|
||||
size_t maxLocalWorkgroupSize =
|
||||
(((int)max_local_mem_size / 2) / localStorageSpacePerWorkitem);
|
||||
|
||||
|
|
@ -231,42 +227,41 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
if (maxLocalWorkgroupSize > max_workgroup_size)
|
||||
localWorkgroupSize = max_workgroup_size;
|
||||
|
||||
size_t maxTotalPlanesIn = ((max_alloc_size / elementSize) + srcPlaneStride)
|
||||
/ ((numLines * numElementsPerLine + numLines * srcLineStride)
|
||||
+ srcPlaneStride);
|
||||
size_t maxTotalPlanesOut = ((max_alloc_size / elementSize) + dstPlaneStride)
|
||||
/ ((numLines * numElementsPerLine + numLines * dstLineStride)
|
||||
+ dstPlaneStride);
|
||||
size_t maxTotalPlanes = (std::min)(maxTotalPlanesIn, maxTotalPlanesOut);
|
||||
size_t maxLocalWorkgroups =
|
||||
const size_t maxTotalPlanesIn =
|
||||
((max_alloc_size / elementSize) + srcPlaneMargin) / srcPlaneStride;
|
||||
const size_t maxTotalPlanesOut =
|
||||
((max_alloc_size / elementSize) + dstPlaneMargin) / dstPlaneStride;
|
||||
const size_t maxTotalPlanes = std::min(maxTotalPlanesIn, maxTotalPlanesOut);
|
||||
const size_t maxLocalWorkgroups =
|
||||
maxTotalPlanes / (localWorkgroupSize * planesCopiesPerWorkItem);
|
||||
|
||||
size_t localBufferSize = localWorkgroupSize * localStorageSpacePerWorkitem
|
||||
- (localIsDst ? dstPlaneStride : srcPlaneStride);
|
||||
size_t numberOfLocalWorkgroups = (std::min)(1111, (int)maxLocalWorkgroups);
|
||||
size_t totalPlanes =
|
||||
const size_t localBufferSize =
|
||||
localWorkgroupSize * localStorageSpacePerWorkitem
|
||||
- (localIsDst ? dstPlaneMargin : srcPlaneMargin);
|
||||
const size_t numberOfLocalWorkgroups =
|
||||
std::min(1111, (int)maxLocalWorkgroups);
|
||||
const size_t totalPlanes =
|
||||
numberOfLocalWorkgroups * localWorkgroupSize * planesCopiesPerWorkItem;
|
||||
size_t inBufferSize = elementSize
|
||||
* (totalPlanes
|
||||
* (numLines * numElementsPerLine + numLines * srcLineStride)
|
||||
+ (totalPlanes - 1) * srcPlaneStride);
|
||||
size_t outBufferSize = elementSize
|
||||
* (totalPlanes
|
||||
* (numLines * numElementsPerLine + numLines * dstLineStride)
|
||||
+ (totalPlanes - 1) * dstPlaneStride);
|
||||
size_t globalWorkgroupSize = numberOfLocalWorkgroups * localWorkgroupSize;
|
||||
const size_t inBufferSize = elementSize
|
||||
* (totalPlanes * numLines * srcLineStride
|
||||
+ (totalPlanes - 1) * srcPlaneMargin);
|
||||
const size_t outBufferSize = elementSize
|
||||
* (totalPlanes * numLines * dstLineStride
|
||||
+ (totalPlanes - 1) * dstPlaneMargin);
|
||||
const size_t globalWorkgroupSize =
|
||||
numberOfLocalWorkgroups * localWorkgroupSize;
|
||||
|
||||
inBuffer = (void *)malloc(inBufferSize);
|
||||
outBuffer = (void *)malloc(outBufferSize);
|
||||
outBufferCopy = (void *)malloc(outBufferSize);
|
||||
|
||||
cl_int planesCopiesPerWorkItemInt, numElementsPerLineInt, numLinesInt,
|
||||
planesCopiesPerWorkgroup;
|
||||
planesCopiesPerWorkItemInt = (int)planesCopiesPerWorkItem;
|
||||
numElementsPerLineInt = (int)numElementsPerLine;
|
||||
numLinesInt = (int)numLines;
|
||||
planesCopiesPerWorkgroup =
|
||||
(int)(planesCopiesPerWorkItem * localWorkgroupSize);
|
||||
const cl_int planesCopiesPerWorkItemInt =
|
||||
static_cast<cl_int>(planesCopiesPerWorkItem);
|
||||
const cl_int numElementsPerLineInt =
|
||||
static_cast<cl_int>(numElementsPerLine);
|
||||
const cl_int numLinesInt = static_cast<cl_int>(numLines);
|
||||
const cl_int planesCopiesPerWorkgroup =
|
||||
static_cast<cl_int>(planesCopiesPerWorkItem * localWorkgroupSize);
|
||||
|
||||
log_info("Global: %d, local %d, local buffer %db, global in buffer %db, "
|
||||
"global out buffer %db, each work group will copy %d planes and "
|
||||
|
|
@ -343,14 +338,8 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
for (int k = 0; k < (int)numElementsPerLine * elementSize;
|
||||
k += elementSize)
|
||||
{
|
||||
int inIdx = i
|
||||
* (numLines * numElementsPerLine
|
||||
+ numLines * srcLineStride + srcPlaneStride)
|
||||
+ j * (numElementsPerLine + srcLineStride) + k;
|
||||
int outIdx = i
|
||||
* (numLines * numElementsPerLine
|
||||
+ numLines * dstLineStride + dstPlaneStride)
|
||||
+ j * (numElementsPerLine + dstLineStride) + k;
|
||||
int inIdx = i * srcPlaneStride + j * srcLineStride + k;
|
||||
int outIdx = i * dstPlaneStride + j * dstLineStride + k;
|
||||
if (memcmp(((char *)inBuffer) + inIdx,
|
||||
((char *)outBuffer) + outIdx, typeSize)
|
||||
!= 0)
|
||||
|
|
@ -385,14 +374,11 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
}
|
||||
if (j < (int)numLines * elementSize)
|
||||
{
|
||||
int outIdx = i
|
||||
* (numLines * numElementsPerLine
|
||||
+ numLines * dstLineStride + dstPlaneStride)
|
||||
+ j * (numElementsPerLine + dstLineStride)
|
||||
int outIdx = i * dstPlaneStride + j * dstLineStride
|
||||
+ numElementsPerLine * elementSize;
|
||||
if (memcmp(((char *)outBuffer) + outIdx,
|
||||
((char *)outBufferCopy) + outIdx,
|
||||
dstLineStride * elementSize)
|
||||
dstLineMargin * elementSize)
|
||||
!= 0)
|
||||
{
|
||||
if (failuresPrinted == 0)
|
||||
|
|
@ -416,14 +402,11 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
if (i < (int)(globalWorkgroupSize * planesCopiesPerWorkItem - 1)
|
||||
* elementSize)
|
||||
{
|
||||
int outIdx = i
|
||||
* (numLines * numElementsPerLine + numLines * dstLineStride
|
||||
+ dstPlaneStride)
|
||||
+ (numLines * elementSize) * (numElementsPerLine)
|
||||
+ (numLines * elementSize) * (dstLineStride);
|
||||
int outIdx =
|
||||
i * dstPlaneStride + numLines * dstLineStride * elementSize;
|
||||
if (memcmp(((char *)outBuffer) + outIdx,
|
||||
((char *)outBufferCopy) + outIdx,
|
||||
dstPlaneStride * elementSize)
|
||||
dstPlaneMargin * elementSize)
|
||||
!= 0)
|
||||
{
|
||||
if (failuresPrinted == 0)
|
||||
|
|
@ -460,13 +443,23 @@ int test_copy3D_all_types(cl_device_id deviceID, cl_context context,
|
|||
kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong,
|
||||
kULong, kFloat, kDouble, kNumExplicitTypes
|
||||
};
|
||||
// The margins below represent the number of elements between the end of
|
||||
// one line or plane and the start of the next. The strides are equivalent
|
||||
// to the size of the line or plane plus the chosen margin.
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int smallTypesStrideSizes[] = { 0, 10, 100 };
|
||||
unsigned int size, typeIndex, srcLineStride, dstLineStride, srcPlaneStride,
|
||||
dstPlaneStride;
|
||||
unsigned int smallTypesMarginSizes[] = { 0, 10, 100 };
|
||||
unsigned int size, typeIndex, srcLineMargin, dstLineMargin, srcPlaneMargin,
|
||||
dstPlaneMargin;
|
||||
|
||||
int errors = 0;
|
||||
|
||||
if (!is_extension_available(deviceID, "cl_khr_extended_async_copies"))
|
||||
{
|
||||
log_info(
|
||||
"Device does not support extended async copies. Skipping test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (typeIndex = 0; vecType[typeIndex] != kNumExplicitTypes; typeIndex++)
|
||||
{
|
||||
if (vecType[typeIndex] == kDouble
|
||||
|
|
@ -482,33 +475,33 @@ int test_copy3D_all_types(cl_device_id deviceID, cl_context context,
|
|||
if (get_explicit_type_size(vecType[typeIndex]) * vecSizes[size]
|
||||
<= 2) // small type
|
||||
{
|
||||
for (srcLineStride = 0;
|
||||
srcLineStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
srcLineStride++)
|
||||
for (srcLineMargin = 0;
|
||||
srcLineMargin < sizeof(smallTypesMarginSizes)
|
||||
/ sizeof(smallTypesMarginSizes[0]);
|
||||
srcLineMargin++)
|
||||
{
|
||||
for (dstLineStride = 0;
|
||||
dstLineStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
dstLineStride++)
|
||||
for (dstLineMargin = 0;
|
||||
dstLineMargin < sizeof(smallTypesMarginSizes)
|
||||
/ sizeof(smallTypesMarginSizes[0]);
|
||||
dstLineMargin++)
|
||||
{
|
||||
for (srcPlaneStride = 0;
|
||||
srcPlaneStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
srcPlaneStride++)
|
||||
for (srcPlaneMargin = 0;
|
||||
srcPlaneMargin < sizeof(smallTypesMarginSizes)
|
||||
/ sizeof(smallTypesMarginSizes[0]);
|
||||
srcPlaneMargin++)
|
||||
{
|
||||
for (dstPlaneStride = 0;
|
||||
dstPlaneStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
dstPlaneStride++)
|
||||
for (dstPlaneMargin = 0;
|
||||
dstPlaneMargin < sizeof(smallTypesMarginSizes)
|
||||
/ sizeof(smallTypesMarginSizes[0]);
|
||||
dstPlaneMargin++)
|
||||
{
|
||||
if (test_copy3D(
|
||||
deviceID, context, queue, kernelCode,
|
||||
vecType[typeIndex], vecSizes[size],
|
||||
smallTypesStrideSizes[srcLineStride],
|
||||
smallTypesStrideSizes[dstLineStride],
|
||||
smallTypesStrideSizes[srcPlaneStride],
|
||||
smallTypesStrideSizes[dstPlaneStride],
|
||||
smallTypesMarginSizes[srcLineMargin],
|
||||
smallTypesMarginSizes[dstLineMargin],
|
||||
smallTypesMarginSizes[srcPlaneMargin],
|
||||
smallTypesMarginSizes[dstPlaneMargin],
|
||||
localIsDst))
|
||||
{
|
||||
errors++;
|
||||
|
|
|
|||
|
|
@ -360,14 +360,6 @@ int test_copy_fence(cl_device_id deviceID, cl_context context,
|
|||
size_t elementSize = get_explicit_type_size(vecType) * vecSize;
|
||||
log_info("Testing %s\n", vecNameString);
|
||||
|
||||
if (!is_extension_available(deviceID, "cl_khr_async_work_group_copy_fence"))
|
||||
{
|
||||
log_info(
|
||||
"Device does not support extended async copies fence. Skipping "
|
||||
"test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cl_long max_local_mem_size;
|
||||
error =
|
||||
clGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE,
|
||||
|
|
@ -732,6 +724,14 @@ int test_copy_fence_all_types(cl_device_id deviceID, cl_context context,
|
|||
|
||||
int errors = 0;
|
||||
|
||||
if (!is_extension_available(deviceID, "cl_khr_async_work_group_copy_fence"))
|
||||
{
|
||||
log_info(
|
||||
"Device does not support extended async copies fence. Skipping "
|
||||
"test.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (typeIndex = 0; vecType[typeIndex] != kNumExplicitTypes; typeIndex++)
|
||||
{
|
||||
if (vecType[typeIndex] == kDouble
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ int test_enqueue_map_image(cl_device_id deviceID, cl_context context, cl_command
|
|||
clMemWrapper memObject;
|
||||
log_info("Testing with cl_mem_flags src: %s\n", flag_set_names[src_flag_id]);
|
||||
|
||||
generate_random_data(kUInt, (unsigned int)(imageSize * imageSize), d,
|
||||
generate_random_data(kUInt, (unsigned int)(imageSize * imageSize * 4), d,
|
||||
hostPtrData);
|
||||
memcpy(referenceData, hostPtrData, imageDataSize);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -14,42 +14,45 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
#include "harness/rounding_mode.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "harness/rounding_mode.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
static const char *enqueued_local_size_2d_code =
|
||||
"__kernel void test_enqueued_local_size_2d(global int *dst)\n"
|
||||
"{\n"
|
||||
" if ((get_global_id(0) == 0) && (get_global_id(1) == 0))\n"
|
||||
" {\n"
|
||||
" dst[0] = (int)get_enqueued_local_size(0)\n;"
|
||||
" dst[1] = (int)get_enqueued_local_size(1)\n;"
|
||||
" }\n"
|
||||
"}\n";
|
||||
static const char *enqueued_local_size_2d_code = R"(
|
||||
__kernel void test_enqueued_local_size_2d(global int *dst)
|
||||
{
|
||||
if ((get_global_id(0) == 0) && (get_global_id(1) == 0))
|
||||
{
|
||||
dst[0] = (int)get_enqueued_local_size(0);
|
||||
dst[1] = (int)get_enqueued_local_size(1);
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
static const char *enqueued_local_size_1d_code =
|
||||
"__kernel void test_enqueued_local_size_1d(global int *dst)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" if (get_global_id(0) == 0)\n"
|
||||
" {\n"
|
||||
" dst[tid_x] = (int)get_enqueued_local_size(0)\n;"
|
||||
" }\n"
|
||||
"}\n";
|
||||
static const char *enqueued_local_size_1d_code = R"(
|
||||
__kernel void test_enqueued_local_size_1d(global int *dst)
|
||||
{
|
||||
int tid_x = get_global_id(0);
|
||||
if (get_global_id(0) == 0)
|
||||
{
|
||||
dst[tid_x] = (int)get_enqueued_local_size(0);
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
static int
|
||||
verify_enqueued_local_size(int *result, size_t *expected, int n)
|
||||
static int verify_enqueued_local_size(int *result, size_t *expected, int n)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<n; i++)
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (result[i] != (int)expected[i])
|
||||
{
|
||||
|
|
@ -62,14 +65,14 @@ verify_enqueued_local_size(int *result, size_t *expected, int n)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
test_enqueued_local_size(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
int test_enqueued_local_size(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams;
|
||||
cl_program program[2];
|
||||
cl_kernel kernel[2];
|
||||
clMemWrapper stream;
|
||||
clProgramWrapper program[2];
|
||||
clKernelWrapper kernel[2];
|
||||
|
||||
int *output_ptr;
|
||||
cl_int output_ptr[2];
|
||||
size_t globalsize[2];
|
||||
size_t localsize[2];
|
||||
int err;
|
||||
|
|
@ -95,37 +98,36 @@ test_enqueued_local_size(cl_device_id device, cl_context context, cl_command_que
|
|||
}
|
||||
}
|
||||
|
||||
output_ptr = (int*)malloc(2 * sizeof(int));
|
||||
|
||||
streams =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE, 2 * sizeof(int), NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
stream = clCreateBuffer(context, CL_MEM_READ_WRITE, 2 * sizeof(cl_int),
|
||||
nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed.");
|
||||
|
||||
std::string cl_std = "-cl-std=CL";
|
||||
cl_std += (get_device_cl_version(device) == Version(3, 0)) ? "3.0" : "2.0";
|
||||
err = create_single_kernel_helper_with_build_options(
|
||||
context, &program[0], &kernel[0], 1, &enqueued_local_size_1d_code,
|
||||
"test_enqueued_local_size_1d", cl_std.c_str());
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
test_error(err, "create_single_kernel_helper failed");
|
||||
err = create_single_kernel_helper_with_build_options(
|
||||
context, &program[1], &kernel[1], 1, &enqueued_local_size_2d_code,
|
||||
"test_enqueued_local_size_2d", cl_std.c_str());
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
test_error(err, "create_single_kernel_helper failed");
|
||||
|
||||
err = clSetKernelArg(kernel[0], 0, sizeof streams, &streams);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
err = clSetKernelArg(kernel[1], 0, sizeof streams, &streams);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
err = clSetKernelArg(kernel[0], 0, sizeof stream, &stream);
|
||||
test_error(err, "clSetKernelArgs failed.");
|
||||
err = clSetKernelArg(kernel[1], 0, sizeof stream, &stream);
|
||||
test_error(err, "clSetKernelArgs failed.");
|
||||
|
||||
globalsize[0] = (size_t)num_elements;
|
||||
globalsize[1] = (size_t)num_elements;
|
||||
globalsize[0] = static_cast<size_t>(num_elements);
|
||||
globalsize[1] = static_cast<size_t>(num_elements);
|
||||
|
||||
size_t max_wgs;
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_wgs), &max_wgs, NULL);
|
||||
test_error( err, "clGetDeviceInfo failed.");
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE,
|
||||
sizeof(max_wgs), &max_wgs, nullptr);
|
||||
test_error(err, "clGetDeviceInfo failed.");
|
||||
|
||||
localsize[0] = MIN(16, max_wgs);
|
||||
localsize[1] = MIN(11, max_wgs / localsize[0]);
|
||||
localsize[0] = std::min<size_t>(16, max_wgs);
|
||||
localsize[1] = std::min<size_t>(11, max_wgs / localsize[0]);
|
||||
// If we need to use uniform workgroups because non-uniform workgroups are
|
||||
// not supported, round up to the next global size that is divisible by the
|
||||
// local size.
|
||||
|
|
@ -141,35 +143,31 @@ test_enqueued_local_size(cl_device_id device, cl_context context, cl_command_que
|
|||
}
|
||||
}
|
||||
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[1], 2, NULL, globalsize, localsize, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueNDRangeKernel failed.");
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[1], 2, nullptr, globalsize,
|
||||
localsize, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams, CL_TRUE, 0, 2*sizeof(int), output_ptr, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueReadBuffer failed.");
|
||||
err = clEnqueueReadBuffer(queue, stream, CL_BLOCKING, 0, 2 * sizeof(int),
|
||||
output_ptr, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
err = verify_enqueued_local_size(output_ptr, localsize, 2);
|
||||
|
||||
globalsize[0] = (size_t)num_elements;
|
||||
globalsize[0] = static_cast<size_t>(num_elements);
|
||||
localsize[0] = 9;
|
||||
if (use_uniform_work_groups && (globalsize[0] % localsize[0]))
|
||||
{
|
||||
globalsize[0] += (localsize[0] - (globalsize[0] % localsize[0]));
|
||||
}
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[1], 1, NULL, globalsize, localsize, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueNDRangeKernel failed.");
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[1], 1, nullptr, globalsize,
|
||||
localsize, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams, CL_TRUE, 0, 2*sizeof(int), output_ptr, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueReadBuffer failed.");
|
||||
err = clEnqueueReadBuffer(queue, stream, CL_BLOCKING, 0, 2 * sizeof(int),
|
||||
output_ptr, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
err = verify_enqueued_local_size(output_ptr, localsize, 1);
|
||||
|
||||
// cleanup
|
||||
clReleaseMemObject(streams);
|
||||
clReleaseKernel(kernel[0]);
|
||||
clReleaseKernel(kernel[1]);
|
||||
clReleaseProgram(program[0]);
|
||||
clReleaseProgram(program[1]);
|
||||
free(output_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -22,247 +22,175 @@
|
|||
#include <sys/stat.h>
|
||||
#include "harness/rounding_mode.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
static const char *fpadd_kernel_code =
|
||||
"__kernel void test_fpadd(__global float *srcA, __global float *srcB, __global float *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] + srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
static const char *fpsub_kernel_code =
|
||||
"__kernel void test_fpsub(__global float *srcA, __global float *srcB, __global float *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] - srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
static const char *fpmul_kernel_code =
|
||||
"__kernel void test_fpmul(__global float *srcA, __global float *srcB, __global float *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] * srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static const float MAX_ERR = 1e-5f;
|
||||
|
||||
static int
|
||||
verify_fpadd(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
struct TestDef
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
const char op;
|
||||
std::function<float(float, float)> ref;
|
||||
};
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
static const char *fp_kernel_code = R"(
|
||||
__kernel void test_fp(__global TYPE *srcA, __global TYPE *srcB, __global TYPE *dst)
|
||||
{
|
||||
int tid = get_global_id(0);
|
||||
|
||||
dst[tid] = srcA[tid] OP srcB[tid];
|
||||
})";
|
||||
|
||||
static int verify_fp(std::vector<float> (&input)[2], std::vector<float> &output,
|
||||
const TestDef &test)
|
||||
{
|
||||
|
||||
auto &inA = input[0];
|
||||
auto &inB = input[1];
|
||||
for (int i = 0; i < output.size(); i++)
|
||||
{
|
||||
r = inptrA[i] + inptrB[i];
|
||||
if (r != outptr[i])
|
||||
float r = test.ref(inA[i], inB[i]);
|
||||
if (r != output[i])
|
||||
{
|
||||
log_error("FP_ADD float test failed\n");
|
||||
log_error("FP '%c' float test failed\n", test.op);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_ADD float test passed\n");
|
||||
log_info("FP '%c' float test passed\n", test.op);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
verify_fpsub(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
void generate_random_inputs(std::vector<cl_float> (&input)[2])
|
||||
{
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
auto random_generator = [&seed]() {
|
||||
return get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31),
|
||||
MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), seed);
|
||||
};
|
||||
|
||||
for (auto &v : input)
|
||||
{
|
||||
r = inptrA[i] - inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_SUB float test failed\n");
|
||||
return -1;
|
||||
}
|
||||
std::generate(v.begin(), v.end(), random_generator);
|
||||
}
|
||||
|
||||
log_info("FP_SUB float test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
verify_fpmul(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
template <size_t N>
|
||||
int test_fpmath(cl_device_id device, cl_context context, cl_command_queue queue,
|
||||
int num_elements, const std::string type_str,
|
||||
const TestDef &test)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
clMemWrapper streams[3];
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] * inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_MUL float test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int err;
|
||||
|
||||
log_info("FP_MUL float test passed\n");
|
||||
return 0;
|
||||
}
|
||||
size_t length = sizeof(cl_float) * num_elements * N;
|
||||
|
||||
|
||||
int
|
||||
test_fpmath_float(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[4];
|
||||
cl_program program[3];
|
||||
cl_kernel kernel[3];
|
||||
|
||||
float *input_ptr[3], *output_ptr, *p;
|
||||
size_t threads[1];
|
||||
int err, i;
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
size_t length = sizeof(cl_float) * num_elements;
|
||||
int isRTZ = 0;
|
||||
RoundingMode oldMode = kDefaultRoundingMode;
|
||||
|
||||
// check for floating point capabilities
|
||||
cl_device_fp_config single_config = 0;
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single_config ), &single_config, NULL );
|
||||
if (err) {
|
||||
log_error("clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
//If we only support rtz mode
|
||||
if( CL_FP_ROUND_TO_ZERO == ( single_config & (CL_FP_ROUND_TO_ZERO|CL_FP_ROUND_TO_NEAREST) ) )
|
||||
// If we only support rtz mode
|
||||
if (CL_FP_ROUND_TO_ZERO == get_default_rounding_mode(device))
|
||||
{
|
||||
//Check to make sure we are an embedded device
|
||||
char profile[32];
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL);
|
||||
if( err )
|
||||
{
|
||||
log_error("clGetDeviceInfo for CL_DEVICE_PROFILE failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
if( 0 != strcmp( profile, "EMBEDDED_PROFILE"))
|
||||
{
|
||||
log_error( "FAILURE: Device doesn't support CL_FP_ROUND_TO_NEAREST and isn't EMBEDDED_PROFILE\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
isRTZ = 1;
|
||||
oldMode = get_round();
|
||||
}
|
||||
|
||||
|
||||
input_ptr[0] = (cl_float*)malloc(length);
|
||||
input_ptr[1] = (cl_float*)malloc(length);
|
||||
input_ptr[2] = (cl_float*)malloc(length);
|
||||
output_ptr = (cl_float*)malloc(length);
|
||||
std::vector<cl_float> inputs[]{ std::vector<cl_float>(N * num_elements),
|
||||
std::vector<cl_float>(N * num_elements) };
|
||||
std::vector<cl_float> output = std::vector<cl_float>(N * num_elements);
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
generate_random_inputs(inputs);
|
||||
|
||||
p = input_ptr[0];
|
||||
for (i=0; i<num_elements; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), d);
|
||||
p = input_ptr[1];
|
||||
for (i=0; i<num_elements; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), d);
|
||||
p = input_ptr[2];
|
||||
for (i=0; i<num_elements; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), d);
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueWriteBuffer failed.");
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, input_ptr[1], 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueWriteBuffer failed.");
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, input_ptr[2], 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueWriteBuffer failed.");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &fpadd_kernel_code, "test_fpadd");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &fpsub_kernel_code, "test_fpsub");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[2], &kernel[2], 1, &fpmul_kernel_code, "test_fpmul");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
|
||||
err = clSetKernelArg(kernel[0], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[0], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[0], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
err = clSetKernelArg(kernel[1], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[1], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[1], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
err = clSetKernelArg(kernel[2], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[2], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[2], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
threads[0] = (unsigned int)num_elements;
|
||||
for (i=0; i<3; i++)
|
||||
for (int i = 0; i < ARRAY_SIZE(streams); i++)
|
||||
{
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[3], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
if( isRTZ )
|
||||
set_round( kRoundTowardZero, kfloat );
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
err = verify_fpadd(input_ptr[0], input_ptr[1], output_ptr, num_elements);
|
||||
break;
|
||||
case 1:
|
||||
err = verify_fpsub(input_ptr[0], input_ptr[1], output_ptr, num_elements);
|
||||
break;
|
||||
case 2:
|
||||
err = verify_fpmul(input_ptr[0], input_ptr[1], output_ptr, num_elements);
|
||||
break;
|
||||
}
|
||||
|
||||
if( isRTZ )
|
||||
set_round( oldMode, kfloat );
|
||||
|
||||
if (err)
|
||||
break;
|
||||
streams[i] =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed.");
|
||||
}
|
||||
for (int i = 0; i < ARRAY_SIZE(inputs); i++)
|
||||
{
|
||||
err = clEnqueueWriteBuffer(queue, streams[i], CL_TRUE, 0, length,
|
||||
inputs[i].data(), 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
// cleanup
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseMemObject(streams[2]);
|
||||
clReleaseMemObject(streams[3]);
|
||||
for (i=0; i<3; i++)
|
||||
std::string build_options = "-DTYPE=";
|
||||
build_options.append(type_str).append(" -DOP=").append(1, test.op);
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
&fp_kernel_code, "test_fp",
|
||||
build_options.c_str());
|
||||
|
||||
test_error(err, "create_single_kernel_helper failed");
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(streams); i++)
|
||||
{
|
||||
clReleaseKernel(kernel[i]);
|
||||
clReleaseProgram(program[i]);
|
||||
err = clSetKernelArg(kernel, i, sizeof(streams[i]), &streams[i]);
|
||||
test_error(err, "clSetKernelArgs failed.");
|
||||
}
|
||||
free(input_ptr[0]);
|
||||
free(input_ptr[1]);
|
||||
free(input_ptr[2]);
|
||||
free(output_ptr);
|
||||
free_mtdata( d );
|
||||
|
||||
size_t threads[] = { static_cast<size_t>(num_elements) };
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads, NULL, 0, NULL,
|
||||
NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[2], CL_TRUE, 0, length,
|
||||
output.data(), 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
if (isRTZ) set_round(kRoundTowardZero, kfloat);
|
||||
|
||||
err = verify_fp(inputs, output, test);
|
||||
|
||||
if (isRTZ) set_round(oldMode, kfloat);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
template <size_t N>
|
||||
int test_fpmath_common(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements,
|
||||
const std::string type_str)
|
||||
{
|
||||
TestDef tests[] = { { '+', std::plus<float>() },
|
||||
{ '-', std::minus<float>() },
|
||||
{ '*', std::multiplies<float>() } };
|
||||
int err = TEST_PASS;
|
||||
|
||||
for (const auto &test : tests)
|
||||
{
|
||||
err |= test_fpmath<N>(device, context, queue, num_elements, type_str,
|
||||
test);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_fpmath_float(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_fpmath_common<1>(device, context, queue, num_elements, "float");
|
||||
}
|
||||
|
||||
int test_fpmath_float2(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_fpmath_common<2>(device, context, queue, num_elements,
|
||||
"float2");
|
||||
}
|
||||
|
||||
int test_fpmath_float4(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_fpmath_common<4>(device, context, queue, num_elements,
|
||||
"float4");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,266 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "harness/rounding_mode.h"
|
||||
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
const char *fpadd2_kernel_code =
|
||||
"__kernel void test_fpadd2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] + srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
const char *fpsub2_kernel_code =
|
||||
"__kernel void test_fpsub2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] - srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
const char *fpmul2_kernel_code =
|
||||
"__kernel void test_fpmul2(__global float2 *srcA, __global float2 *srcB, __global float2 *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] * srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
int
|
||||
verify_fpadd2(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] + inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_ADD float2 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_ADD float2 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_fpsub2(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] - inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_SUB float2 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_SUB float2 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_fpmul2(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] * inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_MUL float2 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_MUL float2 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_fpmath_float2(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[4];
|
||||
cl_program program[3];
|
||||
cl_kernel kernel[3];
|
||||
|
||||
cl_float *input_ptr[3], *output_ptr, *p;
|
||||
size_t threads[1];
|
||||
int err, i;
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
|
||||
size_t length = sizeof(cl_float) * 2 * num_elements;
|
||||
int isRTZ = 0;
|
||||
RoundingMode oldMode = kDefaultRoundingMode;
|
||||
|
||||
// check for floating point capabilities
|
||||
cl_device_fp_config single_config = 0;
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single_config ), &single_config, NULL );
|
||||
if (err) {
|
||||
log_error("clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
//If we only support rtz mode
|
||||
if( CL_FP_ROUND_TO_ZERO == ( single_config & (CL_FP_ROUND_TO_ZERO|CL_FP_ROUND_TO_NEAREST) ) )
|
||||
{
|
||||
//Check to make sure we are an embedded device
|
||||
char profile[32];
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL);
|
||||
if( err )
|
||||
{
|
||||
log_error("clGetDeviceInfo for CL_DEVICE_PROFILE failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
if( 0 != strcmp( profile, "EMBEDDED_PROFILE"))
|
||||
{
|
||||
log_error( "FAILURE: Device doesn't support CL_FP_ROUND_TO_NEAREST and isn't EMBEDDED_PROFILE\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
isRTZ = 1;
|
||||
oldMode = get_round();
|
||||
}
|
||||
|
||||
input_ptr[0] = (cl_float*)malloc(length);
|
||||
input_ptr[1] = (cl_float*)malloc(length);
|
||||
input_ptr[2] = (cl_float*)malloc(length);
|
||||
output_ptr = (cl_float*)malloc(length);
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
|
||||
p = input_ptr[0];
|
||||
for (i=0; i<num_elements*2; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), d);
|
||||
p = input_ptr[1];
|
||||
for (i=0; i<num_elements*2; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), d);
|
||||
p = input_ptr[2];
|
||||
for (i=0; i<num_elements*2; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), d);
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, input_ptr[1], 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, input_ptr[2], 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &fpadd2_kernel_code, "test_fpadd2");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &fpsub2_kernel_code, "test_fpsub2");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[2], &kernel[2], 1, &fpmul2_kernel_code, "test_fpmul2");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
|
||||
err = clSetKernelArg(kernel[0], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[0], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[0], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
err = clSetKernelArg(kernel[1], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[1], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[1], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
err = clSetKernelArg(kernel[2], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[2], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[2], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
free_mtdata(d);
|
||||
d = NULL;
|
||||
|
||||
threads[0] = (unsigned int)num_elements;
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[3], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
if( isRTZ )
|
||||
set_round( kRoundTowardZero, kfloat );
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
err = verify_fpadd2(input_ptr[0], input_ptr[1], output_ptr, num_elements*2);
|
||||
break;
|
||||
case 1:
|
||||
err = verify_fpsub2(input_ptr[0], input_ptr[1], output_ptr, num_elements*2);
|
||||
break;
|
||||
case 2:
|
||||
err = verify_fpmul2(input_ptr[0], input_ptr[1], output_ptr, num_elements*2);
|
||||
break;
|
||||
}
|
||||
|
||||
if( isRTZ )
|
||||
set_round( oldMode, kfloat );
|
||||
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseMemObject(streams[2]);
|
||||
clReleaseMemObject(streams[3]);
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
clReleaseKernel(kernel[i]);
|
||||
clReleaseProgram(program[i]);
|
||||
}
|
||||
free(input_ptr[0]);
|
||||
free(input_ptr[1]);
|
||||
free(input_ptr[2]);
|
||||
free(output_ptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,267 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "procs.h"
|
||||
#include "harness/rounding_mode.h"
|
||||
|
||||
const char *fpadd4_kernel_code =
|
||||
"__kernel void test_fpadd4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] + srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
const char *fpsub4_kernel_code =
|
||||
"__kernel void test_fpsub4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] - srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
const char *fpmul4_kernel_code =
|
||||
"__kernel void test_fpmul4(__global float4 *srcA, __global float4 *srcB, __global float4 *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = srcA[tid] * srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
int
|
||||
verify_fpadd4(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] + inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_ADD float4 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_ADD float4 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_fpsub4(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] - inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_SUB float4 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_SUB float4 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_fpmul4(float *inptrA, float *inptrB, float *outptr, int n)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r = inptrA[i] * inptrB[i];
|
||||
if (r != outptr[i])
|
||||
{
|
||||
log_error("FP_MUL float4 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FP_MUL float4 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_fpmath_float4(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[4];
|
||||
cl_program program[3];
|
||||
cl_kernel kernel[3];
|
||||
|
||||
cl_float *input_ptr[3], *output_ptr, *p;
|
||||
size_t threads[1];
|
||||
int err, i;
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
|
||||
size_t length = sizeof(cl_float) * 4 * num_elements;
|
||||
int isRTZ = 0;
|
||||
RoundingMode oldMode = kDefaultRoundingMode;
|
||||
|
||||
// check for floating point capabilities
|
||||
cl_device_fp_config single_config = 0;
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof( single_config ), &single_config, NULL );
|
||||
if (err) {
|
||||
log_error("clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
//If we only support rtz mode
|
||||
if( CL_FP_ROUND_TO_ZERO == ( single_config & (CL_FP_ROUND_TO_ZERO|CL_FP_ROUND_TO_NEAREST) ) )
|
||||
{
|
||||
//Check to make sure we are an embedded device
|
||||
char profile[32];
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL);
|
||||
if( err )
|
||||
{
|
||||
log_error("clGetDeviceInfo for CL_DEVICE_PROFILE failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
if( 0 != strcmp( profile, "EMBEDDED_PROFILE"))
|
||||
{
|
||||
log_error( "FAILURE: Device doesn't support CL_FP_ROUND_TO_NEAREST and isn't EMBEDDED_PROFILE\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
isRTZ = 1;
|
||||
oldMode = get_round();
|
||||
}
|
||||
|
||||
input_ptr[0] = (cl_float*)malloc(length);
|
||||
input_ptr[1] = (cl_float*)malloc(length);
|
||||
input_ptr[2] = (cl_float*)malloc(length);
|
||||
output_ptr = (cl_float*)malloc(length);
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
streams[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error( err, "clCreateBuffer failed.");
|
||||
|
||||
p = input_ptr[0];
|
||||
for (i=0; i<num_elements*4; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), d);
|
||||
p = input_ptr[1];
|
||||
for (i=0; i<num_elements*4; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), d);
|
||||
p = input_ptr[2];
|
||||
for (i=0; i<num_elements*4; i++)
|
||||
p[i] = get_random_float(-MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT(0x1.0p31f, 0x1, 31), d);
|
||||
|
||||
free_mtdata(d);
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, length, input_ptr[0], 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, length, input_ptr[1], 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, length, input_ptr[2], 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &fpadd4_kernel_code, "test_fpadd4");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &fpsub4_kernel_code, "test_fpsub4");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program[2], &kernel[2], 1, &fpmul4_kernel_code, "test_fpmul4");
|
||||
test_error( err, "create_single_kernel_helper failed");
|
||||
|
||||
|
||||
err = clSetKernelArg(kernel[0], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[0], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[0], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
err = clSetKernelArg(kernel[1], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[1], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[1], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
err = clSetKernelArg(kernel[2], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[2], 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[2], 2, sizeof streams[3], &streams[3]);
|
||||
test_error( err, "clSetKernelArgs failed.");
|
||||
|
||||
|
||||
threads[0] = (unsigned int)num_elements;
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[i], 1, NULL, threads, NULL, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[3], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
test_error( err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
if( isRTZ )
|
||||
set_round( kRoundTowardZero, kfloat );
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
err = verify_fpadd4(input_ptr[0], input_ptr[1], output_ptr, num_elements*4);
|
||||
break;
|
||||
case 1:
|
||||
err = verify_fpsub4(input_ptr[0], input_ptr[1], output_ptr, num_elements*4);
|
||||
break;
|
||||
case 2:
|
||||
err = verify_fpmul4(input_ptr[0], input_ptr[1], output_ptr, num_elements*4);
|
||||
break;
|
||||
}
|
||||
|
||||
if( isRTZ )
|
||||
set_round( oldMode, kfloat );
|
||||
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseMemObject(streams[2]);
|
||||
clReleaseMemObject(streams[3]);
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
clReleaseKernel(kernel[i]);
|
||||
clReleaseProgram(program[i]);
|
||||
}
|
||||
free(input_ptr[0]);
|
||||
free(input_ptr[1]);
|
||||
free(input_ptr[2]);
|
||||
free(output_ptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -43,8 +43,6 @@ static const unsigned int out_vector_idx[] = { 0, 0, 1, 1, 3, 4};
|
|||
// input type name is strcat(gentype, vector_size_names[i]);
|
||||
// and output type name is
|
||||
// strcat(gentype, vector_size_names[out_vector_idx[i]]);
|
||||
static const int size_to_idx[] = {-1,0,1,2,3,-1,-1,-1,4,
|
||||
-1,-1,-1,-1,-1,-1,-1,5};
|
||||
static const char *vector_size_names[] = { "", "2", "3", "4", "8", "16"};
|
||||
|
||||
static const size_t kSizes[] = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8 };
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ const char *hostptr_kernel_code =
|
|||
" dst[tid] = srcA[tid] + srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
static const float MAX_ERR = 1e-5f;
|
||||
|
||||
static int verify_hostptr(cl_float *inptrA, cl_float *inptrB, cl_float *outptr, int n)
|
||||
{
|
||||
cl_float r;
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ int validate_results( size_t width, size_t height, cl_image_format &format, char
|
|||
}
|
||||
default:
|
||||
// Should never get here
|
||||
break;
|
||||
log_error("Unhandled channel data type\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( format.image_channel_order == CL_BGRA )
|
||||
|
|
|
|||
|
|
@ -87,11 +87,11 @@ int test_imagearraycopy_single_format(cl_device_id device, cl_context context, c
|
|||
char values[4096];
|
||||
values[0] = 0;
|
||||
if (failed) {
|
||||
sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i);
|
||||
sprintf(values + strlen(values), "%d(0x%x) -> expected [", i, i);
|
||||
int j;
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", inchar[i+j]);
|
||||
sprintf(values + strlen(values), "] != expected [");
|
||||
sprintf(values + strlen(values), "] != actual [");
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", outchar[i+j]);
|
||||
sprintf(values + strlen(values), "]");
|
||||
|
|
|
|||
|
|
@ -84,11 +84,11 @@ int test_imagearraycopy3d_single_format(cl_device_id device, cl_context context,
|
|||
char values[4096];
|
||||
values[0] = 0;
|
||||
if (failed) {
|
||||
sprintf(values + strlen(values), "%d(0x%x) -> actual [", i, i);
|
||||
sprintf(values + strlen(values), "%d(0x%x) -> expected [", i, i);
|
||||
int j;
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", inchar[i+j]);
|
||||
sprintf(values + strlen(values), "] != expected [");
|
||||
sprintf(values + strlen(values), "] != actual [");
|
||||
for (j=0; j<(int)elem_size; j++)
|
||||
sprintf(values + strlen( values), "0x%02x ", outchar[i+j]);
|
||||
sprintf(values + strlen(values), "]");
|
||||
|
|
|
|||
|
|
@ -153,14 +153,14 @@ int test_mri_one(cl_device_id device, cl_context context, cl_command_queue queue
|
|||
err = clSetKernelArg(kernel, 0, sizeof i, &i);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof err, &err);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler);
|
||||
for (i=0; i<8; i++)
|
||||
err |= clSetKernelArg(kernel, 3+i, sizeof streams[i], &streams[i]);
|
||||
for (i = 0; i < 8; i++)
|
||||
err |= clSetKernelArg(kernel, 3 + i, sizeof streams[i], &streams[i]);
|
||||
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArgs failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArgs failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
threads[0] = (unsigned int)img_width;
|
||||
threads[1] = (unsigned int)img_height;
|
||||
|
|
@ -182,15 +182,13 @@ int test_mri_one(cl_device_id device, cl_context context, cl_command_queue queue
|
|||
|
||||
// cleanup
|
||||
clReleaseSampler(sampler);
|
||||
for (i=0; i<8; i++)
|
||||
clReleaseMemObject(streams[i]);
|
||||
for (i = 0; i < 8; i++) clReleaseMemObject(streams[i]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
for (i=0; i<7; i++)
|
||||
free(input_ptr[i]);
|
||||
free(output_ptr);
|
||||
for (i = 0; i < 7; i++) free(input_ptr[i]);
|
||||
free(output_ptr);
|
||||
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -97,10 +97,10 @@ int test_kernel_preprocessor_macros(cl_device_id deviceID, cl_context context, c
|
|||
char programSource[4096];
|
||||
char curFileName[512];
|
||||
char *programPtr = programSource;
|
||||
int i = 0;
|
||||
snprintf(curFileName, 512, "%s", __FILE__);
|
||||
#ifdef _WIN32
|
||||
// Replace "\" with "\\"
|
||||
int i = 0;
|
||||
while(curFileName[i] != '\0') {
|
||||
if (curFileName[i] == '\\') {
|
||||
int j = i + 1;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -48,13 +48,9 @@ static const char *fpmul_kernel_code =
|
|||
" dst[tid] = srcA[tid] * srcB[tid];\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static const float MAX_ERR = 1e-5f;
|
||||
|
||||
static int
|
||||
verify_fpadd(float *inptrA, float *inptrB, float *outptr, int n, int fileNum)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
float * reference_ptr = (float *)malloc(n * sizeof(float));
|
||||
|
|
@ -82,7 +78,6 @@ verify_fpadd(float *inptrA, float *inptrB, float *outptr, int n, int fileNum)
|
|||
static int
|
||||
verify_fpsub(float *inptrA, float *inptrB, float *outptr, int n, int fileNum)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
float * reference_ptr = (float *)malloc(n * sizeof(float));
|
||||
|
|
@ -110,7 +105,6 @@ verify_fpsub(float *inptrA, float *inptrB, float *outptr, int n, int fileNum)
|
|||
static int
|
||||
verify_fpmul(float *inptrA, float *inptrB, float *outptr, int n, int fileNum)
|
||||
{
|
||||
float r;
|
||||
int i;
|
||||
|
||||
float * reference_ptr = (float *)malloc(n * sizeof(float));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
#include "harness/imageHelpers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -21,272 +22,356 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
static const char *bgra8888_kernel_code =
|
||||
"\n"
|
||||
"__kernel void test_bgra8888(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int indx = tid_y * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;\n"
|
||||
" dst[indx] = convert_uchar4_rte(color.zyxw);\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
#define TEST_IMAGE_WIDTH_2D (512)
|
||||
#define TEST_IMAGE_HEIGHT_2D (512)
|
||||
|
||||
#define TEST_IMAGE_WIDTH_3D (64)
|
||||
#define TEST_IMAGE_HEIGHT_3D (64)
|
||||
#define TEST_IMAGE_DEPTH_3D (64)
|
||||
|
||||
static const char *rgba8888_kernel_code =
|
||||
"\n"
|
||||
"__kernel void test_rgba8888(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int indx = tid_y * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;\n"
|
||||
" dst[indx] = convert_uchar4_rte(color);\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
#define TEST_IMAGE_WIDTH(TYPE) \
|
||||
((CL_MEM_OBJECT_IMAGE2D == TYPE) ? TEST_IMAGE_WIDTH_2D \
|
||||
: TEST_IMAGE_WIDTH_3D)
|
||||
#define TEST_IMAGE_HEIGHT(TYPE) \
|
||||
((CL_MEM_OBJECT_IMAGE2D == TYPE) ? TEST_IMAGE_HEIGHT_2D \
|
||||
: TEST_IMAGE_HEIGHT_3D)
|
||||
#define TEST_IMAGE_DEPTH(TYPE) \
|
||||
((CL_MEM_OBJECT_IMAGE2D == TYPE) ? 1 : TEST_IMAGE_DEPTH_3D)
|
||||
|
||||
|
||||
static unsigned char *
|
||||
generate_8888_image(int w, int h, MTdata d)
|
||||
namespace {
|
||||
const char *kernel_source_2d = R"(
|
||||
__kernel void test_CL_BGRACL_UNORM_INT8(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char*)malloc(w * h * 4);
|
||||
int i;
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int indx = tid_y * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
for (i=0; i<w*h*4; i++)
|
||||
ptr[i] = (unsigned char)genrand_int32( d);
|
||||
|
||||
return ptr;
|
||||
color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;
|
||||
dst[indx] = convert_uchar4_rte(color.zyxw);
|
||||
}
|
||||
|
||||
static int
|
||||
verify_bgra8888_image(unsigned char *image, unsigned char *outptr, int w, int h)
|
||||
__kernel void test_CL_RGBACL_UNORM_INT8(read_only image2d_t srcimg, __global uchar4 *dst, sampler_t sampler)
|
||||
{
|
||||
int i;
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int indx = tid_y * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
for (i=0; i<w*h; i++)
|
||||
{
|
||||
if (outptr[i] != image[i])
|
||||
{
|
||||
log_error("READ_IMAGE_BGRA_UNORM_INT8 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("READ_IMAGE_BGRA_UNORM_INT8 test passed\n");
|
||||
return 0;
|
||||
color = read_imagef(srcimg, sampler, (int2)(tid_x, tid_y)) * 255.0f;
|
||||
dst[indx] = convert_uchar4_rte(color);
|
||||
}
|
||||
|
||||
static int
|
||||
verify_rgba8888_image(unsigned char *image, unsigned char *outptr, int w, int h)
|
||||
__kernel void test_CL_RGBACL_UNORM_INT16(read_only image2d_t srcimg, __global ushort4 *dst, sampler_t smp)
|
||||
{
|
||||
int i;
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int indx = tid_y * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
for (i=0; i<w*h*4; i++)
|
||||
{
|
||||
if (outptr[i] != image[i])
|
||||
{
|
||||
log_error("READ_IMAGE_RGBA_UNORM_INT8 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("READ_IMAGE_RGBA_UNORM_INT8 test passed\n");
|
||||
return 0;
|
||||
color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));
|
||||
ushort4 dst_write;
|
||||
dst_write.x = convert_ushort_rte(color.x * 65535.0f);
|
||||
dst_write.y = convert_ushort_rte(color.y * 65535.0f);
|
||||
dst_write.z = convert_ushort_rte(color.z * 65535.0f);
|
||||
dst_write.w = convert_ushort_rte(color.w * 65535.0f);
|
||||
dst[indx] = dst_write;
|
||||
}
|
||||
|
||||
|
||||
int test_readimage(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
__kernel void test_CL_RGBACL_FLOAT(read_only image2d_t srcimg, __global float4 *dst, sampler_t smp)
|
||||
{
|
||||
cl_mem streams[3];
|
||||
cl_program program[2];
|
||||
cl_kernel kernel[2];
|
||||
cl_image_format img_format;
|
||||
cl_image_format *supported_formats;
|
||||
unsigned char *input_ptr[2], *output_ptr;
|
||||
size_t threads[2];
|
||||
int img_width = 512;
|
||||
int img_height = 512;
|
||||
int i, err;
|
||||
size_t origin[3] = {0, 0, 0};
|
||||
size_t region[3] = {img_width, img_height, 1};
|
||||
size_t length = img_width * img_height * 4 * sizeof(unsigned char);
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
int supportsBGRA = 0;
|
||||
cl_uint numFormats = 0;
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int indx = tid_y * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT( device )
|
||||
color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));
|
||||
|
||||
dst[indx].x = color.x;
|
||||
dst[indx].y = color.y;
|
||||
dst[indx].z = color.z;
|
||||
dst[indx].w = color.w;
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT( device )
|
||||
}
|
||||
)";
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
input_ptr[0] = generate_8888_image(img_width, img_height, d);
|
||||
input_ptr[1] = generate_8888_image(img_width, img_height, d);
|
||||
free_mtdata(d); d = NULL;
|
||||
static const char *kernel_source_3d = R"(
|
||||
__kernel void test_CL_BGRACL_UNORM_INT8(read_only image3d_t srcimg, __global uchar4 *dst, sampler_t sampler)
|
||||
{
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int tid_z = get_global_id(2);
|
||||
int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
output_ptr = (unsigned char*)malloc(length);
|
||||
color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0))* 255.0f;
|
||||
dst[indx].x = color.z;
|
||||
dst[indx].y = color.y;
|
||||
dst[indx].z = color.x;
|
||||
dst[indx].w = color.w;
|
||||
|
||||
if(gIsEmbedded)
|
||||
}
|
||||
|
||||
__kernel void test_CL_RGBACL_UNORM_INT8(read_only image3d_t srcimg, __global uchar4 *dst, sampler_t sampler)
|
||||
{
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int tid_z = get_global_id(2);
|
||||
int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0))* 255.0f;
|
||||
|
||||
dst[indx].x = color.x;
|
||||
dst[indx].y = color.y;
|
||||
dst[indx].z = color.z;
|
||||
dst[indx].w = color.w;
|
||||
|
||||
}
|
||||
|
||||
__kernel void test_CL_RGBACL_UNORM_INT16(read_only image3d_t srcimg, __global ushort4 *dst, sampler_t sampler)
|
||||
{
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int tid_z = get_global_id(2);
|
||||
int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));
|
||||
ushort4 dst_write;
|
||||
dst_write.x = convert_ushort_rte(color.x * 65535.0f);
|
||||
dst_write.y = convert_ushort_rte(color.y * 65535.0f);
|
||||
dst_write.z = convert_ushort_rte(color.z * 65535.0f);
|
||||
dst_write.w = convert_ushort_rte(color.w * 65535.0f);
|
||||
dst[indx] = dst_write;
|
||||
|
||||
}
|
||||
|
||||
__kernel void test_CL_RGBACL_FLOAT(read_only image3d_t srcimg, __global float *dst, sampler_t sampler)
|
||||
{
|
||||
int tid_x = get_global_id(0);
|
||||
int tid_y = get_global_id(1);
|
||||
int tid_z = get_global_id(2);
|
||||
int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;
|
||||
float4 color;
|
||||
|
||||
color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));
|
||||
indx *= 4;
|
||||
dst[indx+0] = color.x;
|
||||
dst[indx+1] = color.y;
|
||||
dst[indx+2] = color.z;
|
||||
dst[indx+3] = color.w;
|
||||
|
||||
}
|
||||
)";
|
||||
|
||||
template <typename T> void generate_random_inputs(std::vector<T> &v)
|
||||
{
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
auto random_generator = [&seed]() {
|
||||
return static_cast<T>(genrand_int32(seed));
|
||||
};
|
||||
|
||||
std::generate(v.begin(), v.end(), random_generator);
|
||||
}
|
||||
|
||||
template <> void generate_random_inputs<float>(std::vector<float> &v)
|
||||
{
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
auto random_generator = [&seed]() {
|
||||
return get_random_float(-0x40000000, 0x40000000, seed);
|
||||
};
|
||||
|
||||
std::generate(v.begin(), v.end(), random_generator);
|
||||
}
|
||||
|
||||
cl_mem create_image_xd(cl_context context, cl_mem_flags flags,
|
||||
cl_mem_object_type type, const cl_image_format *fmt,
|
||||
size_t x, size_t y, size_t z, cl_int *err)
|
||||
{
|
||||
|
||||
return (CL_MEM_OBJECT_IMAGE2D == type)
|
||||
? create_image_2d(context, flags, fmt, x, y, 0, nullptr, err)
|
||||
: create_image_3d(context, flags, fmt, x, y, z, 0, 0, nullptr, err);
|
||||
}
|
||||
|
||||
template <cl_mem_object_type IMG_TYPE, typename T>
|
||||
int test_readimage(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, const cl_image_format *img_format)
|
||||
{
|
||||
clMemWrapper streams[2];
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
clSamplerWrapper sampler;
|
||||
|
||||
std::string kernel_name("test_");
|
||||
|
||||
size_t img_width = TEST_IMAGE_WIDTH(IMG_TYPE);
|
||||
size_t img_height = TEST_IMAGE_HEIGHT(IMG_TYPE);
|
||||
size_t img_depth = TEST_IMAGE_DEPTH(IMG_TYPE);
|
||||
|
||||
int err;
|
||||
|
||||
const size_t origin[3] = { 0, 0, 0 };
|
||||
const size_t region[3] = { img_width, img_height, img_depth };
|
||||
|
||||
const size_t num_elements = img_width * img_height * img_depth * 4;
|
||||
const size_t length = num_elements * sizeof(T);
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT(device)
|
||||
|
||||
std::vector<T> input(num_elements);
|
||||
std::vector<T> output(num_elements);
|
||||
|
||||
generate_random_inputs(input);
|
||||
|
||||
streams[0] =
|
||||
create_image_xd(context, CL_MEM_READ_ONLY, IMG_TYPE, img_format,
|
||||
img_width, img_height, img_depth, &err);
|
||||
test_error(err, "create_image failed.");
|
||||
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed.");
|
||||
|
||||
sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE,
|
||||
CL_FILTER_NEAREST, &err);
|
||||
test_error(err, "clCreateSampler failed");
|
||||
|
||||
err = clEnqueueWriteImage(queue, streams[0], CL_TRUE, origin, region, 0, 0,
|
||||
input.data(), 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteImage failed.");
|
||||
|
||||
kernel_name += GetChannelOrderName(img_format->image_channel_order);
|
||||
kernel_name += GetChannelTypeName(img_format->image_channel_data_type);
|
||||
|
||||
const char **kernel_source = (CL_MEM_OBJECT_IMAGE2D == IMG_TYPE)
|
||||
? &kernel_source_2d
|
||||
: &kernel_source_3d;
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
kernel_source, kernel_name.c_str());
|
||||
test_error(err, "create_single_kernel_helper failed.");
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof(streams[1]), &streams[1]);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof(sampler), &sampler);
|
||||
test_error(err, "clSetKernelArgs failed\n");
|
||||
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, region, NULL, 0, NULL,
|
||||
NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed\n");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length,
|
||||
output.data(), 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueReadBuffer failed\n");
|
||||
|
||||
if (0 != memcmp(input.data(), output.data(), length))
|
||||
{
|
||||
/* Get the supported image formats to see if BGRA is supported */
|
||||
clGetSupportedImageFormats (context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &numFormats);
|
||||
supported_formats = (cl_image_format *) malloc(sizeof(cl_image_format) * numFormats);
|
||||
clGetSupportedImageFormats (context, CL_MEM_READ_WRITE, CL_MEM_OBJECT_IMAGE2D, numFormats, supported_formats, NULL);
|
||||
|
||||
for(i = 0; i < numFormats; i++)
|
||||
{
|
||||
if(supported_formats[i].image_channel_order == CL_BGRA)
|
||||
{
|
||||
supportsBGRA = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
log_error("READ_IMAGE_%s_%s test failed\n",
|
||||
GetChannelOrderName(img_format->image_channel_order),
|
||||
GetChannelTypeName(img_format->image_channel_data_type));
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
supportsBGRA = 1;
|
||||
log_info("READ_IMAGE_%s_%s test passed\n",
|
||||
GetChannelOrderName(img_format->image_channel_order),
|
||||
GetChannelTypeName(img_format->image_channel_data_type));
|
||||
}
|
||||
|
||||
if(supportsBGRA)
|
||||
{
|
||||
img_format.image_channel_order = CL_BGRA;
|
||||
img_format.image_channel_data_type = CL_UNORM_INT8;
|
||||
streams[0] = clCreateImage2D(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL);
|
||||
if (!streams[0])
|
||||
{
|
||||
log_error("clCreateImage2D failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
img_format.image_channel_order = CL_RGBA;
|
||||
img_format.image_channel_data_type = CL_UNORM_INT8;
|
||||
streams[1] = clCreateImage2D(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL);
|
||||
if (!streams[1])
|
||||
{
|
||||
log_error("clCreateImage2D failed\n");
|
||||
return -1;
|
||||
}
|
||||
streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL);
|
||||
if (!streams[2])
|
||||
{
|
||||
log_error("clCreateBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(supportsBGRA)
|
||||
{
|
||||
err = clEnqueueWriteImage(queue, streams[0], CL_TRUE, origin, region, 0, 0, input_ptr[0], 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueWriteImage failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
err = clEnqueueWriteImage(queue, streams[1], CL_TRUE, origin, region, 0, 0, input_ptr[1], 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueWriteImage failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(supportsBGRA)
|
||||
{
|
||||
err = create_single_kernel_helper(context, &program[0], &kernel[0], 1, &bgra8888_kernel_code, "test_bgra8888" );
|
||||
if (err)
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = create_single_kernel_helper(context, &program[1], &kernel[1], 1, &rgba8888_kernel_code, "test_rgba8888" );
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err);
|
||||
test_error(err, "clCreateSampler failed");
|
||||
|
||||
if(supportsBGRA)
|
||||
{
|
||||
err = clSetKernelArg(kernel[0], 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel[0], 1, sizeof streams[2], &streams[2]);
|
||||
err |= clSetKernelArg(kernel[0], 2, sizeof sampler, &sampler);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArg failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
err = clSetKernelArg(kernel[1], 0, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel[1], 1, sizeof streams[2], &streams[2]);
|
||||
err |= clSetKernelArg(kernel[1], 2, sizeof sampler, &sampler);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArg failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
threads[0] = (unsigned int)img_width;
|
||||
threads[1] = (unsigned int)img_height;
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
if(i == 0 && !supportsBGRA)
|
||||
continue;
|
||||
|
||||
err = clEnqueueNDRangeKernel(queue, kernel[i], 2, NULL, threads, NULL, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("%s clEnqueueNDRangeKernel failed\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueReadBuffer(queue, streams[2], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueReadBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
err = verify_bgra8888_image(input_ptr[i], output_ptr, img_width, img_height);
|
||||
break;
|
||||
case 1:
|
||||
err = verify_rgba8888_image(input_ptr[i], output_ptr, img_width, img_height);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
// cleanup
|
||||
clReleaseSampler(sampler);
|
||||
|
||||
if(supportsBGRA)
|
||||
clReleaseMemObject(streams[0]);
|
||||
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseMemObject(streams[2]);
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
if(i == 0 && !supportsBGRA)
|
||||
continue;
|
||||
|
||||
clReleaseKernel(kernel[i]);
|
||||
clReleaseProgram(program[i]);
|
||||
}
|
||||
free(input_ptr[0]);
|
||||
free(input_ptr[1]);
|
||||
free(output_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool check_format(cl_device_id device, cl_context context,
|
||||
cl_mem_object_type image_type,
|
||||
const cl_image_format img_format)
|
||||
{
|
||||
return is_image_format_required(img_format, CL_MEM_READ_ONLY, image_type,
|
||||
device)
|
||||
|| is_image_format_supported(context, CL_MEM_READ_ONLY, image_type,
|
||||
&img_format);
|
||||
}
|
||||
|
||||
}
|
||||
int test_readimage(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
const cl_image_format format[] = { { CL_RGBA, CL_UNORM_INT8 },
|
||||
{ CL_BGRA, CL_UNORM_INT8 } };
|
||||
|
||||
int err = test_readimage<CL_MEM_OBJECT_IMAGE2D, cl_uchar>(
|
||||
device, context, queue, &format[0]);
|
||||
|
||||
if (check_format(device, context, CL_MEM_OBJECT_IMAGE2D, format[1]))
|
||||
{
|
||||
err |= test_readimage<CL_MEM_OBJECT_IMAGE2D, cl_uchar>(
|
||||
device, context, queue, &format[1]);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_readimage_int16(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
const cl_image_format format = { CL_RGBA, CL_UNORM_INT16 };
|
||||
return test_readimage<CL_MEM_OBJECT_IMAGE2D, cl_ushort>(device, context,
|
||||
queue, &format);
|
||||
}
|
||||
|
||||
int test_readimage_fp32(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
const cl_image_format format = { CL_RGBA, CL_FLOAT };
|
||||
return test_readimage<CL_MEM_OBJECT_IMAGE2D, cl_float>(device, context,
|
||||
queue, &format);
|
||||
}
|
||||
|
||||
int test_readimage3d(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
const cl_image_format format[] = { { CL_RGBA, CL_UNORM_INT8 },
|
||||
{ CL_BGRA, CL_UNORM_INT8 } };
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(device)
|
||||
|
||||
int err = test_readimage<CL_MEM_OBJECT_IMAGE3D, cl_uchar>(
|
||||
device, context, queue, &format[0]);
|
||||
|
||||
if (check_format(device, context, CL_MEM_OBJECT_IMAGE3D, format[1]))
|
||||
{
|
||||
err |= test_readimage<CL_MEM_OBJECT_IMAGE3D, cl_uchar>(
|
||||
device, context, queue, &format[1]);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int test_readimage3d_int16(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
const cl_image_format format = { CL_RGBA, CL_UNORM_INT16 };
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(device)
|
||||
|
||||
return test_readimage<CL_MEM_OBJECT_IMAGE3D, cl_ushort>(device, context,
|
||||
queue, &format);
|
||||
}
|
||||
int test_readimage3d_fp32(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
const cl_image_format format = { CL_RGBA, CL_FLOAT };
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(device)
|
||||
|
||||
return test_readimage<CL_MEM_OBJECT_IMAGE3D, cl_float>(device, context,
|
||||
queue, &format);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,213 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
#include "harness/imageHelpers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
static const char *bgra8888_kernel_code =
|
||||
"\n"
|
||||
"__kernel void test_bgra8888(read_only image3d_t srcimg, __global float4 *dst, sampler_t sampler)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int tid_z = get_global_id(2);\n"
|
||||
" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n"
|
||||
" dst[indx].x = color.z;\n"
|
||||
" dst[indx].y = color.y;\n"
|
||||
" dst[indx].z = color.x;\n"
|
||||
" dst[indx].w = color.w;\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
static const char *rgba8888_kernel_code =
|
||||
"\n"
|
||||
"__kernel void test_rgba8888(read_only image3d_t srcimg, __global float4 *dst, sampler_t sampler)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int tid_z = get_global_id(2);\n"
|
||||
" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n"
|
||||
" //indx *= 4;\n"
|
||||
" dst[indx].x = color.x;\n"
|
||||
" dst[indx].y = color.y;\n"
|
||||
" dst[indx].z = color.z;\n"
|
||||
" dst[indx].w = color.w;\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
static unsigned char *
|
||||
generate_3d_image8(int w, int h, int d, MTdata data)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char*)malloc(w * h * d * 4);
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
ptr[i] = (unsigned char)genrand_int32(data);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
verify_3d_image8(double *image, float *outptr, int w, int h, int d)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
{
|
||||
if (outptr[i] != (float)image[i])
|
||||
{
|
||||
float ulps = Ulp_Error( outptr[i], image[i]);
|
||||
|
||||
if(! (fabsf(ulps) < 1.5f) )
|
||||
{
|
||||
log_error( "ERROR: Data sample %d does not validate! Expected (%a), got (%a), ulp %f\n",
|
||||
(int)i, image[i], outptr[ i ], ulps );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double *
|
||||
prepare_reference(unsigned char * input_ptr, int w, int h, int d)
|
||||
{
|
||||
double *ptr = (double*)malloc(w * h * d * 4 * sizeof(double));
|
||||
int i;
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
ptr[i] = ((double)input_ptr[i]/255);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int test_readimage3d(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
cl_sampler sampler;
|
||||
struct testFormat
|
||||
{
|
||||
const char* kernelName;
|
||||
const char* kernelSourceString;
|
||||
const cl_image_format img_format;
|
||||
};
|
||||
|
||||
static testFormat formatsToTest[] =
|
||||
{
|
||||
{
|
||||
"test_bgra8888",
|
||||
bgra8888_kernel_code,
|
||||
{CL_BGRA, CL_UNORM_INT8},
|
||||
},
|
||||
{
|
||||
"test_rgba8888",
|
||||
rgba8888_kernel_code,
|
||||
{CL_RGBA, CL_UNORM_INT8},
|
||||
},
|
||||
};
|
||||
|
||||
unsigned char *input_ptr;
|
||||
float *output_ptr;
|
||||
double *ref_ptr;
|
||||
size_t threads[3];
|
||||
int img_width = 64;
|
||||
int img_height = 64;
|
||||
int img_depth = 64;
|
||||
int i, err;
|
||||
size_t origin[3] = {0, 0, 0};
|
||||
size_t region[3] = {img_width, img_height, img_depth};
|
||||
size_t length = img_width * img_height * img_depth * 4 * sizeof(float);
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device )
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(formatsToTest); i++)
|
||||
{
|
||||
if (!is_image_format_required(formatsToTest[i].img_format, CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, device))
|
||||
continue;
|
||||
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
input_ptr = generate_3d_image8(img_width, img_height, img_depth, d);
|
||||
ref_ptr = prepare_reference(input_ptr, img_width, img_height, img_depth);
|
||||
output_ptr = (float*)malloc(length);
|
||||
|
||||
streams[0] = create_image_3d(context, CL_MEM_READ_ONLY, &formatsToTest[i].img_format, img_width, img_height, img_depth, 0, 0, NULL, &err);
|
||||
test_error(err, "create_image_3d failed");
|
||||
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err);
|
||||
test_error(err, "clCreateSampler failed");
|
||||
|
||||
err = clEnqueueWriteImage(queue, streams[0], CL_TRUE, origin, region, 0, 0, input_ptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteImage failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &formatsToTest[i].kernelSourceString, formatsToTest[i].kernelName);
|
||||
test_error(err, "create_single_kernel_helper failed");
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
threads[0] = (unsigned int)img_width;
|
||||
threads[1] = (unsigned int)img_height;
|
||||
threads[2] = (unsigned int)img_depth;
|
||||
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
err = verify_3d_image8(ref_ptr, output_ptr, img_width, img_height, img_depth);
|
||||
if ( err == 0 )
|
||||
{
|
||||
log_info("READ_IMAGE3D_%s_%s test passed\n",
|
||||
GetChannelTypeName(formatsToTest[i].img_format.image_channel_data_type),
|
||||
GetChannelOrderName(formatsToTest[i].img_format.image_channel_order));
|
||||
}
|
||||
|
||||
clReleaseSampler(sampler);
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
free_mtdata(d);
|
||||
d = NULL;
|
||||
free(input_ptr);
|
||||
free(ref_ptr);
|
||||
free(output_ptr);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
|
||||
static const char *rgbaFFFF_kernel_code =
|
||||
"__kernel void test_rgbaFFFF(read_only image3d_t srcimg, __global float *dst, sampler_t sampler)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int tid_z = get_global_id(2);\n"
|
||||
" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n"
|
||||
" indx *= 4;\n"
|
||||
" dst[indx+0] = color.x;\n"
|
||||
" dst[indx+1] = color.y;\n"
|
||||
" dst[indx+2] = color.z;\n"
|
||||
" dst[indx+3] = color.w;\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static float *
|
||||
generate_float_image(int w, int h, int d, MTdata data)
|
||||
{
|
||||
float *ptr = (float*)malloc(w * h * d * 4 * sizeof(float));
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
ptr[i] = get_random_float(-0x40000000, 0x40000000, data);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
verify_float_image(float *image, float *outptr, int w, int h, int d)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
{
|
||||
if (outptr[i] != image[i])
|
||||
{
|
||||
log_error("READ_IMAGE3D_RGBA_FLOAT test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("READ_IMAGE3D_RGBA_FLOAT test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int test_readimage3d_fp32(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
cl_image_format img_format;
|
||||
float *input_ptr, *output_ptr;
|
||||
size_t threads[3];
|
||||
int img_width = 64;
|
||||
int img_height = 64;
|
||||
int img_depth = 64;
|
||||
int err;
|
||||
size_t origin[3] = {0, 0, 0};
|
||||
size_t region[3] = {img_width, img_height, img_depth};
|
||||
size_t length = img_width * img_height * img_depth * 4 * sizeof(float);
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device )
|
||||
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
input_ptr = generate_float_image(img_width, img_height, img_depth, d);
|
||||
free_mtdata(d); d = NULL;
|
||||
|
||||
output_ptr = (float*)malloc(length);
|
||||
|
||||
img_format.image_channel_order = CL_RGBA;
|
||||
img_format.image_channel_data_type = CL_FLOAT;
|
||||
streams[0] = create_image_3d(context, CL_MEM_READ_ONLY, &img_format, img_width, img_height, img_depth, 0, 0, NULL, &err);
|
||||
test_error(err, "create_image_3d failed");
|
||||
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
err = clEnqueueWriteImage(queue, streams[0], CL_TRUE, origin, region, 0, 0, input_ptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteImage failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &rgbaFFFF_kernel_code, "test_rgbaFFFF" );
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err);
|
||||
test_error(err, "clCreateSampler failed");
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
threads[0] = (unsigned int)img_width;
|
||||
threads[1] = (unsigned int)img_height;
|
||||
threads[2] = (unsigned int)img_depth;
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
err = verify_float_image(input_ptr, output_ptr, img_width, img_height, img_depth);
|
||||
|
||||
// cleanup
|
||||
clReleaseSampler(sampler);
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
free(input_ptr);
|
||||
free(output_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
static const char *rgba16_kernel_code =
|
||||
"__kernel void test_rgba16(read_only image3d_t srcimg, __global ushort4 *dst, sampler_t sampler)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int tid_z = get_global_id(2);\n"
|
||||
" int indx = (tid_z * get_image_height(srcimg) + tid_y) * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, sampler, (int4)(tid_x, tid_y, tid_z, 0));\n"
|
||||
" ushort4 dst_write;\n"
|
||||
" dst_write.x = convert_ushort_rte(color.x * 65535.0f);\n"
|
||||
" dst_write.y = convert_ushort_rte(color.y * 65535.0f);\n"
|
||||
" dst_write.z = convert_ushort_rte(color.z * 65535.0f);\n"
|
||||
" dst_write.w = convert_ushort_rte(color.w * 65535.0f);\n"
|
||||
" dst[indx] = dst_write;\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static unsigned short *
|
||||
generate_16bit_image(int w, int h, int d, MTdata data)
|
||||
{
|
||||
unsigned short *ptr = (cl_ushort*)malloc(w * h * d * 4 * sizeof(cl_ushort));
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
ptr[i] = (cl_ushort)genrand_int32(data);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
verify_16bit_image(cl_ushort *image, cl_ushort *outptr, int w, int h, int d)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*d*4; i++)
|
||||
{
|
||||
if (outptr[i] != image[i])
|
||||
{
|
||||
log_error("READ_IMAGE3D_RGBA_UNORM_INT16 test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("READ_IMAGE3D_RGBA_UNORM_INT16 test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_readimage3d_int16(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
cl_image_format img_format;
|
||||
cl_ushort *input_ptr, *output_ptr;
|
||||
size_t threads[3];
|
||||
int img_width = 64;
|
||||
int img_height = 64;
|
||||
int img_depth = 64;
|
||||
int err;
|
||||
size_t origin[3] = {0, 0, 0};
|
||||
size_t region[3] = {img_width, img_height, img_depth};
|
||||
size_t length = img_width * img_height * img_depth * 4 * sizeof(cl_ushort);
|
||||
|
||||
PASSIVE_REQUIRE_3D_IMAGE_SUPPORT( device )
|
||||
|
||||
MTdata d = init_genrand( gRandomSeed );
|
||||
input_ptr = generate_16bit_image(img_width, img_height, img_depth, d);
|
||||
free_mtdata(d); d = NULL;
|
||||
|
||||
output_ptr = (cl_ushort*)malloc(length);
|
||||
|
||||
img_format.image_channel_order = CL_RGBA;
|
||||
img_format.image_channel_data_type = CL_UNORM_INT16;
|
||||
streams[0] = create_image_3d(context, CL_MEM_READ_ONLY, &img_format, img_width, img_height, img_depth, 0, 0, NULL, &err);
|
||||
test_error(err, "create_image_3d failed");
|
||||
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
err = clEnqueueWriteImage(queue, streams[0], CL_TRUE, origin, region, 0, 0, input_ptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueWriteImage failed");
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &rgba16_kernel_code, "test_rgba16" );
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err);
|
||||
test_error(err, "clCreateSampler failed");
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
threads[0] = (unsigned int)img_width;
|
||||
threads[1] = (unsigned int)img_height;
|
||||
threads[2] = (unsigned int)img_depth;
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, threads, NULL, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
err = verify_16bit_image(input_ptr, output_ptr, img_width, img_height, img_depth);
|
||||
|
||||
// cleanup
|
||||
clReleaseSampler(sampler);
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
free(input_ptr);
|
||||
free(output_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
|
||||
static const char *rgbaFFFF_kernel_code =
|
||||
"__kernel void test_rgbaFFFF(read_only image2d_t srcimg, __global float *dst, sampler_t smp)\n"
|
||||
"{\n"
|
||||
" int tid_x = get_global_id(0);\n"
|
||||
" int tid_y = get_global_id(1);\n"
|
||||
" int indx = tid_y * get_image_width(srcimg) + tid_x;\n"
|
||||
" float4 color;\n"
|
||||
"\n"
|
||||
" color = read_imagef(srcimg, smp, (int2)(tid_x, tid_y));\n"
|
||||
" indx *= 4;\n"
|
||||
" dst[indx+0] = color.x;\n"
|
||||
" dst[indx+1] = color.y;\n"
|
||||
" dst[indx+2] = color.z;\n"
|
||||
" dst[indx+3] = color.w;\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static float *
|
||||
generate_float_image(int w, int h, MTdata d)
|
||||
{
|
||||
float *ptr = (float*)malloc(w * h * 4 * sizeof(float));
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*4; i++)
|
||||
ptr[i] = get_random_float(-0x40000000, 0x40000000, d);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
verify_float_image(float *image, float *outptr, int w, int h)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<w*h*4; i++)
|
||||
{
|
||||
if (outptr[i] != image[i])
|
||||
{
|
||||
log_error("READ_IMAGE_RGBA_FLOAT test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("READ_IMAGE_RGBA_FLOAT test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_readimage_fp32(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
cl_image_format img_format;
|
||||
float *input_ptr, *output_ptr;
|
||||
size_t threads[2];
|
||||
int img_width = 512;
|
||||
int img_height = 512;
|
||||
int err;
|
||||
size_t origin[3] = {0, 0, 0};
|
||||
size_t region[3] = {img_width, img_height, 1};
|
||||
size_t length = img_width * img_height * 4 * sizeof(float);
|
||||
MTdata d;
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT( device )
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
input_ptr = generate_float_image(img_width, img_height, d);
|
||||
free_mtdata(d); d = NULL;
|
||||
|
||||
output_ptr = (float*)malloc(length);
|
||||
|
||||
img_format.image_channel_order = CL_RGBA;
|
||||
img_format.image_channel_data_type = CL_FLOAT;
|
||||
streams[0] = create_image_2d(context, CL_MEM_READ_WRITE, &img_format, img_width, img_height, 0, NULL, NULL);
|
||||
if (!streams[0])
|
||||
{
|
||||
log_error("create_image_2d failed\n");
|
||||
return -1;
|
||||
}
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, length, NULL, NULL);
|
||||
if (!streams[1])
|
||||
{
|
||||
log_error("clCreateArray failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = clEnqueueWriteImage(queue, streams[0], CL_TRUE, origin, region, 0, 0, input_ptr, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clWriteImage failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &rgbaFFFF_kernel_code, "test_rgbaFFFF" );
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
cl_sampler sampler = clCreateSampler(context, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST, &err);
|
||||
test_error(err, "clCreateSampler failed");
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof sampler, &sampler);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArgs failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
threads[0] = (unsigned int)img_width;
|
||||
threads[1] = (unsigned int)img_height;
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, threads, NULL, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("%s clEnqueueNDRangeKernel failed\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, length, output_ptr, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueReadBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = verify_float_image(input_ptr, output_ptr, img_width, img_height);
|
||||
|
||||
// cleanup
|
||||
clReleaseSampler(sampler);
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
free(input_ptr);
|
||||
free(output_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue