Compare commits
769 commits
main
...
upstream/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9d4078a0b | ||
|
|
f209922722 | ||
|
|
2d165eee74 | ||
|
|
f30a191978 | ||
|
|
3ab4d8aab2 | ||
|
|
dec5644112 | ||
|
|
110799bb67 | ||
|
|
b011fb26d9 | ||
|
|
455c7b0504 | ||
|
|
d3b043a891 | ||
|
|
3f7889bdbd | ||
|
|
9917ed2790 | ||
|
|
8aa47754de | ||
|
|
9fc0d23b4c | ||
|
|
90524879e4 | ||
|
|
33846e6673 | ||
|
|
4ce3d8968a | ||
|
|
829e91663a | ||
|
|
e96edaef8b | ||
|
|
0abec2f49a | ||
|
|
051b82b7e9 | ||
|
|
42b4bca510 | ||
|
|
5930d45fc6 | ||
|
|
78bd3ddece | ||
|
|
a429ce771e | ||
|
|
4e00778b93 | ||
|
|
88953edf6c | ||
|
|
004bc4a82d | ||
|
|
b6924adfb2 | ||
|
|
1cbb548e27 | ||
|
|
81f33190e2 | ||
|
|
e36da9798e | ||
|
|
a9507ce33f | ||
|
|
36178cf6e3 | ||
|
|
e88e5be93e | ||
|
|
b39eff86c5 | ||
|
|
11db5e5d62 | ||
|
|
e52f6a732b | ||
|
|
ac38405a62 | ||
|
|
7cd13e1e93 | ||
|
|
2131aff0e9 | ||
|
|
d4c292ed46 | ||
|
|
395648cfef | ||
|
|
b9301d1ae8 | ||
|
|
d38b8b4ae8 | ||
|
|
bb604702a5 | ||
|
|
641ffeaa67 | ||
|
|
ba95285a0e | ||
|
|
c4fa48db05 | ||
|
|
bb331c2c92 | ||
|
|
671ea7b286 | ||
|
|
13b82d1833 | ||
|
|
132ba21a3c | ||
|
|
c4179d0f6a | ||
|
|
3a275fe81b | ||
|
|
30f9a5eb21 | ||
|
|
2d0fda0179 | ||
|
|
fbeebac9d5 | ||
|
|
3f7774b089 | ||
|
|
aed6c3a214 | ||
|
|
6eb1aa1d0a | ||
|
|
5b47d4b19f | ||
|
|
521d067083 | ||
|
|
11db332281 | ||
|
|
637deb0011 | ||
|
|
6a36bd9d5c | ||
|
|
9a5041a25b | ||
|
|
733cc78c39 | ||
|
|
7feb93cdd7 | ||
|
|
5167d7202b | ||
|
|
5a65278613 | ||
|
|
a7c4d7f4c7 | ||
|
|
9ba6f062d4 | ||
|
|
6419744d76 | ||
|
|
803e665683 | ||
|
|
c84b712366 | ||
|
|
a90a8194bc | ||
|
|
0ddfbbe673 | ||
|
|
32361e1d89 | ||
|
|
bdd0eb0b7e | ||
|
|
6d3d199b42 | ||
|
|
84fd99da76 | ||
|
|
8c298b1c3b | ||
|
|
485964d87c | ||
|
|
9216c81855 | ||
|
|
24597e0145 | ||
|
|
46dcf18a18 | ||
|
|
ea934a7648 | ||
|
|
9c5999bc1d | ||
|
|
9b247c06be | ||
|
|
9f63decb9c | ||
|
|
3618402c3a | ||
|
|
be130c9b1c | ||
|
|
a61feea656 | ||
|
|
0bfe516318 | ||
|
|
d7cb6b006b | ||
|
|
7188c4b29b | ||
|
|
044ec98f66 | ||
|
|
54afc2e7a5 | ||
|
|
ecd012737f | ||
|
|
a8b32b2720 | ||
|
|
2031e21a58 | ||
|
|
bcfa1f7c26 | ||
|
|
cc9e61652f | ||
|
|
5749818906 | ||
|
|
73dd3b9af8 | ||
|
|
c6cfb6800f | ||
|
|
5b3518096c | ||
|
|
98c3fe4f16 | ||
|
|
2ff5cdaf7d | ||
|
|
a7db9a49f9 | ||
|
|
f6611ec912 | ||
|
|
a2d6cadec1 | ||
|
|
bc5b0215ee | ||
|
|
98d52d0d56 | ||
|
|
4fd42150bc | ||
|
|
74cb5cd608 | ||
|
|
d058dfdeef | ||
|
|
4c70fecad7 | ||
|
|
6fc3870728 | ||
|
|
34feb6e008 | ||
|
|
86e0c236a1 | ||
|
|
435db66a3a | ||
|
|
4486241540 | ||
|
|
28da01788d | ||
|
|
2ea4d165d5 | ||
|
|
baed156699 | ||
|
|
794d332bab | ||
|
|
2316c6343f | ||
|
|
9bb8a89bbd | ||
|
|
e17e6eef7b | ||
|
|
57a91b7ffe | ||
|
|
7693ffe0a5 | ||
|
|
be1278d5b2 | ||
|
|
09e4d03e46 | ||
|
|
177be0969b | ||
|
|
2df00c65a1 | ||
|
|
e61da21cd6 | ||
|
|
7d9ecaaf73 | ||
|
|
2fe382ec8a | ||
|
|
5b7af4b36d | ||
|
|
56d383b2e9 | ||
|
|
d99b302f90 | ||
|
|
e361b387d9 | ||
|
|
3bdd2f99b5 | ||
|
|
0a1456d8f9 | ||
|
|
df5e87bf97 | ||
|
|
5d85fb3e3b | ||
|
|
96e3d7e669 | ||
|
|
e360d2de5b | ||
|
|
d3b9520adc | ||
|
|
1102e0bccf | ||
|
|
feca4c6354 | ||
|
|
e9a248f555 | ||
|
|
2358b46553 | ||
|
|
918d561c6c | ||
|
|
a9be3cc0e8 | ||
|
|
239159fd26 | ||
|
|
265cc18843 | ||
|
|
b149060d52 | ||
|
|
10130a1261 | ||
|
|
5d4b51b4f2 | ||
|
|
ef73a1d1ae | ||
|
|
e211470035 | ||
|
|
040dc5f69e | ||
|
|
ccd455040a | ||
|
|
6563c9062c | ||
|
|
c4119f07c1 | ||
|
|
d8228f0d72 | ||
|
|
8369028c92 | ||
|
|
7d3e1f0b82 | ||
|
|
66fd9e4742 | ||
|
|
dd2454685b | ||
|
|
bc5f6cdfe8 | ||
|
|
b1dfe8a640 | ||
|
|
6337d9be46 | ||
|
|
899cbf5cd2 | ||
|
|
5b3bfeeca8 | ||
|
|
e678277c93 | ||
|
|
482a6bcff0 | ||
|
|
6a2c0b1cff | ||
|
|
1a17853e75 | ||
|
|
5026b1be00 | ||
|
|
ec6394488a | ||
|
|
94257defea | ||
|
|
d1fe1ec252 | ||
|
|
63ce937aac | ||
|
|
c071db7637 | ||
|
|
115068e2c4 | ||
|
|
881635a187 | ||
|
|
9f54727924 | ||
|
|
2998463eb4 | ||
|
|
1527c4e425 | ||
|
|
b64f429b4a | ||
|
|
c40c8d56f6 | ||
|
|
617e7cb233 | ||
|
|
7d86714c10 | ||
|
|
d339fd4356 | ||
|
|
9cf439488a | ||
|
|
7cadf60117 | ||
|
|
3a5502539c | ||
|
|
2be73b2be1 | ||
|
|
97cf4c7e25 | ||
|
|
7e859cc296 | ||
|
|
bcd54787e7 | ||
|
|
0395a1efef | ||
|
|
cd74e02643 | ||
|
|
e865c1e8dd | ||
|
|
0c7fbc46e6 | ||
|
|
1cede6dc2b | ||
|
|
661a7b08ae | ||
|
|
8c647c1cf4 | ||
|
|
2d077cf12b | ||
|
|
97045f85a1 | ||
|
|
9f88b0b229 | ||
|
|
dd2117f5fc | ||
|
|
c083a87b35 | ||
|
|
a773a379d9 | ||
|
|
bcfd8f82cd | ||
|
|
a395174037 | ||
|
|
21b0a09ef0 | ||
|
|
c32a76786c | ||
|
|
b57f90eeab | ||
|
|
0bdc5d082f | ||
|
|
ce680690de | ||
|
|
9116bb7acb | ||
|
|
eb7a30ae42 | ||
|
|
7131f87974 | ||
|
|
90f523ea57 | ||
|
|
a7162188d6 | ||
|
|
c0db608eac | ||
|
|
0a00a1f5b0 | ||
|
|
6cbe8cae35 | ||
|
|
746544af80 | ||
|
|
b8981f5fb8 | ||
|
|
b4c3bf2af2 | ||
|
|
aa49f3bb53 | ||
|
|
21ee05ecaf | ||
|
|
a406b34091 | ||
|
|
d1434ae5aa | ||
|
|
3c81548cba | ||
|
|
f47354680f | ||
|
|
995e46590e | ||
|
|
1a9d41867e | ||
|
|
13848621f1 | ||
|
|
5be093e0c8 | ||
|
|
8974d74db7 | ||
|
|
89a720d3f7 | ||
|
|
19cb042985 | ||
|
|
284f7578e6 | ||
|
|
70884151c9 | ||
|
|
0be82dce5e | ||
|
|
5b5e43e1fb | ||
|
|
070052c890 | ||
|
|
39fa6e6d1b | ||
|
|
8558eb88d7 | ||
|
|
7b0f4ee861 | ||
|
|
881560a0fe | ||
|
|
6d60301d20 | ||
|
|
1858922dac | ||
|
|
47546a5c4c | ||
|
|
dd029cab8f | ||
|
|
cabdf6a5fc | ||
|
|
cb9b8db894 | ||
|
|
8cd2b7d799 | ||
|
|
c1af7c3301 | ||
|
|
89cd9660be | ||
|
|
6b4d57d85c | ||
|
|
38ae617ca4 | ||
|
|
f775377e6a | ||
|
|
2d8028668f | ||
|
|
269e8185f6 | ||
|
|
07ddc66d8a | ||
|
|
02471c8f56 | ||
|
|
769984b023 | ||
|
|
89923f8004 | ||
|
|
1cd0266ca1 | ||
|
|
340b7c956a | ||
|
|
fcbccab4d1 | ||
|
|
c7b682f12a | ||
|
|
ac6931198d | ||
|
|
a281046e0e | ||
|
|
80a02cbd48 | ||
|
|
e2c7e901b8 | ||
|
|
8e6c519354 | ||
|
|
2b266434b7 | ||
|
|
b6941b6c61 | ||
|
|
b3c89ebde0 | ||
|
|
c8f91c5ead | ||
|
|
582fea57dc | ||
|
|
d379b58ab6 | ||
|
|
806dd2fb61 | ||
|
|
a130f3d179 | ||
|
|
556025ba14 | ||
|
|
75be6a3125 | ||
|
|
1d3ad8d791 | ||
|
|
6807e165d7 | ||
|
|
1433ffe515 | ||
|
|
d53d7bc559 | ||
|
|
d3e3bdabaa | ||
|
|
fe76832ec8 | ||
|
|
cdf8d5e35e | ||
|
|
5ce18c3f5a | ||
|
|
b377b8537b | ||
|
|
4fceb78b93 | ||
|
|
fb39357911 | ||
|
|
0353c0bdbe | ||
|
|
9500c30492 | ||
|
|
88a707dd13 | ||
|
|
e6fec7417f | ||
|
|
5093ce5be5 | ||
|
|
aa70c06d8f | ||
|
|
46255db86f | ||
|
|
4c085dec4a | ||
|
|
308fa6e78c | ||
|
|
7dc9593d88 | ||
|
|
43237f74a8 | ||
|
|
a977e35e0b | ||
|
|
61a220ff33 | ||
|
|
be8b56d949 | ||
|
|
7fa567c7a5 | ||
|
|
1139f54bde | ||
|
|
48b987827e | ||
|
|
d0300d176f | ||
|
|
f2a30737b6 | ||
|
|
5fe1cc01c0 | ||
|
|
27e47e9e87 | ||
|
|
48003e9d32 | ||
|
|
7f1caf4aa9 | ||
|
|
83203db6e2 | ||
|
|
96361171ed | ||
|
|
349427e4aa | ||
|
|
049b719eea | ||
|
|
0deddf2ce7 | ||
|
|
da4a30d394 | ||
|
|
8f3ef0891d | ||
|
|
109c0a1ddd | ||
|
|
77293c83bd | ||
|
|
4c318a1617 | ||
|
|
d8ad10d1ea | ||
|
|
ffb0265abd | ||
|
|
6530ae45b5 | ||
|
|
90cefbb38e | ||
|
|
a045f76eed | ||
|
|
ee504ba861 | ||
|
|
1f0fa08c4f | ||
|
|
6a60db558b | ||
|
|
26c89df31b | ||
|
|
e0a31a03fc | ||
|
|
0052af2227 | ||
|
|
d4f9d04b39 | ||
|
|
a4b5a30210 | ||
|
|
e1877465cb | ||
|
|
a256e4ad05 | ||
|
|
d394b0f274 | ||
|
|
ac7a14ece1 | ||
|
|
7dbf31e57f | ||
|
|
d5b7d10db7 | ||
|
|
8bb89b165c | ||
|
|
b5f030faa1 | ||
|
|
0bdd0fd2fa | ||
|
|
1260e7f5e0 | ||
|
|
0a32b5ca9d | ||
|
|
7d3db1bd07 | ||
|
|
f924273cdd | ||
|
|
ebe8aa0fcc | ||
|
|
6606fc2e7b | ||
|
|
115bbb3ca2 | ||
|
|
05ba82ad9a | ||
|
|
b041ec0a9a | ||
|
|
b36b2d592c | ||
|
|
47d5d371cd | ||
|
|
344a88301d | ||
|
|
c8ebba8699 | ||
|
|
352e707836 | ||
|
|
a73f2b38fb | ||
|
|
9a8fd1f667 | ||
|
|
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 |
1355 changed files with 116011 additions and 101777 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
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
|
|
@ -1 +0,0 @@
|
|||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
10
.github/dependabot.yml
vendored
Normal file
10
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
182
.github/workflows/presubmit.yml
vendored
182
.github/workflows/presubmit.yml
vendored
|
|
@ -3,38 +3,180 @@ 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 }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mainmatrix: [true]
|
||||
os: [ubuntu-20.04, macos-11.0]
|
||||
build-type: [Release]
|
||||
gl: [0]
|
||||
os: [ubuntu-22.04, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
mainmatrix: true
|
||||
- os: ubuntu-22.04
|
||||
gl: 1
|
||||
- os: ubuntu-20.04
|
||||
mainmatrix: false
|
||||
name: Arm
|
||||
extra: " gl"
|
||||
- os: ubuntu-22.04
|
||||
arch: arm
|
||||
- os: ubuntu-20.04
|
||||
mainmatrix: false
|
||||
name: AArch64
|
||||
- os: ubuntu-22.04
|
||||
arch: aarch64
|
||||
build-type: Debug
|
||||
extra: " debug"
|
||||
- os: ubuntu-22.04
|
||||
arch: android-arm
|
||||
android_arch_abi: armeabi-v7a
|
||||
- os: ubuntu-22.04
|
||||
arch: android-aarch64
|
||||
android_arch_abi: arm64-v8a
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: ./presubmit.sh
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- name: Install Arm and AArch64 compilers
|
||||
if: ${{ matrix.arch == 'arm' || matrix.arch == 'aarch64' }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
gcc-12-arm-linux-gnueabihf g++-12-arm-linux-gnueabihf \
|
||||
gcc-12-aarch64-linux-gnu g++-12-aarch64-linux-gnu
|
||||
sudo update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /usr/bin/arm-linux-gnueabihf-gcc-12 12
|
||||
sudo update-alternatives --install /usr/bin/arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++ /usr/bin/arm-linux-gnueabihf-g++-12 12
|
||||
sudo update-alternatives --install /usr/bin/aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc /usr/bin/aarch64-linux-gnu-gcc-12 12
|
||||
sudo update-alternatives --install /usr/bin/aarch64-linux-gnu-g++ aarch64-linux-gnu-g++ /usr/bin/aarch64-linux-gnu-g++-12 12
|
||||
- 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: Install Vulkan SDK
|
||||
uses: humbletim/install-vulkan-sdk@main
|
||||
with:
|
||||
version: 1.4.309.0
|
||||
cache: true
|
||||
- name: Install Android NDK
|
||||
if: ${{ matrix.arch == 'android-arm' || matrix.arch == 'android-aarch64' }}
|
||||
run: |
|
||||
wget https://dl.google.com/android/repository/android-ndk-r27c-linux.zip -O android-ndk.zip
|
||||
unzip android-ndk.zip -d $HOME
|
||||
export ANDROID_NDK=$HOME/android-ndk-r27c
|
||||
echo "ANDROID_NDK=$ANDROID_NDK" >> $GITHUB_ENV
|
||||
export ANDROID_ARCH_ABI=${{ matrix.android_arch_abi }}
|
||||
echo "ANDROID_ARCH_ABI=$ANDROID_ARCH_ABI" >> $GITHUB_ENV
|
||||
- name: Prepare CMake Toolchain file
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ '${{ matrix.arch }}' == android-* ]]; then
|
||||
TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake
|
||||
else
|
||||
TOOLCHAIN_FILE='${{ github.workspace }}'/toolchain.cmake
|
||||
touch ${TOOLCHAIN_FILE}
|
||||
fi
|
||||
|
||||
TOOLCHAIN_PREFIX_arm=arm-linux-gnueabihf
|
||||
TOOLCHAIN_PREFIX_aarch64=aarch64-linux-gnu
|
||||
|
||||
if [[ '${{ matrix.arch }}' != android-* ]]; then
|
||||
if [[ '${{ matrix.arch }}' != "" && ${RUNNER_OS} != "Windows" ]]; then
|
||||
TOOLCHAIN_PREFIX_VAR=TOOLCHAIN_PREFIX_${{ matrix.arch }}
|
||||
TOOLCHAIN_PREFIX=${!TOOLCHAIN_PREFIX_VAR}
|
||||
|
||||
echo "SET(CMAKE_SYSTEM_NAME Linux)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_SYSTEM_PROCESSOR ${{ matrix.arch }})" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" >> ${TOOLCHAIN_FILE}
|
||||
fi
|
||||
fi
|
||||
echo "TOOLCHAIN_FILE=${TOOLCHAIN_FILE}" >> $GITHUB_ENV
|
||||
- name: Prepare Android CMake arguments
|
||||
if: ${{ matrix.arch == 'android-arm' || matrix.arch == 'android-aarch64' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CMAKE_CONFIG_ARGS_ANDROID=-DCMAKE_ANDROID_ARCH_ABI=${ANDROID_ARCH_ABI}" >> $GITHUB_ENV
|
||||
- name: Fetch and build OpenCL ICD Loader
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader.git
|
||||
cd OpenCL-ICD-Loader
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \
|
||||
-DOPENCL_ICD_LOADER_HEADERS_DIR='${{ github.workspace }}'/OpenCL-Headers/ \
|
||||
"${CMAKE_CONFIG_ARGS_ANDROID}"
|
||||
cmake --build . --parallel
|
||||
- name: Fetch Vulkan Headers
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||
- name: Fetch and build Vulkan Loader
|
||||
if: ${{ matrix.arch != 'android-arm' && matrix.arch != 'android-aarch64' }}
|
||||
shell: bash
|
||||
run: |
|
||||
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 . --parallel
|
||||
- name: Configure and build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
if [[ ${RUNNER_OS} == "Windows" ]]; then
|
||||
CMAKE_OPENCL_LIBRARIES_OPTION="OpenCL"
|
||||
else
|
||||
CMAKE_OPENCL_LIBRARIES_OPTION="-lOpenCL"
|
||||
if [[ '${{ matrix.arch }}' != android-* ]]; then
|
||||
CMAKE_OPENCL_LIBRARIES_OPTION="${CMAKE_OPENCL_LIBRARIES_OPTION} -lpthread"
|
||||
fi
|
||||
fi
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
|
||||
-DCMAKE_CACHE_OPTIONS="-DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache" \
|
||||
-DCL_INCLUDE_DIR='${{ github.workspace }}'/OpenCL-Headers \
|
||||
-DCL_LIB_DIR='${{ github.workspace }}'/OpenCL-ICD-Loader/build \
|
||||
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=./bin \
|
||||
-DOPENCL_LIBRARIES="${CMAKE_OPENCL_LIBRARIES_OPTION}" \
|
||||
-DUSE_CL_EXPERIMENTAL=ON \
|
||||
-DGL_IS_SUPPORTED=${{ matrix.gl }} \
|
||||
-DVULKAN_IS_SUPPORTED=ON \
|
||||
-DVULKAN_INCLUDE_DIR='${{ github.workspace }}'/Vulkan-Headers/include/ \
|
||||
-DVULKAN_LIB_DIR='${{ github.workspace }}'/Vulkan-Loader/build/loader/ \
|
||||
"${CMAKE_CONFIG_ARGS_ANDROID}"
|
||||
cmake --build . --parallel
|
||||
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-14
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check code format
|
||||
|
|
|
|||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Build dir
|
||||
[Bb]uild/
|
||||
171
CMakeLists.txt
171
CMakeLists.txt
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
cmake_minimum_required(VERSION 3.12.0)
|
||||
|
||||
set( CONFORMANCE_SUFFIX "" )
|
||||
set(CLConform_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
|
@ -7,15 +7,9 @@ project(CLConform${CONFORMANCE_SUFFIX})
|
|||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
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,14 @@ 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)
|
||||
add_definitions(-DCL_ENABLE_BETA_EXTENSIONS)
|
||||
|
||||
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 +32,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 +51,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 +84,31 @@ 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(-Wno-narrowing)
|
||||
add_cxx_flag_if_supported(-Wno-format)
|
||||
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-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
|
||||
add_cxx_flag_if_supported(-Wno-strict-aliasing) # Issue 2234
|
||||
|
||||
# -msse -mfpmath=sse to force gcc to use sse for float math,
|
||||
# avoiding excess precision problems that cause tests like int2float
|
||||
|
|
@ -172,14 +126,46 @@ 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" )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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")
|
||||
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")
|
||||
set(Shared_Flags_Intel "-Qlong-double -Qpc80 /DWIN32 /D_WINDOWS /W3 /GR /EHsc -nologo -Od -D_CRT_NONSTDC_NO_WARNINGS -EHsc -Wall -fp:strict")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Shared_Flags_Intel}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${Shared_Flags_Intel}")
|
||||
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM"))
|
||||
set(ICC_Extra_Flags "-Qdiag-disable:68,111,177,186,161,869,1028,2259,2553,181,239,265,1188 -fp:source")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ICC_Extra_Flags}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ICC_Extra_Flags}")
|
||||
endif()
|
||||
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})
|
||||
|
|
@ -197,10 +183,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 +196,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}")
|
||||
|
|
|
|||
130
README.md
130
README.md
|
|
@ -1,2 +1,128 @@
|
|||
# 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.
|
||||
* `SPIRV_TOOLS_DIR` Directory containing the `spirv-as` and `spirv-val` binaries
|
||||
to be used in the CTS build process. Alternatively, the location to these binaries
|
||||
can be provided via the `PATH` variable.
|
||||
* `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
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Tools.git
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Headers.git SPIRV-Tools/external/spirv-headers
|
||||
git clone https://github.com/google/effcee.git SPIRV-Tools/external/effcee
|
||||
git clone https://github.com/google/re2.git SPIRV-Tools/external/re2
|
||||
|
||||
|
||||
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 SPIRV-Tools/build
|
||||
cmake -S SPIRV-Tools -B SPIRV-Tools/build -DSPIRV_SKIP_TESTS=ON
|
||||
cmake --build SPIRV-Tools/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 \
|
||||
-DSPIRV_TOOLS_DIR=$PWD/SPIRV-Tools/build/tools/ \
|
||||
-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/opencl_conformance_tests_full.csv)
|
||||
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-14`"}
|
||||
|
||||
# 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)
|
||||
|
|
|
|||
76
presubmit.sh
76
presubmit.sh
|
|
@ -1,76 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
export TOP=$(pwd)
|
||||
|
||||
TOOLCHAIN_URL_arm="https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz"
|
||||
TOOLCHAIN_URL_aarch64="https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz"
|
||||
|
||||
TOOLCHAIN_PREFIX_arm=arm-linux-gnueabihf
|
||||
TOOLCHAIN_PREFIX_aarch64=aarch64-linux-gnu
|
||||
|
||||
TOOLCHAIN_FILE=${TOP}/toolchain.cmake
|
||||
touch ${TOOLCHAIN_FILE}
|
||||
BUILD_OPENGL_TEST="OFF"
|
||||
|
||||
# Prepare toolchain if needed
|
||||
if [[ ${JOB_ARCHITECTURE} != "" ]]; then
|
||||
TOOLCHAIN_URL_VAR=TOOLCHAIN_URL_${JOB_ARCHITECTURE}
|
||||
TOOLCHAIN_URL=${!TOOLCHAIN_URL_VAR}
|
||||
wget ${TOOLCHAIN_URL}
|
||||
TOOLCHAIN_ARCHIVE=${TOOLCHAIN_URL##*/}
|
||||
tar xf ${TOOLCHAIN_ARCHIVE}
|
||||
TOOLCHAIN_DIR=${TOP}/${TOOLCHAIN_ARCHIVE%.tar.xz}
|
||||
export PATH=${TOOLCHAIN_DIR}/bin:${PATH}
|
||||
|
||||
TOOLCHAIN_PREFIX_VAR=TOOLCHAIN_PREFIX_${JOB_ARCHITECTURE}
|
||||
TOOLCHAIN_PREFIX=${!TOOLCHAIN_PREFIX_VAR}
|
||||
|
||||
echo "SET(CMAKE_SYSTEM_NAME Linux)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_SYSTEM_PROCESSOR ${JOB_ARCHITECTURE})" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" >> ${TOOLCHAIN_FILE}
|
||||
echo "SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" >> ${TOOLCHAIN_FILE}
|
||||
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 ..
|
||||
|
||||
# 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
|
||||
|
||||
# Get libclcxx
|
||||
cd ${TOP}
|
||||
git clone https://github.com/KhronosGroup/libclcxx.git
|
||||
|
||||
# Build CTS
|
||||
ls -l
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -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" \
|
||||
-DUSE_CL_EXPERIMENTAL=ON \
|
||||
-DGL_IS_SUPPORTED=${BUILD_OPENGL_TEST} \
|
||||
..
|
||||
make -j2
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
To run the conformance tests you need SPIR-V binaries.
|
||||
|
||||
If you are using a conformance package then the binaries are included in the
|
||||
package. If you are using conformance tests from gitlab repositories then the
|
||||
binaries need to be picked up from Khronos SVN URL mentioned below:
|
||||
|
||||
https://cvs.khronos.org/svn/repos/OpenCL/trunk/Khronos/spirv/spirv10_2015.11.25.zip
|
||||
|
||||
|
||||
Alternatively you can check out and build all of the below repositories.
|
||||
|
||||
1. SPIRV-LLVM
|
||||
LLVM with support for SPIR-V (required by clang compiler)
|
||||
Repository: https://gitlab.khronos.org/opencl/SPIRV-LLVM
|
||||
Branch: spec_constants
|
||||
Notes: spirv-3.6.1 is a main branch with support for OpenCL C++ kernel language,
|
||||
spec_constants is based on it, but it adds support for specialization constants.
|
||||
|
||||
2. Clang
|
||||
Clang with support for OpenCL C++ kernel language
|
||||
Repository: https://gitlab.khronos.org/opencl/clang
|
||||
Branch: spec_constants
|
||||
Notes: spirv-1.1 is a main branch with support for OpenCL C++ kernel language,
|
||||
spec_constants is based on it, but it adds support for specialization constants.
|
||||
|
||||
3. libclcxx
|
||||
OpenCL C++ Standard Library
|
||||
Repository: https://gitlab.khronos.org/opencl/libclcxx
|
||||
Branch: lit_tests_cl22
|
||||
Notes: lit_tests_cl22 branch includes both LIT tests and changes introduced in
|
||||
spec_constants branch, that is, implementation of Specialization Constants Library.
|
||||
|
||||
4. OpenCL 2.2 headers
|
||||
OpenCL 2.2 headers
|
||||
Repository: https://gitlab.khronos.org/opencl/headers
|
||||
Branch: opencl22
|
||||
|
||||
5. OpenCL ICD (with 2.2 support)
|
||||
OpenCL ICD
|
||||
Repository: https://gitlab.khronos.org/opencl/icd
|
||||
Branch: dev_cl22
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
set(HARNESS_SOURCES
|
||||
harness/threadTesting.cpp
|
||||
harness/alloc.cpp
|
||||
harness/typeWrappers.cpp
|
||||
harness/mt19937.cpp
|
||||
harness/conversions.cpp
|
||||
|
|
@ -22,4 +22,3 @@ set(HARNESS_SOURCES
|
|||
)
|
||||
|
||||
add_library(harness STATIC ${HARNESS_SOURCES})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,38 +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 TEST_COMMON_AUTOTEST_AUTOTEST_HPP
|
||||
#define TEST_COMMON_AUTOTEST_AUTOTEST_HPP
|
||||
|
||||
#include "test_suite.hpp"
|
||||
|
||||
#define STR_JOIN( X, Y ) STR_DO_JOIN( X, Y )
|
||||
#define STR_DO_JOIN( X, Y ) STR_DO_JOIN_2(X,Y)
|
||||
#define STR_DO_JOIN_2( X, Y ) X##Y
|
||||
|
||||
|
||||
// How to use AUTO_TEST_CASE macro:
|
||||
//
|
||||
// AUTO_TEST_CASE(<test_case_name>)(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
// {
|
||||
// (test case code...)
|
||||
// }
|
||||
//
|
||||
#define AUTO_TEST_CASE(name) \
|
||||
struct name { static int run_test(cl_device_id, cl_context, cl_command_queue, int); }; \
|
||||
static autotest::detail::test_case_registration STR_JOIN(name, STR_JOIN(_registration, __LINE__)) (#name, name::run_test); \
|
||||
int name::run_test
|
||||
|
||||
#endif //TEST_COMMON_AUTOTEST_AUTOTEST_HPP
|
||||
|
|
@ -1,61 +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 TEST_COMMON_AUTOTEST_TEST_SUITE_HPP
|
||||
#define TEST_COMMON_AUTOTEST_TEST_SUITE_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace autotest {
|
||||
|
||||
struct test_suite {
|
||||
test_suite(const std::string& name)
|
||||
: name(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void add(const test_definition& td)
|
||||
{
|
||||
test_defs.push_back(td);
|
||||
}
|
||||
|
||||
// List of test definitions
|
||||
std::vector<test_definition> test_defs;
|
||||
// Test suite name
|
||||
const std::string name;
|
||||
|
||||
static test_suite& global_test_suite()
|
||||
{
|
||||
static test_suite global_test_suite("global");
|
||||
return global_test_suite;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct test_case_registration
|
||||
{
|
||||
test_case_registration(const std::string& name, const basefn ptr)
|
||||
{
|
||||
::autotest::test_suite::global_test_suite().add(test_definition({ptr, strdup(name.c_str())}));
|
||||
}
|
||||
};
|
||||
|
||||
} // end detail namespace
|
||||
} // end autotest namespace
|
||||
|
||||
#endif // TEST_COMMON_AUTOTEST_TEST_SUITE_HPP
|
||||
|
|
@ -1,41 +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 TEST_COMMON_CONFIG_HPP
|
||||
#define TEST_COMMON_CONFIG_HPP
|
||||
|
||||
// Enable development options for OpenCL C++ tests (test_conformance/clpp)
|
||||
// #define DEVELOPMENT
|
||||
#if defined(CLPP_DEVELOPMENT_OPTIONS) && !defined(DEVELOPMENT)
|
||||
#define DEVELOPMENT
|
||||
#endif
|
||||
|
||||
#ifdef DEVELOPMENT
|
||||
// If defined OpenCL C++ tests only checks if OpenCL C++ kernels compiles correctly
|
||||
// #define ONLY_SPIRV_COMPILATION
|
||||
#if defined(CLPP_DEVELOPMENT_ONLY_SPIRV_COMPILATION) && !defined(ONLY_SPIRV_COMPILATION)
|
||||
#define ONLY_SPIRV_COMPILATION
|
||||
#endif
|
||||
|
||||
#ifndef ONLY_SPIRV_COMPILATION
|
||||
// If defined OpenCL C++ tests are run using OpenCL C kernels
|
||||
// #define USE_OPENCLC_KERNELS
|
||||
#if defined(CLPP_DEVELOPMENT_USE_OPENCLC_KERNELS) && !defined(USE_OPENCLC_KERNELS)
|
||||
#define USE_OPENCLC_KERNELS
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // TEST_COMMON_CONFIG_HPP
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -19,21 +19,28 @@
|
|||
|
||||
class OSXGLEnvironment : public GLEnvironment
|
||||
{
|
||||
public:
|
||||
OSXGLEnvironment()
|
||||
{
|
||||
mCGLContext = NULL;
|
||||
}
|
||||
private:
|
||||
bool mIsGlutInit;
|
||||
|
||||
public:
|
||||
OSXGLEnvironment()
|
||||
{
|
||||
mCGLContext = NULL;
|
||||
mIsGlutInit = false;
|
||||
}
|
||||
|
||||
virtual int Init( int *argc, char **argv, int use_opengl_32 )
|
||||
{
|
||||
if (!use_opengl_32) {
|
||||
|
||||
// Create a GLUT window to render into
|
||||
glutInit( argc, argv );
|
||||
glutInitWindowSize( 512, 512 );
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
|
||||
glutCreateWindow( "OpenCL <-> OpenGL Test" );
|
||||
if (!mIsGlutInit)
|
||||
{
|
||||
// Create a GLUT window to render into
|
||||
glutInit(argc, argv);
|
||||
glutInitWindowSize(512, 512);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||
glutCreateWindow("OpenCL <-> OpenGL Test");
|
||||
mIsGlutInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
@ -31,20 +26,26 @@ class X11GLEnvironment : public GLEnvironment
|
|||
private:
|
||||
cl_device_id m_devices[64];
|
||||
cl_uint m_device_count;
|
||||
bool m_glut_init;
|
||||
|
||||
public:
|
||||
X11GLEnvironment()
|
||||
{
|
||||
m_device_count = 0;
|
||||
m_glut_init = false;
|
||||
}
|
||||
virtual int Init( int *argc, char **argv, int use_opencl_32 )
|
||||
{
|
||||
// Create a GLUT window to render into
|
||||
glutInit( argc, argv );
|
||||
glutInitWindowSize( 512, 512 );
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
|
||||
glutCreateWindow( "OpenCL <-> OpenGL Test" );
|
||||
glewInit();
|
||||
if (!m_glut_init)
|
||||
{
|
||||
glutInit(argc, argv);
|
||||
glutInitWindowSize(512, 512);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
||||
glutCreateWindow("OpenCL <-> OpenGL Test");
|
||||
glewInit();
|
||||
m_glut_init = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -90,10 +91,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)
|
||||
|
|
@ -30,9 +33,9 @@
|
|||
#include "mingw_compat.h"
|
||||
#include <process.h>
|
||||
#else // !_WIN32
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/errno.h>
|
||||
#ifdef __linux__
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
121
test_common/harness/alloc.cpp
Normal file
121
test_common/harness/alloc.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
//
|
||||
// Copyright (c) 2024 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 "alloc.h"
|
||||
#include "errorHelpers.h"
|
||||
#include "testHarness.h"
|
||||
|
||||
#if defined(linux) || defined(__linux__) || defined(__ANDROID__)
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
|
||||
#include <linux/dma-heap.h>
|
||||
|
||||
struct dma_buf_heap_helper_t
|
||||
{
|
||||
dma_buf_heap_type heap_type;
|
||||
const char* env_var = nullptr;
|
||||
const char* default_path = nullptr;
|
||||
|
||||
constexpr dma_buf_heap_helper_t(dma_buf_heap_type heap_type,
|
||||
const char* env_var,
|
||||
const char* default_path)
|
||||
: heap_type(heap_type), env_var(env_var), default_path(default_path)
|
||||
{}
|
||||
};
|
||||
|
||||
constexpr dma_buf_heap_helper_t DMA_BUF_HEAP_TABLE[] = {
|
||||
{ dma_buf_heap_type::SYSTEM, "OCL_CTS_DMA_HEAP_PATH_SYSTEM",
|
||||
"/dev/dma_heap/system" },
|
||||
};
|
||||
|
||||
static dma_buf_heap_helper_t lookup_dma_heap(dma_buf_heap_type heap_type)
|
||||
{
|
||||
for (const auto& entry : DMA_BUF_HEAP_TABLE)
|
||||
{
|
||||
if (heap_type == entry.heap_type)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false
|
||||
&& "DMA heap type does not have an entry in DMA_BUF_HEAP_TABLE");
|
||||
return DMA_BUF_HEAP_TABLE[0];
|
||||
}
|
||||
#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
|
||||
|
||||
int allocate_dma_buf(uint64_t size, dma_buf_heap_type heap_type)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
|
||||
constexpr int DMA_HEAP_FLAGS = O_RDWR | O_CLOEXEC;
|
||||
|
||||
const auto entry = lookup_dma_heap(heap_type);
|
||||
const auto override_path = getenv(entry.env_var);
|
||||
const auto dma_heap_path =
|
||||
(override_path == nullptr) ? entry.default_path : override_path;
|
||||
|
||||
const int dma_heap_fd = open(dma_heap_path, DMA_HEAP_FLAGS);
|
||||
if (dma_heap_fd == -1)
|
||||
{
|
||||
log_error(
|
||||
"Opening the DMA heap device: %s failed with error: %d (%s)\n",
|
||||
dma_heap_path, errno, strerror(errno));
|
||||
|
||||
return TEST_SKIPPED_ITSELF;
|
||||
}
|
||||
|
||||
dma_heap_allocation_data dma_heap_data = { 0 };
|
||||
dma_heap_data.len = size;
|
||||
dma_heap_data.fd_flags = O_RDWR | O_CLOEXEC;
|
||||
|
||||
int result = ioctl(dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &dma_heap_data);
|
||||
if (result != 0)
|
||||
{
|
||||
log_error("DMA heap allocation IOCTL call failed, error: %d\n", result);
|
||||
|
||||
close(dma_heap_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = close(dma_heap_fd);
|
||||
if (result == -1)
|
||||
{
|
||||
log_info("Failed to close the DMA heap device: %s\n", dma_heap_path);
|
||||
}
|
||||
|
||||
return dma_heap_data.fd;
|
||||
#else
|
||||
return TEST_SKIPPED_ITSELF;
|
||||
#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
|
||||
}
|
||||
|
||||
#else
|
||||
int allocate_dma_buf(uint64_t size, dma_buf_heap_type heap_type)
|
||||
{
|
||||
log_error(
|
||||
"OS doesn't have DMA buffer heaps (only Linux and Android do).\n");
|
||||
|
||||
return TEST_SKIPPED_ITSELF;
|
||||
}
|
||||
#endif // defined(linux) || defined(__linux__) || defined(__ANDROID__)
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2020 The Khronos Group Inc.
|
||||
// Copyright (c) 2020 - 2024 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.
|
||||
|
|
@ -24,12 +24,17 @@
|
|||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#include "mingw_compat.h"
|
||||
#endif
|
||||
|
||||
static void* align_malloc(size_t size, size_t alignment)
|
||||
#if defined(_WIN32)
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
inline void* align_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
return _aligned_malloc(size, alignment);
|
||||
|
|
@ -53,7 +58,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);
|
||||
|
|
@ -66,4 +71,36 @@ static void align_free(void* ptr)
|
|||
#endif
|
||||
}
|
||||
|
||||
enum class dma_buf_heap_type
|
||||
{
|
||||
SYSTEM
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocate a DMA buffer.
|
||||
*
|
||||
* On systems that support it, use the DMA buffer heaps to allocate a DMA buffer
|
||||
* of the requested size, using the requested heap type. The heap type defaults
|
||||
* to using the system heap if no type is specified.
|
||||
*
|
||||
* A heap type will use a default path if one exists, and can be overriden using
|
||||
* an environment variable for each type, as follows:
|
||||
*
|
||||
* SYSTEM:
|
||||
* * Default path: /dev/dma_heap/system
|
||||
* * Environment variable: OCL_CTS_DMA_HEAP_PATH_SYSTEM
|
||||
*
|
||||
* DMA buffer heaps require a minimum Linux kernel version 5.6. A compile-time
|
||||
* warning is issued on older systems, as well as an error message at runtime.
|
||||
*
|
||||
* @param size [in] The requested buffer size in bytes.
|
||||
* @param heap_type [in,opt] The heap type to use for the allocation.
|
||||
*
|
||||
* @retrun A file descriptor representing the allocated DMA buffer on success,
|
||||
* -1 otherwise. Failure to open the DMA device returns TEST_SKIPPED_ITSELF so
|
||||
* it can be handled separately to other failures.
|
||||
*/
|
||||
int allocate_dma_buf(uint64_t size,
|
||||
dma_buf_heap_type heap_type = dma_buf_heap_type::SYSTEM);
|
||||
|
||||
#endif // #ifndef HARNESS_ALLOC_H_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
//
|
||||
|
|
@ -116,6 +116,15 @@ int feclearexcept(int excepts);
|
|||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cmath>
|
||||
extern "C" {
|
||||
using std::isfinite;
|
||||
using std::isinf;
|
||||
using std::isnan;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
#endif
|
||||
|
|
@ -138,18 +147,6 @@ extern "C" {
|
|||
#define INFINITY (FLT_MAX + FLT_MAX)
|
||||
#endif
|
||||
|
||||
#ifndef isfinite
|
||||
#define isfinite(x) _finite(x)
|
||||
#endif
|
||||
|
||||
#ifndef isnan
|
||||
#define isnan(x) ((x) != (x))
|
||||
#endif
|
||||
|
||||
#ifndef isinf
|
||||
#define isinf(_x) ((_x) == INFINITY || (_x) == -INFINITY)
|
||||
#endif
|
||||
|
||||
#if _MSC_VER < 1900 && !defined(__INTEL_COMPILER)
|
||||
|
||||
double rint(double x);
|
||||
|
|
@ -309,13 +306,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 +395,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,12 @@ static Long sLowerLimits[kNumExplicitTypes] = {
|
|||
} \
|
||||
break;
|
||||
|
||||
#define TO_HALF_CASE(inType, halfRoundingMode) \
|
||||
case kHalf: \
|
||||
halfPtr = (cl_half *)outRaw; \
|
||||
*halfPtr = \
|
||||
cl_half_from_float((float)(*inType##Ptr), halfRoundingMode); \
|
||||
break;
|
||||
#define TO_FLOAT_CASE(inType) \
|
||||
case kFloat: \
|
||||
floatPtr = (float *)outRaw; \
|
||||
|
|
@ -280,6 +289,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,16 +447,18 @@ 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;
|
||||
|
||||
void convert_explicit_value(void *inRaw, void *outRaw, ExplicitType inType,
|
||||
bool saturate, RoundingType roundType,
|
||||
cl_half_rounding_mode halfRoundingMode,
|
||||
ExplicitType outType)
|
||||
{
|
||||
bool *boolPtr;
|
||||
char *charPtr;
|
||||
schar *scharPtr;
|
||||
uchar *ucharPtr;
|
||||
short *shortPtr;
|
||||
ushort *ushortPtr;
|
||||
|
|
@ -402,6 +466,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 +497,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 +518,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(schar)
|
||||
TO_DOUBLE_CASE(schar)
|
||||
|
||||
default:
|
||||
log_error("ERROR: Invalid type given to "
|
||||
|
|
@ -490,7 +561,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 +572,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(uchar)
|
||||
TO_DOUBLE_CASE(uchar)
|
||||
|
||||
|
|
@ -522,7 +594,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 +605,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(uchar)
|
||||
TO_DOUBLE_CASE(uchar)
|
||||
|
||||
|
|
@ -553,7 +626,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 +638,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(short)
|
||||
TO_DOUBLE_CASE(short)
|
||||
|
||||
|
|
@ -586,7 +660,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 +671,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(ushort)
|
||||
TO_DOUBLE_CASE(ushort)
|
||||
|
||||
|
|
@ -618,7 +693,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 +704,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(ushort)
|
||||
TO_DOUBLE_CASE(ushort)
|
||||
|
||||
|
|
@ -649,7 +725,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 +737,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(int)
|
||||
TO_DOUBLE_CASE(int)
|
||||
|
||||
|
|
@ -682,7 +759,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 +770,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(uint)
|
||||
TO_DOUBLE_CASE(uint)
|
||||
|
||||
|
|
@ -714,7 +792,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 +803,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(uint)
|
||||
TO_DOUBLE_CASE(uint)
|
||||
|
||||
|
|
@ -745,7 +824,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 +836,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(Long)
|
||||
TO_DOUBLE_CASE(Long)
|
||||
|
||||
|
|
@ -778,7 +858,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 +869,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(ULong)
|
||||
TO_DOUBLE_CASE(ULong)
|
||||
|
||||
|
|
@ -810,7 +891,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 +902,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, halfRoundingMode)
|
||||
TO_FLOAT_CASE(ULong)
|
||||
TO_DOUBLE_CASE(ULong)
|
||||
|
||||
|
|
@ -831,13 +913,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 +971,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, halfRoundingMode)
|
||||
|
||||
case kFloat:
|
||||
memcpy(outRaw, inRaw, get_explicit_type_size(inType));
|
||||
break;
|
||||
|
|
@ -869,7 +992,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 +1005,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, halfRoundingMode)
|
||||
|
||||
TO_FLOAT_CASE(double);
|
||||
|
||||
case kDouble:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <CL/cl_half.h>
|
||||
|
||||
/* Note: the next three all have to match in size and order!! */
|
||||
|
||||
enum ExplicitTypes
|
||||
|
|
@ -71,6 +73,7 @@ extern const char *get_explicit_type_name(ExplicitType type);
|
|||
extern void convert_explicit_value(void *inRaw, void *outRaw,
|
||||
ExplicitType inType, bool saturate,
|
||||
RoundingType roundType,
|
||||
cl_half_rounding_mode halfRoundingMode,
|
||||
ExplicitType outType);
|
||||
|
||||
extern void generate_random_data(ExplicitType type, size_t count, MTdata d,
|
||||
|
|
|
|||
|
|
@ -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,54 @@ 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;
|
||||
}
|
||||
|
||||
static cl_ulong get_device_info_max_size(cl_device_id device,
|
||||
cl_device_info info,
|
||||
unsigned int divisor)
|
||||
{
|
||||
cl_ulong max_size;
|
||||
|
||||
if (divisor == 0)
|
||||
{
|
||||
throw std::runtime_error("Allocation divisor should not be 0\n");
|
||||
}
|
||||
|
||||
if (clGetDeviceInfo(device, info, sizeof(max_size), &max_size, NULL)
|
||||
!= CL_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("clGetDeviceInfo failed\n");
|
||||
}
|
||||
return max_size / divisor;
|
||||
}
|
||||
|
||||
cl_ulong get_device_info_max_mem_alloc_size(cl_device_id device,
|
||||
unsigned int divisor)
|
||||
{
|
||||
return get_device_info_max_size(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
|
||||
divisor);
|
||||
}
|
||||
|
||||
cl_ulong get_device_info_global_mem_size(cl_device_id device,
|
||||
unsigned int divisor)
|
||||
{
|
||||
return get_device_info_max_size(device, CL_DEVICE_GLOBAL_MEM_SIZE, divisor);
|
||||
}
|
||||
|
||||
cl_ulong get_device_info_max_constant_buffer_size(cl_device_id device,
|
||||
unsigned int divisor)
|
||||
{
|
||||
return get_device_info_max_size(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
|
||||
divisor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@
|
|||
#ifndef _deviceInfo_h
|
||||
#define _deviceInfo_h
|
||||
|
||||
// Configuration
|
||||
#include "../config.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <CL/opencl.h>
|
||||
|
|
@ -31,6 +28,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 +44,20 @@ 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);
|
||||
|
||||
/* We need to use a portion of available alloc size,
|
||||
* divide it to leave some memory for the platform. */
|
||||
#define MAX_DEVICE_MEMORY_SIZE_DIVISOR (2)
|
||||
|
||||
/* Get max allocation size. */
|
||||
cl_ulong get_device_info_max_mem_alloc_size(cl_device_id device,
|
||||
unsigned int divisor = 1);
|
||||
cl_ulong get_device_info_global_mem_size(cl_device_id device,
|
||||
unsigned int divisor = 1);
|
||||
cl_ulong get_device_info_max_constant_buffer_size(cl_device_id device,
|
||||
unsigned int divisor = 1);
|
||||
|
||||
#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>
|
||||
|
||||
|
|
@ -102,6 +105,13 @@ const char *IGetErrorString(int clErrorCode)
|
|||
case CL_INVALID_SPEC_ID: return "CL_INVALID_SPEC_ID";
|
||||
case CL_MAX_SIZE_RESTRICTION_EXCEEDED:
|
||||
return "CL_MAX_SIZE_RESTRICTION_EXCEEDED";
|
||||
case CL_INCOMPATIBLE_COMMAND_QUEUE_KHR:
|
||||
return "CL_INCOMPATIBLE_COMMAND_QUEUE_KHR";
|
||||
case CL_INVALID_SYNC_POINT_WAIT_LIST_KHR:
|
||||
return "CL_INVALID_SYNC_POINT_WAIT_LIST_KHR";
|
||||
case CL_INVALID_COMMAND_BUFFER_KHR:
|
||||
return "CL_INVALID_COMMAND_BUFFER_KHR";
|
||||
case CL_INVALID_SEMAPHORE_KHR: return "CL_INVALID_SEMAPHORE_KHR";
|
||||
default: return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +197,8 @@ const char *GetChannelTypeName(cl_channel_type type)
|
|||
case CL_UNORM_SHORT_565: return "CL_UNORM_SHORT_565";
|
||||
case CL_UNORM_SHORT_555: return "CL_UNORM_SHORT_555";
|
||||
case CL_UNORM_INT_101010: return "CL_UNORM_INT_101010";
|
||||
case CL_UNORM_INT_101010_2: return "CL_UNORM_INT_101010_2";
|
||||
case CL_UNORM_INT_2_101010_EXT: return "CL_UNORM_INT_2_101010_EXT";
|
||||
case CL_SIGNED_INT8: return "CL_SIGNED_INT8";
|
||||
case CL_SIGNED_INT16: return "CL_SIGNED_INT16";
|
||||
case CL_SIGNED_INT32: return "CL_SIGNED_INT32";
|
||||
|
|
@ -199,6 +211,14 @@ const char *GetChannelTypeName(cl_channel_type type)
|
|||
case CL_SFIXED14_APPLE: return "CL_SFIXED14_APPLE";
|
||||
#endif
|
||||
case CL_UNORM_INT24: return "CL_UNORM_INT24";
|
||||
case CL_UNSIGNED_INT_RAW10_EXT: return "CL_UNSIGNED_INT_RAW10_EXT";
|
||||
case CL_UNSIGNED_INT_RAW12_EXT: return "CL_UNSIGNED_INT_RAW12_EXT";
|
||||
case CL_UNSIGNED_INT10X6_EXT: return "CL_UNSIGNED_INT10X6_EXT";
|
||||
case CL_UNSIGNED_INT12X4_EXT: return "CL_UNSIGNED_INT12X4_EXT";
|
||||
case CL_UNSIGNED_INT14X2_EXT: return "CL_UNSIGNED_INT14X2_EXT";
|
||||
case CL_UNORM_INT10X6_EXT: return "CL_UNORM_INT10X6_EXT";
|
||||
case CL_UNORM_INT12X4_EXT: return "CL_UNORM_INT12X4_EXT";
|
||||
case CL_UNORM_INT14X2_EXT: return "CL_UNORM_INT14X2_EXT";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -215,6 +235,8 @@ int IsChannelTypeSupported(cl_channel_type type)
|
|||
case CL_UNORM_SHORT_565:
|
||||
case CL_UNORM_SHORT_555:
|
||||
case CL_UNORM_INT_101010:
|
||||
case CL_UNORM_INT_101010_2:
|
||||
case CL_UNORM_INT_2_101010_EXT:
|
||||
case CL_SIGNED_INT8:
|
||||
case CL_SIGNED_INT16:
|
||||
case CL_SIGNED_INT32:
|
||||
|
|
@ -222,10 +244,16 @@ int IsChannelTypeSupported(cl_channel_type type)
|
|||
case CL_UNSIGNED_INT16:
|
||||
case CL_UNSIGNED_INT32:
|
||||
case CL_HALF_FLOAT:
|
||||
case CL_FLOAT: return 1;
|
||||
case CL_FLOAT:
|
||||
#ifdef CL_SFIXED14_APPLE
|
||||
case CL_SFIXED14_APPLE: return 1;
|
||||
case CL_SFIXED14_APPLE:
|
||||
#endif
|
||||
case CL_UNSIGNED_INT10X6_EXT:
|
||||
case CL_UNSIGNED_INT12X4_EXT:
|
||||
case CL_UNSIGNED_INT14X2_EXT:
|
||||
case CL_UNORM_INT10X6_EXT:
|
||||
case CL_UNORM_INT12X4_EXT:
|
||||
case CL_UNORM_INT14X2_EXT: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -300,10 +328,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 +380,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 +388,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 +460,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 +469,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 +538,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 +554,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);
|
||||
|
|
@ -541,6 +567,39 @@ float Ulp_Error_Double(double test, long double reference)
|
|||
return result;
|
||||
}
|
||||
|
||||
cl_int OutputBuildLog(cl_program program, const cl_device_id device)
|
||||
{
|
||||
size_t size_ret;
|
||||
|
||||
// Get the build status
|
||||
cl_build_status build_status;
|
||||
cl_int error =
|
||||
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS,
|
||||
sizeof(build_status), &build_status, &size_ret);
|
||||
test_error(error, "Unable to query build status");
|
||||
|
||||
// If the build failed then print the status, obtain the build log and
|
||||
// print it.
|
||||
if (build_status != CL_BUILD_SUCCESS)
|
||||
{
|
||||
log_error("ERROR: CL_PROGRAM_BUILD_STATUS=%d\n", (int)build_status);
|
||||
error = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0,
|
||||
nullptr, &size_ret);
|
||||
test_error(error, "Unable to query build log size");
|
||||
|
||||
char *build_log = (char *)malloc(size_ret);
|
||||
error = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
|
||||
size_ret, build_log, &size_ret);
|
||||
test_error(error, "Unable to query build log");
|
||||
|
||||
log_error("ERROR: CL_PROGRAM_BUILD_LOG:\n%s\n", build_log);
|
||||
|
||||
free(build_log);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int OutputBuildLogs(cl_program program, cl_uint num_devices,
|
||||
cl_device_id *device_list)
|
||||
{
|
||||
|
|
@ -564,7 +623,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)
|
||||
{
|
||||
|
|
@ -580,33 +639,8 @@ cl_int OutputBuildLogs(cl_program program, cl_uint num_devices,
|
|||
unsigned int i;
|
||||
for (i = 0; i < num_devices; i++)
|
||||
{
|
||||
|
||||
// Get the build status
|
||||
cl_build_status build_status;
|
||||
error = clGetProgramBuildInfo(
|
||||
program, device_list[i], CL_PROGRAM_BUILD_STATUS,
|
||||
sizeof(build_status), &build_status, &size_ret);
|
||||
test_error(error, "Unable to query build status");
|
||||
|
||||
// If the build failed then log the status, and allocate the build
|
||||
// log, log it and free it
|
||||
if (build_status != CL_BUILD_SUCCESS)
|
||||
{
|
||||
|
||||
log_error("ERROR: CL_PROGRAM_BUILD_STATUS=%d\n",
|
||||
(int)build_status);
|
||||
error = clGetProgramBuildInfo(program, device_list[i],
|
||||
CL_PROGRAM_BUILD_LOG, 0, NULL,
|
||||
&size_ret);
|
||||
test_error(error, "Unable to query build log size");
|
||||
char *build_log = (char *)malloc(size_ret);
|
||||
error = clGetProgramBuildInfo(program, device_list[i],
|
||||
CL_PROGRAM_BUILD_LOG, size_ret,
|
||||
build_log, &size_ret);
|
||||
test_error(error, "Unable to query build log");
|
||||
log_error("ERROR: CL_PROGRAM_BUILD_LOG:\n%s\n", build_log);
|
||||
free(build_log);
|
||||
}
|
||||
error = OutputBuildLog(program, device_list[i]);
|
||||
test_error(error, "OutputBuildLog failed");
|
||||
}
|
||||
|
||||
// Was the number of devices given
|
||||
|
|
@ -623,7 +657,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 +724,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,8 @@ 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 OutputBuildLog(cl_program program, const cl_device_id device);
|
||||
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
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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))
|
||||
|
|
@ -126,6 +126,7 @@ typedef struct
|
|||
const cl_image_format *format;
|
||||
cl_mem buffer;
|
||||
cl_mem_object_type type;
|
||||
cl_mem_flags mem_flags;
|
||||
cl_uint num_mip_levels;
|
||||
} image_descriptor;
|
||||
|
||||
|
|
@ -139,6 +140,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,
|
||||
|
|
@ -188,6 +192,42 @@ cl_uint compute_max_mip_levels(size_t width, size_t height, size_t depth);
|
|||
cl_ulong compute_mipmapped_image_size(image_descriptor imageInfo);
|
||||
size_t compute_mip_level_offset(image_descriptor *imageInfo, size_t lod);
|
||||
|
||||
constexpr size_t RAW10_EXT_CLUMP_SIZE = 5;
|
||||
constexpr size_t RAW10_EXT_CLUMP_NUM_PIXELS = 4;
|
||||
constexpr size_t RAW12_EXT_CLUMP_SIZE = 3;
|
||||
constexpr size_t RAW12_EXT_CLUMP_NUM_PIXELS = 2;
|
||||
|
||||
inline bool is_width_compatible(image_descriptor imageInfo)
|
||||
{
|
||||
if (imageInfo.format->image_channel_data_type == CL_UNSIGNED_INT_RAW10_EXT
|
||||
&& (imageInfo.width % RAW10_EXT_CLUMP_NUM_PIXELS) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (imageInfo.format->image_channel_data_type == CL_UNSIGNED_INT_RAW12_EXT
|
||||
&& (imageInfo.width % RAW12_EXT_CLUMP_NUM_PIXELS) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline size_t calculate_row_pitch(image_descriptor imageInfo, size_t pixelSize)
|
||||
{
|
||||
if (imageInfo.format->image_channel_data_type == CL_UNSIGNED_INT_RAW10_EXT)
|
||||
{
|
||||
return (imageInfo.width * RAW10_EXT_CLUMP_SIZE)
|
||||
/ RAW10_EXT_CLUMP_NUM_PIXELS;
|
||||
}
|
||||
if (imageInfo.format->image_channel_data_type == CL_UNSIGNED_INT_RAW12_EXT)
|
||||
{
|
||||
return (imageInfo.width * RAW12_EXT_CLUMP_SIZE)
|
||||
/ RAW12_EXT_CLUMP_NUM_PIXELS;
|
||||
}
|
||||
|
||||
return imageInfo.width * pixelSize;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
|
||||
int y, int z, T *outData, int lod)
|
||||
|
|
@ -252,10 +292,24 @@ void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
|
|||
|
||||
// Advance to the right spot
|
||||
char *ptr = (char *)imageData;
|
||||
size_t pixelSize = get_pixel_size(format);
|
||||
|
||||
ptr += z * slice_pitch_lod + y * row_pitch_lod + x * pixelSize;
|
||||
|
||||
switch (format->image_channel_data_type)
|
||||
{
|
||||
case CL_UNSIGNED_INT_RAW10_EXT: {
|
||||
ptr += z * slice_pitch_lod + y * row_pitch_lod
|
||||
+ (x / RAW10_EXT_CLUMP_NUM_PIXELS) * RAW10_EXT_CLUMP_SIZE;
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT_RAW12_EXT: {
|
||||
ptr += z * slice_pitch_lod + y * row_pitch_lod
|
||||
+ (x / RAW12_EXT_CLUMP_NUM_PIXELS) * RAW12_EXT_CLUMP_SIZE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
size_t pixelSize = get_pixel_size(format);
|
||||
ptr += z * slice_pitch_lod + y * row_pitch_lod + x * pixelSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// OpenCL only supports reading floats from certain formats
|
||||
switch (format->image_channel_data_type)
|
||||
{
|
||||
|
|
@ -344,48 +398,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);
|
||||
|
|
@ -416,6 +428,47 @@ void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
case CL_UNSIGNED_INT_RAW10_EXT: {
|
||||
cl_uchar *dPtr = (cl_uchar *)ptr;
|
||||
i = x % RAW10_EXT_CLUMP_NUM_PIXELS;
|
||||
uint8_t bit_index = i << 1;
|
||||
uint16_t hi_val = dPtr[i] << 2;
|
||||
uint16_t lo_val = (dPtr[4] & (0x3 << bit_index)) >> bit_index;
|
||||
|
||||
tempData[0] = (T)(hi_val | lo_val);
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT_RAW12_EXT: {
|
||||
cl_uchar *dPtr = (cl_uchar *)ptr;
|
||||
i = x % RAW12_EXT_CLUMP_NUM_PIXELS;
|
||||
uint8_t bit_index = i << 2;
|
||||
uint16_t hi_val = dPtr[i] << 4;
|
||||
uint16_t lo_val = (dPtr[2] & (0xF << bit_index)) >> bit_index;
|
||||
|
||||
tempData[0] = (T)(hi_val | lo_val);
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT10X6_EXT: {
|
||||
cl_short *dPtr = (cl_short *)ptr;
|
||||
const size_t channelCount = get_format_channel_count(format);
|
||||
for (i = 0; i < channelCount; i++)
|
||||
tempData[i] = (dPtr[i] >> 6) & 0x3ff;
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT12X4_EXT: {
|
||||
cl_short *dPtr = (cl_short *)ptr;
|
||||
const size_t channelCount = get_format_channel_count(format);
|
||||
for (i = 0; i < channelCount; i++)
|
||||
tempData[i] = (dPtr[i] >> 4) & 0xfff;
|
||||
break;
|
||||
}
|
||||
case CL_UNSIGNED_INT14X2_EXT: {
|
||||
cl_short *dPtr = (cl_short *)ptr;
|
||||
const size_t channelCount = get_format_channel_count(format);
|
||||
for (i = 0; i < channelCount; i++)
|
||||
tempData[i] = (dPtr[i] >> 2) & 0x3fff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -479,6 +532,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 +549,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];
|
||||
}
|
||||
|
|
|
|||
94
test_common/harness/integer_ops_test_info.h
Normal file
94
test_common/harness/integer_ops_test_info.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//
|
||||
// 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"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// 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;
|
||||
|
|
@ -1434,13 +1319,21 @@ size_t get_pixel_bytes(const cl_image_format *fmt)
|
|||
case CL_UNORM_SHORT_565:
|
||||
case CL_UNORM_SHORT_555: return 2;
|
||||
|
||||
case CL_UNORM_INT_101010: return 4;
|
||||
case CL_UNORM_INT_101010:
|
||||
case CL_UNORM_INT_101010_2:
|
||||
case CL_UNORM_INT_2_101010_EXT: return 4;
|
||||
|
||||
case CL_SNORM_INT8:
|
||||
case CL_UNORM_INT8:
|
||||
case CL_SIGNED_INT8:
|
||||
case CL_UNSIGNED_INT8: return chanCount;
|
||||
|
||||
case CL_UNSIGNED_INT10X6_EXT:
|
||||
case CL_UNSIGNED_INT12X4_EXT:
|
||||
case CL_UNSIGNED_INT14X2_EXT:
|
||||
case CL_UNORM_INT10X6_EXT:
|
||||
case CL_UNORM_INT12X4_EXT:
|
||||
case CL_UNORM_INT14X2_EXT:
|
||||
case CL_SNORM_INT16:
|
||||
case CL_UNORM_INT16:
|
||||
case CL_HALF_FLOAT:
|
||||
|
|
@ -1626,22 +1519,30 @@ 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(const cl_device_id device,
|
||||
const cl_uint param)
|
||||
{
|
||||
char profileStr[128] = "";
|
||||
cl_device_fp_config single = 0;
|
||||
int error = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG,
|
||||
sizeof(single), &single, NULL);
|
||||
cl_device_fp_config config = 0;
|
||||
int error = clGetDeviceInfo(device, param, sizeof(config), &config, NULL);
|
||||
if (error)
|
||||
test_error_ret(error, "Unable to get device CL_DEVICE_SINGLE_FP_CONFIG",
|
||||
0);
|
||||
{
|
||||
std::string config_name = "CL_DEVICE_SINGLE_FP_CONFIG";
|
||||
if (param == CL_DEVICE_HALF_FP_CONFIG)
|
||||
config_name = "CL_DEVICE_HALF_FP_CONFIG";
|
||||
else if (param == CL_DEVICE_DOUBLE_FP_CONFIG)
|
||||
config_name = "CL_DEVICE_DOUBLE_FP_CONFIG";
|
||||
std::string message =
|
||||
std::string("Unable to get device ") + config_name;
|
||||
test_error_ret(error, message.c_str(), 0);
|
||||
}
|
||||
|
||||
if (single & CL_FP_ROUND_TO_NEAREST) return CL_FP_ROUND_TO_NEAREST;
|
||||
if (config & CL_FP_ROUND_TO_NEAREST) return CL_FP_ROUND_TO_NEAREST;
|
||||
|
||||
if (0 == (single & CL_FP_ROUND_TO_ZERO))
|
||||
if (0 == (config & 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
|
||||
|
|
@ -1730,7 +1631,7 @@ Version get_device_cl_c_version(cl_device_id device)
|
|||
&opencl_c_version_size_in_bytes);
|
||||
test_error_ret(error,
|
||||
"clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_VERSION\n",
|
||||
(Version{ -1, 0 }));
|
||||
(Version{ 0, 0 }));
|
||||
|
||||
std::string opencl_c_version(opencl_c_version_size_in_bytes, '\0');
|
||||
error =
|
||||
|
|
@ -1739,13 +1640,13 @@ Version get_device_cl_c_version(cl_device_id device)
|
|||
|
||||
test_error_ret(error,
|
||||
"clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_VERSION\n",
|
||||
(Version{ -1, 0 }));
|
||||
(Version{ 0, 0 }));
|
||||
|
||||
// Scrape out the major, minor pair from the string.
|
||||
auto major = opencl_c_version[opencl_c_version.find('.') - 1];
|
||||
auto minor = opencl_c_version[opencl_c_version.find('.') + 1];
|
||||
|
||||
return Version{ major - '0', minor - '0' };
|
||||
return Version{ (cl_uint)(major - '0'), (cl_uint)(minor - '0') };
|
||||
}
|
||||
|
||||
Version get_device_latest_cl_c_version(cl_device_id device)
|
||||
|
|
@ -1763,7 +1664,7 @@ Version get_device_latest_cl_c_version(cl_device_id device)
|
|||
&opencl_c_all_versions_size_in_bytes);
|
||||
test_error_ret(
|
||||
error, "clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_ALL_VERSIONS",
|
||||
(Version{ -1, 0 }));
|
||||
(Version{ 0, 0 }));
|
||||
std::vector<cl_name_version> name_versions(
|
||||
opencl_c_all_versions_size_in_bytes / sizeof(cl_name_version));
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_ALL_VERSIONS,
|
||||
|
|
@ -1771,13 +1672,15 @@ Version get_device_latest_cl_c_version(cl_device_id device)
|
|||
name_versions.data(), nullptr);
|
||||
test_error_ret(
|
||||
error, "clGetDeviceInfo failed for CL_DEVICE_OPENCL_C_ALL_VERSIONS",
|
||||
(Version{ -1, 0 }));
|
||||
(Version{ 0, 0 }));
|
||||
|
||||
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<cl_uint>(CL_VERSION_MAJOR(name_version.version)),
|
||||
static_cast<cl_uint>(CL_VERSION_MINOR(name_version.version))
|
||||
};
|
||||
max_supported_cl_c_version =
|
||||
(current_version > max_supported_cl_c_version)
|
||||
? current_version
|
||||
|
|
@ -1797,7 +1700,7 @@ Version get_max_OpenCL_C_for_context(cl_context context)
|
|||
auto error = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, nullptr,
|
||||
&devices_size_in_bytes);
|
||||
test_error_ret(error, "clGetDeviceInfo failed for CL_CONTEXT_DEVICES",
|
||||
(Version{ -1, 0 }));
|
||||
(Version{ 0, 0 }));
|
||||
std::vector<cl_device_id> devices(devices_size_in_bytes
|
||||
/ sizeof(cl_device_id));
|
||||
error = clGetContextInfo(context, CL_CONTEXT_DEVICES, devices_size_in_bytes,
|
||||
|
|
@ -1822,7 +1725,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 +1763,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<cl_uint>(CL_VERSION_MAJOR(name_version.version)),
|
||||
static_cast<cl_uint>(CL_VERSION_MINOR(name_version.version))
|
||||
};
|
||||
if (current_version == version)
|
||||
{
|
||||
return true;
|
||||
|
|
@ -1891,3 +1796,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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@
|
|||
#ifndef _kernelHelpers_h
|
||||
#define _kernelHelpers_h
|
||||
|
||||
// Configuration
|
||||
#include "../config.hpp"
|
||||
|
||||
#include "compat.h"
|
||||
#include "testHarness.h"
|
||||
|
||||
|
|
@ -42,21 +39,6 @@
|
|||
|
||||
#include <functional>
|
||||
|
||||
/*
|
||||
* The below code is intended to be used at the top of kernels that appear
|
||||
* inline in files to set line and file info for the kernel:
|
||||
*
|
||||
* const char *source = {
|
||||
* INIT_OPENCL_DEBUG_INFO
|
||||
* "__kernel void foo( int x )\n"
|
||||
* "{\n"
|
||||
* " ...\n"
|
||||
* "}\n"
|
||||
* };
|
||||
*/
|
||||
#define INIT_OPENCL_DEBUG_INFO SET_OPENCL_LINE_INFO(__LINE__, __FILE__)
|
||||
#define SET_OPENCL_LINE_INFO(_line, _file) \
|
||||
"#line " STRINGIFY(_line) " " STRINGIFY(_file) "\n"
|
||||
#ifndef STRINGIFY_VALUE
|
||||
#define STRINGIFY_VALUE(_x) STRINGIFY(_x)
|
||||
#endif
|
||||
|
|
@ -72,31 +54,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);
|
||||
|
||||
/* Creates OpenCL C++ program. This one must be used for creating OpenCL C++
|
||||
* program. */
|
||||
extern int create_openclcpp_program(cl_context context, cl_program *outProgram,
|
||||
unsigned int numKernelLines,
|
||||
const char **kernelProgram,
|
||||
const char *buildOptions = NULL);
|
||||
const char *buildOptions = NULL);
|
||||
|
||||
/* Builds program (outProgram) and creates one kernel */
|
||||
int build_program_create_kernel_helper(
|
||||
|
|
@ -162,7 +134,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(const cl_device_id device,
|
||||
const cl_uint param = CL_DEVICE_SINGLE_FP_CONFIG);
|
||||
|
||||
#define PASSIVE_REQUIRE_IMAGE_SUPPORT(device) \
|
||||
if (checkForImageSupport(device)) \
|
||||
|
|
@ -181,7 +155,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 +185,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
|
||||
|
|
|
|||
|
|
@ -714,6 +714,11 @@ int32_t float2int(float fx)
|
|||
return u.i;
|
||||
}
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if !__has_builtin(__builtin_clz)
|
||||
#if !defined(_WIN64)
|
||||
/** Returns the number of leading 0-bits in x,
|
||||
starting at the most significant bit position.
|
||||
|
|
@ -778,6 +783,7 @@ int __builtin_clz(unsigned int pattern)
|
|||
}
|
||||
|
||||
#endif // !defined(_WIN64)
|
||||
#endif // !__has_builtin(__builtin_clz)
|
||||
|
||||
#include <intrin.h>
|
||||
#include <emmintrin.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) \
|
||||
{ \
|
||||
|
|
@ -199,7 +208,8 @@ static std::string _err_msg(int err, int level)
|
|||
*/
|
||||
|
||||
#if (defined(__ANDROID__) && __ANDROID_API__ < 23) \
|
||||
|| ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
|
||||
|| ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) \
|
||||
|| (defined(_GNU_SOURCE) && !defined(__GLIBC__) && !defined(__USE_GNU))
|
||||
|
||||
// XSI version of strerror_r.
|
||||
#warning Not tested!
|
||||
|
|
@ -283,7 +293,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 +343,6 @@ std::string exe_dir()
|
|||
|
||||
|
||||
#include <windows.h>
|
||||
#if defined(max)
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
|
@ -404,7 +411,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 +566,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 strdup(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__
|
||||
|
|
|
|||
|
|
@ -25,14 +25,16 @@
|
|||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
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 +47,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 +66,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 +138,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 +226,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
|
||||
|
|
@ -235,11 +240,11 @@ void UnFlushToZero(void *p)
|
|||
#if defined(__i386__) || defined(__x86_64__) || defined(_MSC_VER)
|
||||
union {
|
||||
void *p;
|
||||
int i;
|
||||
unsigned int i;
|
||||
} 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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2017-2024 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.
|
||||
|
|
@ -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,75 @@ bool gCoreILProgram = true;
|
|||
|
||||
#define DEFAULT_NUM_ELEMENTS 0x4000
|
||||
|
||||
test_definition *test_registry::definitions() { return &m_definitions[0]; }
|
||||
|
||||
size_t test_registry::num_tests() { return m_definitions.size(); }
|
||||
|
||||
void test_registry::add_test(test *t, const char *name, Version version)
|
||||
{
|
||||
|
||||
m_tests.push_back(t);
|
||||
test_definition testDef;
|
||||
testDef.func = t->getFunction();
|
||||
testDef.name = name;
|
||||
testDef.min_version = version;
|
||||
m_definitions.push_back(testDef);
|
||||
}
|
||||
|
||||
test_registry &test_registry::getInstance()
|
||||
{
|
||||
static test_registry instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
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 +139,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 +206,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 +338,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 +381,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 +562,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 +571,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 +591,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 +619,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 +681,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)
|
||||
|
|
@ -646,19 +710,17 @@ static void print_results(int failed, int count, const char *name)
|
|||
log_error("FAILED %s.\n", name);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
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 +759,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 +786,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 +893,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 +912,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 +952,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 +969,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 +997,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 +1230,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());
|
||||
|
|
@ -1170,9 +1316,46 @@ cl_platform_id getPlatformFromDevice(cl_device_id deviceID)
|
|||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to return a string containing platform information
|
||||
* for the specified platform info parameter.
|
||||
*/
|
||||
std::string get_platform_info_string(cl_platform_id platform,
|
||||
cl_platform_info param_name)
|
||||
{
|
||||
size_t size = 0;
|
||||
int err;
|
||||
|
||||
if ((err = clGetPlatformInfo(platform, param_name, 0, NULL, &size))
|
||||
!= CL_SUCCESS
|
||||
|| size == 0)
|
||||
{
|
||||
throw std::runtime_error("clGetPlatformInfo failed\n");
|
||||
}
|
||||
|
||||
std::vector<char> info(size);
|
||||
|
||||
if ((err = clGetPlatformInfo(platform, param_name, size, info.data(), NULL))
|
||||
!= CL_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("clGetPlatformInfo failed\n");
|
||||
}
|
||||
|
||||
/* The returned string does not include the null terminator. */
|
||||
return std::string(info.data(), size - 1);
|
||||
}
|
||||
|
||||
bool is_platform_extension_available(cl_platform_id platform,
|
||||
const char *extensionName)
|
||||
{
|
||||
std::string extString =
|
||||
get_platform_info_string(platform, CL_PLATFORM_EXTENSIONS);
|
||||
return extString.find(extensionName) != std::string::npos;
|
||||
}
|
||||
|
||||
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 +1372,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,32 +16,41 @@
|
|||
#ifndef _testHarness_h
|
||||
#define _testHarness_h
|
||||
|
||||
#include "threadTesting.h"
|
||||
#include "clImageHelper.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Version {
|
||||
public:
|
||||
Version(): m_major(0), m_minor(0) {}
|
||||
Version(int major, int minor): m_major(major), m_minor(minor) {}
|
||||
bool operator>(const Version &rhs) const { return to_int() > rhs.to_int(); }
|
||||
bool operator<(const Version &rhs) const { return to_int() < rhs.to_int(); }
|
||||
|
||||
Version(cl_uint major, cl_uint minor): m_major(major), m_minor(minor) {}
|
||||
int major() const { return m_major; }
|
||||
int minor() const { return m_minor; }
|
||||
bool operator>(const Version &rhs) const
|
||||
{
|
||||
return to_uint() > rhs.to_uint();
|
||||
}
|
||||
bool operator<(const Version &rhs) const
|
||||
{
|
||||
return to_uint() < rhs.to_uint();
|
||||
}
|
||||
bool operator<=(const Version &rhs) const
|
||||
{
|
||||
return to_int() <= rhs.to_int();
|
||||
return to_uint() <= rhs.to_uint();
|
||||
}
|
||||
bool operator>=(const Version &rhs) const
|
||||
{
|
||||
return to_int() >= rhs.to_int();
|
||||
return to_uint() >= rhs.to_uint();
|
||||
}
|
||||
bool operator==(const Version &rhs) const
|
||||
{
|
||||
return to_int() == rhs.to_int();
|
||||
return to_uint() == rhs.to_uint();
|
||||
}
|
||||
int to_int() const { return m_major * 10 + m_minor; }
|
||||
cl_uint to_uint() const { return m_major * 10 + m_minor; }
|
||||
std::string to_string() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
@ -50,8 +59,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
int m_major;
|
||||
int m_minor;
|
||||
cl_uint m_major;
|
||||
cl_uint m_minor;
|
||||
};
|
||||
|
||||
Version get_device_cl_version(cl_device_id device);
|
||||
|
|
@ -67,9 +76,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 +95,72 @@ 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;
|
||||
};
|
||||
|
||||
|
||||
struct test
|
||||
{
|
||||
virtual test_function_pointer getFunction() = 0;
|
||||
};
|
||||
|
||||
class test_registry {
|
||||
private:
|
||||
std::vector<test *> m_tests;
|
||||
std::vector<test_definition> m_definitions;
|
||||
|
||||
public:
|
||||
static test_registry &getInstance();
|
||||
|
||||
test_definition *definitions();
|
||||
|
||||
size_t num_tests();
|
||||
|
||||
void add_test(test *t, const char *name, Version version);
|
||||
test_registry() {}
|
||||
};
|
||||
|
||||
template <typename T> T *register_test(const char *name, Version version)
|
||||
{
|
||||
T *t = new T();
|
||||
test_registry::getInstance().add_test((test *)t, name, version);
|
||||
return t;
|
||||
}
|
||||
|
||||
#define REGISTER_TEST_VERSION(name, version) \
|
||||
extern int test_##name(cl_device_id device, cl_context context, \
|
||||
cl_command_queue queue, int num_elements); \
|
||||
class test_##name##_class : public test { \
|
||||
private: \
|
||||
test_function_pointer fn; \
|
||||
\
|
||||
public: \
|
||||
test_##name##_class(): fn(test_##name) {} \
|
||||
test_function_pointer getFunction() { return fn; } \
|
||||
}; \
|
||||
test_##name##_class *var_##name = \
|
||||
register_test<test_##name##_class>(#name, version); \
|
||||
int test_##name(cl_device_id device, cl_context context, \
|
||||
cl_command_queue queue, int num_elements)
|
||||
|
||||
#define REGISTER_TEST(name) REGISTER_TEST_VERSION(name, Version(1, 2))
|
||||
|
||||
#define REQUIRE_EXTENSION(name) \
|
||||
do \
|
||||
{ \
|
||||
if (!is_extension_available(device, name)) \
|
||||
{ \
|
||||
log_info(name \
|
||||
" is not supported on this device. Skipping test.\n"); \
|
||||
return TEST_SKIPPED_ITSELF; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern int gFailCount;
|
||||
extern int gTestCount;
|
||||
extern cl_uint gReSeed;
|
||||
|
|
@ -115,9 +193,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 +205,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
|
||||
|
||||
|
|
@ -179,6 +253,10 @@ extern int gHasLong; // This is set to 1 if the device suppots long and ulong
|
|||
extern bool gCoreILProgram;
|
||||
|
||||
extern cl_platform_id getPlatformFromDevice(cl_device_id deviceID);
|
||||
extern std::string get_platform_info_string(cl_platform_id platform,
|
||||
cl_platform_info param_name);
|
||||
extern bool is_platform_extension_available(cl_platform_id platform,
|
||||
const char *extensionName);
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
void memset_pattern4(void *, const void *, size_t);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -348,7 +348,7 @@ cl_int clProtectedImage::Create(cl_context context,
|
|||
const cl_image_format *fmt, size_t width,
|
||||
size_t height, size_t depth, size_t arraySize)
|
||||
{
|
||||
cl_int error;
|
||||
cl_int error = 0;
|
||||
#if defined(__APPLE__)
|
||||
int protect_pages = 1;
|
||||
cl_device_id devices[16];
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
@ -403,4 +377,24 @@ public:
|
|||
size_t getSize() const { return allocsize; };
|
||||
};
|
||||
|
||||
// scope guard helper to ensure proper releasing of sub devices
|
||||
struct SubDevicesScopeGuarded
|
||||
{
|
||||
SubDevicesScopeGuarded(const cl_int dev_count)
|
||||
{
|
||||
sub_devices.resize(dev_count);
|
||||
}
|
||||
~SubDevicesScopeGuarded()
|
||||
{
|
||||
for (auto &device : sub_devices)
|
||||
{
|
||||
cl_int err = clReleaseDevice(device);
|
||||
if (err != CL_SUCCESS)
|
||||
log_error("\n Releasing sub-device failed \n");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cl_device_id> sub_devices;
|
||||
};
|
||||
|
||||
#endif // _typeWrappers_h
|
||||
|
|
|
|||
|
|
@ -7,3 +7,8 @@ add_executable(${${MODULE_NAME}_OUT} ${${MODULE_NAME}_SOURCES})
|
|||
set_property(TARGET ${${MODULE_NAME}_OUT} PROPERTY FOLDER "CONFORMANCE${CONFORMANCE_SUFFIX}")
|
||||
|
||||
TARGET_LINK_LIBRARIES(${${MODULE_NAME}_OUT} ${HARNESS_LIB} ${CLConform_LIBRARIES})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS ${${MODULE_NAME}_OUT}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/$<CONFIG>)
|
||||
|
|
|
|||
|
|
@ -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,9 +1,9 @@
|
|||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(MODULE_NAME SVM)
|
||||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
main.cpp
|
||||
test_allocate_shared_buffer.cpp
|
||||
test_allocate_shared_buffer_negative.cpp
|
||||
test_byte_granularity.cpp
|
||||
test_cross_buffer_pointers.cpp
|
||||
test_enqueue_api.cpp
|
||||
|
|
@ -18,4 +18,6 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_migrate.cpp
|
||||
)
|
||||
|
||||
set_gnulike_module_compile_flags("-Wno-sometimes-uninitialized -Wno-sign-compare")
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
|
|
|
|||
|
|
@ -81,21 +81,6 @@ extern cl_int verify_linked_lists_on_device(int qi, cl_command_queue q, c
|
|||
extern cl_int create_linked_lists_on_device_no_map(int qi, cl_command_queue q, size_t *pAllocator, cl_kernel k, size_t numLists );
|
||||
extern cl_int verify_linked_lists_on_device_no_map(int qi, cl_command_queue q, cl_int *pNum_correct, cl_kernel k, cl_int ListLength, size_t numLists );
|
||||
|
||||
extern int test_svm_byte_granularity(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_set_kernel_exec_info_svm_ptrs(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_fine_grain_memory_consistency(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_fine_grain_sync_buffers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_shared_address_space_coarse_grain_old_api(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_shared_address_space_coarse_grain_new_api(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_shared_address_space_fine_grain_buffers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_shared_address_space_fine_grain(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_cross_buffer_pointers_coarse_grain(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_pointer_passing(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_allocate_shared_buffer(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_shared_sub_buffers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_enqueue_api(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_svm_migrate(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern cl_int create_cl_objects(cl_device_id device_from_harness, const char** ppCodeString, cl_context* context, cl_program *program, cl_command_queue *queues, cl_uint *num_devices, cl_device_svm_capabilities required_svm_caps, std::vector<std::string> extensions_list = std::vector<std::string>());
|
||||
|
||||
extern const char *linked_list_create_and_verify_kernels[];
|
||||
|
|
|
|||
|
|
@ -260,25 +260,6 @@ cl_int create_cl_objects(cl_device_id device_from_harness, const char** ppCodeSt
|
|||
return 0;
|
||||
}
|
||||
|
||||
test_definition test_list[] = {
|
||||
ADD_TEST( svm_byte_granularity),
|
||||
ADD_TEST( svm_set_kernel_exec_info_svm_ptrs ),
|
||||
ADD_TEST( svm_fine_grain_memory_consistency ),
|
||||
ADD_TEST( svm_fine_grain_sync_buffers ),
|
||||
ADD_TEST( svm_shared_address_space_fine_grain ),
|
||||
ADD_TEST( svm_shared_sub_buffers ),
|
||||
ADD_TEST( svm_shared_address_space_fine_grain_buffers ),
|
||||
ADD_TEST( svm_allocate_shared_buffer ),
|
||||
ADD_TEST( svm_shared_address_space_coarse_grain_old_api ),
|
||||
ADD_TEST( svm_shared_address_space_coarse_grain_new_api ),
|
||||
ADD_TEST( svm_cross_buffer_pointers_coarse_grain ),
|
||||
ADD_TEST( svm_pointer_passing ),
|
||||
ADD_TEST( svm_enqueue_api ),
|
||||
ADD_TEST_VERSION( svm_migrate, Version(2, 1)),
|
||||
};
|
||||
|
||||
const int test_num = ARRAY_SIZE( test_list );
|
||||
|
||||
test_status InitCL(cl_device_id device) {
|
||||
auto version = get_device_cl_version(device);
|
||||
auto expected_min_version = Version(2, 0);
|
||||
|
|
@ -309,6 +290,7 @@ test_status InitCL(cl_device_id device) {
|
|||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
return runTestHarnessWithCheck(argc, argv, test_num, test_list, true, 0, InitCL);
|
||||
return runTestHarnessWithCheck(
|
||||
argc, argv, test_registry::getInstance().num_tests(),
|
||||
test_registry::getInstance().definitions(), true, 0, InitCL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,71 +41,82 @@ const char* flag_set_names[] = {
|
|||
};
|
||||
|
||||
|
||||
int test_svm_allocate_shared_buffer(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_allocate_shared_buffer)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
cl_device_svm_capabilities caps;
|
||||
err = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_CAPABILITIES, sizeof(cl_device_svm_capabilities), &caps, NULL);
|
||||
test_error(err,"clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES");
|
||||
cl_device_svm_capabilities caps;
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_SVM_CAPABILITIES,
|
||||
sizeof(cl_device_svm_capabilities), &caps, NULL);
|
||||
test_error(err, "clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES");
|
||||
|
||||
// under construction...
|
||||
err = create_cl_objects(deviceID, NULL, &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if(err) return -1;
|
||||
// under construction...
|
||||
err = create_cl_objects(device, NULL, &contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (err) return -1;
|
||||
|
||||
size_t size = 1024;
|
||||
size_t size = 1024;
|
||||
|
||||
// iteration over flag combos
|
||||
int num_flags = sizeof(flag_set)/sizeof(cl_mem_flags);
|
||||
for(int i = 0; i < num_flags; i++)
|
||||
{
|
||||
if (((flag_set[i] & CL_MEM_SVM_FINE_GRAIN_BUFFER) != 0 && (caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER) == 0)
|
||||
|| ((flag_set[i] & CL_MEM_SVM_ATOMICS) != 0 && (caps & CL_DEVICE_SVM_ATOMICS) == 0))
|
||||
// iteration over flag combos
|
||||
int num_flags = sizeof(flag_set) / sizeof(cl_mem_flags);
|
||||
for (int i = 0; i < num_flags; i++)
|
||||
{
|
||||
log_info("Skipping clSVMalloc with flags: %s\n", flag_set_names[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_info("Testing clSVMalloc with flags: %s\n", flag_set_names[i]);
|
||||
cl_char *pBufData1 = (cl_char*) clSVMAlloc(context, flag_set[i], size, 0);
|
||||
if(pBufData1 == NULL)
|
||||
{
|
||||
log_error("SVMalloc returned NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, size, pBufData1, &err);
|
||||
test_error(err,"clCreateBuffer failed");
|
||||
|
||||
cl_char *pBufData2 = NULL;
|
||||
cl_uint flags = CL_MAP_READ | CL_MAP_READ;
|
||||
if(flag_set[i] & CL_MEM_HOST_READ_ONLY) flags ^= CL_MAP_WRITE;
|
||||
if(flag_set[i] & CL_MEM_HOST_WRITE_ONLY) flags ^= CL_MAP_READ;
|
||||
|
||||
if(!(flag_set[i] & CL_MEM_HOST_NO_ACCESS))
|
||||
{
|
||||
pBufData2 = (cl_char*) clEnqueueMapBuffer(queues[0], buf, CL_TRUE, flags, 0, size, 0, NULL,NULL, &err);
|
||||
test_error(err, "clEnqueueMapBuffer failed");
|
||||
|
||||
if(pBufData2 != pBufData1 || NULL == pBufData1)
|
||||
if (((flag_set[i] & CL_MEM_SVM_FINE_GRAIN_BUFFER) != 0
|
||||
&& (caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER) == 0)
|
||||
|| ((flag_set[i] & CL_MEM_SVM_ATOMICS) != 0
|
||||
&& (caps & CL_DEVICE_SVM_ATOMICS) == 0))
|
||||
{
|
||||
log_error("SVM pointer returned by clEnqueueMapBuffer doesn't match pointer returned by clSVMalloc");
|
||||
return -1;
|
||||
log_info("Skipping clSVMalloc with flags: %s\n", flag_set_names[i]);
|
||||
continue;
|
||||
}
|
||||
err = clEnqueueUnmapMemObject(queues[0], buf, pBufData2, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueUnmapMemObject failed");
|
||||
err = clFinish(queues[0]);
|
||||
test_error(err, "clFinish failed");
|
||||
}
|
||||
|
||||
log_info("Testing clSVMalloc with flags: %s\n", flag_set_names[i]);
|
||||
cl_char *pBufData1 =
|
||||
(cl_char *)clSVMAlloc(context, flag_set[i], size, 0);
|
||||
if (pBufData1 == NULL)
|
||||
{
|
||||
log_error("SVMalloc returned NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR,
|
||||
size, pBufData1, &err);
|
||||
test_error(err, "clCreateBuffer failed");
|
||||
|
||||
cl_char *pBufData2 = NULL;
|
||||
cl_uint flags = CL_MAP_READ | CL_MAP_READ;
|
||||
if (flag_set[i] & CL_MEM_HOST_READ_ONLY) flags ^= CL_MAP_WRITE;
|
||||
if (flag_set[i] & CL_MEM_HOST_WRITE_ONLY) flags ^= CL_MAP_READ;
|
||||
|
||||
if (!(flag_set[i] & CL_MEM_HOST_NO_ACCESS))
|
||||
{
|
||||
pBufData2 = (cl_char *)clEnqueueMapBuffer(
|
||||
queues[0], buf, CL_TRUE, flags, 0, size, 0, NULL, NULL,
|
||||
&err);
|
||||
test_error(err, "clEnqueueMapBuffer failed");
|
||||
|
||||
if (pBufData2 != pBufData1 || NULL == pBufData1)
|
||||
{
|
||||
log_error("SVM pointer returned by clEnqueueMapBuffer "
|
||||
"doesn't match pointer returned by clSVMalloc");
|
||||
return -1;
|
||||
}
|
||||
err = clEnqueueUnmapMemObject(queues[0], buf, pBufData2, 0,
|
||||
NULL, NULL);
|
||||
test_error(err, "clEnqueueUnmapMemObject failed");
|
||||
err = clFinish(queues[0]);
|
||||
test_error(err, "clFinish failed");
|
||||
}
|
||||
}
|
||||
|
||||
clSVMFree(context, pBufData1);
|
||||
}
|
||||
|
||||
clSVMFree(context, pBufData1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
100
test_conformance/SVM/test_allocate_shared_buffer_negative.cpp
Normal file
100
test_conformance/SVM/test_allocate_shared_buffer_negative.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// 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 "common.h"
|
||||
|
||||
const cl_mem_flags svm_flag_set[] = {
|
||||
CL_MEM_READ_WRITE,
|
||||
CL_MEM_WRITE_ONLY,
|
||||
CL_MEM_READ_ONLY,
|
||||
CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS,
|
||||
CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS,
|
||||
CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS,
|
||||
0
|
||||
};
|
||||
const char* svm_flag_set_names[] = {
|
||||
"CL_MEM_READ_WRITE",
|
||||
"CL_MEM_WRITE_ONLY",
|
||||
"CL_MEM_READ_ONLY",
|
||||
"CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER",
|
||||
"CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER",
|
||||
"CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER",
|
||||
"CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS",
|
||||
"CL_MEM_WRITE_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS",
|
||||
"CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS",
|
||||
"0"
|
||||
};
|
||||
|
||||
|
||||
REGISTER_TEST(svm_allocate_shared_buffer_negative)
|
||||
{
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
cl_device_svm_capabilities caps;
|
||||
err = clGetDeviceInfo(device, CL_DEVICE_SVM_CAPABILITIES,
|
||||
sizeof(cl_device_svm_capabilities), &caps, NULL);
|
||||
test_error(err, "clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES");
|
||||
|
||||
// under construction...
|
||||
err = create_cl_objects(device, NULL, &contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (err) return err;
|
||||
|
||||
size_t size = 1024;
|
||||
|
||||
// iteration over flag combos
|
||||
int num_flags = sizeof(svm_flag_set) / sizeof(cl_mem_flags);
|
||||
for (int i = 0; i < num_flags; i++)
|
||||
{
|
||||
if (((svm_flag_set[i] & CL_MEM_SVM_FINE_GRAIN_BUFFER) != 0
|
||||
&& (caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER) == 0)
|
||||
|| ((svm_flag_set[i] & CL_MEM_SVM_ATOMICS) != 0
|
||||
&& (caps & CL_DEVICE_SVM_ATOMICS) == 0))
|
||||
{
|
||||
log_info("Skipping clSVMalloc with flags: %s\n",
|
||||
svm_flag_set_names[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_info("Testing clSVMalloc with flags: %s\n", svm_flag_set_names[i]);
|
||||
cl_char* pBufData1 =
|
||||
(cl_char*)clSVMAlloc(context, svm_flag_set[i], size, 0);
|
||||
if (pBufData1 == NULL)
|
||||
{
|
||||
log_error("SVMalloc returned NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
clMemWrapper buf1 = clCreateBuffer(context, CL_MEM_USE_HOST_PTR,
|
||||
2 * size, pBufData1, &err);
|
||||
test_failure_error(err, CL_INVALID_BUFFER_SIZE,
|
||||
"clCreateBuffer did not return expected error"
|
||||
"CL_INVALID_BUFFER_SIZE");
|
||||
}
|
||||
|
||||
clSVMFree(context, pBufData1);
|
||||
}
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
|
@ -48,101 +48,115 @@ const char *byte_manipulation_kernels[] = {
|
|||
};
|
||||
|
||||
|
||||
|
||||
int test_svm_byte_granularity(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_byte_granularity)
|
||||
{
|
||||
clContextWrapper context;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper k1,k2;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper k1, k2;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
cl_int rval = CL_SUCCESS;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = 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.
|
||||
if(err < 0) return -1; // fail test.
|
||||
err = create_cl_objects(device, &byte_manipulation_kernels[0],
|
||||
&contextWrapper, &program, &queues[0], &num_devices,
|
||||
CL_DEVICE_SVM_FINE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (err == 1)
|
||||
return 0; // no devices capable of requested SVM level, so don't execute
|
||||
// but count test as passing.
|
||||
if (err < 0) return -1; // fail test.
|
||||
|
||||
cl_uint num_devices_plus_host = num_devices + 1;
|
||||
cl_uint num_devices_plus_host = num_devices + 1;
|
||||
|
||||
k1 = clCreateKernel(program, "write_owned_locations", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
k2 = clCreateKernel(program, "sum_neighbor_locations", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
k1 = clCreateKernel(program, "write_owned_locations", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
k2 = clCreateKernel(program, "sum_neighbor_locations", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
|
||||
|
||||
cl_char *pA = (cl_char*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_char) * num_elements, 0);
|
||||
cl_char *pA = (cl_char *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
sizeof(cl_char) * num_elements, 0);
|
||||
|
||||
cl_uint **error_counts = (cl_uint**) malloc(sizeof(void*) * num_devices);
|
||||
cl_uint **error_counts = (cl_uint **)malloc(sizeof(void *) * num_devices);
|
||||
|
||||
for(cl_uint i=0; i < num_devices; i++) {
|
||||
error_counts[i] = (cl_uint*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_uint), 0);
|
||||
*error_counts[i] = 0;
|
||||
}
|
||||
for(int i=0; i < num_elements; i++) pA[i] = -1;
|
||||
for (cl_uint i = 0; i < num_devices; i++)
|
||||
{
|
||||
error_counts[i] = (cl_uint *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
sizeof(cl_uint), 0);
|
||||
*error_counts[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < num_elements; i++) pA[i] = -1;
|
||||
|
||||
err |= clSetKernelArgSVMPointer(k1, 0, pA);
|
||||
err |= clSetKernelArg(k1, 1, sizeof(cl_uint), &num_devices_plus_host);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
// get all the devices going simultaneously
|
||||
size_t element_num = num_elements;
|
||||
for(cl_uint d=0; d < num_devices; d++) // device ids starting at 1.
|
||||
{
|
||||
err = clSetKernelArg(k1, 2, sizeof(cl_uint), &d);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
err = clEnqueueNDRangeKernel(queues[d], k1, 1, NULL, &element_num, NULL, 0, NULL, NULL);
|
||||
test_error(err,"clEnqueueNDRangeKernel failed");
|
||||
}
|
||||
|
||||
for(cl_uint d=0; d < num_devices; d++) clFlush(queues[d]);
|
||||
|
||||
cl_uint host_id = num_devices; // host code will take the id above the devices.
|
||||
for(int i = (int)num_devices; i < num_elements; i+= num_devices_plus_host) pA[i] = host_id;
|
||||
|
||||
for(cl_uint id = 0; id < num_devices; id++) clFinish(queues[id]);
|
||||
|
||||
// now check that each device can see the byte writes made by the other devices.
|
||||
|
||||
err |= clSetKernelArgSVMPointer(k2, 0, pA);
|
||||
err |= clSetKernelArg(k2, 1, sizeof(cl_uint), &num_devices_plus_host);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
// adjusted so k2 doesn't read past end of buffer
|
||||
size_t adjusted_num_elements = num_elements - num_devices;
|
||||
for(cl_uint id = 0; id < num_devices; id++)
|
||||
{
|
||||
err = clSetKernelArgSVMPointer(k2, 2, error_counts[id]);
|
||||
err |= clSetKernelArgSVMPointer(k1, 0, pA);
|
||||
err |= clSetKernelArg(k1, 1, sizeof(cl_uint), &num_devices_plus_host);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
err = clEnqueueNDRangeKernel(queues[id], k2, 1, NULL, &adjusted_num_elements, NULL, 0, NULL, NULL);
|
||||
test_error(err,"clEnqueueNDRangeKernel failed");
|
||||
}
|
||||
// get all the devices going simultaneously
|
||||
size_t element_num = num_elements;
|
||||
for (cl_uint d = 0; d < num_devices; d++) // device ids starting at 1.
|
||||
{
|
||||
err = clSetKernelArg(k1, 2, sizeof(cl_uint), &d);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
err = clEnqueueNDRangeKernel(queues[d], k1, 1, NULL, &element_num, NULL,
|
||||
0, NULL, NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
}
|
||||
|
||||
for(cl_uint id = 0; id < num_devices; id++) clFinish(queues[id]);
|
||||
for (cl_uint d = 0; d < num_devices; d++) clFlush(queues[d]);
|
||||
|
||||
bool failed = false;
|
||||
cl_uint host_id =
|
||||
num_devices; // host code will take the id above the devices.
|
||||
for (int i = (int)num_devices; i < num_elements; i += num_devices_plus_host)
|
||||
pA[i] = host_id;
|
||||
|
||||
// see if any of the devices found errors
|
||||
for(cl_uint i=0; i < num_devices; i++) {
|
||||
if(*error_counts[i] > 0)
|
||||
failed = true;
|
||||
}
|
||||
cl_uint expected = (num_devices_plus_host * (num_devices_plus_host - 1))/2;
|
||||
// check that host can see the byte writes made by the devices.
|
||||
for(cl_uint i = 0; i < num_elements - num_devices_plus_host; i++)
|
||||
{
|
||||
int sum = 0;
|
||||
for(cl_uint j=0; j < num_devices_plus_host; j++) sum += pA[i+j];
|
||||
if(sum != expected)
|
||||
failed = true;
|
||||
}
|
||||
for (cl_uint id = 0; id < num_devices; id++) clFinish(queues[id]);
|
||||
|
||||
clSVMFree(context, pA);
|
||||
for(cl_uint i=0; i < num_devices; i++) clSVMFree(context, error_counts[i]);
|
||||
// now check that each device can see the byte writes made by the other
|
||||
// devices.
|
||||
|
||||
if(failed)
|
||||
return -1;
|
||||
return 0;
|
||||
err |= clSetKernelArgSVMPointer(k2, 0, pA);
|
||||
err |= clSetKernelArg(k2, 1, sizeof(cl_uint), &num_devices_plus_host);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
// adjusted so k2 doesn't read past end of buffer
|
||||
size_t adjusted_num_elements = num_elements - num_devices;
|
||||
for (cl_uint id = 0; id < num_devices; id++)
|
||||
{
|
||||
err = clSetKernelArgSVMPointer(k2, 2, error_counts[id]);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
err =
|
||||
clEnqueueNDRangeKernel(queues[id], k2, 1, NULL,
|
||||
&adjusted_num_elements, NULL, 0, NULL, NULL);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
}
|
||||
|
||||
for (cl_uint id = 0; id < num_devices; id++) clFinish(queues[id]);
|
||||
|
||||
bool failed = false;
|
||||
|
||||
// see if any of the devices found errors
|
||||
for (cl_uint i = 0; i < num_devices; i++)
|
||||
{
|
||||
if (*error_counts[i] > 0) failed = true;
|
||||
}
|
||||
cl_uint expected =
|
||||
(num_devices_plus_host * (num_devices_plus_host - 1)) / 2;
|
||||
// check that host can see the byte writes made by the devices.
|
||||
for (cl_uint i = 0; i < num_elements - num_devices_plus_host; i++)
|
||||
{
|
||||
int sum = 0;
|
||||
for (cl_uint j = 0; j < num_devices_plus_host; j++) sum += pA[i + j];
|
||||
if (sum != expected) failed = true;
|
||||
}
|
||||
|
||||
clSVMFree(context, pA);
|
||||
for (cl_uint i = 0; i < num_devices; i++)
|
||||
clSVMFree(context, error_counts[i]);
|
||||
|
||||
if (failed) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,92 +128,128 @@ cl_int verify_linked_lists_on_host(int ci, cl_command_queue cmdq, cl_mem nodes,
|
|||
// on another device or the host.
|
||||
// The linked list nodes are allocated from two different buffers this is done to ensure that cross buffer pointers work correctly.
|
||||
// This basic test is performed for all combinations of devices and the host.
|
||||
int test_svm_cross_buffer_pointers_coarse_grain(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_cross_buffer_pointers_coarse_grain)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
error = create_cl_objects(deviceID, &SVMCrossBufferPointers_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if(error) return -1;
|
||||
error = create_cl_objects(device, &SVMCrossBufferPointers_test_kernel[0],
|
||||
&contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (error) return -1;
|
||||
|
||||
size_t numLists = num_elements;
|
||||
cl_int ListLength = 32;
|
||||
size_t numLists = num_elements;
|
||||
cl_int ListLength = 32;
|
||||
|
||||
clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_create_lists =
|
||||
clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_verify_lists =
|
||||
clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
// this buffer holds some of the linked list nodes.
|
||||
Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(Node)*ListLength*numLists, 0);
|
||||
// this buffer holds some of the linked list nodes.
|
||||
Node *pNodes = (Node *)clSVMAlloc(context, CL_MEM_READ_WRITE,
|
||||
sizeof(Node) * ListLength * numLists, 0);
|
||||
|
||||
// this buffer holds some of the linked list nodes.
|
||||
Node* pNodes2 = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(Node)*ListLength*numLists, 0);
|
||||
// this buffer holds some of the linked list nodes.
|
||||
Node *pNodes2 = (Node *)clSVMAlloc(context, CL_MEM_READ_WRITE,
|
||||
sizeof(Node) * ListLength * numLists, 0);
|
||||
|
||||
{
|
||||
clMemWrapper nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
clMemWrapper nodes2 = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes2, &error);
|
||||
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);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
// this buffer holds the count of correct nodes which is computed by the verify kernel.
|
||||
clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void*), (void *) &nodes);
|
||||
//error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, (void *) pNodes);
|
||||
error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void*), (void *) &nodes2);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void*), (void *) &allocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 3, sizeof(cl_int), (void *) &ListLength);
|
||||
|
||||
error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void*), (void *) &nodes);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void*), (void *) &nodes2);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void*), (void *) &num_correct);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(cl_int), (void *) &ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// Create linked list on one device and verify on another device (or the host).
|
||||
// Do this for all possible combinations of devices and host within the platform.
|
||||
for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on
|
||||
{
|
||||
for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on
|
||||
{
|
||||
if(ci == num_devices) // last device index represents the host, note the num_device+1 above.
|
||||
{
|
||||
error = create_linked_lists_on_host(queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device(ci, queues[ci], allocator, kernel_create_lists, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
clMemWrapper nodes = clCreateBuffer(
|
||||
context, CL_MEM_USE_HOST_PTR, sizeof(Node) * ListLength * numLists,
|
||||
pNodes, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
if(vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists_on_host(vi, queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device(vi, queues[vi], num_correct, kernel_verify_lists, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
} // inner loop, vi
|
||||
} // outer loop, ci
|
||||
}
|
||||
clMemWrapper nodes2 = clCreateBuffer(
|
||||
context, CL_MEM_USE_HOST_PTR, sizeof(Node) * ListLength * numLists,
|
||||
pNodes2, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
clSVMFree(context, pNodes2);
|
||||
clSVMFree(context, pNodes);
|
||||
// this buffer holds the index into the nodes buffer that is used for
|
||||
// node allocation
|
||||
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(size_t), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
return 0;
|
||||
// this buffer holds the count of correct nodes which is computed by the
|
||||
// verify kernel.
|
||||
clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void *),
|
||||
(void *)&nodes);
|
||||
// error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, (void *)
|
||||
// pNodes);
|
||||
error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void *),
|
||||
(void *)&nodes2);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void *),
|
||||
(void *)&allocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 3, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
|
||||
error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void *),
|
||||
(void *)&nodes);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void *),
|
||||
(void *)&nodes2);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void *),
|
||||
(void *)&num_correct);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// Create linked list on one device and verify on another device (or the
|
||||
// host). Do this for all possible combinations of devices and host
|
||||
// within the platform.
|
||||
for (int ci = 0; ci < (int)num_devices + 1;
|
||||
ci++) // ci is CreationIndex, index of device/q to create linked
|
||||
// list on
|
||||
{
|
||||
for (int vi = 0; vi < (int)num_devices + 1;
|
||||
vi++) // vi is VerificationIndex, index of device/q to verify
|
||||
// linked list on
|
||||
{
|
||||
if (ci == num_devices) // last device index represents the host,
|
||||
// note the num_device+1 above.
|
||||
{
|
||||
error = create_linked_lists_on_host(
|
||||
queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device(
|
||||
ci, queues[ci], allocator, kernel_create_lists,
|
||||
numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
|
||||
if (vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists_on_host(
|
||||
vi, queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device(
|
||||
vi, queues[vi], num_correct, kernel_verify_lists,
|
||||
ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
} // inner loop, vi
|
||||
} // outer loop, ci
|
||||
}
|
||||
|
||||
clSVMFree(context, pNodes2);
|
||||
clSVMFree(context, pNodes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,240 +70,282 @@ void CL_CALLBACK callback_svm_free(cl_command_queue queue, cl_uint num_svm_point
|
|||
data->status.store(1, std::memory_order_release);
|
||||
}
|
||||
|
||||
int test_svm_enqueue_api(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_enqueue_api)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
cl_uint num_devices = 0;
|
||||
const size_t elementNum = 1024;
|
||||
const size_t numSVMBuffers = 32;
|
||||
cl_int error = CL_SUCCESS;
|
||||
RandomSeed seed(0);
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
cl_uint num_devices = 0;
|
||||
const size_t elementNum = 1024;
|
||||
const size_t numSVMBuffers = 32;
|
||||
cl_int error = CL_SUCCESS;
|
||||
RandomSeed seed(0);
|
||||
|
||||
error = create_cl_objects(deviceID, NULL, &context, NULL, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if(error) return TEST_FAIL;
|
||||
error = create_cl_objects(device, NULL, &contextWrapper, NULL, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (error) return TEST_FAIL;
|
||||
|
||||
queue = queues[0];
|
||||
queue = queues[0];
|
||||
|
||||
//all possible sizes of vectors and scalars
|
||||
size_t typeSizes[] = {
|
||||
sizeof(cl_uchar),
|
||||
sizeof(cl_uchar2),
|
||||
sizeof(cl_uchar3),
|
||||
sizeof(cl_uchar4),
|
||||
sizeof(cl_uchar8),
|
||||
sizeof(cl_uchar16),
|
||||
sizeof(cl_ushort),
|
||||
sizeof(cl_ushort2),
|
||||
sizeof(cl_ushort3),
|
||||
sizeof(cl_ushort4),
|
||||
sizeof(cl_ushort8),
|
||||
sizeof(cl_ushort16),
|
||||
sizeof(cl_uint),
|
||||
sizeof(cl_uint2),
|
||||
sizeof(cl_uint3),
|
||||
sizeof(cl_uint4),
|
||||
sizeof(cl_uint8),
|
||||
sizeof(cl_uint16),
|
||||
sizeof(cl_ulong),
|
||||
sizeof(cl_ulong2),
|
||||
sizeof(cl_ulong3),
|
||||
sizeof(cl_ulong4),
|
||||
sizeof(cl_ulong8),
|
||||
sizeof(cl_ulong16),
|
||||
};
|
||||
// all possible sizes of vectors and scalars
|
||||
size_t typeSizes[] = {
|
||||
sizeof(cl_uchar), sizeof(cl_uchar2), sizeof(cl_uchar3),
|
||||
sizeof(cl_uchar4), sizeof(cl_uchar8), sizeof(cl_uchar16),
|
||||
sizeof(cl_ushort), sizeof(cl_ushort2), sizeof(cl_ushort3),
|
||||
sizeof(cl_ushort4), sizeof(cl_ushort8), sizeof(cl_ushort16),
|
||||
sizeof(cl_uint), sizeof(cl_uint2), sizeof(cl_uint3),
|
||||
sizeof(cl_uint4), sizeof(cl_uint8), sizeof(cl_uint16),
|
||||
sizeof(cl_ulong), sizeof(cl_ulong2), sizeof(cl_ulong3),
|
||||
sizeof(cl_ulong4), sizeof(cl_ulong8), sizeof(cl_ulong16),
|
||||
};
|
||||
|
||||
enum allocationTypes {
|
||||
host,
|
||||
svm
|
||||
};
|
||||
|
||||
struct TestType {
|
||||
allocationTypes srcAlloc;
|
||||
allocationTypes dstAlloc;
|
||||
TestType(allocationTypes type1, allocationTypes type2): srcAlloc(type1), dstAlloc(type2){}
|
||||
};
|
||||
|
||||
std::vector<TestType> testTypes;
|
||||
|
||||
testTypes.push_back(TestType(host, host));
|
||||
testTypes.push_back(TestType(host, svm));
|
||||
testTypes.push_back(TestType(svm, host));
|
||||
testTypes.push_back(TestType(svm, svm));
|
||||
|
||||
for (const auto test_case : testTypes)
|
||||
{
|
||||
log_info("clEnqueueSVMMemcpy case: src_alloc = %s, dst_alloc = %s\n", test_case.srcAlloc == svm ? "svm" : "host", test_case.dstAlloc == svm ? "svm" : "host");
|
||||
for (size_t i = 0; i < ARRAY_SIZE(typeSizes); ++i)
|
||||
enum allocationTypes
|
||||
{
|
||||
//generate initial data
|
||||
std::vector<cl_uchar> fillData0(typeSizes[i]), fillData1(typeSizes[i]);
|
||||
generate_data(fillData0, typeSizes[i], seed);
|
||||
generate_data(fillData1, typeSizes[i], seed);
|
||||
size_t data_size = elementNum * typeSizes[i];
|
||||
std::vector<cl_uchar> srcHostData(data_size, 0);
|
||||
std::vector<cl_uchar> dstHostData(data_size, 0);
|
||||
generate_data(srcHostData, srcHostData.size(), seed);
|
||||
generate_data(dstHostData, dstHostData.size(), seed);
|
||||
host,
|
||||
svm
|
||||
};
|
||||
|
||||
cl_uchar *srcBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, data_size, 0);
|
||||
cl_uchar *dstBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, data_size, 0);
|
||||
struct TestType
|
||||
{
|
||||
allocationTypes srcAlloc;
|
||||
allocationTypes dstAlloc;
|
||||
TestType(allocationTypes type1, allocationTypes type2)
|
||||
: srcAlloc(type1), dstAlloc(type2)
|
||||
{}
|
||||
};
|
||||
|
||||
clEventWrapper userEvent = clCreateUserEvent(context, &error);
|
||||
test_error(error, "clCreateUserEvent failed");
|
||||
clEventWrapper eventMemFillList[2];
|
||||
std::vector<TestType> testTypes;
|
||||
|
||||
error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData0[0], typeSizes[i], data_size, 1, &userEvent, &eventMemFillList[0]);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
error = clEnqueueSVMMemFill(queue, dstBuffer, &fillData1[0], typeSizes[i], data_size, 1, &userEvent, &eventMemFillList[1]);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
testTypes.push_back(TestType(host, host));
|
||||
testTypes.push_back(TestType(host, svm));
|
||||
testTypes.push_back(TestType(svm, host));
|
||||
testTypes.push_back(TestType(svm, svm));
|
||||
|
||||
error = clSetUserEventStatus(userEvent, CL_COMPLETE);
|
||||
test_error(error, "clSetUserEventStatus failed");
|
||||
for (const auto test_case : testTypes)
|
||||
{
|
||||
log_info("clEnqueueSVMMemcpy case: src_alloc = %s, dst_alloc = %s\n",
|
||||
test_case.srcAlloc == svm ? "svm" : "host",
|
||||
test_case.dstAlloc == svm ? "svm" : "host");
|
||||
for (size_t i = 0; i < ARRAY_SIZE(typeSizes); ++i)
|
||||
{
|
||||
// generate initial data
|
||||
std::vector<cl_uchar> fillData0(typeSizes[i]),
|
||||
fillData1(typeSizes[i]);
|
||||
generate_data(fillData0, typeSizes[i], seed);
|
||||
generate_data(fillData1, typeSizes[i], seed);
|
||||
size_t data_size = elementNum * typeSizes[i];
|
||||
std::vector<cl_uchar> srcHostData(data_size, 0);
|
||||
std::vector<cl_uchar> dstHostData(data_size, 0);
|
||||
generate_data(srcHostData, srcHostData.size(), seed);
|
||||
generate_data(dstHostData, dstHostData.size(), seed);
|
||||
|
||||
cl_uchar * src_ptr;
|
||||
cl_uchar * dst_ptr;
|
||||
if (test_case.srcAlloc == host) {
|
||||
src_ptr = srcHostData.data();
|
||||
} else if (test_case.srcAlloc == svm) {
|
||||
src_ptr = srcBuffer;
|
||||
}
|
||||
if (test_case.dstAlloc == host) {
|
||||
dst_ptr = dstHostData.data();
|
||||
} else if (test_case.dstAlloc == svm) {
|
||||
dst_ptr = dstBuffer;
|
||||
}
|
||||
clEventWrapper eventMemcpy;
|
||||
error = clEnqueueSVMMemcpy(queue, CL_FALSE, dst_ptr, src_ptr, data_size, 2, &eventMemFillList[0], &eventMemcpy);
|
||||
test_error(error, "clEnqueueSVMMemcpy failed");
|
||||
cl_uchar *srcBuffer = (cl_uchar *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE, data_size, 0);
|
||||
cl_uchar *dstBuffer = (cl_uchar *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE, data_size, 0);
|
||||
|
||||
//coarse grain only supported. Synchronization required using map
|
||||
clEventWrapper eventMap[2];
|
||||
clEventWrapper userEvent = clCreateUserEvent(context, &error);
|
||||
test_error(error, "clCreateUserEvent failed");
|
||||
clEventWrapper eventMemFillList[2];
|
||||
|
||||
error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ, srcBuffer, data_size, 1, &eventMemcpy, &eventMap[0]);
|
||||
test_error(error, "clEnqueueSVMMap srcBuffer failed");
|
||||
error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData0[0],
|
||||
typeSizes[i], data_size, 1, &userEvent,
|
||||
&eventMemFillList[0]);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
error = clEnqueueSVMMemFill(queue, dstBuffer, &fillData1[0],
|
||||
typeSizes[i], data_size, 1, &userEvent,
|
||||
&eventMemFillList[1]);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
|
||||
error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ, dstBuffer, data_size, 1, &eventMemcpy, &eventMap[1]);
|
||||
test_error(error, "clEnqueueSVMMap dstBuffer failed");
|
||||
error = clSetUserEventStatus(userEvent, CL_COMPLETE);
|
||||
test_error(error, "clSetUserEventStatus failed");
|
||||
|
||||
error = clWaitForEvents(2, &eventMap[0]);
|
||||
test_error(error, "clWaitForEvents failed");
|
||||
cl_uchar *src_ptr = nullptr;
|
||||
cl_uchar *dst_ptr = nullptr;
|
||||
if (test_case.srcAlloc == host)
|
||||
{
|
||||
src_ptr = srcHostData.data();
|
||||
}
|
||||
else if (test_case.srcAlloc == svm)
|
||||
{
|
||||
src_ptr = srcBuffer;
|
||||
}
|
||||
if (test_case.dstAlloc == host)
|
||||
{
|
||||
dst_ptr = dstHostData.data();
|
||||
}
|
||||
else if (test_case.dstAlloc == svm)
|
||||
{
|
||||
dst_ptr = dstBuffer;
|
||||
}
|
||||
clEventWrapper eventMemcpy;
|
||||
error =
|
||||
clEnqueueSVMMemcpy(queue, CL_FALSE, dst_ptr, src_ptr, data_size,
|
||||
2, &eventMemFillList[0], &eventMemcpy);
|
||||
test_error(error, "clEnqueueSVMMemcpy failed");
|
||||
|
||||
//data verification
|
||||
for (size_t j = 0; j < data_size; ++j)
|
||||
{
|
||||
if (dst_ptr[j] != src_ptr[j]) {
|
||||
log_error("Invalid data at index %ld, dst_ptr %d, src_ptr %d\n", j, dst_ptr[j], src_ptr[j]);
|
||||
// coarse grain only supported. Synchronization required using map
|
||||
clEventWrapper eventMap[2];
|
||||
|
||||
error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ, srcBuffer,
|
||||
data_size, 1, &eventMemcpy, &eventMap[0]);
|
||||
test_error(error, "clEnqueueSVMMap srcBuffer failed");
|
||||
|
||||
error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ, dstBuffer,
|
||||
data_size, 1, &eventMemcpy, &eventMap[1]);
|
||||
test_error(error, "clEnqueueSVMMap dstBuffer failed");
|
||||
|
||||
error = clWaitForEvents(2, &eventMap[0]);
|
||||
test_error(error, "clWaitForEvents failed");
|
||||
|
||||
// data verification
|
||||
for (size_t j = 0; j < data_size; ++j)
|
||||
{
|
||||
if (dst_ptr[j] != src_ptr[j])
|
||||
{
|
||||
log_error(
|
||||
"Invalid data at index %zu, dst_ptr %d, src_ptr %d\n",
|
||||
j, dst_ptr[j], src_ptr[j]);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
clEventWrapper eventUnmap[2];
|
||||
error =
|
||||
clEnqueueSVMUnmap(queue, srcBuffer, 0, nullptr, &eventUnmap[0]);
|
||||
test_error(error, "clEnqueueSVMUnmap srcBuffer failed");
|
||||
|
||||
error =
|
||||
clEnqueueSVMUnmap(queue, dstBuffer, 0, nullptr, &eventUnmap[1]);
|
||||
test_error(error, "clEnqueueSVMUnmap dstBuffer failed");
|
||||
|
||||
error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData1[0],
|
||||
typeSizes[i], data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
|
||||
error = clEnqueueSVMMemFill(queue, dstBuffer + data_size / 2,
|
||||
&fillData1[0], typeSizes[i],
|
||||
data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
|
||||
error = clEnqueueSVMMemcpy(queue, CL_FALSE, dstBuffer, srcBuffer,
|
||||
data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemcpy failed");
|
||||
|
||||
error = clEnqueueSVMMemcpy(
|
||||
queue, CL_TRUE, dstBuffer + data_size / 2,
|
||||
srcBuffer + data_size / 2, data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemcpy failed");
|
||||
|
||||
void *ptrs[] = { (void *)srcBuffer, (void *)dstBuffer };
|
||||
|
||||
clEventWrapper eventFree;
|
||||
error = clEnqueueSVMFree(queue, 2, ptrs, 0, 0, 0, 0, &eventFree);
|
||||
test_error(error, "clEnqueueSVMFree failed");
|
||||
|
||||
error = clWaitForEvents(1, &eventFree);
|
||||
test_error(error, "clWaitForEvents failed");
|
||||
|
||||
// event info verification for new SVM commands
|
||||
cl_command_type commandType;
|
||||
for (auto &check_event : eventMemFillList)
|
||||
{
|
||||
error =
|
||||
clGetEventInfo(check_event, CL_EVENT_COMMAND_TYPE,
|
||||
sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_MEMFILL)
|
||||
{
|
||||
log_error("Invalid command type returned for "
|
||||
"clEnqueueSVMMemFill\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
error = clGetEventInfo(eventMemcpy, CL_EVENT_COMMAND_TYPE,
|
||||
sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_MEMCPY)
|
||||
{
|
||||
log_error(
|
||||
"Invalid command type returned for clEnqueueSVMMemcpy\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
for (size_t map_id = 0; map_id < ARRAY_SIZE(eventMap); map_id++)
|
||||
{
|
||||
error =
|
||||
clGetEventInfo(eventMap[map_id], CL_EVENT_COMMAND_TYPE,
|
||||
sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_MAP)
|
||||
{
|
||||
log_error(
|
||||
"Invalid command type returned for clEnqueueSVMMap\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
error =
|
||||
clGetEventInfo(eventUnmap[map_id], CL_EVENT_COMMAND_TYPE,
|
||||
sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_UNMAP)
|
||||
{
|
||||
log_error("Invalid command type returned for "
|
||||
"clEnqueueSVMUnmap\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
error = clGetEventInfo(eventFree, CL_EVENT_COMMAND_TYPE,
|
||||
sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_FREE)
|
||||
{
|
||||
log_error(
|
||||
"Invalid command type returned for clEnqueueSVMFree\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<void *> buffers(numSVMBuffers, 0);
|
||||
for (size_t i = 0; i < numSVMBuffers; ++i)
|
||||
buffers[i] = clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum, 0);
|
||||
|
||||
// verify if callback is triggered correctly
|
||||
CallbackData data;
|
||||
data.status = 0;
|
||||
|
||||
error = clEnqueueSVMFree(queue, buffers.size(), &buffers[0],
|
||||
callback_svm_free, &data, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMFree failed");
|
||||
|
||||
error = clFinish(queue);
|
||||
test_error(error, "clFinish failed");
|
||||
|
||||
// wait for the callback
|
||||
while (data.status.load(std::memory_order_acquire) == 0)
|
||||
{
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
// check if number of SVM pointers returned in the callback matches with
|
||||
// expected
|
||||
if (data.num_svm_pointers != buffers.size())
|
||||
{
|
||||
log_error("Invalid number of SVM pointers returned in the callback, "
|
||||
"expected: %zu, got: %d\n",
|
||||
buffers.size(), data.num_svm_pointers);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
// check if pointers returned in callback are correct
|
||||
for (size_t i = 0; i < buffers.size(); ++i)
|
||||
{
|
||||
if (data.svm_pointers[i] != buffers[i])
|
||||
{
|
||||
log_error(
|
||||
"Invalid SVM pointer returned in the callback, idx: %zu\n", i);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
clEventWrapper eventUnmap[2];
|
||||
error = clEnqueueSVMUnmap(queue, srcBuffer, 0, nullptr, &eventUnmap[0]);
|
||||
test_error(error, "clEnqueueSVMUnmap srcBuffer failed");
|
||||
|
||||
error = clEnqueueSVMUnmap(queue, dstBuffer, 0, nullptr, &eventUnmap[1]);
|
||||
test_error(error, "clEnqueueSVMUnmap dstBuffer failed");
|
||||
|
||||
error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData1[0], typeSizes[i], data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
|
||||
error = clEnqueueSVMMemFill(queue, dstBuffer + data_size / 2, &fillData1[0], typeSizes[i], data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemFill failed");
|
||||
|
||||
error = clEnqueueSVMMemcpy(queue, CL_FALSE, dstBuffer, srcBuffer, data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemcpy failed");
|
||||
|
||||
error = clEnqueueSVMMemcpy(queue, CL_TRUE, dstBuffer + data_size / 2, srcBuffer + data_size / 2, data_size / 2, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMMemcpy failed");
|
||||
|
||||
void *ptrs[] = { (void *)srcBuffer, (void *)dstBuffer };
|
||||
|
||||
clEventWrapper eventFree;
|
||||
error = clEnqueueSVMFree(queue, 2, ptrs, 0, 0, 0, 0, &eventFree);
|
||||
test_error(error, "clEnqueueSVMFree failed");
|
||||
|
||||
error = clWaitForEvents(1, &eventFree);
|
||||
test_error(error, "clWaitForEvents failed");
|
||||
|
||||
//event info verification for new SVM commands
|
||||
cl_command_type commandType;
|
||||
for (auto &check_event : eventMemFillList) {
|
||||
error = clGetEventInfo(check_event, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_MEMFILL)
|
||||
{
|
||||
log_error("Invalid command type returned for clEnqueueSVMMemFill\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
error = clGetEventInfo(eventMemcpy, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_MEMCPY)
|
||||
{
|
||||
log_error("Invalid command type returned for clEnqueueSVMMemcpy\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
for (size_t map_id = 0; map_id < ARRAY_SIZE(eventMap); map_id++) {
|
||||
error = clGetEventInfo(eventMap[map_id], CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_MAP)
|
||||
{
|
||||
log_error("Invalid command type returned for clEnqueueSVMMap\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
error = clGetEventInfo(eventUnmap[map_id], CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_UNMAP)
|
||||
{
|
||||
log_error("Invalid command type returned for clEnqueueSVMUnmap\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
error = clGetEventInfo(eventFree, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
|
||||
test_error(error, "clGetEventInfo failed");
|
||||
if (commandType != CL_COMMAND_SVM_FREE)
|
||||
{
|
||||
log_error("Invalid command type returned for clEnqueueSVMFree\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<void *> buffers(numSVMBuffers, 0);
|
||||
for(size_t i = 0; i < numSVMBuffers; ++i) buffers[i] = clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum, 0);
|
||||
|
||||
//verify if callback is triggered correctly
|
||||
CallbackData data;
|
||||
data.status = 0;
|
||||
|
||||
error = clEnqueueSVMFree(queue, buffers.size(), &buffers[0], callback_svm_free, &data, 0, 0, 0);
|
||||
test_error(error, "clEnqueueSVMFree failed");
|
||||
|
||||
error = clFinish(queue);
|
||||
test_error(error, "clFinish failed");
|
||||
|
||||
//wait for the callback
|
||||
while(data.status.load(std::memory_order_acquire) == 0) {
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
//check if number of SVM pointers returned in the callback matches with expected
|
||||
if (data.num_svm_pointers != buffers.size())
|
||||
{
|
||||
log_error("Invalid number of SVM pointers returned in the callback, expected: %ld, got: %d\n", buffers.size(), data.num_svm_pointers);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
//check if pointers returned in callback are correct
|
||||
for (size_t i = 0; i < buffers.size(); ++i)
|
||||
{
|
||||
if (data.svm_pointers[i] != buffers[i])
|
||||
{
|
||||
log_error("Invalid SVM pointer returned in the callback, idx: %ld\n", i);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,8 +126,10 @@ int launch_kernels_and_verify(clContextWrapper &context, clCommandQueueWrapper*
|
|||
// each device and the host inserted all of the pixels, check that none are missing.
|
||||
if(num_items != num_pixels * (num_devices + 1) )
|
||||
{
|
||||
log_error("The hash table is not correct, num items %d, expected num items: %d\n", num_items, num_pixels * (num_devices + 1));
|
||||
return -1; // test did not pass
|
||||
log_error("The hash table is not correct, num items %d, expected num "
|
||||
"items: %zu\n",
|
||||
num_items, num_pixels * (num_devices + 1));
|
||||
return -1; // test did not pass
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -137,44 +139,55 @@ int launch_kernels_and_verify(clContextWrapper &context, clCommandQueueWrapper*
|
|||
// Each bin in the hash table is a linked list. Each bin is protected against simultaneous
|
||||
// update using a lock free technique. The correctness of the list is verfied on the host.
|
||||
// This test requires the new OpenCL 2.0 atomic operations that implement the new seq_cst memory ordering.
|
||||
int test_svm_fine_grain_memory_consistency(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_fine_grain_memory_consistency)
|
||||
{
|
||||
clContextWrapper context;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper;
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
std::vector<std::string> required_extensions;
|
||||
required_extensions.push_back("cl_khr_int64_base_atomics");
|
||||
required_extensions.push_back("cl_khr_int64_extended_atomics");
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
std::vector<std::string> required_extensions;
|
||||
required_extensions.push_back("cl_khr_int64_base_atomics");
|
||||
required_extensions.push_back("cl_khr_int64_extended_atomics");
|
||||
|
||||
// Make pragmas visible for 64-bit addresses
|
||||
hash_table_kernel[4] = sizeof(void *) == 8 ? '1' : '0';
|
||||
// Make pragmas visible for 64-bit addresses
|
||||
hash_table_kernel[4] = sizeof(void *) == 8 ? '1' : '0';
|
||||
|
||||
char *source[] = { hash_table_kernel };
|
||||
char *source[] = { hash_table_kernel };
|
||||
|
||||
err = create_cl_objects(deviceID, (const char**)source, &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_ATOMICS, required_extensions);
|
||||
if(err == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing.
|
||||
if(err < 0) return -1; // fail test.
|
||||
err = create_cl_objects(
|
||||
device, (const char **)source, &contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_ATOMICS,
|
||||
required_extensions);
|
||||
context = contextWrapper;
|
||||
if (err == 1)
|
||||
return 0; // no devices capable of requested SVM level, so don't execute
|
||||
// but count test as passing.
|
||||
if (err < 0) return -1; // fail test.
|
||||
|
||||
kernel = clCreateKernel(program, "build_hash_table", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
size_t num_pixels = num_elements;
|
||||
kernel = clCreateKernel(program, "build_hash_table", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
size_t num_pixels = num_elements;
|
||||
|
||||
int result;
|
||||
cl_uint numBins = 1; // all work groups in all devices and the host code will hammer on this one lock.
|
||||
result = launch_kernels_and_verify(context, queues, kernel, num_devices, numBins, num_pixels);
|
||||
if(result == -1) return result;
|
||||
int result;
|
||||
cl_uint numBins = 1; // all work groups in all devices and the host code
|
||||
// will hammer on this one lock.
|
||||
result = launch_kernels_and_verify(contextWrapper, queues, kernel,
|
||||
num_devices, numBins, num_pixels);
|
||||
if (result == -1) return result;
|
||||
|
||||
numBins = 2; // 2 locks within in same cache line will get hit from different devices and host.
|
||||
result = launch_kernels_and_verify(context, queues, kernel, num_devices, numBins, num_pixels);
|
||||
if(result == -1) return result;
|
||||
numBins = 2; // 2 locks within in same cache line will get hit from
|
||||
// different devices and host.
|
||||
result = launch_kernels_and_verify(contextWrapper, queues, kernel,
|
||||
num_devices, numBins, num_pixels);
|
||||
if (result == -1) return result;
|
||||
|
||||
numBins = 29; // locks span a few cache lines.
|
||||
result = launch_kernels_and_verify(context, queues, kernel, num_devices, numBins, num_pixels);
|
||||
if(result == -1) return result;
|
||||
numBins = 29; // locks span a few cache lines.
|
||||
result = launch_kernels_and_verify(contextWrapper, queues, kernel,
|
||||
num_devices, numBins, num_pixels);
|
||||
if (result == -1) return result;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,67 +44,87 @@ void spawnAnalysisTask(int location)
|
|||
// Concept: a device kernel is used to search an input image for regions that match a target pattern.
|
||||
// The device immediately notifies the host when it finds a target (via an atomic operation that works across host and devices).
|
||||
// The host is then able to spawn a task that further analyzes the target while the device continues searching for more targets.
|
||||
int test_svm_fine_grain_sync_buffers(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_fine_grain_sync_buffers)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int err = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
err = create_cl_objects(deviceID, &find_targets_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_ATOMICS);
|
||||
if(err == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing.
|
||||
if(err < 0) return -1; // fail test.
|
||||
err = create_cl_objects(
|
||||
device, &find_targets_kernel[0], &contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER | CL_DEVICE_SVM_ATOMICS);
|
||||
context = contextWrapper;
|
||||
if (err == 1)
|
||||
return 0; // no devices capable of requested SVM level, so don't execute
|
||||
// but count test as passing.
|
||||
if (err < 0) return -1; // fail test.
|
||||
|
||||
clKernelWrapper kernel = clCreateKernel(program, "find_targets", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
clKernelWrapper kernel = clCreateKernel(program, "find_targets", &err);
|
||||
test_error(err, "clCreateKernel failed");
|
||||
|
||||
size_t num_pixels = num_elements;
|
||||
//cl_uint num_pixels = 1024*1024*32;
|
||||
size_t num_pixels = num_elements;
|
||||
// cl_uint num_pixels = 1024*1024*32;
|
||||
|
||||
cl_uint *pInputImage = (cl_uint*) clSVMAlloc(context, CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_uint) * num_pixels, 0);
|
||||
cl_uint *pNumTargetsFound = (cl_uint*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, sizeof(cl_uint), 0);
|
||||
cl_int *pTargetLocations = (cl_int* ) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, sizeof(cl_int) * MAX_TARGETS, 0);
|
||||
cl_uint *pInputImage = (cl_uint *)clSVMAlloc(
|
||||
context, CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
sizeof(cl_uint) * num_pixels, 0);
|
||||
cl_uint *pNumTargetsFound = (cl_uint *)clSVMAlloc(
|
||||
context,
|
||||
CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS,
|
||||
sizeof(cl_uint), 0);
|
||||
cl_int *pTargetLocations = (cl_int *)clSVMAlloc(
|
||||
context,
|
||||
CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS,
|
||||
sizeof(cl_int) * MAX_TARGETS, 0);
|
||||
|
||||
cl_uint targetDescriptor = 777;
|
||||
*pNumTargetsFound = 0;
|
||||
cl_uint i;
|
||||
for(i=0; i < MAX_TARGETS; i++) pTargetLocations[i] = -1;
|
||||
for(i=0; i < num_pixels; i++) pInputImage[i] = 0;
|
||||
pInputImage[0] = targetDescriptor;
|
||||
pInputImage[3] = targetDescriptor;
|
||||
pInputImage[num_pixels - 1] = targetDescriptor;
|
||||
cl_uint targetDescriptor = 777;
|
||||
*pNumTargetsFound = 0;
|
||||
cl_uint i;
|
||||
for (i = 0; i < MAX_TARGETS; i++) pTargetLocations[i] = -1;
|
||||
for (i = 0; i < num_pixels; i++) pInputImage[i] = 0;
|
||||
pInputImage[0] = targetDescriptor;
|
||||
pInputImage[3] = targetDescriptor;
|
||||
pInputImage[num_pixels - 1] = targetDescriptor;
|
||||
|
||||
err |= clSetKernelArgSVMPointer(kernel, 0, pInputImage);
|
||||
err |= clSetKernelArg(kernel, 1, sizeof(cl_uint), (void*) &targetDescriptor);
|
||||
err |= clSetKernelArgSVMPointer(kernel, 2, pNumTargetsFound);
|
||||
err |= clSetKernelArgSVMPointer(kernel, 3, pTargetLocations);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
err |= clSetKernelArgSVMPointer(kernel, 0, pInputImage);
|
||||
err |=
|
||||
clSetKernelArg(kernel, 1, sizeof(cl_uint), (void *)&targetDescriptor);
|
||||
err |= clSetKernelArgSVMPointer(kernel, 2, pNumTargetsFound);
|
||||
err |= clSetKernelArgSVMPointer(kernel, 3, pTargetLocations);
|
||||
test_error(err, "clSetKernelArg failed");
|
||||
|
||||
cl_event done;
|
||||
err = clEnqueueNDRangeKernel(queues[0], kernel, 1, NULL, &num_pixels, NULL, 0, NULL, &done);
|
||||
test_error(err,"clEnqueueNDRangeKernel failed");
|
||||
clFlush(queues[0]);
|
||||
cl_event done;
|
||||
err = clEnqueueNDRangeKernel(queues[0], kernel, 1, NULL, &num_pixels, NULL,
|
||||
0, NULL, &done);
|
||||
test_error(err, "clEnqueueNDRangeKernel failed");
|
||||
clFlush(queues[0]);
|
||||
|
||||
|
||||
i=0;
|
||||
cl_int status;
|
||||
// check for new targets, if found spawn a task to analyze target.
|
||||
do {
|
||||
err = clGetEventInfo(done,CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &status, NULL);
|
||||
test_error(err,"clGetEventInfo failed");
|
||||
if( AtomicLoadExplicit(&pTargetLocations[i], memory_order_relaxed) != -1) // -1 indicates slot not used yet.
|
||||
i = 0;
|
||||
cl_int status;
|
||||
// check for new targets, if found spawn a task to analyze target.
|
||||
do
|
||||
{
|
||||
spawnAnalysisTask(pTargetLocations[i]);
|
||||
i++;
|
||||
}
|
||||
} while (status != CL_COMPLETE || AtomicLoadExplicit(&pTargetLocations[i], memory_order_relaxed) != -1);
|
||||
err = clGetEventInfo(done, CL_EVENT_COMMAND_EXECUTION_STATUS,
|
||||
sizeof(cl_int), &status, NULL);
|
||||
test_error(err, "clGetEventInfo failed");
|
||||
if (AtomicLoadExplicit(&pTargetLocations[i], memory_order_relaxed)
|
||||
!= -1) // -1 indicates slot not used yet.
|
||||
{
|
||||
spawnAnalysisTask(pTargetLocations[i]);
|
||||
i++;
|
||||
}
|
||||
} while (status != CL_COMPLETE
|
||||
|| AtomicLoadExplicit(&pTargetLocations[i], memory_order_relaxed)
|
||||
!= -1);
|
||||
|
||||
clReleaseEvent(done);
|
||||
clSVMFree(context, pInputImage);
|
||||
clSVMFree(context, pNumTargetsFound);
|
||||
clSVMFree(context, pTargetLocations);
|
||||
clReleaseEvent(done);
|
||||
clSVMFree(context, pInputImage);
|
||||
clSVMFree(context, pNumTargetsFound);
|
||||
clSVMFree(context, pTargetLocations);
|
||||
|
||||
if(i != 3) return -1;
|
||||
return 0;
|
||||
if (i != 3) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "common.h"
|
||||
#include "harness/mt19937.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define GLOBAL_SIZE 65536
|
||||
|
||||
static const char *sources[] = {
|
||||
|
|
@ -73,29 +75,28 @@ wait_and_release(const char* s, cl_event* evs, int n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_migrate)
|
||||
{
|
||||
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;
|
||||
|
||||
RandomSeed seed(0);
|
||||
|
||||
clContextWrapper context = NULL;
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
cl_uint num_devices = 0;
|
||||
clProgramWrapper program;
|
||||
cl_int error;
|
||||
|
||||
error = create_cl_objects(deviceID, &sources[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if (error)
|
||||
return -1;
|
||||
error = create_cl_objects(device, &sources[0], &contextWrapper, &program,
|
||||
&queues[0], &num_devices,
|
||||
CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (error) return -1;
|
||||
|
||||
if (num_devices > 1) {
|
||||
log_info(" Running on two devices.\n");
|
||||
|
|
@ -148,9 +149,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
|
||||
{
|
||||
|
|
@ -201,7 +202,7 @@ int test_svm_migrate(cl_device_id deviceID, cl_context c, cl_command_queue queue
|
|||
|
||||
// Check the event command type for clEnqueueSVMMigrateMem (OpenCL 3.0 and
|
||||
// newer)
|
||||
Version version = get_device_cl_version(deviceID);
|
||||
Version version = get_device_cl_version(device);
|
||||
if (version >= Version(3, 0))
|
||||
{
|
||||
cl_command_type commandType;
|
||||
|
|
@ -221,9 +222,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 +308,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 };
|
||||
|
|
|
|||
|
|
@ -35,81 +35,107 @@ const char *SVMPointerPassing_test_kernel[] = {
|
|||
// The buffer is initialized to known values at each location.
|
||||
// The kernel checks that it finds the expected value at each location.
|
||||
// TODO: possibly make this work across all base types (including typeN?), also check ptr arithmetic ++,--.
|
||||
int test_svm_pointer_passing(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_pointer_passing)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
error = create_cl_objects(deviceID, &SVMPointerPassing_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if(error) return -1;
|
||||
error = create_cl_objects(device, &SVMPointerPassing_test_kernel[0],
|
||||
&contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (error) return -1;
|
||||
|
||||
clKernelWrapper kernel_verify_char = clCreateKernel(program, "verify_char", &error);
|
||||
test_error(error,"clCreateKernel failed");
|
||||
clKernelWrapper kernel_verify_char =
|
||||
clCreateKernel(program, "verify_char", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
size_t bufSize = 256;
|
||||
cl_uchar *pbuf_svm_alloc = (cl_uchar*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_uchar)*bufSize, 0);
|
||||
size_t bufSize = 256;
|
||||
cl_uchar *pbuf_svm_alloc = (cl_uchar *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE, sizeof(cl_uchar) * bufSize, 0);
|
||||
|
||||
cl_int *pNumCorrect = NULL;
|
||||
pNumCorrect = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_int), 0);
|
||||
cl_int *pNumCorrect = NULL;
|
||||
pNumCorrect =
|
||||
(cl_int *)clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_int), 0);
|
||||
|
||||
{
|
||||
clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_uchar)*bufSize, pbuf_svm_alloc, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_int), pNumCorrect, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
error = clSetKernelArg(kernel_verify_char, 1, sizeof(void*), (void *) &num_correct);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// put values into buf so that we can expect to see these values in the kernel when we pass a pointer to them.
|
||||
cl_command_queue cmdq = queues[0];
|
||||
cl_uchar* pbuf_map_buffer = (cl_uchar*) clEnqueueMapBuffer(cmdq, buf, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_uchar)*bufSize, 0, NULL,NULL, &error);
|
||||
test_error2(error, pbuf_map_buffer, "clEnqueueMapBuffer failed");
|
||||
for(int i = 0; i<(int)bufSize; i++)
|
||||
{
|
||||
pbuf_map_buffer[i]= (cl_uchar)i;
|
||||
}
|
||||
error = clEnqueueUnmapMemObject(cmdq, buf, pbuf_map_buffer, 0,NULL,NULL);
|
||||
test_error(error, "clEnqueueUnmapMemObject failed.");
|
||||
clMemWrapper buf =
|
||||
clCreateBuffer(context, CL_MEM_USE_HOST_PTR,
|
||||
sizeof(cl_uchar) * bufSize, pbuf_svm_alloc, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
for (cl_uint ii = 0; ii<num_devices; ++ii) // iterate over all devices in the platform.
|
||||
{
|
||||
cmdq = queues[ii];
|
||||
for(int i = 0; i<(int)bufSize; i++)
|
||||
{
|
||||
cl_uchar* pChar = &pbuf_svm_alloc[i];
|
||||
error = clSetKernelArgSVMPointer(kernel_verify_char, 0, pChar); // pass a pointer to a location within the buffer
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
error = clSetKernelArg(kernel_verify_char, 2, sizeof(cl_uchar), (void *) &i ); // pass the expected value at the above location.
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
error = clEnqueueNDRangeKernel(cmdq, kernel_verify_char, 1, NULL, &bufSize, NULL, 0, NULL, NULL);
|
||||
test_error(error,"clEnqueueNDRangeKernel failed");
|
||||
clMemWrapper num_correct = clCreateBuffer(
|
||||
context, CL_MEM_USE_HOST_PTR, sizeof(cl_int), pNumCorrect, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
pNumCorrect = (cl_int*) clEnqueueMapBuffer(cmdq, num_correct, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error);
|
||||
test_error2(error, pNumCorrect, "clEnqueueMapBuffer failed");
|
||||
cl_int correct_count = *pNumCorrect;
|
||||
error = clEnqueueUnmapMemObject(cmdq, num_correct, pNumCorrect, 0,NULL,NULL);
|
||||
error = clSetKernelArg(kernel_verify_char, 1, sizeof(void *),
|
||||
(void *)&num_correct);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// put values into buf so that we can expect to see these values in the
|
||||
// kernel when we pass a pointer to them.
|
||||
cl_command_queue cmdq = queues[0];
|
||||
cl_uchar *pbuf_map_buffer = (cl_uchar *)clEnqueueMapBuffer(
|
||||
cmdq, buf, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0,
|
||||
sizeof(cl_uchar) * bufSize, 0, NULL, NULL, &error);
|
||||
test_error2(error, pbuf_map_buffer, "clEnqueueMapBuffer failed");
|
||||
for (int i = 0; i < (int)bufSize; i++)
|
||||
{
|
||||
pbuf_map_buffer[i] = (cl_uchar)i;
|
||||
}
|
||||
error =
|
||||
clEnqueueUnmapMemObject(cmdq, buf, pbuf_map_buffer, 0, NULL, NULL);
|
||||
test_error(error, "clEnqueueUnmapMemObject failed.");
|
||||
|
||||
if(correct_count != 1)
|
||||
for (cl_uint ii = 0; ii < num_devices;
|
||||
++ii) // iterate over all devices in the platform.
|
||||
{
|
||||
log_error("Passing pointer directly to kernel for byte #%d failed on device %d\n", i, ii);
|
||||
return -1;
|
||||
cmdq = queues[ii];
|
||||
for (int i = 0; i < (int)bufSize; i++)
|
||||
{
|
||||
cl_uchar *pChar = &pbuf_svm_alloc[i];
|
||||
error = clSetKernelArgSVMPointer(
|
||||
kernel_verify_char, 0,
|
||||
pChar); // pass a pointer to a location within the buffer
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
error = clSetKernelArg(kernel_verify_char, 2, sizeof(cl_uchar),
|
||||
(void *)&i); // pass the expected value
|
||||
// at the above location.
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
error =
|
||||
clEnqueueNDRangeKernel(cmdq, kernel_verify_char, 1, NULL,
|
||||
&bufSize, NULL, 0, NULL, NULL);
|
||||
test_error(error, "clEnqueueNDRangeKernel failed");
|
||||
|
||||
pNumCorrect = (cl_int *)clEnqueueMapBuffer(
|
||||
cmdq, num_correct, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0,
|
||||
sizeof(cl_int), 0, NULL, NULL, &error);
|
||||
test_error2(error, pNumCorrect, "clEnqueueMapBuffer failed");
|
||||
cl_int correct_count = *pNumCorrect;
|
||||
error = clEnqueueUnmapMemObject(cmdq, num_correct, pNumCorrect,
|
||||
0, NULL, NULL);
|
||||
test_error(error, "clEnqueueUnmapMemObject failed.");
|
||||
|
||||
if (correct_count != 1)
|
||||
{
|
||||
log_error("Passing pointer directly to kernel for byte #%d "
|
||||
"failed on device %d\n",
|
||||
i, ii);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
error = clFinish(cmdq);
|
||||
test_error(error, "clFinish failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error = clFinish(cmdq);
|
||||
test_error(error, "clFinish failed");
|
||||
}
|
||||
|
||||
clSVMFree(context, pbuf_svm_alloc);
|
||||
clSVMFree(context, pNumCorrect);
|
||||
|
||||
clSVMFree(context, pbuf_svm_alloc);
|
||||
clSVMFree(context, pNumCorrect);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ const char *set_kernel_exec_info_svm_ptrs_kernel[] = {
|
|||
|
||||
// Test that clSetKernelExecInfo works correctly with CL_KERNEL_EXEC_INFO_SVM_PTRS flag.
|
||||
//
|
||||
int test_svm_set_kernel_exec_info_svm_ptrs(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_set_kernel_exec_info_svm_ptrs)
|
||||
{
|
||||
clContextWrapper c = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
|
|
@ -50,8 +50,11 @@ int test_svm_set_kernel_exec_info_svm_ptrs(cl_device_id deviceID, cl_context con
|
|||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
//error = create_cl_objects(deviceID, &set_kernel_exec_info_svm_ptrs_kernel[0], &context, &program, &q, &num_devices, CL_DEVICE_SVM_FINE_GRAIN);
|
||||
error = create_cl_objects(deviceID, &set_kernel_exec_info_svm_ptrs_kernel[0], &c, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
// error = create_cl_objects(device, &set_kernel_exec_info_svm_ptrs_kernel[0],
|
||||
// &context, &program, &q, &num_devices, CL_DEVICE_SVM_FINE_GRAIN);
|
||||
error = create_cl_objects(device, &set_kernel_exec_info_svm_ptrs_kernel[0],
|
||||
&c, &program, &queues[0], &num_devices,
|
||||
CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if(error == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing.
|
||||
if(error < 0) return -1; // fail test.
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -271,12 +272,14 @@ int shared_address_space_coarse_grain(cl_device_id deviceID, cl_context context2
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_svm_shared_address_space_coarse_grain_old_api(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_shared_address_space_coarse_grain_old_api)
|
||||
{
|
||||
return shared_address_space_coarse_grain(deviceID, context2, queue, num_elements, CL_FALSE);
|
||||
return shared_address_space_coarse_grain(device, context, queue,
|
||||
num_elements, CL_FALSE);
|
||||
}
|
||||
|
||||
int test_svm_shared_address_space_coarse_grain_new_api(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_shared_address_space_coarse_grain_new_api)
|
||||
{
|
||||
return shared_address_space_coarse_grain(deviceID, context2, queue, num_elements, CL_TRUE);
|
||||
return shared_address_space_coarse_grain(device, context, queue,
|
||||
num_elements, CL_TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,82 +20,103 @@
|
|||
// This is done by creating a linked list on a device and then verifying the correctness of the list
|
||||
// on another device or the host. This basic test is performed for all combinations of devices and the host that exist within
|
||||
// the platform. The test passes only if every combination passes.
|
||||
int test_svm_shared_address_space_fine_grain(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_shared_address_space_fine_grain)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
error = create_cl_objects(deviceID, &linked_list_create_and_verify_kernels[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_SYSTEM);
|
||||
if(error == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing.
|
||||
if(error < 0) return -1; // fail test.
|
||||
error = create_cl_objects(device, &linked_list_create_and_verify_kernels[0],
|
||||
&contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_FINE_GRAIN_SYSTEM);
|
||||
context = contextWrapper;
|
||||
if (error == 1)
|
||||
return 0; // no devices capable of requested SVM level, so don't execute
|
||||
// but count test as passing.
|
||||
if (error < 0) return -1; // fail test.
|
||||
|
||||
size_t numLists = num_elements;
|
||||
cl_int ListLength = 32;
|
||||
size_t numLists = num_elements;
|
||||
cl_int ListLength = 32;
|
||||
|
||||
clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_create_lists =
|
||||
clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_verify_lists =
|
||||
clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
// this allocation holds the linked list nodes.
|
||||
// FIXME: remove the alignment once prototype can handle it
|
||||
Node* pNodes = (Node*) align_malloc(numLists*ListLength*sizeof(Node),128);
|
||||
test_error2(error, pNodes, "malloc failed");
|
||||
// this allocation holds the linked list nodes.
|
||||
// FIXME: remove the alignment once prototype can handle it
|
||||
Node *pNodes =
|
||||
(Node *)align_malloc(numLists * ListLength * sizeof(Node), 128);
|
||||
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);
|
||||
test_error2(error, pAllocator, "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(size_t), 128);
|
||||
test_error2(error, pAllocator, "malloc failed");
|
||||
|
||||
// this allocation holds the count of correct nodes, which is computed by the verify kernel.
|
||||
cl_int* pNum_correct = (cl_int*) align_malloc(sizeof(cl_int), 128);
|
||||
test_error2(error, pNum_correct, "malloc failed");
|
||||
// this allocation holds the count of correct nodes, which is computed by
|
||||
// the verify kernel.
|
||||
cl_int *pNum_correct = (cl_int *)align_malloc(sizeof(cl_int), 128);
|
||||
test_error2(error, pNum_correct, "malloc failed");
|
||||
|
||||
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 1, pAllocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int),(void *) &ListLength);
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 1, pAllocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 1, pNum_correct);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int), (void *) &ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 1, pNum_correct);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// Create linked list on one device and verify on another device (or the host).
|
||||
// Do this for all possible combinations of devices and host within the platform.
|
||||
for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on
|
||||
{
|
||||
for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on
|
||||
// Create linked list on one device and verify on another device (or the
|
||||
// host). Do this for all possible combinations of devices and host within
|
||||
// the platform.
|
||||
for (int ci = 0; ci < (int)num_devices + 1;
|
||||
ci++) // ci is CreationIndex, index of device/q to create linked list
|
||||
// on
|
||||
{
|
||||
if(ci == num_devices) // last device index represents the host, note the num_device+1 above.
|
||||
{
|
||||
log_info("creating linked list on host ");
|
||||
create_linked_lists(pNodes, numLists, ListLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device_no_map(ci, queues[ci], pAllocator, kernel_create_lists, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
for (int vi = 0; vi < (int)num_devices + 1;
|
||||
vi++) // vi is VerificationIndex, index of device/q to verify
|
||||
// linked list on
|
||||
{
|
||||
if (ci == num_devices) // last device index represents the host,
|
||||
// note the num_device+1 above.
|
||||
{
|
||||
log_info("creating linked list on host ");
|
||||
create_linked_lists(pNodes, numLists, ListLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device_no_map(
|
||||
ci, queues[ci], pAllocator, kernel_create_lists, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
|
||||
if(vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists(pNodes, numLists, ListLength);
|
||||
if(error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device_no_map(vi, queues[vi], pNum_correct, kernel_verify_lists, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
if (vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists(pNodes, numLists, ListLength);
|
||||
if (error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device_no_map(
|
||||
vi, queues[vi], pNum_correct, kernel_verify_lists,
|
||||
ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
align_free(pNodes);
|
||||
align_free(pAllocator);
|
||||
align_free(pNum_correct);
|
||||
return 0;
|
||||
align_free(pNodes);
|
||||
align_free(pAllocator);
|
||||
align_free(pNum_correct);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,78 +61,104 @@ cl_int verify_linked_lists_on_device_no_map(int vi, cl_command_queue cmdq,cl_int
|
|||
// This is done by creating a linked list on a device and then verifying the correctness of the list
|
||||
// on another device or the host. This basic test is performed for all combinations of devices and the host that exist within
|
||||
// the platform. The test passes only if every combination passes.
|
||||
int test_svm_shared_address_space_fine_grain_buffers(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_shared_address_space_fine_grain_buffers)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
error = create_cl_objects(deviceID, &linked_list_create_and_verify_kernels[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER);
|
||||
if(error == 1) return 0; // no devices capable of requested SVM level, so don't execute but count test as passing.
|
||||
if(error < 0) return -1; // fail test.
|
||||
error = create_cl_objects(device, &linked_list_create_and_verify_kernels[0],
|
||||
&contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_FINE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (error == 1)
|
||||
return 0; // no devices capable of requested SVM level, so don't execute
|
||||
// but count test as passing.
|
||||
if (error < 0) return -1; // fail test.
|
||||
|
||||
size_t numLists = num_elements;
|
||||
cl_int ListLength = 32;
|
||||
size_t numLists = num_elements;
|
||||
cl_int ListLength = 32;
|
||||
|
||||
clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_create_lists =
|
||||
clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_verify_lists =
|
||||
clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
// this buffer holds the linked list nodes.
|
||||
Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(Node)*ListLength*numLists, 0);
|
||||
// this buffer holds the linked list nodes.
|
||||
Node *pNodes = (Node *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
sizeof(Node) * ListLength * numLists, 0);
|
||||
|
||||
// this buffer holds an index into the nodes buffer, it is used for node allocation
|
||||
size_t *pAllocator = (size_t*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(size_t), 0);
|
||||
// this buffer holds an index into the nodes buffer, it is used for node
|
||||
// allocation
|
||||
size_t *pAllocator = (size_t *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
sizeof(size_t), 0);
|
||||
|
||||
// this buffer holds the count of correct nodes, which is computed by the verify kernel.
|
||||
cl_int *pNumCorrect = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, sizeof(cl_int), 0);
|
||||
// this buffer holds the count of correct nodes, which is computed by the
|
||||
// verify kernel.
|
||||
cl_int *pNumCorrect = (cl_int *)clSVMAlloc(
|
||||
context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER,
|
||||
sizeof(cl_int), 0);
|
||||
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 1, pAllocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int), (void *) &ListLength);
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_create_lists, 1, pAllocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 1, pNumCorrect);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int), (void *) &ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 0, pNodes);
|
||||
error |= clSetKernelArgSVMPointer(kernel_verify_lists, 1, pNumCorrect);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// Create linked list on one device and verify on another device (or the host).
|
||||
// Do this for all possible combinations of devices and host within the platform.
|
||||
for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on
|
||||
{
|
||||
for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on
|
||||
// Create linked list on one device and verify on another device (or the
|
||||
// host). Do this for all possible combinations of devices and host within
|
||||
// the platform.
|
||||
for (int ci = 0; ci < (int)num_devices + 1;
|
||||
ci++) // ci is CreationIndex, index of device/q to create linked list
|
||||
// on
|
||||
{
|
||||
if(ci == num_devices) // last device index represents the host, note the num_device+1 above.
|
||||
{
|
||||
log_info("SVM: creating linked list on host ");
|
||||
create_linked_lists(pNodes, numLists, ListLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device_no_map(ci, queues[ci], pAllocator, kernel_create_lists, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
for (int vi = 0; vi < (int)num_devices + 1;
|
||||
vi++) // vi is VerificationIndex, index of device/q to verify
|
||||
// linked list on
|
||||
{
|
||||
if (ci == num_devices) // last device index represents the host,
|
||||
// note the num_device+1 above.
|
||||
{
|
||||
log_info("SVM: creating linked list on host ");
|
||||
create_linked_lists(pNodes, numLists, ListLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device_no_map(
|
||||
ci, queues[ci], pAllocator, kernel_create_lists, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
|
||||
if(vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists(pNodes, numLists, ListLength);
|
||||
if(error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device_no_map(vi, queues[vi], pNumCorrect, kernel_verify_lists, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
if (vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists(pNodes, numLists, ListLength);
|
||||
if (error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device_no_map(
|
||||
vi, queues[vi], pNumCorrect, kernel_verify_lists,
|
||||
ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clSVMFree(context, pNodes);
|
||||
clSVMFree(context, pAllocator);
|
||||
clSVMFree(context, pNumCorrect);
|
||||
clSVMFree(context, pNodes);
|
||||
clSVMFree(context, pAllocator);
|
||||
clSVMFree(context, pNumCorrect);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,117 +125,160 @@ cl_int verify_linked_lists_on_host_sb(int ci, cl_command_queue cmdq, cl_mem node
|
|||
// on another device or the host.
|
||||
// The linked list nodes are allocated from two different buffers this is done to ensure that cross buffer pointers work correctly.
|
||||
// This basic test is performed for all combinations of devices and the host.
|
||||
int test_svm_shared_sub_buffers(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(svm_shared_sub_buffers)
|
||||
{
|
||||
clContextWrapper context = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
clContextWrapper contextWrapper = NULL;
|
||||
clProgramWrapper program = NULL;
|
||||
cl_uint num_devices = 0;
|
||||
cl_int error = CL_SUCCESS;
|
||||
clCommandQueueWrapper queues[MAXQ];
|
||||
|
||||
error = create_cl_objects(deviceID, &shared_sub_buffers_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
if(error) return -1;
|
||||
error = create_cl_objects(device, &shared_sub_buffers_test_kernel[0],
|
||||
&contextWrapper, &program, &queues[0],
|
||||
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
|
||||
context = contextWrapper;
|
||||
if (error) return -1;
|
||||
|
||||
size_t numLists = num_elements;
|
||||
if(numLists & 0x1) numLists++; // force even size, so we can easily create two sub-buffers of same size.
|
||||
size_t numLists = num_elements;
|
||||
if (numLists & 0x1)
|
||||
numLists++; // force even size, so we can easily create two sub-buffers
|
||||
// of same size.
|
||||
|
||||
cl_int ListLength = 32;
|
||||
cl_int ListLength = 32;
|
||||
|
||||
clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_create_lists =
|
||||
clCreateKernel(program, "create_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
clKernelWrapper kernel_verify_lists =
|
||||
clCreateKernel(program, "verify_linked_lists", &error);
|
||||
test_error(error, "clCreateKernel failed");
|
||||
|
||||
size_t nodes_bufsize = sizeof(Node)*ListLength*numLists;
|
||||
Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0);
|
||||
Node* pNodes2 = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0);
|
||||
size_t nodes_bufsize = sizeof(Node) * ListLength * numLists;
|
||||
Node *pNodes =
|
||||
(Node *)clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0);
|
||||
Node *pNodes2 =
|
||||
(Node *)clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0);
|
||||
|
||||
{
|
||||
// this buffer holds some of the linked list nodes.
|
||||
clMemWrapper nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, nodes_bufsize, pNodes, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
cl_buffer_region r;
|
||||
r.origin = 0;
|
||||
r.size = nodes_bufsize / 2;
|
||||
// this should inherit the flag settings from nodes buffer
|
||||
clMemWrapper nodes_sb1 = clCreateSubBuffer(nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
r.origin = nodes_bufsize / 2;
|
||||
clMemWrapper nodes_sb2 = clCreateSubBuffer(nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
|
||||
|
||||
// this buffer holds some of the linked list nodes.
|
||||
clMemWrapper nodes2 = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes2, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
r.origin = 0;
|
||||
r.size = nodes_bufsize / 2;
|
||||
// this should inherit the flag settings from nodes buffer
|
||||
clMemWrapper nodes2_sb1 = clCreateSubBuffer(nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
r.origin = nodes_bufsize / 2;
|
||||
clMemWrapper nodes2_sb2 = clCreateSubBuffer(nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION,(void*)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
// this buffer holds the count of correct nodes which is computed by the verify kernel.
|
||||
clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void*), (void *) &nodes_sb1);
|
||||
error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void*), (void *) &nodes2_sb1);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void*), (void *) &nodes_sb2);
|
||||
error |= clSetKernelArg(kernel_create_lists, 3, sizeof(void*), (void *) &nodes2_sb2);
|
||||
error |= clSetKernelArg(kernel_create_lists, 4, sizeof(void*), (void *) &allocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 5, sizeof(cl_int),(void *) &ListLength);
|
||||
|
||||
error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void*), (void *) &nodes_sb1);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void*), (void *) &nodes2_sb1);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void*), (void *) &nodes_sb2);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(void*), (void *) &nodes2_sb2);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 4, sizeof(void*), (void *) &num_correct);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 5, sizeof(cl_int),(void *) &ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// Create linked list on one device and verify on another device (or the host).
|
||||
// Do this for all possible combinations of devices and host within the platform.
|
||||
for (int ci=0; ci<(int)num_devices+1; ci++) // ci is CreationIndex, index of device/q to create linked list on
|
||||
{
|
||||
for (int vi=0; vi<(int)num_devices+1; vi++) // vi is VerificationIndex, index of device/q to verify linked list on
|
||||
{
|
||||
if(ci == num_devices) // last device index represents the host, note the num_device+1 above.
|
||||
{
|
||||
error = create_linked_lists_on_host_sb(queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device(ci, queues[ci], allocator, kernel_create_lists, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
// this buffer holds some of the linked list nodes.
|
||||
clMemWrapper nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR,
|
||||
nodes_bufsize, pNodes, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
if(vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists_on_host_sb(vi, queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device(vi, queues[vi], num_correct, kernel_verify_lists, ListLength, numLists);
|
||||
if(error) return -1;
|
||||
}
|
||||
} // inner loop, vi
|
||||
} // outer loop, ci
|
||||
}
|
||||
clSVMFree(context, pNodes2);
|
||||
clSVMFree(context, pNodes);
|
||||
cl_buffer_region r;
|
||||
r.origin = 0;
|
||||
r.size = nodes_bufsize / 2;
|
||||
// this should inherit the flag settings from nodes buffer
|
||||
clMemWrapper nodes_sb1 = clCreateSubBuffer(
|
||||
nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void *)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
r.origin = nodes_bufsize / 2;
|
||||
clMemWrapper nodes_sb2 = clCreateSubBuffer(
|
||||
nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void *)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
|
||||
return 0;
|
||||
|
||||
// this buffer holds some of the linked list nodes.
|
||||
clMemWrapper nodes2 = clCreateBuffer(
|
||||
context, CL_MEM_USE_HOST_PTR, sizeof(Node) * ListLength * numLists,
|
||||
pNodes2, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
r.origin = 0;
|
||||
r.size = nodes_bufsize / 2;
|
||||
// this should inherit the flag settings from nodes buffer
|
||||
clMemWrapper nodes2_sb1 = clCreateSubBuffer(
|
||||
nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION, (void *)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
r.origin = nodes_bufsize / 2;
|
||||
clMemWrapper nodes2_sb2 = clCreateSubBuffer(
|
||||
nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION, (void *)&r, &error);
|
||||
test_error(error, "clCreateSubBuffer");
|
||||
|
||||
|
||||
// this buffer holds the index into the nodes buffer that is used for
|
||||
// node allocation
|
||||
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.
|
||||
clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE,
|
||||
sizeof(cl_int), NULL, &error);
|
||||
test_error(error, "clCreateBuffer failed.");
|
||||
|
||||
error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void *),
|
||||
(void *)&nodes_sb1);
|
||||
error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void *),
|
||||
(void *)&nodes2_sb1);
|
||||
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void *),
|
||||
(void *)&nodes_sb2);
|
||||
error |= clSetKernelArg(kernel_create_lists, 3, sizeof(void *),
|
||||
(void *)&nodes2_sb2);
|
||||
error |= clSetKernelArg(kernel_create_lists, 4, sizeof(void *),
|
||||
(void *)&allocator);
|
||||
error |= clSetKernelArg(kernel_create_lists, 5, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
|
||||
error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void *),
|
||||
(void *)&nodes_sb1);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void *),
|
||||
(void *)&nodes2_sb1);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void *),
|
||||
(void *)&nodes_sb2);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(void *),
|
||||
(void *)&nodes2_sb2);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 4, sizeof(void *),
|
||||
(void *)&num_correct);
|
||||
error |= clSetKernelArg(kernel_verify_lists, 5, sizeof(cl_int),
|
||||
(void *)&ListLength);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
|
||||
// Create linked list on one device and verify on another device (or the
|
||||
// host). Do this for all possible combinations of devices and host
|
||||
// within the platform.
|
||||
for (int ci = 0; ci < (int)num_devices + 1;
|
||||
ci++) // ci is CreationIndex, index of device/q to create linked
|
||||
// list on
|
||||
{
|
||||
for (int vi = 0; vi < (int)num_devices + 1;
|
||||
vi++) // vi is VerificationIndex, index of device/q to verify
|
||||
// linked list on
|
||||
{
|
||||
if (ci == num_devices) // last device index represents the host,
|
||||
// note the num_device+1 above.
|
||||
{
|
||||
error = create_linked_lists_on_host_sb(
|
||||
queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = create_linked_lists_on_device(
|
||||
ci, queues[ci], allocator, kernel_create_lists,
|
||||
numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
|
||||
if (vi == num_devices)
|
||||
{
|
||||
error = verify_linked_lists_on_host_sb(
|
||||
vi, queues[0], nodes, nodes2, ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = verify_linked_lists_on_device(
|
||||
vi, queues[vi], num_correct, kernel_verify_lists,
|
||||
ListLength, numLists);
|
||||
if (error) return -1;
|
||||
}
|
||||
} // inner loop, vi
|
||||
} // outer loop, ci
|
||||
}
|
||||
clSVMFree(context, pNodes2);
|
||||
clSVMFree(context, pNodes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@ set(${MODULE_NAME}_SOURCES
|
|||
allocation_utils.cpp
|
||||
)
|
||||
|
||||
set_gnulike_module_compile_flags("-Wno-sign-compare")
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -16,18 +16,27 @@
|
|||
#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"
|
||||
"__kernel void sample_test(%s __global uint *result, __global %s "
|
||||
"*array_sizes, uint per_item)\n"
|
||||
"{\n"
|
||||
"\tint tid = get_global_id(0);\n"
|
||||
"\tuint r = 0;\n"
|
||||
"\t%s i;\n"
|
||||
"\tfor(i=(%s)tid*(%s)per_item; i<(%s)(1+tid)*(%s)per_item; i++) {\n"
|
||||
"%s"
|
||||
"\t}\n"
|
||||
"\tresult[tid] = r;\n"
|
||||
"}\n" };
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char *accumulate_pattern = {
|
||||
"\t%s end%d = min((%s)(1+tid)*(%s)per_item, array_sizes[%d]);\n"
|
||||
"\tfor(i=(%s)tid*(%s)per_item; i<end%d; i++) {\n"
|
||||
"\t\tr += buffer%d[i];\n"
|
||||
"\t}\n"
|
||||
};
|
||||
|
||||
const char *image_kernel_pattern = {
|
||||
"__kernel void sample_test(%s __global uint *result)\n"
|
||||
|
|
@ -38,7 +47,8 @@ const char *image_kernel_pattern = {
|
|||
"\tint x, y;\n"
|
||||
"%s"
|
||||
"\tresult[get_global_id(0)] += color.x + color.y + color.z + color.w;\n"
|
||||
"}\n" };
|
||||
"}\n"
|
||||
};
|
||||
|
||||
const char *read_pattern = {
|
||||
"\tfor(y=0; y<get_image_height(image%d); y++)\n"
|
||||
|
|
@ -48,11 +58,11 @@ const char *read_pattern = {
|
|||
"\t\t\t}\n"
|
||||
};
|
||||
|
||||
const char *offset_pattern =
|
||||
"\tconst uint4 offset = (uint4)(0,1,2,3);\n";
|
||||
const char *offset_pattern = "\tconst uint4 offset = (uint4)(0,1,2,3);\n";
|
||||
|
||||
const char *sampler_pattern =
|
||||
"\tconst sampler_t sampler = CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST | CLK_NORMALIZED_COORDS_FALSE;\n";
|
||||
"\tconst sampler_t sampler = CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST | "
|
||||
"CLK_NORMALIZED_COORDS_FALSE;\n";
|
||||
|
||||
|
||||
const char *write_pattern = {
|
||||
|
|
@ -66,7 +76,8 @@ const char *write_pattern = {
|
|||
};
|
||||
|
||||
|
||||
int check_image(cl_command_queue queue, cl_mem mem) {
|
||||
int check_image(cl_command_queue queue, cl_mem mem)
|
||||
{
|
||||
int error;
|
||||
cl_mem_object_type type;
|
||||
size_t width, height;
|
||||
|
|
@ -74,30 +85,42 @@ int check_image(cl_command_queue queue, cl_mem mem) {
|
|||
cl_uint *data;
|
||||
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_TYPE, sizeof(type), &type, NULL);
|
||||
if (error) {
|
||||
if (error)
|
||||
{
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_MEM_TYPE.");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
data = (cl_uint*)malloc(width*4*sizeof(cl_uint));
|
||||
if (data == NULL) {
|
||||
data = (cl_uint *)malloc(width * 4 * sizeof(cl_uint));
|
||||
if (data == NULL)
|
||||
{
|
||||
log_error("Failed to malloc host buffer for writing into image.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
|
@ -107,19 +130,27 @@ int check_image(cl_command_queue queue, cl_mem mem) {
|
|||
region[0] = width;
|
||||
region[1] = 1;
|
||||
region[2] = 1;
|
||||
for (origin[1] = 0; origin[1] < height; origin[1]++) {
|
||||
error = clEnqueueReadImage(queue, mem, CL_TRUE, origin, region, 0, 0, data, 0, NULL, NULL);
|
||||
if (error) {
|
||||
for (origin[1] = 0; origin[1] < height; origin[1]++)
|
||||
{
|
||||
error = clEnqueueReadImage(queue, mem, CL_TRUE, origin, region, 0, 0,
|
||||
data, 0, NULL, NULL);
|
||||
if (error)
|
||||
{
|
||||
print_error(error, "clEnqueueReadImage failed");
|
||||
free(data);
|
||||
return error;
|
||||
}
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
for (j=0; j<4; j++) {
|
||||
if (data[x*4+j] != (cl_uint)(x*origin[1]+j)) {
|
||||
log_error("Pixel %d, %d, component %d, expected %u, got %u.\n",
|
||||
(int)x, (int)origin[1], (int)j, (cl_uint)(x*origin[1]+j), data[x*4+j]);
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (data[x * 4 + j] != (cl_uint)(x * origin[1] + j))
|
||||
{
|
||||
log_error(
|
||||
"Pixel %d, %d, component %d, expected %u, got %u.\n",
|
||||
(int)x, (int)origin[1], (int)j,
|
||||
(cl_uint)(x * origin[1] + j), data[x * 4 + j]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -130,9 +161,11 @@ int check_image(cl_command_queue queue, cl_mem mem) {
|
|||
}
|
||||
|
||||
|
||||
#define NUM_OF_WORK_ITEMS 8192*2
|
||||
|
||||
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) {
|
||||
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,
|
||||
unsigned int number_of_work_items)
|
||||
{
|
||||
|
||||
char *argument_string;
|
||||
char *access_string;
|
||||
|
|
@ -145,73 +178,112 @@ 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(number_of_work_items);
|
||||
clEventWrapper event;
|
||||
cl_int event_status;
|
||||
|
||||
// Allocate memory for the kernel source
|
||||
argument_string = (char*)malloc(sizeof(char)*MAX_NUMBER_TO_ALLOCATE*64);
|
||||
access_string = (char*)malloc(sizeof(char)*MAX_NUMBER_TO_ALLOCATE*(strlen(read_pattern)+10));
|
||||
kernel_string = (char*)malloc(sizeof(char)*MAX_NUMBER_TO_ALLOCATE*(strlen(read_pattern)+10+64)+1024);
|
||||
char *used_pattern = nullptr;
|
||||
if (test == BUFFER || test == BUFFER_NON_BLOCKING)
|
||||
{
|
||||
used_pattern = (char *)accumulate_pattern;
|
||||
}
|
||||
else if (test == IMAGE_READ || test == IMAGE_READ_NON_BLOCKING)
|
||||
{
|
||||
used_pattern = (char *)read_pattern;
|
||||
}
|
||||
else if (test == IMAGE_WRITE || test == IMAGE_WRITE_NON_BLOCKING)
|
||||
{
|
||||
used_pattern = (char *)write_pattern;
|
||||
}
|
||||
argument_string =
|
||||
(char *)malloc(sizeof(char) * MAX_NUMBER_TO_ALLOCATE * 64);
|
||||
access_string = (char *)malloc(sizeof(char) * MAX_NUMBER_TO_ALLOCATE
|
||||
* (strlen(used_pattern) + 10));
|
||||
kernel_string = (char *)malloc(sizeof(char) * MAX_NUMBER_TO_ALLOCATE
|
||||
* (strlen(used_pattern) + 10 + 64)
|
||||
+ 1024);
|
||||
|
||||
argument_string[0] = '\0';
|
||||
access_string[0] = '\0';
|
||||
kernel_string[0] = '\0';
|
||||
|
||||
// Zero the results.
|
||||
for (i=0; i<NUM_OF_WORK_ITEMS; i++)
|
||||
returned_results[i] = 0;
|
||||
for (i = 0; i < number_of_work_items; i++) returned_results[i] = 0;
|
||||
|
||||
// detect if device supports ulong/int64
|
||||
//detect whether profile of the device is embedded
|
||||
// detect whether profile of the device is embedded
|
||||
bool support64 = true;
|
||||
char profile[1024] = "";
|
||||
error = clGetDeviceInfo(device_id, CL_DEVICE_PROFILE, sizeof(profile), profile, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" );
|
||||
if ((NULL != strstr(profile, "EMBEDDED_PROFILE")) &&
|
||||
(!is_extension_available(device_id, "cles_khr_int64"))) {
|
||||
support64 = false;
|
||||
error = clGetDeviceInfo(device_id, CL_DEVICE_PROFILE, sizeof(profile),
|
||||
profile, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n");
|
||||
if ((NULL != strstr(profile, "EMBEDDED_PROFILE"))
|
||||
&& (!is_extension_available(device_id, "cles_khr_int64")))
|
||||
{
|
||||
support64 = false;
|
||||
}
|
||||
|
||||
// Build the kernel source
|
||||
if (test == BUFFER || test == BUFFER_NON_BLOCKING) {
|
||||
for(i=0; i<number_of_mems_used; i++) {
|
||||
sprintf(argument_string + strlen(argument_string), " __global uint *buffer%d, ", i);
|
||||
sprintf(access_string + strlen( access_string), "\t\tif (i<array_sizes[%d]) r += buffer%d[i];\n", i, i);
|
||||
}
|
||||
if (test == BUFFER || test == BUFFER_NON_BLOCKING)
|
||||
{
|
||||
char type[10];
|
||||
if (support64) {
|
||||
if (support64)
|
||||
{
|
||||
sprintf(type, "ulong");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
sprintf(type, "uint");
|
||||
}
|
||||
sprintf(kernel_string, buffer_kernel_pattern, argument_string, type, type, type, type, type, type, access_string);
|
||||
}
|
||||
else if (test == IMAGE_READ || test == IMAGE_READ_NON_BLOCKING) {
|
||||
for(i=0; i<number_of_mems_used; i++) {
|
||||
sprintf(argument_string + strlen(argument_string), " read_only image2d_t image%d, ", i);
|
||||
sprintf(access_string + strlen(access_string), read_pattern, i, "%", i, i);
|
||||
for (i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
sprintf(argument_string + strlen(argument_string),
|
||||
" __global uint *buffer%d, ", i);
|
||||
sprintf(access_string + strlen(access_string), accumulate_pattern,
|
||||
type, i, type, type, i, type, type, i, i);
|
||||
}
|
||||
sprintf(kernel_string, image_kernel_pattern, argument_string, sampler_pattern, access_string);
|
||||
sprintf(kernel_string, buffer_kernel_pattern, argument_string, type,
|
||||
type, access_string);
|
||||
}
|
||||
else if (test == IMAGE_WRITE || test == IMAGE_WRITE_NON_BLOCKING) {
|
||||
for(i=0; i<number_of_mems_used; i++) {
|
||||
sprintf(argument_string + strlen(argument_string), " write_only image2d_t image%d, ", i);
|
||||
sprintf(access_string + strlen( access_string), write_pattern, i, "%", i, i);
|
||||
else if (test == IMAGE_READ || test == IMAGE_READ_NON_BLOCKING)
|
||||
{
|
||||
for (i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
sprintf(argument_string + strlen(argument_string),
|
||||
" read_only image2d_t image%d, ", i);
|
||||
sprintf(access_string + strlen(access_string), read_pattern, i, "%",
|
||||
i, i);
|
||||
}
|
||||
sprintf(kernel_string, image_kernel_pattern, argument_string, offset_pattern, access_string);
|
||||
sprintf(kernel_string, image_kernel_pattern, argument_string,
|
||||
sampler_pattern, access_string);
|
||||
}
|
||||
else if (test == IMAGE_WRITE || test == IMAGE_WRITE_NON_BLOCKING)
|
||||
{
|
||||
for (i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
sprintf(argument_string + strlen(argument_string),
|
||||
" write_only image2d_t image%d, ", i);
|
||||
sprintf(access_string + strlen(access_string), write_pattern, i,
|
||||
"%", i, i);
|
||||
}
|
||||
sprintf(kernel_string, image_kernel_pattern, argument_string,
|
||||
offset_pattern, access_string);
|
||||
}
|
||||
ptr = kernel_string;
|
||||
|
||||
// Create the kernel
|
||||
error = create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&ptr, "sample_test" );
|
||||
error = create_single_kernel_helper(context, &program, &kernel, 1,
|
||||
(const char **)&ptr, "sample_test");
|
||||
|
||||
free(argument_string);
|
||||
free(access_string);
|
||||
free(kernel_string);
|
||||
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
if (result != SUCCEEDED) {
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
if (result == FAILED_TOO_BIG)
|
||||
log_info("\t\tCreate kernel failed: %s.\n", IGetErrorString(error));
|
||||
else
|
||||
|
|
@ -220,78 +292,109 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
}
|
||||
|
||||
// Set the arguments
|
||||
for (i=0; i<number_of_mems_used; i++) {
|
||||
for (i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
error = clSetKernelArg(kernel, i, sizeof(cl_mem), &mems[i]);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
}
|
||||
|
||||
// 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) * number_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");
|
||||
|
||||
// Thread dimensions for execution
|
||||
global_dims[0] = NUM_OF_WORK_ITEMS; global_dims[1] = 1; global_dims[2] = 1;
|
||||
global_dims[0] = number_of_work_items;
|
||||
global_dims[1] = 1;
|
||||
global_dims[2] = 1;
|
||||
|
||||
// We have extra arguments for the buffer kernel because we need to pass in the buffer sizes
|
||||
// We have extra arguments for the buffer kernel because we need to pass in
|
||||
// the buffer sizes
|
||||
cl_ulong *ulSizes = NULL;
|
||||
cl_uint *uiSizes = NULL;
|
||||
if (support64) {
|
||||
ulSizes = (cl_ulong*)malloc(sizeof(cl_ulong)*number_of_mems_used);
|
||||
cl_uint *uiSizes = NULL;
|
||||
if (support64)
|
||||
{
|
||||
ulSizes = (cl_ulong *)malloc(sizeof(cl_ulong) * number_of_mems_used);
|
||||
}
|
||||
else {
|
||||
uiSizes = (cl_uint*)malloc(sizeof(cl_uint)*number_of_mems_used);
|
||||
else
|
||||
{
|
||||
uiSizes = (cl_uint *)malloc(sizeof(cl_uint) * number_of_mems_used);
|
||||
}
|
||||
cl_ulong max_size = 0;
|
||||
clMemWrapper buffer_sizes;
|
||||
if (test == BUFFER || test == BUFFER_NON_BLOCKING) {
|
||||
for (i=0; i<number_of_mems_used; i++) {
|
||||
if (test == BUFFER || test == BUFFER_NON_BLOCKING)
|
||||
{
|
||||
for (i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
size_t size;
|
||||
error = clGetMemObjectInfo(mems[i], CL_MEM_SIZE, sizeof(size), &size, NULL);
|
||||
test_error_abort(error, "clGetMemObjectInfo failed for CL_MEM_SIZE.");
|
||||
if (support64) {
|
||||
ulSizes[i] = size/sizeof(cl_uint);
|
||||
error = clGetMemObjectInfo(mems[i], CL_MEM_SIZE, sizeof(size),
|
||||
&size, NULL);
|
||||
test_error_abort(error,
|
||||
"clGetMemObjectInfo failed for CL_MEM_SIZE.");
|
||||
if (support64)
|
||||
{
|
||||
ulSizes[i] = size / sizeof(cl_uint);
|
||||
}
|
||||
else {
|
||||
uiSizes[i] = (cl_uint)size/sizeof(cl_uint);
|
||||
else
|
||||
{
|
||||
uiSizes[i] = (cl_uint)size / sizeof(cl_uint);
|
||||
}
|
||||
if (size/sizeof(cl_uint) > max_size)
|
||||
max_size = size/sizeof(cl_uint);
|
||||
if (size / sizeof(cl_uint) > max_size)
|
||||
max_size = size / sizeof(cl_uint);
|
||||
}
|
||||
if (support64) {
|
||||
buffer_sizes = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(cl_ulong)*number_of_mems_used, ulSizes, &error);
|
||||
if (support64)
|
||||
{
|
||||
buffer_sizes = clCreateBuffer(
|
||||
context, CL_MEM_COPY_HOST_PTR,
|
||||
sizeof(cl_ulong) * number_of_mems_used, ulSizes, &error);
|
||||
}
|
||||
else {
|
||||
buffer_sizes = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(cl_uint)*number_of_mems_used, uiSizes, &error);
|
||||
else
|
||||
{
|
||||
buffer_sizes = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
|
||||
sizeof(cl_uint) * number_of_mems_used,
|
||||
uiSizes, &error);
|
||||
}
|
||||
test_error_abort(error, "clCreateBuffer failed");
|
||||
error = clSetKernelArg(kernel, number_of_mems_used+1, sizeof(cl_mem), &buffer_sizes);
|
||||
error = clSetKernelArg(kernel, number_of_mems_used + 1, sizeof(cl_mem),
|
||||
&buffer_sizes);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
per_item = (cl_uint)ceil((double)max_size/global_dims[0]);
|
||||
per_item = (cl_uint)ceil((double)max_size / global_dims[0]);
|
||||
if (per_item > CL_UINT_MAX)
|
||||
log_error("Size is too large for a uint parameter to the kernel. Expect invalid results.\n");
|
||||
log_error("Size is too large for a uint parameter to the kernel. "
|
||||
"Expect invalid results.\n");
|
||||
per_item_uint = (cl_uint)per_item;
|
||||
error = clSetKernelArg(kernel, number_of_mems_used+2, sizeof(per_item_uint), &per_item_uint);
|
||||
error = clSetKernelArg(kernel, number_of_mems_used + 2,
|
||||
sizeof(per_item_uint), &per_item_uint);
|
||||
test_error(error, "clSetKernelArg failed");
|
||||
}
|
||||
if (ulSizes) {
|
||||
if (ulSizes)
|
||||
{
|
||||
free(ulSizes);
|
||||
}
|
||||
if (uiSizes) {
|
||||
if (uiSizes)
|
||||
{
|
||||
free(uiSizes);
|
||||
}
|
||||
|
||||
size_t local_dims[3] = {1,1,1};
|
||||
error = get_max_common_work_group_size(context, kernel, global_dims[0], &local_dims[0]);
|
||||
size_t local_dims[3] = { 1, 1, 1 };
|
||||
error = get_max_common_work_group_size(context, kernel, global_dims[0],
|
||||
&local_dims[0]);
|
||||
test_error(error, "get_max_common_work_group_size failed");
|
||||
|
||||
// Execute the kernel
|
||||
error = clEnqueueNDRangeKernel(*queue, kernel, 1, NULL, global_dims, local_dims, 0, NULL, &event);
|
||||
error = clEnqueueNDRangeKernel(*queue, kernel, 1, NULL, global_dims,
|
||||
local_dims, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
if (result != SUCCEEDED) {
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
if (result == FAILED_TOO_BIG)
|
||||
log_info("\t\tExecute kernel failed: %s (global dim: %ld, local dim: %ld)\n", IGetErrorString(error), global_dims[0], local_dims[0]);
|
||||
log_info("\t\tExecute kernel failed: %s (global dim: %zu, local "
|
||||
"dim: %zu)\n",
|
||||
IGetErrorString(error), global_dims[0], local_dims[0]);
|
||||
else
|
||||
print_error(error, "clEnqueueNDRangeKernel failed");
|
||||
return result;
|
||||
|
|
@ -302,7 +405,8 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
if (result == FAILED_TOO_BIG)
|
||||
log_info("\t\tclFinish failed: %s.\n", IGetErrorString(error));
|
||||
else
|
||||
|
|
@ -311,13 +415,20 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
}
|
||||
|
||||
// Verify that the event from the execution did not have an error
|
||||
error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(event_status), &event_status, NULL);
|
||||
test_error_abort(error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
|
||||
if (event_status < 0) {
|
||||
result = check_allocation_error(context, device_id, event_status, queue);
|
||||
if (result != SUCCEEDED) {
|
||||
error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
|
||||
sizeof(event_status), &event_status, NULL);
|
||||
test_error_abort(
|
||||
error, "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
|
||||
if (event_status < 0)
|
||||
{
|
||||
result =
|
||||
check_allocation_error(context, device_id, event_status, queue);
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
if (result == FAILED_TOO_BIG)
|
||||
log_info("\t\tEvent returned from kernel execution indicates failure: %s.\n", IGetErrorString(event_status));
|
||||
log_info("\t\tEvent returned from kernel execution indicates "
|
||||
"failure: %s.\n",
|
||||
IGetErrorString(event_status));
|
||||
else
|
||||
print_error(event_status, "clEnqueueNDRangeKernel failed");
|
||||
return result;
|
||||
|
|
@ -325,31 +436,46 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
}
|
||||
|
||||
// If we are not verifying the checksum return here
|
||||
if (!verify_checksum) {
|
||||
log_info("Note: Allocations were not initialized so kernel execution can not verify correct results.\n");
|
||||
if (!verify_checksum)
|
||||
{
|
||||
log_info("Note: Allocations were not initialized so kernel execution "
|
||||
"can not verify correct results.\n");
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
// 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) * number_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) {
|
||||
// For buffers or read images we are just looking at the sum of what each thread summed up
|
||||
for (i=0; i<NUM_OF_WORK_ITEMS; i++) {
|
||||
if (test == BUFFER || test == IMAGE_READ || test == BUFFER_NON_BLOCKING
|
||||
|| test == IMAGE_READ_NON_BLOCKING)
|
||||
{
|
||||
// For buffers or read images we are just looking at the sum of what
|
||||
// each thread summed up
|
||||
for (i = 0; i < number_of_work_items; i++)
|
||||
{
|
||||
final_result += returned_results[i];
|
||||
}
|
||||
if (final_result != checksum) {
|
||||
log_error("\t\tChecksum failed to verify. Expected %u got %u.\n", checksum, final_result);
|
||||
if (final_result != checksum)
|
||||
{
|
||||
log_error("\t\tChecksum failed to verify. Expected %u got %u.\n",
|
||||
checksum, final_result);
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
log_info("\t\tChecksum verified (%u == %u).\n", checksum, final_result);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// For write images we need to verify the values
|
||||
for (i=0; i<number_of_mems_used; i++) {
|
||||
if (check_image(*queue, mems[i])) {
|
||||
log_error("\t\tImage contents failed to verify for image %d.\n", (int)i);
|
||||
for (i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
if (check_image(*queue, mems[i]))
|
||||
{
|
||||
log_error("\t\tImage contents failed to verify for image %d.\n",
|
||||
(int)i);
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
}
|
||||
|
|
@ -359,7 +485,8 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
// Finish the test
|
||||
error = clFinish(*queue);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
if (result != SUCCEEDED) {
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
if (result == FAILED_TOO_BIG)
|
||||
log_info("\t\tclFinish failed: %s.\n", IGetErrorString(error));
|
||||
else
|
||||
|
|
@ -369,5 +496,3 @@ int execute_kernel(cl_context context, cl_command_queue *queue, cl_device_id dev
|
|||
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include "allocation_utils.h"
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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,
|
||||
unsigned int number_of_work_items);
|
||||
|
|
|
|||
|
|
@ -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,315 +15,387 @@
|
|||
//
|
||||
#include "allocation_fill.h"
|
||||
|
||||
#define BUFFER_CHUNK_SIZE 8*1024*1024
|
||||
#define BUFFER_CHUNK_SIZE 8 * 1024 * 1024
|
||||
#define IMAGE_LINES 8
|
||||
|
||||
#include "harness/compat.h"
|
||||
|
||||
int fill_buffer_with_data(cl_context context, cl_device_id device_id, cl_command_queue *queue, cl_mem mem, size_t size, MTdata d, cl_bool blocking_write) {
|
||||
size_t i, j;
|
||||
cl_uint *data;
|
||||
int error, result;
|
||||
cl_uint checksum_delta = 0;
|
||||
cl_event event;
|
||||
int fill_buffer_with_data(cl_context context, cl_device_id device_id,
|
||||
cl_command_queue *queue, cl_mem mem, size_t size,
|
||||
MTdata d, cl_bool blocking_write)
|
||||
{
|
||||
size_t i, j;
|
||||
cl_uint *data;
|
||||
int error, result;
|
||||
cl_uint checksum_delta = 0;
|
||||
cl_event event;
|
||||
|
||||
size_t size_to_use = BUFFER_CHUNK_SIZE;
|
||||
if (size_to_use > size)
|
||||
size_to_use = size;
|
||||
size_t size_to_use = BUFFER_CHUNK_SIZE;
|
||||
if (size_to_use > size) size_to_use = size;
|
||||
|
||||
data = (cl_uint*)malloc(size_to_use);
|
||||
if (data == NULL) {
|
||||
log_error("Failed to malloc host buffer for writing into buffer.\n");
|
||||
data = (cl_uint *)malloc(size_to_use);
|
||||
if (data == NULL)
|
||||
{
|
||||
log_error("Failed to malloc host buffer for writing into buffer.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
for (i = 0; i < size - size_to_use; i += size_to_use)
|
||||
{
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j = 0; j < size_to_use / sizeof(cl_uint); j++)
|
||||
{
|
||||
data[j] = genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
if (blocking_write)
|
||||
{
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_TRUE, i, size_to_use,
|
||||
data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_FALSE, i, size_to_use,
|
||||
data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue,
|
||||
&event);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with any leftover bits
|
||||
if (i < size)
|
||||
{
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j = 0; j < (size - i) / sizeof(cl_uint); j++)
|
||||
{
|
||||
data[j] = (cl_uint)genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
|
||||
if (blocking_write)
|
||||
{
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_TRUE, i, size - i,
|
||||
data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_FALSE, i, size - i,
|
||||
data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue,
|
||||
&event);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
// Only update the checksum if this succeeded.
|
||||
checksum += checksum_delta;
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
int fill_image_with_data(cl_context context, cl_device_id device_id,
|
||||
cl_command_queue *queue, cl_mem mem, size_t width,
|
||||
size_t height, MTdata d, cl_bool blocking_write)
|
||||
{
|
||||
size_t origin[3], region[3], j;
|
||||
int error, result;
|
||||
cl_uint *data;
|
||||
cl_uint checksum_delta = 0;
|
||||
cl_event event;
|
||||
|
||||
size_t image_lines_to_use;
|
||||
image_lines_to_use = IMAGE_LINES;
|
||||
if (image_lines_to_use > height) image_lines_to_use = height;
|
||||
|
||||
data = (cl_uint *)malloc(width * 4 * sizeof(cl_uint) * image_lines_to_use);
|
||||
if (data == NULL)
|
||||
{
|
||||
log_error("Failed to malloc host buffer for writing into image.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
origin[0] = 0;
|
||||
origin[1] = 0;
|
||||
origin[2] = 0;
|
||||
region[0] = width;
|
||||
region[1] = image_lines_to_use;
|
||||
region[2] = 1;
|
||||
for (origin[1] = 0; origin[1] < height - image_lines_to_use;
|
||||
origin[1] += image_lines_to_use)
|
||||
{
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j = 0; j < width * 4 * image_lines_to_use; j++)
|
||||
{
|
||||
data[j] = (cl_uint)genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
|
||||
if (blocking_write)
|
||||
{
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_TRUE, origin, region, 0,
|
||||
0, data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
result = clFinish(*queue);
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
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);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue,
|
||||
&event);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with any leftover bits
|
||||
if (origin[1] < height)
|
||||
{
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j = 0; j < width * 4 * (height - origin[1]); j++)
|
||||
{
|
||||
data[j] = (cl_uint)genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
|
||||
region[1] = height - origin[1];
|
||||
if (blocking_write)
|
||||
{
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_TRUE, origin, region, 0,
|
||||
0, data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_FALSE, origin, region,
|
||||
0, 0, data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue,
|
||||
&event);
|
||||
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
clFinish(*queue);
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
// Only update the checksum if this succeeded.
|
||||
checksum += checksum_delta;
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
int fill_mem_with_data(cl_context context, cl_device_id device_id,
|
||||
cl_command_queue *queue, cl_mem mem, MTdata d,
|
||||
cl_bool blocking_write)
|
||||
{
|
||||
int error;
|
||||
cl_mem_object_type type;
|
||||
size_t size, width, height;
|
||||
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_TYPE, sizeof(type), &type, NULL);
|
||||
test_error_abort(error, "clGetMemObjectInfo failed for CL_MEM_TYPE.");
|
||||
|
||||
if (type == CL_MEM_OBJECT_BUFFER)
|
||||
{
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(size), &size, NULL);
|
||||
test_error_abort(error, "clGetMemObjectInfo failed for CL_MEM_SIZE.");
|
||||
return fill_buffer_with_data(context, device_id, queue, mem, size, d,
|
||||
blocking_write);
|
||||
}
|
||||
else if (type == CL_MEM_OBJECT_IMAGE2D)
|
||||
{
|
||||
error =
|
||||
clGetImageInfo(mem, CL_IMAGE_WIDTH, sizeof(width), &width, NULL);
|
||||
test_error_abort(error, "clGetImageInfo failed for CL_IMAGE_WIDTH.");
|
||||
error =
|
||||
clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL);
|
||||
test_error_abort(error, "clGetImageInfo failed for CL_IMAGE_HEIGHT.");
|
||||
return fill_image_with_data(context, device_id, queue, mem, width,
|
||||
height, d, blocking_write);
|
||||
}
|
||||
|
||||
log_error("Invalid CL_MEM_TYPE: %d\n", type);
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
for (i=0; i<size-size_to_use; i+=size_to_use) {
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j=0; j<size_to_use/sizeof(cl_uint); j++) {
|
||||
data[j] = genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
if (blocking_write) {
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_TRUE, i, size_to_use, data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_FALSE, i, size_to_use, data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue, &event);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with any leftover bits
|
||||
if (i < size) {
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j=0; j<(size-i)/sizeof(cl_uint); j++) {
|
||||
data[j] = (cl_uint)genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
|
||||
if (blocking_write) {
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_TRUE, i, size-i, data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
error = clEnqueueWriteBuffer(*queue, mem, CL_FALSE, i, size-i, data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteBuffer failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue, &event);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
// Only update the checksum if this succeeded.
|
||||
checksum += checksum_delta;
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
int fill_image_with_data(cl_context context, cl_device_id device_id, cl_command_queue *queue, cl_mem mem, size_t width, size_t height, MTdata d, cl_bool blocking_write) {
|
||||
size_t origin[3], region[3], j;
|
||||
int error, result;
|
||||
cl_uint *data;
|
||||
cl_uint checksum_delta = 0;
|
||||
cl_event event;
|
||||
|
||||
size_t image_lines_to_use;
|
||||
image_lines_to_use = IMAGE_LINES;
|
||||
if (image_lines_to_use > height)
|
||||
image_lines_to_use = height;
|
||||
|
||||
data = (cl_uint*)malloc(width*4*sizeof(cl_uint)*image_lines_to_use);
|
||||
if (data == NULL) {
|
||||
log_error("Failed to malloc host buffer for writing into image.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
origin[0] = 0;
|
||||
origin[1] = 0;
|
||||
origin[2] = 0;
|
||||
region[0] = width;
|
||||
region[1] = image_lines_to_use;
|
||||
region[2] = 1;
|
||||
for (origin[1] = 0; origin[1] < height - image_lines_to_use; origin[1] += image_lines_to_use) {
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j=0; j<width*4*image_lines_to_use; j++) {
|
||||
data[j] = (cl_uint)genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
|
||||
if (blocking_write) {
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_TRUE, origin, region, 0, 0, data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
result = clFinish(*queue);
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
print_error(error, "clFinish failed after successful enquing filling buffer with data.");
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_FALSE, origin, region, 0, 0, data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue, &event);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with any leftover bits
|
||||
if (origin[1] < height) {
|
||||
// Put values in the data, and keep a checksum as we go along.
|
||||
for (j=0; j<width*4*(height-origin[1]); j++) {
|
||||
data[j] = (cl_uint)genrand_int32(d);
|
||||
checksum_delta += data[j];
|
||||
}
|
||||
|
||||
region[1] = height-origin[1];
|
||||
if(blocking_write) {
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_TRUE, origin, region, 0, 0, data, 0, NULL, NULL);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
error = clEnqueueWriteImage(*queue, mem, CL_FALSE, origin, region, 0, 0, data, 0, NULL, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clEnqueueWriteImage failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseMemObject(mem);
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
error = clWaitForEvents(1, &event);
|
||||
result = check_allocation_error(context, device_id, error, queue, &event);
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
print_error(error, "clWaitForEvents failed.");
|
||||
}
|
||||
|
||||
if (result != SUCCEEDED) {
|
||||
clFinish(*queue);
|
||||
clReleaseEvent(event);
|
||||
free(data);
|
||||
clReleaseMemObject(mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
clReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
// Only update the checksum if this succeeded.
|
||||
checksum += checksum_delta;
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int fill_mem_with_data(cl_context context, cl_device_id device_id, cl_command_queue *queue, cl_mem mem, MTdata d, cl_bool blocking_write) {
|
||||
int error;
|
||||
cl_mem_object_type type;
|
||||
size_t size, width, height;
|
||||
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_TYPE, sizeof(type), &type, NULL);
|
||||
test_error_abort(error, "clGetMemObjectInfo failed for CL_MEM_TYPE.");
|
||||
|
||||
if (type == CL_MEM_OBJECT_BUFFER) {
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(size), &size, NULL);
|
||||
test_error_abort(error, "clGetMemObjectInfo failed for CL_MEM_SIZE.");
|
||||
return fill_buffer_with_data(context, device_id, queue, mem, size, d, blocking_write);
|
||||
} else if (type == CL_MEM_OBJECT_IMAGE2D) {
|
||||
error = clGetImageInfo(mem, CL_IMAGE_WIDTH, sizeof(width), &width, NULL);
|
||||
test_error_abort(error, "clGetImageInfo failed for CL_IMAGE_WIDTH.");
|
||||
error = clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL);
|
||||
test_error_abort(error, "clGetImageInfo failed for CL_IMAGE_HEIGHT.");
|
||||
return fill_image_with_data(context, device_id, queue, mem, width, height, d, blocking_write);
|
||||
}
|
||||
|
||||
log_error("Invalid CL_MEM_TYPE: %d\n", type);
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -16,4 +16,6 @@
|
|||
#include "testBase.h"
|
||||
#include "allocation_utils.h"
|
||||
|
||||
int fill_mem_with_data(cl_context context, cl_device_id device_id, cl_command_queue *queue, cl_mem mem, MTdata d, cl_bool blocking_write);
|
||||
int fill_mem_with_data(cl_context context, cl_device_id device_id,
|
||||
cl_command_queue *queue, cl_mem mem, MTdata d,
|
||||
cl_bool blocking_write);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -17,273 +17,367 @@
|
|||
#include "allocation_fill.h"
|
||||
|
||||
|
||||
static cl_image_format image_format = { CL_RGBA, CL_UNSIGNED_INT32 };
|
||||
static cl_image_format image_format = { CL_RGBA, CL_UNSIGNED_INT32 };
|
||||
|
||||
int allocate_buffer(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate, cl_bool blocking_write) {
|
||||
int error;
|
||||
// log_info("\t\tAttempting to allocate a %gMB array and fill with %s writes.\n", (size_to_allocate/(1024.0*1024.0)), (blocking_write ? "blocking" : "non-blocking"));
|
||||
*mem = clCreateBuffer(context, CL_MEM_READ_WRITE, size_to_allocate, NULL, &error);
|
||||
return check_allocation_error(context, device_id, error, queue);
|
||||
int allocate_buffer(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, cl_mem *mem,
|
||||
size_t size_to_allocate, cl_bool blocking_write)
|
||||
{
|
||||
int error;
|
||||
// log_info("\t\tAttempting to allocate a %gMB array and fill with %s
|
||||
// writes.\n", (size_to_allocate/(1024.0*1024.0)), (blocking_write ?
|
||||
// "blocking" : "non-blocking"));
|
||||
*mem = clCreateBuffer(context, CL_MEM_READ_WRITE, size_to_allocate, NULL,
|
||||
&error);
|
||||
return check_allocation_error(context, device_id, error, queue);
|
||||
}
|
||||
|
||||
|
||||
int find_good_image_size(cl_device_id device_id, size_t size_to_allocate, size_t *width, size_t *height, size_t* max_size) {
|
||||
size_t max_width, max_height, num_pixels, found_width, found_height;
|
||||
int error;
|
||||
int find_good_image_size(cl_device_id device_id, size_t size_to_allocate,
|
||||
size_t *width, size_t *height, size_t *max_size)
|
||||
{
|
||||
size_t max_width, max_height, num_pixels, found_width, found_height;
|
||||
int error;
|
||||
|
||||
if (checkForImageSupport(device_id)) {
|
||||
log_info("Can not allocate an image on this device because it does not support images.");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
if (size_to_allocate == 0) {
|
||||
log_error("Trying to allcoate a zero sized image.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
error = clGetDeviceInfo( device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( max_width ), &max_width, NULL );
|
||||
test_error_abort(error, "clGetDeviceInfo failed.");
|
||||
error = clGetDeviceInfo( device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( max_height ), &max_height, NULL );
|
||||
test_error_abort(error, "clGetDeviceInfo failed.");
|
||||
|
||||
num_pixels = size_to_allocate / (sizeof(cl_uint)*4);
|
||||
|
||||
// Use a 64-bit variable to avoid overflow in 32-bit architectures
|
||||
long long unsigned max_pixels = (long long unsigned)max_width * max_height;
|
||||
|
||||
if (num_pixels > max_pixels) {
|
||||
if(NULL != max_size) {
|
||||
*max_size = max_width * max_height * sizeof(cl_uint) * 4;
|
||||
if (checkForImageSupport(device_id))
|
||||
{
|
||||
log_info("Can not allocate an image on this device because it does not "
|
||||
"support images.");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
return FAILED_TOO_BIG;
|
||||
}
|
||||
|
||||
// We want a close-to-square aspect ratio.
|
||||
// Note that this implicitly assumes that max width >= max height
|
||||
found_width = (int)sqrt( (double) num_pixels );
|
||||
if( found_width > max_width ) {
|
||||
found_width = max_width;
|
||||
}
|
||||
if (found_width == 0)
|
||||
found_width = 1;
|
||||
if (size_to_allocate == 0)
|
||||
{
|
||||
log_error("Trying to allocate a zero sized image.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
found_height = (size_t)num_pixels/found_width;
|
||||
if (found_height > max_height) {
|
||||
found_height = max_height;
|
||||
}
|
||||
if (found_height == 0)
|
||||
found_height = 1;
|
||||
error = clGetDeviceInfo(device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH,
|
||||
sizeof(max_width), &max_width, NULL);
|
||||
test_error_abort(error, "clGetDeviceInfo failed.");
|
||||
error = clGetDeviceInfo(device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
|
||||
sizeof(max_height), &max_height, NULL);
|
||||
test_error_abort(error, "clGetDeviceInfo failed.");
|
||||
|
||||
*width = found_width;
|
||||
*height = found_height;
|
||||
num_pixels = size_to_allocate / (sizeof(cl_uint) * 4);
|
||||
|
||||
if(NULL != max_size) {
|
||||
*max_size = found_width * found_height * sizeof(cl_uint) * 4;
|
||||
}
|
||||
// Use a 64-bit variable to avoid overflow in 32-bit architectures
|
||||
long long unsigned max_pixels = (long long unsigned)max_width * max_height;
|
||||
|
||||
return SUCCEEDED;
|
||||
if (num_pixels > max_pixels)
|
||||
{
|
||||
if (NULL != max_size)
|
||||
{
|
||||
*max_size = max_width * max_height * sizeof(cl_uint) * 4;
|
||||
}
|
||||
return FAILED_TOO_BIG;
|
||||
}
|
||||
|
||||
// We want a close-to-square aspect ratio.
|
||||
// Note that this implicitly assumes that max width >= max height
|
||||
found_width = (int)sqrt((double)num_pixels);
|
||||
if (found_width > max_width)
|
||||
{
|
||||
found_width = max_width;
|
||||
}
|
||||
if (found_width == 0) found_width = 1;
|
||||
|
||||
found_height = (size_t)num_pixels / found_width;
|
||||
if (found_height > max_height)
|
||||
{
|
||||
found_height = max_height;
|
||||
}
|
||||
if (found_height == 0) found_height = 1;
|
||||
|
||||
*width = found_width;
|
||||
*height = found_height;
|
||||
|
||||
if (NULL != max_size)
|
||||
{
|
||||
*max_size = found_width * found_height * sizeof(cl_uint) * 4;
|
||||
}
|
||||
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
int allocate_image2d_read(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate, cl_bool blocking_write) {
|
||||
size_t width, height;
|
||||
int error;
|
||||
int allocate_image2d_read(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, cl_mem *mem,
|
||||
size_t size_to_allocate, cl_bool blocking_write)
|
||||
{
|
||||
size_t width, height;
|
||||
int error;
|
||||
|
||||
error = find_good_image_size(device_id, size_to_allocate, &width, &height, NULL);
|
||||
if (error != SUCCEEDED)
|
||||
return error;
|
||||
error = find_good_image_size(device_id, size_to_allocate, &width, &height,
|
||||
NULL);
|
||||
if (error != SUCCEEDED) return error;
|
||||
|
||||
log_info("\t\tAttempting to allocate a %gMB read-only image (%d x %d) and fill with %s writes.\n",
|
||||
(size_to_allocate/(1024.0*1024.0)), (int)width, (int)height, (blocking_write ? "blocking" : "non-blocking"));
|
||||
*mem = create_image_2d(context, CL_MEM_READ_ONLY, &image_format, width, height, 0, NULL, &error);
|
||||
log_info("\t\tAttempting to allocate a %gMB read-only image (%d x %d) and "
|
||||
"fill with %s writes.\n",
|
||||
(size_to_allocate / (1024.0 * 1024.0)), (int)width, (int)height,
|
||||
(blocking_write ? "blocking" : "non-blocking"));
|
||||
*mem = create_image_2d(context, CL_MEM_READ_ONLY, &image_format, width,
|
||||
height, 0, NULL, &error);
|
||||
|
||||
return check_allocation_error(context, device_id, error, queue);
|
||||
return check_allocation_error(context, device_id, error, queue);
|
||||
}
|
||||
|
||||
|
||||
int allocate_image2d_write(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate, cl_bool blocking_write) {
|
||||
size_t width, height;
|
||||
int error;
|
||||
int allocate_image2d_write(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, cl_mem *mem,
|
||||
size_t size_to_allocate, cl_bool blocking_write)
|
||||
{
|
||||
size_t width, height;
|
||||
int error;
|
||||
|
||||
error = find_good_image_size(device_id, size_to_allocate, &width, &height, NULL);
|
||||
if (error != SUCCEEDED)
|
||||
return error;
|
||||
error = find_good_image_size(device_id, size_to_allocate, &width, &height,
|
||||
NULL);
|
||||
if (error != SUCCEEDED) return error;
|
||||
|
||||
//log_info("\t\tAttempting to allocate a %gMB write-only image (%d x %d) and fill with %s writes.\n",
|
||||
//(size_to_allocate/(1024.0*1024.0)), (int)width, (int)height, (blocking_write ? "blocking" : "non-blocking"));
|
||||
*mem = create_image_2d(context, CL_MEM_WRITE_ONLY, &image_format, width, height, 0, NULL, &error);
|
||||
// log_info("\t\tAttempting to allocate a %gMB write-only image (%d x %d)
|
||||
// and fill with %s writes.\n", (size_to_allocate/(1024.0*1024.0)),
|
||||
//(int)width, (int)height, (blocking_write ? "blocking" : "non-blocking"));
|
||||
*mem = create_image_2d(context, CL_MEM_WRITE_ONLY, &image_format, width,
|
||||
height, 0, NULL, &error);
|
||||
|
||||
return check_allocation_error(context, device_id, error, queue);
|
||||
return check_allocation_error(context, device_id, error, queue);
|
||||
}
|
||||
|
||||
int do_allocation(cl_context context, cl_command_queue *queue, cl_device_id device_id, size_t size_to_allocate, int type, cl_mem *mem) {
|
||||
if (type == BUFFER) return allocate_buffer(context, queue, device_id, mem, size_to_allocate, true);
|
||||
if (type == IMAGE_READ) return allocate_image2d_read(context, queue, device_id, mem, size_to_allocate, true);
|
||||
if (type == IMAGE_WRITE) return allocate_image2d_write(context, queue, device_id, mem, size_to_allocate, true);
|
||||
if (type == BUFFER_NON_BLOCKING) return allocate_buffer(context, queue, device_id, mem, size_to_allocate, false);
|
||||
if (type == IMAGE_READ_NON_BLOCKING) return allocate_image2d_read(context, queue, device_id, mem, size_to_allocate, false);
|
||||
if (type == IMAGE_WRITE_NON_BLOCKING) return allocate_image2d_write(context, queue, device_id, mem, size_to_allocate, false);
|
||||
int do_allocation(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, size_t size_to_allocate, int type,
|
||||
cl_mem *mem)
|
||||
{
|
||||
if (type == BUFFER)
|
||||
return allocate_buffer(context, queue, device_id, mem, size_to_allocate,
|
||||
true);
|
||||
if (type == IMAGE_READ)
|
||||
return allocate_image2d_read(context, queue, device_id, mem,
|
||||
size_to_allocate, true);
|
||||
if (type == IMAGE_WRITE)
|
||||
return allocate_image2d_write(context, queue, device_id, mem,
|
||||
size_to_allocate, true);
|
||||
if (type == BUFFER_NON_BLOCKING)
|
||||
return allocate_buffer(context, queue, device_id, mem, size_to_allocate,
|
||||
false);
|
||||
if (type == IMAGE_READ_NON_BLOCKING)
|
||||
return allocate_image2d_read(context, queue, device_id, mem,
|
||||
size_to_allocate, false);
|
||||
if (type == IMAGE_WRITE_NON_BLOCKING)
|
||||
return allocate_image2d_write(context, queue, device_id, mem,
|
||||
size_to_allocate, false);
|
||||
log_error("Invalid allocation type: %d\n", type);
|
||||
return FAILED_ABORT;
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
|
||||
int allocate_size(cl_context context, cl_command_queue *queue, cl_device_id device_id, int multiple_allocations, size_t size_to_allocate,
|
||||
int type, cl_mem mems[], int *number_of_mems, size_t *final_size, int force_fill, MTdata d) {
|
||||
int allocate_size(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, int multiple_allocations,
|
||||
size_t size_to_allocate, int type, cl_mem mems[],
|
||||
int *number_of_mems, size_t *final_size, int force_fill,
|
||||
MTdata d)
|
||||
{
|
||||
|
||||
cl_ulong max_individual_allocation_size, global_mem_size;
|
||||
int error, result;
|
||||
size_t amount_allocated;
|
||||
size_t reduction_amount;
|
||||
int current_allocation;
|
||||
size_t allocation_this_time, actual_allocation;
|
||||
int error, result;
|
||||
size_t amount_allocated;
|
||||
size_t reduction_amount;
|
||||
int current_allocation;
|
||||
size_t allocation_this_time, actual_allocation;
|
||||
|
||||
// Set the number of mems used to 0 so if we fail to create even a single one we don't end up returning a garbage value
|
||||
*number_of_mems = 0;
|
||||
// Set the number of mems used to 0 so if we fail to create even a single
|
||||
// one we don't end up returning a garbage value
|
||||
*number_of_mems = 0;
|
||||
|
||||
error = clGetDeviceInfo(device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(max_individual_allocation_size), &max_individual_allocation_size, NULL);
|
||||
test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_MEM_ALLOC_SIZE");
|
||||
error = clGetDeviceInfo(device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(global_mem_size), &global_mem_size, NULL);
|
||||
test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_GLOBAL_MEM_SIZE");
|
||||
max_individual_allocation_size =
|
||||
get_device_info_max_mem_alloc_size(device_id);
|
||||
global_mem_size = get_device_info_global_mem_size(device_id);
|
||||
|
||||
if (global_mem_size > (cl_ulong)SIZE_MAX) {
|
||||
global_mem_size = (cl_ulong)SIZE_MAX;
|
||||
}
|
||||
|
||||
// log_info("Device reports CL_DEVICE_MAX_MEM_ALLOC_SIZE=%llu bytes (%gMB), CL_DEVICE_GLOBAL_MEM_SIZE=%llu bytes (%gMB).\n",
|
||||
// max_individual_allocation_size, toMB(max_individual_allocation_size),
|
||||
// global_mem_size, toMB(global_mem_size));
|
||||
|
||||
if (size_to_allocate > global_mem_size) {
|
||||
log_error("Can not allocate more than the global memory size.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
amount_allocated = 0;
|
||||
current_allocation = 0;
|
||||
|
||||
// If allocating for images, reduce the maximum allocation size to the maximum image size.
|
||||
// If we don't do this, then the value of CL_DEVICE_MAX_MEM_ALLOC_SIZE / 4 can be higher
|
||||
// than the maximum image size on systems with 16GB or RAM or more. In this case, we
|
||||
// succeed in allocating an image but its size is less than CL_DEVICE_MAX_MEM_ALLOC_SIZE / 4
|
||||
// (min_allocation_allowed) and thus we fail the allocation below.
|
||||
if(type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING || type == IMAGE_WRITE || type == IMAGE_WRITE_NON_BLOCKING) {
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t max_size;
|
||||
error = find_good_image_size(device_id, size_to_allocate, &width, &height, &max_size);
|
||||
if (!(error == SUCCEEDED || error == FAILED_TOO_BIG))
|
||||
return error;
|
||||
if(max_size < max_individual_allocation_size)
|
||||
max_individual_allocation_size = max_size;
|
||||
}
|
||||
|
||||
reduction_amount = (size_t)max_individual_allocation_size/16;
|
||||
|
||||
if (type == BUFFER || type == BUFFER_NON_BLOCKING) log_info("\tAttempting to allocate a buffer of size %gMB.\n", toMB(size_to_allocate));
|
||||
else if (type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING) log_info("\tAttempting to allocate a read-only image of size %gMB.\n", toMB(size_to_allocate));
|
||||
else if (type == IMAGE_WRITE || type == IMAGE_WRITE_NON_BLOCKING) log_info("\tAttempting to allocate a write-only image of size %gMB.\n", toMB(size_to_allocate));
|
||||
|
||||
// log_info("\t\t(Reduction size is %gMB per iteration, minimum allowable individual allocation size is %gMB.)\n",
|
||||
// toMB(reduction_amount), toMB(min_allocation_allowed));
|
||||
// if (force_fill && type != IMAGE_WRITE && type != IMAGE_WRITE_NON_BLOCKING) log_info("\t\t(Allocations will be filled with random data for checksum calculation.)\n");
|
||||
|
||||
// If we are only doing a single allocation, only allow 1
|
||||
int max_to_allocate = multiple_allocations ? MAX_NUMBER_TO_ALLOCATE : 1;
|
||||
|
||||
// Make sure that the maximum number of images allocated is constrained by the
|
||||
// maximum that may be passed to a kernel
|
||||
if (type != BUFFER && type != BUFFER_NON_BLOCKING) {
|
||||
cl_device_info param_name = (type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING) ?
|
||||
CL_DEVICE_MAX_READ_IMAGE_ARGS : CL_DEVICE_MAX_WRITE_IMAGE_ARGS;
|
||||
|
||||
cl_uint max_image_args;
|
||||
error = clGetDeviceInfo(device_id, param_name, sizeof(max_image_args), &max_image_args, NULL);
|
||||
test_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX IMAGE_ARGS");
|
||||
|
||||
if ((int)max_image_args < max_to_allocate) {
|
||||
log_info("\t\tMaximum number of images per kernel limited to %d\n",(int)max_image_args);
|
||||
max_to_allocate = max_image_args;
|
||||
if (global_mem_size > (cl_ulong)SIZE_MAX)
|
||||
{
|
||||
global_mem_size = (cl_ulong)SIZE_MAX;
|
||||
}
|
||||
|
||||
if (size_to_allocate > global_mem_size)
|
||||
{
|
||||
log_error("Can not allocate more than the global memory size.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
amount_allocated = 0;
|
||||
current_allocation = 0;
|
||||
|
||||
// If allocating for images, reduce the maximum allocation size to the
|
||||
// maximum image size. If we don't do this, then the value of
|
||||
// CL_DEVICE_MAX_MEM_ALLOC_SIZE / 4 can be higher than the maximum image
|
||||
// size on systems with 16GB or RAM or more. In this case, we succeed in
|
||||
// allocating an image but its size is less than
|
||||
// CL_DEVICE_MAX_MEM_ALLOC_SIZE / 4 (min_allocation_allowed) and thus we
|
||||
// fail the allocation below.
|
||||
if (type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING
|
||||
|| type == IMAGE_WRITE || type == IMAGE_WRITE_NON_BLOCKING)
|
||||
{
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t max_size;
|
||||
error = find_good_image_size(device_id, size_to_allocate, &width,
|
||||
&height, &max_size);
|
||||
if (!(error == SUCCEEDED || error == FAILED_TOO_BIG)) return error;
|
||||
if (max_size < max_individual_allocation_size)
|
||||
max_individual_allocation_size = max_size;
|
||||
}
|
||||
|
||||
reduction_amount = (size_t)max_individual_allocation_size / 16;
|
||||
|
||||
if (type == BUFFER || type == BUFFER_NON_BLOCKING)
|
||||
log_info("\tAttempting to allocate a buffer of size %gMB.\n",
|
||||
toMB(size_to_allocate));
|
||||
else if (type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING)
|
||||
log_info("\tAttempting to allocate a read-only image of size %gMB.\n",
|
||||
toMB(size_to_allocate));
|
||||
else if (type == IMAGE_WRITE || type == IMAGE_WRITE_NON_BLOCKING)
|
||||
log_info("\tAttempting to allocate a write-only image of size %gMB.\n",
|
||||
toMB(size_to_allocate));
|
||||
|
||||
// log_info("\t\t(Reduction size is %gMB per iteration, minimum allowable
|
||||
// individual allocation size is %gMB.)\n",
|
||||
// toMB(reduction_amount), toMB(min_allocation_allowed));
|
||||
// if (force_fill && type != IMAGE_WRITE && type !=
|
||||
// IMAGE_WRITE_NON_BLOCKING) log_info("\t\t(Allocations will be filled with
|
||||
// random data for checksum calculation.)\n");
|
||||
|
||||
// If we are only doing a single allocation, only allow 1
|
||||
int max_to_allocate = multiple_allocations ? MAX_NUMBER_TO_ALLOCATE : 1;
|
||||
|
||||
// Make sure that the maximum number of images allocated is constrained by
|
||||
// the maximum that may be passed to a kernel
|
||||
if (type != BUFFER && type != BUFFER_NON_BLOCKING)
|
||||
{
|
||||
cl_device_info param_name =
|
||||
(type == IMAGE_READ || type == IMAGE_READ_NON_BLOCKING)
|
||||
? CL_DEVICE_MAX_READ_IMAGE_ARGS
|
||||
: CL_DEVICE_MAX_WRITE_IMAGE_ARGS;
|
||||
|
||||
cl_uint max_image_args;
|
||||
error = clGetDeviceInfo(device_id, param_name, sizeof(max_image_args),
|
||||
&max_image_args, NULL);
|
||||
test_error(error,
|
||||
"clGetDeviceInfo failed for CL_DEVICE_MAX IMAGE_ARGS");
|
||||
|
||||
if ((int)max_image_args < max_to_allocate)
|
||||
{
|
||||
log_info("\t\tMaximum number of images per kernel limited to %d\n",
|
||||
(int)max_image_args);
|
||||
max_to_allocate = max_image_args;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try to allocate the requested amount.
|
||||
while (amount_allocated != size_to_allocate && current_allocation < max_to_allocate) {
|
||||
// Try to allocate the requested amount.
|
||||
while (amount_allocated != size_to_allocate
|
||||
&& current_allocation < max_to_allocate)
|
||||
{
|
||||
|
||||
// Determine how much more is needed
|
||||
allocation_this_time = size_to_allocate - amount_allocated;
|
||||
// Determine how much more is needed
|
||||
allocation_this_time = size_to_allocate - amount_allocated;
|
||||
|
||||
// Bound by the individual allocation size
|
||||
if (allocation_this_time > max_individual_allocation_size)
|
||||
allocation_this_time = (size_t)max_individual_allocation_size;
|
||||
// Bound by the individual allocation size
|
||||
if (allocation_this_time > max_individual_allocation_size)
|
||||
allocation_this_time = (size_t)max_individual_allocation_size;
|
||||
|
||||
// Allocate the largest object possible
|
||||
result = FAILED_TOO_BIG;
|
||||
//log_info("\t\tTrying sub-allocation %d at size %gMB.\n", current_allocation, toMB(allocation_this_time));
|
||||
while (result == FAILED_TOO_BIG && allocation_this_time != 0) {
|
||||
// Allocate the largest object possible
|
||||
result = FAILED_TOO_BIG;
|
||||
// log_info("\t\tTrying sub-allocation %d at size %gMB.\n",
|
||||
// current_allocation, toMB(allocation_this_time));
|
||||
while (result == FAILED_TOO_BIG && allocation_this_time != 0)
|
||||
{
|
||||
|
||||
// Create the object
|
||||
result = do_allocation(context, queue, device_id, allocation_this_time, type, &mems[current_allocation]);
|
||||
if (result == SUCCEEDED) {
|
||||
// Allocation succeeded, another memory object was added to the array
|
||||
*number_of_mems = (current_allocation+1);
|
||||
// Create the object
|
||||
result =
|
||||
do_allocation(context, queue, device_id, allocation_this_time,
|
||||
type, &mems[current_allocation]);
|
||||
if (result == SUCCEEDED)
|
||||
{
|
||||
// Allocation succeeded, another memory object was added to the
|
||||
// array
|
||||
*number_of_mems = (current_allocation + 1);
|
||||
|
||||
// Verify the size is correct to within 1MB.
|
||||
actual_allocation = get_actual_allocation_size(mems[current_allocation]);
|
||||
if (fabs((double)allocation_this_time - (double)actual_allocation) > 1024.0*1024.0) {
|
||||
log_error("Allocation not of expected size. Expected %gMB, got %gMB.\n", toMB(allocation_this_time), toMB( actual_allocation));
|
||||
return FAILED_ABORT;
|
||||
// Verify the size is correct to within 1MB.
|
||||
actual_allocation =
|
||||
get_actual_allocation_size(mems[current_allocation]);
|
||||
if (fabs((double)allocation_this_time
|
||||
- (double)actual_allocation)
|
||||
> 1024.0 * 1024.0)
|
||||
{
|
||||
log_error("Allocation not of expected size. Expected %gMB, "
|
||||
"got %gMB.\n",
|
||||
toMB(allocation_this_time),
|
||||
toMB(actual_allocation));
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
// If we are filling the allocation for verification do so
|
||||
if (force_fill)
|
||||
{
|
||||
// log_info("\t\t\tWriting random values to object and
|
||||
// calculating checksum.\n");
|
||||
cl_bool blocking_write = true;
|
||||
if (type == BUFFER_NON_BLOCKING
|
||||
|| type == IMAGE_READ_NON_BLOCKING
|
||||
|| type == IMAGE_WRITE_NON_BLOCKING)
|
||||
{
|
||||
blocking_write = false;
|
||||
}
|
||||
result = fill_mem_with_data(context, device_id, queue,
|
||||
mems[current_allocation], d,
|
||||
blocking_write);
|
||||
}
|
||||
}
|
||||
|
||||
// If creation failed, try to create a smaller object
|
||||
if (result == FAILED_TOO_BIG)
|
||||
{
|
||||
// log_info("\t\t\tAllocation %d failed at size %gMB. Trying
|
||||
// smaller.\n", current_allocation, toMB(allocation_this_time));
|
||||
if (allocation_this_time > reduction_amount)
|
||||
allocation_this_time -= reduction_amount;
|
||||
else if (reduction_amount > 1)
|
||||
{
|
||||
reduction_amount /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
allocation_this_time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we are filling the allocation for verification do so
|
||||
if (force_fill) {
|
||||
//log_info("\t\t\tWriting random values to object and calculating checksum.\n");
|
||||
cl_bool blocking_write = true;
|
||||
if (type == BUFFER_NON_BLOCKING || type == IMAGE_READ_NON_BLOCKING || type == IMAGE_WRITE_NON_BLOCKING) {
|
||||
blocking_write = false;
|
||||
}
|
||||
result = fill_mem_with_data(context, device_id, queue, mems[current_allocation], d, blocking_write);
|
||||
}
|
||||
}
|
||||
|
||||
// If creation failed, try to create a smaller object
|
||||
if (result == FAILED_TOO_BIG) {
|
||||
//log_info("\t\t\tAllocation %d failed at size %gMB. Trying smaller.\n", current_allocation, toMB(allocation_this_time));
|
||||
if (allocation_this_time > reduction_amount)
|
||||
allocation_this_time -= reduction_amount;
|
||||
else if (reduction_amount > 1) {
|
||||
reduction_amount /= 2;
|
||||
}
|
||||
else {
|
||||
allocation_this_time = 0;
|
||||
if (result == FAILED_ABORT)
|
||||
{
|
||||
log_error("\t\tAllocation failed.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
}
|
||||
if (!allocation_this_time)
|
||||
{
|
||||
log_info("\t\tFailed to allocate %gMB across several objects.\n",
|
||||
toMB(size_to_allocate));
|
||||
return FAILED_TOO_BIG;
|
||||
}
|
||||
|
||||
// Otherwise we succeeded
|
||||
if (result != SUCCEEDED)
|
||||
{
|
||||
log_error("Test logic error.");
|
||||
exit(-1);
|
||||
}
|
||||
amount_allocated += allocation_this_time;
|
||||
|
||||
*final_size = amount_allocated;
|
||||
|
||||
current_allocation++;
|
||||
}
|
||||
|
||||
if (result == FAILED_ABORT) {
|
||||
log_error("\t\tAllocation failed.\n");
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
|
||||
if (!allocation_this_time) {
|
||||
log_info("\t\tFailed to allocate %gMB across several objects.\n", toMB(size_to_allocate));
|
||||
return FAILED_TOO_BIG;
|
||||
}
|
||||
|
||||
// Otherwise we succeeded
|
||||
if (result != SUCCEEDED) {
|
||||
log_error("Test logic error.");
|
||||
exit(-1);
|
||||
}
|
||||
amount_allocated += allocation_this_time;
|
||||
|
||||
*final_size = amount_allocated;
|
||||
|
||||
current_allocation++;
|
||||
}
|
||||
|
||||
log_info("\t\tSucceeded in allocating %gMB using %d memory objects.\n", toMB(amount_allocated), current_allocation);
|
||||
return SUCCEEDED;
|
||||
log_info("\t\tSucceeded in allocating %gMB using %d memory objects.\n",
|
||||
toMB(amount_allocated), current_allocation);
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
|
@ -16,9 +16,20 @@
|
|||
#include "testBase.h"
|
||||
#include "allocation_utils.h"
|
||||
|
||||
int do_allocation(cl_context context, cl_command_queue *queue, cl_device_id device_id, size_t size_to_allocate, int type, cl_mem *mem);
|
||||
int allocate_buffer(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate);
|
||||
int allocate_image2d_read(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate);
|
||||
int allocate_image2d_write(cl_context context, cl_command_queue *queue, cl_device_id device_id, cl_mem *mem, size_t size_to_allocate);
|
||||
int allocate_size(cl_context context, cl_command_queue *queue, cl_device_id device_id, int multiple_allocations, size_t size_to_allocate,
|
||||
int type, cl_mem mems[], int *number_of_mems, size_t *final_size, int force_fill, MTdata d);
|
||||
int do_allocation(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, size_t size_to_allocate, int type,
|
||||
cl_mem *mem);
|
||||
int allocate_buffer(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, cl_mem *mem,
|
||||
size_t size_to_allocate);
|
||||
int allocate_image2d_read(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, cl_mem *mem,
|
||||
size_t size_to_allocate);
|
||||
int allocate_image2d_write(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, cl_mem *mem,
|
||||
size_t size_to_allocate);
|
||||
int allocate_size(cl_context context, cl_command_queue *queue,
|
||||
cl_device_id device_id, int multiple_allocations,
|
||||
size_t size_to_allocate, int type, cl_mem mems[],
|
||||
int *number_of_mems, size_t *final_size, int force_fill,
|
||||
MTdata d);
|
||||
|
|
|
|||
|
|
@ -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,90 +15,116 @@
|
|||
//
|
||||
#include "allocation_utils.h"
|
||||
|
||||
cl_command_queue reset_queue(cl_context context, cl_device_id device_id, cl_command_queue *queue, int *error)
|
||||
cl_command_queue reset_queue(cl_context context, cl_device_id device_id,
|
||||
cl_command_queue *queue, int *error)
|
||||
{
|
||||
log_info("Invalid command queue. Releasing and recreating the command queue.\n");
|
||||
clReleaseCommandQueue(*queue);
|
||||
log_info(
|
||||
"Invalid command queue. Releasing and recreating the command queue.\n");
|
||||
clReleaseCommandQueue(*queue);
|
||||
*queue = clCreateCommandQueue(context, device_id, 0, error);
|
||||
return *queue;
|
||||
return *queue;
|
||||
}
|
||||
|
||||
int check_allocation_error(cl_context context, cl_device_id device_id, int error, cl_command_queue *queue, cl_event *event) {
|
||||
//log_info("check_allocation_error context=%p device_id=%p error=%d *queue=%p\n", context, device_id, error, *queue);
|
||||
if (error == CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST && event != 0)
|
||||
{
|
||||
// check for errors from clWaitForEvents (e.g after clEnqueueWriteBuffer)
|
||||
cl_int eventError;
|
||||
error = clGetEventInfo(*event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(error), &eventError, 0);
|
||||
if (CL_SUCCESS != error)
|
||||
int check_allocation_error(cl_context context, cl_device_id device_id,
|
||||
int error, cl_command_queue *queue, cl_event *event)
|
||||
{
|
||||
// log_info("check_allocation_error context=%p device_id=%p error=%d
|
||||
// *queue=%p\n", context, device_id, error, *queue);
|
||||
if (error == CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST && event != 0)
|
||||
{
|
||||
log_error("Failed to get event execution status: %s\n", IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
// check for errors from clWaitForEvents (e.g after
|
||||
// clEnqueueWriteBuffer)
|
||||
cl_int eventError;
|
||||
error = clGetEventInfo(*event, CL_EVENT_COMMAND_EXECUTION_STATUS,
|
||||
sizeof(error), &eventError, 0);
|
||||
if (CL_SUCCESS != error)
|
||||
{
|
||||
log_error("Failed to get event execution status: %s\n",
|
||||
IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
if (eventError >= 0)
|
||||
{
|
||||
log_error("Non-negative event execution status after "
|
||||
"CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: %s\n",
|
||||
IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
error = eventError;
|
||||
}
|
||||
if (eventError >= 0)
|
||||
if ((error == CL_MEM_OBJECT_ALLOCATION_FAILURE)
|
||||
|| (error == CL_OUT_OF_RESOURCES) || (error == CL_OUT_OF_HOST_MEMORY)
|
||||
|| (error == CL_INVALID_IMAGE_SIZE))
|
||||
{
|
||||
log_error("Non-negative event execution status after CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: %s\n", IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
return FAILED_TOO_BIG;
|
||||
}
|
||||
error = eventError;
|
||||
}
|
||||
if ((error == CL_MEM_OBJECT_ALLOCATION_FAILURE ) || (error == CL_OUT_OF_RESOURCES ) || (error == CL_OUT_OF_HOST_MEMORY) || (error == CL_INVALID_IMAGE_SIZE)) {
|
||||
return FAILED_TOO_BIG;
|
||||
} else if (error == CL_INVALID_COMMAND_QUEUE) {
|
||||
*queue = reset_queue(context, device_id, queue, &error);
|
||||
if (CL_SUCCESS != error)
|
||||
else if (error == CL_INVALID_COMMAND_QUEUE)
|
||||
{
|
||||
log_error("Failed to reset command queue after corrupted queue: %s\n", IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
*queue = reset_queue(context, device_id, queue, &error);
|
||||
if (CL_SUCCESS != error)
|
||||
{
|
||||
log_error(
|
||||
"Failed to reset command queue after corrupted queue: %s\n",
|
||||
IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
// Try again with smaller resources.
|
||||
return FAILED_TOO_BIG;
|
||||
}
|
||||
// Try again with smaller resources.
|
||||
return FAILED_TOO_BIG;
|
||||
} else if (error != CL_SUCCESS) {
|
||||
log_error("Allocation failed with %s.\n", IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
return SUCCEEDED;
|
||||
else if (error != CL_SUCCESS)
|
||||
{
|
||||
log_error("Allocation failed with %s.\n", IGetErrorString(error));
|
||||
return FAILED_ABORT;
|
||||
}
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
||||
double toMB(cl_ulong size_in) {
|
||||
return (double)size_in/(1024.0*1024.0);
|
||||
}
|
||||
double toMB(cl_ulong size_in) { return (double)size_in / (1024.0 * 1024.0); }
|
||||
|
||||
size_t get_actual_allocation_size(cl_mem mem) {
|
||||
int error;
|
||||
cl_mem_object_type type;
|
||||
size_t size, width, height;
|
||||
size_t get_actual_allocation_size(cl_mem mem)
|
||||
{
|
||||
int error;
|
||||
cl_mem_object_type type;
|
||||
size_t size, width, height;
|
||||
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_TYPE, sizeof(type), &type, NULL);
|
||||
if (error) {
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_MEM_TYPE.");
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_TYPE, sizeof(type), &type, NULL);
|
||||
if (error)
|
||||
{
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_MEM_TYPE.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type == CL_MEM_OBJECT_BUFFER)
|
||||
{
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(size), &size, NULL);
|
||||
if (error)
|
||||
{
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_MEM_SIZE.");
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
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.");
|
||||
return 0;
|
||||
}
|
||||
error =
|
||||
clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL);
|
||||
if (error)
|
||||
{
|
||||
print_error(error,
|
||||
"clGetMemObjectInfo failed for CL_IMAGE_HEIGHT.");
|
||||
return 0;
|
||||
}
|
||||
return width * height * 4 * sizeof(cl_uint);
|
||||
}
|
||||
|
||||
log_error("Invalid CL_MEM_TYPE: %d\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type == CL_MEM_OBJECT_BUFFER) {
|
||||
error = clGetMemObjectInfo(mem, CL_MEM_SIZE, sizeof(size), &size, NULL);
|
||||
if (error) {
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_MEM_SIZE.");
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
} 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.");
|
||||
return 0;
|
||||
}
|
||||
error = clGetImageInfo(mem, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL);
|
||||
if (error) {
|
||||
print_error(error, "clGetMemObjectInfo failed for CL_IMAGE_HEIGHT.");
|
||||
return 0;
|
||||
}
|
||||
return width*height*4*sizeof(cl_uint);
|
||||
}
|
||||
|
||||
log_error("Invalid CL_MEM_TYPE: %d\n", type);
|
||||
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
|
||||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
extern cl_uint checksum;
|
||||
|
||||
int check_allocation_error(cl_context context, cl_device_id device_id, int error, cl_command_queue *queue, cl_event *event = 0);
|
||||
int check_allocation_error(cl_context context, cl_device_id device_id,
|
||||
int error, cl_command_queue *queue,
|
||||
cl_event *event = 0);
|
||||
double toMB(cl_ulong size_in);
|
||||
size_t get_actual_allocation_size(cl_mem mem);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,85 +24,100 @@
|
|||
|
||||
typedef long long unsigned llu;
|
||||
|
||||
#define REDUCTION_PERCENTAGE_DEFAULT 50
|
||||
|
||||
#define BYTES_PER_WORK_ITEM 2048ULL
|
||||
|
||||
int g_repetition_count = 1;
|
||||
int g_reduction_percentage = 100;
|
||||
int g_reduction_percentage = REDUCTION_PERCENTAGE_DEFAULT;
|
||||
int g_write_allocations = 1;
|
||||
int g_multiple_allocations = 0;
|
||||
int g_execute_kernel = 1;
|
||||
|
||||
static size_t g_max_size;
|
||||
static RandomSeed g_seed( gRandomSeed );
|
||||
static RandomSeed g_seed(gRandomSeed);
|
||||
|
||||
cl_long g_max_individual_allocation_size;
|
||||
cl_long g_global_mem_size;
|
||||
|
||||
cl_uint checksum;
|
||||
|
||||
static void printUsage( const char *execName );
|
||||
static void printUsage(const char *execName);
|
||||
|
||||
test_status init_cl( cl_device_id device ) {
|
||||
test_status init_cl(cl_device_id device)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(g_max_individual_allocation_size), &g_max_individual_allocation_size, NULL );
|
||||
if ( error ) {
|
||||
print_error( error, "clGetDeviceInfo failed for CL_DEVICE_MAX_MEM_ALLOC_SIZE");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(g_global_mem_size), &g_global_mem_size, NULL );
|
||||
if ( error ) {
|
||||
print_error( error, "clGetDeviceInfo failed for CL_DEVICE_GLOBAL_MEM_SIZE");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
g_max_individual_allocation_size =
|
||||
get_device_info_max_mem_alloc_size(device);
|
||||
g_global_mem_size = get_device_info_global_mem_size(device);
|
||||
|
||||
log_info("Device reports CL_DEVICE_MAX_MEM_ALLOC_SIZE=%llu bytes (%gMB), CL_DEVICE_GLOBAL_MEM_SIZE=%llu bytes (%gMB).\n",
|
||||
llu( g_max_individual_allocation_size ), toMB( g_max_individual_allocation_size ),
|
||||
llu( g_global_mem_size ), toMB( g_global_mem_size ) );
|
||||
log_info("Device reports CL_DEVICE_MAX_MEM_ALLOC_SIZE=%llu bytes (%gMB), "
|
||||
"CL_DEVICE_GLOBAL_MEM_SIZE=%llu bytes (%gMB).\n",
|
||||
llu(g_max_individual_allocation_size),
|
||||
toMB(g_max_individual_allocation_size), llu(g_global_mem_size),
|
||||
toMB(g_global_mem_size));
|
||||
|
||||
if( g_global_mem_size > (cl_ulong)SIZE_MAX )
|
||||
if (g_global_mem_size > (cl_ulong)SIZE_MAX)
|
||||
{
|
||||
g_global_mem_size = (cl_ulong)SIZE_MAX;
|
||||
}
|
||||
|
||||
if( g_max_individual_allocation_size > g_global_mem_size )
|
||||
if (g_max_individual_allocation_size > g_global_mem_size)
|
||||
{
|
||||
log_error( "FAILURE: CL_DEVICE_MAX_MEM_ALLOC_SIZE (%llu) is greater than the CL_DEVICE_GLOBAL_MEM_SIZE (%llu)\n",
|
||||
llu( g_max_individual_allocation_size ), llu( g_global_mem_size ) );
|
||||
log_error("FAILURE: CL_DEVICE_MAX_MEM_ALLOC_SIZE (%llu) is greater "
|
||||
"than the CL_DEVICE_GLOBAL_MEM_SIZE (%llu)\n",
|
||||
llu(g_max_individual_allocation_size),
|
||||
llu(g_global_mem_size));
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
// We may need to back off the global_mem_size on unified memory devices to leave room for application and operating system code
|
||||
// and associated data in the working set, so we dont start pathologically paging.
|
||||
// Check to see if we are a unified memory device
|
||||
// We may need to back off the global_mem_size on unified memory devices to
|
||||
// leave room for application and operating system code and associated data
|
||||
// in the working set, so we dont start pathologically paging. Check to see
|
||||
// if we are a unified memory device
|
||||
cl_bool hasUnifiedMemory = CL_FALSE;
|
||||
if( ( error = clGetDeviceInfo( device, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof( hasUnifiedMemory ), &hasUnifiedMemory, NULL ) ) )
|
||||
if ((error = clGetDeviceInfo(device, CL_DEVICE_HOST_UNIFIED_MEMORY,
|
||||
sizeof(hasUnifiedMemory), &hasUnifiedMemory,
|
||||
NULL)))
|
||||
{
|
||||
print_error( error, "clGetDeviceInfo failed for CL_DEVICE_HOST_UNIFIED_MEMORY");
|
||||
print_error(error,
|
||||
"clGetDeviceInfo failed for CL_DEVICE_HOST_UNIFIED_MEMORY");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
// we share unified memory so back off to 1/2 the global memory size.
|
||||
if( CL_TRUE == hasUnifiedMemory )
|
||||
if (CL_TRUE == hasUnifiedMemory)
|
||||
{
|
||||
g_global_mem_size -= g_global_mem_size /2;
|
||||
log_info( "Device shares memory with the host, so backing off the maximum combined allocation size to be %gMB to avoid rampant paging.\n",
|
||||
toMB( g_global_mem_size ) );
|
||||
g_global_mem_size -= g_global_mem_size / 2;
|
||||
log_info(
|
||||
"Device shares memory with the host, so backing off the maximum "
|
||||
"combined allocation size to be %gMB to avoid rampant paging.\n",
|
||||
toMB(g_global_mem_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lets just use 60% of total available memory as framework/driver may not allow using all of it
|
||||
// e.g. vram on GPU is used by window server and even for this test, we need some space for context,
|
||||
// queue, kernel code on GPU.
|
||||
// Lets just use 60% of total available memory as framework/driver may
|
||||
// not allow using all of it e.g. vram on GPU is used by window server
|
||||
// and even for this test, we need some space for context, queue, kernel
|
||||
// code on GPU.
|
||||
g_global_mem_size *= 0.60;
|
||||
}
|
||||
|
||||
if( gReSeed )
|
||||
/* Cap the allocation size as the global size was deduced */
|
||||
if (g_max_individual_allocation_size > g_global_mem_size)
|
||||
{
|
||||
g_seed = RandomSeed( gRandomSeed );
|
||||
g_max_individual_allocation_size = g_global_mem_size;
|
||||
}
|
||||
|
||||
if (gReSeed)
|
||||
{
|
||||
g_seed = RandomSeed(gRandomSeed);
|
||||
}
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int doTest( cl_device_id device, cl_context context, cl_command_queue queue, AllocType alloc_type )
|
||||
int doTest(cl_device_id device, cl_context context, cl_command_queue queue,
|
||||
AllocType alloc_type)
|
||||
{
|
||||
int error;
|
||||
int failure_counts = 0;
|
||||
|
|
@ -111,115 +126,145 @@ int doTest( cl_device_id device, cl_context context, cl_command_queue queue, All
|
|||
cl_mem mems[MAX_NUMBER_TO_ALLOCATE];
|
||||
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 ;
|
||||
cl_ulong global_mem_size = g_global_mem_size;
|
||||
unsigned int number_of_work_items;
|
||||
const bool allocate_image =
|
||||
(alloc_type != BUFFER) && (alloc_type != BUFFER_NON_BLOCKING);
|
||||
|
||||
static const char* alloc_description[] = {
|
||||
"buffer(s)",
|
||||
"read-only image(s)",
|
||||
"write-only image(s)",
|
||||
"buffer(s)",
|
||||
"read-only image(s)",
|
||||
"write-only image(s)",
|
||||
static const char *alloc_description[] = {
|
||||
"buffer(s)", "read-only image(s)", "write-only image(s)",
|
||||
"buffer(s)", "read-only image(s)", "write-only image(s)",
|
||||
};
|
||||
|
||||
// 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" );
|
||||
log_info("Can not test image allocation because device does not "
|
||||
"support images.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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 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 (allocate_image)
|
||||
{
|
||||
size_t max_width, max_height;
|
||||
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof( max_width ), &max_width, NULL );
|
||||
test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_IMAGE2D_MAX_WIDTH" );
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH,
|
||||
sizeof(max_width), &max_width, NULL);
|
||||
test_error_abort(
|
||||
error, "clGetDeviceInfo failed for CL_DEVICE_IMAGE2D_MAX_WIDTH");
|
||||
|
||||
error = clGetDeviceInfo( device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof( max_height ), &max_height, NULL );
|
||||
test_error_abort( error, "clGetDeviceInfo failed for CL_DEVICE_IMAGE2D_MAX_HEIGHT" );
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
|
||||
sizeof(max_height), &max_height, NULL);
|
||||
test_error_abort(
|
||||
error, "clGetDeviceInfo failed for CL_DEVICE_IMAGE2D_MAX_HEIGHT");
|
||||
|
||||
cl_ulong max_image2d_size = (cl_ulong)max_height * max_width * 4 * sizeof(cl_uint);
|
||||
cl_ulong max_image2d_size =
|
||||
(cl_ulong)max_height * max_width * 4 * sizeof(cl_uint);
|
||||
|
||||
if( max_individual_allocation_size > max_image2d_size )
|
||||
if (max_individual_allocation_size > max_image2d_size)
|
||||
{
|
||||
max_individual_allocation_size = max_image2d_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Pick the baseline size based on whether we are doing a single large or multiple allocations
|
||||
g_max_size = g_multiple_allocations ? (size_t)global_mem_size : (size_t)max_individual_allocation_size;
|
||||
// Pick the baseline size based on whether we are doing a single large or
|
||||
// multiple allocations
|
||||
g_max_size = g_multiple_allocations
|
||||
? (size_t)global_mem_size
|
||||
: (size_t)max_individual_allocation_size;
|
||||
|
||||
// Adjust based on the percentage
|
||||
if( g_reduction_percentage != 100 )
|
||||
if (g_reduction_percentage != 100)
|
||||
{
|
||||
log_info( "NOTE: reducing max allocations to %d%%.\n", g_reduction_percentage );
|
||||
g_max_size = (size_t)( (double)g_max_size * (double)g_reduction_percentage / 100.0 );
|
||||
log_info("NOTE: reducing max allocations to %d%%.\n",
|
||||
g_reduction_percentage);
|
||||
g_max_size = (size_t)((double)g_max_size
|
||||
* (double)g_reduction_percentage / 100.0);
|
||||
}
|
||||
|
||||
// Round to nearest MB.
|
||||
g_max_size &= (size_t)(0xFFFFFFFFFF00000ULL);
|
||||
|
||||
log_info( "** Target allocation size (rounded to nearest MB) is: %llu bytes (%gMB).\n", llu( g_max_size ), toMB( g_max_size ) );
|
||||
log_info( "** Allocating %s to size %gMB.\n", alloc_description[alloc_type], toMB( g_max_size ) );
|
||||
// Scales the number of work-items to keep the amount of bytes processed
|
||||
// per work-item the same.
|
||||
number_of_work_items =
|
||||
std::max(g_max_size / BYTES_PER_WORK_ITEM, 8192ULL * 2ULL);
|
||||
|
||||
for( int count = 0; count < g_repetition_count; count++ )
|
||||
log_info("** Target allocation size (rounded to nearest MB) is: %llu bytes "
|
||||
"(%gMB).\n",
|
||||
llu(g_max_size), toMB(g_max_size));
|
||||
log_info("** Allocating %s to size %gMB.\n", alloc_description[alloc_type],
|
||||
toMB(g_max_size));
|
||||
|
||||
for (int count = 0; count < g_repetition_count; count++)
|
||||
{
|
||||
current_test_size = g_max_size;
|
||||
error = FAILED_TOO_BIG;
|
||||
log_info( " => Allocation %d\n", count + 1 );
|
||||
log_info(" => Allocation %d\n", count + 1);
|
||||
|
||||
while( ( error == FAILED_TOO_BIG ) && ( current_test_size > g_max_size / 8 ) )
|
||||
while ((error == FAILED_TOO_BIG)
|
||||
&& (current_test_size > g_max_size / 8))
|
||||
{
|
||||
// Reset our checksum for each allocation
|
||||
checksum = 0;
|
||||
|
||||
// Do the allocation
|
||||
error = allocate_size( context, &queue, device, g_multiple_allocations, current_test_size, alloc_type,
|
||||
mems, &number_of_mems_used, &final_size, g_write_allocations, g_seed );
|
||||
error = allocate_size(context, &queue, device,
|
||||
g_multiple_allocations, current_test_size,
|
||||
alloc_type, mems, &number_of_mems_used,
|
||||
&final_size, g_write_allocations, g_seed);
|
||||
|
||||
// If we succeeded and we're supposed to execute a kernel, do so.
|
||||
if( error == SUCCEEDED && g_execute_kernel )
|
||||
if (error == SUCCEEDED && g_execute_kernel)
|
||||
{
|
||||
log_info( "\tExecuting kernel with memory objects.\n" );
|
||||
error = execute_kernel( context, &queue, device, alloc_type, mems, number_of_mems_used,
|
||||
g_write_allocations );
|
||||
log_info("\tExecuting kernel with memory objects.\n");
|
||||
error =
|
||||
execute_kernel(context, &queue, device, alloc_type, mems,
|
||||
number_of_mems_used, g_write_allocations,
|
||||
number_of_work_items);
|
||||
}
|
||||
|
||||
// If we failed to allocate more than 1/8th of the requested amount return a failure.
|
||||
if( final_size < (size_t)g_max_size / 8 )
|
||||
// If we failed to allocate more than 1/8th of the requested amount
|
||||
// return a failure.
|
||||
if (final_size < (size_t)g_max_size / 8)
|
||||
{
|
||||
log_error( "===> Allocation %d failed to allocate more than 1/8th of the requested size.\n", count + 1 );
|
||||
log_error("===> Allocation %d failed to allocate more than "
|
||||
"1/8th of the requested size.\n",
|
||||
count + 1);
|
||||
failure_counts++;
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
for( int i = 0; i < number_of_mems_used; i++ )
|
||||
for (int i = 0; i < number_of_mems_used; i++)
|
||||
{
|
||||
clReleaseMemObject( mems[i] );
|
||||
clReleaseMemObject(mems[i]);
|
||||
}
|
||||
|
||||
if( error == FAILED_ABORT )
|
||||
if (error == FAILED_ABORT)
|
||||
{
|
||||
log_error( " => Allocation %d failed.\n", count + 1 );
|
||||
log_error(" => Allocation %d failed.\n", count + 1);
|
||||
failure_counts++;
|
||||
}
|
||||
|
||||
if( error == FAILED_TOO_BIG )
|
||||
if (error == FAILED_TOO_BIG)
|
||||
{
|
||||
current_test_size -= g_max_size / 16;
|
||||
log_info( "\tFailed at this size; trying a smaller size of %gMB.\n", toMB( current_test_size ) );
|
||||
log_info(
|
||||
"\tFailed at this size; trying a smaller size of %gMB.\n",
|
||||
toMB(current_test_size));
|
||||
}
|
||||
}
|
||||
|
||||
if( error == SUCCEEDED && current_test_size == g_max_size )
|
||||
if (error == SUCCEEDED && current_test_size == g_max_size)
|
||||
{
|
||||
log_info("\tPASS: Allocation succeeded.\n");
|
||||
}
|
||||
else if( error == SUCCEEDED && current_test_size > g_max_size / 8 )
|
||||
else if (error == SUCCEEDED && current_test_size > g_max_size / 8)
|
||||
{
|
||||
log_info("\tPASS: Allocation succeeded at reduced size.\n");
|
||||
}
|
||||
|
|
@ -233,41 +278,27 @@ int doTest( cl_device_id device, cl_context context, cl_command_queue queue, All
|
|||
return failure_counts;
|
||||
}
|
||||
|
||||
int test_buffer(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(buffer) { return doTest(device, context, queue, BUFFER); }
|
||||
REGISTER_TEST(image2d_read)
|
||||
{
|
||||
return doTest( device, context, queue, BUFFER );
|
||||
return doTest(device, context, queue, IMAGE_READ);
|
||||
}
|
||||
int test_image2d_read(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(image2d_write)
|
||||
{
|
||||
return doTest( device, context, queue, IMAGE_READ );
|
||||
return doTest(device, context, queue, IMAGE_WRITE);
|
||||
}
|
||||
int test_image2d_write(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(buffer_non_blocking)
|
||||
{
|
||||
return doTest( device, context, queue, IMAGE_WRITE );
|
||||
return doTest(device, context, queue, BUFFER_NON_BLOCKING);
|
||||
}
|
||||
int test_buffer_non_blocking(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(image2d_read_non_blocking)
|
||||
{
|
||||
return doTest( device, context, queue, BUFFER_NON_BLOCKING );
|
||||
return doTest(device, context, queue, IMAGE_READ_NON_BLOCKING);
|
||||
}
|
||||
int test_image2d_read_non_blocking(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(image2d_write_non_blocking)
|
||||
{
|
||||
return doTest( device, context, queue, IMAGE_READ_NON_BLOCKING );
|
||||
return doTest(device, context, queue, IMAGE_WRITE_NON_BLOCKING);
|
||||
}
|
||||
int test_image2d_write_non_blocking(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
|
||||
{
|
||||
return doTest( device, context, queue, IMAGE_WRITE_NON_BLOCKING );
|
||||
}
|
||||
|
||||
test_definition test_list[] = {
|
||||
ADD_TEST( buffer ),
|
||||
ADD_TEST( image2d_read ),
|
||||
ADD_TEST( image2d_write ),
|
||||
ADD_TEST( buffer_non_blocking ),
|
||||
ADD_TEST( image2d_read_non_blocking ),
|
||||
ADD_TEST( image2d_write_non_blocking ),
|
||||
};
|
||||
|
||||
const int test_num = ARRAY_SIZE( test_list );
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
|
|
@ -280,11 +311,11 @@ int main(int argc, const char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
const char ** argList = (const char **)calloc( argc, sizeof( char*) );
|
||||
const char **argList = (const char **)calloc(argc, sizeof(char *));
|
||||
|
||||
if( NULL == argList )
|
||||
if (NULL == argList)
|
||||
{
|
||||
log_error( "Failed to allocate memory for argList array.\n" );
|
||||
log_error("Failed to allocate memory for argList array.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -292,38 +323,41 @@ int main(int argc, const char *argv[])
|
|||
size_t argCount = 1;
|
||||
|
||||
// Parse arguments
|
||||
for( int i = 1; i < argc; i++ )
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if( strcmp( argv[i], "multiple" ) == 0 )
|
||||
if (strcmp(argv[i], "multiple") == 0)
|
||||
g_multiple_allocations = 1;
|
||||
else if( strcmp( argv[i], "single" ) == 0 )
|
||||
else if (strcmp(argv[i], "single") == 0)
|
||||
g_multiple_allocations = 0;
|
||||
|
||||
else if( ( r = (int)strtol( argv[i], &endPtr, 10 ) ) && ( endPtr != argv[i] ) && ( *endPtr == 0 ) )
|
||||
else if ((r = (int)strtol(argv[i], &endPtr, 10)) && (endPtr != argv[i])
|
||||
&& (*endPtr == 0))
|
||||
{
|
||||
// By spec, that means the entire string was an integer, so take it as a repetition count
|
||||
// By spec, that means the entire string was an integer, so take it
|
||||
// as a repetition count
|
||||
g_repetition_count = r;
|
||||
}
|
||||
|
||||
else if( strchr( argv[i], '%' ) != NULL )
|
||||
else if (strchr(argv[i], '%') != NULL)
|
||||
{
|
||||
// Reduction percentage (let strtol ignore the percentage)
|
||||
g_reduction_percentage = (int)strtol( argv[i], NULL, 10 );
|
||||
g_reduction_percentage = (int)strtol(argv[i], NULL, 10);
|
||||
}
|
||||
|
||||
else if( strcmp( argv[i], "do_not_force_fill" ) == 0 )
|
||||
else if (strcmp(argv[i], "do_not_force_fill") == 0)
|
||||
{
|
||||
g_write_allocations = 0;
|
||||
}
|
||||
|
||||
else if( strcmp( argv[i], "do_not_execute" ) == 0 )
|
||||
else if (strcmp(argv[i], "do_not_execute") == 0)
|
||||
{
|
||||
g_execute_kernel = 0;
|
||||
}
|
||||
|
||||
else if ( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
|
||||
else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0)
|
||||
{
|
||||
printUsage( argv[0] );
|
||||
printUsage(argv[0]);
|
||||
free(argList);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -334,35 +368,43 @@ int main(int argc, const char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
int ret = runTestHarnessWithCheck( argCount, argList, test_num, test_list, false, 0, init_cl );
|
||||
int ret = runTestHarnessWithCheck(
|
||||
argCount, argList, test_registry::getInstance().num_tests(),
|
||||
test_registry::getInstance().definitions(), false, 0, init_cl);
|
||||
|
||||
free(argList);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void printUsage( const char *execName )
|
||||
void printUsage(const char *execName)
|
||||
{
|
||||
const char *p = strrchr( execName, '/' );
|
||||
if( p != NULL )
|
||||
execName = p + 1;
|
||||
const char *p = strrchr(execName, '/');
|
||||
if (p != NULL) execName = p + 1;
|
||||
|
||||
log_info( "Usage: %s [options] [test_names]\n", execName );
|
||||
log_info( "Options:\n" );
|
||||
log_info( "\trandomize - Uses random seed\n" );
|
||||
log_info( "\tsingle - Tests using a single allocation as large as possible\n" );
|
||||
log_info( "\tmultiple - Tests using as many allocations as possible\n" );
|
||||
log_info( "\n" );
|
||||
log_info( "\tnumReps - Optional integer specifying the number of repetitions to run and average the result (defaults to 1)\n" );
|
||||
log_info( "\treduction%% - Optional integer, followed by a %% sign, that acts as a multiplier for the target amount of memory.\n" );
|
||||
log_info( "\t Example: target amount of 512MB and a reduction of 75%% will result in a target of 384MB.\n" );
|
||||
log_info( "\n" );
|
||||
log_info( "\tdo_not_force_fill - Disable explicitly write data to all memory objects after creating them.\n" );
|
||||
log_info( "\t Without this, the kernel execution can not verify its checksum.\n" );
|
||||
log_info( "\tdo_not_execute - Disable executing a kernel that accesses all of the memory objects.\n" );
|
||||
log_info( "\n" );
|
||||
log_info( "Test names (Allocation Types):\n" );
|
||||
for( int i = 0; i < test_num; i++ )
|
||||
log_info("Usage: %s [options] [test_names]\n", execName);
|
||||
log_info("Options:\n");
|
||||
log_info("\trandomize - Uses random seed\n");
|
||||
log_info(
|
||||
"\tsingle - Tests using a single allocation as large as possible\n");
|
||||
log_info("\tmultiple - Tests using as many allocations as possible\n");
|
||||
log_info("\n");
|
||||
log_info("\tnumReps - Optional integer specifying the number of "
|
||||
"repetitions to run and average the result (defaults to 1)\n");
|
||||
log_info("\treduction%% - Optional integer, followed by a %% sign, that "
|
||||
"acts as a multiplier for the target amount of memory.\n");
|
||||
log_info("\t Example: target amount of 512MB and a reduction "
|
||||
"of 75%% will result in a target of 384MB.\n");
|
||||
log_info("\n");
|
||||
log_info("\tdo_not_force_fill - Disable explicitly write data to all "
|
||||
"memory objects after creating them.\n");
|
||||
log_info("\t Without this, the kernel execution can not "
|
||||
"verify its checksum.\n");
|
||||
log_info("\tdo_not_execute - Disable executing a kernel that accesses all "
|
||||
"of the memory objects.\n");
|
||||
log_info("\n");
|
||||
log_info("Test names (Allocation Types):\n");
|
||||
for (int i = 0; i < test_registry::getInstance().num_tests(); i++)
|
||||
{
|
||||
log_info( "\t%s\n", test_list[i].name );
|
||||
log_info("\t%s\n", test_registry::getInstance().definitions()[i].name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -39,9 +39,10 @@
|
|||
#define FAILED_CORRUPTED_QUEUE -2
|
||||
#define FAILED_ABORT -1
|
||||
#define FAILED_TOO_BIG 1
|
||||
// On Windows macro `SUCCEEDED' is defined in `WinError.h'. It causes compiler warnings. Let us avoid them.
|
||||
#if defined( _WIN32 ) && defined( SUCCEEDED )
|
||||
#undef SUCCEEDED
|
||||
// On Windows macro `SUCCEEDED' is defined in `WinError.h'. It causes compiler
|
||||
// warnings. Let us avoid them.
|
||||
#if defined(_WIN32) && defined(SUCCEEDED)
|
||||
#undef SUCCEEDED
|
||||
#endif
|
||||
#define SUCCEEDED 0
|
||||
|
||||
|
|
@ -55,11 +56,16 @@ enum AllocType
|
|||
IMAGE_WRITE_NON_BLOCKING,
|
||||
};
|
||||
|
||||
#define test_error_abort(errCode,msg) test_error_ret_abort(errCode,msg,errCode)
|
||||
#define test_error_ret_abort(errCode,msg,retValue) { if( errCode != CL_SUCCESS ) { print_error( errCode, msg ); return FAILED_ABORT ; } }
|
||||
#define test_error_abort(errCode, msg) \
|
||||
test_error_ret_abort(errCode, msg, errCode)
|
||||
#define test_error_ret_abort(errCode, msg, retValue) \
|
||||
{ \
|
||||
if (errCode != CL_SUCCESS) \
|
||||
{ \
|
||||
print_error(errCode, msg); \
|
||||
return FAILED_ABORT; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#endif // _testBase_h
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ set(MODULE_NAME API)
|
|||
set(${MODULE_NAME}_SOURCES
|
||||
main.cpp
|
||||
negative_platform.cpp
|
||||
negative_queue.cpp
|
||||
test_api_consistency.cpp
|
||||
test_bool.cpp
|
||||
test_retain.cpp
|
||||
|
|
@ -10,10 +11,12 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_queries.cpp
|
||||
test_create_kernels.cpp
|
||||
test_kernels.cpp
|
||||
test_kernel_local_memory_size.cpp
|
||||
test_kernel_private_memory_size.cpp
|
||||
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 +24,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
|
||||
|
|
@ -35,6 +37,8 @@ set(${MODULE_NAME}_SOURCES
|
|||
test_mem_object_properties_queries.cpp
|
||||
test_queue_properties_queries.cpp
|
||||
test_pipe_properties_queries.cpp
|
||||
test_wg_suggested_local_work_size.cpp
|
||||
test_device_command_queue.cpp
|
||||
)
|
||||
|
||||
include(../CMakeCommon.txt)
|
||||
|
|
|
|||
|
|
@ -13,146 +13,11 @@
|
|||
// 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 "procs.h"
|
||||
#include "harness/testHarness.h"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// FIXME: To use certain functions in harness/imageHelpers.h
|
||||
// (for example, generate_random_image_data()), the tests are required to
|
||||
// declare the following variables (<rdar://problem/11111245>):
|
||||
|
||||
test_definition test_list[] = {
|
||||
ADD_TEST(get_platform_info),
|
||||
ADD_TEST_VERSION(get_sampler_info, Version(2, 0)),
|
||||
ADD_TEST(get_sampler_info_compatibility),
|
||||
ADD_TEST_VERSION(get_command_queue_info, Version(2, 0)),
|
||||
ADD_TEST(get_command_queue_info_compatibility),
|
||||
ADD_TEST(get_context_info),
|
||||
ADD_TEST(get_device_info),
|
||||
ADD_TEST(enqueue_task),
|
||||
ADD_TEST(binary_get),
|
||||
ADD_TEST(binary_create),
|
||||
ADD_TEST(kernel_required_group_size),
|
||||
|
||||
ADD_TEST(release_kernel_order),
|
||||
ADD_TEST(release_during_execute),
|
||||
|
||||
ADD_TEST(load_single_kernel),
|
||||
ADD_TEST(load_two_kernels),
|
||||
ADD_TEST(load_two_kernels_in_one),
|
||||
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),
|
||||
ADD_TEST(execute_kernel_local_sizes),
|
||||
ADD_TEST(set_kernel_arg_by_index),
|
||||
ADD_TEST(set_kernel_arg_constant),
|
||||
ADD_TEST(set_kernel_arg_struct_array),
|
||||
ADD_TEST(kernel_global_constant),
|
||||
|
||||
ADD_TEST(min_max_thread_dimensions),
|
||||
ADD_TEST(min_max_work_items_sizes),
|
||||
ADD_TEST(min_max_work_group_size),
|
||||
ADD_TEST(min_max_read_image_args),
|
||||
ADD_TEST(min_max_write_image_args),
|
||||
ADD_TEST(min_max_mem_alloc_size),
|
||||
ADD_TEST(min_max_image_2d_width),
|
||||
ADD_TEST(min_max_image_2d_height),
|
||||
ADD_TEST(min_max_image_3d_width),
|
||||
ADD_TEST(min_max_image_3d_height),
|
||||
ADD_TEST(min_max_image_3d_depth),
|
||||
ADD_TEST(min_max_image_array_size),
|
||||
ADD_TEST(min_max_image_buffer_size),
|
||||
ADD_TEST(min_max_parameter_size),
|
||||
ADD_TEST(min_max_samplers),
|
||||
ADD_TEST(min_max_constant_buffer_size),
|
||||
ADD_TEST(min_max_constant_args),
|
||||
ADD_TEST(min_max_compute_units),
|
||||
ADD_TEST(min_max_address_bits),
|
||||
ADD_TEST(min_max_single_fp_config),
|
||||
ADD_TEST(min_max_double_fp_config),
|
||||
ADD_TEST(min_max_local_mem_size),
|
||||
ADD_TEST(min_max_kernel_preferred_work_group_size_multiple),
|
||||
ADD_TEST(min_max_execution_capabilities),
|
||||
ADD_TEST(min_max_queue_properties),
|
||||
ADD_TEST(min_max_device_version),
|
||||
ADD_TEST(min_max_language_version),
|
||||
|
||||
ADD_TEST(kernel_arg_changes),
|
||||
ADD_TEST(kernel_arg_multi_setup_random),
|
||||
|
||||
ADD_TEST(native_kernel),
|
||||
|
||||
ADD_TEST(create_context_from_type),
|
||||
|
||||
ADD_TEST(platform_extensions),
|
||||
ADD_TEST(get_platform_ids),
|
||||
ADD_TEST(bool_type),
|
||||
|
||||
ADD_TEST(repeated_setup_cleanup),
|
||||
|
||||
ADD_TEST(retain_queue_single),
|
||||
ADD_TEST(retain_queue_multiple),
|
||||
ADD_TEST(retain_mem_object_single),
|
||||
ADD_TEST(retain_mem_object_multiple),
|
||||
ADD_TEST(retain_mem_object_set_kernel_arg),
|
||||
ADD_TEST(min_data_type_align_size_alignment),
|
||||
|
||||
ADD_TEST_VERSION(context_destructor_callback, Version(3, 0)),
|
||||
ADD_TEST(mem_object_destructor_callback),
|
||||
ADD_TEST(null_buffer_arg),
|
||||
ADD_TEST(get_buffer_info),
|
||||
ADD_TEST(get_image2d_info),
|
||||
ADD_TEST(get_image3d_info),
|
||||
ADD_TEST(get_image1d_info),
|
||||
ADD_TEST(get_image1d_array_info),
|
||||
ADD_TEST(get_image2d_array_info),
|
||||
ADD_TEST(queue_flush_on_release),
|
||||
ADD_TEST(queue_hint),
|
||||
ADD_TEST(queue_properties),
|
||||
ADD_TEST_VERSION(sub_group_dispatch, Version(2, 1)),
|
||||
ADD_TEST_VERSION(clone_kernel, Version(2, 1)),
|
||||
ADD_TEST_VERSION(zero_sized_enqueue, Version(2, 1)),
|
||||
|
||||
ADD_TEST_VERSION(buffer_properties_queries, Version(3, 0)),
|
||||
ADD_TEST_VERSION(image_properties_queries, Version(3, 0)),
|
||||
ADD_TEST_VERSION(queue_properties_queries, Version(3, 0)),
|
||||
ADD_TEST_VERSION(pipe_properties_queries, Version(3, 0)),
|
||||
|
||||
ADD_TEST_VERSION(consistency_svm, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_memory_model, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_device_enqueue, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_pipes, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_progvar, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_non_uniform_work_group, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_read_write_images, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_2d_image_from_buffer, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_depth_images, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_device_and_host_timer, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_il_programs, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_subgroups, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_prog_ctor_dtor, Version(3, 0)),
|
||||
ADD_TEST_VERSION(consistency_3d_image_writes, Version(3, 0)),
|
||||
|
||||
ADD_TEST(min_image_formats),
|
||||
ADD_TEST(negative_get_platform_info),
|
||||
ADD_TEST(negative_get_platform_ids),
|
||||
};
|
||||
|
||||
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);
|
||||
return runTestHarness(argc, argv, test_registry::getInstance().num_tests(),
|
||||
test_registry::getInstance().definitions(), false, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
#include "testBase.h"
|
||||
|
||||
int test_negative_get_platform_ids(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(negative_get_platform_ids)
|
||||
{
|
||||
cl_platform_id platform;
|
||||
cl_int err = clGetPlatformIDs(0, &platform, nullptr);
|
||||
|
|
@ -37,31 +36,13 @@ int test_negative_get_platform_ids(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_negative_get_platform_info(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(negative_get_platform_info)
|
||||
{
|
||||
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);
|
||||
cl_platform_id platform = getPlatformFromDevice(device);
|
||||
|
||||
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 "
|
||||
|
|
|
|||
168
test_conformance/api/negative_queue.cpp
Normal file
168
test_conformance/api/negative_queue.cpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
//
|
||||
// Copyright (c) 2024 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 "testBase.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
|
||||
REGISTER_TEST(negative_create_command_queue)
|
||||
{
|
||||
cl_command_queue_properties device_props = 0;
|
||||
cl_int error = clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES,
|
||||
sizeof(device_props), &device_props, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_QUEUE_PROPERTIES failed");
|
||||
|
||||
// CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE is the only optional property to
|
||||
// clCreateCommandQueue, CL_QUEUE_PROFILING_ENABLE is mandatory.
|
||||
const bool out_of_order_device_support =
|
||||
device_props & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
|
||||
if (out_of_order_device_support)
|
||||
{
|
||||
// Early return as we can't check correct error is returned for
|
||||
// unsupported property.
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
// Try create a command queue with out-of-order property and check return
|
||||
// code
|
||||
cl_int test_error = CL_SUCCESS;
|
||||
clCommandQueueWrapper test_queue = clCreateCommandQueue(
|
||||
context, device, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &test_error);
|
||||
|
||||
test_failure_error_ret(
|
||||
test_error, CL_INVALID_QUEUE_PROPERTIES,
|
||||
"clCreateCommandQueue should return CL_INVALID_QUEUE_PROPERTIES if "
|
||||
"values specified in properties are valid but are not supported by "
|
||||
"the "
|
||||
"device.",
|
||||
TEST_FAIL);
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
REGISTER_TEST_VERSION(negative_create_command_queue_with_properties,
|
||||
Version(2, 0))
|
||||
{
|
||||
cl_command_queue_properties device_props = 0;
|
||||
cl_int error = clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES,
|
||||
sizeof(device_props), &device_props, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_QUEUE_PROPERTIES failed");
|
||||
|
||||
cl_command_queue_properties device_on_host_props = 0;
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
|
||||
sizeof(device_on_host_props), &device_on_host_props,
|
||||
NULL);
|
||||
test_error(error,
|
||||
"clGetDeviceInfo for CL_DEVICE_QUEUE_ON_HOST_PROPERTIES failed");
|
||||
|
||||
if (device_on_host_props != device_props)
|
||||
{
|
||||
log_error(
|
||||
"ERROR: CL_DEVICE_QUEUE_PROPERTIES and "
|
||||
"CL_DEVICE_QUEUE_ON_HOST_PROPERTIES properties should match\n");
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
// CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE is the only optional host-queue
|
||||
// property to clCreateCommandQueueWithProperties,
|
||||
// CL_QUEUE_PROFILING_ENABLE is mandatory.
|
||||
const bool out_of_order_device_support =
|
||||
device_props & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
|
||||
if (out_of_order_device_support)
|
||||
{
|
||||
// Early return as we can't check correct error is returned for
|
||||
// unsupported property.
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
// Try create a command queue with out-of-order property and check return
|
||||
// code
|
||||
cl_command_queue_properties queue_prop_def[] = {
|
||||
CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0
|
||||
};
|
||||
|
||||
cl_int test_error = CL_SUCCESS;
|
||||
clCommandQueueWrapper test_queue = clCreateCommandQueueWithProperties(
|
||||
context, device, queue_prop_def, &test_error);
|
||||
|
||||
test_failure_error_ret(test_error, CL_INVALID_QUEUE_PROPERTIES,
|
||||
"clCreateCommandQueueWithProperties should "
|
||||
"return CL_INVALID_QUEUE_PROPERTIES if "
|
||||
"values specified in properties are valid but "
|
||||
"are not supported by the "
|
||||
"device.",
|
||||
TEST_FAIL);
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
REGISTER_TEST(negative_create_command_queue_with_properties_khr)
|
||||
{
|
||||
if (!is_extension_available(device, "cl_khr_create_command_queue"))
|
||||
{
|
||||
return TEST_SKIPPED_ITSELF;
|
||||
}
|
||||
|
||||
cl_platform_id platform;
|
||||
cl_int error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM,
|
||||
sizeof(cl_platform_id), &platform, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed");
|
||||
|
||||
clCreateCommandQueueWithPropertiesKHR_fn
|
||||
clCreateCommandQueueWithPropertiesKHR =
|
||||
(clCreateCommandQueueWithPropertiesKHR_fn)
|
||||
clGetExtensionFunctionAddressForPlatform(
|
||||
platform, "clCreateCommandQueueWithPropertiesKHR");
|
||||
if (clCreateCommandQueueWithPropertiesKHR == NULL)
|
||||
{
|
||||
log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cl_command_queue_properties device_props = 0;
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES,
|
||||
sizeof(device_props), &device_props, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_QUEUE_PROPERTIES failed");
|
||||
|
||||
// CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE is the only optional host-queue
|
||||
// property to clCreateCommandQueueWithPropertiesKHR,
|
||||
// CL_QUEUE_PROFILING_ENABLE is mandatory.
|
||||
const bool out_of_order_device_support =
|
||||
device_props & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
|
||||
if (out_of_order_device_support)
|
||||
{
|
||||
// Early return as we can't check correct error is returned for
|
||||
// unsupported property.
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
// Try create a command queue with out-of-order property and check return
|
||||
// code
|
||||
cl_queue_properties_khr queue_prop_def[] = {
|
||||
CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0
|
||||
};
|
||||
|
||||
cl_int test_error = CL_SUCCESS;
|
||||
clCommandQueueWrapper test_khr_queue =
|
||||
clCreateCommandQueueWithPropertiesKHR(context, device, queue_prop_def,
|
||||
&test_error);
|
||||
|
||||
test_failure_error_ret(test_error, CL_INVALID_QUEUE_PROPERTIES,
|
||||
"clCreateCommandQueueWithPropertiesKHR should "
|
||||
"return CL_INVALID_QUEUE_PROPERTIES if "
|
||||
"values specified in properties are valid but "
|
||||
"are not supported by the "
|
||||
"device.",
|
||||
TEST_FAIL);
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
|
@ -1,205 +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/errorHelpers.h"
|
||||
#include "harness/kernelHelpers.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
#include "harness/clImageHelper.h"
|
||||
#include "harness/imageHelpers.h"
|
||||
extern float calculate_ulperror(float a, float b);
|
||||
|
||||
extern int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_load_two_kernels_manually(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_create_kernels_in_program(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_bool_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_platform_extensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_platform_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_sampler_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_sampler_info_compatibility(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_command_queue_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_command_queue_info_compatibility(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_context_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_get_device_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_kernel_required_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_binary_get(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_binary_create(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_release_kernel_order(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_release_during_execute(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_get_kernel_info(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_kernel_private_memory_size(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_execute_kernel_local_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_set_kernel_arg_by_index(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_set_kernel_arg_struct(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_set_kernel_arg_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_set_kernel_arg_struct_array(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_kernel_global_constant(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_min_max_thread_dimensions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_work_items_sizes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_work_group_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_read_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_write_image_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_mem_alloc_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_2d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_2d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_3d_width(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_3d_height(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_3d_depth(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_array_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_image_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_parameter_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_samplers(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_constant_args(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_compute_units(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_address_bits(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_execution_capabilities(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_queue_properties(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_device_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_max_language_version(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_native_kernel(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems );
|
||||
|
||||
extern int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_get_platform_ids(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_kernel_arg_changes(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_kernel_arg_multi_setup_random(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_retain_queue_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_retain_queue_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_retain_mem_object_single(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_retain_mem_object_multiple(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_retain_mem_object_set_kernel_arg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_min_data_type_align_size_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems );
|
||||
|
||||
extern int test_context_destructor_callback(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_mem_object_destructor_callback(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
|
||||
extern int test_null_buffer_arg( cl_device_id device_id, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements );
|
||||
extern int test_get_image2d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements );
|
||||
extern int test_get_image3d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements );
|
||||
extern int test_get_image1d_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements );
|
||||
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);
|
||||
extern int test_zero_sized_enqueue(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
|
||||
extern int test_queue_properties( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements );
|
||||
extern int test_queue_flush_on_release(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_buffer_properties_queries(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_image_properties_queries(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_queue_properties_queries(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
int test_pipe_properties_queries(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
|
||||
extern int test_consistency_svm(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_consistency_memory_model(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_device_enqueue(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_pipes(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_consistency_progvar(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_consistency_non_uniform_work_group(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_read_write_images(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_2d_image_from_buffer(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_depth_images(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_device_and_host_timer(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_il_programs(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_consistency_prog_ctor_dtor(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_consistency_3d_image_writes(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
|
||||
extern int test_min_image_formats(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements);
|
||||
extern int test_negative_get_platform_info(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements);
|
||||
extern int test_negative_get_platform_ids(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
|
||||
|
|
@ -17,15 +17,14 @@
|
|||
#define _testBase_h
|
||||
|
||||
#include "harness/compat.h"
|
||||
#include "harness/testHarness.h"
|
||||
#include "harness/typeWrappers.h"
|
||||
#include "harness/imageHelpers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "procs.h"
|
||||
|
||||
#endif // _testBase_h
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include <cinttypes>
|
||||
|
||||
#include "testBase.h"
|
||||
#include "harness/testHarness.h"
|
||||
#include "harness/deviceInfo.h"
|
||||
|
|
@ -23,8 +25,7 @@ __kernel void test(__global int* dst) {
|
|||
}
|
||||
)CLC";
|
||||
|
||||
int test_consistency_svm(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_svm, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_SVM_CAPABILITIES:
|
||||
// May return 0, indicating that device does not support Shared Virtual
|
||||
|
|
@ -37,8 +38,8 @@ int test_consistency_svm(cl_device_id deviceID, cl_context context,
|
|||
clKernelWrapper kernel;
|
||||
|
||||
cl_device_svm_capabilities svmCaps = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_CAPABILITIES,
|
||||
sizeof(svmCaps), &svmCaps, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_SVM_CAPABILITIES, sizeof(svmCaps),
|
||||
&svmCaps, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_SVM_CAPABILITIES");
|
||||
|
||||
if (svmCaps == 0)
|
||||
|
|
@ -158,8 +159,9 @@ static int check_atomic_capabilities(cl_device_atomic_capabilities atomicCaps,
|
|||
{
|
||||
if ((atomicCaps & requiredCaps) != requiredCaps)
|
||||
{
|
||||
log_error("Atomic capabilities %llx is missing support for at least "
|
||||
"one required capability %llx!\n",
|
||||
log_error("Atomic capabilities %" PRIx64
|
||||
" is missing support for at least "
|
||||
"one required capability %" PRIx64 "!\n",
|
||||
atomicCaps, requiredCaps);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
|
@ -199,13 +201,12 @@ static int check_atomic_capabilities(cl_device_atomic_capabilities atomicCaps,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_memory_model(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_memory_model, Version(3, 0))
|
||||
{
|
||||
cl_int error;
|
||||
cl_device_atomic_capabilities atomicCaps = 0;
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES,
|
||||
sizeof(atomicCaps), &atomicCaps, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES");
|
||||
|
||||
|
|
@ -218,7 +219,7 @@ int test_consistency_memory_model(cl_device_id deviceID, cl_context context,
|
|||
return error;
|
||||
}
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_ATOMIC_FENCE_CAPABILITIES,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_ATOMIC_FENCE_CAPABILITIES,
|
||||
sizeof(atomicCaps), &atomicCaps, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_ATOMIC_FENCE_CAPABILITIES");
|
||||
|
||||
|
|
@ -235,8 +236,7 @@ int test_consistency_memory_model(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_device_enqueue, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES
|
||||
// May return 0, indicating that device does not support Device-Side Enqueue
|
||||
|
|
@ -244,7 +244,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
cl_int error;
|
||||
|
||||
cl_device_device_enqueue_capabilities dseCaps = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES,
|
||||
sizeof(dseCaps), &dseCaps, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES");
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
// On-Device Queues.
|
||||
|
||||
cl_command_queue_properties devQueueProps = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES,
|
||||
sizeof(devQueueProps), &devQueueProps, NULL);
|
||||
test_error(error,
|
||||
"Unable to query CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES");
|
||||
|
|
@ -275,7 +275,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
cl_uint u = 0;
|
||||
|
||||
error =
|
||||
clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE,
|
||||
clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE,
|
||||
sizeof(u), &u, NULL);
|
||||
test_error(error,
|
||||
"Unable to query CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE");
|
||||
|
|
@ -284,7 +284,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
"but CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE "
|
||||
"returned a non-zero value");
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE,
|
||||
sizeof(u), &u, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE");
|
||||
test_assert_error(
|
||||
|
|
@ -292,7 +292,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
"CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but "
|
||||
"CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE returned a non-zero value");
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_ON_DEVICE_QUEUES,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES,
|
||||
sizeof(u), &u, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_MAX_ON_DEVICE_QUEUES");
|
||||
test_assert_error(
|
||||
|
|
@ -300,7 +300,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
"CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but "
|
||||
"CL_DEVICE_MAX_ON_DEVICE_QUEUES returned a non-zero value");
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_ON_DEVICE_EVENTS,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_EVENTS,
|
||||
sizeof(u), &u, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_MAX_ON_DEVICE_EVENTS");
|
||||
test_assert_error(
|
||||
|
|
@ -331,7 +331,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
// clSetDefaultDeviceCommandQueue
|
||||
// Returns CL_INVALID_OPERATION if device does not support On-Device
|
||||
// Queues.
|
||||
error = clSetDefaultDeviceCommandQueue(context, deviceID, NULL);
|
||||
error = clSetDefaultDeviceCommandQueue(context, device, NULL);
|
||||
test_failure_error(error, CL_INVALID_OPERATION,
|
||||
"CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 "
|
||||
"but clSetDefaultDeviceCommandQueue did not return "
|
||||
|
|
@ -344,7 +344,7 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
// clSetDefaultDeviceCommandQueue
|
||||
// Returns CL_INVALID_OPERATION if device does not support a
|
||||
// replaceable default On-Device Queue.
|
||||
error = clSetDefaultDeviceCommandQueue(context, deviceID, NULL);
|
||||
error = clSetDefaultDeviceCommandQueue(context, device, NULL);
|
||||
test_failure_error(
|
||||
error, CL_INVALID_OPERATION,
|
||||
"CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES did not "
|
||||
|
|
@ -368,9 +368,9 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
if ((dseCaps & CL_DEVICE_QUEUE_SUPPORTED) != 0)
|
||||
{
|
||||
cl_bool b;
|
||||
error = clGetDeviceInfo(deviceID,
|
||||
CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT,
|
||||
sizeof(b), &b, NULL);
|
||||
error =
|
||||
clGetDeviceInfo(device, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT,
|
||||
sizeof(b), &b, NULL);
|
||||
test_error(
|
||||
error,
|
||||
"Unable to query CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT");
|
||||
|
|
@ -384,16 +384,15 @@ int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_pipes(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_pipes, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_PIPE_SUPPORT
|
||||
// May return CL_FALSE, indicating that device does not support Pipes.
|
||||
cl_int error;
|
||||
|
||||
cl_bool pipeSupport = CL_FALSE;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_SUPPORT,
|
||||
sizeof(pipeSupport), &pipeSupport, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PIPE_SUPPORT, sizeof(pipeSupport),
|
||||
&pipeSupport, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_PIPE_SUPPORT");
|
||||
|
||||
if (pipeSupport == CL_FALSE)
|
||||
|
|
@ -406,16 +405,15 @@ int test_consistency_pipes(cl_device_id deviceID, cl_context context,
|
|||
|
||||
cl_uint u = 0;
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PIPE_ARGS, sizeof(u),
|
||||
&u, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_MAX_PIPE_ARGS, sizeof(u), &u,
|
||||
NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_MAX_PIPE_ARGS");
|
||||
test_assert_error(u == 0,
|
||||
"CL_DEVICE_PIPE_SUPPORT returned CL_FALSE, but "
|
||||
"CL_DEVICE_MAX_PIPE_ARGS returned a non-zero value");
|
||||
|
||||
error =
|
||||
clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS,
|
||||
sizeof(u), &u, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS,
|
||||
sizeof(u), &u, NULL);
|
||||
test_error(error,
|
||||
"Unable to query CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS");
|
||||
test_assert_error(u == 0,
|
||||
|
|
@ -423,7 +421,7 @@ int test_consistency_pipes(cl_device_id deviceID, cl_context context,
|
|||
"CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS returned "
|
||||
"a non-zero value");
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_MAX_PACKET_SIZE,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PIPE_MAX_PACKET_SIZE,
|
||||
sizeof(u), &u, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_PIPE_MAX_PACKET_SIZE");
|
||||
test_assert_error(
|
||||
|
|
@ -458,9 +456,8 @@ int test_consistency_pipes(cl_device_id deviceID, cl_context context,
|
|||
// Devices that support pipes must also return CL_TRUE
|
||||
// for CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT.
|
||||
cl_bool b;
|
||||
error =
|
||||
clGetDeviceInfo(deviceID, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT,
|
||||
sizeof(b), &b, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT,
|
||||
sizeof(b), &b, NULL);
|
||||
test_error(error,
|
||||
"Unable to query CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT");
|
||||
test_assert_error(
|
||||
|
|
@ -472,8 +469,7 @@ int test_consistency_pipes(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_progvar(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_progvar, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE
|
||||
// May return 0, indicating that device does not support Program Scope
|
||||
|
|
@ -484,7 +480,7 @@ int test_consistency_progvar(cl_device_id deviceID, cl_context context,
|
|||
clKernelWrapper kernel;
|
||||
|
||||
size_t maxGlobalVariableSize = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE,
|
||||
sizeof(maxGlobalVariableSize),
|
||||
&maxGlobalVariableSize, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE");
|
||||
|
|
@ -503,7 +499,7 @@ int test_consistency_progvar(cl_device_id deviceID, cl_context context,
|
|||
// CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE
|
||||
// Returns 0 if device does not support Program Scope Global Variables.
|
||||
|
||||
error = clGetDeviceInfo(deviceID,
|
||||
error = clGetDeviceInfo(device,
|
||||
CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE,
|
||||
sizeof(sz), &sz, NULL);
|
||||
test_error(
|
||||
|
|
@ -520,7 +516,7 @@ int test_consistency_progvar(cl_device_id deviceID, cl_context context,
|
|||
// Returns 0 if device does not support Program Scope Global Variables.
|
||||
|
||||
error = clGetProgramBuildInfo(
|
||||
program, deviceID, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE,
|
||||
program, device, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE,
|
||||
sizeof(sz), &sz, NULL);
|
||||
test_error(
|
||||
error,
|
||||
|
|
@ -534,10 +530,7 @@ int test_consistency_progvar(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_non_uniform_work_group(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_non_uniform_work_group, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT:
|
||||
// May return CL_FALSE, indicating that device does not support Non-Uniform
|
||||
|
|
@ -550,7 +543,7 @@ int test_consistency_non_uniform_work_group(cl_device_id deviceID,
|
|||
clKernelWrapper kernel;
|
||||
|
||||
cl_bool nonUniformWorkGroupSupport = CL_FALSE;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT,
|
||||
sizeof(nonUniformWorkGroupSupport),
|
||||
&nonUniformWorkGroupSupport, NULL);
|
||||
test_error(error,
|
||||
|
|
@ -617,9 +610,7 @@ int test_consistency_non_uniform_work_group(cl_device_id deviceID,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_read_write_images(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_read_write_images, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing
|
||||
// CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS May return 0,
|
||||
|
|
@ -627,7 +618,7 @@ int test_consistency_read_write_images(cl_device_id deviceID,
|
|||
cl_int error;
|
||||
|
||||
cl_uint maxReadWriteImageArgs = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS,
|
||||
sizeof(maxReadWriteImageArgs),
|
||||
&maxReadWriteImageArgs, NULL);
|
||||
test_error(error,
|
||||
|
|
@ -647,7 +638,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(
|
||||
|
|
@ -680,10 +671,7 @@ int test_consistency_read_write_images(cl_device_id deviceID,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_2d_image_from_buffer(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_2d_image_from_buffer, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_IMAGE_PITCH_ALIGNMENT or
|
||||
// CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT
|
||||
|
|
@ -700,7 +688,7 @@ int test_consistency_2d_image_from_buffer(cl_device_id deviceID,
|
|||
clMemWrapper image;
|
||||
|
||||
cl_uint imagePitchAlignment = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_PITCH_ALIGNMENT,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE_PITCH_ALIGNMENT,
|
||||
sizeof(imagePitchAlignment), &imagePitchAlignment,
|
||||
NULL);
|
||||
test_error(error,
|
||||
|
|
@ -708,7 +696,7 @@ int test_consistency_2d_image_from_buffer(cl_device_id deviceID,
|
|||
"CL_DEVICE_IMAGE_PITCH_ALIGNMENT");
|
||||
|
||||
cl_uint imageBaseAddressAlignment = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT,
|
||||
sizeof(imageBaseAddressAlignment),
|
||||
&imageBaseAddressAlignment, NULL);
|
||||
test_error(error,
|
||||
|
|
@ -716,7 +704,7 @@ int test_consistency_2d_image_from_buffer(cl_device_id deviceID,
|
|||
"CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT");
|
||||
|
||||
bool supports_cl_khr_image2d_from_buffer =
|
||||
is_extension_available(deviceID, "cl_khr_image2d_from_buffer");
|
||||
is_extension_available(device, "cl_khr_image2d_from_buffer");
|
||||
|
||||
if (imagePitchAlignment == 0 || imageBaseAddressAlignment == 0)
|
||||
{
|
||||
|
|
@ -787,8 +775,7 @@ int test_consistency_2d_image_from_buffer(cl_device_id deviceID,
|
|||
// All of the sRGB Image Channel Orders (such as CL_sRGBA) are optional for
|
||||
// devices supporting OpenCL 3.0.
|
||||
|
||||
int test_consistency_depth_images(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_depth_images, Version(3, 0))
|
||||
{
|
||||
// The CL_DEPTH Image Channel Order is optional for devices supporting
|
||||
// OpenCL 3.0.
|
||||
|
|
@ -801,7 +788,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],
|
||||
|
|
@ -827,7 +814,7 @@ int test_consistency_depth_images(cl_device_id deviceID, cl_context context,
|
|||
}
|
||||
|
||||
bool supports_cl_khr_depth_images =
|
||||
is_extension_available(deviceID, "cl_khr_depth_images");
|
||||
is_extension_available(device, "cl_khr_depth_images");
|
||||
|
||||
if (totalDepthImageFormats == 0)
|
||||
{
|
||||
|
|
@ -845,10 +832,7 @@ int test_consistency_depth_images(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_device_and_host_timer(cl_device_id deviceID,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_device_and_host_timer, Version(3, 0))
|
||||
{
|
||||
// clGetPlatformInfo, passing CL_PLATFORM_HOST_TIMER_RESOLUTION
|
||||
// May return 0, indicating that platform does not support Device and Host
|
||||
|
|
@ -856,7 +840,7 @@ int test_consistency_device_and_host_timer(cl_device_id deviceID,
|
|||
cl_int error;
|
||||
|
||||
cl_platform_id platform = NULL;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform),
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform),
|
||||
&platform, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_PLATFORM");
|
||||
|
||||
|
|
@ -875,13 +859,13 @@ int test_consistency_device_and_host_timer(cl_device_id deviceID,
|
|||
cl_ulong dt = 0;
|
||||
cl_ulong ht = 0;
|
||||
|
||||
error = clGetDeviceAndHostTimer(deviceID, &dt, &ht);
|
||||
error = clGetDeviceAndHostTimer(device, &dt, &ht);
|
||||
test_failure_error(
|
||||
error, CL_INVALID_OPERATION,
|
||||
"CL_PLATFORM_HOST_TIMER_RESOLUTION returned 0 but "
|
||||
"clGetDeviceAndHostTimer did not return CL_INVALID_OPERATION");
|
||||
|
||||
error = clGetHostTimer(deviceID, &ht);
|
||||
error = clGetHostTimer(device, &ht);
|
||||
test_failure_error(
|
||||
error, CL_INVALID_OPERATION,
|
||||
"CL_PLATFORM_HOST_TIMER_RESOLUTION returned 0 but "
|
||||
|
|
@ -891,8 +875,7 @@ int test_consistency_device_and_host_timer(cl_device_id deviceID,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_il_programs(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_il_programs, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_IL_VERSION or
|
||||
// CL_DEVICE_ILS_WITH_VERSION
|
||||
|
|
@ -906,14 +889,14 @@ int test_consistency_il_programs(cl_device_id deviceID, cl_context context,
|
|||
// Even if the device does not support Intermediate Language Programs the
|
||||
// size of the string query should not be zero.
|
||||
size_t sz = SIZE_MAX;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_IL_VERSION, 0, NULL, &sz);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION, 0, NULL, &sz);
|
||||
test_error(error, "Unable to query CL_DEVICE_IL_VERSION");
|
||||
test_assert_error(sz != 0,
|
||||
"CL_DEVICE_IL_VERSION should return a non-zero size");
|
||||
|
||||
std::string ilVersion = get_device_il_version_string(deviceID);
|
||||
std::string ilVersion = get_device_il_version_string(device);
|
||||
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_ILS_WITH_VERSION, 0, NULL, &sz);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_ILS_WITH_VERSION, 0, NULL, &sz);
|
||||
test_error(error, "Unable to query CL_DEVICE_ILS_WITH_VERSION");
|
||||
|
||||
if (ilVersion == "" || sz == 0)
|
||||
|
|
@ -932,7 +915,7 @@ int test_consistency_il_programs(cl_device_id deviceID, cl_context context,
|
|||
"but CL_DEVICE_IL_VERSION returned an empty string");
|
||||
|
||||
bool supports_cl_khr_il_program =
|
||||
is_extension_available(deviceID, "cl_khr_il_program");
|
||||
is_extension_available(device, "cl_khr_il_program");
|
||||
test_assert_error(supports_cl_khr_il_program == false,
|
||||
"Device does not support IL Programs but does "
|
||||
"support cl_khr_il_program");
|
||||
|
|
@ -982,8 +965,7 @@ int test_consistency_il_programs(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_subgroups, Version(3, 0))
|
||||
{
|
||||
// clGetDeviceInfo, passing CL_DEVICE_MAX_NUM_SUB_GROUPS
|
||||
// May return 0, indicating that device does not support Subgroups.
|
||||
|
|
@ -993,7 +975,7 @@ int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
|||
clKernelWrapper kernel;
|
||||
|
||||
cl_uint maxNumSubGroups = 0;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_NUM_SUB_GROUPS,
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_MAX_NUM_SUB_GROUPS,
|
||||
sizeof(maxNumSubGroups), &maxNumSubGroups, NULL);
|
||||
test_error(error, "Unable to query CL_DEVICE_MAX_NUM_SUB_GROUPS");
|
||||
|
||||
|
|
@ -1011,7 +993,7 @@ int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
|||
|
||||
cl_bool ifp = CL_FALSE;
|
||||
error = clGetDeviceInfo(
|
||||
deviceID, CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS,
|
||||
device, CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS,
|
||||
sizeof(ifp), &ifp, NULL);
|
||||
test_error(
|
||||
error,
|
||||
|
|
@ -1026,7 +1008,7 @@ int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
|||
// device does not support Subgroups.
|
||||
|
||||
bool supports_cl_khr_subgroups =
|
||||
is_extension_available(deviceID, "cl_khr_subgroups");
|
||||
is_extension_available(device, "cl_khr_subgroups");
|
||||
test_assert_error(supports_cl_khr_subgroups == false,
|
||||
"Device does not support Subgroups but does "
|
||||
"support cl_khr_subgroups");
|
||||
|
|
@ -1035,7 +1017,7 @@ int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
|||
// Returns CL_INVALID_OPERATION if device does not support Subgroups.
|
||||
|
||||
size_t sz = SIZE_MAX;
|
||||
error = clGetKernelSubGroupInfo(kernel, deviceID,
|
||||
error = clGetKernelSubGroupInfo(kernel, device,
|
||||
CL_KERNEL_MAX_NUM_SUB_GROUPS, 0, NULL,
|
||||
sizeof(sz), &sz, NULL);
|
||||
test_failure_error(
|
||||
|
|
@ -1049,8 +1031,7 @@ int test_consistency_subgroups(cl_device_id deviceID, cl_context context,
|
|||
|
||||
static void CL_CALLBACK program_callback(cl_program, void*) {}
|
||||
|
||||
int test_consistency_prog_ctor_dtor(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_prog_ctor_dtor, Version(3, 0))
|
||||
{
|
||||
cl_int error;
|
||||
|
||||
|
|
@ -1096,8 +1077,7 @@ int test_consistency_prog_ctor_dtor(cl_device_id deviceID, cl_context context,
|
|||
return TEST_PASS;
|
||||
}
|
||||
|
||||
int test_consistency_3d_image_writes(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(consistency_3d_image_writes, Version(3, 0))
|
||||
{
|
||||
// clGetSupportedImageFormats, passing CL_MEM_OBJECT_IMAGE3D and one of
|
||||
// CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE, or CL_MEM_KERNEL_READ_AND_WRITE
|
||||
|
|
@ -1114,7 +1094,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],
|
||||
|
|
@ -1128,7 +1108,7 @@ int test_consistency_3d_image_writes(cl_device_id deviceID, cl_context context,
|
|||
}
|
||||
|
||||
bool supports_cl_khr_3d_image_writes =
|
||||
is_extension_available(deviceID, "cl_khr_3d_image_writes");
|
||||
is_extension_available(device, "cl_khr_3d_image_writes");
|
||||
|
||||
if (total3DImageWriteFormats == 0)
|
||||
{
|
||||
|
|
@ -1148,3 +1128,137 @@ int test_consistency_3d_image_writes(cl_device_id deviceID, cl_context context,
|
|||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
REGISTER_TEST(consistency_requirements_fp64)
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
cl_device_fp_config value = 0;
|
||||
|
||||
if (is_extension_available(device, "cl_khr_fp64"))
|
||||
{
|
||||
const Version version = get_device_cl_version(device);
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_DOUBLE_FP_CONFIG,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(error, "Unable to get device CL_DEVICE_DOUBLE_FP_CONFIG");
|
||||
test_assert_error(
|
||||
value > 0, "CL_DEVICE_DOUBLE_FP_CONFIG must return nonzero value");
|
||||
if (version < Version(2, 0))
|
||||
{
|
||||
test_assert_error(
|
||||
value
|
||||
& (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO
|
||||
| CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM),
|
||||
"Reported double fp config doesn't meet minimum set "
|
||||
"for OpenCL 1.0, OpenCL 1.1, OpenCL 1.2 devices");
|
||||
}
|
||||
else
|
||||
{
|
||||
test_assert_error(
|
||||
value
|
||||
& (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN
|
||||
| CL_FP_DENORM),
|
||||
"Reported double fp config doesn't meet minimum set "
|
||||
"for OpenCL 2.0 or newer devices");
|
||||
}
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(
|
||||
error,
|
||||
"Unable to get device CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE");
|
||||
test_assert_error(value > 0,
|
||||
"CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE must return "
|
||||
"nonzero value");
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(error,
|
||||
"Unable to get device CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE");
|
||||
test_assert_error(
|
||||
value > 0,
|
||||
"CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE must return nonzero value");
|
||||
}
|
||||
else
|
||||
{
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_DOUBLE_FP_CONFIG,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(error, "Unable to get device CL_DEVICE_DOUBLE_FP_CONFIG");
|
||||
test_assert_error(value == 0,
|
||||
"CL_DEVICE_DOUBLE_FP_CONFIG must return 0");
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(
|
||||
error,
|
||||
"Unable to get device CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE");
|
||||
test_assert_error(
|
||||
value == 0,
|
||||
"CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE must return 0");
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(error,
|
||||
"Unable to get device CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE");
|
||||
test_assert_error(value == 0,
|
||||
"CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE must return 0");
|
||||
}
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
REGISTER_TEST(consistency_requirements_fp16)
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
cl_device_fp_config value = 0;
|
||||
|
||||
if (is_extension_available(device, "cl_khr_fp16"))
|
||||
{
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_HALF_FP_CONFIG, sizeof(value),
|
||||
&value, nullptr);
|
||||
test_error(error, "Unable to get device CL_DEVICE_HALF_FP_CONFIG");
|
||||
test_assert_error(value > 0,
|
||||
"CL_DEVICE_HALF_FP_CONFIG must return nonzero value");
|
||||
|
||||
test_assert_error((value & (CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN))
|
||||
|| (value & CL_FP_ROUND_TO_ZERO),
|
||||
"Reported half fp config doesn't meet minimum set");
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(
|
||||
error,
|
||||
"Unable to get device CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF");
|
||||
test_assert_error(value > 0,
|
||||
"CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF must return "
|
||||
"nonzero value");
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(error,
|
||||
"Unable to get device CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF");
|
||||
test_assert_error(
|
||||
value > 0,
|
||||
"CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF must return nonzero value");
|
||||
}
|
||||
else
|
||||
{
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(
|
||||
error,
|
||||
"Unable to get device CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF");
|
||||
test_assert_error(value == 0,
|
||||
"CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF must return "
|
||||
"0");
|
||||
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF,
|
||||
sizeof(value), &value, nullptr);
|
||||
test_error(error,
|
||||
"Unable to get device CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF");
|
||||
test_assert_error(value == 0,
|
||||
"CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF must return 0");
|
||||
}
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -25,7 +25,7 @@ static const char *sample_binary_kernel_source[] = {
|
|||
"}\n" };
|
||||
|
||||
|
||||
int test_binary_get(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(binary_get)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -71,7 +71,7 @@ int test_binary_get(cl_device_id deviceID, cl_context context, cl_command_queue
|
|||
}
|
||||
|
||||
|
||||
int test_binary_create(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(binary_create)
|
||||
{
|
||||
/* To test this in a self-contained fashion, we have to create a program with
|
||||
source, then get the binary, then use that binary to reload the program, and then verify */
|
||||
|
|
@ -103,12 +103,13 @@ int test_binary_create(cl_device_id deviceID, cl_context context, cl_command_que
|
|||
test_error( error, "Unable to get program binary" );
|
||||
|
||||
cl_int loadErrors[ 1 ];
|
||||
program_from_binary = clCreateProgramWithBinary( context, 1, &deviceID, &binarySize, buffers, loadErrors, &error );
|
||||
program_from_binary = clCreateProgramWithBinary(
|
||||
context, 1, &device, &binarySize, buffers, loadErrors, &error);
|
||||
test_error( error, "Unable to load valid program binary" );
|
||||
test_error( loadErrors[ 0 ], "Unable to load valid device binary into program" );
|
||||
|
||||
error = clBuildProgram( program_from_binary, 1, &deviceID, NULL, NULL, NULL );
|
||||
test_error( error, "Unable to build binary program" );
|
||||
error = clBuildProgram(program_from_binary, 1, &device, NULL, NULL, NULL);
|
||||
test_error(error, "Unable to build binary program");
|
||||
|
||||
// Get the size of the binary built from the first binary
|
||||
size_t binary2Size;
|
||||
|
|
@ -123,10 +124,11 @@ int test_binary_create(cl_device_id deviceID, cl_context context, cl_command_que
|
|||
|
||||
// Try again, this time without passing the status ptr in, to make sure we still
|
||||
// get a valid binary
|
||||
clProgramWrapper programWithoutStatus = clCreateProgramWithBinary( context, 1, &deviceID, &binary2Size, buffers, NULL, &error );
|
||||
clProgramWrapper programWithoutStatus = clCreateProgramWithBinary(
|
||||
context, 1, &device, &binary2Size, buffers, NULL, &error);
|
||||
test_error( error, "Unable to load valid program binary when binary_status pointer is NULL" );
|
||||
|
||||
error = clBuildProgram( programWithoutStatus, 1, &deviceID, NULL, NULL, NULL );
|
||||
error = clBuildProgram(programWithoutStatus, 1, &device, NULL, NULL, NULL);
|
||||
test_error( error, "Unable to build binary program created without binary_status" );
|
||||
|
||||
// Get the size of the binary created without passing binary_status
|
||||
|
|
@ -214,5 +216,3 @@ int test_binary_create(cl_device_id deviceID, cl_context context, cl_command_que
|
|||
free(out_data_binary);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const char *kernel_with_bool[] = {
|
|||
"}\n"
|
||||
};
|
||||
|
||||
int test_bool_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(bool_type)
|
||||
{
|
||||
|
||||
clProgramWrapper program;
|
||||
|
|
@ -48,4 +48,3 @@ int test_bool_type(cl_device_id deviceID, cl_context context, cl_command_queue q
|
|||
"kernel_with_bool" );
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char *clone_kernel_test_img[] =
|
||||
{
|
||||
"__kernel void img_read_kernel(read_only image2d_t img, sampler_t sampler, __global int* outbuf)\n"
|
||||
|
|
@ -94,19 +92,9 @@ 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 test_image_arg_shallow_clone(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements,
|
||||
void* pbufRes, clMemWrapper& bufOut)
|
||||
{
|
||||
int error;
|
||||
cl_image_format img_format;
|
||||
|
|
@ -205,7 +193,9 @@ int test_image_arg_shallow_clone(cl_device_id deviceID, cl_context context, cl_c
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_double_arg_clone(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, void* pbufRes, clMemWrapper& bufOut)
|
||||
int test_double_arg_clone(cl_device_id device, cl_context context,
|
||||
cl_command_queue queue, int num_elements,
|
||||
void* pbufRes, clMemWrapper& bufOut)
|
||||
{
|
||||
int error = 0;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -242,7 +232,7 @@ int test_double_arg_clone(cl_device_id deviceID, cl_context context, cl_command_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(clone_kernel, Version(2, 1))
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -264,11 +254,12 @@ int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
cl_bool bimg = CL_FALSE;
|
||||
cl_bool bdouble = CL_FALSE;
|
||||
// test image support
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &bimg, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool),
|
||||
&bimg, NULL);
|
||||
test_error( error, "clGetDeviceInfo failed." );
|
||||
|
||||
// test double support
|
||||
if (is_extension_available(deviceID, "cl_khr_fp64"))
|
||||
if (is_extension_available(device, "cl_khr_fp64"))
|
||||
{
|
||||
bdouble = CL_TRUE;
|
||||
}
|
||||
|
|
@ -323,6 +314,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." );
|
||||
|
|
@ -383,13 +382,15 @@ int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
|
||||
if (bimg)
|
||||
{
|
||||
error = test_image_arg_shallow_clone(deviceID, context, queue, num_elements, pbufRes, bufOut);
|
||||
error = test_image_arg_shallow_clone(device, context, queue,
|
||||
num_elements, pbufRes, bufOut);
|
||||
test_error( error, "image arg shallow clone test failed." );
|
||||
}
|
||||
|
||||
if (bdouble)
|
||||
{
|
||||
error = test_double_arg_clone(deviceID, context, queue, num_elements, pbufRes, bufOut);
|
||||
error = test_double_arg_clone(device, context, queue, num_elements,
|
||||
pbufRes, bufOut);
|
||||
test_error( error, "double arg clone test failed." );
|
||||
}
|
||||
|
||||
|
|
@ -398,4 +399,3 @@ int test_clone_kernel(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,11 @@ void CL_CALLBACK context_destructor_callback(cl_context context, void *userData)
|
|||
*userPtr = ++sDestructorIndex;
|
||||
}
|
||||
|
||||
int test_context_destructor_callback(cl_device_id deviceID, cl_context context,
|
||||
cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST_VERSION(context_destructor_callback, Version(3, 0))
|
||||
{
|
||||
cl_int error;
|
||||
clContextWrapper localContext =
|
||||
clCreateContext(NULL, 1, &deviceID, NULL, NULL, &error);
|
||||
clCreateContext(NULL, 1, &device, NULL, NULL, &error);
|
||||
test_error(error, "Unable to create local context");
|
||||
|
||||
// Set up some variables to catch the order in which callbacks are called
|
||||
|
|
@ -52,12 +51,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;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@
|
|||
#endif
|
||||
|
||||
#include "harness/conversions.h"
|
||||
#include <bitset>
|
||||
|
||||
int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(create_context_from_type)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -46,11 +47,12 @@ int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_
|
|||
"}\n" };
|
||||
|
||||
cl_device_type type;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed\n");
|
||||
|
||||
cl_platform_id platform;
|
||||
error = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL);
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform),
|
||||
&platform, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed\n");
|
||||
|
||||
cl_context_properties properties[3] = {
|
||||
|
|
@ -66,7 +68,7 @@ int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_
|
|||
return -1;
|
||||
}
|
||||
|
||||
queue_to_test = clCreateCommandQueue(context_to_test, deviceID, 0, &error);
|
||||
queue_to_test = clCreateCommandQueue(context_to_test, device, 0, &error);
|
||||
test_error(error, "clCreateCommandQueue failed");
|
||||
if (queue_to_test == NULL) {
|
||||
log_error("clCreateCommandQueue returned NULL, but error was CL_SUCCESS.");
|
||||
|
|
@ -127,4 +129,107 @@ int test_create_context_from_type(cl_device_id deviceID, cl_context context, cl_
|
|||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_TEST(create_context_from_type_device_type_all)
|
||||
{
|
||||
cl_device_type type;
|
||||
cl_int error =
|
||||
clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed\n");
|
||||
|
||||
std::bitset<sizeof(cl_device_type)> type_bits(type);
|
||||
|
||||
if (type_bits.count() > 1 || (type & CL_DEVICE_TYPE_DEFAULT))
|
||||
{
|
||||
log_error("clGetDeviceInfo(CL_DEVICE_TYPE) must report a single device "
|
||||
"type, which must not be CL_DEVICE_TYPE_DEFAULT or "
|
||||
"CL_DEVICE_TYPE_ALL.\n");
|
||||
return -1;
|
||||
}
|
||||
cl_platform_id platform;
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform),
|
||||
&platform, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed\n");
|
||||
|
||||
cl_context_properties properties[3] = {
|
||||
(cl_context_properties)CL_CONTEXT_PLATFORM,
|
||||
(cl_context_properties)platform, 0
|
||||
};
|
||||
|
||||
clContextWrapper context_to_test = clCreateContextFromType(
|
||||
properties, CL_DEVICE_TYPE_ALL, notify_callback, NULL, &error);
|
||||
test_error(error, "clCreateContextFromType failed");
|
||||
|
||||
cl_uint num_devices = 0;
|
||||
error = clGetContextInfo(context_to_test, CL_CONTEXT_NUM_DEVICES,
|
||||
sizeof(cl_uint), &num_devices, nullptr);
|
||||
test_error(error, "clGetContextInfo CL_CONTEXT_NUM_DEVICES failed\n");
|
||||
|
||||
test_assert_error(num_devices >= 1,
|
||||
"Context must contain at least one device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_TEST(create_context_from_type_device_type_default)
|
||||
{
|
||||
cl_device_type type;
|
||||
cl_int error =
|
||||
clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_TYPE failed\n");
|
||||
|
||||
std::bitset<sizeof(cl_device_type)> type_bits(type);
|
||||
|
||||
if (type_bits.count() > 1 || (type & CL_DEVICE_TYPE_DEFAULT))
|
||||
{
|
||||
log_error("clGetDeviceInfo(CL_DEVICE_TYPE) must report a single device "
|
||||
"type, which must not be CL_DEVICE_TYPE_DEFAULT or "
|
||||
"CL_DEVICE_TYPE_ALL.\n");
|
||||
return -1;
|
||||
}
|
||||
cl_platform_id platform;
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform),
|
||||
&platform, NULL);
|
||||
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed\n");
|
||||
|
||||
cl_context_properties properties[3] = {
|
||||
(cl_context_properties)CL_CONTEXT_PLATFORM,
|
||||
(cl_context_properties)platform, 0
|
||||
};
|
||||
|
||||
clContextWrapper context_to_test = clCreateContextFromType(
|
||||
properties, CL_DEVICE_TYPE_DEFAULT, notify_callback, NULL, &error);
|
||||
test_error(error, "clCreateContextFromType failed");
|
||||
|
||||
cl_uint num_devices = 0;
|
||||
error = clGetContextInfo(context_to_test, CL_CONTEXT_NUM_DEVICES,
|
||||
sizeof(cl_uint), &num_devices, nullptr);
|
||||
test_error(error, "clGetContextInfo CL_CONTEXT_NUM_DEVICES failed\n");
|
||||
|
||||
std::vector<cl_device_id> devices(num_devices);
|
||||
error = clGetContextInfo(context_to_test, CL_CONTEXT_DEVICES,
|
||||
num_devices * sizeof(cl_device_id), devices.data(),
|
||||
nullptr);
|
||||
test_error(error, "clGetContextInfo CL_CONTEXT_DEVICES failed\n");
|
||||
|
||||
test_assert_error(devices.size() == 1,
|
||||
"Context must contain exactly one device\n");
|
||||
|
||||
cl_uint num_platform_devices;
|
||||
|
||||
error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_DEFAULT, 0, NULL,
|
||||
&num_platform_devices);
|
||||
test_error(error, "clGetDeviceIDs failed.\n");
|
||||
test_assert_error(num_platform_devices == 1,
|
||||
"clGetDeviceIDs must return exactly one device\n");
|
||||
|
||||
std::vector<cl_device_id> platform_devices(num_platform_devices);
|
||||
error = clGetDeviceIDs(platform, CL_DEVICE_TYPE_DEFAULT,
|
||||
num_platform_devices, platform_devices.data(), NULL);
|
||||
test_error(error, "clGetDeviceIDs failed.\n");
|
||||
|
||||
test_assert_error(platform_devices[0] == devices[0],
|
||||
"device in the context must be equivalent to device "
|
||||
"returned by clGetDeviceIDs\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,7 @@ const char *repeate_test_kernel =
|
|||
"}\n";
|
||||
|
||||
|
||||
|
||||
int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(load_single_kernel)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -159,7 +158,7 @@ int test_load_single_kernel(cl_device_id deviceID, cl_context context, cl_comman
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(load_two_kernels)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -239,7 +238,7 @@ int test_load_two_kernels(cl_device_id deviceID, cl_context context, cl_command_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(load_two_kernels_in_one)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -320,7 +319,7 @@ int test_load_two_kernels_in_one(cl_device_id deviceID, cl_context context, cl_c
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_load_two_kernels_manually( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(load_two_kernels_manually)
|
||||
{
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel1, kernel2;
|
||||
|
|
@ -351,7 +350,7 @@ int test_load_two_kernels_manually( cl_device_id deviceID, cl_context context, c
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test_get_program_info_kernel_names( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(get_program_info_kernel_names)
|
||||
{
|
||||
clProgramWrapper program;
|
||||
clKernelWrapper kernel1, kernel2;
|
||||
|
|
@ -406,8 +405,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;
|
||||
|
|
@ -442,7 +441,7 @@ static const char *single_task_kernel[] = {
|
|||
"\n"
|
||||
"}\n" };
|
||||
|
||||
int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(enqueue_task)
|
||||
{
|
||||
int error;
|
||||
clProgramWrapper program;
|
||||
|
|
@ -491,9 +490,8 @@ int test_enqueue_task(cl_device_id deviceID, cl_context context, cl_command_queu
|
|||
}
|
||||
|
||||
|
||||
|
||||
#define TEST_SIZE 1000
|
||||
int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
|
||||
REGISTER_TEST(repeated_setup_cleanup)
|
||||
{
|
||||
|
||||
cl_context local_context;
|
||||
|
|
@ -519,10 +517,11 @@ int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_co
|
|||
for (i=0; i<100; i++) {
|
||||
memset(outData, 0, sizeof(cl_int)*TEST_SIZE);
|
||||
|
||||
local_context = clCreateContext(NULL, 1, &deviceID, notify_callback, NULL, &error);
|
||||
local_context =
|
||||
clCreateContext(NULL, 1, &device, notify_callback, NULL, &error);
|
||||
test_error( error, "clCreateContext failed");
|
||||
|
||||
local_queue = clCreateCommandQueue(local_context, deviceID, 0, &error);
|
||||
local_queue = clCreateCommandQueue(local_context, device, 0, &error);
|
||||
test_error( error, "clCreateCommandQueue failed");
|
||||
|
||||
error = create_single_kernel_helper(
|
||||
|
|
@ -590,6 +589,3 @@ int test_repeated_setup_cleanup(cl_device_id deviceID, cl_context context, cl_co
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
85
test_conformance/api/test_device_command_queue.cpp
Normal file
85
test_conformance/api/test_device_command_queue.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
#include "testBase.h"
|
||||
#include <array>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
int test_command_queue_helper(cl_context context, cl_device_id deviceID,
|
||||
cl_command_queue queue)
|
||||
{
|
||||
cl_int error;
|
||||
cl_command_queue check_queue;
|
||||
|
||||
error = clSetDefaultDeviceCommandQueue(context, deviceID, queue);
|
||||
test_error(error, "clSetDefaultDeviceCommandQueue failed ");
|
||||
|
||||
error = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE_DEFAULT,
|
||||
sizeof(check_queue), &check_queue, nullptr);
|
||||
test_error(error,
|
||||
"clGetCommandQueueInfo failed for CL_QUEUE_DEVICE_DEFAULT");
|
||||
test_assert_error(
|
||||
(check_queue == queue),
|
||||
"Expected the queue to be returned as default device queue failed");
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
|
||||
REGISTER_TEST_VERSION(set_default_device_command_queue, Version(2, 1))
|
||||
{
|
||||
cl_int error;
|
||||
constexpr cl_command_queue_properties PROPERTIES = CL_QUEUE_ON_DEVICE
|
||||
| CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE;
|
||||
std::array<cl_queue_properties, 3> properties = {
|
||||
CL_QUEUE_PROPERTIES, (PROPERTIES | CL_QUEUE_ON_DEVICE_DEFAULT), 0
|
||||
};
|
||||
|
||||
if (get_device_cl_version(device) >= Version(3, 0))
|
||||
{
|
||||
cl_device_device_enqueue_capabilities dseCaps = 0;
|
||||
error = clGetDeviceInfo(device, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES,
|
||||
sizeof(dseCaps), &dseCaps, NULL);
|
||||
test_error(error,
|
||||
"Unable to query CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES");
|
||||
|
||||
if (0 == (dseCaps & CL_DEVICE_QUEUE_REPLACEABLE_DEFAULT))
|
||||
return TEST_SKIPPED_ITSELF;
|
||||
}
|
||||
|
||||
clCommandQueueWrapper cmd_queue_1 = clCreateCommandQueueWithProperties(
|
||||
context, device, properties.data(), &error);
|
||||
test_error(error, "clCreateCommandQueueWithProperties failed");
|
||||
|
||||
properties[1] = PROPERTIES;
|
||||
clCommandQueueWrapper cmd_queue_2 = clCreateCommandQueueWithProperties(
|
||||
context, device, properties.data(), &error);
|
||||
test_error(error, "clCreateCommandQueueWithProperties failed");
|
||||
|
||||
// cmd_queue_1
|
||||
if (test_command_queue_helper(context, device, cmd_queue_1) != 0)
|
||||
{
|
||||
test_fail("test_command_queue_helper failed for cmd_queue_1.\n");
|
||||
}
|
||||
|
||||
// cmd_queue_2 - without CL_QUEUE_ON_DEVICE_DEFAULT
|
||||
if (test_command_queue_helper(context, device, cmd_queue_2) != 0)
|
||||
{
|
||||
test_fail("test_command_queue_helper failed for cmd_queue_2.\n");
|
||||
}
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue