Compare commits
519 Commits
11.2
...
vulkan-hea
Author | SHA1 | Date | |
---|---|---|---|
|
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 bool32_t;
|
||||
|
||||
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__
|
216
include/vulkan/vk_wsi_lunarg.h
Normal file
216
include/vulkan/vk_wsi_lunarg.h
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// 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_DISP_SUBCLASS_HANDLE(VkDisplayWSI, VkObject)
|
||||
VK_DEFINE_DISP_SUBCLASS_HANDLE(VkSwapChainWSI, VkObject)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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)
|
||||
|
||||
// Extend VkObjectType enum for new objects
|
||||
#define VK_OBJECT_TYPE_DISPLAY_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 0)
|
||||
#define VK_OBJECT_TYPE_SWAP_CHAIN_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 1)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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_
|
||||
{
|
||||
bool32_t 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__
|
2753
include/vulkan/vulkan-130.h
Normal file
2753
include/vulkan/vulkan-130.h
Normal file
File diff suppressed because it is too large
Load Diff
2894
include/vulkan/vulkan-90.h
Normal file
2894
include/vulkan/vulkan-90.h
Normal file
File diff suppressed because it is too large
Load Diff
2753
include/vulkan/vulkan.h
Normal file
2753
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
|
||||
}
|
||||
|
1304
src/glsl/nir/spirv.h
Normal file
1304
src/glsl/nir/spirv.h
Normal file
File diff suppressed because it is too large
Load Diff
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;
|
||||
}
|
2819
src/glsl/nir/spirv_to_nir.c
Normal file
2819
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
|
93
src/vulkan/Makefile.am
Normal file
93
src/vulkan/Makefile.am
Normal file
@@ -0,0 +1,93 @@
|
||||
# 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 \
|
||||
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);
|
||||
}
|
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->bo_count * sizeof(aub_bos[0]));
|
||||
offset = writer->offset;
|
||||
for (uint32_t i = 0; i < cmd_buffer->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->bo_count; i++) {
|
||||
bo = cmd_buffer->exec2_bos[i];
|
||||
if (i == cmd_buffer->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
3943
src/vulkan/device.c
Normal file
3943
src/vulkan/device.c
Normal file
File diff suppressed because it is too large
Load Diff
296
src/vulkan/formats.c
Normal file
296
src/vulkan/formats.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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];
|
||||
}
|
||||
|
||||
// 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_GetPhysicalDeviceFormatInfo(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat _format,
|
||||
VkFormatProperties* pFormatInfo)
|
||||
{
|
||||
const struct anv_format *format = anv_format_for_vk_format(_format);
|
||||
fprintf(stderr, "vkGetFormatInfo(%s)\n", format->name);
|
||||
return anv_GetPhysicalDeviceFormatInfo(physicalDevice, _format, pFormatInfo);
|
||||
}
|
||||
|
||||
VkResult anv_GetPhysicalDeviceFormatInfo(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat _format,
|
||||
VkFormatProperties* pFormatInfo)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
pFormatInfo->linearTilingFeatures = linear;
|
||||
pFormatInfo->optimalTilingFeatures = tiled;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
unsupported:
|
||||
pFormatInfo->linearTilingFeatures = 0;
|
||||
pFormatInfo->optimalTilingFeatures = 0;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
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((VkDevice) device, \\
|
||||
&__shader_create_info, &__module); \\
|
||||
__module; \\
|
||||
})
|
||||
"""))
|
||||
|
||||
for shader in parser.shaders:
|
||||
shader.dump_c_code(outfile, glsl_only)
|
744
src/vulkan/image.c
Normal file
744
src/vulkan/image.c
Normal file
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
* 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_destroy(struct anv_device *device,
|
||||
struct anv_surface_view *view)
|
||||
{
|
||||
anv_state_pool_free(&device->surface_state_pool, view->surface_state);
|
||||
|
||||
anv_device_free(device, view);
|
||||
}
|
||||
|
||||
void
|
||||
anv_image_view_init(struct anv_surface_view *view,
|
||||
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 *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_surface_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 = (VkImageView) view;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_DestroyImageView(VkDevice _device, VkImageView _view)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
|
||||
anv_surface_view_destroy(device, (struct anv_surface_view *)_view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
anv_color_attachment_view_init(struct anv_surface_view *view,
|
||||
struct anv_device *device,
|
||||
const VkColorAttachmentViewCreateInfo* pCreateInfo,
|
||||
struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
||||
struct anv_surface *surface = &image->primary_surface;
|
||||
const struct anv_format *format_info =
|
||||
anv_format_for_vk_format(pCreateInfo->format);
|
||||
|
||||
anv_assert(pCreateInfo->arraySize > 0);
|
||||
anv_assert(pCreateInfo->mipLevel < image->levels);
|
||||
anv_assert(pCreateInfo->baseArraySlice + pCreateInfo->arraySize <= image->array_size);
|
||||
|
||||
if (pCreateInfo->msaaResolveImage)
|
||||
anv_finishme("msaaResolveImage");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_CreateColorAttachmentView(VkDevice _device,
|
||||
const VkColorAttachmentViewCreateInfo *pCreateInfo,
|
||||
VkColorAttachmentView *pView)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
struct anv_surface_view *view;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO);
|
||||
|
||||
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 = (VkColorAttachmentView) view;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_DestroyColorAttachmentView(VkDevice _device, VkColorAttachmentView _view)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
|
||||
anv_surface_view_destroy(device, (struct anv_surface_view *)_view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_CreateDepthStencilView(VkDevice _device,
|
||||
const VkDepthStencilViewCreateInfo *pCreateInfo,
|
||||
VkDepthStencilView *pView)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
||||
struct anv_depth_stencil_view *view;
|
||||
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);
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEPTH_STENCIL_VIEW_CREATE_INFO);
|
||||
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
|
||||
*pView = anv_depth_stencil_view_to_handle(view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
anv_DestroyDepthStencilView(VkDevice _device, VkDepthStencilView _view)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
ANV_FROM_HANDLE(anv_depth_stencil_view, view, _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 = (VkDeviceMemory) mem;
|
||||
*pImage = (VkImage) image;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail_mem:
|
||||
anv_gem_close(device, mem->bo.gem_handle);
|
||||
fail:
|
||||
anv_device_free(device, mem);
|
||||
|
||||
return result;
|
||||
}
|
1387
src/vulkan/meta.c
Normal file
1387
src/vulkan/meta.c
Normal file
File diff suppressed because it is too large
Load Diff
911
src/vulkan/pipeline.c
Normal file
911
src/vulkan/pipeline.c
Normal file
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* 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,
|
||||
VkShader* 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_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_CreatePipelineCache(
|
||||
VkDevice device,
|
||||
const VkPipelineCacheCreateInfo* pCreateInfo,
|
||||
VkPipelineCache* pPipelineCache)
|
||||
{
|
||||
*pPipelineCache = 1;
|
||||
|
||||
stub_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 VkPipelineIaStateCreateInfo *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 VkPipelineRsStateCreateInfo *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: bool32_t 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 VkPipelineCbStateCreateInfo *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 VkPipelineCbAttachmentState *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 VkPipelineDsStateCreateInfo *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;
|
||||
}
|
||||
|
||||
/* bool32_t 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);
|
||||
}
|
||||
|
||||
static void
|
||||
anv_pipeline_destroy(struct anv_device *device,
|
||||
struct anv_object *object,
|
||||
VkObjectType obj_type)
|
||||
{
|
||||
struct anv_pipeline *pipeline = (struct anv_pipeline*) object;
|
||||
|
||||
assert(obj_type == VK_OBJECT_TYPE_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);
|
||||
}
|
||||
|
||||
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->base.destructor = anv_pipeline_destroy;
|
||||
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->pTessState)
|
||||
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO");
|
||||
if (pCreateInfo->pVpState)
|
||||
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO");
|
||||
if (pCreateInfo->pMsState)
|
||||
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MS_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->pIaState);
|
||||
emit_ia_state(pipeline, pCreateInfo->pIaState, extra);
|
||||
assert(pCreateInfo->pRsState);
|
||||
emit_rs_state(pipeline, pCreateInfo->pRsState, extra);
|
||||
emit_ds_state(pipeline, pCreateInfo->pDsState);
|
||||
emit_cb_state(pipeline, pCreateInfo->pCbState);
|
||||
|
||||
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_CreateGraphicsPipelines(
|
||||
VkDevice _device,
|
||||
VkPipelineCache pipelineCache,
|
||||
uint32_t count,
|
||||
const VkGraphicsPipelineCreateInfo* pCreateInfos,
|
||||
VkPipeline* pPipelines)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
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_pipeline_destroy(device, (struct anv_object *)pPipelines[j],
|
||||
VK_OBJECT_TYPE_PIPELINE);
|
||||
}
|
||||
|
||||
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->base.destructor = anv_pipeline_destroy;
|
||||
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)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||
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_pipeline_destroy(device, (struct anv_object *)pPipelines[j],
|
||||
VK_OBJECT_TYPE_PIPELINE);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
998
src/vulkan/private.h
Normal file
998
src/vulkan/private.h
Normal file
@@ -0,0 +1,998 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include <i915_drm.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
#include <valgrind.h>
|
||||
#include <memcheck.h>
|
||||
#define VG(x) x
|
||||
#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
|
||||
#else
|
||||
#define VG(x)
|
||||
#endif
|
||||
|
||||
#include "brw_device_info.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#define VK_PROTOTYPES
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_intel.h>
|
||||
#include <vulkan/vk_wsi_lunarg.h>
|
||||
|
||||
#include "entrypoints.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define anv_noreturn __attribute__((__noreturn__))
|
||||
#define anv_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
static inline uint32_t
|
||||
align_u32(uint32_t v, uint32_t a)
|
||||
{
|
||||
return (v + a - 1) & ~(a - 1);
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
align_i32(int32_t v, int32_t a)
|
||||
{
|
||||
return (v + a - 1) & ~(a - 1);
|
||||
}
|
||||
|
||||
/** Alignment must be a power of 2. */
|
||||
static inline bool
|
||||
anv_is_aligned(uintmax_t n, uintmax_t a)
|
||||
{
|
||||
assert(a == (a & -a));
|
||||
return (n & (a - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
anv_minify(uint32_t n, uint32_t levels)
|
||||
{
|
||||
if (unlikely(n == 0))
|
||||
return 0;
|
||||
else
|
||||
return MAX(n >> levels, 1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
anv_clear_mask(uint32_t *inout_mask, uint32_t clear_mask)
|
||||
{
|
||||
if (*inout_mask & clear_mask) {
|
||||
*inout_mask &= ~clear_mask;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define for_each_bit(b, dword) \
|
||||
for (uint32_t __dword = (dword); \
|
||||
(b) = __builtin_ffs(__dword) - 1, __dword; \
|
||||
__dword &= ~(1 << (b)))
|
||||
|
||||
/* Define no kernel as 1, since that's an illegal offset for a kernel */
|
||||
#define NO_KERNEL 1
|
||||
|
||||
struct anv_common {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
};
|
||||
|
||||
/* Whenever we generate an error, pass it through this function. Useful for
|
||||
* debugging, where we can break on it. Only call at error site, not when
|
||||
* propagating errors. Might be useful to plug in a stack trace here.
|
||||
*/
|
||||
|
||||
static inline VkResult
|
||||
vk_error(VkResult error)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "vk_error: %x\n", error);
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void __anv_finishme(const char *file, int line, const char *format, ...)
|
||||
anv_printflike(3, 4);
|
||||
void anv_loge(const char *format, ...) anv_printflike(1, 2);
|
||||
void anv_loge_v(const char *format, va_list va);
|
||||
|
||||
/**
|
||||
* Print a FINISHME message, including its source location.
|
||||
*/
|
||||
#define anv_finishme(format, ...) \
|
||||
__anv_finishme(__FILE__, __LINE__, format, ##__VA_ARGS__);
|
||||
|
||||
/* A non-fatal assert. Useful for debugging. */
|
||||
#ifdef DEBUG
|
||||
#define anv_assert(x) ({ \
|
||||
if (unlikely(!(x))) \
|
||||
fprintf(stderr, "%s:%d ASSERT: %s\n", __FILE__, __LINE__, #x); \
|
||||
})
|
||||
#else
|
||||
#define anv_assert(x)
|
||||
#endif
|
||||
|
||||
void anv_abortf(const char *format, ...) anv_noreturn anv_printflike(1, 2);
|
||||
void anv_abortfv(const char *format, va_list va) anv_noreturn;
|
||||
|
||||
#define stub_return(v) \
|
||||
do { \
|
||||
anv_finishme("stub %s", __func__); \
|
||||
return (v); \
|
||||
} while (0)
|
||||
|
||||
#define stub() \
|
||||
do { \
|
||||
anv_finishme("stub %s", __func__); \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* A dynamically growable, circular buffer. Elements are added at head and
|
||||
* removed from tail. head and tail are free-running uint32_t indices and we
|
||||
* only compute the modulo with size when accessing the array. This way,
|
||||
* number of bytes in the queue is always head - tail, even in case of
|
||||
* wraparound.
|
||||
*/
|
||||
|
||||
struct anv_vector {
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
uint32_t element_size;
|
||||
uint32_t size;
|
||||
void *data;
|
||||
};
|
||||
|
||||
int anv_vector_init(struct anv_vector *queue, uint32_t element_size, uint32_t size);
|
||||
void *anv_vector_add(struct anv_vector *queue);
|
||||
void *anv_vector_remove(struct anv_vector *queue);
|
||||
|
||||
static inline int
|
||||
anv_vector_length(struct anv_vector *queue)
|
||||
{
|
||||
return (queue->head - queue->tail) / queue->element_size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
anv_vector_finish(struct anv_vector *queue)
|
||||
{
|
||||
free(queue->data);
|
||||
}
|
||||
|
||||
#define anv_vector_foreach(elem, queue) \
|
||||
static_assert(__builtin_types_compatible_p(__typeof__(queue), struct anv_vector *), ""); \
|
||||
for (uint32_t __anv_vector_offset = (queue)->tail; \
|
||||
elem = (queue)->data + (__anv_vector_offset & ((queue)->size - 1)), __anv_vector_offset < (queue)->head; \
|
||||
__anv_vector_offset += (queue)->element_size)
|
||||
|
||||
struct anv_bo {
|
||||
int gem_handle;
|
||||
uint32_t index;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
|
||||
/* This field is here for the benefit of the aub dumper. It can (and for
|
||||
* userptr bos it must) be set to the cpu map of the buffer. Destroying
|
||||
* the bo won't clean up the mmap, it's still the responsibility of the bo
|
||||
* user to do that. */
|
||||
void *map;
|
||||
};
|
||||
|
||||
/* Represents a lock-free linked list of "free" things. This is used by
|
||||
* both the block pool and the state pools. Unfortunately, in order to
|
||||
* solve the ABA problem, we can't use a single uint32_t head.
|
||||
*/
|
||||
union anv_free_list {
|
||||
struct {
|
||||
uint32_t offset;
|
||||
|
||||
/* A simple count that is incremented every time the head changes. */
|
||||
uint32_t count;
|
||||
};
|
||||
uint64_t u64;
|
||||
};
|
||||
|
||||
#define ANV_FREE_LIST_EMPTY ((union anv_free_list) { { 1, 0 } })
|
||||
|
||||
struct anv_block_pool {
|
||||
struct anv_device *device;
|
||||
|
||||
struct anv_bo bo;
|
||||
void *map;
|
||||
int fd;
|
||||
uint32_t size;
|
||||
|
||||
/**
|
||||
* Array of mmaps and gem handles owned by the block pool, reclaimed when
|
||||
* the block pool is destroyed.
|
||||
*/
|
||||
struct anv_vector mmap_cleanups;
|
||||
|
||||
uint32_t block_size;
|
||||
|
||||
uint32_t next_block;
|
||||
union anv_free_list free_list;
|
||||
};
|
||||
|
||||
struct anv_block_state {
|
||||
union {
|
||||
struct {
|
||||
uint32_t next;
|
||||
uint32_t end;
|
||||
};
|
||||
uint64_t u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct anv_state {
|
||||
uint32_t offset;
|
||||
uint32_t alloc_size;
|
||||
void *map;
|
||||
};
|
||||
|
||||
struct anv_fixed_size_state_pool {
|
||||
size_t state_size;
|
||||
union anv_free_list free_list;
|
||||
struct anv_block_state block;
|
||||
};
|
||||
|
||||
#define ANV_MIN_STATE_SIZE_LOG2 6
|
||||
#define ANV_MAX_STATE_SIZE_LOG2 10
|
||||
|
||||
#define ANV_STATE_BUCKETS (ANV_MAX_STATE_SIZE_LOG2 - ANV_MIN_STATE_SIZE_LOG2)
|
||||
|
||||
struct anv_state_pool {
|
||||
struct anv_block_pool *block_pool;
|
||||
struct anv_fixed_size_state_pool buckets[ANV_STATE_BUCKETS];
|
||||
};
|
||||
|
||||
struct anv_state_stream {
|
||||
struct anv_block_pool *block_pool;
|
||||
uint32_t next;
|
||||
uint32_t current_block;
|
||||
uint32_t end;
|
||||
};
|
||||
|
||||
void anv_block_pool_init(struct anv_block_pool *pool,
|
||||
struct anv_device *device, uint32_t block_size);
|
||||
void anv_block_pool_finish(struct anv_block_pool *pool);
|
||||
uint32_t anv_block_pool_alloc(struct anv_block_pool *pool);
|
||||
void anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset);
|
||||
void anv_state_pool_init(struct anv_state_pool *pool,
|
||||
struct anv_block_pool *block_pool);
|
||||
struct anv_state anv_state_pool_alloc(struct anv_state_pool *pool,
|
||||
size_t state_size, size_t alignment);
|
||||
void anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state);
|
||||
void anv_state_stream_init(struct anv_state_stream *stream,
|
||||
struct anv_block_pool *block_pool);
|
||||
void anv_state_stream_finish(struct anv_state_stream *stream);
|
||||
struct anv_state anv_state_stream_alloc(struct anv_state_stream *stream,
|
||||
uint32_t size, uint32_t alignment);
|
||||
|
||||
/**
|
||||
* Implements a pool of re-usable BOs. The interface is identical to that
|
||||
* of block_pool except that each block is its own BO.
|
||||
*/
|
||||
struct anv_bo_pool {
|
||||
struct anv_device *device;
|
||||
|
||||
uint32_t bo_size;
|
||||
|
||||
void *free_list;
|
||||
};
|
||||
|
||||
void anv_bo_pool_init(struct anv_bo_pool *pool,
|
||||
struct anv_device *device, uint32_t block_size);
|
||||
void anv_bo_pool_finish(struct anv_bo_pool *pool);
|
||||
VkResult anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo);
|
||||
void anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo);
|
||||
|
||||
struct anv_object;
|
||||
struct anv_device;
|
||||
|
||||
typedef void (*anv_object_destructor_cb)(struct anv_device *,
|
||||
struct anv_object *,
|
||||
VkObjectType);
|
||||
|
||||
struct anv_object {
|
||||
anv_object_destructor_cb destructor;
|
||||
};
|
||||
|
||||
struct anv_physical_device {
|
||||
struct anv_instance * instance;
|
||||
uint32_t chipset_id;
|
||||
bool no_hw;
|
||||
const char * path;
|
||||
const char * name;
|
||||
const struct brw_device_info * info;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct anv_instance {
|
||||
void * pAllocUserData;
|
||||
PFN_vkAllocFunction pfnAlloc;
|
||||
PFN_vkFreeFunction pfnFree;
|
||||
uint32_t apiVersion;
|
||||
uint32_t physicalDeviceCount;
|
||||
struct anv_physical_device physicalDevice;
|
||||
};
|
||||
|
||||
struct anv_meta_state {
|
||||
struct {
|
||||
VkPipeline pipeline;
|
||||
} clear;
|
||||
|
||||
struct {
|
||||
VkPipeline pipeline;
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkDescriptorSetLayout ds_layout;
|
||||
} blit;
|
||||
|
||||
struct {
|
||||
VkDynamicRsState rs_state;
|
||||
VkDynamicCbState cb_state;
|
||||
VkDynamicDsState ds_state;
|
||||
} shared;
|
||||
};
|
||||
|
||||
struct anv_queue {
|
||||
struct anv_device * device;
|
||||
|
||||
struct anv_state_pool * pool;
|
||||
|
||||
/**
|
||||
* Serial number of the most recently completed batch executed on the
|
||||
* engine.
|
||||
*/
|
||||
struct anv_state completed_serial;
|
||||
|
||||
/**
|
||||
* The next batch submitted to the engine will be assigned this serial
|
||||
* number.
|
||||
*/
|
||||
uint32_t next_serial;
|
||||
|
||||
uint32_t last_collected_serial;
|
||||
};
|
||||
|
||||
struct anv_device {
|
||||
struct anv_instance * instance;
|
||||
uint32_t chipset_id;
|
||||
struct brw_device_info info;
|
||||
int context_id;
|
||||
int fd;
|
||||
bool no_hw;
|
||||
bool dump_aub;
|
||||
|
||||
struct anv_bo_pool batch_bo_pool;
|
||||
|
||||
struct anv_block_pool dynamic_state_block_pool;
|
||||
struct anv_state_pool dynamic_state_pool;
|
||||
|
||||
struct anv_block_pool instruction_block_pool;
|
||||
struct anv_block_pool surface_state_block_pool;
|
||||
struct anv_state_pool surface_state_pool;
|
||||
|
||||
struct anv_meta_state meta_state;
|
||||
|
||||
struct anv_state border_colors;
|
||||
|
||||
struct anv_queue queue;
|
||||
|
||||
struct anv_block_pool scratch_block_pool;
|
||||
|
||||
struct anv_compiler * compiler;
|
||||
struct anv_aub_writer * aub_writer;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
void *
|
||||
anv_device_alloc(struct anv_device * device,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
VkSystemAllocType allocType);
|
||||
|
||||
void
|
||||
anv_device_free(struct anv_device * device,
|
||||
void * mem);
|
||||
|
||||
void* anv_gem_mmap(struct anv_device *device,
|
||||
uint32_t gem_handle, uint64_t offset, uint64_t size);
|
||||
void anv_gem_munmap(void *p, uint64_t size);
|
||||
uint32_t anv_gem_create(struct anv_device *device, size_t size);
|
||||
void anv_gem_close(struct anv_device *device, int gem_handle);
|
||||
int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
|
||||
int anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns);
|
||||
int anv_gem_execbuffer(struct anv_device *device,
|
||||
struct drm_i915_gem_execbuffer2 *execbuf);
|
||||
int anv_gem_set_tiling(struct anv_device *device, int gem_handle,
|
||||
uint32_t stride, uint32_t tiling);
|
||||
int anv_gem_create_context(struct anv_device *device);
|
||||
int anv_gem_destroy_context(struct anv_device *device, int context);
|
||||
int anv_gem_get_param(int fd, uint32_t param);
|
||||
int anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size);
|
||||
int anv_gem_handle_to_fd(struct anv_device *device, int gem_handle);
|
||||
int anv_gem_fd_to_handle(struct anv_device *device, int fd);
|
||||
int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
|
||||
|
||||
VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size);
|
||||
|
||||
struct anv_reloc_list {
|
||||
size_t num_relocs;
|
||||
size_t array_length;
|
||||
struct drm_i915_gem_relocation_entry * relocs;
|
||||
struct anv_bo ** reloc_bos;
|
||||
};
|
||||
|
||||
VkResult anv_reloc_list_init(struct anv_reloc_list *list,
|
||||
struct anv_device *device);
|
||||
void anv_reloc_list_finish(struct anv_reloc_list *list,
|
||||
struct anv_device *device);
|
||||
|
||||
struct anv_batch_bo {
|
||||
struct anv_bo bo;
|
||||
|
||||
/* Bytes actually consumed in this batch BO */
|
||||
size_t length;
|
||||
|
||||
/* These offsets reference the per-batch reloc list */
|
||||
size_t first_reloc;
|
||||
size_t num_relocs;
|
||||
|
||||
struct anv_batch_bo * prev_batch_bo;
|
||||
};
|
||||
|
||||
struct anv_batch {
|
||||
struct anv_device * device;
|
||||
|
||||
void * start;
|
||||
void * end;
|
||||
void * next;
|
||||
|
||||
struct anv_reloc_list relocs;
|
||||
|
||||
/* This callback is called (with the associated user data) in the event
|
||||
* that the batch runs out of space.
|
||||
*/
|
||||
VkResult (*extend_cb)(struct anv_batch *, void *);
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
|
||||
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
|
||||
uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
|
||||
void *location, struct anv_bo *bo, uint32_t offset);
|
||||
|
||||
struct anv_address {
|
||||
struct anv_bo *bo;
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
#define __gen_address_type struct anv_address
|
||||
#define __gen_user_data struct anv_batch
|
||||
|
||||
static inline uint64_t
|
||||
__gen_combine_address(struct anv_batch *batch, void *location,
|
||||
const struct anv_address address, uint32_t delta)
|
||||
{
|
||||
if (address.bo == NULL) {
|
||||
return delta;
|
||||
} else {
|
||||
assert(batch->start <= location && location < batch->end);
|
||||
|
||||
return anv_batch_emit_reloc(batch, location, address.bo, address.offset + delta);
|
||||
}
|
||||
}
|
||||
|
||||
#include "gen7_pack.h"
|
||||
#include "gen75_pack.h"
|
||||
#undef GEN8_3DSTATE_MULTISAMPLE
|
||||
#include "gen8_pack.h"
|
||||
|
||||
#define anv_batch_emit(batch, cmd, ...) do { \
|
||||
struct cmd __template = { \
|
||||
cmd ## _header, \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
void *__dst = anv_batch_emit_dwords(batch, cmd ## _length); \
|
||||
cmd ## _pack(batch, __dst, &__template); \
|
||||
} while (0)
|
||||
|
||||
#define anv_batch_emitn(batch, n, cmd, ...) ({ \
|
||||
struct cmd __template = { \
|
||||
cmd ## _header, \
|
||||
.DwordLength = n - cmd ## _length_bias, \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
void *__dst = anv_batch_emit_dwords(batch, n); \
|
||||
cmd ## _pack(batch, __dst, &__template); \
|
||||
__dst; \
|
||||
})
|
||||
|
||||
#define anv_batch_emit_merge(batch, dwords0, dwords1) \
|
||||
do { \
|
||||
uint32_t *dw; \
|
||||
\
|
||||
assert(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \
|
||||
dw = anv_batch_emit_dwords((batch), ARRAY_SIZE(dwords0)); \
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++) \
|
||||
dw[i] = (dwords0)[i] | (dwords1)[i]; \
|
||||
VG(VALGRIND_CHECK_MEM_IS_DEFINED(dw, ARRAY_SIZE(dwords0) * 4));\
|
||||
} while (0)
|
||||
|
||||
#define GEN8_MOCS { \
|
||||
.MemoryTypeLLCeLLCCacheabilityControl = WB, \
|
||||
.TargetCache = L3DefertoPATforLLCeLLCselection, \
|
||||
.AgeforQUADLRU = 0 \
|
||||
}
|
||||
|
||||
struct anv_device_memory {
|
||||
struct anv_bo bo;
|
||||
VkDeviceSize map_size;
|
||||
void * map;
|
||||
};
|
||||
|
||||
struct anv_dynamic_vp_state {
|
||||
struct anv_object base;
|
||||
struct anv_state sf_clip_vp;
|
||||
struct anv_state cc_vp;
|
||||
struct anv_state scissor;
|
||||
};
|
||||
|
||||
struct anv_dynamic_rs_state {
|
||||
uint32_t state_sf[GEN8_3DSTATE_SF_length];
|
||||
uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
|
||||
};
|
||||
|
||||
struct anv_dynamic_ds_state {
|
||||
uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
|
||||
uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
|
||||
};
|
||||
|
||||
struct anv_dynamic_cb_state {
|
||||
uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
|
||||
|
||||
};
|
||||
|
||||
struct anv_descriptor_slot {
|
||||
int8_t dynamic_slot;
|
||||
uint8_t index;
|
||||
};
|
||||
|
||||
struct anv_descriptor_set_layout {
|
||||
struct {
|
||||
uint32_t surface_count;
|
||||
struct anv_descriptor_slot *surface_start;
|
||||
uint32_t sampler_count;
|
||||
struct anv_descriptor_slot *sampler_start;
|
||||
} stage[VK_SHADER_STAGE_NUM];
|
||||
|
||||
uint32_t count;
|
||||
uint32_t num_dynamic_buffers;
|
||||
uint32_t shader_stages;
|
||||
struct anv_descriptor_slot entries[0];
|
||||
};
|
||||
|
||||
struct anv_descriptor {
|
||||
struct anv_sampler *sampler;
|
||||
struct anv_surface_view *view;
|
||||
};
|
||||
|
||||
struct anv_descriptor_set {
|
||||
struct anv_descriptor descriptors[0];
|
||||
};
|
||||
|
||||
#define MAX_VBS 32
|
||||
#define MAX_SETS 8
|
||||
#define MAX_RTS 8
|
||||
|
||||
struct anv_pipeline_layout {
|
||||
struct {
|
||||
struct anv_descriptor_set_layout *layout;
|
||||
uint32_t surface_start[VK_SHADER_STAGE_NUM];
|
||||
uint32_t sampler_start[VK_SHADER_STAGE_NUM];
|
||||
} set[MAX_SETS];
|
||||
|
||||
uint32_t num_sets;
|
||||
|
||||
struct {
|
||||
uint32_t surface_count;
|
||||
uint32_t sampler_count;
|
||||
} stage[VK_SHADER_STAGE_NUM];
|
||||
};
|
||||
|
||||
struct anv_buffer {
|
||||
struct anv_device * device;
|
||||
VkDeviceSize size;
|
||||
|
||||
/* Set when bound */
|
||||
struct anv_bo * bo;
|
||||
VkDeviceSize offset;
|
||||
};
|
||||
|
||||
#define ANV_CMD_BUFFER_PIPELINE_DIRTY (1 << 0)
|
||||
#define ANV_CMD_BUFFER_RS_DIRTY (1 << 2)
|
||||
#define ANV_CMD_BUFFER_DS_DIRTY (1 << 3)
|
||||
#define ANV_CMD_BUFFER_CB_DIRTY (1 << 4)
|
||||
#define ANV_CMD_BUFFER_VP_DIRTY (1 << 5)
|
||||
#define ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY (1 << 6)
|
||||
|
||||
struct anv_vertex_binding {
|
||||
struct anv_buffer * buffer;
|
||||
VkDeviceSize offset;
|
||||
};
|
||||
|
||||
struct anv_descriptor_set_binding {
|
||||
struct anv_descriptor_set * set;
|
||||
uint32_t dynamic_offsets[128];
|
||||
};
|
||||
|
||||
struct anv_cmd_buffer {
|
||||
struct anv_object base;
|
||||
struct anv_device * device;
|
||||
|
||||
struct drm_i915_gem_execbuffer2 execbuf;
|
||||
struct drm_i915_gem_exec_object2 * exec2_objects;
|
||||
struct anv_bo ** exec2_bos;
|
||||
uint32_t exec2_array_length;
|
||||
bool need_reloc;
|
||||
uint32_t serial;
|
||||
|
||||
uint32_t bo_count;
|
||||
struct anv_batch batch;
|
||||
struct anv_batch_bo * last_batch_bo;
|
||||
struct anv_batch_bo * surface_batch_bo;
|
||||
uint32_t surface_next;
|
||||
struct anv_reloc_list surface_relocs;
|
||||
struct anv_state_stream surface_state_stream;
|
||||
struct anv_state_stream dynamic_state_stream;
|
||||
|
||||
/* State required while building cmd buffer */
|
||||
uint32_t current_pipeline;
|
||||
uint32_t vb_dirty;
|
||||
uint32_t dirty;
|
||||
uint32_t compute_dirty;
|
||||
uint32_t descriptors_dirty;
|
||||
uint32_t scratch_size;
|
||||
struct anv_pipeline * pipeline;
|
||||
struct anv_pipeline * compute_pipeline;
|
||||
struct anv_framebuffer * framebuffer;
|
||||
struct anv_dynamic_rs_state * rs_state;
|
||||
struct anv_dynamic_ds_state * ds_state;
|
||||
struct anv_dynamic_vp_state * vp_state;
|
||||
struct anv_dynamic_cb_state * cb_state;
|
||||
uint32_t state_vf[GEN8_3DSTATE_VF_length];
|
||||
struct anv_vertex_binding vertex_bindings[MAX_VBS];
|
||||
struct anv_descriptor_set_binding descriptors[MAX_SETS];
|
||||
};
|
||||
|
||||
void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
|
||||
void anv_aub_writer_destroy(struct anv_aub_writer *writer);
|
||||
|
||||
struct anv_fence {
|
||||
struct anv_object base;
|
||||
struct anv_bo bo;
|
||||
struct drm_i915_gem_execbuffer2 execbuf;
|
||||
struct drm_i915_gem_exec_object2 exec2_objects[1];
|
||||
bool ready;
|
||||
};
|
||||
|
||||
struct anv_shader_module {
|
||||
uint32_t size;
|
||||
char data[0];
|
||||
};
|
||||
|
||||
struct anv_shader {
|
||||
struct anv_shader_module * module;
|
||||
char entrypoint[0];
|
||||
};
|
||||
|
||||
struct anv_pipeline {
|
||||
struct anv_object base;
|
||||
struct anv_device * device;
|
||||
struct anv_batch batch;
|
||||
uint32_t batch_data[256];
|
||||
struct anv_shader * shaders[VK_SHADER_STAGE_NUM];
|
||||
struct anv_pipeline_layout * layout;
|
||||
bool use_repclear;
|
||||
|
||||
struct brw_vs_prog_data vs_prog_data;
|
||||
struct brw_wm_prog_data wm_prog_data;
|
||||
struct brw_gs_prog_data gs_prog_data;
|
||||
struct brw_cs_prog_data cs_prog_data;
|
||||
bool writes_point_size;
|
||||
struct brw_stage_prog_data * prog_data[VK_SHADER_STAGE_NUM];
|
||||
uint32_t scratch_start[VK_SHADER_STAGE_NUM];
|
||||
uint32_t total_scratch;
|
||||
struct {
|
||||
uint32_t vs_start;
|
||||
uint32_t vs_size;
|
||||
uint32_t nr_vs_entries;
|
||||
uint32_t gs_start;
|
||||
uint32_t gs_size;
|
||||
uint32_t nr_gs_entries;
|
||||
} urb;
|
||||
|
||||
uint32_t active_stages;
|
||||
struct anv_state_stream program_stream;
|
||||
struct anv_state blend_state;
|
||||
uint32_t vs_simd8;
|
||||
uint32_t ps_simd8;
|
||||
uint32_t ps_simd16;
|
||||
uint32_t gs_vec4;
|
||||
uint32_t gs_vertex_count;
|
||||
uint32_t cs_simd;
|
||||
|
||||
uint32_t vb_used;
|
||||
uint32_t binding_stride[MAX_VBS];
|
||||
|
||||
uint32_t state_sf[GEN8_3DSTATE_SF_length];
|
||||
uint32_t state_vf[GEN8_3DSTATE_VF_length];
|
||||
uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
|
||||
uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
|
||||
|
||||
uint32_t cs_thread_width_max;
|
||||
uint32_t cs_right_mask;
|
||||
};
|
||||
|
||||
struct anv_pipeline_create_info {
|
||||
bool use_repclear;
|
||||
bool disable_viewport;
|
||||
bool disable_scissor;
|
||||
bool disable_vs;
|
||||
bool use_rectlist;
|
||||
};
|
||||
|
||||
VkResult
|
||||
anv_pipeline_create(VkDevice device,
|
||||
const VkGraphicsPipelineCreateInfo *pCreateInfo,
|
||||
const struct anv_pipeline_create_info *extra,
|
||||
VkPipeline *pPipeline);
|
||||
|
||||
struct anv_compiler *anv_compiler_create(struct anv_device *device);
|
||||
void anv_compiler_destroy(struct anv_compiler *compiler);
|
||||
int anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline);
|
||||
void anv_compiler_free(struct anv_pipeline *pipeline);
|
||||
|
||||
struct anv_format {
|
||||
const char *name;
|
||||
uint16_t surface_format; /**< RENDER_SURFACE_STATE.SurfaceFormat */
|
||||
uint8_t cpp; /**< Bytes-per-pixel of anv_format::surface_format. */
|
||||
uint8_t num_channels;
|
||||
uint8_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
|
||||
bool has_stencil;
|
||||
};
|
||||
|
||||
const struct anv_format *
|
||||
anv_format_for_vk_format(VkFormat format);
|
||||
|
||||
/**
|
||||
* A proxy for the color surfaces, depth surfaces, and stencil surfaces.
|
||||
*/
|
||||
struct anv_surface {
|
||||
/**
|
||||
* Offset from VkImage's base address, as bound by vkBindImageMemory().
|
||||
*/
|
||||
uint32_t offset;
|
||||
|
||||
uint32_t stride; /**< RENDER_SURFACE_STATE.SurfacePitch */
|
||||
uint16_t qpitch; /**< RENDER_SURFACE_STATE.QPitch */
|
||||
|
||||
/**
|
||||
* \name Alignment of miptree images, in units of pixels.
|
||||
*
|
||||
* These fields contain the real alignment values, not the values to be
|
||||
* given to the GPU. For example, if h_align is 4, then program the GPU
|
||||
* with HALIGN_4.
|
||||
* \{
|
||||
*/
|
||||
uint8_t h_align; /**< RENDER_SURFACE_STATE.SurfaceHorizontalAlignment */
|
||||
uint8_t v_align; /**< RENDER_SURFACE_STATE.SurfaceVerticalAlignment */
|
||||
/** \} */
|
||||
|
||||
uint8_t tile_mode; /**< RENDER_SURFACE_STATE.TileMode */
|
||||
};
|
||||
|
||||
struct anv_image {
|
||||
VkImageType type;
|
||||
VkExtent3D extent;
|
||||
VkFormat format;
|
||||
uint32_t levels;
|
||||
uint32_t array_size;
|
||||
|
||||
VkDeviceSize size;
|
||||
uint32_t alignment;
|
||||
|
||||
/* Set when bound */
|
||||
struct anv_bo *bo;
|
||||
VkDeviceSize offset;
|
||||
|
||||
struct anv_swap_chain *swap_chain;
|
||||
|
||||
/** RENDER_SURFACE_STATE.SurfaceType */
|
||||
uint8_t surf_type;
|
||||
|
||||
/** Primary surface is either color or depth. */
|
||||
struct anv_surface primary_surface;
|
||||
|
||||
/** Stencil surface is optional. */
|
||||
struct anv_surface stencil_surface;
|
||||
};
|
||||
|
||||
struct anv_surface_view {
|
||||
struct anv_state surface_state;
|
||||
struct anv_bo * bo;
|
||||
uint32_t offset;
|
||||
uint32_t range;
|
||||
VkExtent3D extent;
|
||||
VkFormat format;
|
||||
};
|
||||
|
||||
struct anv_image_create_info {
|
||||
const VkImageCreateInfo *vk_info;
|
||||
bool force_tile_mode;
|
||||
uint8_t tile_mode;
|
||||
};
|
||||
|
||||
VkResult anv_image_create(VkDevice _device,
|
||||
const struct anv_image_create_info *info,
|
||||
VkImage *pImage);
|
||||
|
||||
void anv_image_view_init(struct anv_surface_view *view,
|
||||
struct anv_device *device,
|
||||
const VkImageViewCreateInfo* pCreateInfo,
|
||||
struct anv_cmd_buffer *cmd_buffer);
|
||||
|
||||
void anv_color_attachment_view_init(struct anv_surface_view *view,
|
||||
struct anv_device *device,
|
||||
const VkColorAttachmentViewCreateInfo* pCreateInfo,
|
||||
struct anv_cmd_buffer *cmd_buffer);
|
||||
|
||||
void anv_surface_view_destroy(struct anv_device *device,
|
||||
struct anv_surface_view *view);
|
||||
|
||||
struct anv_sampler {
|
||||
uint32_t state[4];
|
||||
};
|
||||
|
||||
struct anv_depth_stencil_view {
|
||||
struct anv_bo *bo;
|
||||
|
||||
uint32_t depth_offset; /**< Offset into bo. */
|
||||
uint32_t depth_stride; /**< 3DSTATE_DEPTH_BUFFER.SurfacePitch */
|
||||
uint32_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
|
||||
uint16_t depth_qpitch; /**< 3DSTATE_DEPTH_BUFFER.SurfaceQPitch */
|
||||
|
||||
uint32_t stencil_offset; /**< Offset into bo. */
|
||||
uint32_t stencil_stride; /**< 3DSTATE_STENCIL_BUFFER.SurfacePitch */
|
||||
uint16_t stencil_qpitch; /**< 3DSTATE_STENCIL_BUFFER.SurfaceQPitch */
|
||||
};
|
||||
|
||||
struct anv_framebuffer {
|
||||
struct anv_object base;
|
||||
uint32_t color_attachment_count;
|
||||
const struct anv_surface_view * color_attachments[MAX_RTS];
|
||||
const struct anv_depth_stencil_view * depth_stencil;
|
||||
|
||||
uint32_t sample_count;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t layers;
|
||||
|
||||
/* Viewport for clears */
|
||||
VkDynamicVpState vp_state;
|
||||
};
|
||||
|
||||
struct anv_render_pass_layer {
|
||||
VkAttachmentLoadOp color_load_op;
|
||||
VkClearColorValue clear_color;
|
||||
};
|
||||
|
||||
struct anv_render_pass {
|
||||
VkRect2D render_area;
|
||||
|
||||
uint32_t num_clear_layers;
|
||||
uint32_t num_layers;
|
||||
struct anv_render_pass_layer layers[0];
|
||||
};
|
||||
|
||||
void anv_device_init_meta(struct anv_device *device);
|
||||
void anv_device_finish_meta(struct anv_device *device);
|
||||
|
||||
void
|
||||
anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_render_pass *pass);
|
||||
|
||||
void *
|
||||
anv_lookup_entrypoint(const char *name);
|
||||
|
||||
VkResult anv_DestroyImage(VkDevice device, VkImage image);
|
||||
VkResult anv_DestroyImageView(VkDevice device, VkImageView imageView);
|
||||
VkResult anv_DestroyBufferView(VkDevice device, VkBufferView bufferView);
|
||||
VkResult anv_DestroyColorAttachmentView(VkDevice device,
|
||||
VkColorAttachmentView view);
|
||||
VkResult anv_DestroyDepthStencilView(VkDevice device, VkDepthStencilView view);
|
||||
VkResult anv_DestroyRenderPass(VkDevice device, VkRenderPass renderPass);
|
||||
|
||||
#define ANV_DEFINE_CASTS(__anv_type, __VkType) \
|
||||
static inline struct __anv_type * \
|
||||
__anv_type ## _from_handle(__VkType _handle) \
|
||||
{ \
|
||||
return (struct __anv_type *) _handle; \
|
||||
} \
|
||||
\
|
||||
static inline __VkType \
|
||||
__anv_type ## _to_handle(struct __anv_type *_obj) \
|
||||
{ \
|
||||
return (__VkType) _obj; \
|
||||
}
|
||||
|
||||
ANV_DEFINE_CASTS(anv_physical_device, VkPhysicalDevice)
|
||||
ANV_DEFINE_CASTS(anv_instance, VkInstance)
|
||||
ANV_DEFINE_CASTS(anv_queue, VkQueue)
|
||||
ANV_DEFINE_CASTS(anv_device, VkDevice)
|
||||
ANV_DEFINE_CASTS(anv_device_memory, VkDeviceMemory)
|
||||
ANV_DEFINE_CASTS(anv_dynamic_vp_state, VkDynamicVpState)
|
||||
ANV_DEFINE_CASTS(anv_dynamic_rs_state, VkDynamicRsState)
|
||||
ANV_DEFINE_CASTS(anv_dynamic_ds_state, VkDynamicDsState)
|
||||
ANV_DEFINE_CASTS(anv_dynamic_cb_state, VkDynamicCbState)
|
||||
ANV_DEFINE_CASTS(anv_descriptor_set_layout, VkDescriptorSetLayout)
|
||||
ANV_DEFINE_CASTS(anv_descriptor_set, VkDescriptorSet)
|
||||
ANV_DEFINE_CASTS(anv_pipeline_layout, VkPipelineLayout)
|
||||
ANV_DEFINE_CASTS(anv_buffer, VkBuffer)
|
||||
ANV_DEFINE_CASTS(anv_cmd_buffer, VkCmdBuffer)
|
||||
ANV_DEFINE_CASTS(anv_fence, VkFence)
|
||||
ANV_DEFINE_CASTS(anv_shader_module, VkShaderModule)
|
||||
ANV_DEFINE_CASTS(anv_shader, VkShader)
|
||||
ANV_DEFINE_CASTS(anv_pipeline, VkPipeline)
|
||||
ANV_DEFINE_CASTS(anv_image, VkImage)
|
||||
ANV_DEFINE_CASTS(anv_sampler, VkSampler)
|
||||
ANV_DEFINE_CASTS(anv_depth_stencil_view, VkDepthStencilView)
|
||||
ANV_DEFINE_CASTS(anv_framebuffer, VkFramebuffer)
|
||||
ANV_DEFINE_CASTS(anv_render_pass, VkRenderPass)
|
||||
ANV_DEFINE_CASTS(anv_query_pool, VkQueryPool)
|
||||
|
||||
#define ANV_FROM_HANDLE(__anv_type, __name, __handle) \
|
||||
struct __anv_type *__name = __anv_type ## _from_handle(__handle)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
356
src/vulkan/query.c
Normal file
356
src/vulkan/query.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* 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 {
|
||||
struct anv_object base;
|
||||
VkQueryType type;
|
||||
uint32_t slots;
|
||||
struct anv_bo bo;
|
||||
};
|
||||
|
||||
static void
|
||||
anv_query_pool_destroy(struct anv_device *device,
|
||||
struct anv_object *object,
|
||||
VkObjectType obj_type)
|
||||
{
|
||||
struct anv_query_pool *pool = (struct anv_query_pool *) object;
|
||||
|
||||
assert(obj_type == VK_OBJECT_TYPE_QUERY_POOL);
|
||||
|
||||
anv_gem_munmap(pool->bo.map, pool->bo.size);
|
||||
anv_gem_close(device, pool->bo.gem_handle);
|
||||
anv_device_free(device, pool);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
pool->base.destructor = anv_query_pool_destroy;
|
||||
|
||||
pool->type = pCreateInfo->queryType;
|
||||
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_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)
|
294
src/vulkan/x11.c
Normal file
294
src/vulkan/x11.c
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct anv_device *device = (struct anv_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++) {
|
||||
struct anv_image *image;
|
||||
struct anv_surface *surface;
|
||||
struct anv_device_memory *memory;
|
||||
|
||||
anv_image_create((VkDevice) 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,
|
||||
}},
|
||||
(VkImage *) &image);
|
||||
|
||||
surface = &image->primary_surface;
|
||||
|
||||
anv_AllocMemory((VkDevice) device,
|
||||
&(VkMemoryAllocInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
|
||||
.allocationSize = image->size,
|
||||
.memoryTypeIndex = 0,
|
||||
},
|
||||
(VkDeviceMemory *) &memory);
|
||||
|
||||
anv_BindObjectMemory(VK_NULL_HANDLE,
|
||||
VK_OBJECT_TYPE_IMAGE,
|
||||
(VkImage) image,
|
||||
(VkDeviceMemory) memory, 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 = (VkImage) chain->images[i].image;
|
||||
images[i].memory = (VkDeviceMemory) chain->images[i].memory;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
default:
|
||||
return VK_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult anv_QueuePresentWSI(
|
||||
VkQueue queue_,
|
||||
const VkPresentInfoWSI* pPresentInfo)
|
||||
{
|
||||
struct anv_image *image = (struct anv_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 ((VkImage) chain->images[i].image == pPresentInfo->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