Compare commits
609 Commits
mesa-11.0.
...
vulkan-hea
Author | SHA1 | Date | |
---|---|---|---|
|
5520221118 | ||
|
73a8f9543a | ||
|
55781f8d02 | ||
|
756d8064c1 | ||
|
927f54de68 | ||
|
9c0db9d349 | ||
|
6037b5d610 | ||
|
7ccc8dd24a | ||
|
d22d5f25fc | ||
|
da4d9f6c7c | ||
|
d862099198 | ||
|
498ae009d3 | ||
|
6f140e8af1 | ||
|
badbf0c94a | ||
|
61a4bfe253 | ||
|
e1c78ebe53 | ||
|
f4748bff59 | ||
|
4c8e1e5888 | ||
|
f5ad06eb78 | ||
|
188f2328de | ||
|
c6270e8044 | ||
|
365d80a91e | ||
|
7529e7ce86 | ||
|
8213be790e | ||
|
43241a24bc | ||
|
94e473c993 | ||
|
e375f722a6 | ||
|
9aabe69028 | ||
|
5f46c4608f | ||
|
0eeba6b80c | ||
|
2b5a4dc5f3 | ||
|
1f658bed70 | ||
|
ca7243b54e | ||
|
553b4434ca | ||
|
e5db209d54 | ||
|
c7fcfebd5b | ||
|
2a9136feb4 | ||
|
2c4dc92f40 | ||
|
d7f44852be | ||
|
1fd3bc818a | ||
|
2e2f48f840 | ||
|
02db21ae11 | ||
|
a463eacb8f | ||
|
98957b18d2 | ||
|
a35811d086 | ||
|
55723e97f1 | ||
|
ccb2e5cd62 | ||
|
30445f8f7a | ||
|
d2c0870ff3 | ||
|
8478350992 | ||
|
68768c40be | ||
|
66cbb7f76d | ||
|
6d0ed38db5 | ||
|
1ca611cbad | ||
|
6eec0b186c | ||
|
4b2c5a98f0 | ||
|
08f7731f67 | ||
|
0c8456ef1e | ||
|
b29c929e8e | ||
|
5e1737c42f | ||
|
d80fea1af6 | ||
|
9250e1e9e5 | ||
|
f925ea31e7 | ||
|
ec5e2f4992 | ||
|
a684198935 | ||
|
6e5ab5cf1b | ||
|
114015321e | ||
|
cb57bff36c | ||
|
8ae8e14ba7 | ||
|
dd67c134ad | ||
|
e18377f435 | ||
|
e93b6d8eb1 | ||
|
584cb7a16f | ||
|
68c7ef502d | ||
|
549070b18c | ||
|
ebb191f145 | ||
|
435ccf4056 | ||
|
ffb51fd112 | ||
|
45f8723f44 | ||
|
180c07ee50 | ||
|
4b05a8cd31 | ||
|
f1cf55fae6 | ||
|
3112098776 | ||
|
c633ab5822 | ||
|
8f3b2187e1 | ||
|
77dcfe3c70 | ||
|
601d0891a6 | ||
|
829810fa27 | ||
|
17c8232ecf | ||
|
a158ff55f0 | ||
|
1c4238a8e5 | ||
|
f43a304dc6 | ||
|
df2a013881 | ||
|
c7f512721c | ||
|
8cda3e9b1b | ||
|
4422bd4cf6 | ||
|
7552e026da | ||
|
8b342b39a3 | ||
|
b94b8dfad5 | ||
|
18340883e3 | ||
|
9e64a2a8e4 | ||
|
19f0a9b582 | ||
|
6eb221c884 | ||
|
fb4e2195ec | ||
|
a52e208203 | ||
|
b1de1d4f6e | ||
|
8739e8fbe2 | ||
|
92556c77f4 | ||
|
098209eedf | ||
|
73f9187e33 | ||
|
7d24fab4ef | ||
|
5c49730164 | ||
|
c95f9b61f2 | ||
|
335e88c8ee | ||
|
34871cf7f3 | ||
|
8c2c37fae7 | ||
|
1f907011a3 | ||
|
977a469bce | ||
|
65e0b304b6 | ||
|
f6d51f3fd3 | ||
|
5b75dffd04 | ||
|
fa915b661d | ||
|
c34d314db3 | ||
|
cff06bbe7d | ||
|
3318a86d12 | ||
|
b8fedc19f5 | ||
|
e4292ac039 | ||
|
997831868f | ||
|
a841e2c747 | ||
|
8640dc12dc | ||
|
5a4ebf6bc1 | ||
|
4fcb32a17d | ||
|
367b9ba78f | ||
|
d29ec8fa36 | ||
|
c8577b5f52 | ||
|
ccb27a002c | ||
|
8985dd15a1 | ||
|
e02dfa309a | ||
|
e9034ed875 | ||
|
aae45ab583 | ||
|
b4ef7f354b | ||
|
522ab835d6 | ||
|
7598329774 | ||
|
52940e8fcf | ||
|
e19d6be2a9 | ||
|
c84f2d3b8c | ||
|
b20cc72603 | ||
|
8e05bbeee9 | ||
|
cc29a5f4be | ||
|
719fa8ac74 | ||
|
fc6dcc6227 | ||
|
12119282e6 | ||
|
3c65a1ac14 | ||
|
bb6567f5d1 | ||
|
e7acdda184 | ||
|
db24afee2f | ||
|
ef8980e256 | ||
|
d9c2caea6a | ||
|
d5349b1b18 | ||
|
6aa1b89457 | ||
|
0ff06540ae | ||
|
435b062b26 | ||
|
518ca9e254 | ||
|
672590710b | ||
|
80046a7d54 | ||
|
3e4b00d283 | ||
|
a35fef1ab2 | ||
|
d2ca7e24b4 | ||
|
abbb776bbe | ||
|
e7ddfe03ab | ||
|
f89e2e6304 | ||
|
55ab1737d3 | ||
|
11901a9100 | ||
|
dff32238c7 | ||
|
85c0d69be9 | ||
|
0ecb789b71 | ||
|
f78d684772 | ||
|
18ee32ef9d | ||
|
4af79ab076 | ||
|
788a8352b9 | ||
|
7fbed521bb | ||
|
d6b840beff | ||
|
84a5bc25e3 | ||
|
f2899b1af2 | ||
|
962d6932fa | ||
|
1fb859e4b2 | ||
|
245583075c | ||
|
0a42332904 | ||
|
a1eea996d4 | ||
|
c325bb24b5 | ||
|
23075bccb3 | ||
|
69e11adecc | ||
|
b844f542e0 | ||
|
5b04db71ff | ||
|
1f1b26bceb | ||
|
63c1190e47 | ||
|
d84f3155b1 | ||
|
65f9ccb4e7 | ||
|
68fa750f2e | ||
|
d5b5bd67f6 | ||
|
d843418c2e | ||
|
2b37fc28d1 | ||
|
a75967b1bb | ||
|
2b404e5d00 | ||
|
c57ca3f16f | ||
|
2de388c49c | ||
|
1b0c47bba6 | ||
|
c7cef662d0 | ||
|
8c5e48f307 | ||
|
d9176f2ec7 | ||
|
e95bf93e5a | ||
|
1b7b580756 | ||
|
2fb524b369 | ||
|
c5ffcc9958 | ||
|
c5ab5925df | ||
|
ea5fbe1957 | ||
|
9a798fa946 | ||
|
78a0d23d4e | ||
|
11cf214578 | ||
|
0dc7d4ac8a | ||
|
19aabb5730 | ||
|
f9dbc34a18 | ||
|
f3ea3b6e58 | ||
|
15047514c9 | ||
|
73351c6a18 | ||
|
70d2336e7e | ||
|
aca5fc6af1 | ||
|
66375e2852 | ||
|
23c179be75 | ||
|
f9bb95ad4a | ||
|
d5dccc1e7a | ||
|
4a42f45514 | ||
|
630b19a1c8 | ||
|
2f9180b1b2 | ||
|
1f1465f077 | ||
|
8a6c8177e0 | ||
|
beb0e25327 | ||
|
fa663c27f5 | ||
|
e3d60d479b | ||
|
7a749aa4ba | ||
|
682eb9489d | ||
|
bba767a9af | ||
|
6720b47717 | ||
|
709fa463ec | ||
|
5b3a1ceb83 | ||
|
c6e76aed9d | ||
|
127cb3f6c5 | ||
|
fdcd71f71d | ||
|
ca6cef3302 | ||
|
9c46ba9ca2 | ||
|
667529fbaa | ||
|
74e3eb304f | ||
|
55752fe94a | ||
|
6ee082718f | ||
|
37d6e04ba1 | ||
|
67a7659d69 | ||
|
5d7103ee15 | ||
|
0349e8d607 | ||
|
068b8a41e2 | ||
|
7ea707a42a | ||
|
b91a76de98 | ||
|
ebe1e768b8 | ||
|
45b804a049 | ||
|
528071f004 | ||
|
4c8146313f | ||
|
4b8b451a1d | ||
|
af0ade0d6c | ||
|
ae29fd1b55 | ||
|
d5e41a3a99 | ||
|
c4c1d96a01 | ||
|
4f5ef945e0 | ||
|
588acdb431 | ||
|
333b8ddd6b | ||
|
7e1792b1b7 | ||
|
b72936fdad | ||
|
ee0a8f23e4 | ||
|
fa352969a2 | ||
|
99031aa0f3 | ||
|
7ea121687c | ||
|
cb30acaced | ||
|
1132080d5d | ||
|
5f2d469e37 | ||
|
f7fb7575ef | ||
|
7cec6c5dfd | ||
|
d178e15567 | ||
|
845002e163 | ||
|
2ecac045a4 | ||
|
e369a0eb41 | ||
|
d0bd2bc604 | ||
|
ba0d9d33d4 | ||
|
1bc0a1ad98 | ||
|
88d02a1b27 | ||
|
24dff4f8fa | ||
|
a62edcce4e | ||
|
dee4a94e69 | ||
|
fe1269cf28 | ||
|
9a3dda101e | ||
|
e9c21d0ca0 | ||
|
9b9f973ca6 | ||
|
9e59003fb1 | ||
|
b20794cfa8 | ||
|
aba75d0546 | ||
|
841aab6f50 | ||
|
d0fc04aacf | ||
|
22854a60ef | ||
|
0e86ab7c0a | ||
|
de4c31a085 | ||
|
aedd3c9579 | ||
|
bf5a615659 | ||
|
fa8a07748d | ||
|
c103c4990c | ||
|
2fdd17d259 | ||
|
00494c6cb7 | ||
|
fbc9fe3c92 | ||
|
765175f5d1 | ||
|
7637b02aaa | ||
|
405697eb3d | ||
|
e7edde60ba | ||
|
f7fe06cf0a | ||
|
9aae480cc4 | ||
|
923e923bbc | ||
|
1dd63fcbed | ||
|
b581e924b6 | ||
|
d76ea7644a | ||
|
a5b49d2799 | ||
|
ea7ef46cf9 | ||
|
a566b1e08a | ||
|
2a3c29698c | ||
|
c8b62d109b | ||
|
7153b56abc | ||
|
29d2bbb2b5 | ||
|
047ed02723 | ||
|
9cae3d18ac | ||
|
d5ad24e39b | ||
|
e17ed04b03 | ||
|
1ee2d1c3fc | ||
|
2d2e148952 | ||
|
ffb1ee5d20 | ||
|
f1db3b3869 | ||
|
11e941900a | ||
|
5d4b6a01af | ||
|
634a6150b9 | ||
|
919e7b7551 | ||
|
0599d39dd9 | ||
|
d57c4cf999 | ||
|
822cb16abe | ||
|
081f617b5a | ||
|
e6bd568f36 | ||
|
5b777e2bcf | ||
|
d842a6965f | ||
|
9f292219bf | ||
|
66b00d5e5a | ||
|
38f5eef59d | ||
|
999b56c507 | ||
|
3a38b0db5f | ||
|
9d6f55dedf | ||
|
e6162c2fef | ||
|
58afc24e57 | ||
|
b6363c3f12 | ||
|
531549d9fc | ||
|
66a4dab89a | ||
|
920fb771d4 | ||
|
52637c0996 | ||
|
9eab70e54f | ||
|
ce00233c13 | ||
|
e69588b764 | ||
|
c2eeab305b | ||
|
ed2ca020f8 | ||
|
aa523d3c62 | ||
|
87d98e1935 | ||
|
b981379bcf | ||
|
8d930da35d | ||
|
7f90e56e42 | ||
|
9cd42b3dea | ||
|
251aea80b0 | ||
|
47bd462b0c | ||
|
a37d122e88 | ||
|
1286bd3160 | ||
|
2f6aa424e9 | ||
|
5744d1763c | ||
|
c8f078537e | ||
|
e702197e3f | ||
|
fbafc946c6 | ||
|
f98c89ef31 | ||
|
08748e3a0c | ||
|
d4cbf6a728 | ||
|
510b5c3bed | ||
|
aded32bf04 | ||
|
5caa408579 | ||
|
76bb658518 | ||
|
dc56e4f7b8 | ||
|
e497ac2c62 | ||
|
2251305e1a | ||
|
33cccbbb73 | ||
|
b2b9fc9fad | ||
|
03ffa9ca31 | ||
|
4ffbab5ae0 | ||
|
c4bd5f87a0 | ||
|
4aecec0bd6 | ||
|
fad418ff47 | ||
|
9ffc1bed15 | ||
|
468c89a351 | ||
|
2dc0f7fe5b | ||
|
8cf932fd25 | ||
|
730ca0efb1 | ||
|
de221a672d | ||
|
6eefeb1f84 | ||
|
5a317ef4cb | ||
|
1435bf4bc4 | ||
|
f559fe9134 | ||
|
ca385dcf2a | ||
|
466f61e9f6 | ||
|
fab9011c44 | ||
|
c0739043b3 | ||
|
4514e63893 | ||
|
fd8b5e0df2 | ||
|
df4b02f4ed | ||
|
b23885857f | ||
|
da8f148203 | ||
|
59def43fc8 | ||
|
1c63575de8 | ||
|
403266be05 | ||
|
5ef81f0a05 | ||
|
6f3e3c715a | ||
|
59328bac10 | ||
|
a1d30f867d | ||
|
2514ac5547 | ||
|
1cd8437b9d | ||
|
610e6291da | ||
|
b29f44218d | ||
|
5e637c5d5a | ||
|
998837764f | ||
|
0dbed616af | ||
|
cbe7ed416e | ||
|
37743f90bc | ||
|
7c0d0021eb | ||
|
0997a7b2e3 | ||
|
c03314bdd3 | ||
|
ae8c93e023 | ||
|
912944e59d | ||
|
1b211feb6c | ||
|
903bd4b056 | ||
|
57153da2d5 | ||
|
0f0b5aecb8 | ||
|
0a54751910 | ||
|
519fe765e2 | ||
|
ccf2bf9b99 | ||
|
f3d70e4165 | ||
|
cb56372eeb | ||
|
0e441cde71 | ||
|
f17e835c26 | ||
|
b13c0f469b | ||
|
f294154e42 | ||
|
f9e66ea621 | ||
|
a29df71dd2 | ||
|
f886647b75 | ||
|
63da974529 | ||
|
387a1bb58f | ||
|
a1bd426393 | ||
|
01504057f5 | ||
|
a61f307996 | ||
|
14929046ba | ||
|
47c1cf5ce6 | ||
|
bea66ac5ad | ||
|
9557b85e3d | ||
|
13719e9225 | ||
|
d7044a19b1 | ||
|
edff076188 | ||
|
e37a89136f | ||
|
4bcf58a192 | ||
|
1573913194 | ||
|
e4c11f50b5 | ||
|
851495d344 | ||
|
4668bbb161 | ||
|
7c9f209427 | ||
|
923691c70d | ||
|
d24f8245db | ||
|
997596e4c4 | ||
|
241b59cba0 | ||
|
ae9ac47c74 | ||
|
82ddab4b18 | ||
|
1d40e6ade8 | ||
|
f330bad545 | ||
|
b6c7d8c911 | ||
|
4063b7deb8 | ||
|
b6ab076d6b | ||
|
682d11a6e8 | ||
|
28804fb9e4 | ||
|
8440b13f55 | ||
|
5286ef7849 | ||
|
69fd473321 | ||
|
cd7ab6ba4e | ||
|
c25ce55fd3 | ||
|
08bd554cda | ||
|
fb27d80781 | ||
|
c15f3834e3 | ||
|
f7b0f922be | ||
|
ca7e62d421 | ||
|
eb92745b2e | ||
|
05754549e8 | ||
|
6afb26452b | ||
|
e26a7ffbd9 | ||
|
b7fac7a7d1 | ||
|
783e6217fc | ||
|
b4b3bd1c51 | ||
|
a9f2115486 | ||
|
60ebcbed54 | ||
|
454345da1e | ||
|
333bcc2072 | ||
|
b9eb56a404 | ||
|
75cb85c56a | ||
|
a924ea0c75 | ||
|
a63952510d | ||
|
4e44dcc312 | ||
|
d6f52dfb3e | ||
|
a53e795524 | ||
|
0fa9211d7f | ||
|
036a4b1855 | ||
|
56f533b3a0 | ||
|
64bc58a88e | ||
|
3a2db9207d | ||
|
a28f8ad9f1 | ||
|
7b9c29e440 | ||
|
b0d1854efc | ||
|
1da9876486 | ||
|
98d78856f6 | ||
|
ff828749ea | ||
|
d2a7972557 | ||
|
683c99908a | ||
|
c5650148a9 | ||
|
ebc152e4c9 | ||
|
f23afc549b | ||
|
ae6d32c635 | ||
|
88f6fbc897 | ||
|
06acd174f3 | ||
|
5045efa4aa | ||
|
01f3aa9c51 | ||
|
6ff0830d64 | ||
|
5acd472271 | ||
|
7182597e50 | ||
|
eccd798cc2 | ||
|
a6cb9d9222 | ||
|
8ee23dab04 | ||
|
707b706d18 | ||
|
b2db85d8e4 | ||
|
3f83579664 | ||
|
e9d3b1e694 | ||
|
fe550f0738 | ||
|
053778c493 | ||
|
7b63b3de93 | ||
|
2b570a49a9 | ||
|
f9a31ba044 | ||
|
4763a13b07 | ||
|
cae8db6b7e | ||
|
98452cd8ae | ||
|
573ca4a4a7 | ||
|
057bef8a84 | ||
|
22e61c9da4 | ||
|
120394ac92 | ||
|
4223de769e | ||
|
eb1952592e | ||
|
3b9f32e893 | ||
|
9540130c41 | ||
|
0cfc493775 | ||
|
af45f4a558 | ||
|
bf096c9ec3 | ||
|
1f6c220b45 | ||
|
b806e80e66 | ||
|
0a775e1eab | ||
|
f5b0f1351f | ||
|
41db8db0f2 | ||
|
79ace6def6 | ||
|
018a0c1741 | ||
|
8c92701a69 | ||
|
4fb8bddc58 | ||
|
bd5b76d6d0 | ||
|
94b8c0b810 | ||
|
d3d4776202 | ||
|
a1309c5255 | ||
|
07943656a7 | ||
|
cd197181f2 | ||
|
1f7dcf9d75 | ||
|
43126388cd | ||
|
50806e8dec | ||
|
83c7e1f1db | ||
|
4f9eaf77a5 | ||
|
5c9d77600b | ||
|
18acfa7301 | ||
|
a1ec789b0b | ||
|
3f52c016fa | ||
|
a77229c979 | ||
|
a3fd136509 | ||
|
828817b88f | ||
|
2b7a060178 | ||
|
cb986ef597 | ||
|
9905481552 | ||
|
ffe9f60358 | ||
|
d3b374ce59 | ||
|
7727720585 | ||
|
4336a1bc00 | ||
|
d77c34d1d2 | ||
|
b734e0bcc5 | ||
|
ad132bbe48 | ||
|
6a895c6681 | ||
|
55b9b703ea | ||
|
099faa1a2b | ||
|
4f25f5d86c | ||
|
20ad071190 | ||
|
769785c497 |
14
configure.ac
14
configure.ac
@@ -1153,6 +1153,10 @@ AC_ARG_ENABLE([driglx-direct],
|
||||
[driglx_direct="$enableval"],
|
||||
[driglx_direct="yes"])
|
||||
|
||||
# Check for libcaca
|
||||
PKG_CHECK_EXISTS([caca], [have_libcaca=yes], [have_libcaca=no])
|
||||
AM_CONDITIONAL([HAVE_LIBCACA], [test x$have_libcaca = xyes])
|
||||
|
||||
dnl
|
||||
dnl libGL configuration per driver
|
||||
dnl
|
||||
@@ -1529,6 +1533,8 @@ GBM_PC_LIB_PRIV="$DLOPEN_LIBS"
|
||||
AC_SUBST([GBM_PC_REQ_PRIV])
|
||||
AC_SUBST([GBM_PC_LIB_PRIV])
|
||||
|
||||
AM_CONDITIONAL(HAVE_VULKAN, true)
|
||||
|
||||
dnl
|
||||
dnl EGL configuration
|
||||
dnl
|
||||
@@ -2318,6 +2324,13 @@ AC_SUBST([XA_MINOR], $XA_MINOR)
|
||||
AC_SUBST([XA_TINY], $XA_TINY)
|
||||
AC_SUBST([XA_VERSION], "$XA_MAJOR.$XA_MINOR.$XA_TINY")
|
||||
|
||||
PKG_CHECK_MODULES(VALGRIND, [valgrind],
|
||||
[have_valgrind=yes], [have_valgrind=no])
|
||||
if test "x$have_valgrind" = "xyes"; then
|
||||
AC_DEFINE([HAVE_VALGRIND], 1,
|
||||
[Use valgrind intrinsics to suppress false warnings])
|
||||
fi
|
||||
|
||||
dnl Restore LDFLAGS and CPPFLAGS
|
||||
LDFLAGS="$_SAVE_LDFLAGS"
|
||||
CPPFLAGS="$_SAVE_CPPFLAGS"
|
||||
@@ -2425,6 +2438,7 @@ AC_CONFIG_FILES([Makefile
|
||||
src/mesa/drivers/osmesa/osmesa.pc
|
||||
src/mesa/drivers/x11/Makefile
|
||||
src/mesa/main/tests/Makefile
|
||||
src/vulkan/Makefile
|
||||
src/util/Makefile
|
||||
src/util/tests/hash_table/Makefile])
|
||||
|
||||
|
90
include/vulkan/vk_platform.h
Normal file
90
include/vulkan/vk_platform.h
Normal file
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// File: vk_platform.h
|
||||
//
|
||||
/*
|
||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __VK_PLATFORM_H__
|
||||
#define __VK_PLATFORM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
/*
|
||||
***************************************************************************************************
|
||||
* Platform-specific directives and type declarations
|
||||
***************************************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
// On Windows, VKAPI should equate to the __stdcall convention
|
||||
#define VKAPI __stdcall
|
||||
#elif defined(__GNUC__)
|
||||
// On other platforms using GCC, VKAPI stays undefined
|
||||
#define VKAPI
|
||||
#else
|
||||
// Unsupported Platform!
|
||||
#error "Unsupported OS Platform detected!"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if !defined(VK_NO_STDINT_H)
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#endif // !defined(VK_NO_STDINT_H)
|
||||
|
||||
typedef uint64_t VkDeviceSize;
|
||||
typedef uint32_t VkBool32;
|
||||
|
||||
typedef uint32_t VkSampleMask;
|
||||
typedef uint32_t VkFlags;
|
||||
|
||||
#if (UINTPTR_MAX >= UINT64_MAX)
|
||||
#define VK_UINTPTRLEAST64_MAX UINTPTR_MAX
|
||||
|
||||
typedef uintptr_t VkUintPtrLeast64;
|
||||
#else
|
||||
#define VK_UINTPTRLEAST64_MAX UINT64_MAX
|
||||
|
||||
typedef uint64_t VkUintPtrLeast64;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __VK_PLATFORM_H__
|
212
include/vulkan/vk_wsi_lunarg.h
Normal file
212
include/vulkan/vk_wsi_lunarg.h
Normal file
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// File: vk_wsi_display.h
|
||||
//
|
||||
/*
|
||||
** Copyright (c) 2014 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef __VK_WSI_LUNARG_H__
|
||||
#define __VK_WSI_LUNARG_H__
|
||||
|
||||
#include "vulkan.h"
|
||||
|
||||
#define VK_WSI_LUNARG_REVISION 3
|
||||
#define VK_WSI_LUNARG_EXTENSION_NUMBER 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
// This macro defines INT_MAX in enumerations to force compilers to use 32 bits
|
||||
// to represent them. This may or may not be necessary on some compilers. The
|
||||
// option to compile it out may allow compilers that warn about missing enumerants
|
||||
// in switch statements to be silenced.
|
||||
// Using this macro is not needed for flag bit enums because those aren't used
|
||||
// as storage type anywhere.
|
||||
#define VK_MAX_ENUM(Prefix) VK_##Prefix##_MAX_ENUM = 0x7FFFFFFF
|
||||
|
||||
// This macro defines the BEGIN_RANGE, END_RANGE, NUM, and MAX_ENUM constants for
|
||||
// the enumerations.
|
||||
#define VK_ENUM_RANGE(Prefix, First, Last) \
|
||||
VK_##Prefix##_BEGIN_RANGE = VK_##Prefix##_##First, \
|
||||
VK_##Prefix##_END_RANGE = VK_##Prefix##_##Last, \
|
||||
VK_NUM_##Prefix = (VK_##Prefix##_END_RANGE - VK_##Prefix##_BEGIN_RANGE + 1), \
|
||||
VK_MAX_ENUM(Prefix)
|
||||
|
||||
// This is a helper macro to define the value of flag bit enum values.
|
||||
#define VK_BIT(bit) (1 << (bit))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Objects
|
||||
|
||||
VK_DEFINE_HANDLE(VkDisplayWSI)
|
||||
VK_DEFINE_HANDLE(VkSwapChainWSI)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Enumeration constants
|
||||
|
||||
#define VK_WSI_LUNARG_ENUM(type,id) ((type)(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000 + (id)))
|
||||
|
||||
// Extend VkPhysicalDeviceInfoType enum with extension specific constants
|
||||
#define VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 0)
|
||||
#define VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 1)
|
||||
|
||||
// Extend VkStructureType enum with extension specific constants
|
||||
#define VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 0)
|
||||
#define VK_STRUCTURE_TYPE_PRESENT_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 1)
|
||||
|
||||
// Extend VkImageLayout enum with extension specific constants
|
||||
#define VK_IMAGE_LAYOUT_PRESENT_SOURCE_WSI VK_WSI_LUNARG_ENUM(VkImageLayout, 0)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Enumerations
|
||||
|
||||
typedef enum VkDisplayInfoTypeWSI_
|
||||
{
|
||||
// Info type for vkGetDisplayInfo()
|
||||
VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI = 0x00000003, // Return the VkFormat(s) supported for swap chains with the display
|
||||
|
||||
VK_ENUM_RANGE(DISPLAY_INFO_TYPE, FORMAT_PROPERTIES_WSI, FORMAT_PROPERTIES_WSI)
|
||||
} VkDisplayInfoTypeWSI;
|
||||
|
||||
typedef enum VkSwapChainInfoTypeWSI_
|
||||
{
|
||||
// Info type for vkGetSwapChainInfo()
|
||||
VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI = 0x00000000, // Return information about the persistent images of the swapchain
|
||||
|
||||
VK_ENUM_RANGE(SWAP_CHAIN_INFO_TYPE, PERSISTENT_IMAGES_WSI, PERSISTENT_IMAGES_WSI)
|
||||
} VkSwapChainInfoTypeWSI;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Flags
|
||||
|
||||
typedef VkFlags VkSwapModeFlagsWSI;
|
||||
typedef enum VkSwapModeFlagBitsWSI_
|
||||
{
|
||||
VK_SWAP_MODE_FLIP_BIT_WSI = VK_BIT(0),
|
||||
VK_SWAP_MODE_BLIT_BIT_WSI = VK_BIT(1),
|
||||
} VkSwapModeFlagBitsWSI;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Structures
|
||||
|
||||
typedef struct VkDisplayPropertiesWSI_
|
||||
{
|
||||
VkDisplayWSI display; // Handle of the display object
|
||||
VkExtent2D physicalResolution; // Max resolution for CRT?
|
||||
} VkDisplayPropertiesWSI;
|
||||
|
||||
typedef struct VkDisplayFormatPropertiesWSI_
|
||||
{
|
||||
VkFormat swapChainFormat; // Format of the images of the swap chain
|
||||
} VkDisplayFormatPropertiesWSI;
|
||||
|
||||
typedef struct VkSwapChainCreateInfoWSI_
|
||||
{
|
||||
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI
|
||||
const void* pNext; // Pointer to next structure
|
||||
|
||||
// TBD: It is not yet clear what the use will be for the following two
|
||||
// values. It seems to be needed for more-global window-system handles
|
||||
// (e.g. X11 display). If not needed for the SDK, we will drop it from
|
||||
// this extension, and from a future version of this header.
|
||||
const void* pNativeWindowSystemHandle; // Pointer to native window system handle
|
||||
const void* pNativeWindowHandle; // Pointer to native window handle
|
||||
|
||||
uint32_t displayCount; // Number of displays the swap chain is created for
|
||||
const VkDisplayWSI* pDisplays; // displayCount number of display objects the swap chain is created for
|
||||
|
||||
uint32_t imageCount; // Number of images in the swap chain
|
||||
|
||||
VkFormat imageFormat; // Format of the images of the swap chain
|
||||
VkExtent2D imageExtent; // Width and height of the images of the swap chain
|
||||
uint32_t imageArraySize; // Number of layers of the images of the swap chain (needed for multi-view rendering)
|
||||
VkFlags imageUsageFlags; // Usage flags for the images of the swap chain (see VkImageUsageFlags)
|
||||
|
||||
VkFlags swapModeFlags; // Allowed swap modes (see VkSwapModeFlagsWSI)
|
||||
} VkSwapChainCreateInfoWSI;
|
||||
|
||||
typedef struct VkSwapChainImageInfoWSI_
|
||||
{
|
||||
VkImage image; // Persistent swap chain image handle
|
||||
VkDeviceMemory memory; // Persistent swap chain image's memory handle
|
||||
} VkSwapChainImageInfoWSI;
|
||||
|
||||
typedef struct VkPhysicalDeviceQueuePresentPropertiesWSI_
|
||||
{
|
||||
VkBool32 supportsPresent; // Tells whether the queue supports presenting
|
||||
} VkPhysicalDeviceQueuePresentPropertiesWSI;
|
||||
|
||||
typedef struct VkPresentInfoWSI_
|
||||
{
|
||||
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_PRESENT_INFO_WSI
|
||||
const void* pNext; // Pointer to next structure
|
||||
VkImage image; // Image to present
|
||||
uint32_t flipInterval; // Flip interval
|
||||
} VkPresentInfoWSI;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Function types
|
||||
|
||||
typedef VkResult (VKAPI *PFN_vkGetDisplayInfoWSI)(VkDisplayWSI display, VkDisplayInfoTypeWSI infoType, size_t* pDataSize, void* pData);
|
||||
typedef VkResult (VKAPI *PFN_vkCreateSwapChainWSI)(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain);
|
||||
typedef VkResult (VKAPI *PFN_vkDestroySwapChainWSI)(VkSwapChainWSI swapChain);
|
||||
typedef VkResult (VKAPI *PFN_vkGetSwapChainInfoWSI)(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData);
|
||||
typedef VkResult (VKAPI *PFN_vkQueuePresentWSI)(VkQueue queue, const VkPresentInfoWSI* pPresentInfo);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Function prototypes
|
||||
|
||||
#ifdef VK_PROTOTYPES
|
||||
|
||||
VkResult VKAPI vkGetDisplayInfoWSI(
|
||||
VkDisplayWSI display,
|
||||
VkDisplayInfoTypeWSI infoType,
|
||||
size_t* pDataSize,
|
||||
void* pData);
|
||||
|
||||
VkResult VKAPI vkCreateSwapChainWSI(
|
||||
VkDevice device,
|
||||
const VkSwapChainCreateInfoWSI* pCreateInfo,
|
||||
VkSwapChainWSI* pSwapChain);
|
||||
|
||||
VkResult VKAPI vkDestroySwapChainWSI(
|
||||
VkSwapChainWSI swapChain);
|
||||
|
||||
VkResult VKAPI vkGetSwapChainInfoWSI(
|
||||
VkSwapChainWSI swapChain,
|
||||
VkSwapChainInfoTypeWSI infoType,
|
||||
size_t* pDataSize,
|
||||
void* pData);
|
||||
|
||||
VkResult VKAPI vkQueuePresentWSI(
|
||||
VkQueue queue,
|
||||
const VkPresentInfoWSI* pPresentInfo);
|
||||
|
||||
#endif // VK_PROTOTYPES
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __VK_WSI_LUNARG_H__
|
3047
include/vulkan/vulkan.h
Normal file
3047
include/vulkan/vulkan.h
Normal file
File diff suppressed because it is too large
Load Diff
61
include/vulkan/vulkan_intel.h
Normal file
61
include/vulkan/vulkan_intel.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __VULKAN_INTEL_H__
|
||||
#define __VULKAN_INTEL_H__
|
||||
|
||||
#include "vulkan.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL 1024
|
||||
typedef struct VkDmaBufImageCreateInfo_
|
||||
{
|
||||
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL
|
||||
const void* pNext; // Pointer to next structure.
|
||||
int fd;
|
||||
VkFormat format;
|
||||
VkExtent3D extent; // Depth must be 1
|
||||
uint32_t strideInBytes;
|
||||
} VkDmaBufImageCreateInfo;
|
||||
|
||||
typedef VkResult (VKAPI *PFN_vkCreateDmaBufImageINTEL)(VkDevice device, const VkDmaBufImageCreateInfo* pCreateInfo, VkDeviceMemory* pMem, VkImage* pImage);
|
||||
|
||||
#ifdef VK_PROTOTYPES
|
||||
|
||||
VkResult VKAPI vkCreateDmaBufImageINTEL(
|
||||
VkDevice _device,
|
||||
const VkDmaBufImageCreateInfo* pCreateInfo,
|
||||
VkDeviceMemory* pMem,
|
||||
VkImage* pImage);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __VULKAN_INTEL_H__
|
@@ -61,6 +61,10 @@ EXTRA_DIST = \
|
||||
AM_CFLAGS = $(VISIBILITY_CFLAGS)
|
||||
AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS)
|
||||
|
||||
if HAVE_VULKAN
|
||||
SUBDIRS += vulkan
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include/ \
|
||||
-I$(top_srcdir)/src/mapi/ \
|
||||
|
1
src/glsl/.gitignore
vendored
1
src/glsl/.gitignore
vendored
@@ -4,6 +4,7 @@ glsl_parser.cpp
|
||||
glsl_parser.h
|
||||
glsl_parser.output
|
||||
glsl_test
|
||||
spirv2nir
|
||||
subtest-cr/
|
||||
subtest-lf/
|
||||
subtest-cr-lf/
|
||||
|
@@ -77,7 +77,7 @@ check_PROGRAMS = \
|
||||
tests/sampler-types-test \
|
||||
tests/uniform-initializer-test
|
||||
|
||||
noinst_PROGRAMS = glsl_compiler
|
||||
noinst_PROGRAMS = glsl_compiler spirv2nir
|
||||
|
||||
tests_blob_test_SOURCES = \
|
||||
tests/blob_test.c
|
||||
@@ -158,6 +158,16 @@ glsl_compiler_LDADD = \
|
||||
$(top_builddir)/src/libglsl_util.la \
|
||||
$(PTHREAD_LIBS)
|
||||
|
||||
spirv2nir_SOURCES = \
|
||||
standalone_scaffolding.cpp \
|
||||
standalone_scaffolding.h \
|
||||
nir/spirv2nir.c
|
||||
|
||||
spirv2nir_LDADD = \
|
||||
libglsl.la \
|
||||
$(top_builddir)/src/libglsl_util.la \
|
||||
$(PTHREAD_LIBS)
|
||||
|
||||
glsl_test_SOURCES = \
|
||||
standalone_scaffolding.cpp \
|
||||
test.cpp \
|
||||
|
@@ -59,6 +59,7 @@ NIR_FILES = \
|
||||
nir/nir_remove_dead_variables.c \
|
||||
nir/nir_search.c \
|
||||
nir/nir_search.h \
|
||||
nir/nir_spirv.h \
|
||||
nir/nir_split_var_copies.c \
|
||||
nir/nir_sweep.c \
|
||||
nir/nir_to_ssa.c \
|
||||
@@ -68,6 +69,8 @@ NIR_FILES = \
|
||||
nir/nir_worklist.c \
|
||||
nir/nir_worklist.h \
|
||||
nir/nir_types.cpp \
|
||||
nir/spirv_to_nir.c \
|
||||
nir/spirv_glsl450_to_nir.c \
|
||||
$(NIR_GENERATED_FILES)
|
||||
|
||||
# libglsl
|
||||
|
@@ -514,6 +514,10 @@ struct ast_type_qualifier {
|
||||
unsigned stream:1; /**< Has stream value assigned */
|
||||
unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */
|
||||
/** \} */
|
||||
|
||||
/** \name Vulkan qualifiers */
|
||||
unsigned vk_set:1;
|
||||
|
||||
}
|
||||
/** \brief Set of flags, accessed by name. */
|
||||
q;
|
||||
@@ -595,6 +599,11 @@ struct ast_type_qualifier {
|
||||
*/
|
||||
glsl_base_type image_base_type;
|
||||
|
||||
/**
|
||||
* Vulkan descriptor set
|
||||
*/
|
||||
int set;
|
||||
|
||||
/**
|
||||
* Return true if and only if an interpolation qualifier is present.
|
||||
*/
|
||||
|
@@ -970,6 +970,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
|
||||
case GLSL_TYPE_SAMPLER:
|
||||
case GLSL_TYPE_IMAGE:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
case GLSL_TYPE_ATOMIC_UINT:
|
||||
/* I assume a comparison of a struct containing a sampler just
|
||||
* ignores the sampler present in the type.
|
||||
@@ -2644,7 +2645,16 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
||||
state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
|
||||
}
|
||||
|
||||
if (qual->flags.q.explicit_location) {
|
||||
if (qual->flags.q.vk_set) {
|
||||
if (!qual->flags.q.explicit_binding)
|
||||
_mesa_glsl_error(loc, state,
|
||||
"Vulkan descriptor set layout requires both set "
|
||||
"and binding qualifiers");
|
||||
|
||||
var->data.vk_set = true;
|
||||
var->data.set = qual->set;
|
||||
var->data.binding = qual->binding;
|
||||
} else if (qual->flags.q.explicit_location) {
|
||||
validate_explicit_location(qual, var, state, loc);
|
||||
} else if (qual->flags.q.explicit_index) {
|
||||
_mesa_glsl_error(loc, state, "explicit index requires explicit location");
|
||||
@@ -5886,6 +5896,10 @@ ast_interface_block::hir(exec_list *instructions,
|
||||
var->data.explicit_binding = this->layout.flags.q.explicit_binding;
|
||||
var->data.binding = this->layout.binding;
|
||||
|
||||
var->data.vk_set = this->layout.flags.q.vk_set;
|
||||
var->data.set = this->layout.set;
|
||||
var->data.binding = this->layout.binding;
|
||||
|
||||
state->symbols->add_variable(var);
|
||||
instructions->push_tail(var);
|
||||
}
|
||||
@@ -5958,6 +5972,10 @@ ast_interface_block::hir(exec_list *instructions,
|
||||
var->data.explicit_binding = this->layout.flags.q.explicit_binding;
|
||||
var->data.binding = this->layout.binding;
|
||||
|
||||
var->data.vk_set = this->layout.flags.q.vk_set;
|
||||
var->data.set = this->layout.set;
|
||||
var->data.binding = this->layout.binding;
|
||||
|
||||
state->symbols->add_variable(var);
|
||||
instructions->push_tail(var);
|
||||
}
|
||||
|
@@ -252,6 +252,11 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
||||
this->image_base_type = q.image_base_type;
|
||||
}
|
||||
|
||||
if (q.flags.q.vk_set) {
|
||||
this->set = q.set;
|
||||
this->binding = q.binding;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -1424,13 +1424,16 @@ layout_qualifier_id:
|
||||
}
|
||||
}
|
||||
|
||||
if ((state->ARB_shading_language_420pack_enable ||
|
||||
state->has_atomic_counters()) &&
|
||||
match_layout_qualifier("binding", $1, state) == 0) {
|
||||
if (match_layout_qualifier("binding", $1, state) == 0) {
|
||||
$$.flags.q.explicit_binding = 1;
|
||||
$$.binding = $3;
|
||||
}
|
||||
|
||||
if (match_layout_qualifier("set", $1, state) == 0) {
|
||||
$$.flags.q.vk_set = 1;
|
||||
$$.set = $3;
|
||||
}
|
||||
|
||||
if (state->has_atomic_counters() &&
|
||||
match_layout_qualifier("offset", $1, state) == 0) {
|
||||
$$.flags.q.explicit_offset = 1;
|
||||
|
@@ -87,6 +87,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
|
||||
|
||||
this->extensions = &ctx->Extensions;
|
||||
|
||||
this->ARB_compute_shader_enable = true;
|
||||
|
||||
this->Const.MaxLights = ctx->Const.MaxLights;
|
||||
this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
|
||||
this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
|
||||
|
@@ -32,6 +32,7 @@ mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
|
||||
hash_table *glsl_type::array_types = NULL;
|
||||
hash_table *glsl_type::record_types = NULL;
|
||||
hash_table *glsl_type::interface_types = NULL;
|
||||
hash_table *glsl_type::function_types = NULL;
|
||||
void *glsl_type::mem_ctx = NULL;
|
||||
|
||||
void
|
||||
@@ -159,6 +160,39 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
|
||||
mtx_unlock(&glsl_type::mutex);
|
||||
}
|
||||
|
||||
glsl_type::glsl_type(const glsl_type *return_type,
|
||||
const glsl_function_param *params, unsigned num_params) :
|
||||
gl_type(0),
|
||||
base_type(GLSL_TYPE_FUNCTION),
|
||||
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
|
||||
sampler_type(0), interface_packing(0),
|
||||
vector_elements(0), matrix_columns(0),
|
||||
length(num_params)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
mtx_lock(&glsl_type::mutex);
|
||||
|
||||
init_ralloc_type_ctx();
|
||||
|
||||
this->fields.parameters = rzalloc_array(this->mem_ctx,
|
||||
glsl_function_param, num_params + 1);
|
||||
|
||||
/* We store the return type as the first parameter */
|
||||
this->fields.parameters[0].type = return_type;
|
||||
this->fields.parameters[0].in = false;
|
||||
this->fields.parameters[0].out = true;
|
||||
|
||||
/* We store the i'th parameter in slot i+1 */
|
||||
for (i = 0; i < length; i++) {
|
||||
this->fields.parameters[i + 1].type = params[i].type;
|
||||
this->fields.parameters[i + 1].in = params[i].in;
|
||||
this->fields.parameters[i + 1].out = params[i].out;
|
||||
}
|
||||
|
||||
mtx_unlock(&glsl_type::mutex);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
glsl_type::contains_sampler() const
|
||||
@@ -827,6 +861,72 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
function_key_compare(const void *a, const void *b)
|
||||
{
|
||||
const glsl_type *const key1 = (glsl_type *) a;
|
||||
const glsl_type *const key2 = (glsl_type *) b;
|
||||
|
||||
if (key1->length != key2->length)
|
||||
return 1;
|
||||
|
||||
return memcmp(key1->fields.parameters, key2->fields.parameters,
|
||||
(key1->length + 1) * sizeof(*key1->fields.parameters));
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
function_key_hash(const void *a)
|
||||
{
|
||||
const glsl_type *const key = (glsl_type *) a;
|
||||
char hash_key[128];
|
||||
unsigned size = 0;
|
||||
|
||||
size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
|
||||
|
||||
for (unsigned i = 0; i < key->length; i++) {
|
||||
if (size >= sizeof(hash_key))
|
||||
break;
|
||||
|
||||
size += snprintf(& hash_key[size], sizeof(hash_key) - size,
|
||||
"%p", (void *) key->fields.structure[i].type);
|
||||
}
|
||||
|
||||
return hash_table_string_hash(& hash_key);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_type::get_function_instance(const glsl_type *return_type,
|
||||
const glsl_function_param *params,
|
||||
unsigned num_params)
|
||||
{
|
||||
const glsl_type key(return_type, params, num_params);
|
||||
|
||||
mtx_lock(&glsl_type::mutex);
|
||||
|
||||
if (function_types == NULL) {
|
||||
function_types = hash_table_ctor(64, function_key_hash,
|
||||
function_key_compare);
|
||||
}
|
||||
|
||||
const glsl_type *t = (glsl_type *) hash_table_find(function_types, &key);
|
||||
if (t == NULL) {
|
||||
mtx_unlock(&glsl_type::mutex);
|
||||
t = new glsl_type(return_type, params, num_params);
|
||||
mtx_lock(&glsl_type::mutex);
|
||||
|
||||
hash_table_insert(function_types, (void *) t, t);
|
||||
}
|
||||
|
||||
assert(t->base_type == GLSL_TYPE_FUNCTION);
|
||||
assert(t->length == num_params);
|
||||
|
||||
mtx_unlock(&glsl_type::mutex);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
const glsl_type *
|
||||
glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
|
||||
{
|
||||
@@ -955,6 +1055,7 @@ glsl_type::component_slots() const
|
||||
case GLSL_TYPE_IMAGE:
|
||||
return 1;
|
||||
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
case GLSL_TYPE_SAMPLER:
|
||||
case GLSL_TYPE_ATOMIC_UINT:
|
||||
case GLSL_TYPE_VOID:
|
||||
@@ -1326,6 +1427,7 @@ glsl_type::count_attribute_slots() const
|
||||
case GLSL_TYPE_ARRAY:
|
||||
return this->length * this->fields.array->count_attribute_slots();
|
||||
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
case GLSL_TYPE_SAMPLER:
|
||||
case GLSL_TYPE_IMAGE:
|
||||
case GLSL_TYPE_ATOMIC_UINT:
|
||||
|
@@ -56,6 +56,7 @@ enum glsl_base_type {
|
||||
GLSL_TYPE_IMAGE,
|
||||
GLSL_TYPE_ATOMIC_UINT,
|
||||
GLSL_TYPE_STRUCT,
|
||||
GLSL_TYPE_FUNCTION,
|
||||
GLSL_TYPE_INTERFACE,
|
||||
GLSL_TYPE_ARRAY,
|
||||
GLSL_TYPE_VOID,
|
||||
@@ -178,7 +179,7 @@ struct glsl_type {
|
||||
*/
|
||||
union {
|
||||
const struct glsl_type *array; /**< Type of array elements. */
|
||||
const struct glsl_type *parameters; /**< Parameters to function. */
|
||||
struct glsl_function_param *parameters; /**< Parameters to function. */
|
||||
struct glsl_struct_field *structure; /**< List of struct fields. */
|
||||
} fields;
|
||||
|
||||
@@ -263,6 +264,13 @@ struct glsl_type {
|
||||
enum glsl_interface_packing packing,
|
||||
const char *block_name);
|
||||
|
||||
/**
|
||||
* Get the instance of a function type
|
||||
*/
|
||||
static const glsl_type *get_function_instance(const struct glsl_type *return_type,
|
||||
const glsl_function_param *parameters,
|
||||
unsigned num_params);
|
||||
|
||||
/**
|
||||
* Get the type resulting from a multiplication of \p type_a * \p type_b
|
||||
*/
|
||||
@@ -676,6 +684,10 @@ private:
|
||||
glsl_type(const glsl_struct_field *fields, unsigned num_fields,
|
||||
enum glsl_interface_packing packing, const char *name);
|
||||
|
||||
/** Constructor for interface types */
|
||||
glsl_type(const glsl_type *return_type,
|
||||
const glsl_function_param *params, unsigned num_params);
|
||||
|
||||
/** Constructor for array types */
|
||||
glsl_type(const glsl_type *array, unsigned length);
|
||||
|
||||
@@ -688,6 +700,9 @@ private:
|
||||
/** Hash table containing the known interface types. */
|
||||
static struct hash_table *interface_types;
|
||||
|
||||
/** Hash table containing the known function types. */
|
||||
static struct hash_table *function_types;
|
||||
|
||||
static int record_key_compare(const void *a, const void *b);
|
||||
static unsigned record_key_hash(const void *key);
|
||||
|
||||
@@ -715,6 +730,10 @@ private:
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
#undef DECL_TYPE
|
||||
#undef STRUCT_TYPE
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct glsl_struct_field {
|
||||
const struct glsl_type *type;
|
||||
const char *name;
|
||||
@@ -758,14 +777,17 @@ struct glsl_struct_field {
|
||||
int stream;
|
||||
};
|
||||
|
||||
struct glsl_function_param {
|
||||
const struct glsl_type *type;
|
||||
|
||||
bool in;
|
||||
bool out;
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
glsl_align(unsigned int a, unsigned int align)
|
||||
{
|
||||
return (a + align - 1) / align * align;
|
||||
}
|
||||
|
||||
#undef DECL_TYPE
|
||||
#undef STRUCT_TYPE
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* GLSL_TYPES_H */
|
||||
|
@@ -683,6 +683,11 @@ public:
|
||||
unsigned explicit_location:1;
|
||||
unsigned explicit_index:1;
|
||||
|
||||
/**
|
||||
* Do we have a Vulkan (group, index) qualifier for this variable?
|
||||
*/
|
||||
unsigned vk_set:1;
|
||||
|
||||
/**
|
||||
* Was an initial binding explicitly set in the shader?
|
||||
*
|
||||
@@ -752,8 +757,10 @@ public:
|
||||
* \note
|
||||
* The GLSL spec only allows the values 0 or 1 for the index in \b dual
|
||||
* source blending.
|
||||
*
|
||||
* This is now also used for the Vulkan descriptor set index.
|
||||
*/
|
||||
unsigned index:1;
|
||||
int16_t index;
|
||||
|
||||
/**
|
||||
* \brief Layout qualifier for gl_FragDepth.
|
||||
@@ -801,6 +808,11 @@ public:
|
||||
*/
|
||||
int16_t binding;
|
||||
|
||||
/**
|
||||
* Vulkan descriptor set for the resource.
|
||||
*/
|
||||
int16_t set;
|
||||
|
||||
/**
|
||||
* Storage location of the base of this variable
|
||||
*
|
||||
|
@@ -357,6 +357,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
return c;
|
||||
}
|
||||
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
case GLSL_TYPE_SAMPLER:
|
||||
case GLSL_TYPE_IMAGE:
|
||||
case GLSL_TYPE_ATOMIC_UINT:
|
||||
|
@@ -53,6 +53,11 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
|
||||
b->binding = 0;
|
||||
}
|
||||
|
||||
if (var->data.vk_set) {
|
||||
b->set = var->data.set;
|
||||
b->index = var->data.index;
|
||||
}
|
||||
|
||||
_mesa_hash_table_insert(ht, var->get_interface_type()->name, (void *) b);
|
||||
return b;
|
||||
} else {
|
||||
|
@@ -35,6 +35,8 @@ struct link_uniform_block_active {
|
||||
unsigned num_array_elements;
|
||||
|
||||
unsigned binding;
|
||||
unsigned set;
|
||||
unsigned index;
|
||||
|
||||
bool has_instance_name;
|
||||
bool has_binding;
|
||||
|
@@ -293,6 +293,9 @@ link_uniform_blocks(void *mem_ctx,
|
||||
blocks[i].NumUniforms =
|
||||
(unsigned)(ptrdiff_t)(&variables[parcel.index] - blocks[i].Uniforms);
|
||||
|
||||
blocks[i].Set = b->set;
|
||||
blocks[i].Binding = b->binding;
|
||||
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
@@ -311,6 +314,9 @@ link_uniform_blocks(void *mem_ctx,
|
||||
blocks[i].NumUniforms =
|
||||
(unsigned)(ptrdiff_t)(&variables[parcel.index] - blocks[i].Uniforms);
|
||||
|
||||
blocks[i].Set = b->set;
|
||||
blocks[i].Binding = b->binding;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@@ -88,6 +88,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
|
||||
case GLSL_TYPE_IMAGE:
|
||||
case GLSL_TYPE_ATOMIC_UINT:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
case GLSL_TYPE_VOID:
|
||||
case GLSL_TYPE_ERROR:
|
||||
/* All other types should have already been filtered by other
|
||||
|
@@ -322,6 +322,7 @@ nir_visitor::visit(ir_variable *ir)
|
||||
}
|
||||
|
||||
var->data.index = ir->data.index;
|
||||
var->data.descriptor_set = ir->data.set;
|
||||
var->data.binding = ir->data.binding;
|
||||
/* XXX Get rid of buffer_index */
|
||||
var->data.atomic.buffer_index = ir->data.binding;
|
||||
|
@@ -300,6 +300,7 @@ typedef struct {
|
||||
*
|
||||
* For array types, this represents the binding point for the first element.
|
||||
*/
|
||||
int descriptor_set;
|
||||
int binding;
|
||||
|
||||
/**
|
||||
@@ -510,7 +511,11 @@ typedef struct nir_src {
|
||||
bool is_ssa;
|
||||
} nir_src;
|
||||
|
||||
#define NIR_SRC_INIT (nir_src) { { NULL } }
|
||||
#ifdef __cplusplus
|
||||
# define NIR_SRC_INIT nir_src()
|
||||
#else
|
||||
# define NIR_SRC_INIT (nir_src) { { NULL } }
|
||||
#endif
|
||||
|
||||
#define nir_foreach_use(reg_or_ssa_def, src) \
|
||||
list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
|
||||
@@ -533,7 +538,11 @@ typedef struct {
|
||||
bool is_ssa;
|
||||
} nir_dest;
|
||||
|
||||
#define NIR_DEST_INIT (nir_dest) { { { NULL } } }
|
||||
#ifdef __cplusplus
|
||||
# define NIR_DEST_INIT nir_dest()
|
||||
#else
|
||||
# define NIR_DEST_INIT (nir_dest) { { { NULL } } }
|
||||
#endif
|
||||
|
||||
#define nir_foreach_def(reg, dest) \
|
||||
list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)
|
||||
@@ -782,6 +791,15 @@ NIR_DEFINE_CAST(nir_deref_as_var, nir_deref, nir_deref_var, deref)
|
||||
NIR_DEFINE_CAST(nir_deref_as_array, nir_deref, nir_deref_array, deref)
|
||||
NIR_DEFINE_CAST(nir_deref_as_struct, nir_deref, nir_deref_struct, deref)
|
||||
|
||||
/** Returns the tail of a deref chain */
|
||||
static inline nir_deref *
|
||||
nir_deref_tail(nir_deref *deref)
|
||||
{
|
||||
while (deref->child)
|
||||
deref = deref->child;
|
||||
return deref;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
nir_instr instr;
|
||||
|
||||
@@ -976,6 +994,9 @@ typedef struct {
|
||||
/* gather component selector */
|
||||
unsigned component : 2;
|
||||
|
||||
/* The descriptor set containing this texture */
|
||||
unsigned sampler_set;
|
||||
|
||||
/** The sampler index
|
||||
*
|
||||
* If this texture instruction has a nir_tex_src_sampler_offset source,
|
||||
@@ -1661,6 +1682,7 @@ void nir_lower_phis_to_scalar(nir_shader *shader);
|
||||
void nir_lower_samplers(nir_shader *shader,
|
||||
const struct gl_shader_program *shader_program,
|
||||
gl_shader_stage stage);
|
||||
void nir_lower_samplers_for_vk(nir_shader *shader);
|
||||
|
||||
void nir_lower_system_values(nir_shader *shader);
|
||||
void nir_lower_tex_projector(nir_shader *shader);
|
||||
|
@@ -28,6 +28,10 @@ struct exec_list;
|
||||
|
||||
typedef struct nir_builder {
|
||||
struct exec_list *cf_node_list;
|
||||
|
||||
nir_block *before_block;
|
||||
nir_block *after_block;
|
||||
|
||||
nir_instr *before_instr;
|
||||
nir_instr *after_instr;
|
||||
|
||||
@@ -48,6 +52,30 @@ nir_builder_insert_after_cf_list(nir_builder *build,
|
||||
struct exec_list *cf_node_list)
|
||||
{
|
||||
build->cf_node_list = cf_node_list;
|
||||
build->before_block = NULL;
|
||||
build->after_block = NULL;
|
||||
build->before_instr = NULL;
|
||||
build->after_instr = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nir_builder_insert_before_block(nir_builder *build,
|
||||
nir_block *block)
|
||||
{
|
||||
build->cf_node_list = NULL;
|
||||
build->before_block = block;
|
||||
build->after_block = NULL;
|
||||
build->before_instr = NULL;
|
||||
build->after_instr = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nir_builder_insert_after_block(nir_builder *build,
|
||||
nir_block *block)
|
||||
{
|
||||
build->cf_node_list = NULL;
|
||||
build->before_block = NULL;
|
||||
build->after_block = block;
|
||||
build->before_instr = NULL;
|
||||
build->after_instr = NULL;
|
||||
}
|
||||
@@ -56,6 +84,8 @@ static inline void
|
||||
nir_builder_insert_before_instr(nir_builder *build, nir_instr *before_instr)
|
||||
{
|
||||
build->cf_node_list = NULL;
|
||||
build->before_block = NULL;
|
||||
build->after_block = NULL;
|
||||
build->before_instr = before_instr;
|
||||
build->after_instr = NULL;
|
||||
}
|
||||
@@ -64,6 +94,8 @@ static inline void
|
||||
nir_builder_insert_after_instr(nir_builder *build, nir_instr *after_instr)
|
||||
{
|
||||
build->cf_node_list = NULL;
|
||||
build->before_block = NULL;
|
||||
build->after_block = NULL;
|
||||
build->before_instr = NULL;
|
||||
build->after_instr = after_instr;
|
||||
}
|
||||
@@ -73,6 +105,10 @@ nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
|
||||
{
|
||||
if (build->cf_node_list) {
|
||||
nir_instr_insert_after_cf_list(build->cf_node_list, instr);
|
||||
} else if (build->before_block) {
|
||||
nir_instr_insert_before_block(build->before_block, instr);
|
||||
} else if (build->after_block) {
|
||||
nir_instr_insert_after_block(build->after_block, instr);
|
||||
} else if (build->before_instr) {
|
||||
nir_instr_insert_before(build->before_instr, instr);
|
||||
} else {
|
||||
@@ -240,6 +276,23 @@ nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
|
||||
nir_imov_alu(build, alu_src, num_components);
|
||||
}
|
||||
|
||||
/* Selects the right fdot given the number of components in each source. */
|
||||
static inline nir_ssa_def *
|
||||
nir_fdot(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1)
|
||||
{
|
||||
assert(src0->num_components == src1->num_components);
|
||||
switch (src0->num_components) {
|
||||
case 1: return nir_fmul(build, src0, src1);
|
||||
case 2: return nir_fdot2(build, src0, src1);
|
||||
case 3: return nir_fdot3(build, src0, src1);
|
||||
case 4: return nir_fdot4(build, src0, src1);
|
||||
default:
|
||||
unreachable("bad component size");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a nir_src into a nir_ssa_def * so it can be passed to
|
||||
* nir_build_alu()-based builder calls.
|
||||
|
@@ -67,6 +67,7 @@ type_size(const struct glsl_type *type)
|
||||
return 0;
|
||||
case GLSL_TYPE_IMAGE:
|
||||
return 0;
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
case GLSL_TYPE_VOID:
|
||||
case GLSL_TYPE_ERROR:
|
||||
case GLSL_TYPE_DOUBLE:
|
||||
|
@@ -35,6 +35,30 @@ extern "C" {
|
||||
#include "program/program.h"
|
||||
}
|
||||
|
||||
static void
|
||||
add_indirect_to_tex(nir_tex_instr *instr, nir_src indirect)
|
||||
{
|
||||
/* First, we have to resize the array of texture sources */
|
||||
nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
|
||||
instr->num_srcs + 1);
|
||||
|
||||
for (unsigned i = 0; i < instr->num_srcs; i++) {
|
||||
new_srcs[i].src_type = instr->src[i].src_type;
|
||||
nir_instr_move_src(&instr->instr, &new_srcs[i].src, &instr->src[i].src);
|
||||
}
|
||||
|
||||
ralloc_free(instr->src);
|
||||
instr->src = new_srcs;
|
||||
|
||||
/* Now we can go ahead and move the source over to being a
|
||||
* first-class texture source.
|
||||
*/
|
||||
instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
|
||||
instr->num_srcs++;
|
||||
nir_instr_rewrite_src(&instr->instr, &instr->src[instr->num_srcs - 1].src,
|
||||
indirect);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
get_sampler_index(const struct gl_shader_program *shader_program,
|
||||
gl_shader_stage stage, const char *name)
|
||||
@@ -176,3 +200,49 @@ nir_lower_samplers(nir_shader *shader, const struct gl_shader_program *shader_pr
|
||||
lower_impl(overload->impl, shader_program, stage);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
lower_samplers_for_vk_block(nir_block *block, void *data)
|
||||
{
|
||||
nir_foreach_instr(block, instr) {
|
||||
if (instr->type != nir_instr_type_tex)
|
||||
continue;
|
||||
|
||||
nir_tex_instr *tex = nir_instr_as_tex(instr);
|
||||
|
||||
assert(tex->sampler);
|
||||
|
||||
tex->sampler_set = tex->sampler->var->data.descriptor_set;
|
||||
tex->sampler_index = tex->sampler->var->data.binding;
|
||||
|
||||
if (tex->sampler->deref.child) {
|
||||
assert(tex->sampler->deref.child->deref_type == nir_deref_type_array);
|
||||
nir_deref_array *arr = nir_deref_as_array(tex->sampler->deref.child);
|
||||
|
||||
/* Only one-level arrays are allowed in vulkan */
|
||||
assert(arr->deref.child == NULL);
|
||||
|
||||
tex->sampler_index += arr->base_offset;
|
||||
if (arr->deref_array_type == nir_deref_array_type_indirect) {
|
||||
add_indirect_to_tex(tex, arr->indirect);
|
||||
nir_instr_rewrite_src(instr, &arr->indirect, NIR_SRC_INIT);
|
||||
|
||||
tex->sampler_array_size = glsl_get_length(tex->sampler->deref.type);
|
||||
}
|
||||
}
|
||||
|
||||
tex->sampler = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
nir_lower_samplers_for_vk(nir_shader *shader)
|
||||
{
|
||||
nir_foreach_overload(shader, overload) {
|
||||
if (overload->impl) {
|
||||
nir_foreach_block(overload->impl, lower_samplers_for_vk_block, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,17 +53,6 @@ deref_next_wildcard_parent(nir_deref *deref)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the last deref in the chain.
|
||||
*/
|
||||
static nir_deref *
|
||||
get_deref_tail(nir_deref *deref)
|
||||
{
|
||||
while (deref->child)
|
||||
deref = deref->child;
|
||||
|
||||
return deref;
|
||||
}
|
||||
|
||||
/* This function recursively walks the given deref chain and replaces the
|
||||
* given copy instruction with an equivalent sequence load/store
|
||||
* operations.
|
||||
@@ -121,8 +110,8 @@ emit_copy_load_store(nir_intrinsic_instr *copy_instr,
|
||||
} else {
|
||||
/* In this case, we have no wildcards anymore, so all we have to do
|
||||
* is just emit the load and store operations. */
|
||||
src_tail = get_deref_tail(src_tail);
|
||||
dest_tail = get_deref_tail(dest_tail);
|
||||
src_tail = nir_deref_tail(src_tail);
|
||||
dest_tail = nir_deref_tail(dest_tail);
|
||||
|
||||
assert(src_tail->type == dest_tail->type);
|
||||
|
||||
|
46
src/glsl/nir/nir_spirv.h
Normal file
46
src/glsl/nir/nir_spirv.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Jason Ekstrand (jason@jlekstrand.net)
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _NIR_SPIRV_H_
|
||||
#define _NIR_SPIRV_H_
|
||||
|
||||
#include "nir.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
nir_shader *spirv_to_nir(const uint32_t *words, size_t word_count,
|
||||
const nir_shader_compiler_options *options);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NIR_SPIRV_H_ */
|
@@ -66,14 +66,6 @@ struct split_var_copies_state {
|
||||
void *dead_ctx;
|
||||
};
|
||||
|
||||
static nir_deref *
|
||||
get_deref_tail(nir_deref *deref)
|
||||
{
|
||||
while (deref->child != NULL)
|
||||
deref = deref->child;
|
||||
return deref;
|
||||
}
|
||||
|
||||
/* Recursively constructs deref chains to split a copy instruction into
|
||||
* multiple (if needed) copy instructions with full-length deref chains.
|
||||
* External callers of this function should pass the tail and head of the
|
||||
@@ -225,8 +217,8 @@ split_var_copies_block(nir_block *block, void *void_state)
|
||||
|
||||
nir_deref *dest_head = &intrinsic->variables[0]->deref;
|
||||
nir_deref *src_head = &intrinsic->variables[1]->deref;
|
||||
nir_deref *dest_tail = get_deref_tail(dest_head);
|
||||
nir_deref *src_tail = get_deref_tail(src_head);
|
||||
nir_deref *dest_tail = nir_deref_tail(dest_head);
|
||||
nir_deref *src_tail = nir_deref_tail(src_head);
|
||||
|
||||
switch (glsl_get_base_type(src_tail->type)) {
|
||||
case GLSL_TYPE_ARRAY:
|
||||
|
@@ -70,6 +70,18 @@ glsl_get_struct_field(const glsl_type *type, unsigned index)
|
||||
return type->fields.structure[index].type;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_get_function_return_type(const glsl_type *type)
|
||||
{
|
||||
return type->fields.parameters[0].type;
|
||||
}
|
||||
|
||||
const glsl_function_param *
|
||||
glsl_get_function_param(const glsl_type *type, unsigned index)
|
||||
{
|
||||
return &type->fields.parameters[index + 1];
|
||||
}
|
||||
|
||||
const struct glsl_type *
|
||||
glsl_get_column_type(const struct glsl_type *type)
|
||||
{
|
||||
@@ -112,6 +124,20 @@ glsl_get_struct_elem_name(const struct glsl_type *type, unsigned index)
|
||||
return type->fields.structure[index].name;
|
||||
}
|
||||
|
||||
glsl_sampler_dim
|
||||
glsl_get_sampler_dim(const struct glsl_type *type)
|
||||
{
|
||||
assert(glsl_type_is_sampler(type));
|
||||
return (glsl_sampler_dim)type->sampler_dimensionality;
|
||||
}
|
||||
|
||||
glsl_base_type
|
||||
glsl_get_sampler_result_type(const struct glsl_type *type)
|
||||
{
|
||||
assert(glsl_type_is_sampler(type));
|
||||
return (glsl_base_type)type->sampler_type;
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_type_is_void(const glsl_type *type)
|
||||
{
|
||||
@@ -130,12 +156,38 @@ glsl_type_is_scalar(const struct glsl_type *type)
|
||||
return type->is_scalar();
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_type_is_vector_or_scalar(const struct glsl_type *type)
|
||||
{
|
||||
return type->is_vector() || type->is_scalar();
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_type_is_matrix(const struct glsl_type *type)
|
||||
{
|
||||
return type->is_matrix();
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_type_is_sampler(const struct glsl_type *type)
|
||||
{
|
||||
return type->is_sampler();
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_sampler_type_is_shadow(const struct glsl_type *type)
|
||||
{
|
||||
assert(glsl_type_is_sampler(type));
|
||||
return type->sampler_shadow;
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_sampler_type_is_array(const struct glsl_type *type)
|
||||
{
|
||||
assert(glsl_type_is_sampler(type));
|
||||
return type->sampler_array;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_void_type(void)
|
||||
{
|
||||
@@ -148,14 +200,80 @@ glsl_float_type(void)
|
||||
return glsl_type::float_type;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_int_type(void)
|
||||
{
|
||||
return glsl_type::int_type;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_uint_type(void)
|
||||
{
|
||||
return glsl_type::uint_type;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_bool_type(void)
|
||||
{
|
||||
return glsl_type::bool_type;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_vec4_type(void)
|
||||
{
|
||||
return glsl_type::vec4_type;
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_scalar_type(enum glsl_base_type base_type)
|
||||
{
|
||||
return glsl_type::get_instance(base_type, 1, 1);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_vector_type(enum glsl_base_type base_type, unsigned components)
|
||||
{
|
||||
assert(components > 1 && components <= 4);
|
||||
return glsl_type::get_instance(base_type, components, 1);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_matrix_type(enum glsl_base_type base_type, unsigned rows, unsigned columns)
|
||||
{
|
||||
assert(rows >= 1 && rows <= 4 && columns >= 1 && columns <= 4);
|
||||
return glsl_type::get_instance(base_type, rows, columns);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_array_type(const glsl_type *base, unsigned elements)
|
||||
{
|
||||
return glsl_type::get_array_instance(base, elements);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_struct_type(const glsl_struct_field *fields,
|
||||
unsigned num_fields, const char *name)
|
||||
{
|
||||
return glsl_type::get_record_instance(fields, num_fields, name);
|
||||
}
|
||||
|
||||
const struct glsl_type *
|
||||
glsl_sampler_type(enum glsl_sampler_dim dim, bool is_shadow, bool is_array,
|
||||
enum glsl_base_type base_type)
|
||||
{
|
||||
return glsl_type::get_sampler_instance(dim, is_shadow, is_array, base_type);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_function_type(const glsl_type *return_type,
|
||||
const glsl_function_param *params, unsigned num_params)
|
||||
{
|
||||
return glsl_type::get_function_instance(return_type, params, num_params);
|
||||
}
|
||||
|
||||
const glsl_type *
|
||||
glsl_transposed_type(const struct glsl_type *type)
|
||||
{
|
||||
return glsl_type::get_instance(type->base_type, type->matrix_columns,
|
||||
type->vector_elements);
|
||||
}
|
||||
|
@@ -49,6 +49,12 @@ const struct glsl_type *glsl_get_array_element(const struct glsl_type *type);
|
||||
|
||||
const struct glsl_type *glsl_get_column_type(const struct glsl_type *type);
|
||||
|
||||
const struct glsl_type *
|
||||
glsl_get_function_return_type(const struct glsl_type *type);
|
||||
|
||||
const struct glsl_function_param *
|
||||
glsl_get_function_param(const struct glsl_type *type, unsigned index);
|
||||
|
||||
enum glsl_base_type glsl_get_base_type(const struct glsl_type *type);
|
||||
|
||||
unsigned glsl_get_vector_elements(const struct glsl_type *type);
|
||||
@@ -62,17 +68,42 @@ unsigned glsl_get_length(const struct glsl_type *type);
|
||||
const char *glsl_get_struct_elem_name(const struct glsl_type *type,
|
||||
unsigned index);
|
||||
|
||||
enum glsl_sampler_dim glsl_get_sampler_dim(const struct glsl_type *type);
|
||||
enum glsl_base_type glsl_get_sampler_result_type(const struct glsl_type *type);
|
||||
|
||||
bool glsl_type_is_void(const struct glsl_type *type);
|
||||
bool glsl_type_is_vector(const struct glsl_type *type);
|
||||
bool glsl_type_is_scalar(const struct glsl_type *type);
|
||||
bool glsl_type_is_vector_or_scalar(const struct glsl_type *type);
|
||||
bool glsl_type_is_matrix(const struct glsl_type *type);
|
||||
bool glsl_type_is_sampler(const struct glsl_type *type);
|
||||
bool glsl_sampler_type_is_shadow(const struct glsl_type *type);
|
||||
bool glsl_sampler_type_is_array(const struct glsl_type *type);
|
||||
|
||||
const struct glsl_type *glsl_void_type(void);
|
||||
const struct glsl_type *glsl_float_type(void);
|
||||
const struct glsl_type *glsl_int_type(void);
|
||||
const struct glsl_type *glsl_uint_type(void);
|
||||
const struct glsl_type *glsl_bool_type(void);
|
||||
|
||||
const struct glsl_type *glsl_vec4_type(void);
|
||||
const struct glsl_type *glsl_scalar_type(enum glsl_base_type base_type);
|
||||
const struct glsl_type *glsl_vector_type(enum glsl_base_type base_type,
|
||||
unsigned components);
|
||||
const struct glsl_type *glsl_matrix_type(enum glsl_base_type base_type,
|
||||
unsigned rows, unsigned columns);
|
||||
const struct glsl_type *glsl_array_type(const struct glsl_type *base,
|
||||
unsigned elements);
|
||||
const struct glsl_type *glsl_struct_type(const struct glsl_struct_field *fields,
|
||||
unsigned num_fields, const char *name);
|
||||
const struct glsl_type *glsl_sampler_type(enum glsl_sampler_dim dim,
|
||||
bool is_shadow, bool is_array,
|
||||
enum glsl_base_type base_type);
|
||||
const struct glsl_type * glsl_function_type(const struct glsl_type *return_type,
|
||||
const struct glsl_function_param *params,
|
||||
unsigned num_params);
|
||||
|
||||
const struct glsl_type *glsl_transposed_type(const struct glsl_type *type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
808
src/glsl/nir/spirv.h
Normal file
808
src/glsl/nir/spirv.h
Normal file
@@ -0,0 +1,808 @@
|
||||
/*
|
||||
** Copyright (c) 2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is automatically generated by the same tool that creates
|
||||
** the Binary Section of the SPIR-V specification.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Specification revision 31.
|
||||
** Enumeration tokens for SPIR-V, in various styles:
|
||||
** C, C++, C++11, JSON, Lua, Python
|
||||
**
|
||||
** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
|
||||
** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
|
||||
** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
|
||||
** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
|
||||
** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
|
||||
**
|
||||
** Some tokens act like mask values, which can be OR'd together,
|
||||
** while others are mutually exclusive. The mask-like ones have
|
||||
** "Mask" in their name, and a parallel enum that has the shift
|
||||
** amount (1 << x) for each corresponding enumerant.
|
||||
*/
|
||||
|
||||
#ifndef spirv_H
|
||||
#define spirv_H
|
||||
|
||||
typedef unsigned int SpvId;
|
||||
|
||||
static const unsigned int SpvMagicNumber = 0x07230203;
|
||||
static const unsigned int SpvVersion = 99;
|
||||
static const unsigned int SpvOpCodeMask = 0xffff;
|
||||
static const unsigned int SpvWordCountShift = 16;
|
||||
|
||||
typedef enum SpvSourceLanguage_ {
|
||||
SpvSourceLanguageUnknown = 0,
|
||||
SpvSourceLanguageESSL = 1,
|
||||
SpvSourceLanguageGLSL = 2,
|
||||
SpvSourceLanguageOpenCL = 3,
|
||||
} SpvSourceLanguage;
|
||||
|
||||
typedef enum SpvExecutionModel_ {
|
||||
SpvExecutionModelVertex = 0,
|
||||
SpvExecutionModelTessellationControl = 1,
|
||||
SpvExecutionModelTessellationEvaluation = 2,
|
||||
SpvExecutionModelGeometry = 3,
|
||||
SpvExecutionModelFragment = 4,
|
||||
SpvExecutionModelGLCompute = 5,
|
||||
SpvExecutionModelKernel = 6,
|
||||
} SpvExecutionModel;
|
||||
|
||||
typedef enum SpvAddressingModel_ {
|
||||
SpvAddressingModelLogical = 0,
|
||||
SpvAddressingModelPhysical32 = 1,
|
||||
SpvAddressingModelPhysical64 = 2,
|
||||
} SpvAddressingModel;
|
||||
|
||||
typedef enum SpvMemoryModel_ {
|
||||
SpvMemoryModelSimple = 0,
|
||||
SpvMemoryModelGLSL450 = 1,
|
||||
SpvMemoryModelOpenCL = 2,
|
||||
} SpvMemoryModel;
|
||||
|
||||
typedef enum SpvExecutionMode_ {
|
||||
SpvExecutionModeInvocations = 0,
|
||||
SpvExecutionModeSpacingEqual = 1,
|
||||
SpvExecutionModeSpacingFractionalEven = 2,
|
||||
SpvExecutionModeSpacingFractionalOdd = 3,
|
||||
SpvExecutionModeVertexOrderCw = 4,
|
||||
SpvExecutionModeVertexOrderCcw = 5,
|
||||
SpvExecutionModePixelCenterInteger = 6,
|
||||
SpvExecutionModeOriginUpperLeft = 7,
|
||||
SpvExecutionModeOriginLowerLeft = 8,
|
||||
SpvExecutionModeEarlyFragmentTests = 9,
|
||||
SpvExecutionModePointMode = 10,
|
||||
SpvExecutionModeXfb = 11,
|
||||
SpvExecutionModeDepthReplacing = 12,
|
||||
SpvExecutionModeDepthAny = 13,
|
||||
SpvExecutionModeDepthGreater = 14,
|
||||
SpvExecutionModeDepthLess = 15,
|
||||
SpvExecutionModeDepthUnchanged = 16,
|
||||
SpvExecutionModeLocalSize = 17,
|
||||
SpvExecutionModeLocalSizeHint = 18,
|
||||
SpvExecutionModeInputPoints = 19,
|
||||
SpvExecutionModeInputLines = 20,
|
||||
SpvExecutionModeInputLinesAdjacency = 21,
|
||||
SpvExecutionModeInputTriangles = 22,
|
||||
SpvExecutionModeInputTrianglesAdjacency = 23,
|
||||
SpvExecutionModeInputQuads = 24,
|
||||
SpvExecutionModeInputIsolines = 25,
|
||||
SpvExecutionModeOutputVertices = 26,
|
||||
SpvExecutionModeOutputPoints = 27,
|
||||
SpvExecutionModeOutputLineStrip = 28,
|
||||
SpvExecutionModeOutputTriangleStrip = 29,
|
||||
SpvExecutionModeVecTypeHint = 30,
|
||||
SpvExecutionModeContractionOff = 31,
|
||||
} SpvExecutionMode;
|
||||
|
||||
typedef enum SpvStorageClass_ {
|
||||
SpvStorageClassUniformConstant = 0,
|
||||
SpvStorageClassInput = 1,
|
||||
SpvStorageClassUniform = 2,
|
||||
SpvStorageClassOutput = 3,
|
||||
SpvStorageClassWorkgroupLocal = 4,
|
||||
SpvStorageClassWorkgroupGlobal = 5,
|
||||
SpvStorageClassPrivateGlobal = 6,
|
||||
SpvStorageClassFunction = 7,
|
||||
SpvStorageClassGeneric = 8,
|
||||
SpvStorageClassPushConstant = 9,
|
||||
SpvStorageClassAtomicCounter = 10,
|
||||
SpvStorageClassImage = 11,
|
||||
} SpvStorageClass;
|
||||
|
||||
typedef enum SpvDim_ {
|
||||
SpvDim1D = 0,
|
||||
SpvDim2D = 1,
|
||||
SpvDim3D = 2,
|
||||
SpvDimCube = 3,
|
||||
SpvDimRect = 4,
|
||||
SpvDimBuffer = 5,
|
||||
} SpvDim;
|
||||
|
||||
typedef enum SpvSamplerAddressingMode_ {
|
||||
SpvSamplerAddressingModeNone = 0,
|
||||
SpvSamplerAddressingModeClampToEdge = 1,
|
||||
SpvSamplerAddressingModeClamp = 2,
|
||||
SpvSamplerAddressingModeRepeat = 3,
|
||||
SpvSamplerAddressingModeRepeatMirrored = 4,
|
||||
} SpvSamplerAddressingMode;
|
||||
|
||||
typedef enum SpvSamplerFilterMode_ {
|
||||
SpvSamplerFilterModeNearest = 0,
|
||||
SpvSamplerFilterModeLinear = 1,
|
||||
} SpvSamplerFilterMode;
|
||||
|
||||
typedef enum SpvImageFormat_ {
|
||||
SpvImageFormatUnknown = 0,
|
||||
SpvImageFormatRgba32f = 1,
|
||||
SpvImageFormatRgba16f = 2,
|
||||
SpvImageFormatR32f = 3,
|
||||
SpvImageFormatRgba8 = 4,
|
||||
SpvImageFormatRgba8Snorm = 5,
|
||||
SpvImageFormatRg32f = 6,
|
||||
SpvImageFormatRg16f = 7,
|
||||
SpvImageFormatR11fG11fB10f = 8,
|
||||
SpvImageFormatR16f = 9,
|
||||
SpvImageFormatRgba16 = 10,
|
||||
SpvImageFormatRgb10A2 = 11,
|
||||
SpvImageFormatRg16 = 12,
|
||||
SpvImageFormatRg8 = 13,
|
||||
SpvImageFormatR16 = 14,
|
||||
SpvImageFormatR8 = 15,
|
||||
SpvImageFormatRgba16Snorm = 16,
|
||||
SpvImageFormatRg16Snorm = 17,
|
||||
SpvImageFormatRg8Snorm = 18,
|
||||
SpvImageFormatR16Snorm = 19,
|
||||
SpvImageFormatR8Snorm = 20,
|
||||
SpvImageFormatRgba32i = 21,
|
||||
SpvImageFormatRgba16i = 22,
|
||||
SpvImageFormatRgba8i = 23,
|
||||
SpvImageFormatR32i = 24,
|
||||
SpvImageFormatRg32i = 25,
|
||||
SpvImageFormatRg16i = 26,
|
||||
SpvImageFormatRg8i = 27,
|
||||
SpvImageFormatR16i = 28,
|
||||
SpvImageFormatR8i = 29,
|
||||
SpvImageFormatRgba32ui = 30,
|
||||
SpvImageFormatRgba16ui = 31,
|
||||
SpvImageFormatRgba8ui = 32,
|
||||
SpvImageFormatR32ui = 33,
|
||||
SpvImageFormatRgb10a2ui = 34,
|
||||
SpvImageFormatRg32ui = 35,
|
||||
SpvImageFormatRg16ui = 36,
|
||||
SpvImageFormatRg8ui = 37,
|
||||
SpvImageFormatR16ui = 38,
|
||||
SpvImageFormatR8ui = 39,
|
||||
} SpvImageFormat;
|
||||
|
||||
typedef enum SpvImageChannelOrder_ {
|
||||
SpvImageChannelOrderR = 0,
|
||||
SpvImageChannelOrderA = 1,
|
||||
SpvImageChannelOrderRG = 2,
|
||||
SpvImageChannelOrderRA = 3,
|
||||
SpvImageChannelOrderRGB = 4,
|
||||
SpvImageChannelOrderRGBA = 5,
|
||||
SpvImageChannelOrderBGRA = 6,
|
||||
SpvImageChannelOrderARGB = 7,
|
||||
SpvImageChannelOrderIntensity = 8,
|
||||
SpvImageChannelOrderLuminance = 9,
|
||||
SpvImageChannelOrderRx = 10,
|
||||
SpvImageChannelOrderRGx = 11,
|
||||
SpvImageChannelOrderRGBx = 12,
|
||||
SpvImageChannelOrderDepth = 13,
|
||||
SpvImageChannelOrderDepthStencil = 14,
|
||||
SpvImageChannelOrdersRGB = 15,
|
||||
SpvImageChannelOrdersRGBx = 16,
|
||||
SpvImageChannelOrdersRGBA = 17,
|
||||
SpvImageChannelOrdersBGRA = 18,
|
||||
} SpvImageChannelOrder;
|
||||
|
||||
typedef enum SpvImageChannelDataType_ {
|
||||
SpvImageChannelDataTypeSnormInt8 = 0,
|
||||
SpvImageChannelDataTypeSnormInt16 = 1,
|
||||
SpvImageChannelDataTypeUnormInt8 = 2,
|
||||
SpvImageChannelDataTypeUnormInt16 = 3,
|
||||
SpvImageChannelDataTypeUnormShort565 = 4,
|
||||
SpvImageChannelDataTypeUnormShort555 = 5,
|
||||
SpvImageChannelDataTypeUnormInt101010 = 6,
|
||||
SpvImageChannelDataTypeSignedInt8 = 7,
|
||||
SpvImageChannelDataTypeSignedInt16 = 8,
|
||||
SpvImageChannelDataTypeSignedInt32 = 9,
|
||||
SpvImageChannelDataTypeUnsignedInt8 = 10,
|
||||
SpvImageChannelDataTypeUnsignedInt16 = 11,
|
||||
SpvImageChannelDataTypeUnsignedInt32 = 12,
|
||||
SpvImageChannelDataTypeHalfFloat = 13,
|
||||
SpvImageChannelDataTypeFloat = 14,
|
||||
SpvImageChannelDataTypeUnormInt24 = 15,
|
||||
} SpvImageChannelDataType;
|
||||
|
||||
typedef enum SpvImageOperandsShift_ {
|
||||
SpvImageOperandsBiasShift = 0,
|
||||
SpvImageOperandsLodShift = 1,
|
||||
SpvImageOperandsGradShift = 2,
|
||||
SpvImageOperandsOffsetShift = 3,
|
||||
SpvImageOperandsOffsetsShift = 4,
|
||||
SpvImageOperandsSampleShift = 5,
|
||||
} SpvImageOperandsShift;
|
||||
|
||||
typedef enum SpvImageOperandsMask_ {
|
||||
SpvImageOperandsMaskNone = 0,
|
||||
SpvImageOperandsBiasMask = 0x00000001,
|
||||
SpvImageOperandsLodMask = 0x00000002,
|
||||
SpvImageOperandsGradMask = 0x00000004,
|
||||
SpvImageOperandsOffsetMask = 0x00000008,
|
||||
SpvImageOperandsOffsetsMask = 0x00000010,
|
||||
SpvImageOperandsSampleMask = 0x00000020,
|
||||
} SpvImageOperandsMask;
|
||||
|
||||
typedef enum SpvFPFastMathModeShift_ {
|
||||
SpvFPFastMathModeNotNaNShift = 0,
|
||||
SpvFPFastMathModeNotInfShift = 1,
|
||||
SpvFPFastMathModeNSZShift = 2,
|
||||
SpvFPFastMathModeAllowRecipShift = 3,
|
||||
SpvFPFastMathModeFastShift = 4,
|
||||
} SpvFPFastMathModeShift;
|
||||
|
||||
typedef enum SpvFPFastMathModeMask_ {
|
||||
SpvFPFastMathModeMaskNone = 0,
|
||||
SpvFPFastMathModeNotNaNMask = 0x00000001,
|
||||
SpvFPFastMathModeNotInfMask = 0x00000002,
|
||||
SpvFPFastMathModeNSZMask = 0x00000004,
|
||||
SpvFPFastMathModeAllowRecipMask = 0x00000008,
|
||||
SpvFPFastMathModeFastMask = 0x00000010,
|
||||
} SpvFPFastMathModeMask;
|
||||
|
||||
typedef enum SpvFPRoundingMode_ {
|
||||
SpvFPRoundingModeRTE = 0,
|
||||
SpvFPRoundingModeRTZ = 1,
|
||||
SpvFPRoundingModeRTP = 2,
|
||||
SpvFPRoundingModeRTN = 3,
|
||||
} SpvFPRoundingMode;
|
||||
|
||||
typedef enum SpvLinkageType_ {
|
||||
SpvLinkageTypeExport = 0,
|
||||
SpvLinkageTypeImport = 1,
|
||||
} SpvLinkageType;
|
||||
|
||||
typedef enum SpvAccessQualifier_ {
|
||||
SpvAccessQualifierReadOnly = 0,
|
||||
SpvAccessQualifierWriteOnly = 1,
|
||||
SpvAccessQualifierReadWrite = 2,
|
||||
} SpvAccessQualifier;
|
||||
|
||||
typedef enum SpvFunctionParameterAttribute_ {
|
||||
SpvFunctionParameterAttributeZext = 0,
|
||||
SpvFunctionParameterAttributeSext = 1,
|
||||
SpvFunctionParameterAttributeByVal = 2,
|
||||
SpvFunctionParameterAttributeSret = 3,
|
||||
SpvFunctionParameterAttributeNoAlias = 4,
|
||||
SpvFunctionParameterAttributeNoCapture = 5,
|
||||
SpvFunctionParameterAttributeSVM = 6,
|
||||
SpvFunctionParameterAttributeNoWrite = 7,
|
||||
SpvFunctionParameterAttributeNoReadWrite = 8,
|
||||
} SpvFunctionParameterAttribute;
|
||||
|
||||
typedef enum SpvDecoration_ {
|
||||
SpvDecorationRelaxedPrecision = 0,
|
||||
SpvDecorationSpecId = 1,
|
||||
SpvDecorationBlock = 2,
|
||||
SpvDecorationBufferBlock = 3,
|
||||
SpvDecorationRowMajor = 4,
|
||||
SpvDecorationColMajor = 5,
|
||||
SpvDecorationArrayStride = 6,
|
||||
SpvDecorationMatrixStride = 7,
|
||||
SpvDecorationGLSLShared = 8,
|
||||
SpvDecorationGLSLPacked = 9,
|
||||
SpvDecorationCPacked = 10,
|
||||
SpvDecorationBuiltIn = 11,
|
||||
SpvDecorationSmooth = 12,
|
||||
SpvDecorationNoperspective = 13,
|
||||
SpvDecorationFlat = 14,
|
||||
SpvDecorationPatch = 15,
|
||||
SpvDecorationCentroid = 16,
|
||||
SpvDecorationSample = 17,
|
||||
SpvDecorationInvariant = 18,
|
||||
SpvDecorationRestrict = 19,
|
||||
SpvDecorationAliased = 20,
|
||||
SpvDecorationVolatile = 21,
|
||||
SpvDecorationConstant = 22,
|
||||
SpvDecorationCoherent = 23,
|
||||
SpvDecorationNonwritable = 24,
|
||||
SpvDecorationNonreadable = 25,
|
||||
SpvDecorationUniform = 26,
|
||||
SpvDecorationNoStaticUse = 27,
|
||||
SpvDecorationSaturatedConversion = 28,
|
||||
SpvDecorationStream = 29,
|
||||
SpvDecorationLocation = 30,
|
||||
SpvDecorationComponent = 31,
|
||||
SpvDecorationIndex = 32,
|
||||
SpvDecorationBinding = 33,
|
||||
SpvDecorationDescriptorSet = 34,
|
||||
SpvDecorationOffset = 35,
|
||||
SpvDecorationXfbBuffer = 36,
|
||||
SpvDecorationXfbStride = 37,
|
||||
SpvDecorationFuncParamAttr = 38,
|
||||
SpvDecorationFPRoundingMode = 39,
|
||||
SpvDecorationFPFastMathMode = 40,
|
||||
SpvDecorationLinkageAttributes = 41,
|
||||
} SpvDecoration;
|
||||
|
||||
typedef enum SpvBuiltIn_ {
|
||||
SpvBuiltInPosition = 0,
|
||||
SpvBuiltInPointSize = 1,
|
||||
SpvBuiltInClipVertex = 2,
|
||||
SpvBuiltInClipDistance = 3,
|
||||
SpvBuiltInCullDistance = 4,
|
||||
SpvBuiltInVertexId = 5,
|
||||
SpvBuiltInInstanceId = 6,
|
||||
SpvBuiltInPrimitiveId = 7,
|
||||
SpvBuiltInInvocationId = 8,
|
||||
SpvBuiltInLayer = 9,
|
||||
SpvBuiltInViewportIndex = 10,
|
||||
SpvBuiltInTessLevelOuter = 11,
|
||||
SpvBuiltInTessLevelInner = 12,
|
||||
SpvBuiltInTessCoord = 13,
|
||||
SpvBuiltInPatchVertices = 14,
|
||||
SpvBuiltInFragCoord = 15,
|
||||
SpvBuiltInPointCoord = 16,
|
||||
SpvBuiltInFrontFacing = 17,
|
||||
SpvBuiltInSampleId = 18,
|
||||
SpvBuiltInSamplePosition = 19,
|
||||
SpvBuiltInSampleMask = 20,
|
||||
SpvBuiltInFragColor = 21,
|
||||
SpvBuiltInFragDepth = 22,
|
||||
SpvBuiltInHelperInvocation = 23,
|
||||
SpvBuiltInNumWorkgroups = 24,
|
||||
SpvBuiltInWorkgroupSize = 25,
|
||||
SpvBuiltInWorkgroupId = 26,
|
||||
SpvBuiltInLocalInvocationId = 27,
|
||||
SpvBuiltInGlobalInvocationId = 28,
|
||||
SpvBuiltInLocalInvocationIndex = 29,
|
||||
SpvBuiltInWorkDim = 30,
|
||||
SpvBuiltInGlobalSize = 31,
|
||||
SpvBuiltInEnqueuedWorkgroupSize = 32,
|
||||
SpvBuiltInGlobalOffset = 33,
|
||||
SpvBuiltInGlobalLinearId = 34,
|
||||
SpvBuiltInWorkgroupLinearId = 35,
|
||||
SpvBuiltInSubgroupSize = 36,
|
||||
SpvBuiltInSubgroupMaxSize = 37,
|
||||
SpvBuiltInNumSubgroups = 38,
|
||||
SpvBuiltInNumEnqueuedSubgroups = 39,
|
||||
SpvBuiltInSubgroupId = 40,
|
||||
SpvBuiltInSubgroupLocalInvocationId = 41,
|
||||
} SpvBuiltIn;
|
||||
|
||||
typedef enum SpvSelectionControlShift_ {
|
||||
SpvSelectionControlFlattenShift = 0,
|
||||
SpvSelectionControlDontFlattenShift = 1,
|
||||
} SpvSelectionControlShift;
|
||||
|
||||
typedef enum SpvSelectionControlMask_ {
|
||||
SpvSelectionControlMaskNone = 0,
|
||||
SpvSelectionControlFlattenMask = 0x00000001,
|
||||
SpvSelectionControlDontFlattenMask = 0x00000002,
|
||||
} SpvSelectionControlMask;
|
||||
|
||||
typedef enum SpvLoopControlShift_ {
|
||||
SpvLoopControlUnrollShift = 0,
|
||||
SpvLoopControlDontUnrollShift = 1,
|
||||
} SpvLoopControlShift;
|
||||
|
||||
typedef enum SpvLoopControlMask_ {
|
||||
SpvLoopControlMaskNone = 0,
|
||||
SpvLoopControlUnrollMask = 0x00000001,
|
||||
SpvLoopControlDontUnrollMask = 0x00000002,
|
||||
} SpvLoopControlMask;
|
||||
|
||||
typedef enum SpvFunctionControlShift_ {
|
||||
SpvFunctionControlInlineShift = 0,
|
||||
SpvFunctionControlDontInlineShift = 1,
|
||||
SpvFunctionControlPureShift = 2,
|
||||
SpvFunctionControlConstShift = 3,
|
||||
} SpvFunctionControlShift;
|
||||
|
||||
typedef enum SpvFunctionControlMask_ {
|
||||
SpvFunctionControlMaskNone = 0,
|
||||
SpvFunctionControlInlineMask = 0x00000001,
|
||||
SpvFunctionControlDontInlineMask = 0x00000002,
|
||||
SpvFunctionControlPureMask = 0x00000004,
|
||||
SpvFunctionControlConstMask = 0x00000008,
|
||||
} SpvFunctionControlMask;
|
||||
|
||||
typedef enum SpvMemorySemanticsShift_ {
|
||||
SpvMemorySemanticsRelaxedShift = 0,
|
||||
SpvMemorySemanticsSequentiallyConsistentShift = 1,
|
||||
SpvMemorySemanticsAcquireShift = 2,
|
||||
SpvMemorySemanticsReleaseShift = 3,
|
||||
SpvMemorySemanticsUniformMemoryShift = 4,
|
||||
SpvMemorySemanticsSubgroupMemoryShift = 5,
|
||||
SpvMemorySemanticsWorkgroupLocalMemoryShift = 6,
|
||||
SpvMemorySemanticsWorkgroupGlobalMemoryShift = 7,
|
||||
SpvMemorySemanticsAtomicCounterMemoryShift = 8,
|
||||
SpvMemorySemanticsImageMemoryShift = 9,
|
||||
} SpvMemorySemanticsShift;
|
||||
|
||||
typedef enum SpvMemorySemanticsMask_ {
|
||||
SpvMemorySemanticsMaskNone = 0,
|
||||
SpvMemorySemanticsRelaxedMask = 0x00000001,
|
||||
SpvMemorySemanticsSequentiallyConsistentMask = 0x00000002,
|
||||
SpvMemorySemanticsAcquireMask = 0x00000004,
|
||||
SpvMemorySemanticsReleaseMask = 0x00000008,
|
||||
SpvMemorySemanticsUniformMemoryMask = 0x00000010,
|
||||
SpvMemorySemanticsSubgroupMemoryMask = 0x00000020,
|
||||
SpvMemorySemanticsWorkgroupLocalMemoryMask = 0x00000040,
|
||||
SpvMemorySemanticsWorkgroupGlobalMemoryMask = 0x00000080,
|
||||
SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000100,
|
||||
SpvMemorySemanticsImageMemoryMask = 0x00000200,
|
||||
} SpvMemorySemanticsMask;
|
||||
|
||||
typedef enum SpvMemoryAccessShift_ {
|
||||
SpvMemoryAccessVolatileShift = 0,
|
||||
SpvMemoryAccessAlignedShift = 1,
|
||||
} SpvMemoryAccessShift;
|
||||
|
||||
typedef enum SpvMemoryAccessMask_ {
|
||||
SpvMemoryAccessMaskNone = 0,
|
||||
SpvMemoryAccessVolatileMask = 0x00000001,
|
||||
SpvMemoryAccessAlignedMask = 0x00000002,
|
||||
} SpvMemoryAccessMask;
|
||||
|
||||
typedef enum SpvScope_ {
|
||||
SpvScopeCrossDevice = 0,
|
||||
SpvScopeDevice = 1,
|
||||
SpvScopeWorkgroup = 2,
|
||||
SpvScopeSubgroup = 3,
|
||||
SpvScopeInvocation = 4,
|
||||
} SpvScope;
|
||||
|
||||
typedef enum SpvGroupOperation_ {
|
||||
SpvGroupOperationReduce = 0,
|
||||
SpvGroupOperationInclusiveScan = 1,
|
||||
SpvGroupOperationExclusiveScan = 2,
|
||||
} SpvGroupOperation;
|
||||
|
||||
typedef enum SpvKernelEnqueueFlags_ {
|
||||
SpvKernelEnqueueFlagsNoWait = 0,
|
||||
SpvKernelEnqueueFlagsWaitKernel = 1,
|
||||
SpvKernelEnqueueFlagsWaitWorkGroup = 2,
|
||||
} SpvKernelEnqueueFlags;
|
||||
|
||||
typedef enum SpvKernelProfilingInfoShift_ {
|
||||
SpvKernelProfilingInfoCmdExecTimeShift = 0,
|
||||
} SpvKernelProfilingInfoShift;
|
||||
|
||||
typedef enum SpvKernelProfilingInfoMask_ {
|
||||
SpvKernelProfilingInfoMaskNone = 0,
|
||||
SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,
|
||||
} SpvKernelProfilingInfoMask;
|
||||
|
||||
typedef enum SpvCapability_ {
|
||||
SpvCapabilityMatrix = 0,
|
||||
SpvCapabilityShader = 1,
|
||||
SpvCapabilityGeometry = 2,
|
||||
SpvCapabilityTessellation = 3,
|
||||
SpvCapabilityAddresses = 4,
|
||||
SpvCapabilityLinkage = 5,
|
||||
SpvCapabilityKernel = 6,
|
||||
SpvCapabilityVector16 = 7,
|
||||
SpvCapabilityFloat16Buffer = 8,
|
||||
SpvCapabilityFloat16 = 9,
|
||||
SpvCapabilityFloat64 = 10,
|
||||
SpvCapabilityInt64 = 11,
|
||||
SpvCapabilityInt64Atomics = 12,
|
||||
SpvCapabilityImageBasic = 13,
|
||||
SpvCapabilityImageReadWrite = 14,
|
||||
SpvCapabilityImageMipmap = 15,
|
||||
SpvCapabilityImageSRGBWrite = 16,
|
||||
SpvCapabilityPipes = 17,
|
||||
SpvCapabilityGroups = 18,
|
||||
SpvCapabilityDeviceEnqueue = 19,
|
||||
SpvCapabilityLiteralSampler = 20,
|
||||
SpvCapabilityAtomicStorage = 21,
|
||||
SpvCapabilityInt16 = 22,
|
||||
} SpvCapability;
|
||||
|
||||
typedef enum SpvOp_ {
|
||||
SpvOpNop = 0,
|
||||
SpvOpUndef = 1,
|
||||
SpvOpSource = 3,
|
||||
SpvOpSourceExtension = 4,
|
||||
SpvOpName = 5,
|
||||
SpvOpMemberName = 6,
|
||||
SpvOpString = 7,
|
||||
SpvOpLine = 8,
|
||||
SpvOpExtension = 10,
|
||||
SpvOpExtInstImport = 11,
|
||||
SpvOpExtInst = 12,
|
||||
SpvOpMemoryModel = 14,
|
||||
SpvOpEntryPoint = 15,
|
||||
SpvOpExecutionMode = 16,
|
||||
SpvOpCapability = 17,
|
||||
SpvOpTypeVoid = 19,
|
||||
SpvOpTypeBool = 20,
|
||||
SpvOpTypeInt = 21,
|
||||
SpvOpTypeFloat = 22,
|
||||
SpvOpTypeVector = 23,
|
||||
SpvOpTypeMatrix = 24,
|
||||
SpvOpTypeImage = 25,
|
||||
SpvOpTypeSampler = 26,
|
||||
SpvOpTypeSampledImage = 27,
|
||||
SpvOpTypeArray = 28,
|
||||
SpvOpTypeRuntimeArray = 29,
|
||||
SpvOpTypeStruct = 30,
|
||||
SpvOpTypeOpaque = 31,
|
||||
SpvOpTypePointer = 32,
|
||||
SpvOpTypeFunction = 33,
|
||||
SpvOpTypeEvent = 34,
|
||||
SpvOpTypeDeviceEvent = 35,
|
||||
SpvOpTypeReserveId = 36,
|
||||
SpvOpTypeQueue = 37,
|
||||
SpvOpTypePipe = 38,
|
||||
SpvOpConstantTrue = 41,
|
||||
SpvOpConstantFalse = 42,
|
||||
SpvOpConstant = 43,
|
||||
SpvOpConstantComposite = 44,
|
||||
SpvOpConstantSampler = 45,
|
||||
SpvOpConstantNull = 46,
|
||||
SpvOpSpecConstantTrue = 48,
|
||||
SpvOpSpecConstantFalse = 49,
|
||||
SpvOpSpecConstant = 50,
|
||||
SpvOpSpecConstantComposite = 51,
|
||||
SpvOpSpecConstantOp = 52,
|
||||
SpvOpFunction = 54,
|
||||
SpvOpFunctionParameter = 55,
|
||||
SpvOpFunctionEnd = 56,
|
||||
SpvOpFunctionCall = 57,
|
||||
SpvOpVariable = 59,
|
||||
SpvOpImageTexelPointer = 60,
|
||||
SpvOpLoad = 61,
|
||||
SpvOpStore = 62,
|
||||
SpvOpCopyMemory = 63,
|
||||
SpvOpCopyMemorySized = 64,
|
||||
SpvOpAccessChain = 65,
|
||||
SpvOpInBoundsAccessChain = 66,
|
||||
SpvOpPtrAccessChain = 67,
|
||||
SpvOpArrayLength = 68,
|
||||
SpvOpGenericPtrMemSemantics = 69,
|
||||
SpvOpDecorate = 71,
|
||||
SpvOpMemberDecorate = 72,
|
||||
SpvOpDecorationGroup = 73,
|
||||
SpvOpGroupDecorate = 74,
|
||||
SpvOpGroupMemberDecorate = 75,
|
||||
SpvOpVectorExtractDynamic = 77,
|
||||
SpvOpVectorInsertDynamic = 78,
|
||||
SpvOpVectorShuffle = 79,
|
||||
SpvOpCompositeConstruct = 80,
|
||||
SpvOpCompositeExtract = 81,
|
||||
SpvOpCompositeInsert = 82,
|
||||
SpvOpCopyObject = 83,
|
||||
SpvOpTranspose = 84,
|
||||
SpvOpSampledImage = 86,
|
||||
SpvOpImageSampleImplicitLod = 87,
|
||||
SpvOpImageSampleExplicitLod = 88,
|
||||
SpvOpImageSampleDrefImplicitLod = 89,
|
||||
SpvOpImageSampleDrefExplicitLod = 90,
|
||||
SpvOpImageSampleProjImplicitLod = 91,
|
||||
SpvOpImageSampleProjExplicitLod = 92,
|
||||
SpvOpImageSampleProjDrefImplicitLod = 93,
|
||||
SpvOpImageSampleProjDrefExplicitLod = 94,
|
||||
SpvOpImageFetch = 95,
|
||||
SpvOpImageGather = 96,
|
||||
SpvOpImageDrefGather = 97,
|
||||
SpvOpImageRead = 98,
|
||||
SpvOpImageWrite = 99,
|
||||
SpvOpImageQueryDim = 100,
|
||||
SpvOpImageQueryFormat = 101,
|
||||
SpvOpImageQueryOrder = 102,
|
||||
SpvOpImageQuerySizeLod = 103,
|
||||
SpvOpImageQuerySize = 104,
|
||||
SpvOpImageQueryLod = 105,
|
||||
SpvOpImageQueryLevels = 106,
|
||||
SpvOpImageQuerySamples = 107,
|
||||
SpvOpConvertFToU = 109,
|
||||
SpvOpConvertFToS = 110,
|
||||
SpvOpConvertSToF = 111,
|
||||
SpvOpConvertUToF = 112,
|
||||
SpvOpUConvert = 113,
|
||||
SpvOpSConvert = 114,
|
||||
SpvOpFConvert = 115,
|
||||
SpvOpQuantizeToF16 = 116,
|
||||
SpvOpConvertPtrToU = 117,
|
||||
SpvOpSatConvertSToU = 118,
|
||||
SpvOpSatConvertUToS = 119,
|
||||
SpvOpConvertUToPtr = 120,
|
||||
SpvOpPtrCastToGeneric = 121,
|
||||
SpvOpGenericCastToPtr = 122,
|
||||
SpvOpGenericCastToPtrExplicit = 123,
|
||||
SpvOpBitcast = 124,
|
||||
SpvOpSNegate = 126,
|
||||
SpvOpFNegate = 127,
|
||||
SpvOpIAdd = 128,
|
||||
SpvOpFAdd = 129,
|
||||
SpvOpISub = 130,
|
||||
SpvOpFSub = 131,
|
||||
SpvOpIMul = 132,
|
||||
SpvOpFMul = 133,
|
||||
SpvOpUDiv = 134,
|
||||
SpvOpSDiv = 135,
|
||||
SpvOpFDiv = 136,
|
||||
SpvOpUMod = 137,
|
||||
SpvOpSRem = 138,
|
||||
SpvOpSMod = 139,
|
||||
SpvOpFRem = 140,
|
||||
SpvOpFMod = 141,
|
||||
SpvOpVectorTimesScalar = 142,
|
||||
SpvOpMatrixTimesScalar = 143,
|
||||
SpvOpVectorTimesMatrix = 144,
|
||||
SpvOpMatrixTimesVector = 145,
|
||||
SpvOpMatrixTimesMatrix = 146,
|
||||
SpvOpOuterProduct = 147,
|
||||
SpvOpDot = 148,
|
||||
SpvOpIAddCarry = 149,
|
||||
SpvOpISubBorrow = 150,
|
||||
SpvOpIMulExtended = 151,
|
||||
SpvOpAny = 154,
|
||||
SpvOpAll = 155,
|
||||
SpvOpIsNan = 156,
|
||||
SpvOpIsInf = 157,
|
||||
SpvOpIsFinite = 158,
|
||||
SpvOpIsNormal = 159,
|
||||
SpvOpSignBitSet = 160,
|
||||
SpvOpLessOrGreater = 161,
|
||||
SpvOpOrdered = 162,
|
||||
SpvOpUnordered = 163,
|
||||
SpvOpLogicalEqual = 164,
|
||||
SpvOpLogicalNotEqual = 165,
|
||||
SpvOpLogicalOr = 166,
|
||||
SpvOpLogicalAnd = 167,
|
||||
SpvOpLogicalNot = 168,
|
||||
SpvOpSelect = 169,
|
||||
SpvOpIEqual = 170,
|
||||
SpvOpINotEqual = 171,
|
||||
SpvOpUGreaterThan = 172,
|
||||
SpvOpSGreaterThan = 173,
|
||||
SpvOpUGreaterThanEqual = 174,
|
||||
SpvOpSGreaterThanEqual = 175,
|
||||
SpvOpULessThan = 176,
|
||||
SpvOpSLessThan = 177,
|
||||
SpvOpULessThanEqual = 178,
|
||||
SpvOpSLessThanEqual = 179,
|
||||
SpvOpFOrdEqual = 180,
|
||||
SpvOpFUnordEqual = 181,
|
||||
SpvOpFOrdNotEqual = 182,
|
||||
SpvOpFUnordNotEqual = 183,
|
||||
SpvOpFOrdLessThan = 184,
|
||||
SpvOpFUnordLessThan = 185,
|
||||
SpvOpFOrdGreaterThan = 186,
|
||||
SpvOpFUnordGreaterThan = 187,
|
||||
SpvOpFOrdLessThanEqual = 188,
|
||||
SpvOpFUnordLessThanEqual = 189,
|
||||
SpvOpFOrdGreaterThanEqual = 190,
|
||||
SpvOpFUnordGreaterThanEqual = 191,
|
||||
SpvOpShiftRightLogical = 194,
|
||||
SpvOpShiftRightArithmetic = 195,
|
||||
SpvOpShiftLeftLogical = 196,
|
||||
SpvOpBitwiseOr = 197,
|
||||
SpvOpBitwiseXor = 198,
|
||||
SpvOpBitwiseAnd = 199,
|
||||
SpvOpNot = 200,
|
||||
SpvOpBitFieldInsert = 201,
|
||||
SpvOpBitFieldSExtract = 202,
|
||||
SpvOpBitFieldUExtract = 203,
|
||||
SpvOpBitReverse = 204,
|
||||
SpvOpBitCount = 205,
|
||||
SpvOpDPdx = 207,
|
||||
SpvOpDPdy = 208,
|
||||
SpvOpFwidth = 209,
|
||||
SpvOpDPdxFine = 210,
|
||||
SpvOpDPdyFine = 211,
|
||||
SpvOpFwidthFine = 212,
|
||||
SpvOpDPdxCoarse = 213,
|
||||
SpvOpDPdyCoarse = 214,
|
||||
SpvOpFwidthCoarse = 215,
|
||||
SpvOpEmitVertex = 218,
|
||||
SpvOpEndPrimitive = 219,
|
||||
SpvOpEmitStreamVertex = 220,
|
||||
SpvOpEndStreamPrimitive = 221,
|
||||
SpvOpControlBarrier = 224,
|
||||
SpvOpMemoryBarrier = 225,
|
||||
SpvOpAtomicLoad = 227,
|
||||
SpvOpAtomicStore = 228,
|
||||
SpvOpAtomicExchange = 229,
|
||||
SpvOpAtomicCompareExchange = 230,
|
||||
SpvOpAtomicCompareExchangeWeak = 231,
|
||||
SpvOpAtomicIIncrement = 232,
|
||||
SpvOpAtomicIDecrement = 233,
|
||||
SpvOpAtomicIAdd = 234,
|
||||
SpvOpAtomicISub = 235,
|
||||
SpvOpAtomicIMin = 236,
|
||||
SpvOpAtomicUMin = 237,
|
||||
SpvOpAtomicIMax = 238,
|
||||
SpvOpAtomicUMax = 239,
|
||||
SpvOpAtomicAnd = 240,
|
||||
SpvOpAtomicOr = 241,
|
||||
SpvOpAtomicXor = 242,
|
||||
SpvOpPhi = 245,
|
||||
SpvOpLoopMerge = 246,
|
||||
SpvOpSelectionMerge = 247,
|
||||
SpvOpLabel = 248,
|
||||
SpvOpBranch = 249,
|
||||
SpvOpBranchConditional = 250,
|
||||
SpvOpSwitch = 251,
|
||||
SpvOpKill = 252,
|
||||
SpvOpReturn = 253,
|
||||
SpvOpReturnValue = 254,
|
||||
SpvOpUnreachable = 255,
|
||||
SpvOpLifetimeStart = 256,
|
||||
SpvOpLifetimeStop = 257,
|
||||
SpvOpAsyncGroupCopy = 259,
|
||||
SpvOpWaitGroupEvents = 260,
|
||||
SpvOpGroupAll = 261,
|
||||
SpvOpGroupAny = 262,
|
||||
SpvOpGroupBroadcast = 263,
|
||||
SpvOpGroupIAdd = 264,
|
||||
SpvOpGroupFAdd = 265,
|
||||
SpvOpGroupFMin = 266,
|
||||
SpvOpGroupUMin = 267,
|
||||
SpvOpGroupSMin = 268,
|
||||
SpvOpGroupFMax = 269,
|
||||
SpvOpGroupUMax = 270,
|
||||
SpvOpGroupSMax = 271,
|
||||
SpvOpReadPipe = 274,
|
||||
SpvOpWritePipe = 275,
|
||||
SpvOpReservedReadPipe = 276,
|
||||
SpvOpReservedWritePipe = 277,
|
||||
SpvOpReserveReadPipePackets = 278,
|
||||
SpvOpReserveWritePipePackets = 279,
|
||||
SpvOpCommitReadPipe = 280,
|
||||
SpvOpCommitWritePipe = 281,
|
||||
SpvOpIsValidReserveId = 282,
|
||||
SpvOpGetNumPipePackets = 283,
|
||||
SpvOpGetMaxPipePackets = 284,
|
||||
SpvOpGroupReserveReadPipePackets = 285,
|
||||
SpvOpGroupReserveWritePipePackets = 286,
|
||||
SpvOpGroupCommitReadPipe = 287,
|
||||
SpvOpGroupCommitWritePipe = 288,
|
||||
SpvOpEnqueueMarker = 291,
|
||||
SpvOpEnqueueKernel = 292,
|
||||
SpvOpGetKernelNDrangeSubGroupCount = 293,
|
||||
SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
|
||||
SpvOpGetKernelWorkGroupSize = 295,
|
||||
SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
|
||||
SpvOpRetainEvent = 297,
|
||||
SpvOpReleaseEvent = 298,
|
||||
SpvOpCreateUserEvent = 299,
|
||||
SpvOpIsValidEvent = 300,
|
||||
SpvOpSetUserEventStatus = 301,
|
||||
SpvOpCaptureEventProfilingInfo = 302,
|
||||
SpvOpGetDefaultQueue = 303,
|
||||
SpvOpBuildNDRange = 304,
|
||||
} SpvOp;
|
||||
|
||||
#endif // #ifndef spirv_H
|
||||
|
54
src/glsl/nir/spirv2nir.c
Normal file
54
src/glsl/nir/spirv2nir.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Jason Ekstrand (jason@jlekstrand.net)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* A simple executable that opens a SPIR-V shader, converts it to NIR, and
|
||||
* dumps out the result. This should be useful for testing the
|
||||
* spirv_to_nir code.
|
||||
*/
|
||||
|
||||
#include "nir_spirv.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd = open(argv[1], O_RDONLY);
|
||||
off_t len = lseek(fd, 0, SEEK_END);
|
||||
|
||||
assert(len % 4 == 0);
|
||||
size_t word_count = len / 4;
|
||||
|
||||
const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
assert(map != NULL);
|
||||
|
||||
nir_shader *shader = spirv_to_nir(map, word_count, NULL);
|
||||
nir_print_shader(shader, stderr);
|
||||
}
|
285
src/glsl/nir/spirv_glsl450_to_nir.c
Normal file
285
src/glsl/nir/spirv_glsl450_to_nir.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Jason Ekstrand (jason@jlekstrand.net)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "spirv_to_nir_private.h"
|
||||
|
||||
enum GLSL450Entrypoint {
|
||||
Round = 0,
|
||||
RoundEven = 1,
|
||||
Trunc = 2,
|
||||
Abs = 3,
|
||||
Sign = 4,
|
||||
Floor = 5,
|
||||
Ceil = 6,
|
||||
Fract = 7,
|
||||
|
||||
Radians = 8,
|
||||
Degrees = 9,
|
||||
Sin = 10,
|
||||
Cos = 11,
|
||||
Tan = 12,
|
||||
Asin = 13,
|
||||
Acos = 14,
|
||||
Atan = 15,
|
||||
Sinh = 16,
|
||||
Cosh = 17,
|
||||
Tanh = 18,
|
||||
Asinh = 19,
|
||||
Acosh = 20,
|
||||
Atanh = 21,
|
||||
Atan2 = 22,
|
||||
|
||||
Pow = 23,
|
||||
Exp = 24,
|
||||
Log = 25,
|
||||
Exp2 = 26,
|
||||
Log2 = 27,
|
||||
Sqrt = 28,
|
||||
InverseSqrt = 29,
|
||||
|
||||
Determinant = 30,
|
||||
MatrixInverse = 31,
|
||||
|
||||
Modf = 32, // second argument needs the OpVariable = , not an OpLoad
|
||||
Min = 33,
|
||||
Max = 34,
|
||||
Clamp = 35,
|
||||
Mix = 36,
|
||||
Step = 37,
|
||||
SmoothStep = 38,
|
||||
|
||||
FloatBitsToInt = 39,
|
||||
FloatBitsToUint = 40,
|
||||
IntBitsToFloat = 41,
|
||||
UintBitsToFloat = 42,
|
||||
|
||||
Fma = 43,
|
||||
Frexp = 44,
|
||||
Ldexp = 45,
|
||||
|
||||
PackSnorm4x8 = 46,
|
||||
PackUnorm4x8 = 47,
|
||||
PackSnorm2x16 = 48,
|
||||
PackUnorm2x16 = 49,
|
||||
PackHalf2x16 = 50,
|
||||
PackDouble2x32 = 51,
|
||||
UnpackSnorm2x16 = 52,
|
||||
UnpackUnorm2x16 = 53,
|
||||
UnpackHalf2x16 = 54,
|
||||
UnpackSnorm4x8 = 55,
|
||||
UnpackUnorm4x8 = 56,
|
||||
UnpackDouble2x32 = 57,
|
||||
|
||||
Length = 58,
|
||||
Distance = 59,
|
||||
Cross = 60,
|
||||
Normalize = 61,
|
||||
Ftransform = 62,
|
||||
FaceForward = 63,
|
||||
Reflect = 64,
|
||||
Refract = 65,
|
||||
|
||||
UaddCarry = 66,
|
||||
UsubBorrow = 67,
|
||||
UmulExtended = 68,
|
||||
ImulExtended = 69,
|
||||
BitfieldExtract = 70,
|
||||
BitfieldInsert = 71,
|
||||
BitfieldReverse = 72,
|
||||
BitCount = 73,
|
||||
FindLSB = 74,
|
||||
FindMSB = 75,
|
||||
|
||||
InterpolateAtCentroid = 76,
|
||||
InterpolateAtSample = 77,
|
||||
InterpolateAtOffset = 78,
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
static nir_ssa_def*
|
||||
build_length(nir_builder *b, nir_ssa_def *vec)
|
||||
{
|
||||
switch (vec->num_components) {
|
||||
case 1: return nir_fsqrt(b, nir_fmul(b, vec, vec));
|
||||
case 2: return nir_fsqrt(b, nir_fdot2(b, vec, vec));
|
||||
case 3: return nir_fsqrt(b, nir_fdot3(b, vec, vec));
|
||||
case 4: return nir_fsqrt(b, nir_fdot4(b, vec, vec));
|
||||
default:
|
||||
unreachable("Invalid number of components");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_glsl450_alu(struct vtn_builder *b, enum GLSL450Entrypoint entrypoint,
|
||||
const uint32_t *w, unsigned count)
|
||||
{
|
||||
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
|
||||
val->ssa = rzalloc(b, struct vtn_ssa_value);
|
||||
val->ssa->type = vtn_value(b, w[1], vtn_value_type_type)->type->type;
|
||||
|
||||
/* Collect the various SSA sources */
|
||||
unsigned num_inputs = count - 5;
|
||||
nir_ssa_def *src[3];
|
||||
for (unsigned i = 0; i < num_inputs; i++)
|
||||
src[i] = vtn_ssa_value(b, w[i + 5])->def;
|
||||
|
||||
nir_op op;
|
||||
switch (entrypoint) {
|
||||
case Round: op = nir_op_fround_even; break; /* TODO */
|
||||
case RoundEven: op = nir_op_fround_even; break;
|
||||
case Trunc: op = nir_op_ftrunc; break;
|
||||
case Abs: op = nir_op_fabs; break;
|
||||
case Sign: op = nir_op_fsign; break;
|
||||
case Floor: op = nir_op_ffloor; break;
|
||||
case Ceil: op = nir_op_fceil; break;
|
||||
case Fract: op = nir_op_ffract; break;
|
||||
case Radians:
|
||||
val->ssa->def = nir_fmul(&b->nb, src[0], nir_imm_float(&b->nb, 0.01745329251));
|
||||
return;
|
||||
case Degrees:
|
||||
val->ssa->def = nir_fmul(&b->nb, src[0], nir_imm_float(&b->nb, 57.2957795131));
|
||||
return;
|
||||
case Sin: op = nir_op_fsin; break;
|
||||
case Cos: op = nir_op_fcos; break;
|
||||
case Tan:
|
||||
val->ssa->def = nir_fdiv(&b->nb, nir_fsin(&b->nb, src[0]),
|
||||
nir_fcos(&b->nb, src[0]));
|
||||
return;
|
||||
case Pow: op = nir_op_fpow; break;
|
||||
case Exp2: op = nir_op_fexp2; break;
|
||||
case Log2: op = nir_op_flog2; break;
|
||||
case Sqrt: op = nir_op_fsqrt; break;
|
||||
case InverseSqrt: op = nir_op_frsq; break;
|
||||
|
||||
case Modf: op = nir_op_fmod; break;
|
||||
case Min: op = nir_op_fmin; break;
|
||||
case Max: op = nir_op_fmax; break;
|
||||
case Mix: op = nir_op_flrp; break;
|
||||
case Step:
|
||||
val->ssa->def = nir_sge(&b->nb, src[1], src[0]);
|
||||
return;
|
||||
|
||||
case FloatBitsToInt:
|
||||
case FloatBitsToUint:
|
||||
case IntBitsToFloat:
|
||||
case UintBitsToFloat:
|
||||
/* Probably going to be removed from the final version of the spec. */
|
||||
val->ssa->def = src[0];
|
||||
return;
|
||||
|
||||
case Fma: op = nir_op_ffma; break;
|
||||
case Ldexp: op = nir_op_ldexp; break;
|
||||
|
||||
/* Packing/Unpacking functions */
|
||||
case PackSnorm4x8: op = nir_op_pack_snorm_4x8; break;
|
||||
case PackUnorm4x8: op = nir_op_pack_unorm_4x8; break;
|
||||
case PackSnorm2x16: op = nir_op_pack_snorm_2x16; break;
|
||||
case PackUnorm2x16: op = nir_op_pack_unorm_2x16; break;
|
||||
case PackHalf2x16: op = nir_op_pack_half_2x16; break;
|
||||
case UnpackSnorm4x8: op = nir_op_unpack_snorm_4x8; break;
|
||||
case UnpackUnorm4x8: op = nir_op_unpack_unorm_4x8; break;
|
||||
case UnpackSnorm2x16: op = nir_op_unpack_snorm_2x16; break;
|
||||
case UnpackUnorm2x16: op = nir_op_unpack_unorm_2x16; break;
|
||||
case UnpackHalf2x16: op = nir_op_unpack_half_2x16; break;
|
||||
|
||||
case Length:
|
||||
val->ssa->def = build_length(&b->nb, src[0]);
|
||||
return;
|
||||
case Distance:
|
||||
val->ssa->def = build_length(&b->nb, nir_fsub(&b->nb, src[0], src[1]));
|
||||
return;
|
||||
case Normalize:
|
||||
val->ssa->def = nir_fdiv(&b->nb, src[0], build_length(&b->nb, src[0]));
|
||||
return;
|
||||
|
||||
case UaddCarry: op = nir_op_uadd_carry; break;
|
||||
case UsubBorrow: op = nir_op_usub_borrow; break;
|
||||
case BitfieldExtract: op = nir_op_ubitfield_extract; break; /* TODO */
|
||||
case BitfieldInsert: op = nir_op_bitfield_insert; break;
|
||||
case BitfieldReverse: op = nir_op_bitfield_reverse; break;
|
||||
case BitCount: op = nir_op_bit_count; break;
|
||||
case FindLSB: op = nir_op_find_lsb; break;
|
||||
case FindMSB: op = nir_op_ufind_msb; break; /* TODO */
|
||||
|
||||
case Exp:
|
||||
case Log:
|
||||
case Clamp:
|
||||
case Asin:
|
||||
case Acos:
|
||||
case Atan:
|
||||
case Atan2:
|
||||
case Sinh:
|
||||
case Cosh:
|
||||
case Tanh:
|
||||
case Asinh:
|
||||
case Acosh:
|
||||
case Atanh:
|
||||
case SmoothStep:
|
||||
case Frexp:
|
||||
case PackDouble2x32:
|
||||
case UnpackDouble2x32:
|
||||
case Cross:
|
||||
case Ftransform:
|
||||
case FaceForward:
|
||||
case Reflect:
|
||||
case Refract:
|
||||
case UmulExtended:
|
||||
case ImulExtended:
|
||||
default:
|
||||
unreachable("Unhandled opcode");
|
||||
}
|
||||
|
||||
nir_alu_instr *instr = nir_alu_instr_create(b->shader, op);
|
||||
nir_ssa_dest_init(&instr->instr, &instr->dest.dest,
|
||||
glsl_get_vector_elements(val->ssa->type), val->name);
|
||||
val->ssa->def = &instr->dest.dest.ssa;
|
||||
|
||||
for (unsigned i = 0; i < nir_op_infos[op].num_inputs; i++)
|
||||
instr->src[i].src = nir_src_for_ssa(src[i]);
|
||||
|
||||
nir_builder_instr_insert(&b->nb, &instr->instr);
|
||||
}
|
||||
|
||||
bool
|
||||
vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
|
||||
const uint32_t *words, unsigned count)
|
||||
{
|
||||
switch ((enum GLSL450Entrypoint)ext_opcode) {
|
||||
case Determinant:
|
||||
case MatrixInverse:
|
||||
case InterpolateAtCentroid:
|
||||
case InterpolateAtSample:
|
||||
case InterpolateAtOffset:
|
||||
unreachable("Unhandled opcode");
|
||||
|
||||
default:
|
||||
handle_glsl450_alu(b, (enum GLSL450Entrypoint)ext_opcode, words, count);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
2822
src/glsl/nir/spirv_to_nir.c
Normal file
2822
src/glsl/nir/spirv_to_nir.c
Normal file
File diff suppressed because it is too large
Load Diff
215
src/glsl/nir/spirv_to_nir_private.h
Normal file
215
src/glsl/nir/spirv_to_nir_private.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Jason Ekstrand (jason@jlekstrand.net)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nir_spirv.h"
|
||||
#include "nir_builder.h"
|
||||
#include "spirv.h"
|
||||
|
||||
struct vtn_builder;
|
||||
struct vtn_decoration;
|
||||
|
||||
enum vtn_value_type {
|
||||
vtn_value_type_invalid = 0,
|
||||
vtn_value_type_undef,
|
||||
vtn_value_type_string,
|
||||
vtn_value_type_decoration_group,
|
||||
vtn_value_type_type,
|
||||
vtn_value_type_constant,
|
||||
vtn_value_type_deref,
|
||||
vtn_value_type_function,
|
||||
vtn_value_type_block,
|
||||
vtn_value_type_ssa,
|
||||
vtn_value_type_extension,
|
||||
};
|
||||
|
||||
struct vtn_block {
|
||||
/* Merge opcode if this block contains a merge; SpvOpNop otherwise. */
|
||||
SpvOp merge_op;
|
||||
uint32_t merge_block_id;
|
||||
const uint32_t *label;
|
||||
const uint32_t *branch;
|
||||
nir_block *block;
|
||||
};
|
||||
|
||||
struct vtn_function {
|
||||
struct exec_node node;
|
||||
|
||||
nir_function_overload *overload;
|
||||
struct vtn_block *start_block;
|
||||
|
||||
const uint32_t *end;
|
||||
};
|
||||
|
||||
typedef bool (*vtn_instruction_handler)(struct vtn_builder *, uint32_t,
|
||||
const uint32_t *, unsigned);
|
||||
|
||||
struct vtn_ssa_value {
|
||||
union {
|
||||
nir_ssa_def *def;
|
||||
struct vtn_ssa_value **elems;
|
||||
};
|
||||
|
||||
/* For matrices, a transposed version of the value, or NULL if it hasn't
|
||||
* been computed
|
||||
*/
|
||||
struct vtn_ssa_value *transposed;
|
||||
|
||||
const struct glsl_type *type;
|
||||
};
|
||||
|
||||
struct vtn_type {
|
||||
const struct glsl_type *type;
|
||||
|
||||
/* for matrices, whether the matrix is stored row-major */
|
||||
bool row_major;
|
||||
|
||||
/* for structs, the offset of each member */
|
||||
unsigned *offsets;
|
||||
|
||||
/* for arrays and matrices, the array stride */
|
||||
unsigned stride;
|
||||
|
||||
/* for arrays, the vtn_type for the elements of the array */
|
||||
struct vtn_type *array_element;
|
||||
|
||||
/* for structures, the vtn_type for each member */
|
||||
struct vtn_type **members;
|
||||
|
||||
/* Whether this type, or a parent type, has been decorated as a builtin */
|
||||
bool is_builtin;
|
||||
|
||||
SpvBuiltIn builtin;
|
||||
};
|
||||
|
||||
struct vtn_value {
|
||||
enum vtn_value_type value_type;
|
||||
const char *name;
|
||||
struct vtn_decoration *decoration;
|
||||
union {
|
||||
void *ptr;
|
||||
char *str;
|
||||
struct vtn_type *type;
|
||||
struct {
|
||||
nir_constant *constant;
|
||||
const struct glsl_type *const_type;
|
||||
};
|
||||
struct {
|
||||
nir_deref_var *deref;
|
||||
struct vtn_type *deref_type;
|
||||
};
|
||||
struct vtn_function *func;
|
||||
struct vtn_block *block;
|
||||
struct vtn_ssa_value *ssa;
|
||||
vtn_instruction_handler ext_handler;
|
||||
};
|
||||
};
|
||||
|
||||
struct vtn_decoration {
|
||||
struct vtn_decoration *next;
|
||||
int member; /* -1 if not a member decoration */
|
||||
const uint32_t *literals;
|
||||
struct vtn_value *group;
|
||||
SpvDecoration decoration;
|
||||
};
|
||||
|
||||
struct vtn_builder {
|
||||
nir_builder nb;
|
||||
|
||||
nir_shader *shader;
|
||||
nir_function_impl *impl;
|
||||
struct vtn_block *block;
|
||||
|
||||
/*
|
||||
* In SPIR-V, constants are global, whereas in NIR, the load_const
|
||||
* instruction we use is per-function. So while we parse each function, we
|
||||
* keep a hash table of constants we've resolved to nir_ssa_value's so
|
||||
* far, and we lazily resolve them when we see them used in a function.
|
||||
*/
|
||||
struct hash_table *const_table;
|
||||
|
||||
/*
|
||||
* Map from nir_block to the vtn_block which ends with it -- used for
|
||||
* handling phi nodes.
|
||||
*/
|
||||
struct hash_table *block_table;
|
||||
|
||||
/*
|
||||
* NIR variable for each SPIR-V builtin.
|
||||
*/
|
||||
nir_variable *builtins[42]; /* XXX need symbolic constant from SPIR-V header */
|
||||
|
||||
unsigned value_id_bound;
|
||||
struct vtn_value *values;
|
||||
|
||||
SpvExecutionModel execution_model;
|
||||
struct vtn_value *entry_point;
|
||||
|
||||
struct vtn_function *func;
|
||||
struct exec_list functions;
|
||||
};
|
||||
|
||||
static inline struct vtn_value *
|
||||
vtn_push_value(struct vtn_builder *b, uint32_t value_id,
|
||||
enum vtn_value_type value_type)
|
||||
{
|
||||
assert(value_id < b->value_id_bound);
|
||||
assert(b->values[value_id].value_type == vtn_value_type_invalid);
|
||||
|
||||
b->values[value_id].value_type = value_type;
|
||||
|
||||
return &b->values[value_id];
|
||||
}
|
||||
|
||||
static inline struct vtn_value *
|
||||
vtn_untyped_value(struct vtn_builder *b, uint32_t value_id)
|
||||
{
|
||||
assert(value_id < b->value_id_bound);
|
||||
return &b->values[value_id];
|
||||
}
|
||||
|
||||
static inline struct vtn_value *
|
||||
vtn_value(struct vtn_builder *b, uint32_t value_id,
|
||||
enum vtn_value_type value_type)
|
||||
{
|
||||
struct vtn_value *val = vtn_untyped_value(b, value_id);
|
||||
assert(val->value_type == value_type);
|
||||
return val;
|
||||
}
|
||||
|
||||
struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
|
||||
|
||||
typedef void (*vtn_decoration_foreach_cb)(struct vtn_builder *,
|
||||
struct vtn_value *,
|
||||
int member,
|
||||
const struct vtn_decoration *,
|
||||
void *);
|
||||
|
||||
void vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,
|
||||
vtn_decoration_foreach_cb cb, void *data);
|
||||
|
||||
bool vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
|
||||
const uint32_t *words, unsigned count);
|
@@ -23,6 +23,8 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "main/config.h"
|
||||
|
||||
#ifndef SHADER_ENUMS_H
|
||||
#define SHADER_ENUMS_H
|
||||
|
||||
@@ -184,4 +186,209 @@ enum glsl_interp_qualifier
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Indexes for vertex program attributes.
|
||||
* GL_NV_vertex_program aliases generic attributes over the conventional
|
||||
* attributes. In GL_ARB_vertex_program shader the aliasing is optional.
|
||||
* In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
|
||||
* generic attributes are distinct/separate).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
VERT_ATTRIB_POS = 0,
|
||||
VERT_ATTRIB_WEIGHT = 1,
|
||||
VERT_ATTRIB_NORMAL = 2,
|
||||
VERT_ATTRIB_COLOR0 = 3,
|
||||
VERT_ATTRIB_COLOR1 = 4,
|
||||
VERT_ATTRIB_FOG = 5,
|
||||
VERT_ATTRIB_COLOR_INDEX = 6,
|
||||
VERT_ATTRIB_EDGEFLAG = 7,
|
||||
VERT_ATTRIB_TEX0 = 8,
|
||||
VERT_ATTRIB_TEX1 = 9,
|
||||
VERT_ATTRIB_TEX2 = 10,
|
||||
VERT_ATTRIB_TEX3 = 11,
|
||||
VERT_ATTRIB_TEX4 = 12,
|
||||
VERT_ATTRIB_TEX5 = 13,
|
||||
VERT_ATTRIB_TEX6 = 14,
|
||||
VERT_ATTRIB_TEX7 = 15,
|
||||
VERT_ATTRIB_POINT_SIZE = 16,
|
||||
VERT_ATTRIB_GENERIC0 = 17,
|
||||
VERT_ATTRIB_GENERIC1 = 18,
|
||||
VERT_ATTRIB_GENERIC2 = 19,
|
||||
VERT_ATTRIB_GENERIC3 = 20,
|
||||
VERT_ATTRIB_GENERIC4 = 21,
|
||||
VERT_ATTRIB_GENERIC5 = 22,
|
||||
VERT_ATTRIB_GENERIC6 = 23,
|
||||
VERT_ATTRIB_GENERIC7 = 24,
|
||||
VERT_ATTRIB_GENERIC8 = 25,
|
||||
VERT_ATTRIB_GENERIC9 = 26,
|
||||
VERT_ATTRIB_GENERIC10 = 27,
|
||||
VERT_ATTRIB_GENERIC11 = 28,
|
||||
VERT_ATTRIB_GENERIC12 = 29,
|
||||
VERT_ATTRIB_GENERIC13 = 30,
|
||||
VERT_ATTRIB_GENERIC14 = 31,
|
||||
VERT_ATTRIB_GENERIC15 = 32,
|
||||
VERT_ATTRIB_MAX = 33
|
||||
} gl_vert_attrib;
|
||||
|
||||
/**
|
||||
* Symbolic constats to help iterating over
|
||||
* specific blocks of vertex attributes.
|
||||
*
|
||||
* VERT_ATTRIB_FF
|
||||
* includes all fixed function attributes as well as
|
||||
* the aliased GL_NV_vertex_program shader attributes.
|
||||
* VERT_ATTRIB_TEX
|
||||
* include the classic texture coordinate attributes.
|
||||
* Is a subset of VERT_ATTRIB_FF.
|
||||
* VERT_ATTRIB_GENERIC
|
||||
* include the OpenGL 2.0+ GLSL generic shader attributes.
|
||||
* These alias the generic GL_ARB_vertex_shader attributes.
|
||||
*/
|
||||
#define VERT_ATTRIB_FF(i) (VERT_ATTRIB_POS + (i))
|
||||
#define VERT_ATTRIB_FF_MAX VERT_ATTRIB_GENERIC0
|
||||
|
||||
#define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i))
|
||||
#define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS
|
||||
|
||||
#define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i))
|
||||
#define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS
|
||||
|
||||
/**
|
||||
* Bitflags for vertex attributes.
|
||||
* These are used in bitfields in many places.
|
||||
*/
|
||||
/*@{*/
|
||||
#define VERT_BIT_POS BITFIELD64_BIT(VERT_ATTRIB_POS)
|
||||
#define VERT_BIT_WEIGHT BITFIELD64_BIT(VERT_ATTRIB_WEIGHT)
|
||||
#define VERT_BIT_NORMAL BITFIELD64_BIT(VERT_ATTRIB_NORMAL)
|
||||
#define VERT_BIT_COLOR0 BITFIELD64_BIT(VERT_ATTRIB_COLOR0)
|
||||
#define VERT_BIT_COLOR1 BITFIELD64_BIT(VERT_ATTRIB_COLOR1)
|
||||
#define VERT_BIT_FOG BITFIELD64_BIT(VERT_ATTRIB_FOG)
|
||||
#define VERT_BIT_COLOR_INDEX BITFIELD64_BIT(VERT_ATTRIB_COLOR_INDEX)
|
||||
#define VERT_BIT_EDGEFLAG BITFIELD64_BIT(VERT_ATTRIB_EDGEFLAG)
|
||||
#define VERT_BIT_TEX0 BITFIELD64_BIT(VERT_ATTRIB_TEX0)
|
||||
#define VERT_BIT_TEX1 BITFIELD64_BIT(VERT_ATTRIB_TEX1)
|
||||
#define VERT_BIT_TEX2 BITFIELD64_BIT(VERT_ATTRIB_TEX2)
|
||||
#define VERT_BIT_TEX3 BITFIELD64_BIT(VERT_ATTRIB_TEX3)
|
||||
#define VERT_BIT_TEX4 BITFIELD64_BIT(VERT_ATTRIB_TEX4)
|
||||
#define VERT_BIT_TEX5 BITFIELD64_BIT(VERT_ATTRIB_TEX5)
|
||||
#define VERT_BIT_TEX6 BITFIELD64_BIT(VERT_ATTRIB_TEX6)
|
||||
#define VERT_BIT_TEX7 BITFIELD64_BIT(VERT_ATTRIB_TEX7)
|
||||
#define VERT_BIT_POINT_SIZE BITFIELD64_BIT(VERT_ATTRIB_POINT_SIZE)
|
||||
#define VERT_BIT_GENERIC0 BITFIELD64_BIT(VERT_ATTRIB_GENERIC0)
|
||||
|
||||
#define VERT_BIT(i) BITFIELD64_BIT(i)
|
||||
#define VERT_BIT_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_MAX)
|
||||
|
||||
#define VERT_BIT_FF(i) VERT_BIT(i)
|
||||
#define VERT_BIT_FF_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_FF_MAX)
|
||||
#define VERT_BIT_TEX(i) VERT_BIT(VERT_ATTRIB_TEX(i))
|
||||
#define VERT_BIT_TEX_ALL \
|
||||
BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX)
|
||||
|
||||
#define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i))
|
||||
#define VERT_BIT_GENERIC_ALL \
|
||||
BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX)
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* Indexes for vertex shader outputs, geometry shader inputs/outputs, and
|
||||
* fragment shader inputs.
|
||||
*
|
||||
* Note that some of these values are not available to all pipeline stages.
|
||||
*
|
||||
* When this enum is updated, the following code must be updated too:
|
||||
* - vertResults (in prog_print.c's arb_output_attrib_string())
|
||||
* - fragAttribs (in prog_print.c's arb_input_attrib_string())
|
||||
* - _mesa_varying_slot_in_fs()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
VARYING_SLOT_POS,
|
||||
VARYING_SLOT_COL0, /* COL0 and COL1 must be contiguous */
|
||||
VARYING_SLOT_COL1,
|
||||
VARYING_SLOT_FOGC,
|
||||
VARYING_SLOT_TEX0, /* TEX0-TEX7 must be contiguous */
|
||||
VARYING_SLOT_TEX1,
|
||||
VARYING_SLOT_TEX2,
|
||||
VARYING_SLOT_TEX3,
|
||||
VARYING_SLOT_TEX4,
|
||||
VARYING_SLOT_TEX5,
|
||||
VARYING_SLOT_TEX6,
|
||||
VARYING_SLOT_TEX7,
|
||||
VARYING_SLOT_PSIZ, /* Does not appear in FS */
|
||||
VARYING_SLOT_BFC0, /* Does not appear in FS */
|
||||
VARYING_SLOT_BFC1, /* Does not appear in FS */
|
||||
VARYING_SLOT_EDGE, /* Does not appear in FS */
|
||||
VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */ VARYING_SLOT_CLIP_DIST0,
|
||||
VARYING_SLOT_CLIP_DIST1,
|
||||
VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */
|
||||
VARYING_SLOT_LAYER, /* Appears as VS or GS output */
|
||||
VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */
|
||||
VARYING_SLOT_FACE, /* FS only */
|
||||
VARYING_SLOT_PNTC, /* FS only */
|
||||
VARYING_SLOT_VAR0, /* First generic varying slot */
|
||||
VARYING_SLOT_MAX = VARYING_SLOT_VAR0 + MAX_VARYING
|
||||
} gl_varying_slot;
|
||||
|
||||
|
||||
/**
|
||||
* Bitflags for varying slots.
|
||||
*/
|
||||
/*@{*/
|
||||
#define VARYING_BIT_POS BITFIELD64_BIT(VARYING_SLOT_POS)
|
||||
#define VARYING_BIT_COL0 BITFIELD64_BIT(VARYING_SLOT_COL0)
|
||||
#define VARYING_BIT_COL1 BITFIELD64_BIT(VARYING_SLOT_COL1)
|
||||
#define VARYING_BIT_FOGC BITFIELD64_BIT(VARYING_SLOT_FOGC)
|
||||
#define VARYING_BIT_TEX0 BITFIELD64_BIT(VARYING_SLOT_TEX0)
|
||||
#define VARYING_BIT_TEX1 BITFIELD64_BIT(VARYING_SLOT_TEX1)
|
||||
#define VARYING_BIT_TEX2 BITFIELD64_BIT(VARYING_SLOT_TEX2)
|
||||
#define VARYING_BIT_TEX3 BITFIELD64_BIT(VARYING_SLOT_TEX3)
|
||||
#define VARYING_BIT_TEX4 BITFIELD64_BIT(VARYING_SLOT_TEX4)
|
||||
#define VARYING_BIT_TEX5 BITFIELD64_BIT(VARYING_SLOT_TEX5)
|
||||
#define VARYING_BIT_TEX6 BITFIELD64_BIT(VARYING_SLOT_TEX6)
|
||||
#define VARYING_BIT_TEX7 BITFIELD64_BIT(VARYING_SLOT_TEX7)
|
||||
#define VARYING_BIT_TEX(U) BITFIELD64_BIT(VARYING_SLOT_TEX0 + (U))
|
||||
#define VARYING_BITS_TEX_ANY BITFIELD64_RANGE(VARYING_SLOT_TEX0, \
|
||||
MAX_TEXTURE_COORD_UNITS)
|
||||
#define VARYING_BIT_PSIZ BITFIELD64_BIT(VARYING_SLOT_PSIZ)
|
||||
#define VARYING_BIT_BFC0 BITFIELD64_BIT(VARYING_SLOT_BFC0)
|
||||
#define VARYING_BIT_BFC1 BITFIELD64_BIT(VARYING_SLOT_BFC1)
|
||||
#define VARYING_BIT_EDGE BITFIELD64_BIT(VARYING_SLOT_EDGE)
|
||||
#define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX)
|
||||
#define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0)
|
||||
#define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1)
|
||||
#define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID)
|
||||
#define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER)
|
||||
#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
|
||||
#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
|
||||
#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
|
||||
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* Fragment program results
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FRAG_RESULT_DEPTH = 0,
|
||||
FRAG_RESULT_STENCIL = 1,
|
||||
/* If a single color should be written to all render targets, this
|
||||
* register is written. No FRAG_RESULT_DATAn will be written.
|
||||
*/
|
||||
FRAG_RESULT_COLOR = 2,
|
||||
FRAG_RESULT_SAMPLE_MASK = 3,
|
||||
|
||||
/* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n]
|
||||
* or ARB_fragment_program fragment.color[n]) color results. If
|
||||
* any are written, FRAG_RESULT_COLOR will not be written.
|
||||
*/
|
||||
FRAG_RESULT_DATA0 = 4,
|
||||
FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
|
||||
} gl_frag_result;
|
||||
|
||||
|
||||
#endif /* SHADER_ENUMS_H */
|
||||
|
@@ -34,6 +34,12 @@
|
||||
#include <string.h>
|
||||
#include "util/ralloc.h"
|
||||
|
||||
extern "C" void
|
||||
_mesa_error_no_memory(const char *caller)
|
||||
{
|
||||
fprintf(stderr, "Mesa error: out of memory in %s", caller);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_warning(struct gl_context *ctx, const char *fmt, ...)
|
||||
{
|
||||
|
@@ -40,8 +40,11 @@ gl_HEADERS = $(top_srcdir)/include/GL/*.h
|
||||
|
||||
.PHONY: main/git_sha1.h.tmp
|
||||
main/git_sha1.h.tmp:
|
||||
@# Don't assume that $(top_srcdir)/.git is a directory. It may be
|
||||
@# a gitlink file if $(top_srcdir) is a submodule checkout or a linked
|
||||
@# worktree.
|
||||
@touch main/git_sha1.h.tmp
|
||||
@if test -d $(top_srcdir)/.git; then \
|
||||
@if test -e $(top_srcdir)/.git; then \
|
||||
if which git > /dev/null; then \
|
||||
git --git-dir=$(top_srcdir)/.git log -n 1 --oneline | \
|
||||
sed 's/^\([^ ]*\) .*/#define MESA_GIT_SHA1 "git-\1"/' \
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include "main/glheader.h"
|
||||
#include "main/compiler.h"
|
||||
#include "glapi/glapi.h"
|
||||
@@ -33,12 +34,14 @@ _glapi_check_multithread(void)
|
||||
|
||||
PUBLIC void
|
||||
_glapi_set_context(void *context)
|
||||
{}
|
||||
{
|
||||
_glapi_Context = context;
|
||||
}
|
||||
|
||||
PUBLIC void *
|
||||
_glapi_get_context(void)
|
||||
{
|
||||
return 0;
|
||||
return _glapi_Context;
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
@@ -84,7 +87,7 @@ _glapi_set_nop_handler(_glapi_nop_handler_proc func)
|
||||
PUBLIC struct _glapi_table *
|
||||
_glapi_new_nop_table(unsigned num_entries)
|
||||
{
|
||||
return NULL;
|
||||
return malloc(16);
|
||||
}
|
||||
|
||||
#ifndef NO_MAIN
|
||||
|
@@ -41,7 +41,7 @@ AM_CFLAGS = \
|
||||
|
||||
AM_CXXFLAGS = $(AM_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libi965_dri.la
|
||||
noinst_LTLIBRARIES = libi965_dri.la libi965_compiler.la
|
||||
libi965_dri_la_SOURCES = $(i965_FILES)
|
||||
libi965_dri_la_LIBADD = $(INTEL_LIBS)
|
||||
|
||||
@@ -55,6 +55,16 @@ TEST_LIBS = \
|
||||
$(CLOCK_LIB) \
|
||||
../common/libdri_test_stubs.la
|
||||
|
||||
libi965_compiler_la_SOURCES = $(i965_FILES)
|
||||
libi965_compiler_la_LIBADD = $(INTEL_LIBS) \
|
||||
../common/libdricommon.la \
|
||||
../common/libxmlconfig.la \
|
||||
../common/libmegadriver_stub.la \
|
||||
../../../libmesa.la \
|
||||
$(DRI_LIB_DEPS) \
|
||||
$(CLOCK_LIB) \
|
||||
../common/libdri_test_stubs.la -lm
|
||||
|
||||
TESTS = \
|
||||
test_fs_cmod_propagation \
|
||||
test_fs_saturate_propagation \
|
||||
|
@@ -311,7 +311,7 @@ brw_init_driver_functions(struct brw_context *brw,
|
||||
functions->GetSamplePosition = gen6_get_sample_position;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
brw_initialize_context_constants(struct brw_context *brw)
|
||||
{
|
||||
struct gl_context *ctx = &brw->ctx;
|
||||
@@ -390,7 +390,8 @@ brw_initialize_context_constants(struct brw_context *brw)
|
||||
int max_samples;
|
||||
const int *msaa_modes = intel_supported_msaa_modes(brw->intelScreen);
|
||||
const int clamp_max_samples =
|
||||
driQueryOptioni(&brw->optionCache, "clamp_max_samples");
|
||||
brw->optionCache.info != NULL ?
|
||||
driQueryOptioni(&brw->optionCache, "clamp_max_samples") : -1;
|
||||
|
||||
if (clamp_max_samples < 0) {
|
||||
max_samples = msaa_modes[0];
|
||||
@@ -801,6 +802,7 @@ brwCreateContext(gl_api api,
|
||||
|
||||
intel_batchbuffer_init(brw);
|
||||
|
||||
#if 0
|
||||
if (brw->gen >= 6) {
|
||||
/* Create a new hardware context. Using a hardware context means that
|
||||
* our GPU state will be saved/restored on context switch, allowing us
|
||||
@@ -819,6 +821,7 @@ brwCreateContext(gl_api api,
|
||||
}
|
||||
|
||||
brw_init_state(brw);
|
||||
#endif
|
||||
|
||||
intelInitExtensions(ctx);
|
||||
|
||||
@@ -882,8 +885,10 @@ brwCreateContext(gl_api api,
|
||||
|
||||
_mesa_compute_version(ctx);
|
||||
|
||||
#if 0
|
||||
_mesa_initialize_dispatch_tables(ctx);
|
||||
_mesa_initialize_vbo_vtxfmt(ctx);
|
||||
#endif
|
||||
|
||||
if (ctx->Extensions.AMD_performance_monitor) {
|
||||
brw_init_performance_monitors(brw);
|
||||
|
@@ -359,6 +359,12 @@ struct brw_stage_prog_data {
|
||||
/** @} */
|
||||
} binding_table;
|
||||
|
||||
uint32_t *map_entries;
|
||||
struct {
|
||||
uint32_t index_count;
|
||||
uint32_t *index;
|
||||
} bind_map[8]; /* MAX_SETS from vulkan/private.h */
|
||||
|
||||
GLuint nr_params; /**< number of float params/constants */
|
||||
GLuint nr_pull_params;
|
||||
|
||||
@@ -1994,6 +2000,15 @@ gen6_upload_push_constants(struct brw_context *brw,
|
||||
struct brw_stage_state *stage_state,
|
||||
enum aub_state_struct_type type);
|
||||
|
||||
struct intel_screen *intel_screen_create(int fd);
|
||||
void intel_screen_destroy(struct intel_screen *screen);
|
||||
|
||||
struct brw_context *intel_context_create(struct intel_screen *screen);
|
||||
void intel_context_destroy(struct brw_context *brw);
|
||||
|
||||
void
|
||||
brw_initialize_context_constants(struct brw_context *brw);
|
||||
|
||||
bool
|
||||
gen9_use_linear_1d_layout(const struct brw_context *brw,
|
||||
const struct intel_mipmap_tree *mt);
|
||||
|
@@ -55,7 +55,7 @@ brw_cs_prog_data_compare(const void *in_a, const void *in_b)
|
||||
}
|
||||
|
||||
|
||||
static const unsigned *
|
||||
const unsigned *
|
||||
brw_cs_emit(struct brw_context *brw,
|
||||
void *mem_ctx,
|
||||
const struct brw_cs_prog_key *key,
|
||||
|
@@ -41,6 +41,15 @@ bool brw_cs_prog_data_compare(const void *a, const void *b);
|
||||
void
|
||||
brw_upload_cs_prog(struct brw_context *brw);
|
||||
|
||||
const unsigned *
|
||||
brw_cs_emit(struct brw_context *brw,
|
||||
void *mem_ctx,
|
||||
const struct brw_cs_prog_key *key,
|
||||
struct brw_cs_prog_data *prog_data,
|
||||
struct gl_compute_program *cp,
|
||||
struct gl_shader_program *prog,
|
||||
unsigned *final_assembly_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -57,6 +57,7 @@
|
||||
# define GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL (0 << 8)
|
||||
# define GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM (1 << 8)
|
||||
|
||||
#ifndef _3DPRIM_POINTLIST /* FIXME: Avoid clashing with defines from bdw_pack.h */
|
||||
#define _3DPRIM_POINTLIST 0x01
|
||||
#define _3DPRIM_LINELIST 0x02
|
||||
#define _3DPRIM_LINESTRIP 0x03
|
||||
@@ -78,6 +79,7 @@
|
||||
#define _3DPRIM_LINESTRIP_BF 0x13
|
||||
#define _3DPRIM_LINESTRIP_CONT_BF 0x14
|
||||
#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15
|
||||
#endif
|
||||
|
||||
/* We use this offset to be able to pass native primitive types in struct
|
||||
* _mesa_prim::mode. Native primitive types are BRW_PRIM_OFFSET +
|
||||
|
@@ -353,3 +353,15 @@ brw_get_device_info(int devid, int revision)
|
||||
|
||||
return devinfo;
|
||||
}
|
||||
|
||||
const char *
|
||||
brw_get_device_name(int devid)
|
||||
{
|
||||
switch (devid) {
|
||||
#undef CHIPSET
|
||||
#define CHIPSET(id, family, name) case id: return name;
|
||||
#include "pci_ids/i965_pci_ids.h"
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@@ -85,3 +85,4 @@ struct brw_device_info
|
||||
};
|
||||
|
||||
const struct brw_device_info *brw_get_device_info(int devid, int revision);
|
||||
const char *brw_get_device_name(int devid);
|
||||
|
@@ -525,6 +525,7 @@ fs_visitor::type_size(const struct glsl_type *type)
|
||||
case GLSL_TYPE_ERROR:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_DOUBLE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
unreachable("not reached");
|
||||
}
|
||||
|
||||
@@ -1460,6 +1461,10 @@ fs_visitor::assign_vs_urb_setup()
|
||||
unsigned vue_entries =
|
||||
MAX2(count, vs_prog_data->base.vue_map.num_slots);
|
||||
|
||||
/* URB entry size is counted in units of 64 bytes (for the 3DSTATE_URB_VS
|
||||
* command). Each attribute is 16 bytes (4 floats/dwords), so each unit
|
||||
* fits four attributes.
|
||||
*/
|
||||
vs_prog_data->base.urb_entry_size = ALIGN(vue_entries, 4) / 4;
|
||||
vs_prog_data->base.urb_read_length = (count + 1) / 2;
|
||||
|
||||
@@ -2590,9 +2595,22 @@ fs_visitor::emit_repclear_shader()
|
||||
brw_wm_prog_key *key = (brw_wm_prog_key*) this->key;
|
||||
int base_mrf = 1;
|
||||
int color_mrf = base_mrf + 2;
|
||||
fs_inst *mov;
|
||||
|
||||
fs_inst *mov = bld.exec_all().MOV(vec4(brw_message_reg(color_mrf)),
|
||||
fs_reg(UNIFORM, 0, BRW_REGISTER_TYPE_F));
|
||||
if (uniforms == 1) {
|
||||
mov = bld.exec_all().MOV(vec4(brw_message_reg(color_mrf)),
|
||||
fs_reg(UNIFORM, 0, BRW_REGISTER_TYPE_F));
|
||||
} else {
|
||||
struct brw_reg reg =
|
||||
brw_reg(BRW_GENERAL_REGISTER_FILE,
|
||||
2, 3, 0, 0, BRW_REGISTER_TYPE_F,
|
||||
BRW_VERTICAL_STRIDE_8,
|
||||
BRW_WIDTH_2,
|
||||
BRW_HORIZONTAL_STRIDE_4, BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
|
||||
|
||||
mov = bld.exec_all().MOV(vec4(brw_message_reg(color_mrf)),
|
||||
fs_reg(reg));
|
||||
}
|
||||
|
||||
fs_inst *write;
|
||||
if (key->nr_color_regions == 1) {
|
||||
@@ -2621,8 +2639,10 @@ fs_visitor::emit_repclear_shader()
|
||||
assign_curb_setup();
|
||||
|
||||
/* Now that we have the uniform assigned, go ahead and force it to a vec4. */
|
||||
assert(mov->src[0].file == HW_REG);
|
||||
mov->src[0] = brw_vec4_grf(mov->src[0].fixed_hw_reg.nr, 0);
|
||||
if (uniforms == 1) {
|
||||
assert(mov->src[0].file == HW_REG);
|
||||
mov->src[0] = brw_vec4_grf(mov->src[0].fixed_hw_reg.nr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3805,7 +3825,8 @@ fs_visitor::run_vs(gl_clip_plane *clip_planes)
|
||||
{
|
||||
assert(stage == MESA_SHADER_VERTEX);
|
||||
|
||||
assign_common_binding_table_offsets(0);
|
||||
if (prog_data->map_entries == NULL)
|
||||
assign_common_binding_table_offsets(0);
|
||||
setup_vs_payload();
|
||||
|
||||
if (shader_time_index >= 0)
|
||||
@@ -3842,9 +3863,8 @@ fs_visitor::run_fs(bool do_rep_send)
|
||||
|
||||
assert(stage == MESA_SHADER_FRAGMENT);
|
||||
|
||||
sanity_param_count = prog->Parameters->NumParameters;
|
||||
|
||||
assign_binding_table_offsets();
|
||||
if (prog_data->map_entries == NULL)
|
||||
assign_binding_table_offsets();
|
||||
|
||||
if (devinfo->gen >= 6)
|
||||
setup_payload_gen6();
|
||||
@@ -3914,13 +3934,6 @@ fs_visitor::run_fs(bool do_rep_send)
|
||||
else
|
||||
wm_prog_data->reg_blocks_16 = brw_register_blocks(grf_used);
|
||||
|
||||
/* If any state parameters were appended, then ParameterValues could have
|
||||
* been realloced, in which case the driver uniform storage set up by
|
||||
* _mesa_associate_uniform_storage() would point to freed memory. Make
|
||||
* sure that didn't happen.
|
||||
*/
|
||||
assert(sanity_param_count == prog->Parameters->NumParameters);
|
||||
|
||||
return !failed;
|
||||
}
|
||||
|
||||
@@ -3993,7 +4006,7 @@ brw_wm_fs_emit(struct brw_context *brw,
|
||||
if (prog)
|
||||
shader = (brw_shader *) prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
|
||||
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_WM))
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_WM) && shader->base.ir)
|
||||
brw_dump_ir("fragment", prog, &shader->base, &fp->Base);
|
||||
|
||||
int st_index8 = -1, st_index16 = -1;
|
||||
|
@@ -1368,9 +1368,19 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
|
||||
fs_reg surf_index;
|
||||
|
||||
if (const_index) {
|
||||
surf_index = fs_reg(stage_prog_data->binding_table.ubo_start +
|
||||
const_index->u[0]);
|
||||
uint32_t index = const_index->u[0];
|
||||
uint32_t set = shader->base.UniformBlocks[index].Set;
|
||||
uint32_t binding = shader->base.UniformBlocks[index].Binding;
|
||||
|
||||
/* FIXME: We should probably assert here, but dota2 seems to hit
|
||||
* it and we'd like to keep going.
|
||||
*/
|
||||
if (binding >= stage_prog_data->bind_map[set].index_count)
|
||||
binding = 0;
|
||||
|
||||
surf_index = fs_reg(stage_prog_data->bind_map[set].index[binding]);
|
||||
} else {
|
||||
assert(0 && "need more info from the ir for this.");
|
||||
/* The block index is not a constant. Evaluate the index expression
|
||||
* per-channel and add the base UBO index; we have to select a value
|
||||
* from any live channel.
|
||||
@@ -1587,7 +1597,13 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
|
||||
void
|
||||
fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr)
|
||||
{
|
||||
unsigned sampler = instr->sampler_index;
|
||||
uint32_t set = instr->sampler_set;
|
||||
uint32_t binding = instr->sampler_index;
|
||||
|
||||
assert(binding < stage_prog_data->bind_map[set].index_count);
|
||||
assert(stage_prog_data->bind_map[set].index[binding] < 1000);
|
||||
|
||||
unsigned sampler = stage_prog_data->bind_map[set].index[binding];
|
||||
fs_reg sampler_reg(sampler);
|
||||
|
||||
/* FINISHME: We're failing to recompile our programs when the sampler is
|
||||
@@ -1758,6 +1774,12 @@ fs_visitor::nir_emit_jump(const fs_builder &bld, nir_jump_instr *instr)
|
||||
bld.emit(BRW_OPCODE_CONTINUE);
|
||||
break;
|
||||
case nir_jump_return:
|
||||
/* This has to be the last block in the shader. We don't handle
|
||||
* early returns.
|
||||
*/
|
||||
assert(nir_cf_node_next(&instr->instr.block->cf_node) == NULL &&
|
||||
instr->instr.block->cf_node.parent->type == nir_cf_node_function);
|
||||
break;
|
||||
default:
|
||||
unreachable("unknown jump");
|
||||
}
|
||||
|
@@ -33,19 +33,23 @@
|
||||
#include "brw_state.h"
|
||||
#include "brw_ff_gs.h"
|
||||
|
||||
|
||||
bool
|
||||
brw_codegen_gs_prog(struct brw_context *brw,
|
||||
brw_compile_gs_prog(struct brw_context *brw,
|
||||
struct gl_shader_program *prog,
|
||||
struct brw_geometry_program *gp,
|
||||
struct brw_gs_prog_key *key)
|
||||
struct brw_gs_prog_key *key,
|
||||
struct brw_gs_compile_output *output)
|
||||
{
|
||||
struct brw_stage_state *stage_state = &brw->gs.base;
|
||||
struct brw_gs_compile c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.key = *key;
|
||||
c.gp = gp;
|
||||
|
||||
/* We get the bind map as input in the output struct...*/
|
||||
c.prog_data.base.base.map_entries = output->prog_data.base.base.map_entries;
|
||||
memcpy(c.prog_data.base.base.bind_map, output->prog_data.base.base.bind_map,
|
||||
sizeof(c.prog_data.base.base.bind_map));
|
||||
|
||||
c.prog_data.include_primitive_id =
|
||||
(gp->program.Base.InputsRead & VARYING_BIT_PRIMITIVE_ID) != 0;
|
||||
|
||||
@@ -274,18 +278,41 @@ brw_codegen_gs_prog(struct brw_context *brw,
|
||||
|
||||
c.prog_data.base.base.total_scratch
|
||||
= brw_get_scratch_size(c.base.last_scratch*REG_SIZE);
|
||||
}
|
||||
|
||||
output->mem_ctx = mem_ctx;
|
||||
output->program = program;
|
||||
output->program_size = program_size;
|
||||
memcpy(&output->prog_data, &c.prog_data,
|
||||
sizeof(output->prog_data));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
brw_codegen_gs_prog(struct brw_context *brw,
|
||||
struct gl_shader_program *prog,
|
||||
struct brw_geometry_program *gp,
|
||||
struct brw_gs_prog_key *key)
|
||||
{
|
||||
struct brw_gs_compile_output output;
|
||||
struct brw_stage_state *stage_state = &brw->gs.base;
|
||||
|
||||
if (brw_compile_gs_prog(brw, prog, gp, key, &output))
|
||||
return false;
|
||||
|
||||
if (output.prog_data.base.base.total_scratch) {
|
||||
brw_get_scratch_bo(brw, &stage_state->scratch_bo,
|
||||
c.prog_data.base.base.total_scratch *
|
||||
output.prog_data.base.base.total_scratch *
|
||||
brw->max_gs_threads);
|
||||
}
|
||||
|
||||
brw_upload_cache(&brw->cache, BRW_CACHE_GS_PROG,
|
||||
&c.key, sizeof(c.key),
|
||||
program, program_size,
|
||||
&c.prog_data, sizeof(c.prog_data),
|
||||
key, sizeof(*key),
|
||||
output.program, output.program_size,
|
||||
&output.prog_data, sizeof(output.prog_data),
|
||||
&stage_state->prog_offset, &brw->gs.prog_data);
|
||||
ralloc_free(mem_ctx);
|
||||
ralloc_free(output.mem_ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -37,6 +37,22 @@ struct gl_context;
|
||||
struct gl_shader_program;
|
||||
struct gl_program;
|
||||
|
||||
struct brw_gs_compile_output {
|
||||
void *mem_ctx;
|
||||
const void *program;
|
||||
uint32_t program_size;
|
||||
struct brw_gs_prog_data prog_data;
|
||||
};
|
||||
|
||||
struct brw_gs_prog_key;
|
||||
|
||||
bool
|
||||
brw_compile_gs_prog(struct brw_context *brw,
|
||||
struct gl_shader_program *prog,
|
||||
struct brw_geometry_program *gp,
|
||||
struct brw_gs_prog_key *key,
|
||||
struct brw_gs_compile_output *output);
|
||||
|
||||
bool brw_gs_prog_data_compare(const void *a, const void *b);
|
||||
|
||||
void
|
||||
|
@@ -89,7 +89,6 @@ brw_create_nir(struct brw_context *brw,
|
||||
const nir_shader_compiler_options *options =
|
||||
ctx->Const.ShaderCompilerOptions[stage].NirOptions;
|
||||
struct gl_shader *shader = shader_prog ? shader_prog->_LinkedShaders[stage] : NULL;
|
||||
bool debug_enabled = INTEL_DEBUG & intel_debug_flag_for_shader_stage(stage);
|
||||
nir_shader *nir;
|
||||
|
||||
/* First, lower the GLSL IR or Mesa IR to NIR */
|
||||
@@ -101,6 +100,28 @@ brw_create_nir(struct brw_context *brw,
|
||||
}
|
||||
nir_validate_shader(nir);
|
||||
|
||||
brw_process_nir(nir, brw->intelScreen->devinfo, shader_prog, stage);
|
||||
|
||||
static GLuint msg_id = 0;
|
||||
_mesa_gl_debug(&brw->ctx, &msg_id,
|
||||
MESA_DEBUG_SOURCE_SHADER_COMPILER,
|
||||
MESA_DEBUG_TYPE_OTHER,
|
||||
MESA_DEBUG_SEVERITY_NOTIFICATION,
|
||||
"%s NIR shader: %d inst\n",
|
||||
_mesa_shader_stage_to_abbrev(stage),
|
||||
count_nir_instrs(nir));
|
||||
|
||||
return nir;
|
||||
}
|
||||
|
||||
void
|
||||
brw_process_nir(nir_shader *nir,
|
||||
const struct brw_device_info *devinfo,
|
||||
const struct gl_shader_program *shader_prog,
|
||||
gl_shader_stage stage)
|
||||
{
|
||||
bool debug_enabled = INTEL_DEBUG & intel_debug_flag_for_shader_stage(stage);
|
||||
|
||||
nir_lower_global_vars_to_local(nir);
|
||||
nir_validate_shader(nir);
|
||||
|
||||
@@ -136,8 +157,10 @@ brw_create_nir(struct brw_context *brw,
|
||||
|
||||
if (shader_prog) {
|
||||
nir_lower_samplers(nir, shader_prog, stage);
|
||||
nir_validate_shader(nir);
|
||||
} else {
|
||||
nir_lower_samplers_for_vk(nir);
|
||||
}
|
||||
nir_validate_shader(nir);
|
||||
|
||||
nir_lower_system_values(nir);
|
||||
nir_validate_shader(nir);
|
||||
@@ -147,7 +170,7 @@ brw_create_nir(struct brw_context *brw,
|
||||
|
||||
nir_optimize(nir);
|
||||
|
||||
if (brw->gen >= 6) {
|
||||
if (devinfo->gen >= 6) {
|
||||
/* Try and fuse multiply-adds */
|
||||
nir_opt_peephole_ffma(nir);
|
||||
nir_validate_shader(nir);
|
||||
@@ -178,15 +201,6 @@ brw_create_nir(struct brw_context *brw,
|
||||
nir_print_shader(nir, stderr);
|
||||
}
|
||||
|
||||
static GLuint msg_id = 0;
|
||||
_mesa_gl_debug(&brw->ctx, &msg_id,
|
||||
MESA_DEBUG_SOURCE_SHADER_COMPILER,
|
||||
MESA_DEBUG_TYPE_OTHER,
|
||||
MESA_DEBUG_SEVERITY_NOTIFICATION,
|
||||
"%s NIR shader: %d inst\n",
|
||||
_mesa_shader_stage_to_abbrev(stage),
|
||||
count_nir_instrs(nir));
|
||||
|
||||
nir_convert_from_ssa(nir);
|
||||
nir_validate_shader(nir);
|
||||
|
||||
@@ -195,7 +209,7 @@ brw_create_nir(struct brw_context *brw,
|
||||
* run it last because it stashes data in instr->pass_flags and we don't
|
||||
* want that to be squashed by other NIR passes.
|
||||
*/
|
||||
if (brw->gen <= 5)
|
||||
if (devinfo->gen <= 5)
|
||||
brw_nir_analyze_boolean_resolves(nir);
|
||||
|
||||
nir_sweep(nir);
|
||||
@@ -205,6 +219,4 @@ brw_create_nir(struct brw_context *brw,
|
||||
_mesa_shader_stage_to_string(stage));
|
||||
nir_print_shader(nir, stderr);
|
||||
}
|
||||
|
||||
return nir;
|
||||
}
|
||||
|
@@ -79,6 +79,12 @@ nir_shader *brw_create_nir(struct brw_context *brw,
|
||||
const struct gl_program *prog,
|
||||
gl_shader_stage stage);
|
||||
|
||||
void
|
||||
brw_process_nir(nir_shader *nir,
|
||||
const struct brw_device_info *devinfo,
|
||||
const struct gl_shader_program *shader_prog,
|
||||
gl_shader_stage stage);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -275,7 +275,7 @@ brw_get_scratch_bo(struct brw_context *brw,
|
||||
|
||||
void brwInitFragProgFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
assert(functions->ProgramStringNotify == _tnl_program_string);
|
||||
/* assert(functions->ProgramStringNotify == _tnl_program_string); */
|
||||
|
||||
functions->NewProgram = brwNewProgram;
|
||||
functions->DeleteProgram = brwDeleteProgram;
|
||||
|
@@ -441,6 +441,7 @@ brw_type_for_base_type(const struct glsl_type *type)
|
||||
case GLSL_TYPE_ERROR:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_DOUBLE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
unreachable("not reached");
|
||||
}
|
||||
|
||||
|
@@ -427,6 +427,9 @@ brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
|
||||
|
||||
DBG("%s\n", __func__);
|
||||
|
||||
if (cache->bo == NULL)
|
||||
return;
|
||||
|
||||
if (brw->has_llc)
|
||||
drm_intel_bo_unmap(cache->bo);
|
||||
drm_intel_bo_unreference(cache->bo);
|
||||
|
@@ -1882,7 +1882,7 @@ brw_vs_emit(struct brw_context *brw,
|
||||
st_index = brw_get_shader_time_index(brw, prog, &c->vp->program.Base,
|
||||
ST_VS);
|
||||
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_VS))
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_VS) && shader->base.ir)
|
||||
brw_dump_ir("vertex", prog, &shader->base, &c->vp->program.Base);
|
||||
|
||||
if (brw->intelScreen->compiler->scalar_vs) {
|
||||
|
@@ -615,6 +615,7 @@ type_size(const struct glsl_type *type)
|
||||
case GLSL_TYPE_DOUBLE:
|
||||
case GLSL_TYPE_ERROR:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
unreachable("not reached");
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,7 @@
|
||||
* Return a bitfield where bit n is set if barycentric interpolation mode n
|
||||
* (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader.
|
||||
*/
|
||||
static unsigned
|
||||
unsigned
|
||||
brw_compute_barycentric_interp_modes(struct brw_context *brw,
|
||||
bool shade_model_flat,
|
||||
bool persample_shading,
|
||||
|
@@ -90,6 +90,12 @@ bool brw_wm_prog_data_compare(const void *a, const void *b);
|
||||
void
|
||||
brw_upload_wm_prog(struct brw_context *brw);
|
||||
|
||||
unsigned
|
||||
brw_compute_barycentric_interp_modes(struct brw_context *brw,
|
||||
bool shade_model_flat,
|
||||
bool persample_shading,
|
||||
const struct gl_fragment_program *fprog);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@@ -60,7 +60,7 @@ static const struct dri_debug_control debug_control[] = {
|
||||
{ "urb", DEBUG_URB },
|
||||
{ "vs", DEBUG_VS },
|
||||
{ "clip", DEBUG_CLIP },
|
||||
{ "aub", DEBUG_AUB },
|
||||
{ "foob", DEBUG_AUB }, /* disable aub dumbing in the dri driver */
|
||||
{ "shader_time", DEBUG_SHADER_TIME },
|
||||
{ "no16", DEBUG_NO16 },
|
||||
{ "blorp", DEBUG_BLORP },
|
||||
|
@@ -275,9 +275,11 @@ intelInitExtensions(struct gl_context *ctx)
|
||||
ctx->Extensions.EXT_shader_integer_mix = ctx->Const.GLSLVersion >= 130;
|
||||
ctx->Extensions.EXT_timer_query = true;
|
||||
|
||||
if (brw->gen == 5 || can_write_oacontrol(brw)) {
|
||||
ctx->Extensions.AMD_performance_monitor = true;
|
||||
ctx->Extensions.INTEL_performance_query = true;
|
||||
if (brw->bufmgr) {
|
||||
if (brw->gen == 5 || can_write_oacontrol(brw)) {
|
||||
ctx->Extensions.AMD_performance_monitor = true;
|
||||
ctx->Extensions.INTEL_performance_query = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +287,7 @@ intelInitExtensions(struct gl_context *ctx)
|
||||
uint64_t dummy;
|
||||
|
||||
ctx->Extensions.ARB_blend_func_extended =
|
||||
brw->optionCache.info == NULL ||
|
||||
!driQueryOptionb(&brw->optionCache, "disable_blend_func_extended");
|
||||
ctx->Extensions.ARB_conditional_render_inverted = true;
|
||||
ctx->Extensions.ARB_draw_buffers_blend = true;
|
||||
@@ -308,7 +311,7 @@ intelInitExtensions(struct gl_context *ctx)
|
||||
ctx->Extensions.OES_depth_texture_cube_map = true;
|
||||
|
||||
/* Test if the kernel has the ioctl. */
|
||||
if (drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &dummy) == 0)
|
||||
if (brw->bufmgr && drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &dummy) == 0)
|
||||
ctx->Extensions.ARB_timer_query = true;
|
||||
|
||||
/* Only enable this in core profile because other parts of Mesa behave
|
||||
@@ -331,7 +334,8 @@ intelInitExtensions(struct gl_context *ctx)
|
||||
ctx->Extensions.ARB_texture_compression_bptc = true;
|
||||
ctx->Extensions.ARB_texture_view = true;
|
||||
|
||||
if (can_do_pipelined_register_writes(brw)) {
|
||||
if (brw->bufmgr &&
|
||||
can_do_pipelined_register_writes(brw)) {
|
||||
ctx->Extensions.ARB_draw_indirect = true;
|
||||
ctx->Extensions.ARB_transform_feedback2 = true;
|
||||
ctx->Extensions.ARB_transform_feedback3 = true;
|
||||
@@ -359,7 +363,9 @@ intelInitExtensions(struct gl_context *ctx)
|
||||
if (ctx->API != API_OPENGL_CORE)
|
||||
ctx->Extensions.ARB_color_buffer_float = true;
|
||||
|
||||
if (ctx->Mesa_DXTn || driQueryOptionb(&brw->optionCache, "force_s3tc_enable"))
|
||||
if (ctx->Mesa_DXTn ||
|
||||
(brw->optionCache.info != NULL &&
|
||||
driQueryOptionb(&brw->optionCache, "force_s3tc_enable")))
|
||||
ctx->Extensions.EXT_texture_compression_s3tc = true;
|
||||
|
||||
ctx->Extensions.ANGLE_texture_compression_dxt = true;
|
||||
|
@@ -1426,6 +1426,78 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
|
||||
return (const __DRIconfig**) intel_screen_make_configs(psp);
|
||||
}
|
||||
|
||||
struct intel_screen *
|
||||
intel_screen_create(int fd)
|
||||
{
|
||||
__DRIscreen *psp;
|
||||
__DRIconfig **configs;
|
||||
int i;
|
||||
|
||||
psp = malloc(sizeof(*psp));
|
||||
if (psp == NULL)
|
||||
return NULL;
|
||||
|
||||
psp->image.loader = (void *) 1; /* Don't complain about this being NULL */
|
||||
psp->fd = fd;
|
||||
psp->dri2.useInvalidate = (void *) 1;
|
||||
|
||||
configs = (__DRIconfig **) intelInitScreen2(psp);
|
||||
for (i = 0; configs[i]; i++)
|
||||
free(configs[i]);
|
||||
free(configs);
|
||||
|
||||
return psp->driverPrivate;
|
||||
}
|
||||
|
||||
void
|
||||
intel_screen_destroy(struct intel_screen *screen)
|
||||
{
|
||||
__DRIscreen *psp;
|
||||
|
||||
psp = screen->driScrnPriv;
|
||||
intelDestroyScreen(screen->driScrnPriv);
|
||||
free(psp);
|
||||
}
|
||||
|
||||
|
||||
struct brw_context *
|
||||
intel_context_create(struct intel_screen *screen)
|
||||
{
|
||||
__DRIcontext *driContextPriv;
|
||||
struct brw_context *brw;
|
||||
unsigned error;
|
||||
|
||||
driContextPriv = malloc(sizeof(*driContextPriv));
|
||||
if (driContextPriv == NULL)
|
||||
return NULL;
|
||||
|
||||
driContextPriv->driScreenPriv = screen->driScrnPriv;
|
||||
|
||||
brwCreateContext(API_OPENGL_CORE,
|
||||
NULL, /* visual */
|
||||
driContextPriv,
|
||||
3, 0,
|
||||
0, /* flags */
|
||||
false, /* notify_reset */
|
||||
&error,
|
||||
NULL);
|
||||
|
||||
brw = driContextPriv->driverPrivate;
|
||||
brw->ctx.FirstTimeCurrent = false;
|
||||
|
||||
return driContextPriv->driverPrivate;
|
||||
}
|
||||
|
||||
void
|
||||
intel_context_destroy(struct brw_context *brw)
|
||||
{
|
||||
__DRIcontext *driContextPriv;
|
||||
|
||||
driContextPriv = brw->driContext;
|
||||
intelDestroyContext(driContextPriv);
|
||||
free(driContextPriv);
|
||||
}
|
||||
|
||||
struct intel_buffer {
|
||||
__DRIbuffer base;
|
||||
drm_intel_bo *bo;
|
||||
|
@@ -96,189 +96,6 @@ struct vbo_context;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Indexes for vertex program attributes.
|
||||
* GL_NV_vertex_program aliases generic attributes over the conventional
|
||||
* attributes. In GL_ARB_vertex_program shader the aliasing is optional.
|
||||
* In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
|
||||
* generic attributes are distinct/separate).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
VERT_ATTRIB_POS = 0,
|
||||
VERT_ATTRIB_WEIGHT = 1,
|
||||
VERT_ATTRIB_NORMAL = 2,
|
||||
VERT_ATTRIB_COLOR0 = 3,
|
||||
VERT_ATTRIB_COLOR1 = 4,
|
||||
VERT_ATTRIB_FOG = 5,
|
||||
VERT_ATTRIB_COLOR_INDEX = 6,
|
||||
VERT_ATTRIB_EDGEFLAG = 7,
|
||||
VERT_ATTRIB_TEX0 = 8,
|
||||
VERT_ATTRIB_TEX1 = 9,
|
||||
VERT_ATTRIB_TEX2 = 10,
|
||||
VERT_ATTRIB_TEX3 = 11,
|
||||
VERT_ATTRIB_TEX4 = 12,
|
||||
VERT_ATTRIB_TEX5 = 13,
|
||||
VERT_ATTRIB_TEX6 = 14,
|
||||
VERT_ATTRIB_TEX7 = 15,
|
||||
VERT_ATTRIB_POINT_SIZE = 16,
|
||||
VERT_ATTRIB_GENERIC0 = 17,
|
||||
VERT_ATTRIB_GENERIC1 = 18,
|
||||
VERT_ATTRIB_GENERIC2 = 19,
|
||||
VERT_ATTRIB_GENERIC3 = 20,
|
||||
VERT_ATTRIB_GENERIC4 = 21,
|
||||
VERT_ATTRIB_GENERIC5 = 22,
|
||||
VERT_ATTRIB_GENERIC6 = 23,
|
||||
VERT_ATTRIB_GENERIC7 = 24,
|
||||
VERT_ATTRIB_GENERIC8 = 25,
|
||||
VERT_ATTRIB_GENERIC9 = 26,
|
||||
VERT_ATTRIB_GENERIC10 = 27,
|
||||
VERT_ATTRIB_GENERIC11 = 28,
|
||||
VERT_ATTRIB_GENERIC12 = 29,
|
||||
VERT_ATTRIB_GENERIC13 = 30,
|
||||
VERT_ATTRIB_GENERIC14 = 31,
|
||||
VERT_ATTRIB_GENERIC15 = 32,
|
||||
VERT_ATTRIB_MAX = 33
|
||||
} gl_vert_attrib;
|
||||
|
||||
/**
|
||||
* Symbolic constats to help iterating over
|
||||
* specific blocks of vertex attributes.
|
||||
*
|
||||
* VERT_ATTRIB_FF
|
||||
* includes all fixed function attributes as well as
|
||||
* the aliased GL_NV_vertex_program shader attributes.
|
||||
* VERT_ATTRIB_TEX
|
||||
* include the classic texture coordinate attributes.
|
||||
* Is a subset of VERT_ATTRIB_FF.
|
||||
* VERT_ATTRIB_GENERIC
|
||||
* include the OpenGL 2.0+ GLSL generic shader attributes.
|
||||
* These alias the generic GL_ARB_vertex_shader attributes.
|
||||
*/
|
||||
#define VERT_ATTRIB_FF(i) (VERT_ATTRIB_POS + (i))
|
||||
#define VERT_ATTRIB_FF_MAX VERT_ATTRIB_GENERIC0
|
||||
|
||||
#define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i))
|
||||
#define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS
|
||||
|
||||
#define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i))
|
||||
#define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS
|
||||
|
||||
/**
|
||||
* Bitflags for vertex attributes.
|
||||
* These are used in bitfields in many places.
|
||||
*/
|
||||
/*@{*/
|
||||
#define VERT_BIT_POS BITFIELD64_BIT(VERT_ATTRIB_POS)
|
||||
#define VERT_BIT_WEIGHT BITFIELD64_BIT(VERT_ATTRIB_WEIGHT)
|
||||
#define VERT_BIT_NORMAL BITFIELD64_BIT(VERT_ATTRIB_NORMAL)
|
||||
#define VERT_BIT_COLOR0 BITFIELD64_BIT(VERT_ATTRIB_COLOR0)
|
||||
#define VERT_BIT_COLOR1 BITFIELD64_BIT(VERT_ATTRIB_COLOR1)
|
||||
#define VERT_BIT_FOG BITFIELD64_BIT(VERT_ATTRIB_FOG)
|
||||
#define VERT_BIT_COLOR_INDEX BITFIELD64_BIT(VERT_ATTRIB_COLOR_INDEX)
|
||||
#define VERT_BIT_EDGEFLAG BITFIELD64_BIT(VERT_ATTRIB_EDGEFLAG)
|
||||
#define VERT_BIT_TEX0 BITFIELD64_BIT(VERT_ATTRIB_TEX0)
|
||||
#define VERT_BIT_TEX1 BITFIELD64_BIT(VERT_ATTRIB_TEX1)
|
||||
#define VERT_BIT_TEX2 BITFIELD64_BIT(VERT_ATTRIB_TEX2)
|
||||
#define VERT_BIT_TEX3 BITFIELD64_BIT(VERT_ATTRIB_TEX3)
|
||||
#define VERT_BIT_TEX4 BITFIELD64_BIT(VERT_ATTRIB_TEX4)
|
||||
#define VERT_BIT_TEX5 BITFIELD64_BIT(VERT_ATTRIB_TEX5)
|
||||
#define VERT_BIT_TEX6 BITFIELD64_BIT(VERT_ATTRIB_TEX6)
|
||||
#define VERT_BIT_TEX7 BITFIELD64_BIT(VERT_ATTRIB_TEX7)
|
||||
#define VERT_BIT_POINT_SIZE BITFIELD64_BIT(VERT_ATTRIB_POINT_SIZE)
|
||||
#define VERT_BIT_GENERIC0 BITFIELD64_BIT(VERT_ATTRIB_GENERIC0)
|
||||
|
||||
#define VERT_BIT(i) BITFIELD64_BIT(i)
|
||||
#define VERT_BIT_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_MAX)
|
||||
|
||||
#define VERT_BIT_FF(i) VERT_BIT(i)
|
||||
#define VERT_BIT_FF_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_FF_MAX)
|
||||
#define VERT_BIT_TEX(i) VERT_BIT(VERT_ATTRIB_TEX(i))
|
||||
#define VERT_BIT_TEX_ALL \
|
||||
BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX)
|
||||
|
||||
#define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i))
|
||||
#define VERT_BIT_GENERIC_ALL \
|
||||
BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX)
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* Indexes for vertex shader outputs, geometry shader inputs/outputs, and
|
||||
* fragment shader inputs.
|
||||
*
|
||||
* Note that some of these values are not available to all pipeline stages.
|
||||
*
|
||||
* When this enum is updated, the following code must be updated too:
|
||||
* - vertResults (in prog_print.c's arb_output_attrib_string())
|
||||
* - fragAttribs (in prog_print.c's arb_input_attrib_string())
|
||||
* - _mesa_varying_slot_in_fs()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
VARYING_SLOT_POS,
|
||||
VARYING_SLOT_COL0, /* COL0 and COL1 must be contiguous */
|
||||
VARYING_SLOT_COL1,
|
||||
VARYING_SLOT_FOGC,
|
||||
VARYING_SLOT_TEX0, /* TEX0-TEX7 must be contiguous */
|
||||
VARYING_SLOT_TEX1,
|
||||
VARYING_SLOT_TEX2,
|
||||
VARYING_SLOT_TEX3,
|
||||
VARYING_SLOT_TEX4,
|
||||
VARYING_SLOT_TEX5,
|
||||
VARYING_SLOT_TEX6,
|
||||
VARYING_SLOT_TEX7,
|
||||
VARYING_SLOT_PSIZ, /* Does not appear in FS */
|
||||
VARYING_SLOT_BFC0, /* Does not appear in FS */
|
||||
VARYING_SLOT_BFC1, /* Does not appear in FS */
|
||||
VARYING_SLOT_EDGE, /* Does not appear in FS */
|
||||
VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */
|
||||
VARYING_SLOT_CLIP_DIST0,
|
||||
VARYING_SLOT_CLIP_DIST1,
|
||||
VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */
|
||||
VARYING_SLOT_LAYER, /* Appears as VS or GS output */
|
||||
VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */
|
||||
VARYING_SLOT_FACE, /* FS only */
|
||||
VARYING_SLOT_PNTC, /* FS only */
|
||||
VARYING_SLOT_VAR0, /* First generic varying slot */
|
||||
VARYING_SLOT_MAX = VARYING_SLOT_VAR0 + MAX_VARYING
|
||||
} gl_varying_slot;
|
||||
|
||||
|
||||
/**
|
||||
* Bitflags for varying slots.
|
||||
*/
|
||||
/*@{*/
|
||||
#define VARYING_BIT_POS BITFIELD64_BIT(VARYING_SLOT_POS)
|
||||
#define VARYING_BIT_COL0 BITFIELD64_BIT(VARYING_SLOT_COL0)
|
||||
#define VARYING_BIT_COL1 BITFIELD64_BIT(VARYING_SLOT_COL1)
|
||||
#define VARYING_BIT_FOGC BITFIELD64_BIT(VARYING_SLOT_FOGC)
|
||||
#define VARYING_BIT_TEX0 BITFIELD64_BIT(VARYING_SLOT_TEX0)
|
||||
#define VARYING_BIT_TEX1 BITFIELD64_BIT(VARYING_SLOT_TEX1)
|
||||
#define VARYING_BIT_TEX2 BITFIELD64_BIT(VARYING_SLOT_TEX2)
|
||||
#define VARYING_BIT_TEX3 BITFIELD64_BIT(VARYING_SLOT_TEX3)
|
||||
#define VARYING_BIT_TEX4 BITFIELD64_BIT(VARYING_SLOT_TEX4)
|
||||
#define VARYING_BIT_TEX5 BITFIELD64_BIT(VARYING_SLOT_TEX5)
|
||||
#define VARYING_BIT_TEX6 BITFIELD64_BIT(VARYING_SLOT_TEX6)
|
||||
#define VARYING_BIT_TEX7 BITFIELD64_BIT(VARYING_SLOT_TEX7)
|
||||
#define VARYING_BIT_TEX(U) BITFIELD64_BIT(VARYING_SLOT_TEX0 + (U))
|
||||
#define VARYING_BITS_TEX_ANY BITFIELD64_RANGE(VARYING_SLOT_TEX0, \
|
||||
MAX_TEXTURE_COORD_UNITS)
|
||||
#define VARYING_BIT_PSIZ BITFIELD64_BIT(VARYING_SLOT_PSIZ)
|
||||
#define VARYING_BIT_BFC0 BITFIELD64_BIT(VARYING_SLOT_BFC0)
|
||||
#define VARYING_BIT_BFC1 BITFIELD64_BIT(VARYING_SLOT_BFC1)
|
||||
#define VARYING_BIT_EDGE BITFIELD64_BIT(VARYING_SLOT_EDGE)
|
||||
#define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX)
|
||||
#define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0)
|
||||
#define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1)
|
||||
#define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID)
|
||||
#define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER)
|
||||
#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
|
||||
#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
|
||||
#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
|
||||
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Determine if the given gl_varying_slot appears in the fragment shader.
|
||||
*/
|
||||
@@ -299,28 +116,6 @@ _mesa_varying_slot_in_fs(gl_varying_slot slot)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fragment program results
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FRAG_RESULT_DEPTH = 0,
|
||||
FRAG_RESULT_STENCIL = 1,
|
||||
/* If a single color should be written to all render targets, this
|
||||
* register is written. No FRAG_RESULT_DATAn will be written.
|
||||
*/
|
||||
FRAG_RESULT_COLOR = 2,
|
||||
FRAG_RESULT_SAMPLE_MASK = 3,
|
||||
|
||||
/* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n]
|
||||
* or ARB_fragment_program fragment.color[n]) color results. If
|
||||
* any are written, FRAG_RESULT_COLOR will not be written.
|
||||
*/
|
||||
FRAG_RESULT_DATA0 = 4,
|
||||
FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
|
||||
} gl_frag_result;
|
||||
|
||||
|
||||
/**
|
||||
* Indexes for all renderbuffers
|
||||
*/
|
||||
@@ -2558,6 +2353,11 @@ struct gl_uniform_block
|
||||
*/
|
||||
GLuint Binding;
|
||||
|
||||
/**
|
||||
* Vulkan descriptor set qualifier for this block.
|
||||
*/
|
||||
GLuint Set;
|
||||
|
||||
/**
|
||||
* Minimum size (in bytes) of a buffer object to back this uniform buffer
|
||||
* (GL_UNIFORM_BLOCK_DATA_SIZE).
|
||||
|
@@ -542,6 +542,7 @@ type_size(const struct glsl_type *type)
|
||||
case GLSL_TYPE_VOID:
|
||||
case GLSL_TYPE_ERROR:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
assert(!"Invalid type in type_size");
|
||||
break;
|
||||
}
|
||||
@@ -2460,6 +2461,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
|
||||
case GLSL_TYPE_STRUCT:
|
||||
case GLSL_TYPE_ERROR:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
case GLSL_TYPE_FUNCTION:
|
||||
assert(!"Should not get here.");
|
||||
break;
|
||||
}
|
||||
|
4
src/vulkan/.gitignore
vendored
Normal file
4
src/vulkan/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Generated source files
|
||||
/*-spirv.h
|
||||
/entrypoints.c
|
||||
/entrypoints.h
|
95
src/vulkan/Makefile.am
Normal file
95
src/vulkan/Makefile.am
Normal file
@@ -0,0 +1,95 @@
|
||||
# Copyright © 2015 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
|
||||
vulkan_includedir = $(includedir)/vulkan
|
||||
|
||||
vulkan_include_HEADERS = \
|
||||
$(top_srcdir)/include/vulkan/vk_platform.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan_intel.h \
|
||||
$(top_srcdir)/include/vulkan/vk_wsi_lunarg.h
|
||||
|
||||
lib_LTLIBRARIES = libvulkan.la
|
||||
|
||||
# The gallium includes are for the util/u_math.h include from main/macros.h
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(INTEL_CFLAGS) \
|
||||
$(VALGRIND_CFLAGS) \
|
||||
$(DEFINES) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/mapi \
|
||||
-I$(top_srcdir)/src/mesa \
|
||||
-I$(top_srcdir)/src/mesa/drivers/dri/common \
|
||||
-I$(top_srcdir)/src/mesa/drivers/dri/i965 \
|
||||
-I$(top_srcdir)/src/gallium/auxiliary \
|
||||
-I$(top_srcdir)/src/gallium/include \
|
||||
-I$(top_builddir)/src/vulkan
|
||||
|
||||
libvulkan_la_CFLAGS = \
|
||||
-Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -O0 -g \
|
||||
-Wstrict-prototypes -Wmissing-prototypes -Wno-override-init
|
||||
|
||||
libvulkan_la_CXXFLAGS = \
|
||||
-Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -O0 -g
|
||||
|
||||
libvulkan_la_SOURCES = \
|
||||
private.h \
|
||||
gem.c \
|
||||
device.c \
|
||||
anv_cmd_buffer.c \
|
||||
anv_cmd_emit.c \
|
||||
aub.c \
|
||||
allocator.c \
|
||||
util.c \
|
||||
pipeline.c \
|
||||
image.c \
|
||||
meta.c \
|
||||
intel.c \
|
||||
entrypoints.c \
|
||||
entrypoints.h \
|
||||
x11.c \
|
||||
formats.c \
|
||||
compiler.cpp \
|
||||
query.c
|
||||
|
||||
BUILT_SOURCES = \
|
||||
entrypoints.h \
|
||||
entrypoints.c \
|
||||
meta-spirv.h
|
||||
|
||||
entrypoints.h : vk_gen.py $(vulkan_include_HEADERS)
|
||||
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< header > $@
|
||||
|
||||
entrypoints.c : vk_gen.py $(vulkan_include_HEADERS)
|
||||
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< code > $@
|
||||
|
||||
%-spirv.h: %.c glsl_scraper.py
|
||||
$(AM_V_GEN) $(PYTHON2) $(srcdir)/glsl_scraper.py --glsl-only -o $@ $<
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
libvulkan_la_LIBADD = -lxcb -lxcb-dri3 \
|
||||
$(top_builddir)/src/mesa/drivers/dri/i965/libi965_compiler.la
|
||||
|
||||
include $(top_srcdir)/install-lib-links.mk
|
665
src/vulkan/allocator.c
Normal file
665
src/vulkan/allocator.c
Normal file
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <values.h>
|
||||
#include <assert.h>
|
||||
#include <linux/futex.h>
|
||||
#include <linux/memfd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
#define VG_NOACCESS_READ(__ptr) ({ \
|
||||
VALGRIND_MAKE_MEM_DEFINED((__ptr), sizeof(*(__ptr))); \
|
||||
__typeof(*(__ptr)) __val = *(__ptr); \
|
||||
VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr)));\
|
||||
__val; \
|
||||
})
|
||||
#define VG_NOACCESS_WRITE(__ptr, __val) ({ \
|
||||
VALGRIND_MAKE_MEM_UNDEFINED((__ptr), sizeof(*(__ptr))); \
|
||||
*(__ptr) = (__val); \
|
||||
VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr))); \
|
||||
})
|
||||
#else
|
||||
#define VG_NOACCESS_READ(__ptr) (*(__ptr))
|
||||
#define VG_NOACCESS_WRITE(__ptr, __val) (*(__ptr) = (__val))
|
||||
#endif
|
||||
|
||||
/* Design goals:
|
||||
*
|
||||
* - Lock free (except when resizing underlying bos)
|
||||
*
|
||||
* - Constant time allocation with typically only one atomic
|
||||
*
|
||||
* - Multiple allocation sizes without fragmentation
|
||||
*
|
||||
* - Can grow while keeping addresses and offset of contents stable
|
||||
*
|
||||
* - All allocations within one bo so we can point one of the
|
||||
* STATE_BASE_ADDRESS pointers at it.
|
||||
*
|
||||
* The overall design is a two-level allocator: top level is a fixed size, big
|
||||
* block (8k) allocator, which operates out of a bo. Allocation is done by
|
||||
* either pulling a block from the free list or growing the used range of the
|
||||
* bo. Growing the range may run out of space in the bo which we then need to
|
||||
* grow. Growing the bo is tricky in a multi-threaded, lockless environment:
|
||||
* we need to keep all pointers and contents in the old map valid. GEM bos in
|
||||
* general can't grow, but we use a trick: we create a memfd and use ftruncate
|
||||
* to grow it as necessary. We mmap the new size and then create a gem bo for
|
||||
* it using the new gem userptr ioctl. Without heavy-handed locking around
|
||||
* our allocation fast-path, there isn't really a way to munmap the old mmap,
|
||||
* so we just keep it around until garbage collection time. While the block
|
||||
* allocator is lockless for normal operations, we block other threads trying
|
||||
* to allocate while we're growing the map. It sholdn't happen often, and
|
||||
* growing is fast anyway.
|
||||
*
|
||||
* At the next level we can use various sub-allocators. The state pool is a
|
||||
* pool of smaller, fixed size objects, which operates much like the block
|
||||
* pool. It uses a free list for freeing objects, but when it runs out of
|
||||
* space it just allocates a new block from the block pool. This allocator is
|
||||
* intended for longer lived state objects such as SURFACE_STATE and most
|
||||
* other persistent state objects in the API. We may need to track more info
|
||||
* with these object and a pointer back to the CPU object (eg VkImage). In
|
||||
* those cases we just allocate a slightly bigger object and put the extra
|
||||
* state after the GPU state object.
|
||||
*
|
||||
* The state stream allocator works similar to how the i965 DRI driver streams
|
||||
* all its state. Even with Vulkan, we need to emit transient state (whether
|
||||
* surface state base or dynamic state base), and for that we can just get a
|
||||
* block and fill it up. These cases are local to a command buffer and the
|
||||
* sub-allocator need not be thread safe. The streaming allocator gets a new
|
||||
* block when it runs out of space and chains them together so they can be
|
||||
* easily freed.
|
||||
*/
|
||||
|
||||
/* Allocations are always at least 64 byte aligned, so 1 is an invalid value.
|
||||
* We use it to indicate the free list is empty. */
|
||||
#define EMPTY 1
|
||||
|
||||
struct anv_mmap_cleanup {
|
||||
void *map;
|
||||
size_t size;
|
||||
uint32_t gem_handle;
|
||||
};
|
||||
|
||||
#define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0})
|
||||
|
||||
static inline long
|
||||
sys_futex(void *addr1, int op, int val1,
|
||||
struct timespec *timeout, void *addr2, int val3)
|
||||
{
|
||||
return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
|
||||
}
|
||||
|
||||
static inline int
|
||||
futex_wake(uint32_t *addr, int count)
|
||||
{
|
||||
return sys_futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
futex_wait(uint32_t *addr, int32_t value)
|
||||
{
|
||||
return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
memfd_create(const char *name, unsigned int flags)
|
||||
{
|
||||
return syscall(SYS_memfd_create, name, flags);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ilog2_round_up(uint32_t value)
|
||||
{
|
||||
assert(value != 0);
|
||||
return 32 - __builtin_clz(value - 1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
round_to_power_of_two(uint32_t value)
|
||||
{
|
||||
return 1 << ilog2_round_up(value);
|
||||
}
|
||||
|
||||
static bool
|
||||
anv_free_list_pop(union anv_free_list *list, void **map, uint32_t *offset)
|
||||
{
|
||||
union anv_free_list current, next, old;
|
||||
|
||||
current = *list;
|
||||
while (current.offset != EMPTY) {
|
||||
/* We have to add a memory barrier here so that the list head (and
|
||||
* offset) gets read before we read the map pointer. This way we
|
||||
* know that the map pointer is valid for the given offset at the
|
||||
* point where we read it.
|
||||
*/
|
||||
__sync_synchronize();
|
||||
|
||||
uint32_t *next_ptr = *map + current.offset;
|
||||
next.offset = VG_NOACCESS_READ(next_ptr);
|
||||
next.count = current.count + 1;
|
||||
old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, next.u64);
|
||||
if (old.u64 == current.u64) {
|
||||
*offset = current.offset;
|
||||
return true;
|
||||
}
|
||||
current = old;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_free_list_push(union anv_free_list *list, void *map, uint32_t offset)
|
||||
{
|
||||
union anv_free_list current, old, new;
|
||||
uint32_t *next_ptr = map + offset;
|
||||
|
||||
old = *list;
|
||||
do {
|
||||
current = old;
|
||||
VG_NOACCESS_WRITE(next_ptr, current.offset);
|
||||
new.offset = offset;
|
||||
new.count = current.count + 1;
|
||||
old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, new.u64);
|
||||
} while (old.u64 != current.u64);
|
||||
}
|
||||
|
||||
/* All pointers in the ptr_free_list are assumed to be page-aligned. This
|
||||
* means that the bottom 12 bits should all be zero.
|
||||
*/
|
||||
#define PFL_COUNT(x) ((uintptr_t)(x) & 0xfff)
|
||||
#define PFL_PTR(x) ((void *)((uintptr_t)(x) & ~0xfff))
|
||||
#define PFL_PACK(ptr, count) ({ \
|
||||
assert(((uintptr_t)(ptr) & 0xfff) == 0); \
|
||||
(void *)((uintptr_t)(ptr) | (uintptr_t)((count) & 0xfff)); \
|
||||
})
|
||||
|
||||
static bool
|
||||
anv_ptr_free_list_pop(void **list, void **elem)
|
||||
{
|
||||
void *current = *list;
|
||||
while (PFL_PTR(current) != NULL) {
|
||||
void **next_ptr = PFL_PTR(current);
|
||||
void *new_ptr = VG_NOACCESS_READ(next_ptr);
|
||||
unsigned new_count = PFL_COUNT(current) + 1;
|
||||
void *new = PFL_PACK(new_ptr, new_count);
|
||||
void *old = __sync_val_compare_and_swap(list, current, new);
|
||||
if (old == current) {
|
||||
*elem = PFL_PTR(current);
|
||||
return true;
|
||||
}
|
||||
current = old;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_ptr_free_list_push(void **list, void *elem)
|
||||
{
|
||||
void *old, *current;
|
||||
void **next_ptr = elem;
|
||||
|
||||
old = *list;
|
||||
do {
|
||||
current = old;
|
||||
VG_NOACCESS_WRITE(next_ptr, PFL_PTR(current));
|
||||
unsigned new_count = PFL_COUNT(current) + 1;
|
||||
void *new = PFL_PACK(elem, new_count);
|
||||
old = __sync_val_compare_and_swap(list, current, new);
|
||||
} while (old != current);
|
||||
}
|
||||
|
||||
static int
|
||||
anv_block_pool_grow(struct anv_block_pool *pool);
|
||||
|
||||
void
|
||||
anv_block_pool_init(struct anv_block_pool *pool,
|
||||
struct anv_device *device, uint32_t block_size)
|
||||
{
|
||||
assert(is_power_of_two(block_size));
|
||||
|
||||
pool->device = device;
|
||||
pool->bo.gem_handle = 0;
|
||||
pool->bo.offset = 0;
|
||||
pool->size = 0;
|
||||
pool->block_size = block_size;
|
||||
pool->next_block = 0;
|
||||
pool->free_list = ANV_FREE_LIST_EMPTY;
|
||||
anv_vector_init(&pool->mmap_cleanups,
|
||||
round_to_power_of_two(sizeof(struct anv_mmap_cleanup)), 128);
|
||||
|
||||
/* Immediately grow the pool so we'll have a backing bo. */
|
||||
anv_block_pool_grow(pool);
|
||||
}
|
||||
|
||||
void
|
||||
anv_block_pool_finish(struct anv_block_pool *pool)
|
||||
{
|
||||
struct anv_mmap_cleanup *cleanup;
|
||||
|
||||
anv_vector_foreach(cleanup, &pool->mmap_cleanups) {
|
||||
if (cleanup->map)
|
||||
munmap(cleanup->map, cleanup->size);
|
||||
if (cleanup->gem_handle)
|
||||
anv_gem_close(pool->device, cleanup->gem_handle);
|
||||
}
|
||||
|
||||
anv_vector_finish(&pool->mmap_cleanups);
|
||||
|
||||
close(pool->fd);
|
||||
}
|
||||
|
||||
static int
|
||||
anv_block_pool_grow(struct anv_block_pool *pool)
|
||||
{
|
||||
size_t size;
|
||||
void *map;
|
||||
int gem_handle;
|
||||
struct anv_mmap_cleanup *cleanup;
|
||||
|
||||
if (pool->size == 0) {
|
||||
size = 32 * pool->block_size;
|
||||
} else {
|
||||
size = pool->size * 2;
|
||||
}
|
||||
|
||||
cleanup = anv_vector_add(&pool->mmap_cleanups);
|
||||
if (!cleanup)
|
||||
return -1;
|
||||
*cleanup = ANV_MMAP_CLEANUP_INIT;
|
||||
|
||||
if (pool->size == 0)
|
||||
pool->fd = memfd_create("block pool", MFD_CLOEXEC);
|
||||
|
||||
if (pool->fd == -1)
|
||||
return -1;
|
||||
|
||||
if (ftruncate(pool->fd, size) == -1)
|
||||
return -1;
|
||||
|
||||
/* First try to see if mremap can grow the map in place. */
|
||||
map = MAP_FAILED;
|
||||
if (pool->size > 0)
|
||||
map = mremap(pool->map, pool->size, size, 0);
|
||||
if (map == MAP_FAILED) {
|
||||
/* Just leak the old map until we destroy the pool. We can't munmap it
|
||||
* without races or imposing locking on the block allocate fast path. On
|
||||
* the whole the leaked maps adds up to less than the size of the
|
||||
* current map. MAP_POPULATE seems like the right thing to do, but we
|
||||
* should try to get some numbers.
|
||||
*/
|
||||
map = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_POPULATE, pool->fd, 0);
|
||||
cleanup->map = map;
|
||||
cleanup->size = size;
|
||||
}
|
||||
if (map == MAP_FAILED)
|
||||
return -1;
|
||||
|
||||
gem_handle = anv_gem_userptr(pool->device, map, size);
|
||||
if (gem_handle == 0)
|
||||
return -1;
|
||||
cleanup->gem_handle = gem_handle;
|
||||
|
||||
/* Now that we successfull allocated everything, we can write the new
|
||||
* values back into pool. */
|
||||
pool->map = map;
|
||||
pool->bo.gem_handle = gem_handle;
|
||||
pool->bo.size = size;
|
||||
pool->bo.map = map;
|
||||
pool->bo.index = 0;
|
||||
|
||||
/* Write size last and after the memory barrier here. We need the memory
|
||||
* barrier to make sure map and gem_handle are written before other threads
|
||||
* see the new size. A thread could allocate a block and then go try using
|
||||
* the old pool->map and access out of bounds. */
|
||||
|
||||
__sync_synchronize();
|
||||
pool->size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
anv_block_pool_alloc(struct anv_block_pool *pool)
|
||||
{
|
||||
uint32_t offset, block, size;
|
||||
|
||||
/* Try free list first. */
|
||||
if (anv_free_list_pop(&pool->free_list, &pool->map, &offset)) {
|
||||
assert(pool->map);
|
||||
return offset;
|
||||
}
|
||||
|
||||
restart:
|
||||
size = pool->size;
|
||||
block = __sync_fetch_and_add(&pool->next_block, pool->block_size);
|
||||
if (block < size) {
|
||||
assert(pool->map);
|
||||
return block;
|
||||
} else if (block == size) {
|
||||
/* We allocated the first block outside the pool, we have to grow it.
|
||||
* pool->next_block acts a mutex: threads who try to allocate now will
|
||||
* get block indexes above the current limit and hit futex_wait
|
||||
* below. */
|
||||
int err = anv_block_pool_grow(pool);
|
||||
assert(err == 0);
|
||||
(void) err;
|
||||
futex_wake(&pool->size, INT_MAX);
|
||||
} else {
|
||||
futex_wait(&pool->size, size);
|
||||
__sync_fetch_and_add(&pool->next_block, -pool->block_size);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void
|
||||
anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset)
|
||||
{
|
||||
anv_free_list_push(&pool->free_list, pool->map, offset);
|
||||
}
|
||||
|
||||
static void
|
||||
anv_fixed_size_state_pool_init(struct anv_fixed_size_state_pool *pool,
|
||||
size_t state_size)
|
||||
{
|
||||
/* At least a cache line and must divide the block size. */
|
||||
assert(state_size >= 64 && is_power_of_two(state_size));
|
||||
|
||||
pool->state_size = state_size;
|
||||
pool->free_list = ANV_FREE_LIST_EMPTY;
|
||||
pool->block.next = 0;
|
||||
pool->block.end = 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
anv_fixed_size_state_pool_alloc(struct anv_fixed_size_state_pool *pool,
|
||||
struct anv_block_pool *block_pool)
|
||||
{
|
||||
uint32_t offset;
|
||||
struct anv_block_state block, old, new;
|
||||
|
||||
/* Try free list first. */
|
||||
if (anv_free_list_pop(&pool->free_list, &block_pool->map, &offset))
|
||||
return offset;
|
||||
|
||||
/* If free list was empty (or somebody raced us and took the items) we
|
||||
* allocate a new item from the end of the block */
|
||||
restart:
|
||||
block.u64 = __sync_fetch_and_add(&pool->block.u64, pool->state_size);
|
||||
|
||||
if (block.next < block.end) {
|
||||
return block.next;
|
||||
} else if (block.next == block.end) {
|
||||
new.next = anv_block_pool_alloc(block_pool);
|
||||
new.end = new.next + block_pool->block_size;
|
||||
old.u64 = __sync_fetch_and_add(&pool->block.u64, new.u64 - block.u64);
|
||||
if (old.next != block.next)
|
||||
futex_wake(&pool->block.end, INT_MAX);
|
||||
return new.next;
|
||||
} else {
|
||||
futex_wait(&pool->block.end, block.end);
|
||||
__sync_fetch_and_add(&pool->block.u64, -pool->state_size);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
anv_fixed_size_state_pool_free(struct anv_fixed_size_state_pool *pool,
|
||||
struct anv_block_pool *block_pool,
|
||||
uint32_t offset)
|
||||
{
|
||||
anv_free_list_push(&pool->free_list, block_pool->map, offset);
|
||||
}
|
||||
|
||||
void
|
||||
anv_state_pool_init(struct anv_state_pool *pool,
|
||||
struct anv_block_pool *block_pool)
|
||||
{
|
||||
pool->block_pool = block_pool;
|
||||
for (unsigned i = 0; i < ANV_STATE_BUCKETS; i++) {
|
||||
size_t size = 1 << (ANV_MIN_STATE_SIZE_LOG2 + i);
|
||||
anv_fixed_size_state_pool_init(&pool->buckets[i], size);
|
||||
}
|
||||
}
|
||||
|
||||
struct anv_state
|
||||
anv_state_pool_alloc(struct anv_state_pool *pool, size_t size, size_t align)
|
||||
{
|
||||
unsigned size_log2 = ilog2_round_up(size < align ? align : size);
|
||||
assert(size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
|
||||
if (size_log2 < ANV_MIN_STATE_SIZE_LOG2)
|
||||
size_log2 = ANV_MIN_STATE_SIZE_LOG2;
|
||||
unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
|
||||
|
||||
struct anv_state state;
|
||||
state.alloc_size = 1 << size_log2;
|
||||
state.offset = anv_fixed_size_state_pool_alloc(&pool->buckets[bucket],
|
||||
pool->block_pool);
|
||||
state.map = pool->block_pool->map + state.offset;
|
||||
VG(VALGRIND_MALLOCLIKE_BLOCK(state.map, size, 0, false));
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state)
|
||||
{
|
||||
assert(is_power_of_two(state.alloc_size));
|
||||
unsigned size_log2 = ilog2_round_up(state.alloc_size);
|
||||
assert(size_log2 >= ANV_MIN_STATE_SIZE_LOG2 &&
|
||||
size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
|
||||
unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
|
||||
|
||||
VG(VALGRIND_FREELIKE_BLOCK(state.map, 0));
|
||||
anv_fixed_size_state_pool_free(&pool->buckets[bucket],
|
||||
pool->block_pool, state.offset);
|
||||
}
|
||||
|
||||
#define NULL_BLOCK 1
|
||||
struct stream_block {
|
||||
uint32_t next;
|
||||
|
||||
/* The map for the BO at the time the block was givne to us */
|
||||
void *current_map;
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
void *_vg_ptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The state stream allocator is a one-shot, single threaded allocator for
|
||||
* variable sized blocks. We use it for allocating dynamic state.
|
||||
*/
|
||||
void
|
||||
anv_state_stream_init(struct anv_state_stream *stream,
|
||||
struct anv_block_pool *block_pool)
|
||||
{
|
||||
stream->block_pool = block_pool;
|
||||
stream->next = 0;
|
||||
stream->end = 0;
|
||||
stream->current_block = NULL_BLOCK;
|
||||
}
|
||||
|
||||
void
|
||||
anv_state_stream_finish(struct anv_state_stream *stream)
|
||||
{
|
||||
struct stream_block *sb;
|
||||
uint32_t block, next_block;
|
||||
|
||||
block = stream->current_block;
|
||||
while (block != NULL_BLOCK) {
|
||||
sb = stream->block_pool->map + block;
|
||||
next_block = VG_NOACCESS_READ(&sb->next);
|
||||
VG(VALGRIND_FREELIKE_BLOCK(VG_NOACCESS_READ(&sb->_vg_ptr), 0));
|
||||
anv_block_pool_free(stream->block_pool, block);
|
||||
block = next_block;
|
||||
}
|
||||
}
|
||||
|
||||
struct anv_state
|
||||
anv_state_stream_alloc(struct anv_state_stream *stream,
|
||||
uint32_t size, uint32_t alignment)
|
||||
{
|
||||
struct stream_block *sb;
|
||||
struct anv_state state;
|
||||
uint32_t block;
|
||||
|
||||
state.offset = align_u32(stream->next, alignment);
|
||||
if (state.offset + size > stream->end) {
|
||||
block = anv_block_pool_alloc(stream->block_pool);
|
||||
void *current_map = stream->block_pool->map;
|
||||
sb = current_map + block;
|
||||
VG_NOACCESS_WRITE(&sb->current_map, current_map);
|
||||
VG_NOACCESS_WRITE(&sb->next, stream->current_block);
|
||||
VG(VG_NOACCESS_WRITE(&sb->_vg_ptr, 0));
|
||||
stream->current_block = block;
|
||||
stream->next = block + sizeof(*sb);
|
||||
stream->end = block + stream->block_pool->block_size;
|
||||
state.offset = align_u32(stream->next, alignment);
|
||||
assert(state.offset + size <= stream->end);
|
||||
}
|
||||
|
||||
sb = stream->block_pool->map + stream->current_block;
|
||||
void *current_map = VG_NOACCESS_READ(&sb->current_map);
|
||||
|
||||
state.map = current_map + state.offset;
|
||||
state.alloc_size = size;
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
void *vg_ptr = VG_NOACCESS_READ(&sb->_vg_ptr);
|
||||
if (vg_ptr == NULL) {
|
||||
vg_ptr = state.map;
|
||||
VG_NOACCESS_WRITE(&sb->_vg_ptr, vg_ptr);
|
||||
VALGRIND_MALLOCLIKE_BLOCK(vg_ptr, size, 0, false);
|
||||
} else {
|
||||
ptrdiff_t vg_offset = vg_ptr - current_map;
|
||||
assert(vg_offset >= stream->current_block &&
|
||||
vg_offset < stream->end);
|
||||
VALGRIND_RESIZEINPLACE_BLOCK(vg_ptr,
|
||||
stream->next - vg_offset,
|
||||
(state.offset + size) - vg_offset,
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
stream->next = state.offset + size;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
struct bo_pool_bo_link {
|
||||
struct bo_pool_bo_link *next;
|
||||
struct anv_bo bo;
|
||||
};
|
||||
|
||||
void
|
||||
anv_bo_pool_init(struct anv_bo_pool *pool,
|
||||
struct anv_device *device, uint32_t bo_size)
|
||||
{
|
||||
pool->device = device;
|
||||
pool->bo_size = bo_size;
|
||||
pool->free_list = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
anv_bo_pool_finish(struct anv_bo_pool *pool)
|
||||
{
|
||||
struct bo_pool_bo_link *link = PFL_PTR(pool->free_list);
|
||||
while (link != NULL) {
|
||||
struct bo_pool_bo_link link_copy = VG_NOACCESS_READ(link);
|
||||
|
||||
/* The anv_gem_m[un]map() functions are also valgrind-safe so they
|
||||
* act as an alloc/free. In order to avoid a double-free warning, we
|
||||
* need to mark thiss as malloc'd before we unmap it.
|
||||
*/
|
||||
VG(VALGRIND_MALLOCLIKE_BLOCK(link_copy.bo.map, pool->bo_size, 0, false));
|
||||
|
||||
anv_gem_munmap(link_copy.bo.map, pool->bo_size);
|
||||
anv_gem_close(pool->device, link_copy.bo.gem_handle);
|
||||
link = link_copy.next;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo)
|
||||
{
|
||||
VkResult result;
|
||||
|
||||
void *next_free_void;
|
||||
if (anv_ptr_free_list_pop(&pool->free_list, &next_free_void)) {
|
||||
struct bo_pool_bo_link *next_free = next_free_void;
|
||||
*bo = VG_NOACCESS_READ(&next_free->bo);
|
||||
assert(bo->map == next_free);
|
||||
assert(bo->size == pool->bo_size);
|
||||
|
||||
VG(VALGRIND_MALLOCLIKE_BLOCK(bo->map, pool->bo_size, 0, false));
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
struct anv_bo new_bo;
|
||||
|
||||
result = anv_bo_init_new(&new_bo, pool->device, pool->bo_size);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
assert(new_bo.size == pool->bo_size);
|
||||
|
||||
new_bo.map = anv_gem_mmap(pool->device, new_bo.gem_handle, 0, pool->bo_size);
|
||||
if (new_bo.map == NULL) {
|
||||
anv_gem_close(pool->device, new_bo.gem_handle);
|
||||
return vk_error(VK_ERROR_MEMORY_MAP_FAILED);
|
||||
}
|
||||
|
||||
/* We don't need to call VALGRIND_MALLOCLIKE_BLOCK here because gem_mmap
|
||||
* calls it for us. If we really want to be pedantic we could do a
|
||||
* VALGRIND_FREELIKE_BLOCK right after the mmap, but there's no good
|
||||
* reason.
|
||||
*/
|
||||
|
||||
*bo = new_bo;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo)
|
||||
{
|
||||
struct bo_pool_bo_link *link = bo->map;
|
||||
link->bo = *bo;
|
||||
|
||||
VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0));
|
||||
anv_ptr_free_list_push(&pool->free_list, link);
|
||||
}
|
706
src/vulkan/anv_cmd_buffer.c
Normal file
706
src/vulkan/anv_cmd_buffer.c
Normal file
@@ -0,0 +1,706 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
/** \file anv_cmd_buffer.c
|
||||
*
|
||||
* This file contains functions related to anv_cmd_buffer as a data
|
||||
* structure. This involves everything required to create and destroy
|
||||
* the actual batch buffers as well as link them together and handle
|
||||
* relocations and surface state. It specifically does *not* contain any
|
||||
* handling of actual vkCmd calls beyond vkCmdExecuteCommands.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------*
|
||||
* Functions related to anv_reloc_list
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
VkResult
|
||||
anv_reloc_list_init(struct anv_reloc_list *list, struct anv_device *device)
|
||||
{
|
||||
list->num_relocs = 0;
|
||||
list->array_length = 256;
|
||||
list->relocs =
|
||||
anv_device_alloc(device, list->array_length * sizeof(*list->relocs), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
|
||||
if (list->relocs == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
list->reloc_bos =
|
||||
anv_device_alloc(device, list->array_length * sizeof(*list->reloc_bos), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
|
||||
if (list->relocs == NULL) {
|
||||
anv_device_free(device, list->relocs);
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
anv_reloc_list_finish(struct anv_reloc_list *list, struct anv_device *device)
|
||||
{
|
||||
anv_device_free(device, list->relocs);
|
||||
anv_device_free(device, list->reloc_bos);
|
||||
}
|
||||
|
||||
static VkResult
|
||||
anv_reloc_list_grow(struct anv_reloc_list *list, struct anv_device *device,
|
||||
size_t num_additional_relocs)
|
||||
{
|
||||
if (list->num_relocs + num_additional_relocs <= list->array_length)
|
||||
return VK_SUCCESS;
|
||||
|
||||
size_t new_length = list->array_length * 2;
|
||||
while (new_length < list->num_relocs + num_additional_relocs)
|
||||
new_length *= 2;
|
||||
|
||||
struct drm_i915_gem_relocation_entry *new_relocs =
|
||||
anv_device_alloc(device, new_length * sizeof(*list->relocs), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
if (new_relocs == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
struct anv_bo **new_reloc_bos =
|
||||
anv_device_alloc(device, new_length * sizeof(*list->reloc_bos), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
if (new_relocs == NULL) {
|
||||
anv_device_free(device, new_relocs);
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
memcpy(new_relocs, list->relocs, list->num_relocs * sizeof(*list->relocs));
|
||||
memcpy(new_reloc_bos, list->reloc_bos,
|
||||
list->num_relocs * sizeof(*list->reloc_bos));
|
||||
|
||||
anv_device_free(device, list->relocs);
|
||||
anv_device_free(device, list->reloc_bos);
|
||||
|
||||
list->relocs = new_relocs;
|
||||
list->reloc_bos = new_reloc_bos;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
anv_reloc_list_add(struct anv_reloc_list *list, struct anv_device *device,
|
||||
uint32_t offset, struct anv_bo *target_bo, uint32_t delta)
|
||||
{
|
||||
struct drm_i915_gem_relocation_entry *entry;
|
||||
int index;
|
||||
|
||||
anv_reloc_list_grow(list, device, 1);
|
||||
/* TODO: Handle failure */
|
||||
|
||||
/* XXX: Can we use I915_EXEC_HANDLE_LUT? */
|
||||
index = list->num_relocs++;
|
||||
list->reloc_bos[index] = target_bo;
|
||||
entry = &list->relocs[index];
|
||||
entry->target_handle = target_bo->gem_handle;
|
||||
entry->delta = delta;
|
||||
entry->offset = offset;
|
||||
entry->presumed_offset = target_bo->offset;
|
||||
entry->read_domains = 0;
|
||||
entry->write_domain = 0;
|
||||
|
||||
return target_bo->offset + delta;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_reloc_list_append(struct anv_reloc_list *list, struct anv_device *device,
|
||||
struct anv_reloc_list *other, uint32_t offset)
|
||||
{
|
||||
anv_reloc_list_grow(list, device, other->num_relocs);
|
||||
/* TODO: Handle failure */
|
||||
|
||||
memcpy(&list->relocs[list->num_relocs], &other->relocs[0],
|
||||
other->num_relocs * sizeof(other->relocs[0]));
|
||||
memcpy(&list->reloc_bos[list->num_relocs], &other->reloc_bos[0],
|
||||
other->num_relocs * sizeof(other->reloc_bos[0]));
|
||||
|
||||
for (uint32_t i = 0; i < other->num_relocs; i++)
|
||||
list->relocs[i + list->num_relocs].offset += offset;
|
||||
|
||||
list->num_relocs += other->num_relocs;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*
|
||||
* Functions related to anv_batch
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
void *
|
||||
anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords)
|
||||
{
|
||||
if (batch->next + num_dwords * 4 > batch->end)
|
||||
batch->extend_cb(batch, batch->user_data);
|
||||
|
||||
void *p = batch->next;
|
||||
|
||||
batch->next += num_dwords * 4;
|
||||
assert(batch->next <= batch->end);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
anv_batch_emit_reloc(struct anv_batch *batch,
|
||||
void *location, struct anv_bo *bo, uint32_t delta)
|
||||
{
|
||||
return anv_reloc_list_add(&batch->relocs, batch->device,
|
||||
location - batch->start, bo, delta);
|
||||
}
|
||||
|
||||
void
|
||||
anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other)
|
||||
{
|
||||
uint32_t size, offset;
|
||||
|
||||
size = other->next - other->start;
|
||||
assert(size % 4 == 0);
|
||||
|
||||
if (batch->next + size > batch->end)
|
||||
batch->extend_cb(batch, batch->user_data);
|
||||
|
||||
assert(batch->next + size <= batch->end);
|
||||
|
||||
memcpy(batch->next, other->start, size);
|
||||
|
||||
offset = batch->next - batch->start;
|
||||
anv_reloc_list_append(&batch->relocs, batch->device,
|
||||
&other->relocs, offset);
|
||||
|
||||
batch->next += size;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*
|
||||
* Functions related to anv_batch_bo
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
static VkResult
|
||||
anv_batch_bo_create(struct anv_device *device, struct anv_batch_bo **bbo_out)
|
||||
{
|
||||
VkResult result;
|
||||
|
||||
struct anv_batch_bo *bbo =
|
||||
anv_device_alloc(device, sizeof(*bbo), 8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
if (bbo == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
bbo->num_relocs = 0;
|
||||
bbo->prev_batch_bo = NULL;
|
||||
|
||||
result = anv_bo_pool_alloc(&device->batch_bo_pool, &bbo->bo);
|
||||
if (result != VK_SUCCESS) {
|
||||
anv_device_free(device, bbo);
|
||||
return result;
|
||||
}
|
||||
|
||||
*bbo_out = bbo;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_batch_bo_start(struct anv_batch_bo *bbo, struct anv_batch *batch,
|
||||
size_t batch_padding)
|
||||
{
|
||||
batch->next = batch->start = bbo->bo.map;
|
||||
batch->end = bbo->bo.map + bbo->bo.size - batch_padding;
|
||||
bbo->first_reloc = batch->relocs.num_relocs;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_batch_bo_finish(struct anv_batch_bo *bbo, struct anv_batch *batch)
|
||||
{
|
||||
/* Round batch up to an even number of dwords. */
|
||||
if ((batch->next - batch->start) & 4)
|
||||
anv_batch_emit(batch, GEN8_MI_NOOP);
|
||||
|
||||
assert(batch->start == bbo->bo.map);
|
||||
bbo->length = batch->next - batch->start;
|
||||
VG(VALGRIND_CHECK_MEM_IS_DEFINED(batch->start, bbo->length));
|
||||
bbo->num_relocs = batch->relocs.num_relocs - bbo->first_reloc;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_batch_bo_destroy(struct anv_batch_bo *bbo, struct anv_device *device)
|
||||
{
|
||||
anv_bo_pool_free(&device->batch_bo_pool, &bbo->bo);
|
||||
anv_device_free(device, bbo);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*
|
||||
* Functions related to anv_batch_bo
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
static VkResult
|
||||
anv_cmd_buffer_chain_batch(struct anv_batch *batch, void *_data)
|
||||
{
|
||||
struct anv_cmd_buffer *cmd_buffer = _data;
|
||||
|
||||
struct anv_batch_bo *new_bbo, *old_bbo = cmd_buffer->last_batch_bo;
|
||||
|
||||
VkResult result = anv_batch_bo_create(cmd_buffer->device, &new_bbo);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
/* We set the end of the batch a little short so we would be sure we
|
||||
* have room for the chaining command. Since we're about to emit the
|
||||
* chaining command, let's set it back where it should go.
|
||||
*/
|
||||
batch->end += GEN8_MI_BATCH_BUFFER_START_length * 4;
|
||||
assert(batch->end == old_bbo->bo.map + old_bbo->bo.size);
|
||||
|
||||
anv_batch_emit(batch, GEN8_MI_BATCH_BUFFER_START,
|
||||
GEN8_MI_BATCH_BUFFER_START_header,
|
||||
._2ndLevelBatchBuffer = _1stlevelbatch,
|
||||
.AddressSpaceIndicator = ASI_PPGTT,
|
||||
.BatchBufferStartAddress = { &new_bbo->bo, 0 },
|
||||
);
|
||||
|
||||
anv_batch_bo_finish(cmd_buffer->last_batch_bo, batch);
|
||||
|
||||
new_bbo->prev_batch_bo = old_bbo;
|
||||
cmd_buffer->last_batch_bo = new_bbo;
|
||||
|
||||
anv_batch_bo_start(new_bbo, batch, GEN8_MI_BATCH_BUFFER_START_length * 4);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
struct anv_state
|
||||
anv_cmd_buffer_alloc_surface_state(struct anv_cmd_buffer *cmd_buffer,
|
||||
uint32_t size, uint32_t alignment)
|
||||
{
|
||||
struct anv_state state;
|
||||
|
||||
state.offset = align_u32(cmd_buffer->surface_next, alignment);
|
||||
if (state.offset + size > cmd_buffer->surface_batch_bo->bo.size)
|
||||
return (struct anv_state) { 0 };
|
||||
|
||||
state.map = cmd_buffer->surface_batch_bo->bo.map + state.offset;
|
||||
state.alloc_size = size;
|
||||
cmd_buffer->surface_next = state.offset + size;
|
||||
|
||||
assert(state.offset + size <= cmd_buffer->surface_batch_bo->bo.size);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
struct anv_state
|
||||
anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer,
|
||||
uint32_t size, uint32_t alignment)
|
||||
{
|
||||
return anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream,
|
||||
size, alignment);
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_cmd_buffer_new_surface_state_bo(struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct anv_batch_bo *new_bbo, *old_bbo = cmd_buffer->surface_batch_bo;
|
||||
|
||||
/* Finish off the old buffer */
|
||||
old_bbo->num_relocs =
|
||||
cmd_buffer->surface_relocs.num_relocs - old_bbo->first_reloc;
|
||||
old_bbo->length = cmd_buffer->surface_next;
|
||||
|
||||
VkResult result = anv_batch_bo_create(cmd_buffer->device, &new_bbo);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
new_bbo->first_reloc = cmd_buffer->surface_relocs.num_relocs;
|
||||
cmd_buffer->surface_next = 1;
|
||||
|
||||
new_bbo->prev_batch_bo = old_bbo;
|
||||
cmd_buffer->surface_batch_bo = new_bbo;
|
||||
|
||||
/* Re-emit state base addresses so we get the new surface state base
|
||||
* address before we start emitting binding tables etc.
|
||||
*/
|
||||
anv_cmd_buffer_emit_state_base_address(cmd_buffer);
|
||||
|
||||
/* After re-setting the surface state base address, we have to do some
|
||||
* cache flusing so that the sampler engine will pick up the new
|
||||
* SURFACE_STATE objects and binding tables. From the Broadwell PRM,
|
||||
* Shared Function > 3D Sampler > State > State Caching (page 96):
|
||||
*
|
||||
* Coherency with system memory in the state cache, like the texture
|
||||
* cache is handled partially by software. It is expected that the
|
||||
* command stream or shader will issue Cache Flush operation or
|
||||
* Cache_Flush sampler message to ensure that the L1 cache remains
|
||||
* coherent with system memory.
|
||||
*
|
||||
* [...]
|
||||
*
|
||||
* Whenever the value of the Dynamic_State_Base_Addr,
|
||||
* Surface_State_Base_Addr are altered, the L1 state cache must be
|
||||
* invalidated to ensure the new surface or sampler state is fetched
|
||||
* from system memory.
|
||||
*
|
||||
* The PIPE_CONTROL command has a "State Cache Invalidation Enable" bit
|
||||
* which, according the PIPE_CONTROL instruction documentation in the
|
||||
* Broadwell PRM:
|
||||
*
|
||||
* Setting this bit is independent of any other bit in this packet.
|
||||
* This bit controls the invalidation of the L1 and L2 state caches
|
||||
* at the top of the pipe i.e. at the parsing time.
|
||||
*
|
||||
* Unfortunately, experimentation seems to indicate that state cache
|
||||
* invalidation through a PIPE_CONTROL does nothing whatsoever in
|
||||
* regards to surface state and binding tables. In stead, it seems that
|
||||
* invalidating the texture cache is what is actually needed.
|
||||
*
|
||||
* XXX: As far as we have been able to determine through
|
||||
* experimentation, shows that flush the texture cache appears to be
|
||||
* sufficient. The theory here is that all of the sampling/rendering
|
||||
* units cache the binding table in the texture cache. However, we have
|
||||
* yet to be able to actually confirm this.
|
||||
*/
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
|
||||
.TextureCacheInvalidationEnable = true);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_CreateCommandBuffer(
|
||||
VkDevice _device,
|
||||
const VkCmdBufferCreateInfo* pCreateInfo,
|
||||
VkCmdBuffer* pCmdBuffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_cmd_buffer *cmd_buffer;
|
||||
VkResult result;
|
||||
|
||||
assert(pCreateInfo->level == VK_CMD_BUFFER_LEVEL_PRIMARY);
|
||||
|
||||
cmd_buffer = anv_device_alloc(device, sizeof(*cmd_buffer), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (cmd_buffer == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
cmd_buffer->device = device;
|
||||
|
||||
result = anv_batch_bo_create(device, &cmd_buffer->last_batch_bo);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
result = anv_reloc_list_init(&cmd_buffer->batch.relocs, device);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail_batch_bo;
|
||||
|
||||
cmd_buffer->batch.device = device;
|
||||
cmd_buffer->batch.extend_cb = anv_cmd_buffer_chain_batch;
|
||||
cmd_buffer->batch.user_data = cmd_buffer;
|
||||
|
||||
anv_batch_bo_start(cmd_buffer->last_batch_bo, &cmd_buffer->batch,
|
||||
GEN8_MI_BATCH_BUFFER_START_length * 4);
|
||||
|
||||
result = anv_batch_bo_create(device, &cmd_buffer->surface_batch_bo);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail_batch_relocs;
|
||||
cmd_buffer->surface_batch_bo->first_reloc = 0;
|
||||
|
||||
result = anv_reloc_list_init(&cmd_buffer->surface_relocs, device);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail_ss_batch_bo;
|
||||
|
||||
/* Start surface_next at 1 so surface offset 0 is invalid. */
|
||||
cmd_buffer->surface_next = 1;
|
||||
|
||||
cmd_buffer->exec2_objects = NULL;
|
||||
cmd_buffer->exec2_bos = NULL;
|
||||
cmd_buffer->exec2_array_length = 0;
|
||||
|
||||
anv_state_stream_init(&cmd_buffer->surface_state_stream,
|
||||
&device->surface_state_block_pool);
|
||||
anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
|
||||
&device->dynamic_state_block_pool);
|
||||
|
||||
anv_cmd_state_init(&cmd_buffer->state);
|
||||
|
||||
*pCmdBuffer = anv_cmd_buffer_to_handle(cmd_buffer);
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail_ss_batch_bo:
|
||||
anv_batch_bo_destroy(cmd_buffer->surface_batch_bo, device);
|
||||
fail_batch_relocs:
|
||||
anv_reloc_list_finish(&cmd_buffer->batch.relocs, device);
|
||||
fail_batch_bo:
|
||||
anv_batch_bo_destroy(cmd_buffer->last_batch_bo, device);
|
||||
fail:
|
||||
anv_device_free(device, cmd_buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult anv_DestroyCommandBuffer(
|
||||
VkDevice _device,
|
||||
VkCmdBuffer _cmd_buffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, _cmd_buffer);
|
||||
|
||||
anv_cmd_state_fini(&cmd_buffer->state);
|
||||
|
||||
/* Destroy all of the batch buffers */
|
||||
struct anv_batch_bo *bbo = cmd_buffer->last_batch_bo;
|
||||
while (bbo) {
|
||||
struct anv_batch_bo *prev = bbo->prev_batch_bo;
|
||||
anv_batch_bo_destroy(bbo, device);
|
||||
bbo = prev;
|
||||
}
|
||||
anv_reloc_list_finish(&cmd_buffer->batch.relocs, device);
|
||||
|
||||
/* Destroy all of the surface state buffers */
|
||||
bbo = cmd_buffer->surface_batch_bo;
|
||||
while (bbo) {
|
||||
struct anv_batch_bo *prev = bbo->prev_batch_bo;
|
||||
anv_batch_bo_destroy(bbo, device);
|
||||
bbo = prev;
|
||||
}
|
||||
anv_reloc_list_finish(&cmd_buffer->surface_relocs, device);
|
||||
|
||||
anv_state_stream_finish(&cmd_buffer->surface_state_stream);
|
||||
anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
|
||||
anv_device_free(device, cmd_buffer->exec2_objects);
|
||||
anv_device_free(device, cmd_buffer->exec2_bos);
|
||||
anv_device_free(device, cmd_buffer);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
anv_cmd_buffer_add_bo(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_bo *bo,
|
||||
struct drm_i915_gem_relocation_entry *relocs,
|
||||
size_t num_relocs)
|
||||
{
|
||||
struct drm_i915_gem_exec_object2 *obj;
|
||||
|
||||
if (bo->index < cmd_buffer->exec2_bo_count &&
|
||||
cmd_buffer->exec2_bos[bo->index] == bo)
|
||||
return VK_SUCCESS;
|
||||
|
||||
if (cmd_buffer->exec2_bo_count >= cmd_buffer->exec2_array_length) {
|
||||
uint32_t new_len = cmd_buffer->exec2_objects ?
|
||||
cmd_buffer->exec2_array_length * 2 : 64;
|
||||
|
||||
struct drm_i915_gem_exec_object2 *new_objects =
|
||||
anv_device_alloc(cmd_buffer->device, new_len * sizeof(*new_objects),
|
||||
8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
if (new_objects == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
struct anv_bo **new_bos =
|
||||
anv_device_alloc(cmd_buffer->device, new_len * sizeof(*new_bos),
|
||||
8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
|
||||
if (new_objects == NULL) {
|
||||
anv_device_free(cmd_buffer->device, new_objects);
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
if (cmd_buffer->exec2_objects) {
|
||||
memcpy(new_objects, cmd_buffer->exec2_objects,
|
||||
cmd_buffer->exec2_bo_count * sizeof(*new_objects));
|
||||
memcpy(new_bos, cmd_buffer->exec2_bos,
|
||||
cmd_buffer->exec2_bo_count * sizeof(*new_bos));
|
||||
}
|
||||
|
||||
cmd_buffer->exec2_objects = new_objects;
|
||||
cmd_buffer->exec2_bos = new_bos;
|
||||
cmd_buffer->exec2_array_length = new_len;
|
||||
}
|
||||
|
||||
assert(cmd_buffer->exec2_bo_count < cmd_buffer->exec2_array_length);
|
||||
|
||||
bo->index = cmd_buffer->exec2_bo_count++;
|
||||
obj = &cmd_buffer->exec2_objects[bo->index];
|
||||
cmd_buffer->exec2_bos[bo->index] = bo;
|
||||
|
||||
obj->handle = bo->gem_handle;
|
||||
obj->relocation_count = 0;
|
||||
obj->relocs_ptr = 0;
|
||||
obj->alignment = 0;
|
||||
obj->offset = bo->offset;
|
||||
obj->flags = 0;
|
||||
obj->rsvd1 = 0;
|
||||
obj->rsvd2 = 0;
|
||||
|
||||
if (relocs) {
|
||||
obj->relocation_count = num_relocs;
|
||||
obj->relocs_ptr = (uintptr_t) relocs;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_cmd_buffer_add_validate_bos(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_reloc_list *list)
|
||||
{
|
||||
for (size_t i = 0; i < list->num_relocs; i++)
|
||||
anv_cmd_buffer_add_bo(cmd_buffer, list->reloc_bos[i], NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
anv_cmd_buffer_process_relocs(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_reloc_list *list)
|
||||
{
|
||||
struct anv_bo *bo;
|
||||
|
||||
/* If the kernel supports I915_EXEC_NO_RELOC, it will compare offset in
|
||||
* struct drm_i915_gem_exec_object2 against the bos current offset and if
|
||||
* all bos haven't moved it will skip relocation processing alltogether.
|
||||
* If I915_EXEC_NO_RELOC is not supported, the kernel ignores the incoming
|
||||
* value of offset so we can set it either way. For that to work we need
|
||||
* to make sure all relocs use the same presumed offset.
|
||||
*/
|
||||
|
||||
for (size_t i = 0; i < list->num_relocs; i++) {
|
||||
bo = list->reloc_bos[i];
|
||||
if (bo->offset != list->relocs[i].presumed_offset)
|
||||
cmd_buffer->need_reloc = true;
|
||||
|
||||
list->relocs[i].target_handle = bo->index;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult anv_EndCommandBuffer(
|
||||
VkCmdBuffer cmdBuffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
|
||||
struct anv_device *device = cmd_buffer->device;
|
||||
struct anv_batch *batch = &cmd_buffer->batch;
|
||||
|
||||
anv_batch_emit(batch, GEN8_MI_BATCH_BUFFER_END);
|
||||
|
||||
anv_batch_bo_finish(cmd_buffer->last_batch_bo, &cmd_buffer->batch);
|
||||
cmd_buffer->surface_batch_bo->num_relocs =
|
||||
cmd_buffer->surface_relocs.num_relocs - cmd_buffer->surface_batch_bo->first_reloc;
|
||||
cmd_buffer->surface_batch_bo->length = cmd_buffer->surface_next;
|
||||
|
||||
cmd_buffer->exec2_bo_count = 0;
|
||||
cmd_buffer->need_reloc = false;
|
||||
|
||||
/* Lock for access to bo->index. */
|
||||
pthread_mutex_lock(&device->mutex);
|
||||
|
||||
/* Add surface state bos first so we can add them with their relocs. */
|
||||
for (struct anv_batch_bo *bbo = cmd_buffer->surface_batch_bo;
|
||||
bbo != NULL; bbo = bbo->prev_batch_bo) {
|
||||
anv_cmd_buffer_add_bo(cmd_buffer, &bbo->bo,
|
||||
&cmd_buffer->surface_relocs.relocs[bbo->first_reloc],
|
||||
bbo->num_relocs);
|
||||
}
|
||||
|
||||
/* Add all of the BOs referenced by surface state */
|
||||
anv_cmd_buffer_add_validate_bos(cmd_buffer, &cmd_buffer->surface_relocs);
|
||||
|
||||
/* Add all but the first batch BO */
|
||||
struct anv_batch_bo *batch_bo = cmd_buffer->last_batch_bo;
|
||||
while (batch_bo->prev_batch_bo) {
|
||||
anv_cmd_buffer_add_bo(cmd_buffer, &batch_bo->bo,
|
||||
&batch->relocs.relocs[batch_bo->first_reloc],
|
||||
batch_bo->num_relocs);
|
||||
batch_bo = batch_bo->prev_batch_bo;
|
||||
}
|
||||
|
||||
/* Add everything referenced by the batches */
|
||||
anv_cmd_buffer_add_validate_bos(cmd_buffer, &batch->relocs);
|
||||
|
||||
/* Add the first batch bo last */
|
||||
assert(batch_bo->prev_batch_bo == NULL && batch_bo->first_reloc == 0);
|
||||
anv_cmd_buffer_add_bo(cmd_buffer, &batch_bo->bo,
|
||||
&batch->relocs.relocs[batch_bo->first_reloc],
|
||||
batch_bo->num_relocs);
|
||||
assert(batch_bo->bo.index == cmd_buffer->exec2_bo_count - 1);
|
||||
|
||||
anv_cmd_buffer_process_relocs(cmd_buffer, &cmd_buffer->surface_relocs);
|
||||
anv_cmd_buffer_process_relocs(cmd_buffer, &batch->relocs);
|
||||
|
||||
cmd_buffer->execbuf.buffers_ptr = (uintptr_t) cmd_buffer->exec2_objects;
|
||||
cmd_buffer->execbuf.buffer_count = cmd_buffer->exec2_bo_count;
|
||||
cmd_buffer->execbuf.batch_start_offset = 0;
|
||||
cmd_buffer->execbuf.batch_len = batch->next - batch->start;
|
||||
cmd_buffer->execbuf.cliprects_ptr = 0;
|
||||
cmd_buffer->execbuf.num_cliprects = 0;
|
||||
cmd_buffer->execbuf.DR1 = 0;
|
||||
cmd_buffer->execbuf.DR4 = 0;
|
||||
|
||||
cmd_buffer->execbuf.flags = I915_EXEC_HANDLE_LUT;
|
||||
if (!cmd_buffer->need_reloc)
|
||||
cmd_buffer->execbuf.flags |= I915_EXEC_NO_RELOC;
|
||||
cmd_buffer->execbuf.flags |= I915_EXEC_RENDER;
|
||||
cmd_buffer->execbuf.rsvd1 = device->context_id;
|
||||
cmd_buffer->execbuf.rsvd2 = 0;
|
||||
|
||||
pthread_mutex_unlock(&device->mutex);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_ResetCommandBuffer(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkCmdBufferResetFlags flags)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
|
||||
|
||||
/* Delete all but the first batch bo */
|
||||
while (cmd_buffer->last_batch_bo->prev_batch_bo) {
|
||||
struct anv_batch_bo *prev = cmd_buffer->last_batch_bo->prev_batch_bo;
|
||||
anv_batch_bo_destroy(cmd_buffer->last_batch_bo, cmd_buffer->device);
|
||||
cmd_buffer->last_batch_bo = prev;
|
||||
}
|
||||
assert(cmd_buffer->last_batch_bo->prev_batch_bo == NULL);
|
||||
|
||||
cmd_buffer->batch.relocs.num_relocs = 0;
|
||||
anv_batch_bo_start(cmd_buffer->last_batch_bo, &cmd_buffer->batch,
|
||||
GEN8_MI_BATCH_BUFFER_START_length * 4);
|
||||
|
||||
/* Delete all but the first batch bo */
|
||||
while (cmd_buffer->surface_batch_bo->prev_batch_bo) {
|
||||
struct anv_batch_bo *prev = cmd_buffer->surface_batch_bo->prev_batch_bo;
|
||||
anv_batch_bo_destroy(cmd_buffer->surface_batch_bo, cmd_buffer->device);
|
||||
cmd_buffer->surface_batch_bo = prev;
|
||||
}
|
||||
assert(cmd_buffer->surface_batch_bo->prev_batch_bo == NULL);
|
||||
|
||||
cmd_buffer->surface_next = 1;
|
||||
cmd_buffer->surface_relocs.num_relocs = 0;
|
||||
|
||||
anv_cmd_state_fini(&cmd_buffer->state);
|
||||
anv_cmd_state_init(&cmd_buffer->state);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
1222
src/vulkan/anv_cmd_emit.c
Normal file
1222
src/vulkan/anv_cmd_emit.c
Normal file
File diff suppressed because it is too large
Load Diff
310
src/vulkan/aub.c
Normal file
310
src/vulkan/aub.c
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <drm.h>
|
||||
#include <i915_drm.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "aub.h"
|
||||
|
||||
struct anv_aub_writer {
|
||||
FILE *file;
|
||||
uint32_t offset;
|
||||
int gen;
|
||||
};
|
||||
|
||||
static void
|
||||
aub_out(struct anv_aub_writer *writer, uint32_t data)
|
||||
{
|
||||
fwrite(&data, 1, 4, writer->file);
|
||||
}
|
||||
|
||||
static void
|
||||
aub_out_data(struct anv_aub_writer *writer, const void *data, size_t size)
|
||||
{
|
||||
fwrite(data, 1, size, writer->file);
|
||||
}
|
||||
|
||||
static struct anv_aub_writer *
|
||||
get_anv_aub_writer(struct anv_device *device)
|
||||
{
|
||||
struct anv_aub_writer *writer = device->aub_writer;
|
||||
int entry = 0x200003;
|
||||
int i;
|
||||
int gtt_size = 0x10000;
|
||||
const char *filename;
|
||||
|
||||
if (geteuid() != getuid())
|
||||
return NULL;
|
||||
|
||||
if (writer)
|
||||
return writer;
|
||||
|
||||
writer = malloc(sizeof(*writer));
|
||||
if (writer == NULL)
|
||||
return NULL;
|
||||
|
||||
filename = "intel.aub";
|
||||
writer->gen = device->info.gen;
|
||||
writer->file = fopen(filename, "w+");
|
||||
if (!writer->file) {
|
||||
free(writer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Start allocating objects from just after the GTT. */
|
||||
writer->offset = gtt_size;
|
||||
|
||||
/* Start with a (required) version packet. */
|
||||
aub_out(writer, CMD_AUB_HEADER | (13 - 2));
|
||||
aub_out(writer,
|
||||
(4 << AUB_HEADER_MAJOR_SHIFT) |
|
||||
(0 << AUB_HEADER_MINOR_SHIFT));
|
||||
for (i = 0; i < 8; i++) {
|
||||
aub_out(writer, 0); /* app name */
|
||||
}
|
||||
aub_out(writer, 0); /* timestamp */
|
||||
aub_out(writer, 0); /* timestamp */
|
||||
aub_out(writer, 0); /* comment len */
|
||||
|
||||
/* Set up the GTT. The max we can handle is 256M */
|
||||
aub_out(writer, CMD_AUB_TRACE_HEADER_BLOCK | ((writer->gen >= 8 ? 6 : 5) - 2));
|
||||
aub_out(writer,
|
||||
AUB_TRACE_MEMTYPE_GTT_ENTRY |
|
||||
AUB_TRACE_TYPE_NOTYPE | AUB_TRACE_OP_DATA_WRITE);
|
||||
aub_out(writer, 0); /* subtype */
|
||||
aub_out(writer, 0); /* offset */
|
||||
aub_out(writer, gtt_size); /* size */
|
||||
if (writer->gen >= 8)
|
||||
aub_out(writer, 0);
|
||||
for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
|
||||
aub_out(writer, entry);
|
||||
}
|
||||
|
||||
return device->aub_writer = writer;
|
||||
}
|
||||
|
||||
void
|
||||
anv_aub_writer_destroy(struct anv_aub_writer *writer)
|
||||
{
|
||||
fclose(writer->file);
|
||||
free(writer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Break up large objects into multiple writes. Otherwise a 128kb VBO
|
||||
* would overflow the 16 bits of size field in the packet header and
|
||||
* everything goes badly after that.
|
||||
*/
|
||||
static void
|
||||
aub_write_trace_block(struct anv_aub_writer *writer, uint32_t type,
|
||||
void *virtual, uint32_t size, uint32_t gtt_offset)
|
||||
{
|
||||
uint32_t block_size;
|
||||
uint32_t offset;
|
||||
uint32_t subtype = 0;
|
||||
static const char null_block[8 * 4096];
|
||||
|
||||
for (offset = 0; offset < size; offset += block_size) {
|
||||
block_size = size - offset;
|
||||
|
||||
if (block_size > 8 * 4096)
|
||||
block_size = 8 * 4096;
|
||||
|
||||
aub_out(writer,
|
||||
CMD_AUB_TRACE_HEADER_BLOCK |
|
||||
((writer->gen >= 8 ? 6 : 5) - 2));
|
||||
aub_out(writer,
|
||||
AUB_TRACE_MEMTYPE_GTT |
|
||||
type | AUB_TRACE_OP_DATA_WRITE);
|
||||
aub_out(writer, subtype);
|
||||
aub_out(writer, gtt_offset + offset);
|
||||
aub_out(writer, align_u32(block_size, 4));
|
||||
if (writer->gen >= 8)
|
||||
aub_out(writer, 0);
|
||||
|
||||
if (virtual)
|
||||
aub_out_data(writer, (char *) virtual + offset, block_size);
|
||||
else
|
||||
aub_out_data(writer, null_block, block_size);
|
||||
|
||||
/* Pad to a multiple of 4 bytes. */
|
||||
aub_out_data(writer, null_block, -block_size & 3);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a ringbuffer on fly and dump it
|
||||
*/
|
||||
static void
|
||||
aub_build_dump_ringbuffer(struct anv_aub_writer *writer,
|
||||
uint32_t batch_offset, uint32_t offset,
|
||||
int ring_flag)
|
||||
{
|
||||
uint32_t ringbuffer[4096];
|
||||
int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */
|
||||
int ring_count = 0;
|
||||
|
||||
if (ring_flag == I915_EXEC_BSD)
|
||||
ring = AUB_TRACE_TYPE_RING_PRB1;
|
||||
else if (ring_flag == I915_EXEC_BLT)
|
||||
ring = AUB_TRACE_TYPE_RING_PRB2;
|
||||
|
||||
/* Make a ring buffer to execute our batchbuffer. */
|
||||
memset(ringbuffer, 0, sizeof(ringbuffer));
|
||||
if (writer->gen >= 8) {
|
||||
ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2);
|
||||
ringbuffer[ring_count++] = batch_offset;
|
||||
ringbuffer[ring_count++] = 0;
|
||||
} else {
|
||||
ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
|
||||
ringbuffer[ring_count++] = batch_offset;
|
||||
}
|
||||
|
||||
/* Write out the ring. This appears to trigger execution of
|
||||
* the ring in the simulator.
|
||||
*/
|
||||
aub_out(writer,
|
||||
CMD_AUB_TRACE_HEADER_BLOCK |
|
||||
((writer->gen >= 8 ? 6 : 5) - 2));
|
||||
aub_out(writer,
|
||||
AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
|
||||
aub_out(writer, 0); /* general/surface subtype */
|
||||
aub_out(writer, offset);
|
||||
aub_out(writer, ring_count * 4);
|
||||
if (writer->gen >= 8)
|
||||
aub_out(writer, 0);
|
||||
|
||||
/* FIXME: Need some flush operations here? */
|
||||
aub_out_data(writer, ringbuffer, ring_count * 4);
|
||||
}
|
||||
|
||||
struct aub_bo {
|
||||
uint32_t offset;
|
||||
void *map;
|
||||
void *relocated;
|
||||
};
|
||||
|
||||
static void
|
||||
relocate_bo(struct anv_bo *bo, struct drm_i915_gem_relocation_entry *relocs,
|
||||
size_t num_relocs, struct aub_bo *bos)
|
||||
{
|
||||
struct aub_bo *aub_bo = &bos[bo->index];
|
||||
struct drm_i915_gem_relocation_entry *reloc;
|
||||
uint32_t *dw;
|
||||
|
||||
aub_bo->relocated = malloc(bo->size);
|
||||
memcpy(aub_bo->relocated, aub_bo->map, bo->size);
|
||||
for (size_t i = 0; i < num_relocs; i++) {
|
||||
reloc = &relocs[i];
|
||||
assert(reloc->offset < bo->size);
|
||||
dw = aub_bo->relocated + reloc->offset;
|
||||
*dw = bos[reloc->target_handle].offset + reloc->delta;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct anv_device *device = cmd_buffer->device;
|
||||
struct anv_batch *batch = &cmd_buffer->batch;
|
||||
struct anv_aub_writer *writer;
|
||||
struct anv_bo *bo;
|
||||
uint32_t ring_flag = 0;
|
||||
uint32_t offset;
|
||||
struct aub_bo *aub_bos;
|
||||
|
||||
writer = get_anv_aub_writer(device);
|
||||
if (writer == NULL)
|
||||
return;
|
||||
|
||||
aub_bos = malloc(cmd_buffer->exec2_bo_count * sizeof(aub_bos[0]));
|
||||
offset = writer->offset;
|
||||
for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++) {
|
||||
bo = cmd_buffer->exec2_bos[i];
|
||||
if (bo->map)
|
||||
aub_bos[i].map = bo->map;
|
||||
else
|
||||
aub_bos[i].map = anv_gem_mmap(device, bo->gem_handle, 0, bo->size);
|
||||
aub_bos[i].relocated = aub_bos[i].map;
|
||||
aub_bos[i].offset = offset;
|
||||
offset = align_u32(offset + bo->size + 4095, 4096);
|
||||
}
|
||||
|
||||
struct anv_batch_bo *first_bbo;
|
||||
for (struct anv_batch_bo *bbo = cmd_buffer->last_batch_bo;
|
||||
bbo != NULL; bbo = bbo->prev_batch_bo) {
|
||||
/* Keep stashing the current BO until we get to the beginning */
|
||||
first_bbo = bbo;
|
||||
|
||||
/* Handle relocations for this batch BO */
|
||||
relocate_bo(&bbo->bo, &batch->relocs.relocs[bbo->first_reloc],
|
||||
bbo->num_relocs, aub_bos);
|
||||
}
|
||||
assert(first_bbo->prev_batch_bo == NULL);
|
||||
|
||||
for (struct anv_batch_bo *bbo = cmd_buffer->surface_batch_bo;
|
||||
bbo != NULL; bbo = bbo->prev_batch_bo) {
|
||||
|
||||
/* Handle relocations for this surface state BO */
|
||||
relocate_bo(&bbo->bo,
|
||||
&cmd_buffer->surface_relocs.relocs[bbo->first_reloc],
|
||||
bbo->num_relocs, aub_bos);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++) {
|
||||
bo = cmd_buffer->exec2_bos[i];
|
||||
if (i == cmd_buffer->exec2_bo_count - 1) {
|
||||
assert(bo == &first_bbo->bo);
|
||||
aub_write_trace_block(writer, AUB_TRACE_TYPE_BATCH,
|
||||
aub_bos[i].relocated,
|
||||
first_bbo->length, aub_bos[i].offset);
|
||||
} else {
|
||||
aub_write_trace_block(writer, AUB_TRACE_TYPE_NOTYPE,
|
||||
aub_bos[i].relocated,
|
||||
bo->size, aub_bos[i].offset);
|
||||
}
|
||||
if (aub_bos[i].relocated != aub_bos[i].map)
|
||||
free(aub_bos[i].relocated);
|
||||
if (aub_bos[i].map != bo->map)
|
||||
anv_gem_munmap(aub_bos[i].map, bo->size);
|
||||
}
|
||||
|
||||
/* Dump ring buffer */
|
||||
aub_build_dump_ringbuffer(writer, aub_bos[first_bbo->bo.index].offset,
|
||||
offset, ring_flag);
|
||||
|
||||
free(aub_bos);
|
||||
|
||||
fflush(writer->file);
|
||||
}
|
153
src/vulkan/aub.h
Normal file
153
src/vulkan/aub.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file intel_aub.h
|
||||
*
|
||||
* The AUB file is a file format used by Intel's internal simulation
|
||||
* and other validation tools. It can be used at various levels by a
|
||||
* driver to input state to the simulated hardware or a replaying
|
||||
* debugger.
|
||||
*
|
||||
* We choose to dump AUB files using the trace block format for ease
|
||||
* of implementation -- dump out the blocks of memory as plain blobs
|
||||
* and insert ring commands to execute the batchbuffer blob.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_AUB_H
|
||||
#define _INTEL_AUB_H
|
||||
|
||||
#define AUB_MI_NOOP (0)
|
||||
#define AUB_MI_BATCH_BUFFER_START (0x31 << 23)
|
||||
#define AUB_PIPE_CONTROL (0x7a000002)
|
||||
|
||||
/* DW0: instruction type. */
|
||||
|
||||
#define CMD_AUB (7 << 29)
|
||||
|
||||
#define CMD_AUB_HEADER (CMD_AUB | (1 << 23) | (0x05 << 16))
|
||||
/* DW1 */
|
||||
# define AUB_HEADER_MAJOR_SHIFT 24
|
||||
# define AUB_HEADER_MINOR_SHIFT 16
|
||||
|
||||
#define CMD_AUB_TRACE_HEADER_BLOCK (CMD_AUB | (1 << 23) | (0x41 << 16))
|
||||
#define CMD_AUB_DUMP_BMP (CMD_AUB | (1 << 23) | (0x9e << 16))
|
||||
|
||||
/* DW1 */
|
||||
#define AUB_TRACE_OPERATION_MASK 0x000000ff
|
||||
#define AUB_TRACE_OP_COMMENT 0x00000000
|
||||
#define AUB_TRACE_OP_DATA_WRITE 0x00000001
|
||||
#define AUB_TRACE_OP_COMMAND_WRITE 0x00000002
|
||||
#define AUB_TRACE_OP_MMIO_WRITE 0x00000003
|
||||
// operation = TRACE_DATA_WRITE, Type
|
||||
#define AUB_TRACE_TYPE_MASK 0x0000ff00
|
||||
#define AUB_TRACE_TYPE_NOTYPE (0 << 8)
|
||||
#define AUB_TRACE_TYPE_BATCH (1 << 8)
|
||||
#define AUB_TRACE_TYPE_VERTEX_BUFFER (5 << 8)
|
||||
#define AUB_TRACE_TYPE_2D_MAP (6 << 8)
|
||||
#define AUB_TRACE_TYPE_CUBE_MAP (7 << 8)
|
||||
#define AUB_TRACE_TYPE_VOLUME_MAP (9 << 8)
|
||||
#define AUB_TRACE_TYPE_1D_MAP (10 << 8)
|
||||
#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8)
|
||||
#define AUB_TRACE_TYPE_CONSTANT_URB (12 << 8)
|
||||
#define AUB_TRACE_TYPE_INDEX_BUFFER (13 << 8)
|
||||
#define AUB_TRACE_TYPE_GENERAL (14 << 8)
|
||||
#define AUB_TRACE_TYPE_SURFACE (15 << 8)
|
||||
|
||||
|
||||
// operation = TRACE_COMMAND_WRITE, Type =
|
||||
#define AUB_TRACE_TYPE_RING_HWB (1 << 8)
|
||||
#define AUB_TRACE_TYPE_RING_PRB0 (2 << 8)
|
||||
#define AUB_TRACE_TYPE_RING_PRB1 (3 << 8)
|
||||
#define AUB_TRACE_TYPE_RING_PRB2 (4 << 8)
|
||||
|
||||
// Address space
|
||||
#define AUB_TRACE_ADDRESS_SPACE_MASK 0x00ff0000
|
||||
#define AUB_TRACE_MEMTYPE_GTT (0 << 16)
|
||||
#define AUB_TRACE_MEMTYPE_LOCAL (1 << 16)
|
||||
#define AUB_TRACE_MEMTYPE_NONLOCAL (2 << 16)
|
||||
#define AUB_TRACE_MEMTYPE_PCI (3 << 16)
|
||||
#define AUB_TRACE_MEMTYPE_GTT_ENTRY (4 << 16)
|
||||
|
||||
/* DW2 */
|
||||
|
||||
/**
|
||||
* aub_state_struct_type enum values are encoded with the top 16 bits
|
||||
* representing the type to be delivered to the .aub file, and the bottom 16
|
||||
* bits representing the subtype. This macro performs the encoding.
|
||||
*/
|
||||
#define ENCODE_SS_TYPE(type, subtype) (((type) << 16) | (subtype))
|
||||
|
||||
enum aub_state_struct_type {
|
||||
AUB_TRACE_VS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 1),
|
||||
AUB_TRACE_GS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 2),
|
||||
AUB_TRACE_CLIP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 3),
|
||||
AUB_TRACE_SF_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 4),
|
||||
AUB_TRACE_WM_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 5),
|
||||
AUB_TRACE_CC_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 6),
|
||||
AUB_TRACE_CLIP_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 7),
|
||||
AUB_TRACE_SF_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 8),
|
||||
AUB_TRACE_CC_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x9),
|
||||
AUB_TRACE_SAMPLER_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xa),
|
||||
AUB_TRACE_KERNEL_INSTRUCTIONS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xb),
|
||||
AUB_TRACE_SCRATCH_SPACE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xc),
|
||||
AUB_TRACE_SAMPLER_DEFAULT_COLOR = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xd),
|
||||
|
||||
AUB_TRACE_SCISSOR_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x15),
|
||||
AUB_TRACE_BLEND_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x16),
|
||||
AUB_TRACE_DEPTH_STENCIL_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x17),
|
||||
|
||||
AUB_TRACE_VERTEX_BUFFER = ENCODE_SS_TYPE(AUB_TRACE_TYPE_VERTEX_BUFFER, 0),
|
||||
AUB_TRACE_BINDING_TABLE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x100),
|
||||
AUB_TRACE_SURFACE_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x200),
|
||||
AUB_TRACE_VS_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 0),
|
||||
AUB_TRACE_WM_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 1),
|
||||
};
|
||||
|
||||
#undef ENCODE_SS_TYPE
|
||||
|
||||
/**
|
||||
* Decode a aub_state_struct_type value to determine the type that should be
|
||||
* stored in the .aub file.
|
||||
*/
|
||||
static inline uint32_t AUB_TRACE_TYPE(enum aub_state_struct_type ss_type)
|
||||
{
|
||||
return (ss_type & 0xFFFF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a state_struct_type value to determine the subtype that should be
|
||||
* stored in the .aub file.
|
||||
*/
|
||||
static inline uint32_t AUB_TRACE_SUBTYPE(enum aub_state_struct_type ss_type)
|
||||
{
|
||||
return ss_type & 0xFFFF;
|
||||
}
|
||||
|
||||
/* DW3: address */
|
||||
/* DW4: len */
|
||||
|
||||
#endif /* _INTEL_AUB_H */
|
1213
src/vulkan/compiler.cpp
Normal file
1213
src/vulkan/compiler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2390
src/vulkan/device.c
Normal file
2390
src/vulkan/device.c
Normal file
File diff suppressed because it is too large
Load Diff
334
src/vulkan/formats.c
Normal file
334
src/vulkan/formats.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#define UNSUPPORTED 0xffff
|
||||
|
||||
#define fmt(__vk_fmt, ...) \
|
||||
[__vk_fmt] = { .name = #__vk_fmt, __VA_ARGS__ }
|
||||
|
||||
static const struct anv_format anv_formats[] = {
|
||||
fmt(VK_FORMAT_UNDEFINED, RAW, .cpp = 1, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R4G4_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R4G4_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R4G4B4A4_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R4G4B4A4_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R5G6B5_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R5G6B5_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R5G5B5A1_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R5G5B5A1_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R8_UNORM, R8_UNORM, .cpp = 1, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R8_SNORM, R8_SNORM, .cpp = 1, .num_channels = 1,),
|
||||
fmt(VK_FORMAT_R8_USCALED, R8_USCALED, .cpp = 1, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R8_SSCALED, R8_SSCALED, .cpp = 1, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R8_UINT, R8_UINT, .cpp = 1, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R8_SINT, R8_SINT, .cpp = 1, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R8_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_R8G8_UNORM, R8G8_UNORM, .cpp = 2, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R8G8_SNORM, R8G8_SNORM, .cpp = 2, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R8G8_USCALED, R8G8_USCALED, .cpp = 2, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R8G8_SSCALED, R8G8_SSCALED, .cpp = 2, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R8G8_UINT, R8G8_UINT, .cpp = 2, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R8G8_SINT, R8G8_SINT, .cpp = 2, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R8G8_SRGB, UNSUPPORTED), /* L8A8_UNORM_SRGB */
|
||||
fmt(VK_FORMAT_R8G8B8_UNORM, R8G8B8X8_UNORM, .cpp = 3, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R8G8B8_SNORM, R8G8B8_SNORM, .cpp = 3, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R8G8B8_USCALED, R8G8B8_USCALED, .cpp = 3, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R8G8B8_SSCALED, R8G8B8_SSCALED, .cpp = 3, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R8G8B8_UINT, R8G8B8_UINT, .cpp = 3, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R8G8B8_SINT, R8G8B8_SINT, .cpp = 3, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R8G8B8_SRGB, UNSUPPORTED), /* B8G8R8A8_UNORM_SRGB */
|
||||
fmt(VK_FORMAT_R8G8B8A8_UNORM, R8G8B8A8_UNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R8G8B8A8_SNORM, R8G8B8A8_SNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R8G8B8A8_USCALED, R8G8B8A8_USCALED, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R8G8B8A8_SSCALED, R8G8B8A8_SSCALED, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R8G8B8A8_UINT, R8G8B8A8_UINT, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R8G8B8A8_SINT, R8G8B8A8_SINT, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R8G8B8A8_SRGB, R8G8B8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R10G10B10A2_UNORM, R10G10B10A2_UNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R10G10B10A2_SNORM, R10G10B10A2_SNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R10G10B10A2_USCALED, R10G10B10A2_USCALED, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R10G10B10A2_SSCALED, R10G10B10A2_SSCALED, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R10G10B10A2_UINT, R10G10B10A2_UINT, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R10G10B10A2_SINT, R10G10B10A2_SINT, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16_SNORM, R16_SNORM, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16_USCALED, R16_USCALED, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16_SSCALED, R16_SSCALED, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16_UINT, R16_UINT, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16_SINT, R16_SINT, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16_SFLOAT, R16_FLOAT, .cpp = 2, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R16G16_UNORM, R16G16_UNORM, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16_SNORM, R16G16_SNORM, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16_USCALED, R16G16_USCALED, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16_SSCALED, R16G16_SSCALED, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16_UINT, R16G16_UINT, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16_SINT, R16G16_SINT, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16_SFLOAT, R16G16_FLOAT, .cpp = 4, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R16G16B16_UNORM, R16G16B16_UNORM, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16_SNORM, R16G16B16_SNORM, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16_USCALED, R16G16B16_USCALED, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16_SSCALED, R16G16B16_SSCALED, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16_UINT, R16G16B16_UINT, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16_SINT, R16G16B16_SINT, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16_SFLOAT, R16G16B16_FLOAT, .cpp = 6, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R16G16B16A16_UNORM, R16G16B16A16_UNORM, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16G16B16A16_SNORM, R16G16B16A16_SNORM, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16G16B16A16_USCALED, R16G16B16A16_USCALED, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16G16B16A16_SSCALED, R16G16B16A16_SSCALED, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16G16B16A16_UINT, R16G16B16A16_UINT, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16G16B16A16_SINT, R16G16B16A16_SINT, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R16G16B16A16_SFLOAT, R16G16B16A16_FLOAT, .cpp = 8, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R32_UINT, R32_UINT, .cpp = 4, .num_channels = 1,),
|
||||
fmt(VK_FORMAT_R32_SINT, R32_SINT, .cpp = 4, .num_channels = 1,),
|
||||
fmt(VK_FORMAT_R32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1,),
|
||||
fmt(VK_FORMAT_R32G32_UINT, R32G32_UINT, .cpp = 8, .num_channels = 2,),
|
||||
fmt(VK_FORMAT_R32G32_SINT, R32G32_SINT, .cpp = 8, .num_channels = 2,),
|
||||
fmt(VK_FORMAT_R32G32_SFLOAT, R32G32_FLOAT, .cpp = 8, .num_channels = 2,),
|
||||
fmt(VK_FORMAT_R32G32B32_UINT, R32G32B32_UINT, .cpp = 12, .num_channels = 3,),
|
||||
fmt(VK_FORMAT_R32G32B32_SINT, R32G32B32_SINT, .cpp = 12, .num_channels = 3,),
|
||||
fmt(VK_FORMAT_R32G32B32_SFLOAT, R32G32B32_FLOAT, .cpp = 12, .num_channels = 3,),
|
||||
fmt(VK_FORMAT_R32G32B32A32_UINT, R32G32B32A32_UINT, .cpp = 16, .num_channels = 4,),
|
||||
fmt(VK_FORMAT_R32G32B32A32_SINT, R32G32B32A32_SINT, .cpp = 16, .num_channels = 4,),
|
||||
fmt(VK_FORMAT_R32G32B32A32_SFLOAT, R32G32B32A32_FLOAT, .cpp = 16, .num_channels = 4,),
|
||||
fmt(VK_FORMAT_R64_SFLOAT, R64_FLOAT, .cpp = 8, .num_channels = 1),
|
||||
fmt(VK_FORMAT_R64G64_SFLOAT, R64G64_FLOAT, .cpp = 16, .num_channels = 2),
|
||||
fmt(VK_FORMAT_R64G64B64_SFLOAT, R64G64B64_FLOAT, .cpp = 24, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R64G64B64A64_SFLOAT, R64G64B64A64_FLOAT, .cpp = 32, .num_channels = 4),
|
||||
fmt(VK_FORMAT_R11G11B10_UFLOAT, R11G11B10_FLOAT, .cpp = 4, .num_channels = 3),
|
||||
fmt(VK_FORMAT_R9G9B9E5_UFLOAT, R9G9B9E5_SHAREDEXP, .cpp = 4, .num_channels = 3),
|
||||
|
||||
fmt(VK_FORMAT_D16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1, .depth_format = D16_UNORM),
|
||||
fmt(VK_FORMAT_D24_UNORM, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 1, .depth_format = D24_UNORM_X8_UINT),
|
||||
fmt(VK_FORMAT_D32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1, .depth_format = D32_FLOAT),
|
||||
fmt(VK_FORMAT_S8_UINT, R8_UINT, .cpp = 1, .num_channels = 1, .has_stencil = true),
|
||||
fmt(VK_FORMAT_D16_UNORM_S8_UINT, R16_UNORM, .cpp = 2, .num_channels = 2, .depth_format = D16_UNORM, .has_stencil = true),
|
||||
fmt(VK_FORMAT_D24_UNORM_S8_UINT, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 2, .depth_format = D24_UNORM_X8_UINT, .has_stencil = true),
|
||||
fmt(VK_FORMAT_D32_SFLOAT_S8_UINT, R32_FLOAT, .cpp = 4, .num_channels = 2, .depth_format = D32_FLOAT, .has_stencil = true),
|
||||
|
||||
fmt(VK_FORMAT_BC1_RGB_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC1_RGB_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC1_RGBA_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC1_RGBA_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC2_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC2_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC3_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC3_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC4_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC4_SNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC5_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC5_SNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC6H_UFLOAT, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC6H_SFLOAT, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC7_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_BC7_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ETC2_R8G8B8_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ETC2_R8G8B8_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ETC2_R8G8B8A1_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ETC2_R8G8B8A1_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ETC2_R8G8B8A8_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ETC2_R8G8B8A8_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_EAC_R11_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_EAC_R11_SNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_EAC_R11G11_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_EAC_R11G11_SNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_4x4_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_4x4_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_5x4_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_5x4_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_5x5_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_5x5_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_6x5_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_6x5_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_6x6_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_6x6_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_8x5_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_8x5_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_8x6_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_8x6_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_8x8_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_8x8_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x5_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x5_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x6_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x6_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x8_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x8_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x10_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_10x10_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_12x10_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_12x10_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_12x12_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_ASTC_12x12_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B4G4R4A4_UNORM, B4G4R4A4_UNORM, .cpp = 2, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B5G5R5A1_UNORM, B5G5R5A1_UNORM, .cpp = 2, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B5G6R5_UNORM, B5G6R5_UNORM, .cpp = 2, .num_channels = 3),
|
||||
fmt(VK_FORMAT_B5G6R5_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_UNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_SNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_SSCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_UINT, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_SINT, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8_SRGB, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8A8_UNORM, B8G8R8A8_UNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B8G8R8A8_SNORM, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8A8_USCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8A8_SSCALED, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8A8_UINT, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8A8_SINT, UNSUPPORTED),
|
||||
fmt(VK_FORMAT_B8G8R8A8_SRGB, B8G8R8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B10G10R10A2_UNORM, B10G10R10A2_UNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B10G10R10A2_SNORM, B10G10R10A2_SNORM, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B10G10R10A2_USCALED, B10G10R10A2_USCALED, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B10G10R10A2_SSCALED, B10G10R10A2_SSCALED, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B10G10R10A2_UINT, B10G10R10A2_UINT, .cpp = 4, .num_channels = 4),
|
||||
fmt(VK_FORMAT_B10G10R10A2_SINT, B10G10R10A2_SINT, .cpp = 4, .num_channels = 4)
|
||||
};
|
||||
|
||||
#undef fmt
|
||||
|
||||
const struct anv_format *
|
||||
anv_format_for_vk_format(VkFormat format)
|
||||
{
|
||||
return &anv_formats[format];
|
||||
}
|
||||
|
||||
bool
|
||||
anv_is_vk_format_depth_or_stencil(VkFormat format)
|
||||
{
|
||||
const struct anv_format *format_info =
|
||||
anv_format_for_vk_format(format);
|
||||
|
||||
if (format_info->depth_format != UNSUPPORTED &&
|
||||
format_info->depth_format != 0)
|
||||
return true;
|
||||
|
||||
return format_info->has_stencil;
|
||||
}
|
||||
|
||||
// Format capabilities
|
||||
|
||||
struct surface_format_info {
|
||||
bool exists;
|
||||
int sampling;
|
||||
int filtering;
|
||||
int shadow_compare;
|
||||
int chroma_key;
|
||||
int render_target;
|
||||
int alpha_blend;
|
||||
int input_vb;
|
||||
int streamed_output_vb;
|
||||
int color_processing;
|
||||
};
|
||||
|
||||
extern const struct surface_format_info surface_formats[];
|
||||
|
||||
VkResult anv_validate_GetPhysicalDeviceFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat _format,
|
||||
VkFormatProperties* pFormatProperties)
|
||||
{
|
||||
const struct anv_format *format = anv_format_for_vk_format(_format);
|
||||
fprintf(stderr, "vkGetFormatProperties(%s)\n", format->name);
|
||||
return anv_GetPhysicalDeviceFormatProperties(physicalDevice, _format, pFormatProperties);
|
||||
}
|
||||
|
||||
VkResult anv_GetPhysicalDeviceFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat _format,
|
||||
VkFormatProperties* pFormatProperties)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
|
||||
const struct surface_format_info *info;
|
||||
int gen;
|
||||
|
||||
const struct anv_format *format = anv_format_for_vk_format(_format);
|
||||
if (format == NULL)
|
||||
return vk_error(VK_ERROR_INVALID_VALUE);
|
||||
|
||||
gen = physical_device->info->gen * 10;
|
||||
if (physical_device->info->is_haswell)
|
||||
gen += 5;
|
||||
|
||||
if (format->surface_format == UNSUPPORTED)
|
||||
goto unsupported;
|
||||
|
||||
info = &surface_formats[format->surface_format];
|
||||
if (!info->exists)
|
||||
goto unsupported;
|
||||
|
||||
uint32_t linear = 0, tiled = 0;
|
||||
if (info->sampling <= gen) {
|
||||
linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
||||
tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
||||
}
|
||||
if (info->render_target <= gen) {
|
||||
linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
||||
tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
if (info->alpha_blend <= gen) {
|
||||
linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
|
||||
tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
|
||||
}
|
||||
if (info->input_vb <= gen) {
|
||||
linear |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
|
||||
}
|
||||
|
||||
pFormatProperties->linearTilingFeatures = linear;
|
||||
pFormatProperties->optimalTilingFeatures = tiled;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
unsupported:
|
||||
pFormatProperties->linearTilingFeatures = 0;
|
||||
pFormatProperties->optimalTilingFeatures = 0;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_GetPhysicalDeviceImageFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkImageType type,
|
||||
VkImageTiling tiling,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageFormatProperties* pImageFormatProperties)
|
||||
{
|
||||
/* TODO: We should do something here. Chad? */
|
||||
stub_return(VK_UNSUPPORTED);
|
||||
}
|
||||
|
||||
VkResult anv_GetPhysicalDeviceSparseImageFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkImageType type,
|
||||
uint32_t samples,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageTiling tiling,
|
||||
uint32_t* pNumProperties,
|
||||
VkSparseImageFormatProperties* pProperties)
|
||||
{
|
||||
stub_return(VK_UNSUPPORTED);
|
||||
}
|
279
src/vulkan/gem.c
Normal file
279
src/vulkan/gem.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
|
||||
|
||||
static int
|
||||
anv_ioctl(int fd, unsigned long request, void *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = ioctl(fd, request, arg);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around DRM_IOCTL_I915_GEM_CREATE.
|
||||
*
|
||||
* Return gem handle, or 0 on failure. Gem handles are never 0.
|
||||
*/
|
||||
uint32_t
|
||||
anv_gem_create(struct anv_device *device, size_t size)
|
||||
{
|
||||
struct drm_i915_gem_create gem_create;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(gem_create);
|
||||
gem_create.size = size;
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
|
||||
if (ret != 0) {
|
||||
/* FIXME: What do we do if this fails? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gem_create.handle;
|
||||
}
|
||||
|
||||
void
|
||||
anv_gem_close(struct anv_device *device, int gem_handle)
|
||||
{
|
||||
struct drm_gem_close close;
|
||||
|
||||
VG_CLEAR(close);
|
||||
close.handle = gem_handle;
|
||||
anv_ioctl(device->fd, DRM_IOCTL_GEM_CLOSE, &close);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around DRM_IOCTL_I915_GEM_MMAP.
|
||||
*/
|
||||
void*
|
||||
anv_gem_mmap(struct anv_device *device, uint32_t gem_handle,
|
||||
uint64_t offset, uint64_t size)
|
||||
{
|
||||
struct drm_i915_gem_mmap gem_mmap;
|
||||
int ret;
|
||||
|
||||
gem_mmap.handle = gem_handle;
|
||||
VG_CLEAR(gem_mmap.pad);
|
||||
gem_mmap.offset = offset;
|
||||
gem_mmap.size = size;
|
||||
VG_CLEAR(gem_mmap.addr_ptr);
|
||||
|
||||
#ifdef I915_MMAP_WC
|
||||
gem_mmap.flags = 0;
|
||||
#endif
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap);
|
||||
if (ret != 0) {
|
||||
/* FIXME: Is NULL the right error return? Cf MAP_INVALID */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VG(VALGRIND_MALLOCLIKE_BLOCK(gem_mmap.addr_ptr, gem_mmap.size, 0, 1));
|
||||
return (void *)(uintptr_t) gem_mmap.addr_ptr;
|
||||
}
|
||||
|
||||
/* This is just a wrapper around munmap, but it also notifies valgrind that
|
||||
* this map is no longer valid. Pair this with anv_gem_mmap().
|
||||
*/
|
||||
void
|
||||
anv_gem_munmap(void *p, uint64_t size)
|
||||
{
|
||||
VG(VALGRIND_FREELIKE_BLOCK(p, 0));
|
||||
munmap(p, size);
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_userptr(struct anv_device *device, void *mem, size_t size)
|
||||
{
|
||||
struct drm_i915_gem_userptr userptr;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(userptr);
|
||||
userptr.user_ptr = (__u64)((unsigned long) mem);
|
||||
userptr.user_size = size;
|
||||
userptr.flags = 0;
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
|
||||
return userptr.handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* On error, \a timeout_ns holds the remaining time.
|
||||
*/
|
||||
int
|
||||
anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns)
|
||||
{
|
||||
struct drm_i915_gem_wait wait;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(wait);
|
||||
wait.bo_handle = gem_handle;
|
||||
wait.timeout_ns = *timeout_ns;
|
||||
wait.flags = 0;
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
|
||||
*timeout_ns = wait.timeout_ns;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_execbuffer(struct anv_device *device,
|
||||
struct drm_i915_gem_execbuffer2 *execbuf)
|
||||
{
|
||||
return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_set_tiling(struct anv_device *device,
|
||||
int gem_handle, uint32_t stride, uint32_t tiling)
|
||||
{
|
||||
struct drm_i915_gem_set_tiling set_tiling;
|
||||
int ret;
|
||||
|
||||
/* set_tiling overwrites the input on the error path, so we have to open
|
||||
* code anv_ioctl.
|
||||
*/
|
||||
|
||||
do {
|
||||
VG_CLEAR(set_tiling);
|
||||
set_tiling.handle = gem_handle;
|
||||
set_tiling.tiling_mode = I915_TILING_X;
|
||||
set_tiling.stride = stride;
|
||||
|
||||
ret = ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_get_param(int fd, uint32_t param)
|
||||
{
|
||||
drm_i915_getparam_t gp;
|
||||
int ret, tmp;
|
||||
|
||||
VG_CLEAR(gp);
|
||||
gp.param = param;
|
||||
gp.value = &tmp;
|
||||
ret = anv_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
|
||||
if (ret == 0)
|
||||
return tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_create_context(struct anv_device *device)
|
||||
{
|
||||
struct drm_i915_gem_context_create create;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(create);
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
return create.ctx_id;
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_destroy_context(struct anv_device *device, int context)
|
||||
{
|
||||
struct drm_i915_gem_context_destroy destroy;
|
||||
|
||||
VG_CLEAR(destroy);
|
||||
destroy.ctx_id = context;
|
||||
|
||||
return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size)
|
||||
{
|
||||
struct drm_i915_gem_get_aperture aperture;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(aperture);
|
||||
ret = anv_ioctl(physical_dev->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
*size = aperture.aper_available_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_handle_to_fd(struct anv_device *device, int gem_handle)
|
||||
{
|
||||
struct drm_prime_handle args;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(args);
|
||||
args.handle = gem_handle;
|
||||
args.flags = DRM_CLOEXEC;
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
return args.fd;
|
||||
}
|
||||
|
||||
int
|
||||
anv_gem_fd_to_handle(struct anv_device *device, int fd)
|
||||
{
|
||||
struct drm_prime_handle args;
|
||||
int ret;
|
||||
|
||||
VG_CLEAR(args);
|
||||
args.fd = fd;
|
||||
|
||||
ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
|
||||
if (ret == -1)
|
||||
return 0;
|
||||
|
||||
return args.handle;
|
||||
}
|
8144
src/vulkan/gen75_pack.h
Normal file
8144
src/vulkan/gen75_pack.h
Normal file
File diff suppressed because it is too large
Load Diff
6852
src/vulkan/gen7_pack.h
Normal file
6852
src/vulkan/gen7_pack.h
Normal file
File diff suppressed because it is too large
Load Diff
8960
src/vulkan/gen8_pack.h
Normal file
8960
src/vulkan/gen8_pack.h
Normal file
File diff suppressed because it is too large
Load Diff
274
src/vulkan/glsl_scraper.py
Normal file
274
src/vulkan/glsl_scraper.py
Normal file
@@ -0,0 +1,274 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import cStringIO
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from textwrap import dedent
|
||||
|
||||
class Shader:
|
||||
def __init__(self, stage):
|
||||
self.stream = cStringIO.StringIO()
|
||||
self.stage = stage
|
||||
|
||||
if self.stage == 'VERTEX':
|
||||
self.ext = 'vert'
|
||||
elif self.stage == 'TESS_CONTROL':
|
||||
self.ext = 'tesc'
|
||||
elif self.stage == 'TESS_EVALUATION':
|
||||
self.ext = 'tese'
|
||||
elif self.stage == 'GEOMETRY':
|
||||
self.ext = 'geom'
|
||||
elif self.stage == 'FRAGMENT':
|
||||
self.ext = 'frag'
|
||||
elif self.stage == 'COMPUTE':
|
||||
self.ext = 'comp'
|
||||
else:
|
||||
assert False
|
||||
|
||||
def add_text(self, s):
|
||||
self.stream.write(s)
|
||||
|
||||
def finish_text(self, line):
|
||||
self.line = line
|
||||
|
||||
def glsl_source(self):
|
||||
return self.stream.getvalue()
|
||||
|
||||
def compile(self):
|
||||
# We can assume if we got here that we have a temp directory and that
|
||||
# we're currently living in it.
|
||||
glsl_fname = 'shader{0}.{1}'.format(self.line, self.ext)
|
||||
spirv_fname = self.ext + '.spv'
|
||||
|
||||
glsl_file = open(glsl_fname, 'w')
|
||||
glsl_file.write('#version 420 core\n')
|
||||
glsl_file.write(self.glsl_source())
|
||||
glsl_file.close()
|
||||
|
||||
out = open('glslang.out', 'wb')
|
||||
err = subprocess.call([glslang, '-V', glsl_fname], stdout=out)
|
||||
if err != 0:
|
||||
out = open('glslang.out', 'r')
|
||||
sys.stderr.write(out.read())
|
||||
out.close()
|
||||
exit(1)
|
||||
|
||||
def dwords(f):
|
||||
while True:
|
||||
dword_str = f.read(4)
|
||||
if not dword_str:
|
||||
return
|
||||
assert len(dword_str) == 4
|
||||
yield struct.unpack('I', dword_str)[0]
|
||||
|
||||
spirv_file = open(spirv_fname, 'rb')
|
||||
self.dwords = list(dwords(spirv_file))
|
||||
spirv_file.close()
|
||||
|
||||
os.remove(glsl_fname)
|
||||
os.remove(spirv_fname)
|
||||
|
||||
def dump_c_code(self, f, glsl_only = False):
|
||||
f.write('\n\n')
|
||||
var_prefix = '_glsl_helpers_shader{0}'.format(self.line)
|
||||
|
||||
# First dump the GLSL source as strings
|
||||
f.write('static const char {0}_glsl_src[] ='.format(var_prefix))
|
||||
f.write('\n_ANV_SPIRV_' + self.stage)
|
||||
f.write('\n"#version 330\\n"')
|
||||
for line in self.glsl_source().splitlines():
|
||||
if not line.strip():
|
||||
continue
|
||||
f.write('\n"{0}\\n"'.format(line))
|
||||
f.write(';\n\n')
|
||||
|
||||
if glsl_only:
|
||||
return
|
||||
|
||||
# Now dump the SPIR-V source
|
||||
f.write('static const uint32_t {0}_spir_v_src[] = {{'.format(var_prefix))
|
||||
line_start = 0
|
||||
while line_start < len(self.dwords):
|
||||
f.write('\n ')
|
||||
for i in range(line_start, min(line_start + 6, len(self.dwords))):
|
||||
f.write(' 0x{:08x},'.format(self.dwords[i]))
|
||||
line_start += 6
|
||||
f.write('\n};\n')
|
||||
|
||||
token_exp = re.compile(r'(GLSL_VK_SHADER_MODULE|\(|\)|,)')
|
||||
|
||||
class Parser:
|
||||
def __init__(self, f):
|
||||
self.infile = f
|
||||
self.paren_depth = 0
|
||||
self.shader = None
|
||||
self.line_number = 1
|
||||
self.shaders = []
|
||||
|
||||
def tokenize(f):
|
||||
leftover = ''
|
||||
for line in f:
|
||||
pos = 0
|
||||
while True:
|
||||
m = token_exp.search(line, pos)
|
||||
if m:
|
||||
if m.start() > pos:
|
||||
leftover += line[pos:m.start()]
|
||||
pos = m.end()
|
||||
|
||||
if leftover:
|
||||
yield leftover
|
||||
leftover = ''
|
||||
|
||||
yield m.group(0)
|
||||
|
||||
else:
|
||||
leftover += line[pos:]
|
||||
break
|
||||
|
||||
self.line_number += 1
|
||||
|
||||
if leftover:
|
||||
yield leftover
|
||||
|
||||
self.token_iter = tokenize(self.infile)
|
||||
|
||||
def handle_shader_src(self):
|
||||
paren_depth = 1
|
||||
for t in self.token_iter:
|
||||
if t == '(':
|
||||
paren_depth += 1
|
||||
elif t == ')':
|
||||
paren_depth -= 1
|
||||
if paren_depth == 0:
|
||||
return
|
||||
|
||||
self.current_shader.add_text(t)
|
||||
|
||||
def handle_macro(self):
|
||||
t = self.token_iter.next()
|
||||
assert t == '('
|
||||
t = self.token_iter.next()
|
||||
t = self.token_iter.next()
|
||||
assert t == ','
|
||||
|
||||
stage = self.token_iter.next().strip()
|
||||
|
||||
t = self.token_iter.next()
|
||||
assert t == ','
|
||||
|
||||
self.current_shader = Shader(stage)
|
||||
self.handle_shader_src()
|
||||
self.current_shader.finish_text(self.line_number)
|
||||
|
||||
self.shaders.append(self.current_shader)
|
||||
self.current_shader = None
|
||||
|
||||
def run(self):
|
||||
for t in self.token_iter:
|
||||
if t == 'GLSL_VK_SHADER_MODULE':
|
||||
self.handle_macro()
|
||||
|
||||
def open_file(name, mode):
|
||||
if name == '-':
|
||||
if mode == 'w':
|
||||
return sys.stdout
|
||||
elif mode == 'r':
|
||||
return sys.stdin
|
||||
else:
|
||||
assert False
|
||||
else:
|
||||
return open(name, mode)
|
||||
|
||||
def parse_args():
|
||||
description = dedent("""\
|
||||
This program scrapes a C file for any instance of the
|
||||
GLSL_VK_SHADER_MODULE macro, grabs the GLSL source code, compiles it
|
||||
to SPIR-V. The resulting SPIR-V code is written to another C file as
|
||||
an array of 32-bit words.
|
||||
|
||||
If '-' is passed as the input file or output file, stdin or stdout will be
|
||||
used instead of a file on disc.""")
|
||||
|
||||
p = argparse.ArgumentParser(
|
||||
description=description,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
p.add_argument('-o', '--outfile', default='-',
|
||||
help='Output to the given file (default: stdout).')
|
||||
p.add_argument('--with-glslang', metavar='PATH',
|
||||
default='glslangValidator',
|
||||
dest='glslang',
|
||||
help='Full path to the glslangValidator program.')
|
||||
p.add_argument('--glsl-only', action='store_true')
|
||||
p.add_argument('infile', metavar='INFILE')
|
||||
|
||||
return p.parse_args()
|
||||
|
||||
|
||||
args = parse_args()
|
||||
infname = args.infile
|
||||
outfname = args.outfile
|
||||
glslang = args.glslang
|
||||
glsl_only = args.glsl_only
|
||||
|
||||
with open_file(infname, 'r') as infile:
|
||||
parser = Parser(infile)
|
||||
parser.run()
|
||||
|
||||
if not glsl_only:
|
||||
# glslangValidator has an absolutely *insane* interface. We pretty much
|
||||
# have to run in a temporary directory. Sad day.
|
||||
current_dir = os.getcwd()
|
||||
tmpdir = tempfile.mkdtemp('glsl_scraper')
|
||||
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
|
||||
for shader in parser.shaders:
|
||||
shader.compile()
|
||||
|
||||
os.chdir(current_dir)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
with open_file(outfname, 'w') as outfile:
|
||||
outfile.write(dedent("""\
|
||||
/* =========================== DO NOT EDIT! ===========================
|
||||
* This file is autogenerated by glsl_scraper.py.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define _ANV_SPIRV_MAGIC "\\x03\\x02\\x23\\x07\\0\\0\\0\\0"
|
||||
|
||||
#define _ANV_SPIRV_VERTEX _ANV_SPIRV_MAGIC "\\0\\0\\0\\0"
|
||||
#define _ANV_SPIRV_TESS_CONTROL _ANV_SPIRV_MAGIC "\\1\\0\\0\\0"
|
||||
#define _ANV_SPIRV_TESS_EVALUATION _ANV_SPIRV_MAGIC "\\2\\0\\0\\0"
|
||||
#define _ANV_SPIRV_GEOMETRY _ANV_SPIRV_MAGIC "\\3\\0\\0\\0"
|
||||
#define _ANV_SPIRV_FRAGMENT _ANV_SPIRV_MAGIC "\\4\\0\\0\\0"
|
||||
#define _ANV_SPIRV_COMPUTE _ANV_SPIRV_MAGIC "\\5\\0\\0\\0"
|
||||
|
||||
#define _ANV_GLSL_SRC_VAR2(_line) _glsl_helpers_shader ## _line ## _glsl_src
|
||||
#define _ANV_GLSL_SRC_VAR(_line) _ANV_GLSL_SRC_VAR2(_line)
|
||||
|
||||
#define GLSL_VK_SHADER_MODULE(device, stage, ...) ({ \\
|
||||
VkShaderModule __module; \\
|
||||
VkShaderModuleCreateInfo __shader_create_info = { \\
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, \\
|
||||
.codeSize = sizeof(_ANV_GLSL_SRC_VAR(__LINE__)), \\
|
||||
.pCode = _ANV_GLSL_SRC_VAR(__LINE__), \\
|
||||
}; \\
|
||||
vkCreateShaderModule(anv_device_to_handle(device), \\
|
||||
&__shader_create_info, &__module); \\
|
||||
__module; \\
|
||||
})
|
||||
"""))
|
||||
|
||||
for shader in parser.shaders:
|
||||
shader.dump_c_code(outfile, glsl_only)
|
743
src/vulkan/image.c
Normal file
743
src/vulkan/image.c
Normal file
@@ -0,0 +1,743 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
struct anv_image_view_info {
|
||||
uint8_t surface_type; /**< RENDER_SURFACE_STATE.SurfaceType */
|
||||
bool is_array:1; /**< RENDER_SURFACE_STATE.SurfaceArray */
|
||||
bool is_cube:1; /**< RENDER_SURFACE_STATE.CubeFaceEnable* */
|
||||
};
|
||||
|
||||
static const uint8_t anv_halign[] = {
|
||||
[4] = HALIGN4,
|
||||
[8] = HALIGN8,
|
||||
[16] = HALIGN16,
|
||||
};
|
||||
|
||||
static const uint8_t anv_valign[] = {
|
||||
[4] = VALIGN4,
|
||||
[8] = VALIGN8,
|
||||
[16] = VALIGN16,
|
||||
};
|
||||
|
||||
static const uint8_t anv_surf_type_from_image_type[] = {
|
||||
[VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
|
||||
[VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
|
||||
[VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
|
||||
|
||||
};
|
||||
|
||||
static const struct anv_image_view_info
|
||||
anv_image_view_info_table[] = {
|
||||
#define INFO(s, ...) { .surface_type = s, __VA_ARGS__ }
|
||||
[VK_IMAGE_VIEW_TYPE_1D] = INFO(SURFTYPE_1D),
|
||||
[VK_IMAGE_VIEW_TYPE_2D] = INFO(SURFTYPE_2D),
|
||||
[VK_IMAGE_VIEW_TYPE_3D] = INFO(SURFTYPE_3D),
|
||||
[VK_IMAGE_VIEW_TYPE_CUBE] = INFO(SURFTYPE_CUBE, .is_cube = 1),
|
||||
[VK_IMAGE_VIEW_TYPE_1D_ARRAY] = INFO(SURFTYPE_1D, .is_array = 1),
|
||||
[VK_IMAGE_VIEW_TYPE_2D_ARRAY] = INFO(SURFTYPE_2D, .is_array = 1),
|
||||
[VK_IMAGE_VIEW_TYPE_CUBE_ARRAY] = INFO(SURFTYPE_CUBE, .is_array = 1, .is_cube = 1),
|
||||
#undef INFO
|
||||
};
|
||||
|
||||
static const struct anv_surf_type_limits {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t depth;
|
||||
} anv_surf_type_limits[] = {
|
||||
[SURFTYPE_1D] = {16384, 0, 2048},
|
||||
[SURFTYPE_2D] = {16384, 16384, 2048},
|
||||
[SURFTYPE_3D] = {2048, 2048, 2048},
|
||||
[SURFTYPE_CUBE] = {16384, 16384, 340},
|
||||
[SURFTYPE_BUFFER] = {128, 16384, 64},
|
||||
[SURFTYPE_STRBUF] = {128, 16384, 64},
|
||||
};
|
||||
|
||||
static const struct anv_tile_info {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
/**
|
||||
* Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
|
||||
*
|
||||
* To simplify calculations, the alignments defined in the table are
|
||||
* sometimes larger than required. For example, Skylake requires that X and
|
||||
* Y tiled buffers be aligned to 4K, but Broadwell permits smaller
|
||||
* alignment. We choose 4K to accomodate both chipsets. The alignment of
|
||||
* a linear buffer depends on its element type and usage. Linear depth
|
||||
* buffers have the largest alignment, 64B, so we choose that for all linear
|
||||
* buffers.
|
||||
*/
|
||||
uint32_t surface_alignment;
|
||||
} anv_tile_info_table[] = {
|
||||
[LINEAR] = { 1, 1, 64 },
|
||||
[XMAJOR] = { 512, 8, 4096 },
|
||||
[YMAJOR] = { 128, 32, 4096 },
|
||||
[WMAJOR] = { 128, 32, 4096 },
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
anv_image_choose_tile_mode(const struct anv_image_create_info *anv_info)
|
||||
{
|
||||
if (anv_info->force_tile_mode)
|
||||
return anv_info->tile_mode;
|
||||
|
||||
if (anv_info->vk_info->format == VK_FORMAT_S8_UINT)
|
||||
return WMAJOR;
|
||||
|
||||
switch (anv_info->vk_info->tiling) {
|
||||
case VK_IMAGE_TILING_LINEAR:
|
||||
return LINEAR;
|
||||
case VK_IMAGE_TILING_OPTIMAL:
|
||||
return YMAJOR;
|
||||
default:
|
||||
assert(!"bad VKImageTiling");
|
||||
return LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
static VkResult
|
||||
anv_image_make_surface(const struct anv_image_create_info *create_info,
|
||||
uint64_t *inout_image_size,
|
||||
uint32_t *inout_image_alignment,
|
||||
struct anv_surface *out_surface)
|
||||
{
|
||||
/* See RENDER_SURFACE_STATE.SurfaceQPitch */
|
||||
static const uint16_t min_qpitch UNUSED = 0x4;
|
||||
static const uint16_t max_qpitch UNUSED = 0x1ffc;
|
||||
|
||||
const VkExtent3D *restrict extent = &create_info->vk_info->extent;
|
||||
const uint32_t levels = create_info->vk_info->mipLevels;
|
||||
const uint32_t array_size = create_info->vk_info->arraySize;
|
||||
|
||||
const uint8_t tile_mode = anv_image_choose_tile_mode(create_info);
|
||||
|
||||
const struct anv_tile_info *tile_info =
|
||||
&anv_tile_info_table[tile_mode];
|
||||
|
||||
const struct anv_format *format_info =
|
||||
anv_format_for_vk_format(create_info->vk_info->format);
|
||||
|
||||
const uint32_t i = 4; /* FINISHME: Stop hardcoding subimage alignment */
|
||||
const uint32_t j = 4; /* FINISHME: Stop hardcoding subimage alignment */
|
||||
const uint32_t w0 = align_u32(extent->width, i);
|
||||
const uint32_t h0 = align_u32(extent->height, j);
|
||||
|
||||
uint16_t qpitch;
|
||||
uint32_t mt_width;
|
||||
uint32_t mt_height;
|
||||
|
||||
if (levels == 1 && array_size == 1) {
|
||||
qpitch = min_qpitch;
|
||||
mt_width = w0;
|
||||
mt_height = h0;
|
||||
} else {
|
||||
uint32_t w1 = align_u32(anv_minify(extent->width, 1), i);
|
||||
uint32_t h1 = align_u32(anv_minify(extent->height, 1), j);
|
||||
uint32_t w2 = align_u32(anv_minify(extent->width, 2), i);
|
||||
|
||||
qpitch = h0 + h1 + 11 * j;
|
||||
mt_width = MAX(w0, w1 + w2);
|
||||
mt_height = array_size * qpitch;
|
||||
}
|
||||
|
||||
assert(qpitch >= min_qpitch);
|
||||
if (qpitch > max_qpitch) {
|
||||
anv_loge("image qpitch > 0x%x\n", max_qpitch);
|
||||
return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
|
||||
}
|
||||
|
||||
/* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch:
|
||||
*
|
||||
* This field must be set an integer multiple of the Surface Vertical
|
||||
* Alignment.
|
||||
*/
|
||||
assert(anv_is_aligned(qpitch, j));
|
||||
|
||||
const uint32_t stride = align_u32(mt_width * format_info->cpp,
|
||||
tile_info->width);
|
||||
const uint32_t size = stride * align_u32(mt_height, tile_info->height);
|
||||
const uint32_t offset = align_u32(*inout_image_size,
|
||||
tile_info->surface_alignment);
|
||||
|
||||
*inout_image_size = offset + size;
|
||||
*inout_image_alignment = MAX(*inout_image_alignment,
|
||||
tile_info->surface_alignment);
|
||||
|
||||
*out_surface = (struct anv_surface) {
|
||||
.offset = offset,
|
||||
.stride = stride,
|
||||
.tile_mode = tile_mode,
|
||||
.qpitch = qpitch,
|
||||
.h_align = i,
|
||||
.v_align = j,
|
||||
};
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_image_create(VkDevice _device,
|
||||
const struct anv_image_create_info *create_info,
|
||||
VkImage *pImage)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
|
||||
const VkExtent3D *restrict extent = &pCreateInfo->extent;
|
||||
struct anv_image *image = NULL;
|
||||
VkResult r;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
|
||||
|
||||
/* XXX: We don't handle any of these */
|
||||
anv_assert(pCreateInfo->imageType == VK_IMAGE_TYPE_2D);
|
||||
anv_assert(pCreateInfo->mipLevels > 0);
|
||||
anv_assert(pCreateInfo->arraySize > 0);
|
||||
anv_assert(pCreateInfo->samples == 1);
|
||||
anv_assert(pCreateInfo->extent.width > 0);
|
||||
anv_assert(pCreateInfo->extent.height > 0);
|
||||
anv_assert(pCreateInfo->extent.depth > 0);
|
||||
|
||||
/* TODO(chadv): How should we validate inputs? */
|
||||
const uint8_t surf_type =
|
||||
anv_surf_type_from_image_type[pCreateInfo->imageType];
|
||||
|
||||
const struct anv_surf_type_limits *limits =
|
||||
&anv_surf_type_limits[surf_type];
|
||||
|
||||
if (extent->width > limits->width ||
|
||||
extent->height > limits->height ||
|
||||
extent->depth > limits->depth) {
|
||||
/* TODO(chadv): What is the correct error? */
|
||||
anv_loge("image extent is too large");
|
||||
return vk_error(VK_ERROR_INVALID_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
const struct anv_format *format_info =
|
||||
anv_format_for_vk_format(pCreateInfo->format);
|
||||
|
||||
image = anv_device_alloc(device, sizeof(*image), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (!image)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
memset(image, 0, sizeof(*image));
|
||||
image->type = pCreateInfo->imageType;
|
||||
image->extent = pCreateInfo->extent;
|
||||
image->format = pCreateInfo->format;
|
||||
image->levels = pCreateInfo->mipLevels;
|
||||
image->array_size = pCreateInfo->arraySize;
|
||||
image->surf_type = surf_type;
|
||||
|
||||
if (likely(!format_info->has_stencil || format_info->depth_format)) {
|
||||
/* The image's primary surface is a color or depth surface. */
|
||||
r = anv_image_make_surface(create_info, &image->size, &image->alignment,
|
||||
&image->primary_surface);
|
||||
if (r != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (format_info->has_stencil) {
|
||||
/* From the GPU's perspective, the depth buffer and stencil buffer are
|
||||
* separate buffers. From Vulkan's perspective, though, depth and
|
||||
* stencil reside in the same image. To satisfy Vulkan and the GPU, we
|
||||
* place the depth and stencil buffers in the same bo.
|
||||
*/
|
||||
VkImageCreateInfo stencil_info = *pCreateInfo;
|
||||
stencil_info.format = VK_FORMAT_S8_UINT;
|
||||
|
||||
r = anv_image_make_surface(
|
||||
&(struct anv_image_create_info) {
|
||||
.vk_info = &stencil_info,
|
||||
},
|
||||
&image->size, &image->alignment, &image->stencil_surface);
|
||||
|
||||
if (r != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*pImage = anv_image_to_handle(image);
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
if (image)
|
||||
anv_device_free(device, image);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_CreateImage(VkDevice device,
|
||||
const VkImageCreateInfo *pCreateInfo,
|
||||
VkImage *pImage)
|
||||
{
|
||||
return anv_image_create(device,
|
||||
&(struct anv_image_create_info) {
|
||||
.vk_info = pCreateInfo,
|
||||
},
|
||||
pImage);
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_DestroyImage(VkDevice _device, VkImage _image)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
|
||||
anv_device_free(device, anv_image_from_handle(_image));
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_GetImageSubresourceLayout(
|
||||
VkDevice device,
|
||||
VkImage image,
|
||||
const VkImageSubresource* pSubresource,
|
||||
VkSubresourceLayout* pLayout)
|
||||
{
|
||||
stub_return(VK_UNSUPPORTED);
|
||||
}
|
||||
|
||||
void
|
||||
anv_surface_view_fini(struct anv_device *device,
|
||||
struct anv_surface_view *view)
|
||||
{
|
||||
anv_state_pool_free(&device->surface_state_pool, view->surface_state);
|
||||
}
|
||||
|
||||
void
|
||||
anv_image_view_init(struct anv_image_view *iview,
|
||||
struct anv_device *device,
|
||||
const VkImageViewCreateInfo* pCreateInfo,
|
||||
struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
||||
|
||||
const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
|
||||
struct anv_surface_view *view = &iview->view;
|
||||
struct anv_surface *surface;
|
||||
|
||||
const struct anv_format *format_info =
|
||||
anv_format_for_vk_format(pCreateInfo->format);
|
||||
|
||||
const struct anv_image_view_info *view_type_info
|
||||
= &anv_image_view_info_table[pCreateInfo->viewType];
|
||||
|
||||
if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
|
||||
anv_finishme("non-2D image views");
|
||||
|
||||
switch (pCreateInfo->subresourceRange.aspect) {
|
||||
case VK_IMAGE_ASPECT_STENCIL:
|
||||
anv_finishme("stencil image views");
|
||||
abort();
|
||||
break;
|
||||
case VK_IMAGE_ASPECT_DEPTH:
|
||||
case VK_IMAGE_ASPECT_COLOR:
|
||||
view->offset = image->offset;
|
||||
surface = &image->primary_surface;
|
||||
break;
|
||||
default:
|
||||
unreachable("");
|
||||
break;
|
||||
}
|
||||
|
||||
view->bo = image->bo;
|
||||
view->offset = image->offset + surface->offset;
|
||||
view->format = pCreateInfo->format;
|
||||
|
||||
view->extent = (VkExtent3D) {
|
||||
.width = anv_minify(image->extent.width, range->baseMipLevel),
|
||||
.height = anv_minify(image->extent.height, range->baseMipLevel),
|
||||
.depth = anv_minify(image->extent.depth, range->baseMipLevel),
|
||||
};
|
||||
|
||||
uint32_t depth = 1;
|
||||
if (range->arraySize > 1) {
|
||||
depth = range->arraySize;
|
||||
} else if (image->extent.depth > 1) {
|
||||
depth = image->extent.depth;
|
||||
}
|
||||
|
||||
static const uint32_t vk_to_gen_swizzle[] = {
|
||||
[VK_CHANNEL_SWIZZLE_ZERO] = SCS_ZERO,
|
||||
[VK_CHANNEL_SWIZZLE_ONE] = SCS_ONE,
|
||||
[VK_CHANNEL_SWIZZLE_R] = SCS_RED,
|
||||
[VK_CHANNEL_SWIZZLE_G] = SCS_GREEN,
|
||||
[VK_CHANNEL_SWIZZLE_B] = SCS_BLUE,
|
||||
[VK_CHANNEL_SWIZZLE_A] = SCS_ALPHA
|
||||
};
|
||||
|
||||
struct GEN8_RENDER_SURFACE_STATE surface_state = {
|
||||
.SurfaceType = view_type_info->surface_type,
|
||||
.SurfaceArray = image->array_size > 1,
|
||||
.SurfaceFormat = format_info->surface_format,
|
||||
.SurfaceVerticalAlignment = anv_valign[surface->v_align],
|
||||
.SurfaceHorizontalAlignment = anv_halign[surface->h_align],
|
||||
.TileMode = surface->tile_mode,
|
||||
.VerticalLineStride = 0,
|
||||
.VerticalLineStrideOffset = 0,
|
||||
.SamplerL2BypassModeDisable = true,
|
||||
.RenderCacheReadWriteMode = WriteOnlyCache,
|
||||
.MemoryObjectControlState = GEN8_MOCS,
|
||||
|
||||
/* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
|
||||
* RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
|
||||
* both Base Mip Level fields nonzero".
|
||||
*/
|
||||
.BaseMipLevel = 0.0,
|
||||
|
||||
.SurfaceQPitch = surface->qpitch >> 2,
|
||||
.Height = image->extent.height - 1,
|
||||
.Width = image->extent.width - 1,
|
||||
.Depth = depth - 1,
|
||||
.SurfacePitch = surface->stride - 1,
|
||||
.MinimumArrayElement = range->baseArraySlice,
|
||||
.NumberofMultisamples = MULTISAMPLECOUNT_1,
|
||||
.XOffset = 0,
|
||||
.YOffset = 0,
|
||||
|
||||
/* For sampler surfaces, the hardware interprets field MIPCount/LOD as
|
||||
* MIPCount. The range of levels accessible by the sampler engine is
|
||||
* [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
|
||||
*/
|
||||
.MIPCountLOD = range->mipLevels - 1,
|
||||
.SurfaceMinLOD = range->baseMipLevel,
|
||||
|
||||
.AuxiliarySurfaceMode = AUX_NONE,
|
||||
.RedClearColor = 0,
|
||||
.GreenClearColor = 0,
|
||||
.BlueClearColor = 0,
|
||||
.AlphaClearColor = 0,
|
||||
.ShaderChannelSelectRed = vk_to_gen_swizzle[pCreateInfo->channels.r],
|
||||
.ShaderChannelSelectGreen = vk_to_gen_swizzle[pCreateInfo->channels.g],
|
||||
.ShaderChannelSelectBlue = vk_to_gen_swizzle[pCreateInfo->channels.b],
|
||||
.ShaderChannelSelectAlpha = vk_to_gen_swizzle[pCreateInfo->channels.a],
|
||||
.ResourceMinLOD = 0.0,
|
||||
.SurfaceBaseAddress = { NULL, view->offset },
|
||||
};
|
||||
|
||||
if (cmd_buffer)
|
||||
view->surface_state =
|
||||
anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
|
||||
else
|
||||
view->surface_state =
|
||||
anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
|
||||
|
||||
GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_validate_CreateImageView(VkDevice _device,
|
||||
const VkImageViewCreateInfo *pCreateInfo,
|
||||
VkImageView *pView)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
||||
const VkImageSubresourceRange *subresource;
|
||||
const struct anv_image_view_info *view_info;
|
||||
const struct anv_format *view_format_info;
|
||||
const struct anv_format *image_format_info;
|
||||
|
||||
/* Validate structure type before dereferencing it. */
|
||||
assert(pCreateInfo);
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
|
||||
subresource = &pCreateInfo->subresourceRange;
|
||||
|
||||
/* Validate viewType is in range before using it. */
|
||||
assert(pCreateInfo->viewType >= VK_IMAGE_VIEW_TYPE_BEGIN_RANGE);
|
||||
assert(pCreateInfo->viewType <= VK_IMAGE_VIEW_TYPE_END_RANGE);
|
||||
view_info = &anv_image_view_info_table[pCreateInfo->viewType];
|
||||
|
||||
/* Validate format is in range before using it. */
|
||||
assert(pCreateInfo->format >= VK_FORMAT_BEGIN_RANGE);
|
||||
assert(pCreateInfo->format <= VK_FORMAT_END_RANGE);
|
||||
image_format_info = anv_format_for_vk_format(image->format);
|
||||
view_format_info = anv_format_for_vk_format(pCreateInfo->format);
|
||||
|
||||
/* Validate channel swizzles. */
|
||||
assert(pCreateInfo->channels.r >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
|
||||
assert(pCreateInfo->channels.r <= VK_CHANNEL_SWIZZLE_END_RANGE);
|
||||
assert(pCreateInfo->channels.g >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
|
||||
assert(pCreateInfo->channels.g <= VK_CHANNEL_SWIZZLE_END_RANGE);
|
||||
assert(pCreateInfo->channels.b >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
|
||||
assert(pCreateInfo->channels.b <= VK_CHANNEL_SWIZZLE_END_RANGE);
|
||||
assert(pCreateInfo->channels.a >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
|
||||
assert(pCreateInfo->channels.a <= VK_CHANNEL_SWIZZLE_END_RANGE);
|
||||
|
||||
/* Validate subresource. */
|
||||
assert(subresource->aspect >= VK_IMAGE_ASPECT_BEGIN_RANGE);
|
||||
assert(subresource->aspect <= VK_IMAGE_ASPECT_END_RANGE);
|
||||
assert(subresource->mipLevels > 0);
|
||||
assert(subresource->arraySize > 0);
|
||||
assert(subresource->baseMipLevel < image->levels);
|
||||
assert(subresource->baseMipLevel + subresource->mipLevels <= image->levels);
|
||||
assert(subresource->baseArraySlice < image->array_size);
|
||||
assert(subresource->baseArraySlice + subresource->arraySize <= image->array_size);
|
||||
assert(pView);
|
||||
|
||||
if (view_info->is_cube) {
|
||||
assert(subresource->baseArraySlice % 6 == 0);
|
||||
assert(subresource->arraySize % 6 == 0);
|
||||
}
|
||||
|
||||
/* Validate format. */
|
||||
switch (subresource->aspect) {
|
||||
case VK_IMAGE_ASPECT_COLOR:
|
||||
assert(!image_format_info->depth_format);
|
||||
assert(!image_format_info->has_stencil);
|
||||
assert(!view_format_info->depth_format);
|
||||
assert(!view_format_info->has_stencil);
|
||||
assert(view_format_info->cpp == image_format_info->cpp);
|
||||
break;
|
||||
case VK_IMAGE_ASPECT_DEPTH:
|
||||
assert(image_format_info->depth_format);
|
||||
assert(view_format_info->depth_format);
|
||||
assert(view_format_info->cpp == image_format_info->cpp);
|
||||
break;
|
||||
case VK_IMAGE_ASPECT_STENCIL:
|
||||
/* FINISHME: Is it legal to have an R8 view of S8? */
|
||||
assert(image_format_info->has_stencil);
|
||||
assert(view_format_info->has_stencil);
|
||||
break;
|
||||
default:
|
||||
assert(!"bad VkImageAspect");
|
||||
break;
|
||||
}
|
||||
|
||||
return anv_CreateImageView(_device, pCreateInfo, pView);
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_CreateImageView(VkDevice _device,
|
||||
const VkImageViewCreateInfo *pCreateInfo,
|
||||
VkImageView *pView)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_image_view *view;
|
||||
|
||||
view = anv_device_alloc(device, sizeof(*view), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (view == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
anv_image_view_init(view, device, pCreateInfo, NULL);
|
||||
|
||||
*pView = anv_image_view_to_handle(view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_DestroyImageView(VkDevice _device, VkImageView _iview)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_image_view, iview, _iview);
|
||||
|
||||
anv_surface_view_fini(device, &iview->view);
|
||||
anv_device_free(device, iview);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
anv_color_attachment_view_init(struct anv_color_attachment_view *aview,
|
||||
struct anv_device *device,
|
||||
const VkAttachmentViewCreateInfo* pCreateInfo,
|
||||
struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
||||
struct anv_surface_view *view = &aview->view;
|
||||
struct anv_surface *surface = &image->primary_surface;
|
||||
const struct anv_format *format_info =
|
||||
anv_format_for_vk_format(pCreateInfo->format);
|
||||
|
||||
aview->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_COLOR;
|
||||
|
||||
anv_assert(pCreateInfo->arraySize > 0);
|
||||
anv_assert(pCreateInfo->mipLevel < image->levels);
|
||||
anv_assert(pCreateInfo->baseArraySlice + pCreateInfo->arraySize <= image->array_size);
|
||||
|
||||
view->bo = image->bo;
|
||||
view->offset = image->offset + surface->offset;
|
||||
view->format = pCreateInfo->format;
|
||||
|
||||
view->extent = (VkExtent3D) {
|
||||
.width = anv_minify(image->extent.width, pCreateInfo->mipLevel),
|
||||
.height = anv_minify(image->extent.height, pCreateInfo->mipLevel),
|
||||
.depth = anv_minify(image->extent.depth, pCreateInfo->mipLevel),
|
||||
};
|
||||
|
||||
uint32_t depth = 1;
|
||||
if (pCreateInfo->arraySize > 1) {
|
||||
depth = pCreateInfo->arraySize;
|
||||
} else if (image->extent.depth > 1) {
|
||||
depth = image->extent.depth;
|
||||
}
|
||||
|
||||
if (cmd_buffer)
|
||||
view->surface_state =
|
||||
anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
|
||||
else
|
||||
view->surface_state =
|
||||
anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
|
||||
|
||||
struct GEN8_RENDER_SURFACE_STATE surface_state = {
|
||||
.SurfaceType = SURFTYPE_2D,
|
||||
.SurfaceArray = image->array_size > 1,
|
||||
.SurfaceFormat = format_info->surface_format,
|
||||
.SurfaceVerticalAlignment = anv_valign[surface->v_align],
|
||||
.SurfaceHorizontalAlignment = anv_halign[surface->h_align],
|
||||
.TileMode = surface->tile_mode,
|
||||
.VerticalLineStride = 0,
|
||||
.VerticalLineStrideOffset = 0,
|
||||
.SamplerL2BypassModeDisable = true,
|
||||
.RenderCacheReadWriteMode = WriteOnlyCache,
|
||||
.MemoryObjectControlState = GEN8_MOCS,
|
||||
|
||||
/* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
|
||||
* RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
|
||||
* both Base Mip Level fields nonzero".
|
||||
*/
|
||||
.BaseMipLevel = 0.0,
|
||||
|
||||
.SurfaceQPitch = surface->qpitch >> 2,
|
||||
.Height = image->extent.height - 1,
|
||||
.Width = image->extent.width - 1,
|
||||
.Depth = depth - 1,
|
||||
.SurfacePitch = surface->stride - 1,
|
||||
.MinimumArrayElement = pCreateInfo->baseArraySlice,
|
||||
.NumberofMultisamples = MULTISAMPLECOUNT_1,
|
||||
.XOffset = 0,
|
||||
.YOffset = 0,
|
||||
|
||||
/* For render target surfaces, the hardware interprets field MIPCount/LOD as
|
||||
* LOD. The Broadwell PRM says:
|
||||
*
|
||||
* MIPCountLOD defines the LOD that will be rendered into.
|
||||
* SurfaceMinLOD is ignored.
|
||||
*/
|
||||
.SurfaceMinLOD = 0,
|
||||
.MIPCountLOD = pCreateInfo->mipLevel,
|
||||
|
||||
.AuxiliarySurfaceMode = AUX_NONE,
|
||||
.RedClearColor = 0,
|
||||
.GreenClearColor = 0,
|
||||
.BlueClearColor = 0,
|
||||
.AlphaClearColor = 0,
|
||||
.ShaderChannelSelectRed = SCS_RED,
|
||||
.ShaderChannelSelectGreen = SCS_GREEN,
|
||||
.ShaderChannelSelectBlue = SCS_BLUE,
|
||||
.ShaderChannelSelectAlpha = SCS_ALPHA,
|
||||
.ResourceMinLOD = 0.0,
|
||||
.SurfaceBaseAddress = { NULL, view->offset },
|
||||
};
|
||||
|
||||
GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
|
||||
}
|
||||
|
||||
static void
|
||||
anv_depth_stencil_view_init(struct anv_depth_stencil_view *view,
|
||||
const VkAttachmentViewCreateInfo *pCreateInfo)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
||||
struct anv_surface *depth_surface = &image->primary_surface;
|
||||
struct anv_surface *stencil_surface = &image->stencil_surface;
|
||||
const struct anv_format *format =
|
||||
anv_format_for_vk_format(image->format);
|
||||
|
||||
view->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL;
|
||||
|
||||
/* XXX: We don't handle any of these */
|
||||
anv_assert(pCreateInfo->mipLevel == 0);
|
||||
anv_assert(pCreateInfo->baseArraySlice == 0);
|
||||
anv_assert(pCreateInfo->arraySize == 1);
|
||||
|
||||
view->bo = image->bo;
|
||||
|
||||
view->depth_stride = depth_surface->stride;
|
||||
view->depth_offset = image->offset + depth_surface->offset;
|
||||
view->depth_format = format->depth_format;
|
||||
view->depth_qpitch = 0; /* FINISHME: QPitch */
|
||||
|
||||
view->stencil_stride = stencil_surface->stride;
|
||||
view->stencil_offset = image->offset + stencil_surface->offset;
|
||||
view->stencil_qpitch = 0; /* FINISHME: QPitch */
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_CreateAttachmentView(VkDevice _device,
|
||||
const VkAttachmentViewCreateInfo *pCreateInfo,
|
||||
VkAttachmentView *pView)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO);
|
||||
|
||||
if (anv_is_vk_format_depth_or_stencil(pCreateInfo->format)) {
|
||||
struct anv_depth_stencil_view *view =
|
||||
anv_device_alloc(device, sizeof(*view), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (view == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
anv_depth_stencil_view_init(view, pCreateInfo);
|
||||
|
||||
*pView = anv_attachment_view_to_handle(&view->base);
|
||||
} else {
|
||||
struct anv_color_attachment_view *view =
|
||||
anv_device_alloc(device, sizeof(*view), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (view == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
anv_color_attachment_view_init(view, device, pCreateInfo, NULL);
|
||||
|
||||
*pView = anv_attachment_view_to_handle(&view->base);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_DestroyAttachmentView(VkDevice _device, VkAttachmentView _view)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_attachment_view, view, _view);
|
||||
|
||||
if (view->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_COLOR) {
|
||||
struct anv_color_attachment_view *aview =
|
||||
(struct anv_color_attachment_view *)view;
|
||||
|
||||
anv_surface_view_fini(device, &aview->view);
|
||||
}
|
||||
|
||||
anv_device_free(device, view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
97
src/vulkan/intel.c
Normal file
97
src/vulkan/intel.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
VkResult anv_CreateDmaBufImageINTEL(
|
||||
VkDevice _device,
|
||||
const VkDmaBufImageCreateInfo* pCreateInfo,
|
||||
VkDeviceMemory* pMem,
|
||||
VkImage* pImage)
|
||||
{
|
||||
struct anv_device *device = (struct anv_device *) _device;
|
||||
struct anv_device_memory *mem;
|
||||
struct anv_image *image;
|
||||
VkResult result;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL);
|
||||
|
||||
mem = anv_device_alloc(device, sizeof(*mem), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (mem == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
mem->bo.gem_handle = anv_gem_fd_to_handle(device, pCreateInfo->fd);
|
||||
if (!mem->bo.gem_handle) {
|
||||
result = vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mem->bo.map = NULL;
|
||||
mem->bo.index = 0;
|
||||
mem->bo.offset = 0;
|
||||
mem->bo.size = pCreateInfo->strideInBytes * pCreateInfo->extent.height;
|
||||
|
||||
image = anv_device_alloc(device, sizeof(*image), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (image == NULL) {
|
||||
result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
goto fail_mem;
|
||||
}
|
||||
|
||||
*image = (struct anv_image) {
|
||||
.bo = &mem->bo,
|
||||
.offset = 0,
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.extent = pCreateInfo->extent,
|
||||
.size = mem->bo.size,
|
||||
|
||||
.primary_surface = {
|
||||
.offset = 0,
|
||||
.stride = pCreateInfo->strideInBytes,
|
||||
.tile_mode = XMAJOR,
|
||||
},
|
||||
};
|
||||
|
||||
assert(image->extent.width > 0);
|
||||
assert(image->extent.height > 0);
|
||||
assert(image->extent.depth == 1);
|
||||
|
||||
*pMem = anv_device_memory_to_handle(mem);
|
||||
*pImage = anv_image_to_handle(image);
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail_mem:
|
||||
anv_gem_close(device, mem->bo.gem_handle);
|
||||
fail:
|
||||
anv_device_free(device, mem);
|
||||
|
||||
return result;
|
||||
}
|
1449
src/vulkan/meta.c
Normal file
1449
src/vulkan/meta.c
Normal file
File diff suppressed because it is too large
Load Diff
950
src/vulkan/pipeline.c
Normal file
950
src/vulkan/pipeline.c
Normal file
@@ -0,0 +1,950 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
// Shader functions
|
||||
|
||||
VkResult anv_CreateShaderModule(
|
||||
VkDevice _device,
|
||||
const VkShaderModuleCreateInfo* pCreateInfo,
|
||||
VkShaderModule* pShaderModule)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_shader_module *module;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
|
||||
assert(pCreateInfo->flags == 0);
|
||||
|
||||
module = anv_device_alloc(device, sizeof(*module) + pCreateInfo->codeSize, 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (module == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
module->size = pCreateInfo->codeSize;
|
||||
memcpy(module->data, pCreateInfo->pCode, module->size);
|
||||
|
||||
*pShaderModule = anv_shader_module_to_handle(module);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_DestroyShaderModule(
|
||||
VkDevice _device,
|
||||
VkShaderModule _module)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_shader_module, module, _module);
|
||||
|
||||
anv_device_free(device, module);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_CreateShader(
|
||||
VkDevice _device,
|
||||
const VkShaderCreateInfo* pCreateInfo,
|
||||
VkShader* pShader)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_shader_module, module, pCreateInfo->module);
|
||||
struct anv_shader *shader;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_CREATE_INFO);
|
||||
assert(pCreateInfo->flags == 0);
|
||||
|
||||
size_t name_len = strlen(pCreateInfo->pName);
|
||||
|
||||
if (strcmp(pCreateInfo->pName, "main") != 0) {
|
||||
anv_finishme("Multiple shaders per module not really supported");
|
||||
}
|
||||
|
||||
shader = anv_device_alloc(device, sizeof(*shader) + name_len + 1, 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (shader == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
shader->module = module;
|
||||
memcpy(shader->entrypoint, pCreateInfo->pName, name_len + 1);
|
||||
|
||||
*pShader = anv_shader_to_handle(shader);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_DestroyShader(
|
||||
VkDevice _device,
|
||||
VkShader _shader)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_shader, shader, _shader);
|
||||
|
||||
anv_device_free(device, shader);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
VkResult anv_CreatePipelineCache(
|
||||
VkDevice device,
|
||||
const VkPipelineCacheCreateInfo* pCreateInfo,
|
||||
VkPipelineCache* pPipelineCache)
|
||||
{
|
||||
pPipelineCache->handle = 1;
|
||||
|
||||
stub_return(VK_SUCCESS);
|
||||
}
|
||||
|
||||
VkResult anv_DestroyPipelineCache(
|
||||
VkDevice _device,
|
||||
VkPipelineCache _cache)
|
||||
{
|
||||
/* VkPipelineCache is a dummy object. */
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
size_t anv_GetPipelineCacheSize(
|
||||
VkDevice device,
|
||||
VkPipelineCache pipelineCache)
|
||||
{
|
||||
stub_return(0);
|
||||
}
|
||||
|
||||
VkResult anv_GetPipelineCacheData(
|
||||
VkDevice device,
|
||||
VkPipelineCache pipelineCache,
|
||||
void* pData)
|
||||
{
|
||||
stub_return(VK_UNSUPPORTED);
|
||||
}
|
||||
|
||||
VkResult anv_MergePipelineCaches(
|
||||
VkDevice device,
|
||||
VkPipelineCache destCache,
|
||||
uint32_t srcCacheCount,
|
||||
const VkPipelineCache* pSrcCaches)
|
||||
{
|
||||
stub_return(VK_UNSUPPORTED);
|
||||
}
|
||||
|
||||
// Pipeline functions
|
||||
|
||||
static void
|
||||
emit_vertex_input(struct anv_pipeline *pipeline,
|
||||
const VkPipelineVertexInputStateCreateInfo *info)
|
||||
{
|
||||
const uint32_t num_dwords = 1 + info->attributeCount * 2;
|
||||
uint32_t *p;
|
||||
bool instancing_enable[32];
|
||||
|
||||
pipeline->vb_used = 0;
|
||||
for (uint32_t i = 0; i < info->bindingCount; i++) {
|
||||
const VkVertexInputBindingDescription *desc =
|
||||
&info->pVertexBindingDescriptions[i];
|
||||
|
||||
pipeline->vb_used |= 1 << desc->binding;
|
||||
pipeline->binding_stride[desc->binding] = desc->strideInBytes;
|
||||
|
||||
/* Step rate is programmed per vertex element (attribute), not
|
||||
* binding. Set up a map of which bindings step per instance, for
|
||||
* reference by vertex element setup. */
|
||||
switch (desc->stepRate) {
|
||||
default:
|
||||
case VK_VERTEX_INPUT_STEP_RATE_VERTEX:
|
||||
instancing_enable[desc->binding] = false;
|
||||
break;
|
||||
case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
|
||||
instancing_enable[desc->binding] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p = anv_batch_emitn(&pipeline->batch, num_dwords,
|
||||
GEN8_3DSTATE_VERTEX_ELEMENTS);
|
||||
|
||||
for (uint32_t i = 0; i < info->attributeCount; i++) {
|
||||
const VkVertexInputAttributeDescription *desc =
|
||||
&info->pVertexAttributeDescriptions[i];
|
||||
const struct anv_format *format = anv_format_for_vk_format(desc->format);
|
||||
|
||||
struct GEN8_VERTEX_ELEMENT_STATE element = {
|
||||
.VertexBufferIndex = desc->binding,
|
||||
.Valid = true,
|
||||
.SourceElementFormat = format->surface_format,
|
||||
.EdgeFlagEnable = false,
|
||||
.SourceElementOffset = desc->offsetInBytes,
|
||||
.Component0Control = VFCOMP_STORE_SRC,
|
||||
.Component1Control = format->num_channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
|
||||
.Component2Control = format->num_channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
|
||||
.Component3Control = format->num_channels >= 4 ? VFCOMP_STORE_SRC : VFCOMP_STORE_1_FP
|
||||
};
|
||||
GEN8_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_INSTANCING,
|
||||
.InstancingEnable = instancing_enable[desc->binding],
|
||||
.VertexElementIndex = i,
|
||||
/* Vulkan so far doesn't have an instance divisor, so
|
||||
* this is always 1 (ignored if not instancing). */
|
||||
.InstanceDataStepRate = 1);
|
||||
}
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_SGVS,
|
||||
.VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
|
||||
.VertexIDComponentNumber = 2,
|
||||
.VertexIDElementOffset = info->bindingCount,
|
||||
.InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
|
||||
.InstanceIDComponentNumber = 3,
|
||||
.InstanceIDElementOffset = info->bindingCount);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_ia_state(struct anv_pipeline *pipeline,
|
||||
const VkPipelineInputAssemblyStateCreateInfo *info,
|
||||
const struct anv_pipeline_create_info *extra)
|
||||
{
|
||||
static const uint32_t vk_to_gen_primitive_type[] = {
|
||||
[VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
|
||||
[VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
|
||||
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
|
||||
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
|
||||
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
|
||||
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
|
||||
[VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
|
||||
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
|
||||
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
|
||||
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
|
||||
[VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
|
||||
};
|
||||
uint32_t topology = vk_to_gen_primitive_type[info->topology];
|
||||
|
||||
if (extra && extra->use_rectlist)
|
||||
topology = _3DPRIM_RECTLIST;
|
||||
|
||||
struct GEN8_3DSTATE_VF vf = {
|
||||
GEN8_3DSTATE_VF_header,
|
||||
.IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
|
||||
};
|
||||
GEN8_3DSTATE_VF_pack(NULL, pipeline->state_vf, &vf);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
|
||||
.PrimitiveTopologyType = topology);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_rs_state(struct anv_pipeline *pipeline,
|
||||
const VkPipelineRasterStateCreateInfo *info,
|
||||
const struct anv_pipeline_create_info *extra)
|
||||
{
|
||||
static const uint32_t vk_to_gen_cullmode[] = {
|
||||
[VK_CULL_MODE_NONE] = CULLMODE_NONE,
|
||||
[VK_CULL_MODE_FRONT] = CULLMODE_FRONT,
|
||||
[VK_CULL_MODE_BACK] = CULLMODE_BACK,
|
||||
[VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH
|
||||
};
|
||||
|
||||
static const uint32_t vk_to_gen_fillmode[] = {
|
||||
[VK_FILL_MODE_POINTS] = RASTER_POINT,
|
||||
[VK_FILL_MODE_WIREFRAME] = RASTER_WIREFRAME,
|
||||
[VK_FILL_MODE_SOLID] = RASTER_SOLID
|
||||
};
|
||||
|
||||
static const uint32_t vk_to_gen_front_face[] = {
|
||||
[VK_FRONT_FACE_CCW] = CounterClockwise,
|
||||
[VK_FRONT_FACE_CW] = Clockwise
|
||||
};
|
||||
|
||||
struct GEN8_3DSTATE_SF sf = {
|
||||
GEN8_3DSTATE_SF_header,
|
||||
.ViewportTransformEnable = !(extra && extra->disable_viewport),
|
||||
.TriangleStripListProvokingVertexSelect = 0,
|
||||
.LineStripListProvokingVertexSelect = 0,
|
||||
.TriangleFanProvokingVertexSelect = 0,
|
||||
.PointWidthSource = pipeline->writes_point_size ? Vertex : State,
|
||||
.PointWidth = 1.0,
|
||||
};
|
||||
|
||||
/* FINISHME: VkBool32 rasterizerDiscardEnable; */
|
||||
|
||||
GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
|
||||
|
||||
struct GEN8_3DSTATE_RASTER raster = {
|
||||
GEN8_3DSTATE_RASTER_header,
|
||||
.FrontWinding = vk_to_gen_front_face[info->frontFace],
|
||||
.CullMode = vk_to_gen_cullmode[info->cullMode],
|
||||
.FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
|
||||
.BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
|
||||
.ScissorRectangleEnable = !(extra && extra->disable_scissor),
|
||||
.ViewportZClipTestEnable = info->depthClipEnable
|
||||
};
|
||||
|
||||
GEN8_3DSTATE_RASTER_pack(NULL, pipeline->state_raster, &raster);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
|
||||
.ForceVertexURBEntryReadLength = false,
|
||||
.ForceVertexURBEntryReadOffset = false,
|
||||
.PointSpriteTextureCoordinateOrigin = UPPERLEFT,
|
||||
.NumberofSFOutputAttributes =
|
||||
pipeline->wm_prog_data.num_varying_inputs);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
emit_cb_state(struct anv_pipeline *pipeline,
|
||||
const VkPipelineColorBlendStateCreateInfo *info)
|
||||
{
|
||||
struct anv_device *device = pipeline->device;
|
||||
|
||||
static const uint32_t vk_to_gen_logic_op[] = {
|
||||
[VK_LOGIC_OP_COPY] = LOGICOP_COPY,
|
||||
[VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
|
||||
[VK_LOGIC_OP_AND] = LOGICOP_AND,
|
||||
[VK_LOGIC_OP_AND_REVERSE] = LOGICOP_AND_REVERSE,
|
||||
[VK_LOGIC_OP_AND_INVERTED] = LOGICOP_AND_INVERTED,
|
||||
[VK_LOGIC_OP_NOOP] = LOGICOP_NOOP,
|
||||
[VK_LOGIC_OP_XOR] = LOGICOP_XOR,
|
||||
[VK_LOGIC_OP_OR] = LOGICOP_OR,
|
||||
[VK_LOGIC_OP_NOR] = LOGICOP_NOR,
|
||||
[VK_LOGIC_OP_EQUIV] = LOGICOP_EQUIV,
|
||||
[VK_LOGIC_OP_INVERT] = LOGICOP_INVERT,
|
||||
[VK_LOGIC_OP_OR_REVERSE] = LOGICOP_OR_REVERSE,
|
||||
[VK_LOGIC_OP_COPY_INVERTED] = LOGICOP_COPY_INVERTED,
|
||||
[VK_LOGIC_OP_OR_INVERTED] = LOGICOP_OR_INVERTED,
|
||||
[VK_LOGIC_OP_NAND] = LOGICOP_NAND,
|
||||
[VK_LOGIC_OP_SET] = LOGICOP_SET,
|
||||
};
|
||||
|
||||
static const uint32_t vk_to_gen_blend[] = {
|
||||
[VK_BLEND_ZERO] = BLENDFACTOR_ZERO,
|
||||
[VK_BLEND_ONE] = BLENDFACTOR_ONE,
|
||||
[VK_BLEND_SRC_COLOR] = BLENDFACTOR_SRC_COLOR,
|
||||
[VK_BLEND_ONE_MINUS_SRC_COLOR] = BLENDFACTOR_INV_SRC_COLOR,
|
||||
[VK_BLEND_DEST_COLOR] = BLENDFACTOR_DST_COLOR,
|
||||
[VK_BLEND_ONE_MINUS_DEST_COLOR] = BLENDFACTOR_INV_DST_COLOR,
|
||||
[VK_BLEND_SRC_ALPHA] = BLENDFACTOR_SRC_ALPHA,
|
||||
[VK_BLEND_ONE_MINUS_SRC_ALPHA] = BLENDFACTOR_INV_SRC_ALPHA,
|
||||
[VK_BLEND_DEST_ALPHA] = BLENDFACTOR_DST_ALPHA,
|
||||
[VK_BLEND_ONE_MINUS_DEST_ALPHA] = BLENDFACTOR_INV_DST_ALPHA,
|
||||
[VK_BLEND_CONSTANT_COLOR] = BLENDFACTOR_CONST_COLOR,
|
||||
[VK_BLEND_ONE_MINUS_CONSTANT_COLOR] = BLENDFACTOR_INV_CONST_COLOR,
|
||||
[VK_BLEND_CONSTANT_ALPHA] = BLENDFACTOR_CONST_ALPHA,
|
||||
[VK_BLEND_ONE_MINUS_CONSTANT_ALPHA] = BLENDFACTOR_INV_CONST_ALPHA,
|
||||
[VK_BLEND_SRC_ALPHA_SATURATE] = BLENDFACTOR_SRC_ALPHA_SATURATE,
|
||||
[VK_BLEND_SRC1_COLOR] = BLENDFACTOR_SRC1_COLOR,
|
||||
[VK_BLEND_ONE_MINUS_SRC1_COLOR] = BLENDFACTOR_INV_SRC1_COLOR,
|
||||
[VK_BLEND_SRC1_ALPHA] = BLENDFACTOR_SRC1_ALPHA,
|
||||
[VK_BLEND_ONE_MINUS_SRC1_ALPHA] = BLENDFACTOR_INV_SRC1_ALPHA,
|
||||
};
|
||||
|
||||
static const uint32_t vk_to_gen_blend_op[] = {
|
||||
[VK_BLEND_OP_ADD] = BLENDFUNCTION_ADD,
|
||||
[VK_BLEND_OP_SUBTRACT] = BLENDFUNCTION_SUBTRACT,
|
||||
[VK_BLEND_OP_REVERSE_SUBTRACT] = BLENDFUNCTION_REVERSE_SUBTRACT,
|
||||
[VK_BLEND_OP_MIN] = BLENDFUNCTION_MIN,
|
||||
[VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX,
|
||||
};
|
||||
|
||||
uint32_t num_dwords = 1 + info->attachmentCount * 2;
|
||||
pipeline->blend_state =
|
||||
anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
|
||||
|
||||
struct GEN8_BLEND_STATE blend_state = {
|
||||
.AlphaToCoverageEnable = info->alphaToCoverageEnable,
|
||||
};
|
||||
|
||||
uint32_t *state = pipeline->blend_state.map;
|
||||
GEN8_BLEND_STATE_pack(NULL, state, &blend_state);
|
||||
|
||||
for (uint32_t i = 0; i < info->attachmentCount; i++) {
|
||||
const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[i];
|
||||
|
||||
struct GEN8_BLEND_STATE_ENTRY entry = {
|
||||
.LogicOpEnable = info->logicOpEnable,
|
||||
.LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
|
||||
.ColorBufferBlendEnable = a->blendEnable,
|
||||
.PreBlendSourceOnlyClampEnable = false,
|
||||
.PreBlendColorClampEnable = false,
|
||||
.PostBlendColorClampEnable = false,
|
||||
.SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
|
||||
.DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
|
||||
.ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
|
||||
.SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
|
||||
.DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
|
||||
.AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
|
||||
.WriteDisableAlpha = !(a->channelWriteMask & VK_CHANNEL_A_BIT),
|
||||
.WriteDisableRed = !(a->channelWriteMask & VK_CHANNEL_R_BIT),
|
||||
.WriteDisableGreen = !(a->channelWriteMask & VK_CHANNEL_G_BIT),
|
||||
.WriteDisableBlue = !(a->channelWriteMask & VK_CHANNEL_B_BIT),
|
||||
};
|
||||
|
||||
GEN8_BLEND_STATE_ENTRY_pack(NULL, state + i * 2 + 1, &entry);
|
||||
}
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_BLEND_STATE_POINTERS,
|
||||
.BlendStatePointer = pipeline->blend_state.offset,
|
||||
.BlendStatePointerValid = true);
|
||||
}
|
||||
|
||||
static const uint32_t vk_to_gen_compare_op[] = {
|
||||
[VK_COMPARE_OP_NEVER] = COMPAREFUNCTION_NEVER,
|
||||
[VK_COMPARE_OP_LESS] = COMPAREFUNCTION_LESS,
|
||||
[VK_COMPARE_OP_EQUAL] = COMPAREFUNCTION_EQUAL,
|
||||
[VK_COMPARE_OP_LESS_EQUAL] = COMPAREFUNCTION_LEQUAL,
|
||||
[VK_COMPARE_OP_GREATER] = COMPAREFUNCTION_GREATER,
|
||||
[VK_COMPARE_OP_NOT_EQUAL] = COMPAREFUNCTION_NOTEQUAL,
|
||||
[VK_COMPARE_OP_GREATER_EQUAL] = COMPAREFUNCTION_GEQUAL,
|
||||
[VK_COMPARE_OP_ALWAYS] = COMPAREFUNCTION_ALWAYS,
|
||||
};
|
||||
|
||||
static const uint32_t vk_to_gen_stencil_op[] = {
|
||||
[VK_STENCIL_OP_KEEP] = 0,
|
||||
[VK_STENCIL_OP_ZERO] = 0,
|
||||
[VK_STENCIL_OP_REPLACE] = 0,
|
||||
[VK_STENCIL_OP_INC_CLAMP] = 0,
|
||||
[VK_STENCIL_OP_DEC_CLAMP] = 0,
|
||||
[VK_STENCIL_OP_INVERT] = 0,
|
||||
[VK_STENCIL_OP_INC_WRAP] = 0,
|
||||
[VK_STENCIL_OP_DEC_WRAP] = 0
|
||||
};
|
||||
|
||||
static void
|
||||
emit_ds_state(struct anv_pipeline *pipeline,
|
||||
const VkPipelineDepthStencilStateCreateInfo *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
/* We're going to OR this together with the dynamic state. We need
|
||||
* to make sure it's initialized to something useful.
|
||||
*/
|
||||
memset(pipeline->state_wm_depth_stencil, 0,
|
||||
sizeof(pipeline->state_wm_depth_stencil));
|
||||
return;
|
||||
}
|
||||
|
||||
/* VkBool32 depthBoundsEnable; // optional (depth_bounds_test) */
|
||||
|
||||
struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
|
||||
.DepthTestEnable = info->depthTestEnable,
|
||||
.DepthBufferWriteEnable = info->depthWriteEnable,
|
||||
.DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
|
||||
.DoubleSidedStencilEnable = true,
|
||||
|
||||
.StencilTestEnable = info->stencilTestEnable,
|
||||
.StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
|
||||
.StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
|
||||
.StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
|
||||
.StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
|
||||
.BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
|
||||
.BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
|
||||
.BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
|
||||
.BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
|
||||
};
|
||||
|
||||
GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, pipeline->state_wm_depth_stencil, &wm_depth_stencil);
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_pipeline_create(
|
||||
VkDevice _device,
|
||||
const VkGraphicsPipelineCreateInfo* pCreateInfo,
|
||||
const struct anv_pipeline_create_info * extra,
|
||||
VkPipeline* pPipeline)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_pipeline *pipeline;
|
||||
VkResult result;
|
||||
uint32_t offset, length;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
|
||||
|
||||
pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (pipeline == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
pipeline->device = device;
|
||||
pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
|
||||
memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
|
||||
|
||||
result = anv_reloc_list_init(&pipeline->batch.relocs, device);
|
||||
if (result != VK_SUCCESS) {
|
||||
anv_device_free(device, pipeline);
|
||||
return result;
|
||||
}
|
||||
pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
|
||||
pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
|
||||
|
||||
anv_state_stream_init(&pipeline->program_stream,
|
||||
&device->instruction_block_pool);
|
||||
|
||||
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
|
||||
pipeline->shaders[pCreateInfo->pStages[i].stage] =
|
||||
anv_shader_from_handle(pCreateInfo->pStages[i].shader);
|
||||
}
|
||||
|
||||
if (pCreateInfo->pTessellationState)
|
||||
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO");
|
||||
if (pCreateInfo->pViewportState)
|
||||
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO");
|
||||
if (pCreateInfo->pMultisampleState)
|
||||
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO");
|
||||
|
||||
pipeline->use_repclear = extra && extra->use_repclear;
|
||||
|
||||
anv_compiler_run(device->compiler, pipeline);
|
||||
|
||||
/* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
|
||||
* hard code this to num_attributes - 2. This is because the attributes
|
||||
* include VUE header and position, which aren't counted as varying
|
||||
* inputs. */
|
||||
if (pipeline->vs_simd8 == NO_KERNEL) {
|
||||
pipeline->wm_prog_data.num_varying_inputs =
|
||||
pCreateInfo->pVertexInputState->attributeCount - 2;
|
||||
}
|
||||
|
||||
assert(pCreateInfo->pVertexInputState);
|
||||
emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
|
||||
assert(pCreateInfo->pInputAssemblyState);
|
||||
emit_ia_state(pipeline, pCreateInfo->pInputAssemblyState, extra);
|
||||
assert(pCreateInfo->pRasterState);
|
||||
emit_rs_state(pipeline, pCreateInfo->pRasterState, extra);
|
||||
emit_ds_state(pipeline, pCreateInfo->pDepthStencilState);
|
||||
emit_cb_state(pipeline, pCreateInfo->pColorBlendState);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_STATISTICS,
|
||||
.StatisticsEnable = true);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_HS, .Enable = false);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_TE, .TEEnable = false);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_DS, .FunctionEnable = false);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
|
||||
.ConstantBufferOffset = 0,
|
||||
.ConstantBufferSize = 4);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
|
||||
.ConstantBufferOffset = 4,
|
||||
.ConstantBufferSize = 4);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
|
||||
.ConstantBufferOffset = 8,
|
||||
.ConstantBufferSize = 4);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM_CHROMAKEY,
|
||||
.ChromaKeyKillEnable = false);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE_SWIZ);
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_AA_LINE_PARAMETERS);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
|
||||
.ClipEnable = true,
|
||||
.ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
|
||||
.MinimumPointWidth = 0.125,
|
||||
.MaximumPointWidth = 255.875);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM,
|
||||
.StatisticsEnable = true,
|
||||
.LineEndCapAntialiasingRegionWidth = _05pixels,
|
||||
.LineAntialiasingRegionWidth = _10pixels,
|
||||
.EarlyDepthStencilControl = NORMAL,
|
||||
.ForceThreadDispatchEnable = NORMAL,
|
||||
.PointRasterizationRule = RASTRULE_UPPER_RIGHT,
|
||||
.BarycentricInterpolationMode =
|
||||
pipeline->wm_prog_data.barycentric_interp_modes);
|
||||
|
||||
uint32_t samples = 1;
|
||||
uint32_t log2_samples = __builtin_ffs(samples) - 1;
|
||||
bool enable_sampling = samples > 1 ? true : false;
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_MULTISAMPLE,
|
||||
.PixelPositionOffsetEnable = enable_sampling,
|
||||
.PixelLocation = CENTER,
|
||||
.NumberofMultisamples = log2_samples);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SAMPLE_MASK,
|
||||
.SampleMask = 0xffff);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_VS,
|
||||
.VSURBStartingAddress = pipeline->urb.vs_start,
|
||||
.VSURBEntryAllocationSize = pipeline->urb.vs_size - 1,
|
||||
.VSNumberofURBEntries = pipeline->urb.nr_vs_entries);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_GS,
|
||||
.GSURBStartingAddress = pipeline->urb.gs_start,
|
||||
.GSURBEntryAllocationSize = pipeline->urb.gs_size - 1,
|
||||
.GSNumberofURBEntries = pipeline->urb.nr_gs_entries);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_HS,
|
||||
.HSURBStartingAddress = pipeline->urb.vs_start,
|
||||
.HSURBEntryAllocationSize = 0,
|
||||
.HSNumberofURBEntries = 0);
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_DS,
|
||||
.DSURBStartingAddress = pipeline->urb.vs_start,
|
||||
.DSURBEntryAllocationSize = 0,
|
||||
.DSNumberofURBEntries = 0);
|
||||
|
||||
const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
|
||||
offset = 1;
|
||||
length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - offset;
|
||||
|
||||
if (pipeline->gs_vec4 == NO_KERNEL)
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS, .Enable = false);
|
||||
else
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS,
|
||||
.SingleProgramFlow = false,
|
||||
.KernelStartPointer = pipeline->gs_vec4,
|
||||
.VectorMaskEnable = Vmask,
|
||||
.SamplerCount = 0,
|
||||
.BindingTableEntryCount = 0,
|
||||
.ExpectedVertexCount = pipeline->gs_vertex_count,
|
||||
|
||||
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
|
||||
.PerThreadScratchSpace = ffs(gs_prog_data->base.base.total_scratch / 2048),
|
||||
|
||||
.OutputVertexSize = gs_prog_data->output_vertex_size_hwords * 2 - 1,
|
||||
.OutputTopology = gs_prog_data->output_topology,
|
||||
.VertexURBEntryReadLength = gs_prog_data->base.urb_read_length,
|
||||
.DispatchGRFStartRegisterForURBData =
|
||||
gs_prog_data->base.base.dispatch_grf_start_reg,
|
||||
|
||||
.MaximumNumberofThreads = device->info.max_gs_threads,
|
||||
.ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
|
||||
//pipeline->gs_prog_data.dispatch_mode |
|
||||
.StatisticsEnable = true,
|
||||
.IncludePrimitiveID = gs_prog_data->include_primitive_id,
|
||||
.ReorderMode = TRAILING,
|
||||
.Enable = true,
|
||||
|
||||
.ControlDataFormat = gs_prog_data->control_data_format,
|
||||
|
||||
/* FIXME: mesa sets this based on ctx->Transform.ClipPlanesEnabled:
|
||||
* UserClipDistanceClipTestEnableBitmask_3DSTATE_GS(v)
|
||||
* UserClipDistanceCullTestEnableBitmask(v)
|
||||
*/
|
||||
|
||||
.VertexURBEntryOutputReadOffset = offset,
|
||||
.VertexURBEntryOutputLength = length);
|
||||
|
||||
const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
|
||||
/* Skip the VUE header and position slots */
|
||||
offset = 1;
|
||||
length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
|
||||
|
||||
if (pipeline->vs_simd8 == NO_KERNEL || (extra && extra->disable_vs))
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
|
||||
.FunctionEnable = false,
|
||||
.VertexURBEntryOutputReadOffset = 1,
|
||||
/* Even if VS is disabled, SBE still gets the amount of
|
||||
* vertex data to read from this field. We use attribute
|
||||
* count - 1, as we don't count the VUE header here. */
|
||||
.VertexURBEntryOutputLength =
|
||||
DIV_ROUND_UP(pCreateInfo->pVertexInputState->attributeCount - 1, 2));
|
||||
else
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
|
||||
.KernelStartPointer = pipeline->vs_simd8,
|
||||
.SingleVertexDispatch = Multiple,
|
||||
.VectorMaskEnable = Dmask,
|
||||
.SamplerCount = 0,
|
||||
.BindingTableEntryCount =
|
||||
vue_prog_data->base.binding_table.size_bytes / 4,
|
||||
.ThreadDispatchPriority = Normal,
|
||||
.FloatingPointMode = IEEE754,
|
||||
.IllegalOpcodeExceptionEnable = false,
|
||||
.AccessesUAV = false,
|
||||
.SoftwareExceptionEnable = false,
|
||||
|
||||
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
|
||||
.PerThreadScratchSpace = ffs(vue_prog_data->base.total_scratch / 2048),
|
||||
|
||||
.DispatchGRFStartRegisterForURBData =
|
||||
vue_prog_data->base.dispatch_grf_start_reg,
|
||||
.VertexURBEntryReadLength = vue_prog_data->urb_read_length,
|
||||
.VertexURBEntryReadOffset = 0,
|
||||
|
||||
.MaximumNumberofThreads = device->info.max_vs_threads - 1,
|
||||
.StatisticsEnable = false,
|
||||
.SIMD8DispatchEnable = true,
|
||||
.VertexCacheDisable = false,
|
||||
.FunctionEnable = true,
|
||||
|
||||
.VertexURBEntryOutputReadOffset = offset,
|
||||
.VertexURBEntryOutputLength = length,
|
||||
.UserClipDistanceClipTestEnableBitmask = 0,
|
||||
.UserClipDistanceCullTestEnableBitmask = 0);
|
||||
|
||||
const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
|
||||
uint32_t ksp0, ksp2, grf_start0, grf_start2;
|
||||
|
||||
ksp2 = 0;
|
||||
grf_start2 = 0;
|
||||
if (pipeline->ps_simd8 != NO_KERNEL) {
|
||||
ksp0 = pipeline->ps_simd8;
|
||||
grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
|
||||
if (pipeline->ps_simd16 != NO_KERNEL) {
|
||||
ksp2 = pipeline->ps_simd16;
|
||||
grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
|
||||
}
|
||||
} else if (pipeline->ps_simd16 != NO_KERNEL) {
|
||||
ksp0 = pipeline->ps_simd16;
|
||||
grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
|
||||
} else {
|
||||
unreachable("no ps shader");
|
||||
}
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS,
|
||||
.KernelStartPointer0 = ksp0,
|
||||
|
||||
.SingleProgramFlow = false,
|
||||
.VectorMaskEnable = true,
|
||||
.SamplerCount = 1,
|
||||
|
||||
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
|
||||
.PerThreadScratchSpace = ffs(wm_prog_data->base.total_scratch / 2048),
|
||||
|
||||
.MaximumNumberofThreadsPerPSD = 64 - 2,
|
||||
.PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
|
||||
POSOFFSET_SAMPLE: POSOFFSET_NONE,
|
||||
.PushConstantEnable = wm_prog_data->base.nr_params > 0,
|
||||
._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
|
||||
._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
|
||||
._32PixelDispatchEnable = false,
|
||||
|
||||
.DispatchGRFStartRegisterForConstantSetupData0 = grf_start0,
|
||||
.DispatchGRFStartRegisterForConstantSetupData1 = 0,
|
||||
.DispatchGRFStartRegisterForConstantSetupData2 = grf_start2,
|
||||
|
||||
.KernelStartPointer1 = 0,
|
||||
.KernelStartPointer2 = ksp2);
|
||||
|
||||
bool per_sample_ps = false;
|
||||
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS_EXTRA,
|
||||
.PixelShaderValid = true,
|
||||
.PixelShaderKillsPixel = wm_prog_data->uses_kill,
|
||||
.PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
|
||||
.AttributeEnable = wm_prog_data->num_varying_inputs > 0,
|
||||
.oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
|
||||
.PixelShaderIsPerSample = per_sample_ps);
|
||||
|
||||
*pPipeline = anv_pipeline_to_handle(pipeline);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_DestroyPipeline(
|
||||
VkDevice _device,
|
||||
VkPipeline _pipeline)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
|
||||
|
||||
anv_compiler_free(pipeline);
|
||||
anv_reloc_list_finish(&pipeline->batch.relocs, pipeline->device);
|
||||
anv_state_stream_finish(&pipeline->program_stream);
|
||||
anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
|
||||
anv_device_free(pipeline->device, pipeline);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_CreateGraphicsPipelines(
|
||||
VkDevice _device,
|
||||
VkPipelineCache pipelineCache,
|
||||
uint32_t count,
|
||||
const VkGraphicsPipelineCreateInfo* pCreateInfos,
|
||||
VkPipeline* pPipelines)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
unsigned i = 0;
|
||||
for (; i < count; i++) {
|
||||
result = anv_pipeline_create(_device, &pCreateInfos[i],
|
||||
NULL, &pPipelines[i]);
|
||||
if (result != VK_SUCCESS) {
|
||||
for (unsigned j = 0; j < i; j++) {
|
||||
anv_DestroyPipeline(_device, pPipelines[j]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult anv_compute_pipeline_create(
|
||||
VkDevice _device,
|
||||
const VkComputePipelineCreateInfo* pCreateInfo,
|
||||
VkPipeline* pPipeline)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_pipeline *pipeline;
|
||||
VkResult result;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
|
||||
|
||||
pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (pipeline == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
pipeline->device = device;
|
||||
pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
|
||||
|
||||
result = anv_reloc_list_init(&pipeline->batch.relocs, device);
|
||||
if (result != VK_SUCCESS) {
|
||||
anv_device_free(device, pipeline);
|
||||
return result;
|
||||
}
|
||||
pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
|
||||
pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
|
||||
|
||||
anv_state_stream_init(&pipeline->program_stream,
|
||||
&device->instruction_block_pool);
|
||||
|
||||
memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
|
||||
|
||||
pipeline->shaders[VK_SHADER_STAGE_COMPUTE] =
|
||||
anv_shader_from_handle(pCreateInfo->cs.shader);
|
||||
|
||||
pipeline->use_repclear = false;
|
||||
|
||||
anv_compiler_run(device->compiler, pipeline);
|
||||
|
||||
const struct brw_cs_prog_data *cs_prog_data = &pipeline->cs_prog_data;
|
||||
|
||||
anv_batch_emit(&pipeline->batch, GEN8_MEDIA_VFE_STATE,
|
||||
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
|
||||
.PerThreadScratchSpace = ffs(cs_prog_data->base.total_scratch / 2048),
|
||||
.ScratchSpaceBasePointerHigh = 0,
|
||||
.StackSize = 0,
|
||||
|
||||
.MaximumNumberofThreads = device->info.max_cs_threads - 1,
|
||||
.NumberofURBEntries = 2,
|
||||
.ResetGatewayTimer = true,
|
||||
.BypassGatewayControl = true,
|
||||
.URBEntryAllocationSize = 2,
|
||||
.CURBEAllocationSize = 0);
|
||||
|
||||
struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
|
||||
uint32_t group_size = prog_data->local_size[0] *
|
||||
prog_data->local_size[1] * prog_data->local_size[2];
|
||||
pipeline->cs_thread_width_max = DIV_ROUND_UP(group_size, prog_data->simd_size);
|
||||
uint32_t remainder = group_size & (prog_data->simd_size - 1);
|
||||
|
||||
if (remainder > 0)
|
||||
pipeline->cs_right_mask = ~0u >> (32 - remainder);
|
||||
else
|
||||
pipeline->cs_right_mask = ~0u >> (32 - prog_data->simd_size);
|
||||
|
||||
|
||||
*pPipeline = anv_pipeline_to_handle(pipeline);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_CreateComputePipelines(
|
||||
VkDevice _device,
|
||||
VkPipelineCache pipelineCache,
|
||||
uint32_t count,
|
||||
const VkComputePipelineCreateInfo* pCreateInfos,
|
||||
VkPipeline* pPipelines)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
unsigned i = 0;
|
||||
for (; i < count; i++) {
|
||||
result = anv_compute_pipeline_create(_device, &pCreateInfos[i],
|
||||
&pPipelines[i]);
|
||||
if (result != VK_SUCCESS) {
|
||||
for (unsigned j = 0; j < i; j++) {
|
||||
anv_DestroyPipeline(_device, pPipelines[j]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
// Pipeline layout functions
|
||||
|
||||
VkResult anv_CreatePipelineLayout(
|
||||
VkDevice _device,
|
||||
const VkPipelineLayoutCreateInfo* pCreateInfo,
|
||||
VkPipelineLayout* pPipelineLayout)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_pipeline_layout *layout;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
|
||||
|
||||
layout = anv_device_alloc(device, sizeof(*layout), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (layout == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
layout->num_sets = pCreateInfo->descriptorSetCount;
|
||||
|
||||
uint32_t surface_start[VK_SHADER_STAGE_NUM] = { 0, };
|
||||
uint32_t sampler_start[VK_SHADER_STAGE_NUM] = { 0, };
|
||||
|
||||
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
|
||||
layout->stage[s].surface_count = 0;
|
||||
layout->stage[s].sampler_count = 0;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
|
||||
ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
|
||||
pCreateInfo->pSetLayouts[i]);
|
||||
|
||||
layout->set[i].layout = set_layout;
|
||||
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
|
||||
layout->set[i].surface_start[s] = surface_start[s];
|
||||
surface_start[s] += set_layout->stage[s].surface_count;
|
||||
layout->set[i].sampler_start[s] = sampler_start[s];
|
||||
sampler_start[s] += set_layout->stage[s].sampler_count;
|
||||
|
||||
layout->stage[s].surface_count += set_layout->stage[s].surface_count;
|
||||
layout->stage[s].sampler_count += set_layout->stage[s].sampler_count;
|
||||
}
|
||||
}
|
||||
|
||||
*pPipelineLayout = anv_pipeline_layout_to_handle(layout);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_DestroyPipelineLayout(
|
||||
VkDevice _device,
|
||||
VkPipelineLayout _pipelineLayout)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _pipelineLayout);
|
||||
|
||||
anv_device_free(device, pipeline_layout);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
1066
src/vulkan/private.h
Normal file
1066
src/vulkan/private.h
Normal file
File diff suppressed because it is too large
Load Diff
352
src/vulkan/query.c
Normal file
352
src/vulkan/query.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
struct anv_query_pool_slot {
|
||||
uint64_t begin;
|
||||
uint64_t end;
|
||||
uint64_t available;
|
||||
};
|
||||
|
||||
struct anv_query_pool {
|
||||
VkQueryType type;
|
||||
uint32_t slots;
|
||||
struct anv_bo bo;
|
||||
};
|
||||
|
||||
VkResult anv_CreateQueryPool(
|
||||
VkDevice _device,
|
||||
const VkQueryPoolCreateInfo* pCreateInfo,
|
||||
VkQueryPool* pQueryPool)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_query_pool *pool;
|
||||
VkResult result;
|
||||
size_t size;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
|
||||
|
||||
switch (pCreateInfo->queryType) {
|
||||
case VK_QUERY_TYPE_OCCLUSION:
|
||||
break;
|
||||
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
|
||||
return VK_UNSUPPORTED;
|
||||
default:
|
||||
unreachable("");
|
||||
}
|
||||
|
||||
pool = anv_device_alloc(device, sizeof(*pool), 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (pool == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
size = pCreateInfo->slots * sizeof(struct anv_query_pool_slot);
|
||||
result = anv_bo_init_new(&pool->bo, device, size);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
pool->bo.map = anv_gem_mmap(device, pool->bo.gem_handle, 0, size);
|
||||
|
||||
*pQueryPool = anv_query_pool_to_handle(pool);
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
anv_device_free(device, pool);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult anv_DestroyQueryPool(
|
||||
VkDevice _device,
|
||||
VkQueryPool _pool)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_query_pool, pool, _pool);
|
||||
|
||||
anv_gem_munmap(pool->bo.map, pool->bo.size);
|
||||
anv_gem_close(device, pool->bo.gem_handle);
|
||||
anv_device_free(device, pool);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_GetQueryPoolResults(
|
||||
VkDevice _device,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t startQuery,
|
||||
uint32_t queryCount,
|
||||
size_t* pDataSize,
|
||||
void* pData,
|
||||
VkQueryResultFlags flags)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
|
||||
struct anv_query_pool_slot *slot = pool->bo.map;
|
||||
int64_t timeout = INT64_MAX;
|
||||
uint32_t *dst32 = pData;
|
||||
uint64_t *dst64 = pData;
|
||||
uint64_t result;
|
||||
int ret;
|
||||
|
||||
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
|
||||
/* Where is the availabilty info supposed to go? */
|
||||
anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
|
||||
return VK_UNSUPPORTED;
|
||||
}
|
||||
|
||||
assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
|
||||
|
||||
if (flags & VK_QUERY_RESULT_64_BIT)
|
||||
*pDataSize = queryCount * sizeof(uint64_t);
|
||||
else
|
||||
*pDataSize = queryCount * sizeof(uint32_t);
|
||||
|
||||
if (pData == NULL)
|
||||
return VK_SUCCESS;
|
||||
|
||||
if (flags & VK_QUERY_RESULT_WAIT_BIT) {
|
||||
ret = anv_gem_wait(device, pool->bo.gem_handle, &timeout);
|
||||
if (ret == -1)
|
||||
return vk_error(VK_ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < queryCount; i++) {
|
||||
result = slot[startQuery + i].end - slot[startQuery + i].begin;
|
||||
if (flags & VK_QUERY_RESULT_64_BIT) {
|
||||
*dst64++ = result;
|
||||
} else {
|
||||
if (result > UINT32_MAX)
|
||||
result = UINT32_MAX;
|
||||
*dst32++ = result;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_batch_emit_ps_depth_count(struct anv_batch *batch,
|
||||
struct anv_bo *bo, uint32_t offset)
|
||||
{
|
||||
anv_batch_emit(batch, GEN8_PIPE_CONTROL,
|
||||
.DestinationAddressType = DAT_PPGTT,
|
||||
.PostSyncOperation = WritePSDepthCount,
|
||||
.Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
|
||||
}
|
||||
|
||||
void anv_CmdBeginQuery(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t slot,
|
||||
VkQueryControlFlags flags)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
|
||||
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
|
||||
|
||||
switch (pool->type) {
|
||||
case VK_QUERY_TYPE_OCCLUSION:
|
||||
anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
|
||||
slot * sizeof(struct anv_query_pool_slot));
|
||||
break;
|
||||
|
||||
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
|
||||
default:
|
||||
unreachable("");
|
||||
}
|
||||
}
|
||||
|
||||
void anv_CmdEndQuery(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t slot)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
|
||||
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
|
||||
|
||||
switch (pool->type) {
|
||||
case VK_QUERY_TYPE_OCCLUSION:
|
||||
anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
|
||||
slot * sizeof(struct anv_query_pool_slot) + 8);
|
||||
break;
|
||||
|
||||
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
|
||||
default:
|
||||
unreachable("");
|
||||
}
|
||||
}
|
||||
|
||||
void anv_CmdResetQueryPool(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t startQuery,
|
||||
uint32_t queryCount)
|
||||
{
|
||||
stub();
|
||||
}
|
||||
|
||||
#define TIMESTAMP 0x2358
|
||||
|
||||
void anv_CmdWriteTimestamp(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkTimestampType timestampType,
|
||||
VkBuffer destBuffer,
|
||||
VkDeviceSize destOffset)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
|
||||
ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
|
||||
struct anv_bo *bo = buffer->bo;
|
||||
|
||||
switch (timestampType) {
|
||||
case VK_TIMESTAMP_TYPE_TOP:
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
|
||||
.RegisterAddress = TIMESTAMP,
|
||||
.MemoryAddress = { bo, buffer->offset + destOffset });
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
|
||||
.RegisterAddress = TIMESTAMP + 4,
|
||||
.MemoryAddress = { bo, buffer->offset + destOffset + 4 });
|
||||
break;
|
||||
|
||||
case VK_TIMESTAMP_TYPE_BOTTOM:
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
|
||||
.DestinationAddressType = DAT_PPGTT,
|
||||
.PostSyncOperation = WriteTimestamp,
|
||||
.Address = /* FIXME: This is only lower 32 bits */
|
||||
{ bo, buffer->offset + destOffset });
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define alu_opcode(v) __gen_field((v), 20, 31)
|
||||
#define alu_operand1(v) __gen_field((v), 10, 19)
|
||||
#define alu_operand2(v) __gen_field((v), 0, 9)
|
||||
#define alu(opcode, operand1, operand2) \
|
||||
alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
|
||||
|
||||
#define OPCODE_NOOP 0x000
|
||||
#define OPCODE_LOAD 0x080
|
||||
#define OPCODE_LOADINV 0x480
|
||||
#define OPCODE_LOAD0 0x081
|
||||
#define OPCODE_LOAD1 0x481
|
||||
#define OPCODE_ADD 0x100
|
||||
#define OPCODE_SUB 0x101
|
||||
#define OPCODE_AND 0x102
|
||||
#define OPCODE_OR 0x103
|
||||
#define OPCODE_XOR 0x104
|
||||
#define OPCODE_STORE 0x180
|
||||
#define OPCODE_STOREINV 0x580
|
||||
|
||||
#define OPERAND_R0 0x00
|
||||
#define OPERAND_R1 0x01
|
||||
#define OPERAND_R2 0x02
|
||||
#define OPERAND_R3 0x03
|
||||
#define OPERAND_R4 0x04
|
||||
#define OPERAND_SRCA 0x20
|
||||
#define OPERAND_SRCB 0x21
|
||||
#define OPERAND_ACCU 0x31
|
||||
#define OPERAND_ZF 0x32
|
||||
#define OPERAND_CF 0x33
|
||||
|
||||
#define CS_GPR(n) (0x2600 + (n) * 8)
|
||||
|
||||
static void
|
||||
emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
|
||||
struct anv_bo *bo, uint32_t offset)
|
||||
{
|
||||
anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
|
||||
.RegisterAddress = reg,
|
||||
.MemoryAddress = { bo, offset });
|
||||
anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
|
||||
.RegisterAddress = reg + 4,
|
||||
.MemoryAddress = { bo, offset + 4 });
|
||||
}
|
||||
|
||||
void anv_CmdCopyQueryPoolResults(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t startQuery,
|
||||
uint32_t queryCount,
|
||||
VkBuffer destBuffer,
|
||||
VkDeviceSize destOffset,
|
||||
VkDeviceSize destStride,
|
||||
VkQueryResultFlags flags)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
|
||||
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
|
||||
ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
|
||||
uint32_t slot_offset, dst_offset;
|
||||
|
||||
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
|
||||
/* Where is the availabilty info supposed to go? */
|
||||
anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
|
||||
|
||||
/* FIXME: If we're not waiting, should we just do this on the CPU? */
|
||||
if (flags & VK_QUERY_RESULT_WAIT_BIT)
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
|
||||
.CommandStreamerStallEnable = true,
|
||||
.StallAtPixelScoreboard = true);
|
||||
|
||||
dst_offset = buffer->offset + destOffset;
|
||||
for (uint32_t i = 0; i < queryCount; i++) {
|
||||
|
||||
slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
|
||||
|
||||
emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
|
||||
emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
|
||||
|
||||
/* FIXME: We need to clamp the result for 32 bit. */
|
||||
|
||||
uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
|
||||
dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
|
||||
dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
|
||||
dw[3] = alu(OPCODE_SUB, 0, 0);
|
||||
dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
|
||||
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
|
||||
.RegisterAddress = CS_GPR(2),
|
||||
/* FIXME: This is only lower 32 bits */
|
||||
.MemoryAddress = { buffer->bo, dst_offset });
|
||||
|
||||
if (flags & VK_QUERY_RESULT_64_BIT)
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
|
||||
.RegisterAddress = CS_GPR(2) + 4,
|
||||
/* FIXME: This is only lower 32 bits */
|
||||
.MemoryAddress = { buffer->bo, dst_offset + 4 });
|
||||
|
||||
dst_offset += destStride;
|
||||
}
|
||||
}
|
151
src/vulkan/util.c
Normal file
151
src/vulkan/util.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
/** Log an error message. */
|
||||
void anv_printflike(1, 2)
|
||||
anv_loge(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
anv_loge_v(format, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
/** \see anv_loge() */
|
||||
void
|
||||
anv_loge_v(const char *format, va_list va)
|
||||
{
|
||||
fprintf(stderr, "vk: error: ");
|
||||
vfprintf(stderr, format, va);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void anv_printflike(3, 4)
|
||||
__anv_finishme(const char *file, int line, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[256];
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buffer);
|
||||
}
|
||||
|
||||
void anv_noreturn anv_printflike(1, 2)
|
||||
anv_abortf(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
anv_abortfv(format, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void anv_noreturn
|
||||
anv_abortfv(const char *format, va_list va)
|
||||
{
|
||||
fprintf(stderr, "vk: error: ");
|
||||
vfprintf(stderr, format, va);
|
||||
fprintf(stderr, "\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
anv_vector_init(struct anv_vector *vector, uint32_t element_size, uint32_t size)
|
||||
{
|
||||
assert(is_power_of_two(size));
|
||||
assert(element_size < size && is_power_of_two(element_size));
|
||||
|
||||
vector->head = 0;
|
||||
vector->tail = 0;
|
||||
vector->element_size = element_size;
|
||||
vector->size = size;
|
||||
vector->data = malloc(size);
|
||||
|
||||
return vector->data != NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
anv_vector_add(struct anv_vector *vector)
|
||||
{
|
||||
uint32_t offset, size, split, tail;
|
||||
void *data;
|
||||
|
||||
if (vector->head - vector->tail == vector->size) {
|
||||
size = vector->size * 2;
|
||||
data = malloc(size);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
split = align_u32(vector->tail, vector->size);
|
||||
tail = vector->tail & (vector->size - 1);
|
||||
if (vector->head - split < vector->size) {
|
||||
memcpy(data + tail,
|
||||
vector->data + tail,
|
||||
split - vector->tail);
|
||||
memcpy(data + vector->size,
|
||||
vector->data, vector->head - split);
|
||||
} else {
|
||||
memcpy(data + tail,
|
||||
vector->data + tail,
|
||||
vector->head - vector->tail);
|
||||
}
|
||||
free(vector->data);
|
||||
vector->data = data;
|
||||
vector->size = size;
|
||||
}
|
||||
|
||||
assert(vector->head - vector->tail < vector->size);
|
||||
|
||||
offset = vector->head & (vector->size - 1);
|
||||
vector->head += vector->element_size;
|
||||
|
||||
return vector->data + offset;
|
||||
}
|
||||
|
||||
void *
|
||||
anv_vector_remove(struct anv_vector *vector)
|
||||
{
|
||||
uint32_t offset;
|
||||
|
||||
if (vector->head == vector->tail)
|
||||
return NULL;
|
||||
|
||||
assert(vector->head - vector->tail <= vector->size);
|
||||
|
||||
offset = vector->tail & (vector->size - 1);
|
||||
vector->tail += vector->element_size;
|
||||
|
||||
return vector->data + offset;
|
||||
}
|
269
src/vulkan/vk_gen.py
Normal file
269
src/vulkan/vk_gen.py
Normal file
@@ -0,0 +1,269 @@
|
||||
# coding=utf-8
|
||||
#
|
||||
# Copyright © 2015 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
import fileinput, re, sys
|
||||
|
||||
# Each function typedef in the vulkan.h header is all on one line and matches
|
||||
# this regepx. We hope that won't change.
|
||||
|
||||
p = re.compile('typedef ([^ ]*) *\(VKAPI \*PFN_vk([^(]*)\)(.*);')
|
||||
|
||||
entrypoints = []
|
||||
|
||||
# We generate a static hash table for entry point lookup
|
||||
# (vkGetProcAddress). We use a linear congruential generator for our hash
|
||||
# function and a power-of-two size table. The prime numbers are determined
|
||||
# experimentally.
|
||||
|
||||
none = 0xffff
|
||||
hash_size = 256
|
||||
u32_mask = 2**32 - 1
|
||||
hash_mask = hash_size - 1
|
||||
|
||||
prime_factor = 5024183
|
||||
prime_step = 19
|
||||
|
||||
def hash(name):
|
||||
h = 0;
|
||||
for c in name:
|
||||
h = (h * prime_factor + ord(c)) & u32_mask
|
||||
|
||||
return h
|
||||
|
||||
opt_header = False
|
||||
opt_code = False
|
||||
|
||||
if (sys.argv[1] == "header"):
|
||||
opt_header = True
|
||||
sys.argv.pop()
|
||||
elif (sys.argv[1] == "code"):
|
||||
opt_code = True
|
||||
sys.argv.pop()
|
||||
|
||||
# Parse the entry points in the header
|
||||
|
||||
i = 0
|
||||
for line in fileinput.input():
|
||||
m = p.match(line)
|
||||
if (m):
|
||||
if m.group(2) == 'VoidFunction':
|
||||
continue
|
||||
fullname = "vk" + m.group(2)
|
||||
h = hash(fullname)
|
||||
entrypoints.append((m.group(1), m.group(2), m.group(3), i, h))
|
||||
i = i + 1
|
||||
|
||||
# For outputting entrypoints.h we generate a anv_EntryPoint() prototype
|
||||
# per entry point.
|
||||
|
||||
if opt_header:
|
||||
for type, name, args, num, h in entrypoints:
|
||||
print "%s anv_%s%s;" % (type, name, args)
|
||||
print "%s anv_validate_%s%s;" % (type, name, args)
|
||||
exit()
|
||||
|
||||
|
||||
|
||||
print """/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* This file generated from vk_gen.py, don't edit directly. */
|
||||
|
||||
#include "private.h"
|
||||
|
||||
struct anv_entrypoint {
|
||||
uint32_t name;
|
||||
uint32_t hash;
|
||||
void *function;
|
||||
void *validate;
|
||||
};
|
||||
|
||||
/* We use a big string constant to avoid lots of reloctions from the entry
|
||||
* point table to lots of little strings. The entries in the entry point table
|
||||
* store the index into this big string.
|
||||
*/
|
||||
|
||||
static const char strings[] ="""
|
||||
|
||||
offsets = []
|
||||
i = 0;
|
||||
for type, name, args, num, h in entrypoints:
|
||||
print " \"vk%s\\0\"" % name
|
||||
offsets.append(i)
|
||||
i += 2 + len(name) + 1
|
||||
print """ ;
|
||||
|
||||
/* Weak aliases for all potential validate functions. These will resolve to
|
||||
* NULL if they're not defined, which lets the resolve_entrypoint() function
|
||||
* either pick a validate wrapper if available or just plug in the actual
|
||||
* entry point.
|
||||
*/
|
||||
"""
|
||||
|
||||
for type, name, args, num, h in entrypoints:
|
||||
print "%s anv_validate_%s%s __attribute__ ((weak));" % (type, name, args)
|
||||
|
||||
# Now generate the table of all entry points and their validation functions
|
||||
|
||||
print "\nstatic const struct anv_entrypoint entrypoints[] = {"
|
||||
for type, name, args, num, h in entrypoints:
|
||||
print " { %5d, 0x%08x, anv_%s, anv_validate_%s }," % (offsets[num], h, name, name)
|
||||
print "};\n"
|
||||
|
||||
print """
|
||||
#ifdef DEBUG
|
||||
static bool enable_validate = true;
|
||||
#else
|
||||
static bool enable_validate = false;
|
||||
#endif
|
||||
|
||||
/* We can't use symbols that need resolving (like, oh, getenv) in the resolve
|
||||
* function. This means that we have to determine whether or not to use the
|
||||
* validation layer sometime before that. The constructor function attribute asks
|
||||
* the dynamic linker to invoke determine_validate() at dlopen() time which
|
||||
* works.
|
||||
*/
|
||||
static void __attribute__ ((constructor))
|
||||
determine_validate(void)
|
||||
{
|
||||
const char *s = getenv("ANV_VALIDATE");
|
||||
|
||||
if (s)
|
||||
enable_validate = atoi(s);
|
||||
}
|
||||
|
||||
static void * __attribute__ ((noinline))
|
||||
resolve_entrypoint(uint32_t index)
|
||||
{
|
||||
if (enable_validate && entrypoints[index].validate)
|
||||
return entrypoints[index].validate;
|
||||
|
||||
return entrypoints[index].function;
|
||||
}
|
||||
"""
|
||||
|
||||
# Now output ifuncs and their resolve helpers for all entry points. The
|
||||
# resolve helper calls resolve_entrypoint() with the entry point index, which
|
||||
# lets the resolver look it up in the table.
|
||||
|
||||
for type, name, args, num, h in entrypoints:
|
||||
print "static void *resolve_%s(void) { return resolve_entrypoint(%d); }" % (name, num)
|
||||
print "%s vk%s%s\n __attribute__ ((ifunc (\"resolve_%s\"), visibility (\"default\")));\n" % (type, name, args, name)
|
||||
|
||||
|
||||
# Now generate the hash table used for entry point look up. This is a
|
||||
# uint16_t table of entry point indices. We use 0xffff to indicate an entry
|
||||
# in the hash table is empty.
|
||||
|
||||
map = [none for f in xrange(hash_size)]
|
||||
collisions = [0 for f in xrange(10)]
|
||||
for type, name, args, num, h in entrypoints:
|
||||
level = 0
|
||||
while map[h & hash_mask] != none:
|
||||
h = h + prime_step
|
||||
level = level + 1
|
||||
if level > 9:
|
||||
collisions[9] += 1
|
||||
else:
|
||||
collisions[level] += 1
|
||||
map[h & hash_mask] = num
|
||||
|
||||
print "/* Hash table stats:"
|
||||
print " * size %d entries" % hash_size
|
||||
print " * collisions entries"
|
||||
for i in xrange(10):
|
||||
if (i == 9):
|
||||
plus = "+"
|
||||
else:
|
||||
plus = " "
|
||||
|
||||
print " * %2d%s %4d" % (i, plus, collisions[i])
|
||||
print " */\n"
|
||||
|
||||
print "#define none 0x%04x\n" % none
|
||||
|
||||
print "static const uint16_t map[] = {"
|
||||
for i in xrange(0, hash_size, 8):
|
||||
print " ",
|
||||
for j in xrange(i, i + 8):
|
||||
if map[j] & 0xffff == 0xffff:
|
||||
print " none,",
|
||||
else:
|
||||
print "0x%04x," % (map[j] & 0xffff),
|
||||
print
|
||||
|
||||
print "};"
|
||||
|
||||
# Finally we generate the hash table lookup function. The hash function and
|
||||
# linear probing algorithm matches the hash table generated above.
|
||||
|
||||
print """
|
||||
void *
|
||||
anv_lookup_entrypoint(const char *name)
|
||||
{
|
||||
static const uint32_t prime_factor = %d;
|
||||
static const uint32_t prime_step = %d;
|
||||
const struct anv_entrypoint *e;
|
||||
uint32_t hash, h, i;
|
||||
const char *p;
|
||||
|
||||
hash = 0;
|
||||
for (p = name; *p; p++)
|
||||
hash = hash * prime_factor + *p;
|
||||
|
||||
h = hash;
|
||||
do {
|
||||
i = map[h & %d];
|
||||
if (i == none)
|
||||
return NULL;
|
||||
e = &entrypoints[i];
|
||||
h += prime_step;
|
||||
} while (e->hash != hash);
|
||||
|
||||
if (strcmp(name, strings + e->name) != 0)
|
||||
return NULL;
|
||||
|
||||
return resolve_entrypoint(i);
|
||||
}
|
||||
""" % (prime_factor, prime_step, hash_mask)
|
299
src/vulkan/x11.c
Normal file
299
src/vulkan/x11.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri3.h>
|
||||
#include <xcb/present.h>
|
||||
|
||||
static const VkFormat formats[] = {
|
||||
VK_FORMAT_B5G6R5_UNORM,
|
||||
VK_FORMAT_B8G8R8A8_UNORM,
|
||||
VK_FORMAT_B8G8R8A8_SRGB,
|
||||
};
|
||||
|
||||
VkResult anv_GetDisplayInfoWSI(
|
||||
VkDisplayWSI display,
|
||||
VkDisplayInfoTypeWSI infoType,
|
||||
size_t* pDataSize,
|
||||
void* pData)
|
||||
{
|
||||
VkDisplayFormatPropertiesWSI *properties = pData;
|
||||
size_t size;
|
||||
|
||||
if (pDataSize == NULL)
|
||||
return VK_ERROR_INVALID_POINTER;
|
||||
|
||||
switch (infoType) {
|
||||
case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
|
||||
size = sizeof(properties[0]) * ARRAY_SIZE(formats);
|
||||
|
||||
if (pData == NULL) {
|
||||
*pDataSize = size;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
if (*pDataSize < size)
|
||||
return vk_error(VK_ERROR_INVALID_VALUE);
|
||||
|
||||
*pDataSize = size;
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
|
||||
properties[i].swapChainFormat = formats[i];
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
default:
|
||||
return VK_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
struct anv_swap_chain {
|
||||
struct anv_device * device;
|
||||
xcb_connection_t * conn;
|
||||
xcb_window_t window;
|
||||
xcb_gc_t gc;
|
||||
VkExtent2D extent;
|
||||
uint32_t count;
|
||||
struct {
|
||||
struct anv_image * image;
|
||||
struct anv_device_memory * memory;
|
||||
xcb_pixmap_t pixmap;
|
||||
} images[0];
|
||||
};
|
||||
|
||||
VkResult anv_CreateSwapChainWSI(
|
||||
VkDevice _device,
|
||||
const VkSwapChainCreateInfoWSI* pCreateInfo,
|
||||
VkSwapChainWSI* pSwapChain)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
|
||||
struct anv_swap_chain *chain;
|
||||
xcb_void_cookie_t cookie;
|
||||
VkResult result;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
|
||||
|
||||
size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
|
||||
chain = anv_device_alloc(device, size, 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (chain == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
chain->device = device;
|
||||
chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
|
||||
chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
|
||||
chain->count = pCreateInfo->imageCount;
|
||||
chain->extent = pCreateInfo->imageExtent;
|
||||
|
||||
for (uint32_t i = 0; i < chain->count; i++) {
|
||||
VkDeviceMemory memory_h;
|
||||
VkImage image_h;
|
||||
struct anv_image *image;
|
||||
struct anv_surface *surface;
|
||||
struct anv_device_memory *memory;
|
||||
|
||||
anv_image_create(_device,
|
||||
&(struct anv_image_create_info) {
|
||||
.force_tile_mode = true,
|
||||
.tile_mode = XMAJOR,
|
||||
.vk_info =
|
||||
&(VkImageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = pCreateInfo->imageFormat,
|
||||
.extent = {
|
||||
.width = pCreateInfo->imageExtent.width,
|
||||
.height = pCreateInfo->imageExtent.height,
|
||||
.depth = 1
|
||||
},
|
||||
.mipLevels = 1,
|
||||
.arraySize = 1,
|
||||
.samples = 1,
|
||||
/* FIXME: Need a way to use X tiling to allow scanout */
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.flags = 0,
|
||||
}},
|
||||
&image_h);
|
||||
|
||||
image = anv_image_from_handle(image_h);
|
||||
surface = &image->primary_surface;
|
||||
|
||||
anv_AllocMemory(_device,
|
||||
&(VkMemoryAllocInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
|
||||
.allocationSize = image->size,
|
||||
.memoryTypeIndex = 0,
|
||||
},
|
||||
&memory_h);
|
||||
|
||||
memory = anv_device_memory_from_handle(memory_h);
|
||||
|
||||
anv_BindImageMemory(VK_NULL_HANDLE, anv_image_to_handle(image),
|
||||
memory_h, 0);
|
||||
|
||||
ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
|
||||
surface->stride, I915_TILING_X);
|
||||
if (ret) {
|
||||
result = vk_error(VK_ERROR_UNKNOWN);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
|
||||
if (fd == -1) {
|
||||
result = vk_error(VK_ERROR_UNKNOWN);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint32_t bpp = 32;
|
||||
uint32_t depth = 24;
|
||||
xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
|
||||
|
||||
cookie =
|
||||
xcb_dri3_pixmap_from_buffer_checked(chain->conn,
|
||||
pixmap,
|
||||
chain->window,
|
||||
image->size,
|
||||
pCreateInfo->imageExtent.width,
|
||||
pCreateInfo->imageExtent.height,
|
||||
surface->stride,
|
||||
depth, bpp, fd);
|
||||
|
||||
chain->images[i].image = image;
|
||||
chain->images[i].memory = memory;
|
||||
chain->images[i].pixmap = pixmap;
|
||||
image->swap_chain = chain;
|
||||
|
||||
xcb_discard_reply(chain->conn, cookie.sequence);
|
||||
}
|
||||
|
||||
chain->gc = xcb_generate_id(chain->conn);
|
||||
if (!chain->gc) {
|
||||
result = vk_error(VK_ERROR_UNKNOWN);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cookie = xcb_create_gc(chain->conn,
|
||||
chain->gc,
|
||||
chain->window,
|
||||
XCB_GC_GRAPHICS_EXPOSURES,
|
||||
(uint32_t []) { 0 });
|
||||
xcb_discard_reply(chain->conn, cookie.sequence);
|
||||
|
||||
*pSwapChain = (VkSwapChainWSI) chain;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult anv_DestroySwapChainWSI(
|
||||
VkSwapChainWSI swapChain)
|
||||
{
|
||||
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
|
||||
struct anv_device *device = chain->device;
|
||||
|
||||
anv_device_free(device, chain);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult anv_GetSwapChainInfoWSI(
|
||||
VkSwapChainWSI swapChain,
|
||||
VkSwapChainInfoTypeWSI infoType,
|
||||
size_t* pDataSize,
|
||||
void* pData)
|
||||
{
|
||||
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
|
||||
VkSwapChainImageInfoWSI *images;
|
||||
size_t size;
|
||||
|
||||
switch (infoType) {
|
||||
case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
|
||||
size = sizeof(*images) * chain->count;
|
||||
if (pData && *pDataSize < size)
|
||||
return VK_ERROR_INVALID_VALUE;
|
||||
|
||||
*pDataSize = size;
|
||||
if (!pData)
|
||||
return VK_SUCCESS;
|
||||
|
||||
images = pData;
|
||||
for (uint32_t i = 0; i < chain->count; i++) {
|
||||
images[i].image = anv_image_to_handle(chain->images[i].image);
|
||||
images[i].memory = anv_device_memory_to_handle(chain->images[i].memory);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
default:
|
||||
return VK_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult anv_QueuePresentWSI(
|
||||
VkQueue queue_,
|
||||
const VkPresentInfoWSI* pPresentInfo)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_image, image, pPresentInfo->image);
|
||||
|
||||
struct anv_swap_chain *chain = image->swap_chain;
|
||||
xcb_void_cookie_t cookie;
|
||||
xcb_pixmap_t pixmap;
|
||||
|
||||
assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
|
||||
|
||||
if (chain == NULL)
|
||||
return vk_error(VK_ERROR_INVALID_VALUE);
|
||||
|
||||
pixmap = XCB_NONE;
|
||||
for (uint32_t i = 0; i < chain->count; i++) {
|
||||
if (image == chain->images[i].image) {
|
||||
pixmap = chain->images[i].pixmap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pixmap == XCB_NONE)
|
||||
return vk_error(VK_ERROR_INVALID_VALUE);
|
||||
|
||||
cookie = xcb_copy_area(chain->conn,
|
||||
pixmap,
|
||||
chain->window,
|
||||
chain->gc,
|
||||
0, 0,
|
||||
0, 0,
|
||||
chain->extent.width,
|
||||
chain->extent.height);
|
||||
xcb_discard_reply(chain->conn, cookie.sequence);
|
||||
|
||||
xcb_flush(chain->conn);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user