Compare commits
399 commits
main
...
upstream/f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11e39f533b | ||
|
|
4019a26a5b | ||
|
|
620c689919 | ||
|
|
d338b42e8f | ||
|
|
79fc236e4a | ||
|
|
87dc09c66f | ||
|
|
4216c5323d | ||
|
|
0fa6f236be | ||
|
|
f5bd92b83e | ||
|
|
5815e2ce33 | ||
|
|
eec46a087a | ||
|
|
8b1a44f93f | ||
|
|
482126d611 | ||
|
|
ea6e536ed3 | ||
|
|
f08b3f6aee | ||
|
|
be626ca1fa | ||
|
|
42434d04d0 | ||
|
|
115e999a38 | ||
|
|
7e4b59dfaa | ||
|
|
40aaa2bcf2 | ||
|
|
c6dd6f2aa3 | ||
|
|
72bb711646 | ||
|
|
c73d6a341b | ||
|
|
af2710355d | ||
|
|
a7c33f8dc4 | ||
|
|
60fc7fc844 | ||
|
|
e3c8de8eb6 | ||
|
|
1fe72877d7 | ||
|
|
4984196bcb | ||
|
|
7f0c0aee05 | ||
|
|
43d6886810 | ||
|
|
f39685030f | ||
|
|
b143a990d9 | ||
|
|
7759c2669a | ||
|
|
aa953aaa51 | ||
|
|
1c616238bc | ||
|
|
d20913b4e3 | ||
|
|
d7f24a7986 | ||
|
|
39cca992b8 | ||
|
|
d20de8ddea | ||
|
|
15b54aa0bd | ||
|
|
c511ac62b0 | ||
|
|
8fd55dc889 | ||
|
|
bd548e63e6 | ||
|
|
a3262eb4b6 | ||
|
|
c23631c690 | ||
|
|
46fde8d051 | ||
|
|
ddbb0de4b9 | ||
|
|
0702f2ecee | ||
|
|
df53e02a12 | ||
|
|
ddf46ca9e8 | ||
|
|
aa23f345c3 | ||
|
|
e29d0fd3a1 | ||
|
|
a01349c44e | ||
|
|
0460756f6e | ||
|
|
25ce398037 | ||
|
|
339c932c57 | ||
|
|
cd5c165946 | ||
|
|
3a1daafd5a | ||
|
|
c3babfeebb | ||
|
|
3c1f2814b8 | ||
|
|
19bddc90e4 | ||
|
|
b32d566bca | ||
|
|
6c841fbad8 | ||
|
|
c69bc00b56 | ||
|
|
ae1a712e3e | ||
|
|
64130824a8 | ||
|
|
3b7fda2071 | ||
|
|
1ab4b26821 | ||
|
|
2686b9e2c1 | ||
|
|
3a1388a2b4 | ||
|
|
40b3eb3f7f | ||
|
|
1e2d3522cf | ||
|
|
9e8430a6a6 | ||
|
|
9b0f78549a | ||
|
|
845ec694bb | ||
|
|
729cd8b7a9 | ||
|
|
75aca34e60 | ||
|
|
56974a5858 | ||
|
|
fee6d6bb66 | ||
|
|
73ead9da04 | ||
|
|
43c244f01d | ||
|
|
2495eca9fa | ||
|
|
60f025a7da | ||
|
|
2e88013b34 | ||
|
|
50f9f06323 | ||
|
|
df3ec8deec | ||
|
|
0e229b8f01 | ||
|
|
44b2578ac7 | ||
|
|
16a75dc0af | ||
|
|
095091bc57 | ||
|
|
475a37abbf | ||
|
|
c8061ab21a | ||
|
|
1011f8ea81 | ||
|
|
658a8b62fb | ||
|
|
b843b3bd8c | ||
|
|
c467391680 | ||
|
|
63a8cb6b9d | ||
|
|
ce17549812 | ||
|
|
abd556f7a2 | ||
|
|
19f4fc3f3d | ||
|
|
38abfc7d24 | ||
|
|
b3c1401d48 | ||
|
|
c58ead9aea | ||
|
|
9692380505 | ||
|
|
4cb39b8c14 | ||
|
|
35b8db35c6 | ||
|
|
4dece20f7d | ||
|
|
3e8898ffeb | ||
|
|
957e3b3985 | ||
|
|
4f62adf1ca | ||
|
|
8f3027387a | ||
|
|
85c95297ac | ||
|
|
32688a47b3 | ||
|
|
0447b7a2c8 | ||
|
|
f31b2f029c | ||
|
|
1884042f5d | ||
|
|
06c0c99c2e | ||
|
|
b23268acf5 | ||
|
|
d223e46f20 | ||
|
|
8272c83c6f | ||
|
|
20afedbd4a | ||
|
|
caa656c268 | ||
|
|
ff1369d94e | ||
|
|
033aa195c5 | ||
|
|
aa34b4b8c3 | ||
|
|
b57445e56a | ||
|
|
4f5af72088 | ||
|
|
5b87f53fe8 | ||
|
|
9772516c3f | ||
|
|
f0f887d07f | ||
|
|
605228ae7f | ||
|
|
a70fa56003 | ||
|
|
8e74722a0a | ||
|
|
9afb918bf5 | ||
|
|
14f421e54b | ||
|
|
868de6c15e | ||
|
|
20ab003053 | ||
|
|
f537c40abc | ||
|
|
8352966818 | ||
|
|
c3d36bf9fb | ||
|
|
3478f3d304 | ||
|
|
63b0f441f1 | ||
|
|
b7f2dd58e9 | ||
|
|
9755c7ac58 | ||
|
|
1f94b5748b | ||
|
|
9e0369b307 | ||
|
|
9798a96a9f | ||
|
|
5297ecd673 | ||
|
|
e882a3dc5e | ||
|
|
0b44338eda | ||
|
|
712eb4f988 | ||
|
|
33285facbe | ||
|
|
dc8ee495bd | ||
|
|
75db137822 | ||
|
|
531e5e82f9 | ||
|
|
e71a7bce68 | ||
|
|
df3c4fae95 | ||
|
|
2c9526f9a5 | ||
|
|
296a7a574d | ||
|
|
fa2c1d2417 | ||
|
|
61ec521b1c | ||
|
|
560d6eafbd | ||
|
|
b81b49e10e | ||
|
|
1e5b5c96e2 | ||
|
|
11782f7650 | ||
|
|
b73c3149ad | ||
|
|
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 |
762 changed files with 81007 additions and 85556 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
|
||||
47
.github/workflows/presubmit.yml
vendored
47
.github/workflows/presubmit.yml
vendored
|
|
@ -3,38 +3,63 @@ 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-22.04, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
mainmatrix: true
|
||||
gl: 1
|
||||
- os: ubuntu-20.04
|
||||
extra: " gl"
|
||||
- os: ubuntu-22.04
|
||||
mainmatrix: false
|
||||
name: Arm
|
||||
arch: arm
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
mainmatrix: false
|
||||
name: AArch64
|
||||
arch: aarch64
|
||||
debug: 1
|
||||
extra: " debug"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- 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
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: sudo apt install -y clang-format
|
||||
- uses: actions/checkout@v2
|
||||
run: sudo apt install -y clang-format clang-format-11
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check code format
|
||||
|
|
|
|||
155
CMakeLists.txt
155
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)
|
||||
|
|
@ -23,20 +17,13 @@ add_definitions(-DCL_USE_DEPRECATED_OPENCL_2_0_APIS=1)
|
|||
add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_2_APIS=1)
|
||||
add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS=1)
|
||||
add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_0_APIS=1)
|
||||
add_definitions(-DCL_NO_EXTENSION_PROTOTYPES)
|
||||
|
||||
option(USE_CL_EXPERIMENTAL "Use Experimental definitions" OFF)
|
||||
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 +31,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 +50,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)
|
||||
|
|
@ -140,21 +83,32 @@ endif()
|
|||
|
||||
macro(add_cxx_flag_if_supported flag)
|
||||
string(REGEX REPLACE "[-=+]" "" FLAG_NO_SIGNS ${flag})
|
||||
check_cxx_compiler_flag(${flag} COMPILER_SUPPORTS_${FLAG_NO_SIGNS})
|
||||
set(FLAG_TO_TEST ${flag})
|
||||
if((${flag} MATCHES "^-Wno-") AND NOT (${flag} MATCHES "^-Wno-error="))
|
||||
# -Wno-... only causes a diagnostic if another diagnostic is emitted.
|
||||
# Change such flags into a -W... flag to test if the warning is known.
|
||||
string(REGEX REPLACE "^-Wno-" "-W" FLAG_TO_TEST ${flag})
|
||||
endif()
|
||||
check_cxx_compiler_flag(${FLAG_TO_TEST} COMPILER_SUPPORTS_${FLAG_NO_SIGNS})
|
||||
if(COMPILER_SUPPORTS_${FLAG_NO_SIGNS})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
|
||||
endif()
|
||||
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(-Werror)
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo|MinSizeRel")
|
||||
# Enable more warnings if not doing a release build.
|
||||
add_cxx_flag_if_supported(-Wall)
|
||||
endif()
|
||||
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-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 +126,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" )
|
||||
|
|
@ -182,6 +157,11 @@ if( WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" )
|
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qlong-double -Qpc80 /DWIN32 /D_WINDOWS /W3 /GR /EHsc -nologo -Od -D_CRT_NONSTDC_NO_WARNINGS -EHsc -Wall -Qdiag-disable:68,111,177,186,161,869,1028,2259,2553,181,239,265,1188 -fp:strict -fp:source")
|
||||
endif()
|
||||
|
||||
# To handle addresses larger than 2 gigabytes for 32bit targets
|
||||
if(WIN32 AND ${CLConform_TARGET_ARCH} STREQUAL "x86")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
|
||||
endif()
|
||||
|
||||
list(APPEND CLConform_LIBRARIES ${OPENCL_LIBRARIES})
|
||||
if(ANDROID)
|
||||
list(APPEND CLConform_LIBRARIES m)
|
||||
|
|
@ -197,10 +177,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 +190,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 is 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 submission.
|
||||
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 question 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,8 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Arg used to specify non-'origin/master' comparison branch
|
||||
ORIGIN_BRANCH=${1:-"origin/master"}
|
||||
CLANG_BINARY=${2:-"`which clang-format-9`"}
|
||||
# Arg used to specify non-'origin/main' comparison branch
|
||||
ORIGIN_BRANCH=${1:-"origin/main"}
|
||||
CLANG_BINARY=${2:-"`which clang-format-11`"}
|
||||
|
||||
# Run git-clang-format to check for violations
|
||||
CLANG_FORMAT_OUTPUT=$(git-clang-format --diff $ORIGIN_BRANCH --extensions c,cpp,h,hpp --binary $CLANG_BINARY)
|
||||
|
|
|
|||
68
presubmit.sh
68
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,67 @@ 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 \
|
||||
-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()) }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -966,12 +966,13 @@ void reorder_verification_buffer(GLenum glFormat, GLenum glType, char* buffer, s
|
|||
|
||||
#ifdef GL_VERSION_3_2
|
||||
|
||||
#define check_gl_error() \
|
||||
{ \
|
||||
GLenum errnom = GL_NO_ERROR;\
|
||||
if ((errnom = glGetError()) != GL_NO_ERROR)\
|
||||
log_error("GL Error: 0x%04X at %s:%d\n", errnom, __FILE__, __LINE__);\
|
||||
}
|
||||
#define CHECK_GL_ERROR() \
|
||||
{ \
|
||||
GLenum errnom = GL_NO_ERROR; \
|
||||
if ((errnom = glGetError()) != GL_NO_ERROR) \
|
||||
log_error("GL Error: 0x%04X at %s:%d\n", errnom, __FILE__, \
|
||||
__LINE__); \
|
||||
}
|
||||
|
||||
const char *get_gl_vector_type( GLenum internalformat )
|
||||
{
|
||||
|
|
@ -1045,10 +1046,12 @@ void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples
|
|||
|
||||
// Check if the renderer supports enough samples
|
||||
GLint max_samples = get_gl_max_samples(target, internalFormat);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
if (max_samples < (GLint)samples)
|
||||
log_error("GL error: requested samples (%d) exceeds renderer max samples (%d)\n", samples, max_samples);
|
||||
log_error("GL error: requested samples (%zu) exceeds renderer max "
|
||||
"samples (%d)\n",
|
||||
samples, max_samples);
|
||||
|
||||
// Setup the GLSL program
|
||||
const GLchar *vertex_source =
|
||||
|
|
@ -1075,36 +1078,36 @@ void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples
|
|||
glShaderWrapper vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_source, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glShaderWrapper fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_source, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLuint prog = glCreateProgram();
|
||||
glAttachShader(prog, vertex_shader);
|
||||
glAttachShader(prog, fragment_shader);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glBindAttribLocation(prog, 0, "att0");
|
||||
glLinkProgram(prog);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
// Setup the FBO and texture
|
||||
glFramebufferWrapper fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLuint tex = 0;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, fixedSampleLocations);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLint attachment;
|
||||
switch (internalFormat) {
|
||||
|
|
@ -1122,7 +1125,7 @@ void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples
|
|||
}
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, tex, 0);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
|
||||
|
|
@ -1142,22 +1145,24 @@ void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples
|
|||
// Check if the framebuffer supports enough samples
|
||||
GLint fbo_samples = 0;
|
||||
glGetIntegerv(GL_SAMPLES, &fbo_samples);
|
||||
check_gl_error();
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (fbo_samples < (GLint)samples)
|
||||
log_error("GL Error: requested samples (%d) exceeds FBO capability (%d)\n", samples, fbo_samples);
|
||||
log_error(
|
||||
"GL Error: requested samples (%zu) exceeds FBO capability (%d)\n",
|
||||
samples, fbo_samples);
|
||||
|
||||
glUseProgram(prog);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
if (attachment != GL_DEPTH_ATTACHMENT && attachment != GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
}
|
||||
else {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
}
|
||||
|
||||
// Setup the VBO for rendering a quad
|
||||
|
|
@ -1172,14 +1177,14 @@ void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples
|
|||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glVertexArraysWrapper vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, 0);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
//clearing color and depth buffer
|
||||
glClearColor(0, 0, 0, 0);
|
||||
|
|
@ -1223,13 +1228,13 @@ void * CreateGLTexture2DMultisample( size_t width, size_t height, size_t samples
|
|||
color += color_delta;
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
check_gl_error();
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
glDisable(GL_SAMPLE_MASK);
|
||||
check_gl_error();
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
*outTextureID = tex;
|
||||
|
||||
|
|
@ -1306,7 +1311,9 @@ void * CreateGLTexture2DArrayMultisample(size_t width, size_t height,
|
|||
GLint max_samples = get_gl_max_samples(target, internalFormat);
|
||||
|
||||
if (max_samples < (GLint)samples)
|
||||
log_error("GL error: requested samples (%d) exceeds renderer max samples (%d)\n", samples, max_samples);
|
||||
log_error("GL error: requested samples (%zu) exceeds renderer max "
|
||||
"samples (%d)\n",
|
||||
samples, max_samples);
|
||||
|
||||
// Setup the GLSL program
|
||||
const GLchar *vertex_source =
|
||||
|
|
@ -1333,36 +1340,36 @@ void * CreateGLTexture2DArrayMultisample(size_t width, size_t height,
|
|||
glShaderWrapper vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_source, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glShaderWrapper fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_source, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glProgramWrapper prog = glCreateProgram();
|
||||
glAttachShader(prog, vertex_shader);
|
||||
glAttachShader(prog, fragment_shader);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glBindAttribLocation(prog, 0, "att0");
|
||||
glLinkProgram(prog);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
// Setup the FBO and texture
|
||||
glFramebufferWrapper fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLuint tex = 0;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, tex);
|
||||
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, samples, internalFormat, width, height, total_layers, fixedSampleLocations);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLint attachment;
|
||||
switch (internalFormat) {
|
||||
|
|
@ -1381,16 +1388,15 @@ 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);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
}
|
||||
else {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
}
|
||||
|
||||
// Setup the VBO for rendering a quad
|
||||
|
|
@ -1405,18 +1411,18 @@ void * CreateGLTexture2DArrayMultisample(size_t width, size_t height,
|
|||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STREAM_DRAW);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
glVertexArraysWrapper vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, 0);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
for (size_t l=0; l!=total_layers; ++l) {
|
||||
glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, tex, 0, l);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
|
||||
|
|
@ -1436,13 +1442,15 @@ void * CreateGLTexture2DArrayMultisample(size_t width, size_t height,
|
|||
// Check if the framebuffer supports enough samples
|
||||
GLint fbo_samples = 0;
|
||||
glGetIntegerv(GL_SAMPLES, &fbo_samples);
|
||||
check_gl_error();
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (fbo_samples < (GLint)samples)
|
||||
log_error("GL Error: requested samples (%d) exceeds FBO capability (%d)\n", samples, fbo_samples);
|
||||
log_error(
|
||||
"GL Error: requested samples (%zu) exceeds FBO capability (%d)\n",
|
||||
samples, fbo_samples);
|
||||
|
||||
glUseProgram(prog);
|
||||
check_gl_error()
|
||||
CHECK_GL_ERROR()
|
||||
|
||||
//clearing color and depth buffer
|
||||
glClearColor(0, 0, 0, 0);
|
||||
|
|
@ -1483,13 +1491,13 @@ void * CreateGLTexture2DArrayMultisample(size_t width, size_t height,
|
|||
glUniform1f(glGetUniformLocation(prog, "depthVal"), val);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
check_gl_error();
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
glDisable(GL_SAMPLE_MASK);
|
||||
check_gl_error();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
*outTextureID = tex;
|
||||
|
|
@ -1716,7 +1724,7 @@ void * CreateGLRenderbuffer( GLsizei width, GLsizei height,
|
|||
// Reverse and reorder to validate since in the
|
||||
// kernel the read_imagef() call always returns RGBA
|
||||
cl_uchar *p = (cl_uchar *)buffer;
|
||||
for( size_t i = 0; i < (size_t)width * height; i++ )
|
||||
for (GLsizei i = 0; i < width * height; i++)
|
||||
{
|
||||
cl_uchar uc0 = p[i * 4 + 0];
|
||||
cl_uchar uc1 = p[i * 4 + 1];
|
||||
|
|
@ -1734,7 +1742,7 @@ void * CreateGLRenderbuffer( GLsizei width, GLsizei height,
|
|||
// Reverse and reorder to validate since in the
|
||||
// kernel the read_imagef() call always returns RGBA
|
||||
cl_uchar *p = (cl_uchar *)buffer;
|
||||
for( size_t i = 0; i < width * height; i++ )
|
||||
for (GLsizei i = 0; i < width * height; i++)
|
||||
{
|
||||
cl_uchar uc0 = p[i * 4 + 0];
|
||||
cl_uchar uc1 = p[i * 4 + 1];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef _COMPAT_H_
|
||||
#define _COMPAT_H_
|
||||
#ifndef COMPAT_H_
|
||||
#define COMPAT_H_
|
||||
|
||||
#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:
|
||||
|
|
@ -405,4 +398,4 @@ EXTERN_C int __builtin_clz(unsigned int pattern);
|
|||
#define sleep(sec) Sleep((sec)*1000)
|
||||
#endif
|
||||
|
||||
#endif // _COMPAT_H_
|
||||
#endif // COMPAT_H_
|
||||
|
|
|
|||
|
|
@ -14,12 +14,15 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
#include "conversions.h"
|
||||
#include <cinttypes>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "mt19937.h"
|
||||
#include "compat.h"
|
||||
|
||||
#include <CL/cl_half.h>
|
||||
|
||||
#if defined(__SSE__) || defined(_MSC_VER)
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
|
@ -50,10 +53,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 +184,8 @@ static ULong sUpperLimits[kNumExplicitTypes] = {
|
|||
0xffffffffLL,
|
||||
0xffffffffLL,
|
||||
0x7fffffffffffffffLL,
|
||||
0xffffffffffffffffLL,
|
||||
0xffffffffffffffffLL,
|
||||
0xffffffffffffffffULL,
|
||||
0xffffffffffffffffULL,
|
||||
0,
|
||||
0
|
||||
}; // Last two values aren't stored here
|
||||
|
|
@ -260,6 +263,11 @@ static Long sLowerLimits[kNumExplicitTypes] = {
|
|||
} \
|
||||
break;
|
||||
|
||||
#define TO_HALF_CASE(inType) \
|
||||
case kHalf: \
|
||||
halfPtr = (cl_half *)outRaw; \
|
||||
*halfPtr = cl_half_from_float((float)(*inType##Ptr), CL_HALF_RTE); \
|
||||
break;
|
||||
#define TO_FLOAT_CASE(inType) \
|
||||
case kFloat: \
|
||||
floatPtr = (float *)outRaw; \
|
||||
|
|
@ -280,6 +288,59 @@ static Long sLowerLimits[kNumExplicitTypes] = {
|
|||
*outType##Ptr = (outType)lrintf_clamped(*floatPtr); \
|
||||
break;
|
||||
|
||||
#define HALF_ROUND_CASE(outEnum, outType, rounding, sat) \
|
||||
case outEnum: { \
|
||||
outType##Ptr = (outType *)outRaw; \
|
||||
/* Get the tens digit */ \
|
||||
float fltEq = (Long)cl_half_to_float(*halfPtr); \
|
||||
Long wholeValue = (Long)fltEq; \
|
||||
float largeRemainder = (fltEq - (float)wholeValue) * 10.f; \
|
||||
/* What do we do based on that? */ \
|
||||
if (rounding == kRoundToEven) \
|
||||
{ \
|
||||
if (wholeValue & 1LL) /*between 1 and 1.99 */ \
|
||||
wholeValue += 1LL; /* round up to even */ \
|
||||
} \
|
||||
else if (rounding == kRoundToZero) \
|
||||
{ \
|
||||
/* Nothing to do, round-to-zero is what C casting does */ \
|
||||
} \
|
||||
else if (rounding == kRoundToPosInf) \
|
||||
{ \
|
||||
/* Only positive numbers are wrong */ \
|
||||
if (largeRemainder != 0.f && wholeValue >= 0) wholeValue++; \
|
||||
} \
|
||||
else if (rounding == kRoundToNegInf) \
|
||||
{ \
|
||||
/* Only negative numbers are off */ \
|
||||
if (largeRemainder != 0.f && wholeValue < 0) wholeValue--; \
|
||||
} \
|
||||
else \
|
||||
{ /* Default is round-to-nearest */ \
|
||||
wholeValue = (Long)lrintf_clamped(fltEq); \
|
||||
} \
|
||||
/* Now apply saturation rules */ \
|
||||
if (sat) \
|
||||
{ \
|
||||
if ((sLowerLimits[outEnum] < 0 \
|
||||
&& wholeValue > (Long)sUpperLimits[outEnum]) \
|
||||
|| (sLowerLimits[outEnum] == 0 \
|
||||
&& (ULong)wholeValue > sUpperLimits[outEnum])) \
|
||||
*outType##Ptr = (outType)sUpperLimits[outEnum]; \
|
||||
else if (wholeValue < sLowerLimits[outEnum]) \
|
||||
*outType##Ptr = (outType)sLowerLimits[outEnum]; \
|
||||
else \
|
||||
*outType##Ptr = (outType)wholeValue; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*outType##Ptr = (outType)( \
|
||||
wholeValue \
|
||||
& (0xffffffffffffffffLL >> (64 - (sizeof(outType) * 8)))); \
|
||||
} \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define FLOAT_ROUND_CASE(outEnum, outType, rounding, sat) \
|
||||
case outEnum: { \
|
||||
outType##Ptr = (outType *)outRaw; \
|
||||
|
|
@ -385,6 +446,7 @@ static Long sLowerLimits[kNumExplicitTypes] = {
|
|||
break;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef signed char schar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
|
|
@ -394,7 +456,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
ExplicitType outType)
|
||||
{
|
||||
bool *boolPtr;
|
||||
char *charPtr;
|
||||
schar *scharPtr;
|
||||
uchar *ucharPtr;
|
||||
short *shortPtr;
|
||||
ushort *ushortPtr;
|
||||
|
|
@ -402,6 +464,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
uint *uintPtr;
|
||||
Long *LongPtr;
|
||||
ULong *ULongPtr;
|
||||
cl_half *halfPtr;
|
||||
float *floatPtr;
|
||||
double *doublePtr;
|
||||
|
||||
|
|
@ -432,6 +495,11 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
get_explicit_type_size(outType));
|
||||
break;
|
||||
|
||||
case kHalf:
|
||||
halfPtr = (cl_half *)outRaw;
|
||||
*halfPtr =
|
||||
(*boolPtr) ? cl_half_from_float(-1.f, CL_HALF_RTE) : 0;
|
||||
break;
|
||||
case kFloat:
|
||||
floatPtr = (float *)outRaw;
|
||||
*floatPtr = (*boolPtr) ? -1.f : 0.f;
|
||||
|
|
@ -448,29 +516,30 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
break;
|
||||
|
||||
case kChar:
|
||||
charPtr = (char *)inRaw;
|
||||
scharPtr = (schar *)inRaw;
|
||||
switch (outType)
|
||||
{
|
||||
BOOL_CASE(char)
|
||||
BOOL_CASE(schar)
|
||||
|
||||
case kChar:
|
||||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(char, kUChar, uchar, saturate)
|
||||
SIMPLE_CAST_CASE(char, kUnsignedChar, uchar)
|
||||
SIMPLE_CAST_CASE(char, kShort, short)
|
||||
SIMPLE_CAST_CASE(char, kUShort, ushort)
|
||||
SIMPLE_CAST_CASE(char, kUnsignedShort, ushort)
|
||||
SIMPLE_CAST_CASE(char, kInt, int)
|
||||
SIMPLE_CAST_CASE(char, kUInt, uint)
|
||||
SIMPLE_CAST_CASE(char, kUnsignedInt, uint)
|
||||
SIMPLE_CAST_CASE(char, kLong, Long)
|
||||
SIMPLE_CAST_CASE(char, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(char, kUnsignedLong, ULong)
|
||||
DOWN_CAST_CASE(schar, kUChar, uchar, saturate)
|
||||
SIMPLE_CAST_CASE(schar, kUnsignedChar, uchar)
|
||||
SIMPLE_CAST_CASE(schar, kShort, short)
|
||||
SIMPLE_CAST_CASE(schar, kUShort, ushort)
|
||||
SIMPLE_CAST_CASE(schar, kUnsignedShort, ushort)
|
||||
SIMPLE_CAST_CASE(schar, kInt, int)
|
||||
SIMPLE_CAST_CASE(schar, kUInt, uint)
|
||||
SIMPLE_CAST_CASE(schar, kUnsignedInt, uint)
|
||||
SIMPLE_CAST_CASE(schar, kLong, Long)
|
||||
SIMPLE_CAST_CASE(schar, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(schar, kUnsignedLong, ULong)
|
||||
|
||||
TO_FLOAT_CASE(char)
|
||||
TO_DOUBLE_CASE(char)
|
||||
TO_HALF_CASE(schar)
|
||||
TO_FLOAT_CASE(schar)
|
||||
TO_DOUBLE_CASE(schar)
|
||||
|
||||
default:
|
||||
log_error("ERROR: Invalid type given to "
|
||||
|
|
@ -490,7 +559,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(uchar, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(uchar, kChar, schar, saturate)
|
||||
SIMPLE_CAST_CASE(uchar, kShort, short)
|
||||
SIMPLE_CAST_CASE(uchar, kUShort, ushort)
|
||||
SIMPLE_CAST_CASE(uchar, kUnsignedShort, ushort)
|
||||
|
|
@ -501,6 +570,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(uchar, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(uchar, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(uchar)
|
||||
TO_FLOAT_CASE(uchar)
|
||||
TO_DOUBLE_CASE(uchar)
|
||||
|
||||
|
|
@ -522,7 +592,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(uchar, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(uchar, kChar, schar, saturate)
|
||||
SIMPLE_CAST_CASE(uchar, kShort, short)
|
||||
SIMPLE_CAST_CASE(uchar, kUShort, ushort)
|
||||
SIMPLE_CAST_CASE(uchar, kUnsignedShort, ushort)
|
||||
|
|
@ -533,6 +603,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(uchar, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(uchar, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(uchar)
|
||||
TO_FLOAT_CASE(uchar)
|
||||
TO_DOUBLE_CASE(uchar)
|
||||
|
||||
|
|
@ -553,7 +624,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(short, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(short, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(short, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(short, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(short, kUShort, ushort, saturate)
|
||||
|
|
@ -565,6 +636,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(short, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(short, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(short)
|
||||
TO_FLOAT_CASE(short)
|
||||
TO_DOUBLE_CASE(short)
|
||||
|
||||
|
|
@ -586,7 +658,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(ushort, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(ushort, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(ushort, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(ushort, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(ushort, kShort, short, saturate)
|
||||
|
|
@ -597,6 +669,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(ushort, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(ushort, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(ushort)
|
||||
TO_FLOAT_CASE(ushort)
|
||||
TO_DOUBLE_CASE(ushort)
|
||||
|
||||
|
|
@ -618,7 +691,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(ushort, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(ushort, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(ushort, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(ushort, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(ushort, kShort, short, saturate)
|
||||
|
|
@ -629,6 +702,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(ushort, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(ushort, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(ushort)
|
||||
TO_FLOAT_CASE(ushort)
|
||||
TO_DOUBLE_CASE(ushort)
|
||||
|
||||
|
|
@ -649,7 +723,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(int, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(int, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(int, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(int, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(int, kShort, short, saturate)
|
||||
|
|
@ -661,6 +735,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(int, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(int, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(int)
|
||||
TO_FLOAT_CASE(int)
|
||||
TO_DOUBLE_CASE(int)
|
||||
|
||||
|
|
@ -682,7 +757,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(uint, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(uint, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(uint, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(uint, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(uint, kShort, short, saturate)
|
||||
|
|
@ -693,6 +768,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(uint, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(uint, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(uint)
|
||||
TO_FLOAT_CASE(uint)
|
||||
TO_DOUBLE_CASE(uint)
|
||||
|
||||
|
|
@ -714,7 +790,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(uint, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(uint, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(uint, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(uint, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(uint, kShort, short, saturate)
|
||||
|
|
@ -725,6 +801,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
SIMPLE_CAST_CASE(uint, kULong, ULong)
|
||||
SIMPLE_CAST_CASE(uint, kUnsignedLong, ULong)
|
||||
|
||||
TO_HALF_CASE(uint)
|
||||
TO_FLOAT_CASE(uint)
|
||||
TO_DOUBLE_CASE(uint)
|
||||
|
||||
|
|
@ -745,7 +822,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
DOWN_CAST_CASE(Long, kChar, char, saturate)
|
||||
DOWN_CAST_CASE(Long, kChar, schar, saturate)
|
||||
DOWN_CAST_CASE(Long, kUChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(Long, kUnsignedChar, uchar, saturate)
|
||||
DOWN_CAST_CASE(Long, kShort, short, saturate)
|
||||
|
|
@ -757,6 +834,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
DOWN_CAST_CASE(Long, kULong, ULong, saturate)
|
||||
DOWN_CAST_CASE(Long, kUnsignedLong, ULong, saturate)
|
||||
|
||||
TO_HALF_CASE(Long)
|
||||
TO_FLOAT_CASE(Long)
|
||||
TO_DOUBLE_CASE(Long)
|
||||
|
||||
|
|
@ -778,7 +856,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
U_DOWN_CAST_CASE(ULong, kChar, char, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kChar, schar, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kUChar, uchar, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kUnsignedChar, uchar, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kShort, short, saturate)
|
||||
|
|
@ -789,6 +867,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
U_DOWN_CAST_CASE(ULong, kUnsignedInt, uint, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kLong, Long, saturate)
|
||||
|
||||
TO_HALF_CASE(ULong)
|
||||
TO_FLOAT_CASE(ULong)
|
||||
TO_DOUBLE_CASE(ULong)
|
||||
|
||||
|
|
@ -810,7 +889,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
U_DOWN_CAST_CASE(ULong, kChar, char, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kChar, schar, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kUChar, uchar, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kUnsignedChar, uchar, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kShort, short, saturate)
|
||||
|
|
@ -821,6 +900,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
U_DOWN_CAST_CASE(ULong, kUnsignedInt, uint, saturate)
|
||||
U_DOWN_CAST_CASE(ULong, kLong, Long, saturate)
|
||||
|
||||
TO_HALF_CASE(ULong)
|
||||
TO_FLOAT_CASE(ULong)
|
||||
TO_DOUBLE_CASE(ULong)
|
||||
|
||||
|
|
@ -831,13 +911,52 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
}
|
||||
break;
|
||||
|
||||
case kHalf:
|
||||
halfPtr = (cl_half *)inRaw;
|
||||
switch (outType)
|
||||
{
|
||||
BOOL_CASE(half)
|
||||
|
||||
HALF_ROUND_CASE(kChar, schar, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUChar, uchar, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUnsignedChar, uchar, roundType, saturate)
|
||||
HALF_ROUND_CASE(kShort, short, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUShort, ushort, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUnsignedShort, ushort, roundType, saturate)
|
||||
HALF_ROUND_CASE(kInt, int, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUInt, uint, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUnsignedInt, uint, roundType, saturate)
|
||||
HALF_ROUND_CASE(kLong, Long, roundType, saturate)
|
||||
HALF_ROUND_CASE(kULong, ULong, roundType, saturate)
|
||||
HALF_ROUND_CASE(kUnsignedLong, ULong, roundType, saturate)
|
||||
|
||||
case kHalf:
|
||||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
||||
case kFloat:
|
||||
floatPtr = (float *)outRaw;
|
||||
*floatPtr = cl_half_to_float(*halfPtr);
|
||||
break;
|
||||
case kDouble:
|
||||
doublePtr = (double *)outRaw;
|
||||
*doublePtr = cl_half_to_float(*halfPtr);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("ERROR: Invalid type given to "
|
||||
"convert_explicit_value!!\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kFloat:
|
||||
floatPtr = (float *)inRaw;
|
||||
switch (outType)
|
||||
{
|
||||
BOOL_CASE(float)
|
||||
|
||||
FLOAT_ROUND_CASE(kChar, char, roundType, saturate)
|
||||
FLOAT_ROUND_CASE(kChar, schar, roundType, saturate)
|
||||
FLOAT_ROUND_CASE(kUChar, uchar, roundType, saturate)
|
||||
FLOAT_ROUND_CASE(kUnsignedChar, uchar, roundType, saturate)
|
||||
FLOAT_ROUND_CASE(kShort, short, roundType, saturate)
|
||||
|
|
@ -850,6 +969,8 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
FLOAT_ROUND_CASE(kULong, ULong, roundType, saturate)
|
||||
FLOAT_ROUND_CASE(kUnsignedLong, ULong, roundType, saturate)
|
||||
|
||||
TO_HALF_CASE(float)
|
||||
|
||||
case kFloat:
|
||||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
|
@ -869,7 +990,7 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
{
|
||||
BOOL_CASE(double)
|
||||
|
||||
DOUBLE_ROUND_CASE(kChar, char, roundType, saturate)
|
||||
DOUBLE_ROUND_CASE(kChar, schar, roundType, saturate)
|
||||
DOUBLE_ROUND_CASE(kUChar, uchar, roundType, saturate)
|
||||
DOUBLE_ROUND_CASE(kUnsignedChar, uchar, roundType, saturate)
|
||||
DOUBLE_ROUND_CASE(kShort, short, roundType, saturate)
|
||||
|
|
@ -882,6 +1003,8 @@ void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
|||
DOUBLE_ROUND_CASE(kULong, ULong, roundType, saturate)
|
||||
DOUBLE_ROUND_CASE(kUnsignedLong, ULong, roundType, saturate)
|
||||
|
||||
TO_HALF_CASE(double)
|
||||
|
||||
TO_FLOAT_CASE(double);
|
||||
|
||||
case kDouble:
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
/******************************************************************
|
||||
Copyright (c) 2016 The Khronos Group Inc.
|
||||
All Rights Reserved. This code is protected by copyright laws and
|
||||
contains material proprietary to the Khronos Group, Inc.
|
||||
This is UNPUBLISHED PROPRIETARY SOURCE CODE that may not be disclosed
|
||||
in whole or in part to third parties, and may not be reproduced, republished,
|
||||
distributed, transmitted, displayed, broadcast or otherwise exploited in any
|
||||
manner without the express prior written permission of Khronos Group.
|
||||
//
|
||||
// Copyright (c) 2016-2023 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.
|
||||
//
|
||||
|
||||
The receipt or possession of this code does not convey any rights to
|
||||
reproduce, disclose, or distribute its contents, or to
|
||||
manufacture, use, or sell anything that it may describe, in whole
|
||||
or in part other than under the terms of the Khronos Adopters
|
||||
Agreement or Khronos Conformance Test Source License Agreement as
|
||||
executed between Khronos and the recipient.
|
||||
******************************************************************/
|
||||
|
||||
#ifndef _CRC32_H_
|
||||
#define _CRC32_H_
|
||||
#ifndef CRC32_H_
|
||||
#define CRC32_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
|
|
|||
|
|
@ -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,13 +363,13 @@ 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);
|
||||
}
|
||||
|
||||
float Ulp_Error_Half(cl_half test, float reference)
|
||||
float Ulp_Error_Half(cl_half test, double reference)
|
||||
{
|
||||
return Ulp_Error_Half_Float(cl_half_to_float(test), reference);
|
||||
}
|
||||
|
|
@ -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,28 @@ 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_fail_and_cleanup(errRet, cleanup, msg, ...) \
|
||||
{ \
|
||||
log_error(msg, ##__VA_ARGS__); \
|
||||
errRet = TEST_FAIL; \
|
||||
goto cleanup; \
|
||||
}
|
||||
#define test_error_and_cleanup(errCode, cleanup, msg, ...) \
|
||||
{ \
|
||||
auto errCodeResult = errCode; \
|
||||
if (errCodeResult != CL_SUCCESS) \
|
||||
{ \
|
||||
print_error(errCodeResult, msg); \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
#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 +108,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,9 +168,24 @@ 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);
|
||||
extern float Ulp_Error_Half(cl_half test, double reference);
|
||||
extern float Ulp_Error(float test, double reference);
|
||||
extern float Ulp_Error_Double(double test, long double reference);
|
||||
|
||||
|
|
@ -186,8 +197,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,16 +32,22 @@
|
|||
// 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>
|
||||
#elif defined(__PPC__)
|
||||
#include <fpu_control.h>
|
||||
extern __thread fpu_control_t fpu_control;
|
||||
#elif defined(__mips__)
|
||||
#include "mips/m32c1.h"
|
||||
#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,17 +63,19 @@ 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)));
|
||||
#elif defined(__mips__)
|
||||
fpa_bissr(FPA_CSR_FS);
|
||||
#else
|
||||
#error ForceFTZ needs an implentation
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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,17 +91,19 @@ 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)));
|
||||
#elif defined(__mips__)
|
||||
fpa_bicsr(FPA_CSR_FS);
|
||||
#else
|
||||
#error DisableFTZ needs an implentation
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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__)
|
||||
|
|
@ -103,6 +115,8 @@ static inline void RestoreFPState(FPU_mode_type *mode)
|
|||
// Add 64 bit support
|
||||
#elif defined(__aarch64__)
|
||||
__asm__ volatile("msr fpcr, %0" ::"r"(*mode));
|
||||
#elif defined(__mips__)
|
||||
// Mips runs by default with DAZ=1 FTZ=1
|
||||
#else
|
||||
#error RestoreFPState needs an implementation
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <malloc.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <iterator>
|
||||
#if !defined(_WIN32)
|
||||
#include <cmath>
|
||||
|
|
@ -96,23 +97,9 @@ uint32_t get_channel_data_type_size(cl_channel_type channelType)
|
|||
case CL_UNSIGNED_INT32: return sizeof(cl_int);
|
||||
|
||||
case CL_UNORM_SHORT_565:
|
||||
case CL_UNORM_SHORT_555:
|
||||
#ifdef OBSOLETE_FORAMT
|
||||
case CL_UNORM_SHORT_565_REV:
|
||||
case CL_UNORM_SHORT_555_REV:
|
||||
#endif
|
||||
return 2;
|
||||
case CL_UNORM_SHORT_555: return 2;
|
||||
|
||||
#ifdef OBSOLETE_FORAMT
|
||||
case CL_UNORM_INT_8888:
|
||||
case CL_UNORM_INT_8888_REV: return 4;
|
||||
#endif
|
||||
|
||||
case CL_UNORM_INT_101010:
|
||||
#ifdef OBSOLETE_FORAMT
|
||||
case CL_UNORM_INT_101010_REV:
|
||||
#endif
|
||||
return 4;
|
||||
case CL_UNORM_INT_101010: return 4;
|
||||
|
||||
case CL_FLOAT: return sizeof(cl_float);
|
||||
|
||||
|
|
@ -293,23 +280,9 @@ uint32_t get_pixel_size(const cl_image_format *format)
|
|||
return get_format_channel_count(format) * sizeof(cl_int);
|
||||
|
||||
case CL_UNORM_SHORT_565:
|
||||
case CL_UNORM_SHORT_555:
|
||||
#ifdef OBSOLETE_FORAMT
|
||||
case CL_UNORM_SHORT_565_REV:
|
||||
case CL_UNORM_SHORT_555_REV:
|
||||
#endif
|
||||
return 2;
|
||||
case CL_UNORM_SHORT_555: return 2;
|
||||
|
||||
#ifdef OBSOLETE_FORAMT
|
||||
case CL_UNORM_INT_8888:
|
||||
case CL_UNORM_INT_8888_REV: return 4;
|
||||
#endif
|
||||
|
||||
case CL_UNORM_INT_101010:
|
||||
#ifdef OBSOLETE_FORAMT
|
||||
case CL_UNORM_INT_101010_REV:
|
||||
#endif
|
||||
return 4;
|
||||
case CL_UNORM_INT_101010: return 4;
|
||||
|
||||
case CL_FLOAT:
|
||||
return get_format_channel_count(format) * sizeof(cl_float);
|
||||
|
|
@ -421,7 +394,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 +427,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 +446,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 +568,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 +663,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 +730,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 +771,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 +788,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 +813,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 +832,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 +847,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 +860,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 +897,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 +1139,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 +1177,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 +1694,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 +1784,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 +1808,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 +1967,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 +1987,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 +2001,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 +2066,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 +2124,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 +2158,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 +2591,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 +2607,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 +2732,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 +2896,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 +3235,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;
|
||||
}
|
||||
|
|
@ -3502,7 +3509,6 @@ void copy_image_data(image_descriptor *srcImageInfo,
|
|||
{
|
||||
size_t src_width_lod = 1 /*srcImageInfo->width*/;
|
||||
size_t src_height_lod = 1 /*srcImageInfo->height*/;
|
||||
size_t src_depth_lod = 1 /*srcImageInfo->depth*/;
|
||||
|
||||
switch (srcImageInfo->type)
|
||||
{
|
||||
|
|
@ -3537,10 +3543,6 @@ void copy_image_data(image_descriptor *srcImageInfo,
|
|||
src_height_lod = (srcImageInfo->height >> src_lod)
|
||||
? (srcImageInfo->height >> src_lod)
|
||||
: 1;
|
||||
if (srcImageInfo->type == CL_MEM_OBJECT_IMAGE3D)
|
||||
src_depth_lod = (srcImageInfo->depth >> src_lod)
|
||||
? (srcImageInfo->depth >> src_lod)
|
||||
: 1;
|
||||
break;
|
||||
}
|
||||
src_mip_level_offset = compute_mip_level_offset(srcImageInfo, src_lod);
|
||||
|
|
@ -3553,7 +3555,6 @@ void copy_image_data(image_descriptor *srcImageInfo,
|
|||
{
|
||||
size_t dst_width_lod = 1 /*dstImageInfo->width*/;
|
||||
size_t dst_height_lod = 1 /*dstImageInfo->height*/;
|
||||
size_t dst_depth_lod = 1 /*dstImageInfo->depth*/;
|
||||
switch (dstImageInfo->type)
|
||||
{
|
||||
case CL_MEM_OBJECT_IMAGE1D:
|
||||
|
|
@ -3587,10 +3588,6 @@ void copy_image_data(image_descriptor *srcImageInfo,
|
|||
dst_height_lod = (dstImageInfo->height >> dst_lod)
|
||||
? (dstImageInfo->height >> dst_lod)
|
||||
: 1;
|
||||
if (dstImageInfo->type == CL_MEM_OBJECT_IMAGE3D)
|
||||
dst_depth_lod = (dstImageInfo->depth >> dst_lod)
|
||||
? (dstImageInfo->depth >> dst_lod)
|
||||
: 1;
|
||||
break;
|
||||
}
|
||||
dst_mip_level_offset = compute_mip_level_offset(dstImageInfo, dst_lod);
|
||||
|
|
@ -3988,7 +3985,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,
|
||||
|
|
@ -344,48 +347,6 @@ void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef OBSOLETE_FORMAT
|
||||
case CL_UNORM_SHORT_565_REV: {
|
||||
unsigned short *dPtr = (unsigned short *)ptr;
|
||||
tempData[2] = (T)(dPtr[0] >> 11);
|
||||
tempData[1] = (T)((dPtr[0] >> 5) & 63);
|
||||
tempData[0] = (T)(dPtr[0] & 31);
|
||||
break;
|
||||
}
|
||||
|
||||
case CL_UNORM_SHORT_555_REV: {
|
||||
unsigned short *dPtr = (unsigned short *)ptr;
|
||||
tempData[2] = (T)((dPtr[0] >> 10) & 31);
|
||||
tempData[1] = (T)((dPtr[0] >> 5) & 31);
|
||||
tempData[0] = (T)(dPtr[0] & 31);
|
||||
break;
|
||||
}
|
||||
|
||||
case CL_UNORM_INT_8888: {
|
||||
unsigned int *dPtr = (unsigned int *)ptr;
|
||||
tempData[3] = (T)(dPtr[0] >> 24);
|
||||
tempData[2] = (T)((dPtr[0] >> 16) & 0xff);
|
||||
tempData[1] = (T)((dPtr[0] >> 8) & 0xff);
|
||||
tempData[0] = (T)(dPtr[0] & 0xff);
|
||||
break;
|
||||
}
|
||||
case CL_UNORM_INT_8888_REV: {
|
||||
unsigned int *dPtr = (unsigned int *)ptr;
|
||||
tempData[0] = (T)(dPtr[0] >> 24);
|
||||
tempData[1] = (T)((dPtr[0] >> 16) & 0xff);
|
||||
tempData[2] = (T)((dPtr[0] >> 8) & 0xff);
|
||||
tempData[3] = (T)(dPtr[0] & 0xff);
|
||||
break;
|
||||
}
|
||||
|
||||
case CL_UNORM_INT_101010_REV: {
|
||||
unsigned int *dPtr = (unsigned int *)ptr;
|
||||
tempData[2] = (T)((dPtr[0] >> 20) & 0x3ff);
|
||||
tempData[1] = (T)((dPtr[0] >> 10) & 0x3ff);
|
||||
tempData[0] = (T)(dPtr[0] & 0x3ff);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case CL_UNORM_SHORT_555: {
|
||||
cl_ushort *dPtr = (cl_ushort *)ptr;
|
||||
tempData[0] = (T)((dPtr[0] >> 10) & 31);
|
||||
|
|
@ -479,6 +440,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 +457,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;
|
||||
|
|
@ -1626,22 +1511,33 @@ size_t get_min_alignment(cl_context context)
|
|||
return align_size;
|
||||
}
|
||||
|
||||
cl_device_fp_config get_default_rounding_mode(cl_device_id device)
|
||||
cl_device_fp_config get_default_rounding_mode(cl_device_id device,
|
||||
const cl_uint ¶m)
|
||||
{
|
||||
if (param == CL_DEVICE_DOUBLE_FP_CONFIG)
|
||||
test_error_ret(
|
||||
-1,
|
||||
"FAILURE: CL_DEVICE_DOUBLE_FP_CONFIG not supported by this routine",
|
||||
0);
|
||||
|
||||
char profileStr[128] = "";
|
||||
cl_device_fp_config single = 0;
|
||||
int error = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG,
|
||||
sizeof(single), &single, NULL);
|
||||
int error = clGetDeviceInfo(device, param, sizeof(single), &single, NULL);
|
||||
if (error)
|
||||
test_error_ret(error, "Unable to get device CL_DEVICE_SINGLE_FP_CONFIG",
|
||||
0);
|
||||
{
|
||||
std::string message = std::string("Unable to get device ")
|
||||
+ std::string(param == CL_DEVICE_HALF_FP_CONFIG
|
||||
? "CL_DEVICE_HALF_FP_CONFIG"
|
||||
: "CL_DEVICE_SINGLE_FP_CONFIG");
|
||||
test_error_ret(error, message.c_str(), 0);
|
||||
}
|
||||
|
||||
if (single & CL_FP_ROUND_TO_NEAREST) return CL_FP_ROUND_TO_NEAREST;
|
||||
|
||||
if (0 == (single & CL_FP_ROUND_TO_ZERO))
|
||||
test_error_ret(-1,
|
||||
"FAILURE: device must support either "
|
||||
"CL_DEVICE_SINGLE_FP_CONFIG or CL_FP_ROUND_TO_NEAREST",
|
||||
"CL_FP_ROUND_TO_ZERO or CL_FP_ROUND_TO_NEAREST",
|
||||
0);
|
||||
|
||||
// Make sure we are an embedded device before allowing a pass
|
||||
|
|
@ -1776,8 +1672,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 +1720,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 +1758,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 +1791,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. */
|
||||
|
|
@ -162,7 +159,9 @@ size_t get_min_alignment(cl_context context);
|
|||
|
||||
/* Helper to obtain the default rounding mode for single precision computation.
|
||||
* (Double is always CL_FP_ROUND_TO_NEAREST.) Returns 0 on error. */
|
||||
cl_device_fp_config get_default_rounding_mode(cl_device_id device);
|
||||
cl_device_fp_config
|
||||
get_default_rounding_mode(cl_device_id device,
|
||||
const cl_uint ¶m = CL_DEVICE_SINGLE_FP_CONFIG);
|
||||
|
||||
#define PASSIVE_REQUIRE_IMAGE_SUPPORT(device) \
|
||||
if (checkForImageSupport(device)) \
|
||||
|
|
@ -181,7 +180,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 +210,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
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#include "harness/alloc.h"
|
||||
|
||||
#ifdef __SSE2__
|
||||
#include <mutex>
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ cl_uint genrand_int32(MTdata d)
|
|||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
static const cl_uint mag01[2] = { 0x0UL, MATRIX_A };
|
||||
#ifdef __SSE2__
|
||||
static volatile int init = 0;
|
||||
static std::once_flag init_flag;
|
||||
static union {
|
||||
__m128i v;
|
||||
cl_uint s[4];
|
||||
|
|
@ -123,8 +124,7 @@ cl_uint genrand_int32(MTdata d)
|
|||
int kk;
|
||||
|
||||
#ifdef __SSE2__
|
||||
if (0 == init)
|
||||
{
|
||||
auto init_fn = []() {
|
||||
upper_mask.s[0] = upper_mask.s[1] = upper_mask.s[2] =
|
||||
upper_mask.s[3] = UPPER_MASK;
|
||||
lower_mask.s[0] = lower_mask.s[1] = lower_mask.s[2] =
|
||||
|
|
@ -134,8 +134,8 @@ cl_uint genrand_int32(MTdata d)
|
|||
MATRIX_A;
|
||||
c0.s[0] = c0.s[1] = c0.s[2] = c0.s[3] = (cl_uint)0x9d2c5680UL;
|
||||
c1.s[0] = c1.s[1] = c1.s[2] = c1.s[3] = (cl_uint)0xefc60000UL;
|
||||
init = 1;
|
||||
}
|
||||
};
|
||||
std::call_once(init_flag, init_fn);
|
||||
#endif
|
||||
|
||||
kk = 0;
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -30,8 +30,17 @@
|
|||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/api-level.h>
|
||||
#include "harness/mt19937.h"
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#if defined(__APPLE__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define CHECK_PTR(ptr) \
|
||||
if ((ptr) == NULL) \
|
||||
{ \
|
||||
|
|
@ -283,7 +292,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 +342,6 @@ std::string exe_dir()
|
|||
|
||||
|
||||
#include <windows.h>
|
||||
#if defined(max)
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
|
@ -404,7 +410,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)
|
||||
{
|
||||
|
|
@ -558,4 +565,27 @@ char* get_exe_dir()
|
|||
} // get_exe_dir
|
||||
|
||||
|
||||
char* get_temp_filename()
|
||||
{
|
||||
char gFileName[256] = "";
|
||||
// Create a unique temporary file to allow parallel executed tests.
|
||||
#if (defined(__linux__) || defined(__APPLE__)) && (!defined(__ANDROID__))
|
||||
sprintf(gFileName, "/tmp/tmpfile.XXXXXX");
|
||||
int fd = mkstemp(gFileName);
|
||||
if (fd == -1) return strdup(gFileName);
|
||||
close(fd);
|
||||
#elif defined(_WIN32)
|
||||
UINT ret = GetTempFileName(".", "tmp", 0, gFileName);
|
||||
if (ret == 0) return gFileName;
|
||||
#else
|
||||
MTdata d = init_genrand((cl_uint)time(NULL));
|
||||
sprintf(gFileName, "tmpfile.%u", genrand_int32(d));
|
||||
#endif
|
||||
|
||||
char* fn = strdup(gFileName);
|
||||
CHECK_PTR(fn);
|
||||
return fn;
|
||||
}
|
||||
|
||||
|
||||
// end of file //
|
||||
|
|
|
|||
|
|
@ -41,5 +41,7 @@ char* get_err_msg(int err); // Returns system error message. Subject to free.
|
|||
char* get_dir_sep(); // Returns dir separator. Subject to free.
|
||||
char* get_exe_path(); // Returns path of current executable. Subject to free.
|
||||
char* get_exe_dir(); // Returns dir of current executable. Subject to free.
|
||||
char* get_temp_filename(); // returns temporary file name
|
||||
|
||||
|
||||
#endif // __os_helpers_h__
|
||||
|
|
|
|||
|
|
@ -28,11 +28,15 @@
|
|||
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;
|
||||
unsigned gNumWorkerThreads;
|
||||
|
||||
void helpInfo()
|
||||
{
|
||||
|
|
@ -45,6 +49,8 @@ void helpInfo()
|
|||
online Use online compilation (default)
|
||||
binary Use binary offline compilation
|
||||
spir-v Use SPIR-V offline compilation
|
||||
--num-worker-threads <num>
|
||||
Select parallel execution with the specified number of worker threads.
|
||||
|
||||
For offline compilation (binary and spir-v modes) only:
|
||||
--compilation-cache-mode <cache-mode>
|
||||
|
|
@ -62,7 +68,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)
|
||||
|
|
@ -127,6 +140,23 @@ int parseCustomParam(int argc, const char *argv[], const char *ignore)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "--num-worker-threads"))
|
||||
{
|
||||
delArg++;
|
||||
if ((i + 1) < argc)
|
||||
{
|
||||
delArg++;
|
||||
const char *numthstr = argv[i + 1];
|
||||
|
||||
gNumWorkerThreads = atoi(numthstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(
|
||||
"A parameter to --num-worker-threads must be provided!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "--compilation-cache-mode"))
|
||||
{
|
||||
delArg++;
|
||||
|
|
@ -198,6 +228,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);
|
||||
|
|
@ -197,19 +197,21 @@ RoundingMode get_round(void)
|
|||
#include <xmmintrin.h>
|
||||
#elif defined(__PPC__)
|
||||
#include <fpu_control.h>
|
||||
#elif defined(__mips__)
|
||||
#include "mips/m32c1.h"
|
||||
#endif
|
||||
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;
|
||||
|
|
@ -219,6 +221,9 @@ void *FlushToZero(void)
|
|||
flags |= _FPU_MASK_NI;
|
||||
_FPU_SETCW(flags);
|
||||
return NULL;
|
||||
#elif defined(__mips__)
|
||||
fpa_bissr(FPA_CSR_FS);
|
||||
return NULL;
|
||||
#else
|
||||
#error Unknown arch
|
||||
#endif
|
||||
|
|
@ -239,7 +244,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__)
|
||||
|
|
@ -247,6 +252,8 @@ void UnFlushToZero(void *p)
|
|||
_FPU_GETCW(flags);
|
||||
flags &= ~_FPU_MASK_NI;
|
||||
_FPU_SETCW(flags);
|
||||
#elif defined(__mips__)
|
||||
fpa_bicsr(FPA_CSR_FS);
|
||||
#else
|
||||
#error Unknown arch
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
@ -44,10 +42,11 @@ typedef enum
|
|||
kshort = 3,
|
||||
kuint = 4,
|
||||
kint = 5,
|
||||
kfloat = 6,
|
||||
kdouble = 7,
|
||||
kulong = 8,
|
||||
klong = 9,
|
||||
khalf = 6,
|
||||
kfloat = 7,
|
||||
kdouble = 8,
|
||||
kulong = 9,
|
||||
klong = 10,
|
||||
|
||||
// This goes last
|
||||
kTypeCount
|
||||
|
|
|
|||
42
test_common/harness/stringHelpers.h
Normal file
42
test_common/harness/stringHelpers.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Copyright (c) 2023 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 STRING_HELPERS_H
|
||||
#define STRING_HELPERS_H
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
inline std::string concat_kernel(const char *sstr[], int num)
|
||||
{
|
||||
std::string res;
|
||||
for (int i = 0; i < num; i++) res += std::string(sstr[i]);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline std::string str_sprintf(const std::string &str, Args... args)
|
||||
{
|
||||
int str_size = std::snprintf(nullptr, 0, str.c_str(), args...) + 1;
|
||||
if (str_size <= 0) throw std::runtime_error("Formatting error.");
|
||||
size_t s = static_cast<size_t>(str_size);
|
||||
std::unique_ptr<char[]> buffer(new char[s]);
|
||||
std::snprintf(buffer.get(), s, str.c_str(), args...);
|
||||
return std::string(buffer.get(), buffer.get() + s - 1);
|
||||
}
|
||||
|
||||
#endif // STRING_HELPERS_H
|
||||
|
|
@ -20,9 +20,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "threadTesting.h"
|
||||
#include "errorHelpers.h"
|
||||
#include "kernelHelpers.h"
|
||||
#include "fpcontrol.h"
|
||||
|
|
@ -60,6 +62,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 +118,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)
|
||||
|
|
@ -126,6 +185,9 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
else if (strcmp(env_mode, "accelerator") == 0
|
||||
|| strcmp(env_mode, "CL_DEVICE_TYPE_ACCELERATOR") == 0)
|
||||
device_type = CL_DEVICE_TYPE_ACCELERATOR;
|
||||
else if (strcmp(env_mode, "custom") == 0
|
||||
|| strcmp(env_mode, "CL_DEVICE_TYPE_CUSTOM") == 0)
|
||||
device_type = CL_DEVICE_TYPE_CUSTOM;
|
||||
else if (strcmp(env_mode, "default") == 0
|
||||
|| strcmp(env_mode, "CL_DEVICE_TYPE_DEFAULT") == 0)
|
||||
device_type = CL_DEVICE_TYPE_DEFAULT;
|
||||
|
|
@ -255,6 +317,12 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
device_type = CL_DEVICE_TYPE_ACCELERATOR;
|
||||
argc--;
|
||||
}
|
||||
else if (strcmp(argv[argc - 1], "custom") == 0
|
||||
|| strcmp(argv[argc - 1], "CL_DEVICE_TYPE_CUSTOM") == 0)
|
||||
{
|
||||
device_type = CL_DEVICE_TYPE_CUSTOM;
|
||||
argc--;
|
||||
}
|
||||
else if (strcmp(argv[argc - 1], "CL_DEVICE_TYPE_DEFAULT") == 0)
|
||||
{
|
||||
device_type = CL_DEVICE_TYPE_DEFAULT;
|
||||
|
|
@ -292,6 +360,9 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
case CL_DEVICE_TYPE_ACCELERATOR:
|
||||
log_info("Requesting Accelerator device ");
|
||||
break;
|
||||
case CL_DEVICE_TYPE_CUSTOM:
|
||||
log_info("Requesting Custom device ");
|
||||
break;
|
||||
case CL_DEVICE_TYPE_DEFAULT:
|
||||
log_info("Requesting Default device ");
|
||||
break;
|
||||
|
|
@ -470,6 +541,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 +550,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 +570,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -514,10 +598,12 @@ int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
FPU_mode_type oldMode;
|
||||
DisableFTZ(&oldMode);
|
||||
#endif
|
||||
extern unsigned gNumWorkerThreads;
|
||||
test_harness_config config = { forceNoContextCreation, num_elements,
|
||||
queueProps, gNumWorkerThreads };
|
||||
|
||||
int error = parseAndCallCommandLineTests(argc, argv, device, testNum,
|
||||
testList, forceNoContextCreation,
|
||||
queueProps, num_elements);
|
||||
testList, config);
|
||||
|
||||
#if defined(__APPLE__) && defined(__arm__)
|
||||
// Restore the old FP mode before leaving.
|
||||
|
|
@ -574,49 +660,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)
|
||||
|
|
@ -651,14 +694,11 @@ static void print_results(int failed, int count, const char *name)
|
|||
int parseAndCallCommandLineTests(int argc, const char *argv[],
|
||||
cl_device_id device, int testNum,
|
||||
test_definition testList[],
|
||||
int forceNoContextCreation,
|
||||
cl_command_queue_properties queueProps,
|
||||
int num_elements)
|
||||
const test_harness_config &config)
|
||||
{
|
||||
int ret = EXIT_SUCCESS;
|
||||
|
||||
unsigned char *selectedTestList = (unsigned char *)calloc(testNum, 1);
|
||||
test_status *resultTestList = NULL;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
|
|
@ -697,24 +737,18 @@ 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,
|
||||
queueProps);
|
||||
callTestFunctions(testList, selectedTestList, resultTestList.data(),
|
||||
testNum, device, config);
|
||||
|
||||
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,26 +764,101 @@ int parseAndCallCommandLineTests(int argc, const char *argv[],
|
|||
}
|
||||
|
||||
free(selectedTestList);
|
||||
free(resultTestList);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct test_harness_state
|
||||
{
|
||||
test_definition *tests;
|
||||
test_status *results;
|
||||
cl_device_id device;
|
||||
test_harness_config config;
|
||||
};
|
||||
|
||||
static std::deque<int> gTestQueue;
|
||||
static std::mutex gTestStateMutex;
|
||||
|
||||
void test_function_runner(test_harness_state *state)
|
||||
{
|
||||
int testID;
|
||||
test_definition test;
|
||||
while (true)
|
||||
{
|
||||
// Attempt to get a test
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(gTestStateMutex);
|
||||
|
||||
// The queue is empty, we're done
|
||||
if (gTestQueue.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the test at the front of the queue
|
||||
testID = gTestQueue.front();
|
||||
gTestQueue.pop_front();
|
||||
test = state->tests[testID];
|
||||
}
|
||||
|
||||
// Execute test
|
||||
auto status =
|
||||
callSingleTestFunction(test, state->device, state->config);
|
||||
|
||||
// Store result
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(gTestStateMutex);
|
||||
state->results[testID] = status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void callTestFunctions(test_definition testList[],
|
||||
unsigned char selectedTestList[],
|
||||
test_status resultTestList[], int testNum,
|
||||
cl_device_id deviceToUse, int forceNoContextCreation,
|
||||
int numElementsToUse,
|
||||
cl_command_queue_properties queueProps)
|
||||
cl_device_id deviceToUse,
|
||||
const test_harness_config &config)
|
||||
{
|
||||
for (int i = 0; i < testNum; ++i)
|
||||
// Execute tests serially
|
||||
if (config.numWorkerThreads == 0)
|
||||
{
|
||||
if (selectedTestList[i])
|
||||
for (int i = 0; i < testNum; ++i)
|
||||
{
|
||||
resultTestList[i] = callSingleTestFunction(
|
||||
testList[i], deviceToUse, forceNoContextCreation,
|
||||
numElementsToUse, queueProps);
|
||||
if (selectedTestList[i])
|
||||
{
|
||||
resultTestList[i] =
|
||||
callSingleTestFunction(testList[i], deviceToUse, config);
|
||||
}
|
||||
}
|
||||
// Execute tests in parallel with the specified number of worker threads
|
||||
}
|
||||
else
|
||||
{
|
||||
// Queue all tests that need to run
|
||||
for (int i = 0; i < testNum; ++i)
|
||||
{
|
||||
if (selectedTestList[i])
|
||||
{
|
||||
gTestQueue.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn thread pool
|
||||
std::vector<std::thread *> threads;
|
||||
test_harness_state state = { testList, resultTestList, deviceToUse,
|
||||
config };
|
||||
for (unsigned i = 0; i < config.numWorkerThreads; i++)
|
||||
{
|
||||
log_info("Spawning worker thread %u\n", i);
|
||||
threads.push_back(new std::thread(test_function_runner, &state));
|
||||
}
|
||||
|
||||
// Wait for all threads to complete
|
||||
for (auto th : threads)
|
||||
{
|
||||
th->join();
|
||||
}
|
||||
assert(gTestQueue.size() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -762,9 +871,7 @@ void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info,
|
|||
// Actual function execution
|
||||
test_status callSingleTestFunction(test_definition test,
|
||||
cl_device_id deviceToUse,
|
||||
int forceNoContextCreation,
|
||||
int numElementsToUse,
|
||||
const cl_queue_properties queueProps)
|
||||
const test_harness_config &config)
|
||||
{
|
||||
test_status status;
|
||||
cl_int error;
|
||||
|
|
@ -783,28 +890,39 @@ 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)
|
||||
if (!config.forceNoContextCreation)
|
||||
{
|
||||
context = clCreateContext(NULL, 1, &deviceToUse, notify_callback, NULL,
|
||||
&error);
|
||||
if (!context)
|
||||
{
|
||||
print_error(error, "Unable to create testing context");
|
||||
gFailCount++;
|
||||
gTestsFailed++;
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
if (device_version < Version(2, 0))
|
||||
{
|
||||
queue =
|
||||
clCreateCommandQueue(context, deviceToUse, queueProps, &error);
|
||||
queue = clCreateCommandQueue(context, deviceToUse,
|
||||
config.queueProps, &error);
|
||||
}
|
||||
else
|
||||
{
|
||||
const cl_command_queue_properties cmd_queueProps =
|
||||
(queueProps) ? CL_QUEUE_PROPERTIES : 0;
|
||||
cl_command_queue_properties queueCreateProps[] = { cmd_queueProps,
|
||||
queueProps, 0 };
|
||||
(config.queueProps) ? CL_QUEUE_PROPERTIES : 0;
|
||||
cl_command_queue_properties queueCreateProps[] = {
|
||||
cmd_queueProps, config.queueProps, 0
|
||||
};
|
||||
queue = clCreateCommandQueueWithProperties(
|
||||
context, deviceToUse, &queueCreateProps[0], &error);
|
||||
}
|
||||
|
|
@ -812,14 +930,14 @@ test_status callSingleTestFunction(test_definition test,
|
|||
if (queue == NULL)
|
||||
{
|
||||
print_error(error, "Unable to create testing command queue");
|
||||
clReleaseContext(context);
|
||||
gFailCount++;
|
||||
gTestsFailed++;
|
||||
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
|
||||
|
|
@ -829,7 +947,8 @@ test_status callSingleTestFunction(test_definition test,
|
|||
}
|
||||
else
|
||||
{
|
||||
int ret = test.func(deviceToUse, context, queue, numElementsToUse);
|
||||
int ret =
|
||||
test.func(deviceToUse, context, queue, config.numElementsToUse);
|
||||
if (ret == TEST_SKIPPED_ITSELF)
|
||||
{
|
||||
/* Tests can also let us know they're not supported by the
|
||||
|
|
@ -856,12 +975,14 @@ test_status callSingleTestFunction(test_definition test,
|
|||
}
|
||||
|
||||
/* Release the context */
|
||||
if (!forceNoContextCreation)
|
||||
if (!config.forceNoContextCreation)
|
||||
{
|
||||
int error = clFinish(queue);
|
||||
if (error)
|
||||
{
|
||||
log_error("clFinish failed: %d", error);
|
||||
log_error("clFinish failed: %s\n", IGetErrorString(error));
|
||||
gFailCount++;
|
||||
gTestsFailed++;
|
||||
status = TEST_FAIL;
|
||||
}
|
||||
clReleaseCommandQueue(queue);
|
||||
|
|
@ -1087,18 +1208,21 @@ Version get_device_spirv_il_version(cl_device_id device)
|
|||
ASSERT_SUCCESS(err, "clGetDeviceInfo");
|
||||
}
|
||||
|
||||
if (strstr(str.data(), "SPIR-V_1.0") != NULL)
|
||||
return Version(1, 0);
|
||||
else if (strstr(str.data(), "SPIR-V_1.1") != NULL)
|
||||
return Version(1, 1);
|
||||
else if (strstr(str.data(), "SPIR-V_1.2") != NULL)
|
||||
return Version(1, 2);
|
||||
else if (strstr(str.data(), "SPIR-V_1.3") != NULL)
|
||||
return Version(1, 3);
|
||||
// Because this query returns a space-separated list of IL version strings
|
||||
// we should check for SPIR-V versions in reverse order, to return the
|
||||
// highest version supported.
|
||||
if (strstr(str.data(), "SPIR-V_1.5") != NULL)
|
||||
return Version(1, 5);
|
||||
else if (strstr(str.data(), "SPIR-V_1.4") != NULL)
|
||||
return Version(1, 4);
|
||||
else if (strstr(str.data(), "SPIR-V_1.5") != NULL)
|
||||
return Version(1, 5);
|
||||
else if (strstr(str.data(), "SPIR-V_1.3") != NULL)
|
||||
return Version(1, 3);
|
||||
else if (strstr(str.data(), "SPIR-V_1.2") != NULL)
|
||||
return Version(1, 2);
|
||||
else if (strstr(str.data(), "SPIR-V_1.1") != NULL)
|
||||
return Version(1, 1);
|
||||
else if (strstr(str.data(), "SPIR-V_1.0") != NULL)
|
||||
return Version(1, 0);
|
||||
|
||||
throw std::runtime_error(std::string("Unknown SPIR-V version: ")
|
||||
+ str.data());
|
||||
|
|
@ -1172,7 +1296,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__)
|
||||
|
|
@ -1189,6 +1313,8 @@ void PrintArch(void)
|
|||
vlog("ARCH:\taarch64\n");
|
||||
#elif defined(_WIN32)
|
||||
vlog("ARCH:\tWindows\n");
|
||||
#elif defined(__mips__)
|
||||
vlog("ARCH:\tmips\n");
|
||||
#else
|
||||
#error unknown arch
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -83,6 +85,14 @@ typedef enum test_status
|
|||
TEST_SKIPPED_ITSELF = -100,
|
||||
} test_status;
|
||||
|
||||
struct test_harness_config
|
||||
{
|
||||
int forceNoContextCreation;
|
||||
int numElementsToUse;
|
||||
cl_command_queue_properties queueProps;
|
||||
unsigned numWorkerThreads;
|
||||
};
|
||||
|
||||
extern int gFailCount;
|
||||
extern int gTestCount;
|
||||
extern cl_uint gReSeed;
|
||||
|
|
@ -115,9 +125,7 @@ extern int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
|
|||
extern int parseAndCallCommandLineTests(int argc, const char *argv[],
|
||||
cl_device_id device, int testNum,
|
||||
test_definition testList[],
|
||||
int forceNoContextCreation,
|
||||
cl_command_queue_properties queueProps,
|
||||
int num_elements);
|
||||
const test_harness_config &config);
|
||||
|
||||
// Call this function if you need to do all the setup work yourself, and just
|
||||
// need the function list called/ managed.
|
||||
|
|
@ -129,21 +137,19 @@ extern int parseAndCallCommandLineTests(int argc, const char *argv[],
|
|||
// resultTestList is an array of statuses which contain the result of each
|
||||
// selected test testNum is the number of tests in testList, selectedTestList
|
||||
// and resultTestList contextProps are used to create a testing context for
|
||||
// each test deviceToUse and numElementsToUse are all just passed to each
|
||||
// each test deviceToUse and config are all just passed to each
|
||||
// test function
|
||||
extern void callTestFunctions(test_definition testList[],
|
||||
unsigned char selectedTestList[],
|
||||
test_status resultTestList[], int testNum,
|
||||
cl_device_id deviceToUse,
|
||||
int forceNoContextCreation, int numElementsToUse,
|
||||
cl_command_queue_properties queueProps);
|
||||
const test_harness_config &config);
|
||||
|
||||
// This function is called by callTestFunctions, once per function, to do setup,
|
||||
// call, logging and cleanup
|
||||
extern test_status
|
||||
callSingleTestFunction(test_definition test, cl_device_id deviceToUse,
|
||||
int forceNoContextCreation, int numElementsToUse,
|
||||
cl_command_queue_properties queueProps);
|
||||
extern test_status callSingleTestFunction(test_definition test,
|
||||
cl_device_id deviceToUse,
|
||||
const test_harness_config &config);
|
||||
|
||||
///// Miscellaneous steps
|
||||
|
||||
|
|
|
|||
|
|
@ -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,177 @@
|
|||
#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)
|
||||
operator T() const { return object; }
|
||||
|
||||
// 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 clSVMWrapper {
|
||||
void *Ptr = nullptr;
|
||||
cl_context Ctx = nullptr;
|
||||
|
||||
public:
|
||||
clSVMWrapper() = default;
|
||||
|
||||
clSVMWrapper(cl_context C, size_t Size,
|
||||
cl_svm_mem_flags F = CL_MEM_READ_WRITE)
|
||||
: Ctx(C)
|
||||
{
|
||||
mMem = rhs;
|
||||
Ptr = clSVMAlloc(C, F, Size, 0);
|
||||
}
|
||||
|
||||
clSVMWrapper &operator=(void *other) = delete;
|
||||
clSVMWrapper(clSVMWrapper const &other) = delete;
|
||||
clSVMWrapper &operator=(clSVMWrapper const &other) = delete;
|
||||
clSVMWrapper(clSVMWrapper &&other)
|
||||
{
|
||||
Ptr = other.Ptr;
|
||||
Ctx = other.Ctx;
|
||||
other.Ptr = nullptr;
|
||||
other.Ctx = nullptr;
|
||||
}
|
||||
clSVMWrapper &operator=(clSVMWrapper &&other)
|
||||
{
|
||||
Ptr = other.Ptr;
|
||||
Ctx = other.Ctx;
|
||||
other.Ptr = nullptr;
|
||||
other.Ctx = nullptr;
|
||||
return *this;
|
||||
}
|
||||
operator cl_mem() const { return mMem; }
|
||||
|
||||
cl_mem *operator&() { return &mMem; }
|
||||
~clSVMWrapper()
|
||||
{
|
||||
if (Ptr) clSVMFree(Ctx, Ptr);
|
||||
}
|
||||
|
||||
bool operator==(const cl_mem &rhs) { return mMem == rhs; }
|
||||
|
||||
protected:
|
||||
cl_mem mMem;
|
||||
void *operator()() const { return Ptr; }
|
||||
};
|
||||
|
||||
|
||||
class clProtectedImage {
|
||||
public:
|
||||
clProtectedImage()
|
||||
|
|
@ -183,92 +237,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,12 @@ 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( common/vulkan_wrapper )
|
||||
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
|
||||
|
|
@ -18,4 +17,6 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_migrate.cpp
|
||||
)
|
||||
|
||||
set_gnulike_module_compile_flags("-Wno-sometimes-uninitialized -Wno-sign-compare")
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "common.h"
|
||||
#include "harness/mt19937.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define GLOBAL_SIZE 65536
|
||||
|
||||
static const char *sources[] = {
|
||||
|
|
@ -75,12 +77,9 @@ wait_and_release(const char* s, cl_event* evs, int n)
|
|||
|
||||
int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
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];
|
||||
std::vector<cl_uint> amem(GLOBAL_SIZE);
|
||||
std::vector<cl_uint> bmem(GLOBAL_SIZE);
|
||||
std::vector<cl_uint> cmem(GLOBAL_SIZE);
|
||||
cl_event evs[20];
|
||||
|
||||
const size_t global_size = GLOBAL_SIZE;
|
||||
|
|
@ -148,9 +147,9 @@ int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue
|
|||
test_error(error, "clSetKernelArgSVMPointer failed");
|
||||
|
||||
// Initialize host copy of data (and result)
|
||||
fill_buffer(amem, global_size, seed);
|
||||
fill_buffer(bmem, global_size, seed);
|
||||
fill_buffer(cmem, global_size, seed);
|
||||
fill_buffer(amem.data(), global_size, seed);
|
||||
fill_buffer(bmem.data(), global_size, seed);
|
||||
fill_buffer(cmem.data(), global_size, seed);
|
||||
|
||||
// Now we're ready to start
|
||||
{
|
||||
|
|
@ -221,9 +220,9 @@ int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue
|
|||
if (error)
|
||||
return -1;
|
||||
|
||||
memcpy((void *)asvm, (void *)amem, global_size*sizeof(cl_uint));
|
||||
memcpy((void *)bsvm, (void *)bmem, global_size*sizeof(cl_uint));
|
||||
memcpy((void *)csvm, (void *)cmem, global_size*sizeof(cl_uint));
|
||||
memcpy((void *)asvm, (void *)amem.data(), global_size * sizeof(cl_uint));
|
||||
memcpy((void *)bsvm, (void *)bmem.data(), global_size * sizeof(cl_uint));
|
||||
memcpy((void *)csvm, (void *)cmem.data(), global_size * sizeof(cl_uint));
|
||||
|
||||
{
|
||||
error = clEnqueueSVMUnmap(queues[1], (void *)asvm, 0, NULL, &evs[0]);
|
||||
|
|
@ -307,9 +306,9 @@ int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue
|
|||
return -1;
|
||||
|
||||
// Check kernel results
|
||||
bool ok = check("memory a", (cl_uint *)asvm, amem, global_size);
|
||||
ok &= check("memory b", (cl_uint *)bsvm, bmem, global_size);
|
||||
ok &= check("memory c", (cl_uint *)csvm, cmem, global_size);
|
||||
bool ok = check("memory a", (cl_uint *)asvm, amem.data(), global_size);
|
||||
ok &= check("memory b", (cl_uint *)bsvm, bmem.data(), global_size);
|
||||
ok &= check("memory c", (cl_uint *)csvm, cmem.data(), global_size);
|
||||
|
||||
{
|
||||
void *ptrs[] = { asvm, bsvm, csvm };
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ cl_int create_linked_lists_on_host(cl_command_queue cmdq, cl_mem nodes, Node *pN
|
|||
cl_int verify_linked_lists_on_host(int ci, cl_command_queue cmdq, cl_mem nodes, Node *pNodes2, cl_int ListLength, size_t numLists, cl_bool useNewAPI )
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
cl_int correct_count;
|
||||
|
||||
Node *pNodes;
|
||||
if (useNewAPI == CL_FALSE)
|
||||
|
|
@ -72,8 +71,6 @@ cl_int verify_linked_lists_on_host(int ci, cl_command_queue cmdq, cl_mem nodes,
|
|||
test_error2(error, pNodes, "clEnqueueSVMMap failed");
|
||||
}
|
||||
|
||||
correct_count = 0;
|
||||
|
||||
error = verify_linked_lists(pNodes, numLists, ListLength);
|
||||
if(error) return -1;
|
||||
|
||||
|
|
@ -98,7 +95,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 +205,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.
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@ set(${MODULE_NAME}_SOURCES
|
|||
allocation_utils.cpp
|
||||
)
|
||||
|
||||
set_gnulike_module_compile_flags("-Wno-sign-compare")
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "allocation_execute.h"
|
||||
#include "allocation_functions.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
const char *buffer_kernel_pattern = {
|
||||
"__kernel void sample_test(%s __global uint *result, __global %s *array_sizes, uint per_item)\n"
|
||||
|
|
@ -79,20 +81,30 @@ int check_image(cl_command_queue queue, cl_mem mem) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (type == CL_MEM_OBJECT_BUFFER) {
|
||||
log_error("Expected image object, not buffer.\n");
|
||||
return -1;
|
||||
} else if (type == CL_MEM_OBJECT_IMAGE2D) {
|
||||
error = clGetImageInfo(mem, CL_IMAGE_WIDTH, sizeof(width), &width, NULL);
|
||||
if (error) {
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_IMAGE_WIDTH.");
|
||||
switch (type)
|
||||
{
|
||||
case CL_MEM_OBJECT_BUFFER:
|
||||
log_error("Expected image object, not buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
error = clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL);
|
||||
if (error) {
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_IMAGE_HEIGHT.");
|
||||
return -1;
|
||||
}
|
||||
case CL_MEM_OBJECT_IMAGE2D:
|
||||
error = clGetImageInfo(mem, CL_IMAGE_WIDTH, sizeof(width), &width,
|
||||
NULL);
|
||||
if (error)
|
||||
{
|
||||
print_error(error,
|
||||
"clGetMemObjectInfo failed for CL_IMAGE_WIDTH.");
|
||||
return -1;
|
||||
}
|
||||
error = clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height),
|
||||
&height, NULL);
|
||||
if (error)
|
||||
{
|
||||
print_error(error,
|
||||
"clGetMemObjectInfo failed for CL_IMAGE_HEIGHT.");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default: log_error("unexpected object type"); return -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -130,7 +142,7 @@ int check_image(cl_command_queue queue, cl_mem mem) {
|
|||
}
|
||||
|
||||
|
||||
#define NUM_OF_WORK_ITEMS 8192*2
|
||||
#define NUM_OF_WORK_ITEMS (8192 * 32)
|
||||
|
||||
int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id device_id, int test, cl_mem mems[], int number_of_mems_used, int verify_checksum) {
|
||||
|
||||
|
|
@ -145,7 +157,8 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
size_t global_dims[3];
|
||||
cl_uint per_item;
|
||||
cl_uint per_item_uint;
|
||||
cl_uint returned_results[NUM_OF_WORK_ITEMS], final_result;
|
||||
cl_uint final_result;
|
||||
std::vector<cl_uint> returned_results(NUM_OF_WORK_ITEMS);
|
||||
clEventWrapper event;
|
||||
cl_int event_status;
|
||||
|
||||
|
|
@ -226,7 +239,9 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
}
|
||||
|
||||
// Set the result
|
||||
result_mem = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(cl_uint)*NUM_OF_WORK_ITEMS, &returned_results, &error);
|
||||
result_mem = clCreateBuffer(
|
||||
context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
|
||||
sizeof(cl_uint) * NUM_OF_WORK_ITEMS, returned_results.data(), &error);
|
||||
test_error(error, "clCreateBuffer failed");
|
||||
error = clSetKernelArg(kernel, i, sizeof(result_mem), &result_mem);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
|
@ -332,7 +347,9 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
|
||||
// Verify the checksum.
|
||||
// Read back the result
|
||||
error = clEnqueueReadBuffer(*queue, result_mem, CL_TRUE, 0, sizeof(cl_uint)*NUM_OF_WORK_ITEMS, &returned_results, 0, NULL, NULL);
|
||||
error = clEnqueueReadBuffer(*queue, result_mem, CL_TRUE, 0,
|
||||
sizeof(cl_uint) * NUM_OF_WORK_ITEMS,
|
||||
returned_results.data(), 0, NULL, NULL);
|
||||
test_error_abort(error, "clEnqueueReadBuffer failed");
|
||||
final_result = 0;
|
||||
if (test == BUFFER || test == IMAGE_READ || test == BUFFER_NON_BLOCKING || test == IMAGE_READ_NON_BLOCKING) {
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ test_status init_cl( cl_device_id device ) {
|
|||
// queue, kernel code on GPU.
|
||||
g_global_mem_size *= 0.60;
|
||||
}
|
||||
/* Cap the allocation size as the global size was deduced */
|
||||
if (g_max_individual_allocation_size > g_global_mem_size)
|
||||
{
|
||||
g_max_individual_allocation_size = g_global_mem_size;
|
||||
}
|
||||
|
||||
if( gReSeed )
|
||||
{
|
||||
|
|
@ -112,6 +117,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 +130,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 +139,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;
|
||||
|
||||
|
|
@ -324,6 +331,7 @@ int main(int argc, const char *argv[])
|
|||
else if ( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
|
||||
{
|
||||
printUsage( argv[0] );
|
||||
free(argList);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ int test_consistency_read_write_images(cl_device_id deviceID,
|
|||
CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D,
|
||||
CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY,
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(image_types); i++)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(image_types); i++)
|
||||
{
|
||||
cl_uint numImageFormats = 0;
|
||||
error = clGetSupportedImageFormats(
|
||||
|
|
@ -801,7 +801,7 @@ int test_consistency_depth_images(cl_device_id deviceID, cl_context context,
|
|||
CL_MEM_READ_WRITE,
|
||||
CL_MEM_KERNEL_READ_AND_WRITE,
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(mem_flags); i++)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(mem_flags); i++)
|
||||
{
|
||||
cl_uint numImageFormats = 0;
|
||||
error = clGetSupportedImageFormats(context, mem_flags[i],
|
||||
|
|
@ -1114,7 +1114,7 @@ int test_consistency_3d_image_writes(cl_device_id deviceID, cl_context context,
|
|||
CL_MEM_READ_WRITE,
|
||||
CL_MEM_KERNEL_READ_AND_WRITE,
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(mem_flags); i++)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(mem_flags); i++)
|
||||
{
|
||||
cl_uint numImageFormats = 0;
|
||||
error = clGetSupportedImageFormats(context, mem_flags[i],
|
||||
|
|
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -406,8 +406,8 @@ int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context contex
|
|||
|
||||
if (i == sizeof( actual_names ) / sizeof( actual_names[0] ) )
|
||||
{
|
||||
free(kernel_names);
|
||||
log_error( "Kernel names \"%s\" did not match:\n", kernel_names );
|
||||
free(kernel_names);
|
||||
for( i = 0; i < sizeof( actual_names ) / sizeof( actual_names[0] ); i++ )
|
||||
log_error( "\t\t\"%s\"\n", actual_names[0] );
|
||||
return -1;
|
||||
|
|
|
|||
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;
|
||||
}
|
||||
|
|
@ -217,6 +217,9 @@ int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_
|
|||
// Create a buffer object to test against.
|
||||
bufferObject = clCreateBuffer( context, bufferFlags[ i ], addressAlign * 4, NULL, &error );
|
||||
test_error( error, "Unable to create buffer to test with" );
|
||||
void *ptr;
|
||||
TEST_MEM_OBJECT_PARAM(bufferObject, CL_MEM_HOST_PTR, ptr, NULL,
|
||||
"host pointer", "%p", void *)
|
||||
}
|
||||
|
||||
// Perform buffer object queries.
|
||||
|
|
@ -348,14 +351,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 +366,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;
|
||||
|
|
@ -482,7 +476,8 @@ int test_get_image_info( cl_device_id deviceID, cl_context context, cl_mem_objec
|
|||
CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
|
||||
CL_MEM_HOST_NO_ACCESS | CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
|
||||
};
|
||||
MTdata d;
|
||||
MTdataHolder d_holder(gRandomSeed);
|
||||
MTdata d = static_cast<MTdata>(d_holder);
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID )
|
||||
|
||||
|
|
@ -501,8 +496,6 @@ int test_get_image_info( cl_device_id deviceID, cl_context context, cl_mem_objec
|
|||
imageInfo.buffer = NULL;
|
||||
#endif
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
|
||||
for ( unsigned int i = 0; i < sizeof(imageFlags) / sizeof(cl_mem_flags); ++i )
|
||||
{
|
||||
imageInfo.image_row_pitch = 0;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ int test_min_image_formats(cl_device_id device, cl_context context,
|
|||
int supports_3D_image_writes =
|
||||
is_extension_available(device, "cl_khr_3d_image_writes");
|
||||
|
||||
for (int t = 0; t < ARRAY_SIZE(image_types); t++)
|
||||
for (size_t t = 0; t < ARRAY_SIZE(image_types); t++)
|
||||
{
|
||||
const cl_mem_object_type type = image_types[t];
|
||||
log_info(" testing %s...\n", convert_image_type_to_string(type));
|
||||
for (int f = 0; f < ARRAY_SIZE(mem_flags); f++)
|
||||
for (size_t f = 0; f < ARRAY_SIZE(mem_flags); f++)
|
||||
{
|
||||
const cl_mem_flags flags = mem_flags[f];
|
||||
const char* testTypeString = flags == CL_MEM_READ_ONLY
|
||||
|
|
|
|||
|
|
@ -64,16 +64,21 @@ static int test_setargs_and_execution(cl_command_queue queue, cl_kernel kernel,
|
|||
cl_int status;
|
||||
const char *typestr;
|
||||
|
||||
if (type == NON_NULL_PATH) {
|
||||
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf);
|
||||
typestr = "non-NULL";
|
||||
} else if (type == ADDROF_NULL_PATH) {
|
||||
test_buf = NULL;
|
||||
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf);
|
||||
typestr = "&NULL";
|
||||
} else if (type == NULL_PATH) {
|
||||
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), NULL);
|
||||
typestr = "NULL";
|
||||
switch (type)
|
||||
{
|
||||
case NON_NULL_PATH:
|
||||
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf);
|
||||
typestr = "non-NULL";
|
||||
break;
|
||||
case ADDROF_NULL_PATH:
|
||||
test_buf = NULL;
|
||||
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &test_buf);
|
||||
typestr = "&NULL";
|
||||
break;
|
||||
case NULL_PATH:
|
||||
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), NULL);
|
||||
typestr = "NULL";
|
||||
break;
|
||||
}
|
||||
|
||||
log_info("Testing setKernelArgs with %s buffer.\n", typestr);
|
||||
|
|
@ -149,7 +154,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)
|
||||
{
|
||||
|
|
@ -161,8 +162,8 @@ static cl_filter_mode filter_mode_values[] = { CL_FILTER_NEAREST,
|
|||
CL_FILTER_LINEAR };
|
||||
|
||||
int test_sampler_params(cl_device_id deviceID, cl_context context,
|
||||
bool is_compatibility, int norm_coord_num,
|
||||
int addr_mod_num, int filt_mod_num)
|
||||
bool is_compatibility, size_t norm_coord_num,
|
||||
size_t addr_mod_num, size_t filt_mod_num)
|
||||
{
|
||||
cl_uint refCount;
|
||||
size_t size;
|
||||
|
|
@ -271,10 +272,10 @@ int test_sampler_params(cl_device_id deviceID, cl_context context,
|
|||
int get_sampler_info_params(cl_device_id deviceID, cl_context context,
|
||||
bool is_compatibility)
|
||||
{
|
||||
for (int norm_coord_num = 0;
|
||||
for (size_t norm_coord_num = 0;
|
||||
norm_coord_num < ARRAY_SIZE(normalized_coord_values); norm_coord_num++)
|
||||
{
|
||||
for (int addr_mod_num = 0;
|
||||
for (size_t addr_mod_num = 0;
|
||||
addr_mod_num < ARRAY_SIZE(addressing_mode_values); addr_mod_num++)
|
||||
{
|
||||
if ((normalized_coord_values[norm_coord_num] == CL_FALSE)
|
||||
|
|
@ -284,7 +285,7 @@ int get_sampler_info_params(cl_device_id deviceID, cl_context context,
|
|||
{
|
||||
continue;
|
||||
}
|
||||
for (int filt_mod_num = 0;
|
||||
for (size_t filt_mod_num = 0;
|
||||
filt_mod_num < ARRAY_SIZE(filter_mode_values); filt_mod_num++)
|
||||
{
|
||||
int err = test_sampler_params(deviceID, context,
|
||||
|
|
@ -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 ); \
|
||||
|
|
@ -649,6 +644,13 @@ int test_get_device_info(cl_device_id deviceID, cl_context context, cl_command_q
|
|||
}
|
||||
log_info( "\tReported device profile: %s \n", profile );
|
||||
|
||||
if (strcmp(profile, "FULL_PROFILE") == 0 && compilerAvail != CL_TRUE)
|
||||
{
|
||||
log_error("ERROR: Returned profile of device is FULL , but "
|
||||
"CL_DEVICE_COMPILER_AVAILABLE is not CL_TRUE as required by "
|
||||
"OpenCL 1.2!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -804,8 +806,8 @@ int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, c
|
|||
test_error(error, "clFinish failed");
|
||||
|
||||
if (max_dimensions == 2) {
|
||||
return 0;
|
||||
free(source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
local[1]--; local[2]++;
|
||||
|
|
@ -824,5 +826,3 @@ int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, c
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ int enqueue_kernel(cl_context context, const cl_queue_properties_khr *queue_prop
|
|||
clCommandQueueWrapper queue = clCreateCommandQueueWithPropertiesKHR(context, deviceID, queue_prop_def, &error);
|
||||
test_error(error, "clCreateCommandQueueWithPropertiesKHR failed");
|
||||
|
||||
for (int i = 0; i < num_elements; ++i)
|
||||
for (size_t i = 0; i < num_elements; ++i)
|
||||
{
|
||||
buf[i] = i;
|
||||
}
|
||||
|
|
@ -85,9 +85,9 @@ int enqueue_kernel(cl_context context, const cl_queue_properties_khr *queue_prop
|
|||
error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, num_elements, buf.data(), 0, NULL, NULL);
|
||||
test_error( error, "clEnqueueReadBuffer failed." );
|
||||
|
||||
for (int i = 0; i < num_elements; ++i)
|
||||
for (size_t i = 0; i < num_elements; ++i)
|
||||
{
|
||||
if (buf[i] != i)
|
||||
if (static_cast<size_t>(buf[i]) != i)
|
||||
{
|
||||
log_error("ERROR: Incorrect vector copy result.");
|
||||
return -1;
|
||||
|
|
@ -107,8 +107,9 @@ int test_queue_properties(cl_device_id deviceID, cl_context context, cl_command_
|
|||
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
cl_queue_properties_khr device_props = 0;
|
||||
cl_queue_properties_khr queue_prop_def[] = { CL_QUEUE_PROPERTIES, 0, 0 };
|
||||
cl_command_queue_properties device_props = 0;
|
||||
cl_command_queue_properties queue_prop_def[] = { CL_QUEUE_PROPERTIES, 0,
|
||||
0 };
|
||||
|
||||
// Query extension
|
||||
if (!is_extension_available(deviceID, "cl_khr_create_command_queue"))
|
||||
|
|
@ -162,4 +163,4 @@ int test_queue_properties(cl_device_id deviceID, cl_context context, cl_command_
|
|||
}
|
||||
|
||||
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");
|
||||
|
|
@ -208,8 +188,9 @@ int test_sub_group_dispatch(cl_device_id deviceID, cl_context context, cl_comman
|
|||
}
|
||||
}
|
||||
|
||||
// test when input subgroup count exceeds max wg size
|
||||
size_t large_sg_size = kernel_subgroup_count + 1;
|
||||
// test when input subgroup count exceeds max wg size:
|
||||
// there can be at most the local size of (1 WI) subgroups
|
||||
size_t large_sg_size = max_local + 1;
|
||||
error = clGetKernelSubGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, sizeof(size_t), &large_sg_size, sizeof(ret_ndrange1d), &ret_ndrange1d, &realSize);
|
||||
test_error(error, "clGetKernelSubGroupInfo failed for CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT");
|
||||
if (ret_ndrange1d != 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
|
||||
|
|
@ -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
|
||||
|
|
@ -13,51 +13,61 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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,310 +82,428 @@ 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",
|
||||
(int)global_threads[0], (int)local_threads[0]);
|
||||
|
||||
// Allocate our storage
|
||||
cl_mem bin_counters =
|
||||
clMemWrapper bin_counters =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * number_of_bins, NULL, NULL);
|
||||
cl_mem bins = clCreateBuffer(
|
||||
clMemWrapper bins = clCreateBuffer(
|
||||
context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * number_of_bins * max_counts_per_bin, NULL, NULL);
|
||||
cl_mem bin_assignments =
|
||||
clMemWrapper bin_assignments =
|
||||
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");
|
||||
std::unique_ptr<cl_int[]> l_bin_counts(new 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.get(), 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");
|
||||
std::unique_ptr<cl_int[]> values(
|
||||
new 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.get(), 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");
|
||||
std::unique_ptr<cl_int[]> l_bin_assignments(new 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.get(), 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);
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
std::unique_ptr<cl_int[]> final_bin_assignments(
|
||||
new 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.get(), 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to read back bins: %d\n", err);
|
||||
fail = 1; succeed=-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");
|
||||
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;
|
||||
|
||||
std::unique_ptr<cl_int[]> final_bin_counts(new 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.get(), 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error("add_index_bin_test FAILED to read back bin_counters: %d\n",
|
||||
err);
|
||||
return -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++;
|
||||
}
|
||||
}
|
||||
free(l_bin_counts);
|
||||
free(l_bin_assignments);
|
||||
free(final_bin_assignments);
|
||||
free(final_bin_counts);
|
||||
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,17 +2,16 @@ set(MODULE_NAME BASIC)
|
|||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
main.cpp
|
||||
test_fpmath_float.cpp test_fpmath_float2.cpp test_fpmath_float4.cpp
|
||||
test_fpmath.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
|
||||
test_int2float.cpp test_float2int.cpp
|
||||
test_int2fp.cpp
|
||||
test_createkernelsinprogram.cpp
|
||||
test_hostptr.cpp
|
||||
test_explicit_s2v.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
|
||||
|
|
@ -54,14 +52,12 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_kernel_call_kernel_function.cpp
|
||||
test_local_kernel_scope.cpp
|
||||
test_progvar.cpp
|
||||
test_wg_barrier.cpp
|
||||
test_global_linear_id.cpp
|
||||
test_local_linear_id.cpp
|
||||
test_enqueued_local_size.cpp
|
||||
test_simple_image_pitch.cpp
|
||||
test_get_linear_ids.cpp
|
||||
test_rw_image_access_qualifier.cpp
|
||||
test_wg_barrier.cpp
|
||||
test_enqueued_local_size.cpp
|
||||
test_global_linear_id.cpp
|
||||
test_local_linear_id.cpp
|
||||
|
|
@ -72,4 +68,6 @@ if(APPLE)
|
|||
list(APPEND ${MODULE_NAME}_SOURCES test_queue_priority.cpp)
|
||||
endif(APPLE)
|
||||
|
||||
set_gnulike_module_compile_flags("-Wno-sign-compare")
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2023 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.
|
||||
|
|
@ -22,14 +22,15 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <CL/cl_half.h>
|
||||
|
||||
#include "harness/testHarness.h"
|
||||
#include "procs.h"
|
||||
|
||||
test_definition test_list[] = {
|
||||
ADD_TEST(hostptr),
|
||||
ADD_TEST(fpmath_float),
|
||||
ADD_TEST(fpmath_float2),
|
||||
ADD_TEST(fpmath_float4),
|
||||
ADD_TEST(fpmath),
|
||||
ADD_TEST(intmath_int),
|
||||
ADD_TEST(intmath_int2),
|
||||
ADD_TEST(intmath_int4),
|
||||
|
|
@ -58,8 +59,8 @@ test_definition test_list[] = {
|
|||
ADD_TEST(image_r8),
|
||||
ADD_TEST(barrier),
|
||||
ADD_TEST_VERSION(wg_barrier, Version(2, 0)),
|
||||
ADD_TEST(int2float),
|
||||
ADD_TEST(float2int),
|
||||
ADD_TEST(int2fp),
|
||||
ADD_TEST(fp2int),
|
||||
ADD_TEST(imagereadwrite),
|
||||
ADD_TEST(imagereadwrite3d),
|
||||
ADD_TEST(readimage3d),
|
||||
|
|
@ -91,16 +92,8 @@ test_definition test_list[] = {
|
|||
ADD_TEST(image_param),
|
||||
ADD_TEST(image_multipass_integer_coord),
|
||||
ADD_TEST(image_multipass_float_coord),
|
||||
ADD_TEST(explicit_s2v_char),
|
||||
ADD_TEST(explicit_s2v_uchar),
|
||||
ADD_TEST(explicit_s2v_short),
|
||||
ADD_TEST(explicit_s2v_ushort),
|
||||
ADD_TEST(explicit_s2v_int),
|
||||
ADD_TEST(explicit_s2v_uint),
|
||||
ADD_TEST(explicit_s2v_long),
|
||||
ADD_TEST(explicit_s2v_ulong),
|
||||
ADD_TEST(explicit_s2v_float),
|
||||
ADD_TEST(explicit_s2v_double),
|
||||
|
||||
ADD_TEST(explicit_s2v),
|
||||
|
||||
ADD_TEST(enqueue_map_buffer),
|
||||
ADD_TEST(enqueue_map_image),
|
||||
|
|
@ -155,7 +148,7 @@ test_definition test_list[] = {
|
|||
ADD_TEST(simple_read_image_pitch),
|
||||
ADD_TEST(simple_write_image_pitch),
|
||||
|
||||
#if defined( __APPLE__ )
|
||||
#if defined(__APPLE__)
|
||||
ADD_TEST(queue_priority),
|
||||
#endif
|
||||
|
||||
|
|
@ -164,9 +157,35 @@ test_definition test_list[] = {
|
|||
};
|
||||
|
||||
const int test_num = ARRAY_SIZE( test_list );
|
||||
cl_half_rounding_mode halfRoundingMode = CL_HALF_RTE;
|
||||
|
||||
test_status InitCL(cl_device_id device)
|
||||
{
|
||||
if (is_extension_available(device, "cl_khr_fp16"))
|
||||
{
|
||||
const cl_device_fp_config fpConfigHalf =
|
||||
get_default_rounding_mode(device, CL_DEVICE_HALF_FP_CONFIG);
|
||||
if ((fpConfigHalf & CL_FP_ROUND_TO_NEAREST) != 0)
|
||||
{
|
||||
halfRoundingMode = CL_HALF_RTE;
|
||||
}
|
||||
else if ((fpConfigHalf & CL_FP_ROUND_TO_ZERO) != 0)
|
||||
{
|
||||
halfRoundingMode = CL_HALF_RTZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("Error while acquiring half rounding mode");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
return runTestHarness(argc, argv, test_num, test_list, false, 0);
|
||||
return runTestHarnessWithCheck(argc, argv, test_num, test_list, false, 0,
|
||||
InitCL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Copyright (c) 2023 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
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include "harness/kernelHelpers.h"
|
||||
#include "harness/testHarness.h"
|
||||
#include "harness/errorHelpers.h"
|
||||
|
|
@ -20,12 +21,9 @@
|
|||
#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);
|
||||
extern int test_fpmath_float4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_fpmath(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_intmath_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_intmath_int2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_intmath_int4(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
|
@ -54,8 +52,10 @@ extern int test_image_r8(cl_device_id deviceID, cl_context context, cl_comm
|
|||
extern int test_simplebarrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_barrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_wg_barrier(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_int2float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_float2int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_int2fp(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_fp2int(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_imagearraycopy(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_imagearraycopy3d(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_imagereadwrite(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
|
@ -91,16 +91,8 @@ extern int test_vstore_global(cl_device_id deviceID, cl_context context, cl
|
|||
extern int test_vstore_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_vstore_private(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_explicit_s2v_char(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_uchar(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_short(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_ushort(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_uint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_ulong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_explicit_s2v(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_enqueue_map_image(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;
|
||||
}
|
||||
|
|
@ -14,62 +14,39 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "procs.h"
|
||||
#include "harness/conversions.h"
|
||||
#include "harness/stringHelpers.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
|
||||
static const char *astype_kernel_pattern =
|
||||
"%s\n"
|
||||
#include "procs.h"
|
||||
|
||||
// clang-format off
|
||||
|
||||
static char extension[128] = { 0 };
|
||||
static char strLoad[128] = { 0 };
|
||||
static char strStore[128] = { 0 };
|
||||
static const char *regLoad = "as_%s%s(src[tid]);\n";
|
||||
static const char *v3Load = "as_%s%s(vload3(tid,(__global %s*)src));\n";
|
||||
static const char *regStore = "dst[tid] = tmp;\n";
|
||||
static const char *v3Store = "vstore3(tmp, tid, (__global %s*)dst);\n";
|
||||
|
||||
static const char* astype_kernel_pattern[] = {
|
||||
extension,
|
||||
"__kernel void test_fn( __global %s%s *src, __global %s%s *dst )\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id( 0 );\n"
|
||||
" %s%s tmp = as_%s%s( src[ tid ] );\n"
|
||||
" dst[ tid ] = tmp;\n"
|
||||
"}\n";
|
||||
|
||||
static const char *astype_kernel_pattern_V3srcV3dst =
|
||||
"%s\n"
|
||||
"__kernel void test_fn( __global %s *src, __global %s *dst )\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id( 0 );\n"
|
||||
" %s%s tmp = as_%s%s( vload3(tid,src) );\n"
|
||||
" vstore3(tmp,tid,dst);\n"
|
||||
"}\n";
|
||||
// in the printf, remove the third and fifth argument, each of which
|
||||
// should be a "3", when copying from the printf for astype_kernel_pattern
|
||||
|
||||
static const char *astype_kernel_pattern_V3dst =
|
||||
"%s\n"
|
||||
"__kernel void test_fn( __global %s%s *src, __global %s *dst )\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id( 0 );\n"
|
||||
" %s3 tmp = as_%s3( src[ tid ] );\n"
|
||||
" vstore3(tmp,tid,dst);\n"
|
||||
"}\n";
|
||||
// in the printf, remove the fifth argument, which
|
||||
// should be a "3", when copying from the printf for astype_kernel_pattern
|
||||
|
||||
|
||||
static const char *astype_kernel_pattern_V3src =
|
||||
"%s\n"
|
||||
"__kernel void test_fn( __global %s *src, __global %s%s *dst )\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id( 0 );\n"
|
||||
" %s%s tmp = as_%s%s( vload3(tid,src) );\n"
|
||||
" dst[ tid ] = tmp;\n"
|
||||
"}\n";
|
||||
// in the printf, remove the third argument, which
|
||||
// should be a "3", when copying from the printf for astype_kernel_pattern
|
||||
" int tid = get_global_id( 0 );\n",
|
||||
" %s%s tmp = ", strLoad,
|
||||
" ", strStore,
|
||||
"}\n"};
|
||||
|
||||
// clang-format on
|
||||
|
||||
int test_astype_set( cl_device_id device, cl_context context, cl_command_queue queue, ExplicitType inVecType, ExplicitType outVecType,
|
||||
unsigned int vecSize, unsigned int outVecSize,
|
||||
|
|
@ -81,68 +58,60 @@ int test_astype_set( cl_device_id device, cl_context context, cl_command_queue q
|
|||
clKernelWrapper kernel;
|
||||
clMemWrapper streams[ 2 ];
|
||||
|
||||
char programSrc[ 10240 ];
|
||||
size_t threads[ 1 ], localThreads[ 1 ];
|
||||
size_t typeSize = get_explicit_type_size( inVecType );
|
||||
size_t outTypeSize = get_explicit_type_size(outVecType);
|
||||
char sizeNames[][ 3 ] = { "", "", "2", "3", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" };
|
||||
MTdata d;
|
||||
MTdataHolder d(gRandomSeed);
|
||||
|
||||
std::ostringstream sstr;
|
||||
if (outVecType == kDouble || inVecType == kDouble)
|
||||
sstr << "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
|
||||
|
||||
if (outVecType == kHalf || inVecType == kHalf)
|
||||
sstr << "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n";
|
||||
|
||||
// Create program
|
||||
if(outVecSize == 3 && vecSize == 3) {
|
||||
// astype_kernel_pattern_V3srcV3dst
|
||||
sprintf( programSrc, astype_kernel_pattern_V3srcV3dst,
|
||||
(outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "",
|
||||
get_explicit_type_name( inVecType ), // sizeNames[ vecSize ],
|
||||
get_explicit_type_name( outVecType ), // sizeNames[ outVecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ] );
|
||||
} else if(outVecSize == 3) {
|
||||
// astype_kernel_pattern_V3dst
|
||||
sprintf( programSrc, astype_kernel_pattern_V3dst,
|
||||
(outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "",
|
||||
get_explicit_type_name( inVecType ), sizeNames[ vecSize ],
|
||||
get_explicit_type_name( outVecType ),
|
||||
get_explicit_type_name( outVecType ),
|
||||
get_explicit_type_name( outVecType ));
|
||||
strcpy(extension, sstr.str().c_str());
|
||||
|
||||
} else if(vecSize == 3) {
|
||||
// astype_kernel_pattern_V3src
|
||||
sprintf( programSrc, astype_kernel_pattern_V3src,
|
||||
(outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "",
|
||||
get_explicit_type_name( inVecType ),// sizeNames[ vecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ]);
|
||||
} else {
|
||||
sprintf( programSrc, astype_kernel_pattern,
|
||||
(outVecType == kDouble || inVecType == kDouble) ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "",
|
||||
get_explicit_type_name( inVecType ), sizeNames[ vecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ],
|
||||
get_explicit_type_name( outVecType ), sizeNames[ outVecSize ]);
|
||||
}
|
||||
if (vecSize == 3)
|
||||
std::snprintf(strLoad, sizeof(strLoad), v3Load,
|
||||
get_explicit_type_name(outVecType), sizeNames[outVecSize],
|
||||
get_explicit_type_name(inVecType));
|
||||
else
|
||||
std::snprintf(strLoad, sizeof(strLoad), regLoad,
|
||||
get_explicit_type_name(outVecType),
|
||||
sizeNames[outVecSize]);
|
||||
|
||||
const char *ptr = programSrc;
|
||||
if (outVecSize == 3)
|
||||
std::snprintf(strStore, sizeof(strStore), v3Store,
|
||||
get_explicit_type_name(outVecType));
|
||||
else
|
||||
std::snprintf(strStore, sizeof(strStore), "%s", regStore);
|
||||
|
||||
auto str =
|
||||
concat_kernel(astype_kernel_pattern,
|
||||
sizeof(astype_kernel_pattern) / sizeof(const char *));
|
||||
std::string kernelSource =
|
||||
str_sprintf(str, get_explicit_type_name(inVecType), sizeNames[vecSize],
|
||||
get_explicit_type_name(outVecType), sizeNames[outVecSize],
|
||||
get_explicit_type_name(outVecType), sizeNames[outVecSize]);
|
||||
|
||||
const char *ptr = kernelSource.c_str();
|
||||
error = create_single_kernel_helper( context, &program, &kernel, 1, &ptr, "test_fn" );
|
||||
test_error( error, "Unable to create testing kernel" );
|
||||
|
||||
|
||||
// Create some input values
|
||||
size_t inBufferSize = sizeof(char)* numElements * get_explicit_type_size( inVecType ) * vecSize;
|
||||
char *inBuffer = (char*)malloc( inBufferSize );
|
||||
std::vector<char> inBuffer(inBufferSize);
|
||||
size_t outBufferSize = sizeof(char)* numElements * get_explicit_type_size( outVecType ) *outVecSize;
|
||||
char *outBuffer = (char*)malloc( outBufferSize );
|
||||
std::vector<char> outBuffer(outBufferSize);
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
generate_random_data( inVecType, numElements * vecSize,
|
||||
d, inBuffer );
|
||||
free_mtdata(d); d = NULL;
|
||||
generate_random_data(inVecType, numElements * vecSize, d,
|
||||
&inBuffer.front());
|
||||
|
||||
// Create I/O streams and set arguments
|
||||
streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, inBufferSize, inBuffer, &error );
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, inBufferSize,
|
||||
&inBuffer.front(), &error);
|
||||
test_error( error, "Unable to create I/O stream" );
|
||||
streams[ 1 ] = clCreateBuffer( context, CL_MEM_READ_WRITE, outBufferSize, NULL, &error );
|
||||
test_error( error, "Unable to create I/O stream" );
|
||||
|
|
@ -161,15 +130,15 @@ int test_astype_set( cl_device_id device, cl_context context, cl_command_queue q
|
|||
error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL );
|
||||
test_error( error, "Unable to run kernel" );
|
||||
|
||||
|
||||
// Get the results and compare
|
||||
// The beauty is that astype is supposed to return the bit pattern as a different type, which means
|
||||
// the output should have the exact same bit pattern as the input. No interpretation necessary!
|
||||
error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, outBufferSize, outBuffer, 0, NULL, NULL );
|
||||
error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, outBufferSize,
|
||||
&outBuffer.front(), 0, NULL, NULL);
|
||||
test_error( error, "Unable to read results" );
|
||||
|
||||
char *expected = inBuffer;
|
||||
char *actual = outBuffer;
|
||||
char *expected = &inBuffer.front();
|
||||
char *actual = &outBuffer.front();
|
||||
size_t compSize = typeSize*vecSize;
|
||||
if(outTypeSize*outVecSize < compSize) {
|
||||
compSize = outTypeSize*outVecSize;
|
||||
|
|
@ -178,8 +147,6 @@ int test_astype_set( cl_device_id device, cl_context context, cl_command_queue q
|
|||
if(outVecSize == 4 && vecSize == 3)
|
||||
{
|
||||
// as_type4(vec3) should compile but produce undefined results??
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -188,8 +155,6 @@ int test_astype_set( cl_device_id device, cl_context context, cl_command_queue q
|
|||
// as_typen(vecm) should compile and run but produce
|
||||
// implementation-defined results for m != n
|
||||
// and n*sizeof(type) = sizeof(vecm)
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -203,17 +168,14 @@ int test_astype_set( cl_device_id device, cl_context context, cl_command_queue q
|
|||
GetDataVectorString( expected, typeSize, vecSize, expectedString ),
|
||||
GetDataVectorString( actual, typeSize, vecSize, actualString ) );
|
||||
log_error("Src is :\n%s\n----\n%d threads %d localthreads\n",
|
||||
programSrc, (int)threads[0],(int) localThreads[0]);
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
kernelSource.c_str(), (int)threads[0],
|
||||
(int)localThreads[0]);
|
||||
return 1;
|
||||
}
|
||||
expected += typeSize * vecSize;
|
||||
actual += outTypeSize * outVecSize;
|
||||
}
|
||||
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -223,31 +185,39 @@ int test_astype(cl_device_id device, cl_context context, cl_command_queue queue,
|
|||
// legal in OpenCL 1.0, the result is dependent on the device it runs on, which means there's no actual way
|
||||
// for us to verify what is "valid". So the only thing we can test are types that match in size independent
|
||||
// of the element count (char -> uchar, etc)
|
||||
ExplicitType vecTypes[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes };
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
const std::vector<ExplicitType> vecTypes = { kChar, kUChar, kShort,
|
||||
kUShort, kInt, kUInt,
|
||||
kLong, kULong, kFloat,
|
||||
kHalf, kDouble };
|
||||
const unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int inTypeIdx, outTypeIdx, sizeIdx, outSizeIdx;
|
||||
size_t inTypeSize, outTypeSize;
|
||||
int error = 0;
|
||||
|
||||
for( inTypeIdx = 0; vecTypes[ inTypeIdx ] != kNumExplicitTypes; inTypeIdx++ )
|
||||
bool fp16Support = is_extension_available(device, "cl_khr_fp16");
|
||||
bool fp64Support = is_extension_available(device, "cl_khr_fp64");
|
||||
|
||||
auto skip_type = [&](ExplicitType et) {
|
||||
if ((et == kLong || et == kULong) && !gHasLong)
|
||||
return true;
|
||||
else if (et == kDouble && !fp64Support)
|
||||
return true;
|
||||
else if (et == kHalf && !fp16Support)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
for (inTypeIdx = 0; inTypeIdx < vecTypes.size(); inTypeIdx++)
|
||||
{
|
||||
inTypeSize = get_explicit_type_size(vecTypes[inTypeIdx]);
|
||||
|
||||
if( vecTypes[ inTypeIdx ] == kDouble && !is_extension_available( device, "cl_khr_fp64" ) )
|
||||
continue;
|
||||
if (skip_type(vecTypes[inTypeIdx])) continue;
|
||||
|
||||
if (( vecTypes[ inTypeIdx ] == kLong || vecTypes[ inTypeIdx ] == kULong ) && !gHasLong )
|
||||
continue;
|
||||
|
||||
for( outTypeIdx = 0; vecTypes[ outTypeIdx ] != kNumExplicitTypes; outTypeIdx++ )
|
||||
for (outTypeIdx = 0; outTypeIdx < vecTypes.size(); outTypeIdx++)
|
||||
{
|
||||
outTypeSize = get_explicit_type_size(vecTypes[outTypeIdx]);
|
||||
if( vecTypes[ outTypeIdx ] == kDouble && !is_extension_available( device, "cl_khr_fp64" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (( vecTypes[ outTypeIdx ] == kLong || vecTypes[ outTypeIdx ] == kULong ) && !gHasLong )
|
||||
continue;
|
||||
if (skip_type(vecTypes[outTypeIdx])) continue;
|
||||
|
||||
// change this check
|
||||
if( inTypeIdx == outTypeIdx ) {
|
||||
|
|
@ -259,7 +229,6 @@ int test_astype(cl_device_id device, cl_context context, cl_command_queue queue,
|
|||
|
||||
for( sizeIdx = 0; vecSizes[ sizeIdx ] != 0; sizeIdx++ )
|
||||
{
|
||||
|
||||
for(outSizeIdx = 0; vecSizes[outSizeIdx] != 0; outSizeIdx++)
|
||||
{
|
||||
if(vecSizes[sizeIdx]*inTypeSize !=
|
||||
|
|
@ -268,10 +237,7 @@ int test_astype(cl_device_id device, cl_context context, cl_command_queue queue,
|
|||
continue;
|
||||
}
|
||||
error += test_astype_set( device, context, queue, vecTypes[ inTypeIdx ], vecTypes[ outTypeIdx ], vecSizes[ sizeIdx ], vecSizes[outSizeIdx], n_elems );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if(get_explicit_type_size(vecTypes[inTypeIdx]) ==
|
||||
get_explicit_type_size(vecTypes[outTypeIdx])) {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
#include "harness/conversions.h"
|
||||
|
|
@ -86,8 +85,7 @@ int test_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue,
|
|||
clKernelWrapper kernel;
|
||||
clMemWrapper streams[ 2 ];
|
||||
size_t threads[ 1 ], localThreads[ 1 ];
|
||||
void *inBuffer, *outBuffer;
|
||||
MTdata d;
|
||||
MTdataHolder d(gRandomSeed);
|
||||
char vecNameString[64]; vecNameString[0] = 0;
|
||||
if (vecSize == 1)
|
||||
sprintf(vecNameString, "%s", get_explicit_type_name(vecType));
|
||||
|
|
@ -109,9 +107,15 @@ int test_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue,
|
|||
char programSource[4096]; programSource[0]=0;
|
||||
char *programPtr;
|
||||
|
||||
sprintf(programSource, kernelCode,
|
||||
vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "",
|
||||
vecNameString, vecNameString, vecNameString, vecNameString, get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
std::string extStr = "";
|
||||
if (vecType == kDouble)
|
||||
extStr = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable";
|
||||
else if (vecType == kHalf)
|
||||
extStr = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable";
|
||||
|
||||
sprintf(programSource, kernelCode, extStr.c_str(), vecNameString,
|
||||
vecNameString, vecNameString, vecNameString,
|
||||
get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
//log_info("program: %s\n", programSource);
|
||||
programPtr = programSource;
|
||||
|
||||
|
|
@ -150,9 +154,10 @@ int test_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue,
|
|||
size_t globalBufferSize = numberOfLocalWorkgroups*localBufferSize;
|
||||
size_t globalWorkgroupSize = numberOfLocalWorkgroups*localWorkgroupSize;
|
||||
|
||||
inBuffer = (void*)malloc(globalBufferSize);
|
||||
outBuffer = (void*)malloc(globalBufferSize);
|
||||
memset(outBuffer, 0, globalBufferSize);
|
||||
std::vector<unsigned char> inBuffer(globalBufferSize);
|
||||
std::vector<unsigned char> outBuffer(globalBufferSize);
|
||||
|
||||
outBuffer.assign(globalBufferSize, 0);
|
||||
|
||||
cl_int copiesPerWorkItemInt, copiesPerWorkgroup;
|
||||
copiesPerWorkItemInt = (int)numberOfCopiesPerWorkitem;
|
||||
|
|
@ -164,13 +169,15 @@ int test_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue,
|
|||
threads[0] = globalWorkgroupSize;
|
||||
localThreads[0] = localWorkgroupSize;
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
generate_random_data( vecType, globalBufferSize/get_explicit_type_size(vecType), d, inBuffer );
|
||||
free_mtdata(d); d = NULL;
|
||||
generate_random_data(vecType,
|
||||
globalBufferSize / get_explicit_type_size(vecType), d,
|
||||
&inBuffer.front());
|
||||
|
||||
streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, inBuffer, &error );
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, globalBufferSize,
|
||||
&inBuffer.front(), &error);
|
||||
test_error( error, "Unable to create input buffer" );
|
||||
streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, outBuffer, &error );
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, globalBufferSize,
|
||||
&outBuffer.front(), &error);
|
||||
test_error( error, "Unable to create output buffer" );
|
||||
|
||||
error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] );
|
||||
|
|
@ -189,16 +196,18 @@ int test_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue,
|
|||
test_error( error, "Unable to queue kernel" );
|
||||
|
||||
// Read
|
||||
error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, globalBufferSize, outBuffer, 0, NULL, NULL );
|
||||
error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, globalBufferSize,
|
||||
&outBuffer.front(), 0, NULL, NULL);
|
||||
test_error( error, "Unable to read results" );
|
||||
|
||||
// Verify
|
||||
int failuresPrinted = 0;
|
||||
if( memcmp( inBuffer, outBuffer, globalBufferSize ) != 0 )
|
||||
if (memcmp(&inBuffer.front(), &outBuffer.front(), globalBufferSize) != 0)
|
||||
{
|
||||
size_t typeSize = get_explicit_type_size(vecType)* vecSize;
|
||||
unsigned char * inchar = (unsigned char*)inBuffer;
|
||||
unsigned char * outchar = (unsigned char*)outBuffer;
|
||||
unsigned char *inchar = static_cast<unsigned char *>(&inBuffer.front());
|
||||
unsigned char *outchar =
|
||||
static_cast<unsigned char *>(&outBuffer.front());
|
||||
for (int i=0; i< (int)globalBufferSize; i+=(int)elementSize) {
|
||||
if (memcmp( ((char *)inchar)+i, ((char *)outchar)+i, typeSize) != 0 )
|
||||
{
|
||||
|
|
@ -226,26 +235,29 @@ int test_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue,
|
|||
}
|
||||
}
|
||||
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
|
||||
return failuresPrinted ? -1 : 0;
|
||||
}
|
||||
|
||||
int test_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode) {
|
||||
ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes };
|
||||
const std::vector<ExplicitType> vecType = { kChar, kUChar, kShort, kUShort,
|
||||
kInt, kUInt, kLong, kULong,
|
||||
kFloat, kHalf, kDouble };
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int size, typeIndex;
|
||||
|
||||
int errors = 0;
|
||||
|
||||
for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ )
|
||||
{
|
||||
if( vecType[ typeIndex ] == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) )
|
||||
continue;
|
||||
bool fp16Support = is_extension_available(deviceID, "cl_khr_fp16");
|
||||
bool fp64Support = is_extension_available(deviceID, "cl_khr_fp64");
|
||||
|
||||
for (typeIndex = 0; typeIndex < vecType.size(); typeIndex++)
|
||||
{
|
||||
if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong )
|
||||
continue;
|
||||
else if (vecType[typeIndex] == kDouble && !fp64Support)
|
||||
continue;
|
||||
else if (vecType[typeIndex] == kHalf && !fp16Support)
|
||||
continue;
|
||||
|
||||
for( size = 0; vecSizes[ size ] != 0; size++ )
|
||||
{
|
||||
|
|
@ -259,9 +271,6 @@ int test_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_qu
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int test_async_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_copy_all_types( deviceID, context, queue, async_global_to_local_kernel );
|
||||
|
|
|
|||
|
|
@ -25,104 +25,103 @@
|
|||
#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
|
||||
|
||||
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";
|
||||
#define STRUCT_SIZE %d
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uchar byte[STRUCT_SIZE];
|
||||
} VarSizeStruct __attribute__((aligned(1)));
|
||||
|
||||
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,
|
||||
bool localIsDst)
|
||||
|
||||
__kernel void test_fn(const __global VarSizeStruct *src, __global VarSizeStruct *dst,
|
||||
__local VarSizeStruct *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;
|
||||
for (int k = 0; k < STRUCT_SIZE; k++) {
|
||||
localBuffer[index].byte[k] = 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(VarSizeStruct),
|
||||
(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
|
||||
|
||||
#define STRUCT_SIZE %d
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uchar byte[STRUCT_SIZE];
|
||||
} VarSizeStruct __attribute__((aligned(1)));
|
||||
|
||||
|
||||
__kernel void test_fn(const __global VarSizeStruct *src, __global VarSizeStruct *dst, __local VarSizeStruct *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;
|
||||
for (int k = 0; k < STRUCT_SIZE; k++) {
|
||||
localBuffer[index].byte[k] = 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(VarSizeStruct), (size_t)numElementsPerLine, (size_t)lineCopiesPerWorkgroup, srcStride,
|
||||
dstStride, 0 );
|
||||
|
||||
wait_group_events(1, &event);
|
||||
};
|
||||
)OpenCLC";
|
||||
|
||||
int test_copy2D(const cl_device_id deviceID, const cl_context context,
|
||||
const cl_command_queue queue, const char *const kernelCode,
|
||||
const size_t elementSize, const int srcMargin,
|
||||
const int dstMargin, const bool localIsDst)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
clMemWrapper streams[2];
|
||||
size_t threads[1], localThreads[1];
|
||||
void *inBuffer, *outBuffer, *outBufferCopy;
|
||||
MTdata d;
|
||||
char vecNameString[64];
|
||||
vecNameString[0] = 0;
|
||||
if (vecSize == 1)
|
||||
sprintf(vecNameString, "%s", get_explicit_type_name(vecType));
|
||||
else
|
||||
sprintf(vecNameString, "%s%d", get_explicit_type_name(vecType),
|
||||
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 %d byte element with srcMargin = %d, dstMargin = %d\n",
|
||||
elementSize, srcMargin, dstMargin);
|
||||
|
||||
cl_long max_local_mem_size;
|
||||
error =
|
||||
|
|
@ -142,6 +141,13 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
test_error(error,
|
||||
"clGetDeviceInfo for CL_DEVICE_MAX_MEM_ALLOC_SIZE failed.");
|
||||
|
||||
cl_long max_work_group_size;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_GROUP_SIZE,
|
||||
sizeof(max_work_group_size), &max_work_group_size,
|
||||
NULL);
|
||||
test_error(error,
|
||||
"clGetDeviceInfo for CL_DEVICE_MAX_WORK_GROUP_SIZE failed.");
|
||||
|
||||
if (max_alloc_size > max_global_mem_size / 2)
|
||||
max_alloc_size = max_global_mem_size / 2;
|
||||
|
||||
|
|
@ -152,20 +158,17 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
test_error(error,
|
||||
"clGetDeviceInfo for CL_DEVICE_MAX_COMPUTE_UNITS failed.");
|
||||
|
||||
char programSource[4096];
|
||||
programSource[0] = 0;
|
||||
char *programPtr;
|
||||
char programSource[4096] = { 0 };
|
||||
const char *programPtr = programSource;
|
||||
|
||||
sprintf(programSource, kernelCode,
|
||||
vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"
|
||||
: "",
|
||||
vecNameString, vecNameString, vecNameString, vecNameString,
|
||||
get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
sprintf(programSource, kernelCode, elementSize);
|
||||
// log_info("program: %s\n", programSource);
|
||||
programPtr = programSource;
|
||||
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
error = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
(const char **)&programPtr, "test_fn");
|
||||
&programPtr, "test_fn");
|
||||
test_error(error, "Unable to create testing kernel");
|
||||
|
||||
size_t max_workgroup_size;
|
||||
|
|
@ -187,12 +190,14 @@ 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;
|
||||
elementSize =
|
||||
get_explicit_type_size(vecType) * ((vecSize == 3) ? 4 : vecSize);
|
||||
size_t localStorageSpacePerWorkitem = lineCopiesPerWorkItem * elementSize
|
||||
* (numElementsPerLine + (localIsDst ? dstStride : srcStride));
|
||||
const size_t numElementsPerLine = 10;
|
||||
const cl_int dstStride = numElementsPerLine + dstMargin;
|
||||
const cl_int srcStride = numElementsPerLine + srcMargin;
|
||||
|
||||
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 +211,46 @@ 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);
|
||||
if ((localBufferSize / 4) > max_work_group_size)
|
||||
{
|
||||
log_info("Skipping due to resource requirements local:%db "
|
||||
"max_work_group_size:%d\n",
|
||||
localBufferSize, max_work_group_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cl_int lineCopiesPerWorkItemInt, numElementsPerLineInt,
|
||||
lineCopiesPerWorkgroup;
|
||||
lineCopiesPerWorkItemInt = (int)lineCopiesPerWorkItem;
|
||||
numElementsPerLineInt = (int)numElementsPerLine;
|
||||
lineCopiesPerWorkgroup = (int)(lineCopiesPerWorkItem * localWorkgroupSize);
|
||||
void *const inBuffer = (void *)malloc(inBufferSize);
|
||||
void *const outBuffer = (void *)malloc(outBufferSize);
|
||||
void *const outBufferCopy = (void *)malloc(outBufferSize);
|
||||
|
||||
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, "
|
||||
|
|
@ -243,18 +260,20 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
(int)inBufferSize, (int)outBufferSize, lineCopiesPerWorkgroup,
|
||||
lineCopiesPerWorkItemInt);
|
||||
|
||||
size_t threads[1], localThreads[1];
|
||||
|
||||
threads[0] = globalWorkgroupSize;
|
||||
localThreads[0] = localWorkgroupSize;
|
||||
|
||||
d = init_genrand(gRandomSeed);
|
||||
generate_random_data(
|
||||
vecType, inBufferSize / get_explicit_type_size(vecType), d, inBuffer);
|
||||
generate_random_data(
|
||||
vecType, outBufferSize / get_explicit_type_size(vecType), d, outBuffer);
|
||||
MTdata d = init_genrand(gRandomSeed);
|
||||
generate_random_data(kChar, inBufferSize, d, inBuffer);
|
||||
generate_random_data(kChar, outBufferSize, d, outBuffer);
|
||||
free_mtdata(d);
|
||||
d = NULL;
|
||||
memcpy(outBufferCopy, outBuffer, outBufferSize);
|
||||
|
||||
clMemWrapper streams[2];
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, inBufferSize,
|
||||
inBuffer, &error);
|
||||
test_error(error, "Unable to create input buffer");
|
||||
|
|
@ -294,8 +313,7 @@ int test_copy2D(cl_device_id deviceID, cl_context context,
|
|||
|
||||
// Verify
|
||||
int failuresPrinted = 0;
|
||||
// Verify
|
||||
size_t typeSize = get_explicit_type_size(vecType) * vecSize;
|
||||
|
||||
for (int i = 0;
|
||||
i < (int)globalWorkgroupSize * lineCopiesPerWorkItem * elementSize;
|
||||
i += elementSize)
|
||||
|
|
@ -303,16 +321,15 @@ 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)
|
||||
elementSize)
|
||||
!= 0)
|
||||
{
|
||||
unsigned char *inchar = (unsigned char *)inBuffer + inIdx;
|
||||
unsigned char *outchar = (unsigned char *)outBuffer + outIdx;
|
||||
char values[4096];
|
||||
values[0] = 0;
|
||||
char values[4096] = { 0 };
|
||||
|
||||
if (failuresPrinted == 0)
|
||||
{
|
||||
|
|
@ -339,11 +356,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)
|
||||
|
|
@ -376,62 +392,42 @@ int test_copy2D_all_types(cl_device_id deviceID, cl_context context,
|
|||
cl_command_queue queue, const char *kernelCode,
|
||||
bool localIsDst)
|
||||
{
|
||||
ExplicitType vecType[] = {
|
||||
kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong,
|
||||
kULong, kFloat, kDouble, kNumExplicitTypes
|
||||
};
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int smallTypesStrideSizes[] = { 0, 10, 100 };
|
||||
unsigned int size, typeIndex, srcStride, dstStride;
|
||||
const unsigned int elemSizes[] = { 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 13, 16, 32, 47, 64 };
|
||||
// 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.
|
||||
// These have to be multipliers, because the margin must be a multiple of
|
||||
// element size.
|
||||
const unsigned int marginMultipliers[] = { 0, 10, 100 };
|
||||
|
||||
int errors = 0;
|
||||
|
||||
for (typeIndex = 0; vecType[typeIndex] != kNumExplicitTypes; typeIndex++)
|
||||
if (!is_extension_available(deviceID, "cl_khr_extended_async_copies"))
|
||||
{
|
||||
if (vecType[typeIndex] == kDouble
|
||||
&& !is_extension_available(deviceID, "cl_khr_fp64"))
|
||||
continue;
|
||||
|
||||
if ((vecType[typeIndex] == kLong || vecType[typeIndex] == kULong)
|
||||
&& !gHasLong)
|
||||
continue;
|
||||
|
||||
for (size = 0; vecSizes[size] != 0; size++)
|
||||
log_info(
|
||||
"Device does not support extended async copies. Skipping test.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const unsigned int elemSize : elemSizes)
|
||||
{
|
||||
if (get_explicit_type_size(vecType[typeIndex]) * vecSizes[size]
|
||||
<= 2) // small type
|
||||
for (const unsigned int srcMarginMultiplier : marginMultipliers)
|
||||
{
|
||||
for (srcStride = 0; srcStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
srcStride++)
|
||||
for (const unsigned int dstMarginMultiplier : marginMultipliers)
|
||||
{
|
||||
for (dstStride = 0;
|
||||
dstStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
dstStride++)
|
||||
if (test_copy2D(deviceID, context, queue, kernelCode,
|
||||
elemSize, srcMarginMultiplier * elemSize,
|
||||
dstMarginMultiplier * elemSize, localIsDst))
|
||||
{
|
||||
if (test_copy2D(deviceID, context, queue, kernelCode,
|
||||
vecType[typeIndex], vecSizes[size],
|
||||
smallTypesStrideSizes[srcStride],
|
||||
smallTypesStrideSizes[dstStride],
|
||||
localIsDst))
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// not a small type, check only zero stride
|
||||
else if (test_copy2D(deviceID, context, queue, kernelCode,
|
||||
vecType[typeIndex], vecSizes[size], 0, 0,
|
||||
localIsDst))
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors) return -1;
|
||||
return 0;
|
||||
|
||||
return errors ? -1 : 0;
|
||||
}
|
||||
|
||||
int test_async_copy_global_to_local2D(cl_device_id deviceID, cl_context context,
|
||||
|
|
|
|||
|
|
@ -25,125 +25,118 @@
|
|||
#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
|
||||
|
||||
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";
|
||||
#define STRUCT_SIZE %d
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uchar byte[STRUCT_SIZE];
|
||||
} VarSizeStruct __attribute__((aligned(1)));
|
||||
|
||||
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,
|
||||
bool localIsDst)
|
||||
__kernel void test_fn(const __global VarSizeStruct *src, __global VarSizeStruct *dst, __local VarSizeStruct *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;
|
||||
for (int k = 0; k < STRUCT_SIZE; k++) {
|
||||
localBuffer[index].byte[k] = 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(VarSizeStruct), (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
|
||||
|
||||
#define STRUCT_SIZE %d
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
uchar byte[STRUCT_SIZE];
|
||||
} VarSizeStruct __attribute__((aligned(1)));
|
||||
|
||||
__kernel void test_fn(const __global VarSizeStruct *src, __global VarSizeStruct *dst, __local VarSizeStruct *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;
|
||||
for (int k = 0; k < STRUCT_SIZE; k++) {
|
||||
localBuffer[index].byte[k] = 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(VarSizeStruct), (size_t)numElementsPerLine, (size_t)numLines, planesCopiesPerWorkgroup,
|
||||
srcLineStride, srcPlaneStride, dstLineStride, dstPlaneStride, 0);
|
||||
|
||||
wait_group_events(1, &event);
|
||||
}
|
||||
)OpenCLC";
|
||||
|
||||
int test_copy3D(const cl_device_id deviceID, const cl_context context,
|
||||
const cl_command_queue queue, const char *const kernelCode,
|
||||
const size_t elementSize, const int srcLineMargin,
|
||||
const int dstLineMargin, const int srcPlaneMargin,
|
||||
const int dstPlaneMargin, const bool localIsDst)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
clMemWrapper streams[2];
|
||||
size_t threads[1], localThreads[1];
|
||||
void *inBuffer, *outBuffer, *outBufferCopy;
|
||||
MTdata d;
|
||||
char vecNameString[64];
|
||||
vecNameString[0] = 0;
|
||||
if (vecSize == 1)
|
||||
sprintf(vecNameString, "%s", get_explicit_type_name(vecType));
|
||||
else
|
||||
sprintf(vecNameString, "%s%d", get_explicit_type_name(vecType),
|
||||
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 %d byte element with srcLineMargin = %d, dstLineMargin = %d, "
|
||||
"srcPlaneMargin = %d, dstPlaneMargin = %d\n",
|
||||
elementSize, srcLineMargin, dstLineMargin, srcPlaneMargin,
|
||||
dstPlaneMargin);
|
||||
|
||||
cl_long max_local_mem_size;
|
||||
error =
|
||||
|
|
@ -173,20 +166,16 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
test_error(error,
|
||||
"clGetDeviceInfo for CL_DEVICE_MAX_COMPUTE_UNITS failed.");
|
||||
|
||||
char programSource[4096];
|
||||
programSource[0] = 0;
|
||||
char *programPtr;
|
||||
char programSource[4096] = { 0 };
|
||||
const char *programPtr = programSource;
|
||||
|
||||
sprintf(programSource, kernelCode,
|
||||
vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable"
|
||||
: "",
|
||||
vecNameString, vecNameString, vecNameString, vecNameString,
|
||||
get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
sprintf(programSource, kernelCode, elementSize);
|
||||
// log_info("program: %s\n", programSource);
|
||||
programPtr = programSource;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
error = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
(const char **)&programPtr, "test_fn");
|
||||
&programPtr, "test_fn");
|
||||
test_error(error, "Unable to create testing kernel");
|
||||
|
||||
size_t max_workgroup_size;
|
||||
|
|
@ -204,20 +193,29 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
test_error(error,
|
||||
"clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES");
|
||||
|
||||
cl_long max_work_group_size;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_GROUP_SIZE,
|
||||
sizeof(max_work_group_size), &max_work_group_size,
|
||||
NULL);
|
||||
test_error(error,
|
||||
"clGetDeviceInfo for CL_DEVICE_MAX_WORK_GROUP_SIZE failed.");
|
||||
|
||||
// Pick the minimum of the device and the kernel
|
||||
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;
|
||||
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 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;
|
||||
|
||||
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 +229,49 @@ 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);
|
||||
if ((localBufferSize / 4) > max_work_group_size)
|
||||
{
|
||||
log_info("Skipping due to resource requirements local:%db "
|
||||
"max_work_group_size:%d\n",
|
||||
localBufferSize, max_work_group_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cl_int planesCopiesPerWorkItemInt, numElementsPerLineInt, numLinesInt,
|
||||
planesCopiesPerWorkgroup;
|
||||
planesCopiesPerWorkItemInt = (int)planesCopiesPerWorkItem;
|
||||
numElementsPerLineInt = (int)numElementsPerLine;
|
||||
numLinesInt = (int)numLines;
|
||||
planesCopiesPerWorkgroup =
|
||||
(int)(planesCopiesPerWorkItem * localWorkgroupSize);
|
||||
void *const inBuffer = (void *)malloc(inBufferSize);
|
||||
void *const outBuffer = (void *)malloc(outBufferSize);
|
||||
void *const outBufferCopy = (void *)malloc(outBufferSize);
|
||||
|
||||
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 "
|
||||
|
|
@ -275,18 +280,20 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
(int)localBufferSize, (int)inBufferSize, (int)outBufferSize,
|
||||
planesCopiesPerWorkgroup, planesCopiesPerWorkItemInt);
|
||||
|
||||
size_t threads[1], localThreads[1];
|
||||
|
||||
threads[0] = globalWorkgroupSize;
|
||||
localThreads[0] = localWorkgroupSize;
|
||||
|
||||
d = init_genrand(gRandomSeed);
|
||||
generate_random_data(
|
||||
vecType, inBufferSize / get_explicit_type_size(vecType), d, inBuffer);
|
||||
generate_random_data(
|
||||
vecType, outBufferSize / get_explicit_type_size(vecType), d, outBuffer);
|
||||
MTdata d = init_genrand(gRandomSeed);
|
||||
generate_random_data(kChar, inBufferSize, d, inBuffer);
|
||||
generate_random_data(kChar, outBufferSize, d, outBuffer);
|
||||
free_mtdata(d);
|
||||
d = NULL;
|
||||
memcpy(outBufferCopy, outBuffer, outBufferSize);
|
||||
|
||||
clMemWrapper streams[2];
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, inBufferSize,
|
||||
inBuffer, &error);
|
||||
test_error(error, "Unable to create input buffer");
|
||||
|
|
@ -332,8 +339,7 @@ int test_copy3D(cl_device_id deviceID, cl_context context,
|
|||
|
||||
// Verify
|
||||
int failuresPrinted = 0;
|
||||
// Verify
|
||||
size_t typeSize = get_explicit_type_size(vecType) * vecSize;
|
||||
|
||||
for (int i = 0;
|
||||
i < (int)globalWorkgroupSize * planesCopiesPerWorkItem * elementSize;
|
||||
i += elementSize)
|
||||
|
|
@ -343,23 +349,16 @@ 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)
|
||||
((char *)outBuffer) + outIdx, elementSize)
|
||||
!= 0)
|
||||
{
|
||||
unsigned char *inchar = (unsigned char *)inBuffer + inIdx;
|
||||
unsigned char *outchar =
|
||||
(unsigned char *)outBuffer + outIdx;
|
||||
char values[4096];
|
||||
values[0] = 0;
|
||||
char values[4096] = { 0 };
|
||||
|
||||
if (failuresPrinted == 0)
|
||||
{
|
||||
|
|
@ -385,14 +384,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 +412,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)
|
||||
|
|
@ -456,75 +449,51 @@ int test_copy3D_all_types(cl_device_id deviceID, cl_context context,
|
|||
cl_command_queue queue, const char *kernelCode,
|
||||
bool localIsDst)
|
||||
{
|
||||
ExplicitType vecType[] = {
|
||||
kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong,
|
||||
kULong, kFloat, kDouble, kNumExplicitTypes
|
||||
};
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int smallTypesStrideSizes[] = { 0, 10, 100 };
|
||||
unsigned int size, typeIndex, srcLineStride, dstLineStride, srcPlaneStride,
|
||||
dstPlaneStride;
|
||||
const unsigned int elemSizes[] = { 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 13, 16, 32, 47, 64 };
|
||||
// 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
|
||||
// size of the line or plane plus the chosen margin.
|
||||
// These have to be multipliers, because the margin must be a multiple of
|
||||
// element size.
|
||||
const unsigned int marginMultipliers[] = { 0, 10, 100 };
|
||||
|
||||
int errors = 0;
|
||||
|
||||
for (typeIndex = 0; vecType[typeIndex] != kNumExplicitTypes; typeIndex++)
|
||||
if (!is_extension_available(deviceID, "cl_khr_extended_async_copies"))
|
||||
{
|
||||
if (vecType[typeIndex] == kDouble
|
||||
&& !is_extension_available(deviceID, "cl_khr_fp64"))
|
||||
continue;
|
||||
|
||||
if ((vecType[typeIndex] == kLong || vecType[typeIndex] == kULong)
|
||||
&& !gHasLong)
|
||||
continue;
|
||||
|
||||
for (size = 0; vecSizes[size] != 0; size++)
|
||||
log_info(
|
||||
"Device does not support extended async copies. Skipping test.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const unsigned int elemSize : elemSizes)
|
||||
{
|
||||
if (get_explicit_type_size(vecType[typeIndex]) * vecSizes[size]
|
||||
<= 2) // small type
|
||||
for (const unsigned int srcLineMarginMultiplier : marginMultipliers)
|
||||
{
|
||||
for (srcLineStride = 0;
|
||||
srcLineStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
srcLineStride++)
|
||||
for (const unsigned int dstLineMarginMultiplier :
|
||||
marginMultipliers)
|
||||
{
|
||||
for (dstLineStride = 0;
|
||||
dstLineStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
dstLineStride++)
|
||||
for (const unsigned int srcPlaneMarginMultiplier :
|
||||
marginMultipliers)
|
||||
{
|
||||
for (srcPlaneStride = 0;
|
||||
srcPlaneStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
srcPlaneStride++)
|
||||
for (const unsigned int dstPlaneMarginMultiplier :
|
||||
marginMultipliers)
|
||||
{
|
||||
for (dstPlaneStride = 0;
|
||||
dstPlaneStride < sizeof(smallTypesStrideSizes)
|
||||
/ sizeof(smallTypesStrideSizes[0]);
|
||||
dstPlaneStride++)
|
||||
if (test_copy3D(deviceID, context, queue,
|
||||
kernelCode, elemSize,
|
||||
srcLineMarginMultiplier * elemSize,
|
||||
dstLineMarginMultiplier * elemSize,
|
||||
srcPlaneMarginMultiplier * elemSize,
|
||||
dstPlaneMarginMultiplier * elemSize,
|
||||
localIsDst))
|
||||
{
|
||||
if (test_copy3D(
|
||||
deviceID, context, queue, kernelCode,
|
||||
vecType[typeIndex], vecSizes[size],
|
||||
smallTypesStrideSizes[srcLineStride],
|
||||
smallTypesStrideSizes[dstLineStride],
|
||||
smallTypesStrideSizes[srcPlaneStride],
|
||||
smallTypesStrideSizes[dstPlaneStride],
|
||||
localIsDst))
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// not a small type, check only zero stride
|
||||
else if (test_copy3D(deviceID, context, queue, kernelCode,
|
||||
vecType[typeIndex], vecSizes[size], 0, 0, 0, 0,
|
||||
localIsDst))
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors) return -1;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Copyright (c) 2023 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
|
||||
|
|
@ -20,15 +20,16 @@
|
|||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
#include "harness/conversions.h"
|
||||
|
||||
// clang-format off
|
||||
|
||||
static const char *async_strided_global_to_local_kernel =
|
||||
"%s\n" // optional pragma string
|
||||
"%s__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem, int stride )\n"
|
||||
"__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem, int stride )\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
// Zero the local storage first
|
||||
|
|
@ -46,7 +47,7 @@ static const char *async_strided_global_to_local_kernel =
|
|||
|
||||
static const char *async_strided_local_to_global_kernel =
|
||||
"%s\n" // optional pragma string
|
||||
"%s__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem, int stride )\n"
|
||||
"__kernel void test_fn( const __global %s *src, __global %s *dst, __local %s *localBuffer, int copiesPerWorkgroup, int copiesPerWorkItem, int stride )\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
// Zero the local storage first
|
||||
|
|
@ -63,6 +64,7 @@ static const char *async_strided_local_to_global_kernel =
|
|||
" wait_group_events( 1, &event );\n"
|
||||
"}\n" ;
|
||||
|
||||
// clang-format on
|
||||
|
||||
int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode, ExplicitType vecType, int vecSize, int stride)
|
||||
{
|
||||
|
|
@ -71,8 +73,7 @@ int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
clKernelWrapper kernel;
|
||||
clMemWrapper streams[ 2 ];
|
||||
size_t threads[ 1 ], localThreads[ 1 ];
|
||||
void *inBuffer, *outBuffer;
|
||||
MTdata d;
|
||||
MTdataHolder d(gRandomSeed);
|
||||
char vecNameString[64]; vecNameString[0] = 0;
|
||||
|
||||
if (vecSize == 1)
|
||||
|
|
@ -94,10 +95,15 @@ int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
char programSource[4096]; programSource[0]=0;
|
||||
char *programPtr;
|
||||
|
||||
sprintf(programSource, kernelCode,
|
||||
vecType == kDouble ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" : "",
|
||||
"",
|
||||
vecNameString, vecNameString, vecNameString, vecNameString, get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
std::string extStr = "";
|
||||
if (vecType == kDouble)
|
||||
extStr = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable";
|
||||
else if (vecType == kHalf)
|
||||
extStr = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable";
|
||||
|
||||
sprintf(programSource, kernelCode, extStr.c_str(), vecNameString,
|
||||
vecNameString, vecNameString, vecNameString,
|
||||
get_explicit_type_name(vecType), vecNameString, vecNameString);
|
||||
//log_info("program: %s\n", programSource);
|
||||
programPtr = programSource;
|
||||
|
||||
|
|
@ -151,9 +157,9 @@ int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
size_t globalBufferSize = numberOfLocalWorkgroups*localBufferSize*stride;
|
||||
size_t globalWorkgroupSize = numberOfLocalWorkgroups*localWorkgroupSize;
|
||||
|
||||
inBuffer = (void*)malloc(globalBufferSize);
|
||||
outBuffer = (void*)malloc(globalBufferSize);
|
||||
memset(outBuffer, 0, globalBufferSize);
|
||||
std::vector<unsigned char> inBuffer(globalBufferSize);
|
||||
std::vector<unsigned char> outBuffer(globalBufferSize);
|
||||
memset(outBuffer.data(), 0, globalBufferSize);
|
||||
|
||||
cl_int copiesPerWorkItemInt, copiesPerWorkgroup;
|
||||
copiesPerWorkItemInt = (int)numberOfCopiesPerWorkitem;
|
||||
|
|
@ -165,13 +171,15 @@ int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
threads[0] = globalWorkgroupSize;
|
||||
localThreads[0] = localWorkgroupSize;
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
generate_random_data( vecType, globalBufferSize/get_explicit_type_size(vecType), d, inBuffer );
|
||||
free_mtdata(d); d = NULL;
|
||||
generate_random_data(vecType,
|
||||
globalBufferSize / get_explicit_type_size(vecType), d,
|
||||
inBuffer.data());
|
||||
|
||||
streams[ 0 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, inBuffer, &error );
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, globalBufferSize,
|
||||
inBuffer.data(), &error);
|
||||
test_error( error, "Unable to create input buffer" );
|
||||
streams[ 1 ] = clCreateBuffer( context, CL_MEM_COPY_HOST_PTR, globalBufferSize, outBuffer, &error );
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, globalBufferSize,
|
||||
outBuffer.data(), &error);
|
||||
test_error( error, "Unable to create output buffer" );
|
||||
|
||||
error = clSetKernelArg( kernel, 0, sizeof( streams[ 0 ] ), &streams[ 0 ] );
|
||||
|
|
@ -192,17 +200,20 @@ int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
test_error( error, "Unable to queue kernel" );
|
||||
|
||||
// Read
|
||||
error = clEnqueueReadBuffer( queue, streams[ 1 ], CL_TRUE, 0, globalBufferSize, outBuffer, 0, NULL, NULL );
|
||||
error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, globalBufferSize,
|
||||
outBuffer.data(), 0, NULL, NULL);
|
||||
test_error( error, "Unable to read results" );
|
||||
|
||||
// Verify
|
||||
size_t typeSize = get_explicit_type_size(vecType)* vecSize;
|
||||
for (int i=0; i<(int)globalBufferSize; i+=(int)elementSize*(int)stride)
|
||||
{
|
||||
if (memcmp( ((char *)inBuffer)+i, ((char *)outBuffer)+i, typeSize) != 0 )
|
||||
if (memcmp(&inBuffer.at(i), &outBuffer.at(i), typeSize) != 0)
|
||||
{
|
||||
unsigned char * inchar = (unsigned char*)inBuffer + i;
|
||||
unsigned char * outchar = (unsigned char*)outBuffer + i;
|
||||
unsigned char *inchar =
|
||||
static_cast<unsigned char *>(&inBuffer.at(i));
|
||||
unsigned char *outchar =
|
||||
static_cast<unsigned char *>(&outBuffer.at(i));
|
||||
char values[4096];
|
||||
values[0] = 0;
|
||||
|
||||
|
|
@ -215,34 +226,35 @@ int test_strided_copy(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
sprintf(values + strlen( values), "%2x ", outchar[j]);
|
||||
sprintf(values + strlen(values), "]");
|
||||
log_error("%s\n", values);
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(inBuffer);
|
||||
free(outBuffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_strided_copy_all_types(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *kernelCode)
|
||||
{
|
||||
ExplicitType vecType[] = { kChar, kUChar, kShort, kUShort, kInt, kUInt, kLong, kULong, kFloat, kDouble, kNumExplicitTypes };
|
||||
unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
unsigned int strideSizes[] = { 1, 3, 4, 5, 0 };
|
||||
const std::vector<ExplicitType> vecType = { kChar, kUChar, kShort, kUShort,
|
||||
kInt, kUInt, kLong, kULong,
|
||||
kFloat, kHalf, kDouble };
|
||||
const unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
|
||||
const unsigned int strideSizes[] = { 1, 3, 4, 5, 0 };
|
||||
unsigned int size, typeIndex, stride;
|
||||
|
||||
int errors = 0;
|
||||
|
||||
for( typeIndex = 0; vecType[ typeIndex ] != kNumExplicitTypes; typeIndex++ )
|
||||
{
|
||||
if( vecType[ typeIndex ] == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) )
|
||||
continue;
|
||||
bool fp16Support = is_extension_available(deviceID, "cl_khr_fp16");
|
||||
bool fp64Support = is_extension_available(deviceID, "cl_khr_fp64");
|
||||
|
||||
for (typeIndex = 0; typeIndex < vecType.size(); typeIndex++)
|
||||
{
|
||||
if (( vecType[ typeIndex ] == kLong || vecType[ typeIndex ] == kULong ) && !gHasLong )
|
||||
continue;
|
||||
else if (vecType[typeIndex] == kDouble && !fp64Support)
|
||||
continue;
|
||||
else if (vecType[typeIndex] == kHalf && !fp16Support)
|
||||
continue;
|
||||
|
||||
for( size = 0; vecSizes[ size ] != 0; size++ )
|
||||
{
|
||||
|
|
@ -260,9 +272,6 @@ int test_strided_copy_all_types(cl_device_id deviceID, cl_context context, cl_co
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int test_async_strided_copy_global_to_local(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_strided_copy_all_types( deviceID, context, queue, async_strided_global_to_local_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
|
||||
|
|
@ -21,143 +21,136 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
const char *barrier_kernel_code =
|
||||
"__kernel void compute_sum(__global int *a, int n, __global int *tmp_sum, __global int *sum)\n"
|
||||
"{\n"
|
||||
" int tid = get_local_id(0);\n"
|
||||
" int lsize = get_local_size(0);\n"
|
||||
" int i;\n"
|
||||
"\n"
|
||||
" tmp_sum[tid] = 0;\n"
|
||||
" for (i=tid; i<n; i+=lsize)\n"
|
||||
" tmp_sum[tid] += a[i];\n"
|
||||
" \n"
|
||||
" // updated to work for any workgroup size \n"
|
||||
" for (i=hadd(lsize,1); lsize>1; i = hadd(i,1))\n"
|
||||
" {\n"
|
||||
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
|
||||
" if (tid + i < lsize)\n"
|
||||
" tmp_sum[tid] += tmp_sum[tid + i];\n"
|
||||
" lsize = i; \n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" //no barrier is required here because last person to write to tmp_sum[0] was tid 0 \n"
|
||||
" if (tid == 0)\n"
|
||||
" *sum = tmp_sum[0];\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static int
|
||||
verify_sum(int *inptr, int *outptr, int n)
|
||||
namespace {
|
||||
const char *barrier_kernel_code = R"(
|
||||
__kernel void compute_sum(__global int *a, int n, __global int *tmp_sum,
|
||||
__global int *sum)
|
||||
{
|
||||
int r = 0;
|
||||
int i;
|
||||
int tid = get_local_id(0);
|
||||
int lsize = get_local_size(0);
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
r += inptr[i];
|
||||
}
|
||||
tmp_sum[tid] = 0;
|
||||
for (i = tid; i < n; i += lsize) tmp_sum[tid] += a[i];
|
||||
|
||||
if (r != outptr[0])
|
||||
// updated to work for any workgroup size
|
||||
for (i = hadd(lsize, 1); lsize > 1; i = hadd(i, 1))
|
||||
{
|
||||
log_error("BARRIER test failed\n");
|
||||
return -1;
|
||||
BARRIER(CLK_GLOBAL_MEM_FENCE);
|
||||
if (tid + i < lsize) tmp_sum[tid] += tmp_sum[tid + i];
|
||||
lsize = i;
|
||||
}
|
||||
|
||||
log_info("BARRIER test passed\n");
|
||||
return 0;
|
||||
// no barrier is required here because last person to write to tmp_sum[0]
|
||||
// was tid 0
|
||||
if (tid == 0) *sum = tmp_sum[0];
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
void generate_random_inputs(std::vector<cl_int> &v)
|
||||
{
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
auto random_generator = [&seed]() {
|
||||
return static_cast<cl_int>(
|
||||
get_random_float(-0x01000000, 0x01000000, seed));
|
||||
};
|
||||
|
||||
std::generate(v.begin(), v.end(), random_generator);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_barrier(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
int test_barrier_common(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements,
|
||||
std::string barrier_str)
|
||||
{
|
||||
cl_mem streams[3];
|
||||
cl_int *input_ptr = NULL, *output_ptr = NULL;
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
size_t global_threads[3];
|
||||
size_t local_threads[3];
|
||||
int err;
|
||||
int i;
|
||||
size_t max_local_workgroup_size[3];
|
||||
size_t max_threadgroup_size = 0;
|
||||
MTdata d;
|
||||
clMemWrapper streams[3];
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &barrier_kernel_code, "compute_sum" );
|
||||
cl_int output;
|
||||
int err;
|
||||
|
||||
size_t max_threadgroup_size = 0;
|
||||
std::string build_options = std::string("-DBARRIER=") + barrier_str;
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
&barrier_kernel_code, "compute_sum",
|
||||
build_options.c_str());
|
||||
test_error(err, "Failed to build kernel/program.");
|
||||
|
||||
err = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE,
|
||||
sizeof(max_threadgroup_size), &max_threadgroup_size, NULL);
|
||||
test_error(err, "clGetKernelWorkgroupInfo failed.");
|
||||
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(max_local_workgroup_size), max_local_workgroup_size, NULL);
|
||||
test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES");
|
||||
|
||||
// Pick the minimum of the device and the kernel
|
||||
if (max_threadgroup_size > max_local_workgroup_size[0])
|
||||
max_threadgroup_size = max_local_workgroup_size[0];
|
||||
err = get_max_allowed_1d_work_group_size_on_device(device, kernel,
|
||||
&max_threadgroup_size);
|
||||
test_error(err, "get_max_allowed_1d_work_group_size_on_device failed.");
|
||||
|
||||
// work group size must divide evenly into the global size
|
||||
while( num_elements % max_threadgroup_size )
|
||||
max_threadgroup_size--;
|
||||
while (num_elements % max_threadgroup_size) max_threadgroup_size--;
|
||||
|
||||
input_ptr = (int*)malloc(sizeof(int) * num_elements);
|
||||
output_ptr = (int*)malloc(sizeof(int));
|
||||
std::vector<cl_int> input(num_elements);
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * num_elements, NULL, &err);
|
||||
sizeof(cl_int) * num_elements, nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed.");
|
||||
streams[1] =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &err);
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int),
|
||||
nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed.");
|
||||
streams[2] =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * max_threadgroup_size, NULL, &err);
|
||||
sizeof(cl_int) * max_threadgroup_size, nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed.");
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
for (i=0; i<num_elements; i++)
|
||||
input_ptr[i] = (int)get_random_float(-0x01000000, 0x01000000, d);
|
||||
free_mtdata(d); d = NULL;
|
||||
generate_random_inputs(input);
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, sizeof(cl_int)*num_elements, (void *)input_ptr, 0, NULL, NULL);
|
||||
err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0,
|
||||
sizeof(cl_int) * num_elements, input.data(), 0,
|
||||
nullptr, nullptr);
|
||||
test_error(err, "clEnqueueWriteBuffer failed.");
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof num_elements, &num_elements);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof streams[2], &streams[2]);
|
||||
err |= clSetKernelArg(kernel, 3, sizeof streams[1], &streams[1]);
|
||||
err = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof(num_elements), &num_elements);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof(streams[2]), &streams[2]);
|
||||
err |= clSetKernelArg(kernel, 3, sizeof(streams[1]), &streams[1]);
|
||||
test_error(err, "clSetKernelArg failed.");
|
||||
|
||||
global_threads[0] = max_threadgroup_size;
|
||||
local_threads[0] = max_threadgroup_size;
|
||||
size_t global_threads[] = { max_threadgroup_size };
|
||||
size_t local_threads[] = { max_threadgroup_size };
|
||||
|
||||
err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, global_threads, local_threads, 0, NULL, NULL );
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, global_threads,
|
||||
local_threads, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed.");
|
||||
|
||||
err = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof(cl_int), (void *)output_ptr, 0, NULL, NULL );
|
||||
err = clEnqueueReadBuffer(queue, streams[1], true, 0, sizeof(cl_int),
|
||||
&output, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueReadBuffer failed.");
|
||||
|
||||
err = verify_sum(input_ptr, output_ptr, num_elements);
|
||||
|
||||
|
||||
// cleanup
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseMemObject(streams[2]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
free(input_ptr);
|
||||
free(output_ptr);
|
||||
if (std::accumulate(input.begin(), input.end(), 0) != output)
|
||||
{
|
||||
log_error("%s test failed\n", barrier_str.c_str());
|
||||
err = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("%s test passed\n", barrier_str.c_str());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
int test_barrier(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_barrier_common(device, context, queue, num_elements, "barrier");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int test_wg_barrier(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return test_barrier_common(device, context, queue, num_elements,
|
||||
"work_group_barrier");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -21,41 +21,44 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
const char *constant_kernel_code =
|
||||
"__kernel void constant_kernel(__global float *out, __constant float *tmpF, __constant int *tmpI)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" float ftmp = tmpF[tid]; \n"
|
||||
" float Itmp = tmpI[tid]; \n"
|
||||
" out[tid] = ftmp * Itmp; \n"
|
||||
"}\n";
|
||||
|
||||
const char *loop_constant_kernel_code =
|
||||
"kernel void loop_constant_kernel(global float *out, constant float *i_pos, int num)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
" float sum = 0;\n"
|
||||
" for (int i = 0; i < num; i++) {\n"
|
||||
" float pos = i_pos[i*3];\n"
|
||||
" sum += pos;\n"
|
||||
" }\n"
|
||||
" out[tid] = sum;\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static int
|
||||
verify(cl_float *tmpF, cl_int *tmpI, cl_float *out, int n)
|
||||
namespace {
|
||||
const char* constant_kernel_code = R"(
|
||||
__kernel void constant_kernel(__global float *out, __constant float *tmpF, __constant int *tmpI)
|
||||
{
|
||||
int i;
|
||||
int tid = get_global_id(0);
|
||||
|
||||
for (i=0; i < n; i++)
|
||||
float ftmp = tmpF[tid];
|
||||
float Itmp = tmpI[tid];
|
||||
out[tid] = ftmp * Itmp;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* loop_constant_kernel_code = R"(
|
||||
kernel void loop_constant_kernel(global float *out, constant float *i_pos, int num)
|
||||
{
|
||||
int tid = get_global_id(0);
|
||||
float sum = 0;
|
||||
for (int i = 0; i < num; i++) {
|
||||
float pos = i_pos[i*3];
|
||||
sum += pos;
|
||||
}
|
||||
out[tid] = sum;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
int verify(std::vector<cl_float>& tmpF, std::vector<cl_int>& tmpI,
|
||||
std::vector<cl_float>& out)
|
||||
{
|
||||
for (int i = 0; i < out.size(); i++)
|
||||
{
|
||||
float f = tmpF[i] * tmpI[i];
|
||||
if( out[i] != f )
|
||||
if (out[i] != f)
|
||||
{
|
||||
log_error("CONSTANT test failed\n");
|
||||
return -1;
|
||||
|
|
@ -66,214 +69,172 @@ verify(cl_float *tmpF, cl_int *tmpI, cl_float *out, int n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
verify_loop_constant(const cl_float *tmp, cl_float *out, cl_int l, int n)
|
||||
int verify_loop_constant(const std::vector<cl_float>& tmp,
|
||||
std::vector<cl_float>& out, cl_int l)
|
||||
{
|
||||
int i;
|
||||
cl_int j;
|
||||
for (i=0; i < n; i++)
|
||||
{
|
||||
float sum = 0;
|
||||
for (j=0; j < l; ++j)
|
||||
sum += tmp[j*3];
|
||||
float sum = 0;
|
||||
for (int j = 0; j < l; ++j) sum += tmp[j * 3];
|
||||
|
||||
if( out[i] != sum )
|
||||
{
|
||||
log_error("loop CONSTANT test failed\n");
|
||||
return -1;
|
||||
}
|
||||
auto predicate = [&sum](cl_float elem) { return sum != elem; };
|
||||
|
||||
if (std::any_of(out.cbegin(), out.cend(), predicate))
|
||||
{
|
||||
log_error("loop CONSTANT test failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("loop CONSTANT test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_constant(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
template <typename T> void generate_random_inputs(std::vector<T>& v)
|
||||
{
|
||||
cl_mem streams[3];
|
||||
cl_int *tmpI;
|
||||
cl_float *tmpF, *out;
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
size_t global_threads[3];
|
||||
int err;
|
||||
unsigned int i;
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
auto random_generator = [&seed]() {
|
||||
return static_cast<T>(get_random_float(-0x02000000, 0x02000000, seed));
|
||||
};
|
||||
|
||||
std::generate(v.begin(), v.end(), random_generator);
|
||||
}
|
||||
}
|
||||
|
||||
int test_constant(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
clMemWrapper streams[3];
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
size_t global_threads[3];
|
||||
int err;
|
||||
cl_ulong maxSize, maxGlobalSize, maxAllocSize;
|
||||
size_t num_floats, num_ints, constant_values;
|
||||
MTdata d;
|
||||
RoundingMode oldRoundMode;
|
||||
RoundingMode oldRoundMode;
|
||||
int isRTZ = 0;
|
||||
|
||||
/* Verify our test buffer won't be bigger than allowed */
|
||||
err = clGetDeviceInfo( device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof( maxSize ), &maxSize, 0 );
|
||||
test_error( err, "Unable to get max constant buffer size" );
|
||||
/* Verify our test buffer won't be bigger than allowed */
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
|
||||
sizeof(maxSize), &maxSize, 0);
|
||||
test_error(err, "Unable to get max constant buffer size");
|
||||
log_info("Device reports CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE %llu bytes.\n",
|
||||
maxSize);
|
||||
|
||||
log_info("Device reports CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE %llu bytes.\n", maxSize);
|
||||
|
||||
// Limit test buffer size to 1/4 of CL_DEVICE_GLOBAL_MEM_SIZE
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(maxGlobalSize), &maxGlobalSize, 0);
|
||||
test_error(err, "Unable to get CL_DEVICE_GLOBAL_MEM_SIZE");
|
||||
// Limit test buffer size to 1/4 of CL_DEVICE_GLOBAL_MEM_SIZE
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE,
|
||||
sizeof(maxGlobalSize), &maxGlobalSize, 0);
|
||||
test_error(err, "Unable to get CL_DEVICE_GLOBAL_MEM_SIZE");
|
||||
|
||||
if (maxSize > maxGlobalSize / 4)
|
||||
maxSize = maxGlobalSize / 4;
|
||||
maxSize = std::min(maxSize, maxGlobalSize / 4);
|
||||
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE , sizeof(maxAllocSize), &maxAllocSize, 0);
|
||||
test_error(err, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE ");
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
|
||||
sizeof(maxAllocSize), &maxAllocSize, 0);
|
||||
test_error(err, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE");
|
||||
|
||||
if (maxSize > maxAllocSize)
|
||||
maxSize = maxAllocSize;
|
||||
|
||||
maxSize/=4;
|
||||
num_ints = (size_t)maxSize/sizeof(cl_int);
|
||||
num_floats = (size_t)maxSize/sizeof(cl_float);
|
||||
if (num_ints >= num_floats) {
|
||||
constant_values = num_floats;
|
||||
} else {
|
||||
constant_values = num_ints;
|
||||
}
|
||||
maxSize = std::min(maxSize, maxAllocSize);
|
||||
|
||||
log_info("Test will attempt to use %lu bytes with one %lu byte constant int buffer and one %lu byte constant float buffer.\n",
|
||||
constant_values*sizeof(cl_int) + constant_values*sizeof(cl_float), constant_values*sizeof(cl_int), constant_values*sizeof(cl_float));
|
||||
maxSize /= 4;
|
||||
num_ints = static_cast<size_t>(maxSize / sizeof(cl_int));
|
||||
num_floats = static_cast<size_t>(maxSize / sizeof(cl_float));
|
||||
constant_values = std::min(num_floats, num_ints);
|
||||
|
||||
tmpI = (cl_int*)malloc(sizeof(cl_int) * constant_values);
|
||||
tmpF = (cl_float*)malloc(sizeof(cl_float) * constant_values);
|
||||
out = (cl_float*)malloc(sizeof(cl_float) * constant_values);
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_float) * constant_values, NULL, NULL);
|
||||
if (!streams[0])
|
||||
{
|
||||
log_error("clCreateBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_float) * constant_values, NULL, NULL);
|
||||
if (!streams[1])
|
||||
{
|
||||
log_error("clCreateBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
streams[2] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * constant_values, NULL, NULL);
|
||||
if (!streams[2])
|
||||
{
|
||||
log_error("clCreateBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
for (i=0; i<constant_values; i++) {
|
||||
tmpI[i] = (int)get_random_float(-0x02000000, 0x02000000, d);
|
||||
tmpF[i] = get_random_float(-0x02000000, 0x02000000, d);
|
||||
}
|
||||
free_mtdata(d); d = NULL;
|
||||
log_info(
|
||||
"Test will attempt to use %lu bytes with one %lu byte constant int "
|
||||
"buffer and one %lu byte constant float buffer.\n",
|
||||
constant_values * sizeof(cl_int) + constant_values * sizeof(cl_float),
|
||||
constant_values * sizeof(cl_int), constant_values * sizeof(cl_float));
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0, sizeof(cl_float)*constant_values, (void *)tmpF, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clWriteArray failed\n");
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0, sizeof(cl_int)*constant_values, (void *)tmpI, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clWriteArray failed\n");
|
||||
return -1;
|
||||
}
|
||||
std::vector<cl_int> tmpI(constant_values);
|
||||
std::vector<cl_float> tmpF(constant_values);
|
||||
std::vector<cl_float> out(constant_values);
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &constant_kernel_code, "constant_kernel" );
|
||||
if (err) {
|
||||
log_error("Failed to create kernel and program: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
streams[0] =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_float) * constant_values, nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
streams[1] =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_float) * constant_values, nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
streams[2] =
|
||||
clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * constant_values, nullptr, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
generate_random_inputs(tmpI);
|
||||
generate_random_inputs(tmpF);
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[1], CL_TRUE, 0,
|
||||
sizeof(cl_float) * constant_values, tmpF.data(),
|
||||
0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueWriteBuffer failed");
|
||||
err = clEnqueueWriteBuffer(queue, streams[2], CL_TRUE, 0,
|
||||
sizeof(cl_int) * constant_values, tmpI.data(), 0,
|
||||
nullptr, nullptr);
|
||||
test_error(err, "clEnqueueWriteBuffer faile.");
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
&constant_kernel_code, "constant_kernel");
|
||||
test_error(err, "Failed to create kernel and program");
|
||||
|
||||
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(kernel, 2, sizeof streams[2], &streams[2]);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArgs failed\n");
|
||||
return -1;
|
||||
}
|
||||
test_error(err, "clSetKernelArgs failed");
|
||||
|
||||
global_threads[0] = constant_values;
|
||||
err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, global_threads, NULL, 0, NULL, NULL );
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueNDRangeKernel failed: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*constant_values, (void *)out, 0, NULL, NULL );
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueReadBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, global_threads,
|
||||
nullptr, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
|
||||
//If we only support rtz mode
|
||||
if( CL_FP_ROUND_TO_ZERO == get_default_rounding_mode(device) && gIsEmbedded)
|
||||
err = clEnqueueReadBuffer(queue, streams[0], CL_TRUE, 0,
|
||||
sizeof(cl_float) * constant_values, out.data(), 0,
|
||||
nullptr, nullptr);
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
// If we only support rtz mode
|
||||
if (CL_FP_ROUND_TO_ZERO == get_default_rounding_mode(device) && gIsEmbedded)
|
||||
{
|
||||
oldRoundMode = set_round(kRoundTowardZero, kfloat);
|
||||
isRTZ = 1;
|
||||
}
|
||||
|
||||
err = verify(tmpF, tmpI, out, (int)constant_values);
|
||||
err = verify(tmpF, tmpI, out);
|
||||
|
||||
if (isRTZ)
|
||||
(void)set_round(oldRoundMode, kfloat);
|
||||
if (isRTZ) (void)set_round(oldRoundMode, kfloat);
|
||||
|
||||
// Loop constant buffer test
|
||||
cl_program loop_program;
|
||||
cl_kernel loop_kernel;
|
||||
clProgramWrapper loop_program;
|
||||
clKernelWrapper loop_kernel;
|
||||
cl_int limit = 2;
|
||||
|
||||
memset(out, 0, sizeof(cl_float) * constant_values);
|
||||
memset(out.data(), 0, sizeof(cl_float) * constant_values);
|
||||
err = create_single_kernel_helper(context, &loop_program, &loop_kernel, 1,
|
||||
&loop_constant_kernel_code, "loop_constant_kernel" );
|
||||
if (err) {
|
||||
log_error("Failed to create loop kernel and program: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
&loop_constant_kernel_code,
|
||||
"loop_constant_kernel");
|
||||
test_error(err, "Failed to create kernel and program");
|
||||
|
||||
err = clSetKernelArg(loop_kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err |= clSetKernelArg(loop_kernel, 1, sizeof streams[1], &streams[1]);
|
||||
err |= clSetKernelArg(loop_kernel, 2, sizeof(limit), &limit);
|
||||
if (err != CL_SUCCESS) {
|
||||
log_error("clSetKernelArgs for loop kernel failed\n");
|
||||
return -1;
|
||||
}
|
||||
test_error(err, "clSetKernelArgs failed");
|
||||
|
||||
err = clEnqueueNDRangeKernel( queue, loop_kernel, 1, NULL, global_threads, NULL, 0, NULL, NULL );
|
||||
if (err != CL_SUCCESS) {
|
||||
log_error("clEnqueueNDRangeKernel failed: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueReadBuffer( queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*constant_values, (void *)out, 0, NULL, NULL );
|
||||
if (err != CL_SUCCESS) {
|
||||
log_error("clEnqueueReadBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueNDRangeKernel(queue, loop_kernel, 1, nullptr, global_threads,
|
||||
nullptr, 0, nullptr, nullptr);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
|
||||
err = verify_loop_constant(tmpF, out, limit, (int)constant_values);
|
||||
err = clEnqueueReadBuffer(queue, streams[0], CL_TRUE, 0,
|
||||
sizeof(cl_float) * constant_values, out.data(), 0,
|
||||
nullptr, nullptr);
|
||||
test_error(err, "clEnqueueReadBuffer failed");
|
||||
|
||||
err = verify_loop_constant(tmpF, out, limit);
|
||||
|
||||
// cleanup
|
||||
clReleaseMemObject(streams[0]);
|
||||
clReleaseMemObject(streams[1]);
|
||||
clReleaseMemObject(streams[2]);
|
||||
clReleaseKernel(kernel);
|
||||
clReleaseProgram(program);
|
||||
clReleaseKernel(loop_kernel);
|
||||
clReleaseProgram(loop_program);
|
||||
free(tmpI);
|
||||
free(tmpF);
|
||||
free(out);
|
||||
|
||||
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
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "harness/conversions.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
|
||||
// clang-format off
|
||||
const cl_mem_flags flag_set[] = {
|
||||
CL_MEM_ALLOC_HOST_PTR,
|
||||
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
|
||||
|
|
@ -33,93 +34,105 @@ const cl_mem_flags flag_set[] = {
|
|||
CL_MEM_COPY_HOST_PTR,
|
||||
0
|
||||
};
|
||||
const char* flag_set_names[] = {
|
||||
|
||||
const char *flag_set_names[] = {
|
||||
"CL_MEM_ALLOC_HOST_PTR",
|
||||
"CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR",
|
||||
"CL_MEM_USE_HOST_PTR",
|
||||
"CL_MEM_COPY_HOST_PTR",
|
||||
"0"
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int error;
|
||||
const size_t bufferSize = 256*256;
|
||||
MTdataHolder d{gRandomSeed};
|
||||
const size_t bufferSize = 256 * 256;
|
||||
MTdataHolder d{ gRandomSeed };
|
||||
BufferOwningPtr<cl_char> hostPtrData{ malloc(bufferSize) };
|
||||
BufferOwningPtr<cl_char> referenceData{ malloc(bufferSize) };
|
||||
BufferOwningPtr<cl_char> finalData{malloc(bufferSize)};
|
||||
BufferOwningPtr<cl_char> finalData{ malloc(bufferSize) };
|
||||
|
||||
for (int src_flag_id=0; src_flag_id < ARRAY_SIZE(flag_set); src_flag_id++)
|
||||
for (size_t src_flag_id = 0; src_flag_id < ARRAY_SIZE(flag_set);
|
||||
src_flag_id++)
|
||||
{
|
||||
clMemWrapper memObject;
|
||||
log_info("Testing with cl_mem_flags src: %s\n", flag_set_names[src_flag_id]);
|
||||
log_info("Testing with cl_mem_flags src: %s\n",
|
||||
flag_set_names[src_flag_id]);
|
||||
|
||||
generate_random_data(kChar, (unsigned int)bufferSize, d, hostPtrData);
|
||||
memcpy(referenceData, hostPtrData, bufferSize);
|
||||
|
||||
void *hostPtr = nullptr;
|
||||
cl_mem_flags flags = flag_set[src_flag_id];
|
||||
bool hasHostPtr = (flags & CL_MEM_USE_HOST_PTR) || (flags & CL_MEM_COPY_HOST_PTR);
|
||||
bool hasHostPtr =
|
||||
(flags & CL_MEM_USE_HOST_PTR) || (flags & CL_MEM_COPY_HOST_PTR);
|
||||
if (hasHostPtr) hostPtr = hostPtrData;
|
||||
memObject = clCreateBuffer(context, flags, bufferSize, hostPtr, &error);
|
||||
test_error( error, "Unable to create testing buffer" );
|
||||
memObject = clCreateBuffer(context, flags, bufferSize, hostPtr, &error);
|
||||
test_error(error, "Unable to create testing buffer");
|
||||
|
||||
if (!hasHostPtr)
|
||||
{
|
||||
error =
|
||||
clEnqueueWriteBuffer(queue, memObject, CL_TRUE, 0, bufferSize,
|
||||
hostPtrData, 0, NULL, NULL);
|
||||
test_error( error, "clEnqueueWriteBuffer failed");
|
||||
clEnqueueWriteBuffer(queue, memObject, CL_TRUE, 0, bufferSize,
|
||||
hostPtrData, 0, NULL, NULL);
|
||||
test_error(error, "clEnqueueWriteBuffer failed");
|
||||
}
|
||||
|
||||
for( int i = 0; i < 128; i++ )
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
|
||||
size_t offset = (size_t)random_in_range( 0, (int)bufferSize - 1, d );
|
||||
size_t length = (size_t)random_in_range( 1, (int)( bufferSize - offset ), d );
|
||||
size_t offset = (size_t)random_in_range(0, (int)bufferSize - 1, d);
|
||||
size_t length =
|
||||
(size_t)random_in_range(1, (int)(bufferSize - offset), d);
|
||||
|
||||
cl_char *mappedRegion = (cl_char *)clEnqueueMapBuffer( queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,
|
||||
offset, length, 0, NULL, NULL, &error );
|
||||
if( error != CL_SUCCESS )
|
||||
{
|
||||
print_error( error, "clEnqueueMapBuffer call failed" );
|
||||
log_error( "\tOffset: %d Length: %d\n", (int)offset, (int)length );
|
||||
return -1;
|
||||
}
|
||||
cl_char *mappedRegion = (cl_char *)clEnqueueMapBuffer(
|
||||
queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, offset,
|
||||
length, 0, NULL, NULL, &error);
|
||||
if (error != CL_SUCCESS)
|
||||
{
|
||||
print_error(error, "clEnqueueMapBuffer call failed");
|
||||
log_error("\tOffset: %d Length: %d\n", (int)offset,
|
||||
(int)length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Write into the region
|
||||
for( size_t j = 0; j < length; j++ )
|
||||
{
|
||||
cl_char spin = (cl_char)genrand_int32( d );
|
||||
// Write into the region
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{
|
||||
cl_char spin = (cl_char)genrand_int32(d);
|
||||
|
||||
// Test read AND write in one swipe
|
||||
cl_char value = mappedRegion[ j ];
|
||||
value = spin - value;
|
||||
mappedRegion[ j ] = value;
|
||||
// Test read AND write in one swipe
|
||||
cl_char value = mappedRegion[j];
|
||||
value = spin - value;
|
||||
mappedRegion[j] = value;
|
||||
|
||||
// Also update the initial data array
|
||||
value = referenceData[offset + j];
|
||||
value = spin - value;
|
||||
referenceData[offset + j] = value;
|
||||
}
|
||||
// Also update the initial data array
|
||||
value = referenceData[offset + j];
|
||||
value = spin - value;
|
||||
referenceData[offset + j] = value;
|
||||
}
|
||||
|
||||
// Unmap
|
||||
error = clEnqueueUnmapMemObject( queue, memObject, mappedRegion, 0, NULL, NULL );
|
||||
test_error( error, "Unable to unmap buffer" );
|
||||
// Unmap
|
||||
error = clEnqueueUnmapMemObject(queue, memObject, mappedRegion, 0,
|
||||
NULL, NULL);
|
||||
test_error(error, "Unable to unmap buffer");
|
||||
}
|
||||
|
||||
// Final validation: read actual values of buffer and compare against our reference
|
||||
error = clEnqueueReadBuffer( queue, memObject, CL_TRUE, 0, bufferSize, finalData, 0, NULL, NULL );
|
||||
test_error( error, "Unable to read results" );
|
||||
// Final validation: read actual values of buffer and compare against
|
||||
// our reference
|
||||
error = clEnqueueReadBuffer(queue, memObject, CL_TRUE, 0, bufferSize,
|
||||
finalData, 0, NULL, NULL);
|
||||
test_error(error, "Unable to read results");
|
||||
|
||||
for( size_t q = 0; q < bufferSize; q++ )
|
||||
for (size_t q = 0; q < bufferSize; q++)
|
||||
{
|
||||
if (referenceData[q] != finalData[q])
|
||||
{
|
||||
log_error(
|
||||
"ERROR: Sample %d did not validate! Got %d, expected %d\n",
|
||||
(int)q, (int)finalData[q], (int)referenceData[q]);
|
||||
"ERROR: Sample %d did not validate! Got %d, expected %d\n",
|
||||
(int)q, (int)finalData[q], (int)referenceData[q]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -128,112 +141,129 @@ int test_enqueue_map_buffer(cl_device_id deviceID, cl_context context, cl_comman
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_enqueue_map_image(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
int test_enqueue_map_image(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int error;
|
||||
cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT32 };
|
||||
const size_t imageSize = 256;
|
||||
const size_t imageDataSize = imageSize * imageSize * 4 * sizeof(cl_uint);
|
||||
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT( deviceID )
|
||||
PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
|
||||
|
||||
BufferOwningPtr<cl_uint> hostPtrData{ malloc(imageDataSize) };
|
||||
BufferOwningPtr<cl_uint> referenceData{ malloc(imageDataSize) };
|
||||
BufferOwningPtr<cl_uint> finalData{malloc(imageDataSize)};
|
||||
BufferOwningPtr<cl_uint> finalData{ malloc(imageDataSize) };
|
||||
|
||||
MTdataHolder d{gRandomSeed};
|
||||
for (int src_flag_id=0; src_flag_id < ARRAY_SIZE(flag_set); src_flag_id++) {
|
||||
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,
|
||||
hostPtrData);
|
||||
memcpy(referenceData, hostPtrData, imageDataSize);
|
||||
|
||||
cl_mem_flags flags = flag_set[src_flag_id];
|
||||
bool hasHostPtr = (flags & CL_MEM_USE_HOST_PTR) || (flags & CL_MEM_COPY_HOST_PTR);
|
||||
void *hostPtr = nullptr;
|
||||
if (hasHostPtr) hostPtr = hostPtrData;
|
||||
memObject = create_image_2d(context, CL_MEM_READ_WRITE | flags, &format,
|
||||
imageSize, imageSize, 0, hostPtr, &error );
|
||||
test_error( error, "Unable to create testing buffer" );
|
||||
|
||||
if (!hasHostPtr) {
|
||||
size_t write_origin[3]={0,0,0}, write_region[3]={imageSize, imageSize, 1};
|
||||
error =
|
||||
clEnqueueWriteImage(queue, memObject, CL_TRUE, write_origin, write_region,
|
||||
0, 0, hostPtrData, 0, NULL, NULL);
|
||||
test_error( error, "Unable to write to testing buffer" );
|
||||
}
|
||||
|
||||
for( int i = 0; i < 128; i++ )
|
||||
MTdataHolder d{ gRandomSeed };
|
||||
for (size_t src_flag_id = 0; src_flag_id < ARRAY_SIZE(flag_set);
|
||||
src_flag_id++)
|
||||
{
|
||||
clMemWrapper memObject;
|
||||
log_info("Testing with cl_mem_flags src: %s\n",
|
||||
flag_set_names[src_flag_id]);
|
||||
|
||||
size_t offset[3], region[3];
|
||||
size_t rowPitch;
|
||||
generate_random_data(kUInt, (unsigned int)(imageSize * imageSize * 4),
|
||||
d, hostPtrData);
|
||||
memcpy(referenceData, hostPtrData, imageDataSize);
|
||||
|
||||
offset[ 0 ] = (size_t)random_in_range( 0, (int)imageSize - 1, d );
|
||||
region[ 0 ] = (size_t)random_in_range( 1, (int)( imageSize - offset[ 0 ] - 1), d );
|
||||
offset[ 1 ] = (size_t)random_in_range( 0, (int)imageSize - 1, d );
|
||||
region[ 1 ] = (size_t)random_in_range( 1, (int)( imageSize - offset[ 1 ] - 1), d );
|
||||
offset[ 2 ] = 0;
|
||||
region[ 2 ] = 1;
|
||||
cl_uint *mappedRegion = (cl_uint *)clEnqueueMapImage( queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,
|
||||
offset, region, &rowPitch, NULL, 0, NULL, NULL, &error );
|
||||
if( error != CL_SUCCESS )
|
||||
{
|
||||
print_error( error, "clEnqueueMapImage call failed" );
|
||||
log_error( "\tOffset: %d,%d Region: %d,%d\n", (int)offset[0], (int)offset[1], (int)region[0], (int)region[1] );
|
||||
return -1;
|
||||
}
|
||||
cl_mem_flags flags = flag_set[src_flag_id];
|
||||
bool hasHostPtr =
|
||||
(flags & CL_MEM_USE_HOST_PTR) || (flags & CL_MEM_COPY_HOST_PTR);
|
||||
void *hostPtr = nullptr;
|
||||
if (hasHostPtr) hostPtr = hostPtrData;
|
||||
memObject = create_image_2d(context, CL_MEM_READ_WRITE | flags, &format,
|
||||
imageSize, imageSize, 0, hostPtr, &error);
|
||||
test_error(error, "Unable to create testing buffer");
|
||||
|
||||
// Write into the region
|
||||
cl_uint *mappedPtr = mappedRegion;
|
||||
for( size_t y = 0; y < region[ 1 ]; y++ )
|
||||
{
|
||||
for( size_t x = 0; x < region[ 0 ] * 4; x++ )
|
||||
if (!hasHostPtr)
|
||||
{
|
||||
cl_int spin = (cl_int)random_in_range( 16, 1024, d );
|
||||
|
||||
cl_int value;
|
||||
// Test read AND write in one swipe
|
||||
value = mappedPtr[ ( y * rowPitch/sizeof(cl_uint) ) + x ];
|
||||
value = spin - value;
|
||||
mappedPtr[ ( y * rowPitch/sizeof(cl_uint) ) + x ] = value;
|
||||
|
||||
// Also update the initial data array
|
||||
value =
|
||||
referenceData[((offset[1] + y) * imageSize + offset[0]) * 4 + x];
|
||||
value = spin - value;
|
||||
referenceData[((offset[1] + y) * imageSize + offset[0]) * 4 + x] =
|
||||
value;
|
||||
size_t write_origin[3] = { 0, 0, 0 },
|
||||
write_region[3] = { imageSize, imageSize, 1 };
|
||||
error = clEnqueueWriteImage(queue, memObject, CL_TRUE, write_origin,
|
||||
write_region, 0, 0, hostPtrData, 0,
|
||||
NULL, NULL);
|
||||
test_error(error, "Unable to write to testing buffer");
|
||||
}
|
||||
}
|
||||
|
||||
// Unmap
|
||||
error = clEnqueueUnmapMemObject( queue, memObject, mappedRegion, 0, NULL, NULL );
|
||||
test_error( error, "Unable to unmap buffer" );
|
||||
}
|
||||
|
||||
// Final validation: read actual values of buffer and compare against our reference
|
||||
size_t finalOrigin[3] = { 0, 0, 0 }, finalRegion[3] = { imageSize, imageSize, 1 };
|
||||
error = clEnqueueReadImage( queue, memObject, CL_TRUE, finalOrigin, finalRegion, 0, 0, finalData, 0, NULL, NULL );
|
||||
test_error( error, "Unable to read results" );
|
||||
|
||||
for( size_t q = 0; q < imageSize * imageSize * 4; q++ )
|
||||
{
|
||||
if (referenceData[q] != finalData[q])
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
log_error("ERROR: Sample %d (coord %d,%d) did not validate! Got "
|
||||
"%d, expected %d\n",
|
||||
(int)q, (int)((q / 4) % imageSize),
|
||||
(int)((q / 4) / imageSize), (int)finalData[q],
|
||||
(int)referenceData[q]);
|
||||
return -1;
|
||||
|
||||
size_t offset[3], region[3];
|
||||
size_t rowPitch;
|
||||
|
||||
offset[0] = (size_t)random_in_range(0, (int)imageSize - 1, d);
|
||||
region[0] =
|
||||
(size_t)random_in_range(1, (int)(imageSize - offset[0] - 1), d);
|
||||
offset[1] = (size_t)random_in_range(0, (int)imageSize - 1, d);
|
||||
region[1] =
|
||||
(size_t)random_in_range(1, (int)(imageSize - offset[1] - 1), d);
|
||||
offset[2] = 0;
|
||||
region[2] = 1;
|
||||
cl_uint *mappedRegion = (cl_uint *)clEnqueueMapImage(
|
||||
queue, memObject, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, offset,
|
||||
region, &rowPitch, NULL, 0, NULL, NULL, &error);
|
||||
if (error != CL_SUCCESS)
|
||||
{
|
||||
print_error(error, "clEnqueueMapImage call failed");
|
||||
log_error("\tOffset: %d,%d Region: %d,%d\n", (int)offset[0],
|
||||
(int)offset[1], (int)region[0], (int)region[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Write into the region
|
||||
cl_uint *mappedPtr = mappedRegion;
|
||||
for (size_t y = 0; y < region[1]; y++)
|
||||
{
|
||||
for (size_t x = 0; x < region[0] * 4; x++)
|
||||
{
|
||||
cl_int spin = (cl_int)random_in_range(16, 1024, d);
|
||||
|
||||
cl_int value;
|
||||
// Test read AND write in one swipe
|
||||
value = mappedPtr[(y * rowPitch / sizeof(cl_uint)) + x];
|
||||
value = spin - value;
|
||||
mappedPtr[(y * rowPitch / sizeof(cl_uint)) + x] = value;
|
||||
|
||||
// Also update the initial data array
|
||||
value =
|
||||
referenceData[((offset[1] + y) * imageSize + offset[0])
|
||||
* 4
|
||||
+ x];
|
||||
value = spin - value;
|
||||
referenceData[((offset[1] + y) * imageSize + offset[0]) * 4
|
||||
+ x] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Unmap
|
||||
error = clEnqueueUnmapMemObject(queue, memObject, mappedRegion, 0,
|
||||
NULL, NULL);
|
||||
test_error(error, "Unable to unmap buffer");
|
||||
}
|
||||
}
|
||||
} // cl_mem_flags
|
||||
|
||||
// Final validation: read actual values of buffer and compare against
|
||||
// our reference
|
||||
size_t finalOrigin[3] = { 0, 0, 0 },
|
||||
finalRegion[3] = { imageSize, imageSize, 1 };
|
||||
error = clEnqueueReadImage(queue, memObject, CL_TRUE, finalOrigin,
|
||||
finalRegion, 0, 0, finalData, 0, NULL, NULL);
|
||||
test_error(error, "Unable to read results");
|
||||
|
||||
for (size_t q = 0; q < imageSize * imageSize * 4; q++)
|
||||
{
|
||||
if (referenceData[q] != finalData[q])
|
||||
{
|
||||
log_error(
|
||||
"ERROR: Sample %d (coord %d,%d) did not validate! Got "
|
||||
"%d, expected %d\n",
|
||||
(int)q, (int)((q / 4) % imageSize),
|
||||
(int)((q / 4) / imageSize), (int)finalData[q],
|
||||
(int)referenceData[q]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} // cl_mem_flags
|
||||
|
||||
return 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
|
||||
|
|
@ -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.
|
||||
//
|
||||
// Copyright (c) 2023 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
|
||||
|
|
@ -13,6 +13,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include <cmath>
|
||||
using std::isnan;
|
||||
#include "harness/compat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
@ -20,131 +22,112 @@
|
|||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "procs.h"
|
||||
#include "harness/conversions.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define DECLARE_S2V_IDENT_KERNEL(srctype,dsttype,size) \
|
||||
"__kernel void test_conversion(__global " srctype " *sourceValues, __global " dsttype #size " *destValues )\n" \
|
||||
"{\n" \
|
||||
" int tid = get_global_id(0);\n" \
|
||||
" " srctype " src = sourceValues[tid];\n" \
|
||||
"\n" \
|
||||
" destValues[tid] = (" dsttype #size ")src;\n" \
|
||||
"\n" \
|
||||
"{\n" \
|
||||
" int tid = get_global_id(0);\n" \
|
||||
" " srctype " src = sourceValues[tid];\n" \
|
||||
"\n" \
|
||||
" destValues[tid] = (" dsttype #size ")src;\n" \
|
||||
"\n" \
|
||||
"}\n"
|
||||
|
||||
#define DECLARE_S2V_IDENT_KERNELS(srctype,dsttype) \
|
||||
{ \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,2), \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,4), \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,8), \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype,#dsttype,16) \
|
||||
}
|
||||
#define DECLARE_S2V_IDENT_KERNELS(srctype, dsttype) \
|
||||
{ \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype, #dsttype, 2), \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype, #dsttype, 4), \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype, #dsttype, 8), \
|
||||
DECLARE_S2V_IDENT_KERNEL(srctype, #dsttype, 16) \
|
||||
}
|
||||
|
||||
#define DECLARE_EMPTY { NULL, NULL, NULL, NULL, NULL }
|
||||
#define DECLARE_EMPTY \
|
||||
{ \
|
||||
NULL, NULL, NULL, NULL, NULL \
|
||||
}
|
||||
|
||||
/* Note: the next four arrays all must match in order and size to the ExplicitTypes enum in conversions.h!!! */
|
||||
/* Note: the next four arrays all must match in order and size to the
|
||||
* ExplicitTypes enum in conversions.h!!! */
|
||||
|
||||
#define DECLARE_S2V_IDENT_KERNELS_SET(srctype) \
|
||||
{ \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,bool), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,char), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,uchar), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned char), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,short), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,ushort), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned short), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,int), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,uint), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned int), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,long), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,ulong), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,unsigned long), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype,float), \
|
||||
DECLARE_EMPTY \
|
||||
}
|
||||
#define DECLARE_S2V_IDENT_KERNELS_SET(srctype) \
|
||||
{ \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, char), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, uchar), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, short), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, ushort), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, int), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, uint), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, long), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, ulong), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, float), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, half), \
|
||||
DECLARE_S2V_IDENT_KERNELS(#srctype, double) \
|
||||
}
|
||||
|
||||
#define DECLARE_EMPTY_SET \
|
||||
{ \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY \
|
||||
}
|
||||
#define DECLARE_EMPTY_SET \
|
||||
{ \
|
||||
DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY, \
|
||||
DECLARE_EMPTY, DECLARE_EMPTY, DECLARE_EMPTY \
|
||||
}
|
||||
|
||||
#define NUM_VEC_TYPES 11
|
||||
|
||||
/* The overall array */
|
||||
const char * kernel_explicit_s2v_set[kNumExplicitTypes][kNumExplicitTypes][5] = {
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(bool),
|
||||
const char * kernel_explicit_s2v_set[NUM_VEC_TYPES][NUM_VEC_TYPES][5] = {
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(char),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(uchar),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(unsigned char),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(short),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(ushort),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(unsigned short),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(int),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(uint),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(unsigned int),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(long),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(ulong),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(unsigned long),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(float),
|
||||
DECLARE_EMPTY_SET
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(half),
|
||||
DECLARE_S2V_IDENT_KERNELS_SET(double)
|
||||
};
|
||||
|
||||
int test_explicit_s2v_function(cl_device_id deviceID, cl_context context, cl_command_queue queue, const char *programSrc,
|
||||
ExplicitType srcType, unsigned int count, ExplicitType destType, unsigned int vecSize, void *inputData )
|
||||
// clang-format on
|
||||
|
||||
bool IsHalfNaN(cl_half v)
|
||||
{
|
||||
// Extract FP16 exponent and mantissa
|
||||
uint16_t h_exp = (((cl_half)v) >> (CL_HALF_MANT_DIG - 1)) & 0x1F;
|
||||
uint16_t h_mant = ((cl_half)v) & 0x3FF;
|
||||
|
||||
// NaN test
|
||||
return (h_exp == 0x1F && h_mant != 0);
|
||||
}
|
||||
|
||||
int test_explicit_s2v_function(cl_context context, cl_command_queue queue,
|
||||
cl_kernel kernel, ExplicitType srcType,
|
||||
unsigned int count, ExplicitType destType,
|
||||
unsigned int vecSize, void *inputData)
|
||||
{
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
int error;
|
||||
clMemWrapper streams[2];
|
||||
void *outData;
|
||||
unsigned char convertedData[ 8 ]; /* Max type size is 8 bytes */
|
||||
size_t threadSize[3], groupSize[3];
|
||||
unsigned char convertedData[8]; /* Max type size is 8 bytes */
|
||||
unsigned int i, s;
|
||||
unsigned char *inPtr, *outPtr;
|
||||
size_t paramSize, destTypeSize;
|
||||
|
||||
const char* finalProgramSrc[2] = {
|
||||
"", // optional pragma
|
||||
programSrc
|
||||
};
|
||||
|
||||
if (srcType == kDouble || destType == kDouble) {
|
||||
finalProgramSrc[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
|
||||
}
|
||||
|
||||
|
||||
if( programSrc == NULL )
|
||||
return 0;
|
||||
|
||||
paramSize = get_explicit_type_size( srcType );
|
||||
destTypeSize = get_explicit_type_size( destType );
|
||||
|
||||
size_t destStride = destTypeSize * vecSize;
|
||||
|
||||
outData = malloc( destStride * count );
|
||||
|
||||
if( create_single_kernel_helper( context, &program, &kernel, 2, finalProgramSrc, "test_conversion" ) )
|
||||
{
|
||||
log_info( "****** %s%s *******\n", finalProgramSrc[0], finalProgramSrc[1] );
|
||||
return -1;
|
||||
}
|
||||
std::vector<char> outData(destStride * count);
|
||||
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
|
||||
paramSize * count, inputData, &error);
|
||||
|
|
@ -170,11 +153,13 @@ int test_explicit_s2v_function(cl_device_id deviceID, cl_context context, cl_com
|
|||
|
||||
/* Now verify the results. Each value should have been duplicated four times, and we should be able to just
|
||||
do a memcpy instead of relying on the actual type of data */
|
||||
error = clEnqueueReadBuffer( queue, streams[1], CL_TRUE, 0, destStride * count, outData, 0, NULL, NULL );
|
||||
error =
|
||||
clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, destStride * count,
|
||||
outData.data(), 0, NULL, NULL);
|
||||
test_error( error, "Unable to read output values!" );
|
||||
|
||||
inPtr = (unsigned char *)inputData;
|
||||
outPtr = (unsigned char *)outData;
|
||||
outPtr = (unsigned char *)outData.data();
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
|
|
@ -186,6 +171,28 @@ int test_explicit_s2v_function(cl_device_id deviceID, cl_context context, cl_com
|
|||
{
|
||||
if( memcmp( convertedData, outPtr + destTypeSize * s, destTypeSize ) != 0 )
|
||||
{
|
||||
bool isSrcNaN =
|
||||
(((srcType == kHalf)
|
||||
&& IsHalfNaN(*reinterpret_cast<cl_half *>(inPtr)))
|
||||
|| ((srcType == kFloat)
|
||||
&& isnan(*reinterpret_cast<cl_float *>(inPtr)))
|
||||
|| ((srcType == kDouble)
|
||||
&& isnan(*reinterpret_cast<cl_double *>(inPtr))));
|
||||
bool isDestNaN = (((destType == kHalf)
|
||||
&& IsHalfNaN(*reinterpret_cast<cl_half *>(
|
||||
outPtr + destTypeSize * s)))
|
||||
|| ((destType == kFloat)
|
||||
&& isnan(*reinterpret_cast<cl_float *>(
|
||||
outPtr + destTypeSize * s)))
|
||||
|| ((destType == kDouble)
|
||||
&& isnan(*reinterpret_cast<cl_double *>(
|
||||
outPtr + destTypeSize * s))));
|
||||
|
||||
if (isSrcNaN && isDestNaN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int *p = (unsigned int *)outPtr;
|
||||
log_error( "ERROR: Output value %d:%d does not validate for size %d:%d!\n", i, s, vecSize, (int)destTypeSize );
|
||||
log_error( " Input: 0x%0*x\n", (int)( paramSize * 2 ), *(unsigned int *)inPtr & ( 0xffffffff >> ( 32 - paramSize * 8 ) ) );
|
||||
|
|
@ -196,179 +203,185 @@ int test_explicit_s2v_function(cl_device_id deviceID, cl_context context, cl_com
|
|||
inPtr += paramSize;
|
||||
outPtr += destStride;
|
||||
}
|
||||
|
||||
free( outData );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_function_set(cl_device_id deviceID, cl_context context, cl_command_queue queue, ExplicitType srcType,
|
||||
unsigned int count, void *inputData )
|
||||
struct TypesIterator
|
||||
{
|
||||
unsigned int sizes[] = { 2, 4, 8, 16, 0 };
|
||||
int i, dstType, failed = 0;
|
||||
using TypeIter =
|
||||
std::tuple<cl_char, cl_uchar, cl_short, cl_ushort, cl_int, cl_uint,
|
||||
cl_long, cl_ulong, cl_float, cl_half, cl_double>;
|
||||
|
||||
|
||||
for( dstType = kBool; dstType < kNumExplicitTypes; dstType++ )
|
||||
TypesIterator(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue)
|
||||
: dstType(0), srcType(0), context(context), queue(queue)
|
||||
{
|
||||
if( dstType == kDouble && !is_extension_available( deviceID, "cl_khr_fp64" ) )
|
||||
continue;
|
||||
vecTypes = { kChar, kUChar, kShort, kUShort, kInt, kUInt,
|
||||
kLong, kULong, kFloat, kHalf, kDouble };
|
||||
fp16Support = is_extension_available(deviceID, "cl_khr_fp16");
|
||||
fp64Support = is_extension_available(deviceID, "cl_khr_fp64");
|
||||
|
||||
if (( dstType == kLong || dstType == kULong ) && !gHasLong )
|
||||
continue;
|
||||
for_each_src_elem(it);
|
||||
}
|
||||
|
||||
for( i = 0; sizes[i] != 0; i++ )
|
||||
bool skip_type(ExplicitType type)
|
||||
{
|
||||
if ((type == kLong || type == kULong) && !gHasLong)
|
||||
return true;
|
||||
else if (type == kDouble && !fp64Support)
|
||||
return true;
|
||||
else if (type == kHalf && !fp16Support)
|
||||
return true;
|
||||
else if (strchr(get_explicit_type_name(type), ' ') != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <std::size_t Src = 0, typename SrcType>
|
||||
void iterate_src_type(const SrcType &t)
|
||||
{
|
||||
bool doTest = !skip_type(vecTypes[srcType]);
|
||||
if (doTest)
|
||||
{
|
||||
if( dstType != srcType )
|
||||
continue;
|
||||
if( strchr( get_explicit_type_name( (ExplicitType)srcType ), ' ' ) != NULL ||
|
||||
strchr( get_explicit_type_name( (ExplicitType)dstType ), ' ' ) != NULL )
|
||||
continue;
|
||||
SrcType inputData[sample_count];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
generate_random_data(vecTypes[srcType], 128, seed, inputData);
|
||||
|
||||
if( test_explicit_s2v_function( deviceID, context, queue, kernel_explicit_s2v_set[ srcType ][ dstType ][ i ],
|
||||
srcType, count, (ExplicitType)dstType, sizes[ i ], inputData ) != 0 )
|
||||
for_each_dst_elem<0, Src, SrcType>(it, inputData);
|
||||
}
|
||||
|
||||
srcType++;
|
||||
dstType = 0;
|
||||
}
|
||||
|
||||
// crucial to keep it in-sync with ExplicitType
|
||||
bool isExplicitTypeFloating(ExplicitType type) { return (type >= kFloat); }
|
||||
|
||||
template <std::size_t Dst, std::size_t Src, typename SrcType,
|
||||
typename DstType>
|
||||
void iterate_dst_type(const DstType &t, SrcType *inputData)
|
||||
{
|
||||
bool doTest = !skip_type(vecTypes[dstType]);
|
||||
|
||||
doTest = doTest
|
||||
&& ((isExplicitTypeFloating(vecTypes[srcType])
|
||||
&& isExplicitTypeFloating(vecTypes[dstType]))
|
||||
|| (!isExplicitTypeFloating(vecTypes[srcType])
|
||||
&& !isExplicitTypeFloating(vecTypes[dstType])));
|
||||
|
||||
if (doTest)
|
||||
test_explicit_s2v_function_set<SrcType, DstType>(
|
||||
vecTypes[srcType], vecTypes[dstType], inputData);
|
||||
dstType++;
|
||||
}
|
||||
|
||||
template <std::size_t Out = 0, typename... Tp>
|
||||
inline typename std::enable_if<Out == sizeof...(Tp), void>::type
|
||||
for_each_src_elem(
|
||||
const std::tuple<Tp...> &) // Unused arguments are given no names.
|
||||
{}
|
||||
|
||||
template <std::size_t Out = 0, typename... Tp>
|
||||
inline typename std::enable_if < Out<sizeof...(Tp), void>::type
|
||||
for_each_src_elem(const std::tuple<Tp...> &t)
|
||||
{
|
||||
iterate_src_type<Out>(std::get<Out>(t));
|
||||
for_each_src_elem<Out + 1, Tp...>(t);
|
||||
}
|
||||
|
||||
template <std::size_t In = 0, std::size_t Out, typename SrcType,
|
||||
typename... Tp>
|
||||
inline typename std::enable_if<In == sizeof...(Tp), void>::type
|
||||
for_each_dst_elem(const std::tuple<Tp...> &, SrcType *)
|
||||
{}
|
||||
|
||||
template <std::size_t In = 0, std::size_t Out, typename SrcType,
|
||||
typename... Tp>
|
||||
inline typename std::enable_if < In<sizeof...(Tp), void>::type
|
||||
for_each_dst_elem(const std::tuple<Tp...> &t, SrcType *inputData)
|
||||
{
|
||||
iterate_dst_type<In, Out, SrcType>(std::get<In>(t), inputData);
|
||||
for_each_dst_elem<In + 1, Out, SrcType, Tp...>(t, inputData);
|
||||
}
|
||||
|
||||
template <typename SrcType, typename DstType>
|
||||
void test_explicit_s2v_function_set(ExplicitType srcT, ExplicitType dstT,
|
||||
SrcType *inputData)
|
||||
{
|
||||
unsigned int sizes[] = { 2, 4, 8, 16, 0 };
|
||||
|
||||
for (int i = 0; sizes[i] != 0; i++)
|
||||
{
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
|
||||
char pragma[256] = { 0 };
|
||||
const char *finalProgramSrc[2] = {
|
||||
pragma, // optional pragma
|
||||
kernel_explicit_s2v_set[srcType][dstType][i]
|
||||
};
|
||||
|
||||
std::stringstream sstr;
|
||||
if (srcT == kDouble || dstT == kDouble)
|
||||
sstr << "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
|
||||
|
||||
if (srcT == kHalf || dstT == kHalf)
|
||||
sstr << "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n";
|
||||
|
||||
snprintf(pragma, sizeof(pragma), "%s", sstr.str().c_str());
|
||||
|
||||
if (create_single_kernel_helper(context, &program, &kernel, 2,
|
||||
finalProgramSrc, "test_conversion"))
|
||||
{
|
||||
log_error( "ERROR: Explicit cast of scalar %s to vector %s%d FAILED; skipping other %s vector tests\n",
|
||||
get_explicit_type_name(srcType), get_explicit_type_name((ExplicitType)dstType), sizes[i], get_explicit_type_name((ExplicitType)dstType) );
|
||||
failed = -1;
|
||||
break;
|
||||
log_info("****** %s%s *******\n", finalProgramSrc[0],
|
||||
finalProgramSrc[1]);
|
||||
throw std::runtime_error(
|
||||
"create_single_kernel_helper failed\n");
|
||||
}
|
||||
|
||||
if (test_explicit_s2v_function(context, queue, kernel, srcT,
|
||||
sample_count, dstT, sizes[i],
|
||||
inputData)
|
||||
!= 0)
|
||||
{
|
||||
log_error("ERROR: Explicit cast of scalar %s to vector %s%d "
|
||||
"FAILED; skipping other %s vector tests\n",
|
||||
get_explicit_type_name(srcT),
|
||||
get_explicit_type_name(dstT), sizes[i],
|
||||
get_explicit_type_name(dstT));
|
||||
throw std::runtime_error("test_explicit_s2v_function failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
protected:
|
||||
bool fp16Support;
|
||||
bool fp64Support;
|
||||
|
||||
int test_explicit_s2v_char(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
TypeIter it;
|
||||
unsigned int dstType, srcType;
|
||||
cl_context context;
|
||||
cl_command_queue queue;
|
||||
|
||||
std::vector<ExplicitType> vecTypes;
|
||||
|
||||
constexpr static unsigned int sample_count =
|
||||
128; // hardcoded in original test
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int test_explicit_s2v(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
{
|
||||
char data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kChar, 128, seed, data );
|
||||
|
||||
return test_explicit_s2v_function_set( deviceID, context, queue, kChar, 128, data );
|
||||
}
|
||||
|
||||
int test_explicit_s2v_uchar(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
unsigned char data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kUChar, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUChar, 128, data ) != 0 )
|
||||
return -1;
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedChar, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_short(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
short data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kShort, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kShort, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_ushort(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
unsigned short data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kUShort, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUShort, 128, data ) != 0 )
|
||||
return -1;
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedShort, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_int(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
int data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kInt, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kInt, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_uint(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
unsigned int data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kUInt, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUInt, 128, data ) != 0 )
|
||||
return -1;
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedInt, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_long(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_long data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kLong, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kLong, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_ulong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_ulong data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kULong, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kULong, 128, data ) != 0 )
|
||||
return -1;
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kUnsignedLong, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_explicit_s2v_float(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
float data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
generate_random_data( kFloat, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kFloat, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int test_explicit_s2v_double(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
double data[128];
|
||||
RandomSeed seed(gRandomSeed);
|
||||
|
||||
if( !is_extension_available( deviceID, "cl_khr_fp64" ) ) {
|
||||
log_info("Extension cl_khr_fp64 not supported. Skipping test.\n");
|
||||
return 0;
|
||||
try
|
||||
{
|
||||
TypesIterator(deviceID, context, queue);
|
||||
} catch (const std::runtime_error &e)
|
||||
{
|
||||
log_error("%s", e.what());
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
generate_random_data( kDouble, 128, seed, data );
|
||||
|
||||
if( test_explicit_s2v_function_set( deviceID, context, queue, kDouble, 128, data ) != 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
const char *float2int_kernel_code =
|
||||
"__kernel void test_float2int(__global float *src, __global int *dst)\n"
|
||||
"{\n"
|
||||
" int tid = get_global_id(0);\n"
|
||||
"\n"
|
||||
" dst[tid] = (int)src[tid];\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
int
|
||||
verify_float2int(cl_float *inptr, cl_int *outptr, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
if (outptr[i] != (int)inptr[i])
|
||||
{
|
||||
log_error("FLOAT2INT test failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("FLOAT2INT test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_float2int(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
cl_mem streams[2];
|
||||
cl_float *input_ptr;
|
||||
cl_int *output_ptr;
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
void *values[2];
|
||||
size_t threads[1];
|
||||
int err;
|
||||
int i;
|
||||
MTdata d;
|
||||
|
||||
input_ptr = (cl_float*)malloc(sizeof(cl_float) * num_elements);
|
||||
output_ptr = (cl_int*)malloc(sizeof(cl_int) * num_elements);
|
||||
streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_float) * num_elements, NULL, NULL);
|
||||
if (!streams[0])
|
||||
{
|
||||
log_error("clCreateBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int) * num_elements, NULL, NULL);
|
||||
if (!streams[1])
|
||||
{
|
||||
log_error("clCreateBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = init_genrand( gRandomSeed );
|
||||
for (i=0; i<num_elements; i++)
|
||||
input_ptr[i] = get_random_float(-MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), MAKE_HEX_FLOAT( 0x1.0p31f, 0x1, 31), d);
|
||||
free_mtdata(d); d = NULL;
|
||||
|
||||
err = clEnqueueWriteBuffer(queue, streams[0], CL_TRUE, 0, sizeof(cl_float)*num_elements, (void *)input_ptr, 0, NULL, NULL);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clWriteArray failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = create_single_kernel_helper(context, &program, &kernel, 1, &float2int_kernel_code, "test_float2int");
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("create_single_kernel_helper failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
values[0] = streams[0];
|
||||
values[1] = streams[1];
|
||||
err = clSetKernelArg(kernel, 0, sizeof streams[0], &streams[0]);
|
||||
err = clSetKernelArg(kernel, 1, sizeof streams[1], &streams[1]);
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clSetKernelArgs failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
threads[0] = (size_t)num_elements;
|
||||
err = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, NULL, 0, NULL, NULL );
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueNDRangeKernel failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = clEnqueueReadBuffer( queue, streams[1], true, 0, sizeof(cl_int)*num_elements, (void *)output_ptr, 0, NULL, NULL );
|
||||
if (err != CL_SUCCESS)
|
||||
{
|
||||
log_error("clEnqueueReadBuffer failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = verify_float2int(input_ptr, output_ptr, num_elements);
|
||||
|
||||
// cleanup
|
||||
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