mirror of
https://github.com/ocornut/imgui.git
synced 2026-07-06 17:45:24 +00:00
Compare commits
627 Commits
v1.92.2
...
features/p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef229bc351 | ||
|
|
33803c9883 | ||
|
|
2f3ac76c1b | ||
|
|
6b05f711fd | ||
|
|
86ebb3bc11 | ||
|
|
7e7f3adb80 | ||
|
|
dfe6f9ebca | ||
|
|
37952fb3b8 | ||
|
|
0a811e8ea1 | ||
|
|
82f46a73f8 | ||
|
|
a6a16cf8a2 | ||
|
|
e887098740 | ||
|
|
f934719fbf | ||
|
|
ce3fe4078a | ||
|
|
f2f843c113 | ||
|
|
adc0027912 | ||
|
|
ac06ad7b48 | ||
|
|
4739af2d51 | ||
|
|
b065713cec | ||
|
|
fb308c14ce | ||
|
|
ac261203a5 | ||
|
|
0453ae96e8 | ||
|
|
a5fd597be3 | ||
|
|
382b99c334 | ||
|
|
2d131ef5b7 | ||
|
|
a1e05521e9 | ||
|
|
d7b40ab9a9 | ||
|
|
ac88294b4a | ||
|
|
ea1c04f7ab | ||
|
|
cdb046ac3f | ||
|
|
97939e6837 | ||
|
|
c91b03060d | ||
|
|
a2eb6d99ed | ||
|
|
a2916923a1 | ||
|
|
2cbdb7a337 | ||
|
|
d4783bd553 | ||
|
|
ce855cada2 | ||
|
|
39e7bf5a08 | ||
|
|
0e318a5182 | ||
|
|
19753a30d8 | ||
|
|
6fb74f38af | ||
|
|
4b80d409e7 | ||
|
|
ed4dd679f1 | ||
|
|
3cd8683061 | ||
|
|
bbd0af7256 | ||
|
|
f83a378d62 | ||
|
|
84b4b35902 | ||
|
|
2dc64f99bc | ||
|
|
5da7eb0a84 | ||
|
|
f678c91617 | ||
|
|
6ce4b44547 | ||
|
|
f08b33fd0c | ||
|
|
b444694b3d | ||
|
|
24677c561e | ||
|
|
01a4ad3a50 | ||
|
|
f4ed421a88 | ||
|
|
11de9df44c | ||
|
|
c2565fe642 | ||
|
|
95bd1577d6 | ||
|
|
dd17495a42 | ||
|
|
1870a779e1 | ||
|
|
a9bd173d89 | ||
|
|
bccec3eabc | ||
|
|
d946c6932b | ||
|
|
4d38508c6b | ||
|
|
c0e6580b62 | ||
|
|
6985925244 | ||
|
|
7cb0baeb77 | ||
|
|
49df3116bc | ||
|
|
03a0b00a34 | ||
|
|
4a61188322 | ||
|
|
dac07199cf | ||
|
|
45866bea47 | ||
|
|
65ebca8157 | ||
|
|
9e9fdc97bb | ||
|
|
fc5e421cb9 | ||
|
|
b7bdea3215 | ||
|
|
bf10275aa7 | ||
|
|
0867f6113a | ||
|
|
836278db6c | ||
|
|
505bc9a312 | ||
|
|
07acc8bc87 | ||
|
|
6603cdef98 | ||
|
|
9df0d38d45 | ||
|
|
2ac782fbed | ||
|
|
9fedea83f0 | ||
|
|
ed4cffece7 | ||
|
|
7be8076e9b | ||
|
|
587c4cb87b | ||
|
|
aab17456a7 | ||
|
|
3c78afbbbb | ||
|
|
b003a85143 | ||
|
|
689f837afa | ||
|
|
97075fae4b | ||
|
|
bd3c925680 | ||
|
|
b62cf3894b | ||
|
|
e9eb04ea95 | ||
|
|
ed2e5dd0f0 | ||
|
|
59183cf782 | ||
|
|
59780020f6 | ||
|
|
0b82487fed | ||
|
|
51f590a2a8 | ||
|
|
6c754ed2cb | ||
|
|
79411a0405 | ||
|
|
6b1776a7d2 | ||
|
|
38f5e5a0b8 | ||
|
|
697b6886e3 | ||
|
|
8314fc3e5a | ||
|
|
50b488765f | ||
|
|
4af77622d9 | ||
|
|
2315b9f33d | ||
|
|
04dfcd838b | ||
|
|
2d957152e4 | ||
|
|
325563a982 | ||
|
|
763db046fa | ||
|
|
3a26b640b2 | ||
|
|
386ce49c58 | ||
|
|
b2c3e37d55 | ||
|
|
9700846bb3 | ||
|
|
0b4967992a | ||
|
|
20d8bcb600 | ||
|
|
358d3912c9 | ||
|
|
4d1ba782ee | ||
|
|
0500e546b5 | ||
|
|
7fc3092870 | ||
|
|
b724f940d6 | ||
|
|
4252275c64 | ||
|
|
6abe65aac6 | ||
|
|
f4c2f50896 | ||
|
|
27cacb0e30 | ||
|
|
709be8c495 | ||
|
|
994ca12b29 | ||
|
|
6464276b62 | ||
|
|
16772365e2 | ||
|
|
8957b3df03 | ||
|
|
4a2e3cce69 | ||
|
|
fd752d8357 | ||
|
|
d02c645e38 | ||
|
|
49ee151ed6 | ||
|
|
b76ab6232d | ||
|
|
6dbda97fee | ||
|
|
90743d3112 | ||
|
|
14a500a476 | ||
|
|
6cc99a6e2b | ||
|
|
a103826154 | ||
|
|
0db591935f | ||
|
|
1fbab15c0a | ||
|
|
7546f1eb16 | ||
|
|
5220c14f4b | ||
|
|
378cb85bf0 | ||
|
|
5aa7d61139 | ||
|
|
03a9946a14 | ||
|
|
decb5cdf10 | ||
|
|
5dd56d4bb5 | ||
|
|
512982d0d2 | ||
|
|
9e6b888626 | ||
|
|
83fa0ae263 | ||
|
|
e92820db2a | ||
|
|
6f8bdb7bf7 | ||
|
|
ca166c0e5f | ||
|
|
41765fbda7 | ||
|
|
ba84d2d372 | ||
|
|
11acd9f5cb | ||
|
|
238651ffa3 | ||
|
|
14e0c70f88 | ||
|
|
ef022c5e0a | ||
|
|
c40226e9de | ||
|
|
650eca386e | ||
|
|
848da73a81 | ||
|
|
8a15a1064d | ||
|
|
dd5c604768 | ||
|
|
2b415e642b | ||
|
|
68a91d3060 | ||
|
|
0666da6a72 | ||
|
|
7dec6b6de8 | ||
|
|
33dfa7f834 | ||
|
|
46f0e2e247 | ||
|
|
f6e0953b38 | ||
|
|
14b4d8a625 | ||
|
|
dbee23e09c | ||
|
|
2000008b47 | ||
|
|
37b7a7a9df | ||
|
|
b5ccee78b6 | ||
|
|
221bac8b06 | ||
|
|
05481194b6 | ||
|
|
e8281fdf1a | ||
|
|
f7fbe5bd91 | ||
|
|
c234426f89 | ||
|
|
3fecb234c8 | ||
|
|
0653a0d42a | ||
|
|
635a5c0a12 | ||
|
|
b8a1f74fd9 | ||
|
|
6ded5230d0 | ||
|
|
e118ea06e0 | ||
|
|
f921abe7e7 | ||
|
|
7609963448 | ||
|
|
ff673d31df | ||
|
|
acdaaef625 | ||
|
|
fbe973a8d0 | ||
|
|
eaa32bb787 | ||
|
|
9f2b3bcf7a | ||
|
|
041cdddf35 | ||
|
|
a8bf659143 | ||
|
|
9c33672e5c | ||
|
|
42f28ba305 | ||
|
|
291787bcac | ||
|
|
d67c66c437 | ||
|
|
7b365fa6b4 | ||
|
|
87262dd07a | ||
|
|
8ed10d538e | ||
|
|
9f30044333 | ||
|
|
fd9873a5c2 | ||
|
|
c71b2a1fe6 | ||
|
|
5fe48b6a0e | ||
|
|
1bcc23ef12 | ||
|
|
524f01d248 | ||
|
|
226f62fa8f | ||
|
|
ea83628438 | ||
|
|
76860017d5 | ||
|
|
4b8e41cffb | ||
|
|
a9ca61a7ce | ||
|
|
5166bec5d8 | ||
|
|
6cc7787c77 | ||
|
|
960aff24fc | ||
|
|
8306e32495 | ||
|
|
814c6a194b | ||
|
|
ab6c9d9b12 | ||
|
|
d12b1a938e | ||
|
|
c91bcea7a8 | ||
|
|
c6e54c7ab5 | ||
|
|
d1cf58e590 | ||
|
|
e1217227b2 | ||
|
|
7250fbde2e | ||
|
|
a117055b6b | ||
|
|
b015acc464 | ||
|
|
3050f653cb | ||
|
|
66bb8add73 | ||
|
|
3aba95060e | ||
|
|
cb3b7ff4fb | ||
|
|
d448045669 | ||
|
|
f21307e5c9 | ||
|
|
42b7704b70 | ||
|
|
3803203d47 | ||
|
|
8c0b410371 | ||
|
|
8b86c939c7 | ||
|
|
b933599f00 | ||
|
|
12223cc3e9 | ||
|
|
ea122de913 | ||
|
|
14dfd5bf6b | ||
|
|
5dde06b327 | ||
|
|
21d3299e58 | ||
|
|
d7598aa84f | ||
|
|
9a6eb0ab25 | ||
|
|
a1dfaf4869 | ||
|
|
7143d711bf | ||
|
|
0d08927dae | ||
|
|
791ad9b82d | ||
|
|
f64c7c37ef | ||
|
|
d1c5a66557 | ||
|
|
f5384544cb | ||
|
|
fedf227ea4 | ||
|
|
7a02f4b545 | ||
|
|
ca9b7b4071 | ||
|
|
1566c96ccd | ||
|
|
3389dfd9dd | ||
|
|
9ce41a92c3 | ||
|
|
43a90adc61 | ||
|
|
7b3ad4a282 | ||
|
|
4ce188def8 | ||
|
|
b467a0466c | ||
|
|
69a501df6e | ||
|
|
1dc1964d5b | ||
|
|
f106ccd5fa | ||
|
|
25158fe33b | ||
|
|
960921f03a | ||
|
|
922a11f084 | ||
|
|
b7b8f52437 | ||
|
|
05581da183 | ||
|
|
f006400f05 | ||
|
|
cde6ad3967 | ||
|
|
73dd0e869d | ||
|
|
55ad3b4abd | ||
|
|
d1de937c31 | ||
|
|
d365417e8b | ||
|
|
0ff810038d | ||
|
|
9055c9ed22 | ||
|
|
d87650dffb | ||
|
|
a5dffbec38 | ||
|
|
22ffa3d6d3 | ||
|
|
683f9160b9 | ||
|
|
4e7c05504a | ||
|
|
99bca397d8 | ||
|
|
dc48a7c88e | ||
|
|
4dac00ca0c | ||
|
|
fc89c61089 | ||
|
|
1e7d2adc29 | ||
|
|
bd6f48fe20 | ||
|
|
0d2dd30ee9 | ||
|
|
9971251574 | ||
|
|
a07b2828ce | ||
|
|
9a4fd69f6d | ||
|
|
cf64b7fa72 | ||
|
|
a726bded11 | ||
|
|
7f78f52243 | ||
|
|
60f8b0733c | ||
|
|
fa4b47c5e2 | ||
|
|
a7ecbcdeba | ||
|
|
ded52c71d9 | ||
|
|
9d4fafa671 | ||
|
|
e2c49530cb | ||
|
|
fee06a92ea | ||
|
|
d71091a957 | ||
|
|
d1e262ad55 | ||
|
|
6e0ee6ff03 | ||
|
|
d27dce58cd | ||
|
|
87b193399e | ||
|
|
bfe137893a | ||
|
|
620a33dd85 | ||
|
|
47766ca403 | ||
|
|
7c6febed66 | ||
|
|
1a62292ac0 | ||
|
|
2026e3db88 | ||
|
|
3ff8c466bf | ||
|
|
1f54665799 | ||
|
|
ae873b1e0d | ||
|
|
9c75ef5a61 | ||
|
|
c36162fc6c | ||
|
|
f0699effed | ||
|
|
75db81cf08 | ||
|
|
fd887f5241 | ||
|
|
285e3042ba | ||
|
|
d981b33dd0 | ||
|
|
e768f91dc2 | ||
|
|
3fef0d553d | ||
|
|
3a45bae9dc | ||
|
|
98636f4a23 | ||
|
|
5f82275ba1 | ||
|
|
136d067eed | ||
|
|
324cea1f41 | ||
|
|
ee48fad09d | ||
|
|
6d910d5487 | ||
|
|
26ff93dadc | ||
|
|
a484fd2b56 | ||
|
|
8ff7f35eec | ||
|
|
e8448d0494 | ||
|
|
4ab86e1d61 | ||
|
|
0faa0dba15 | ||
|
|
db6b8e0fb3 | ||
|
|
1f16ca5e5c | ||
|
|
b4a3d423e0 | ||
|
|
68894d4149 | ||
|
|
23bd697f05 | ||
|
|
37f9153105 | ||
|
|
81e01ddebe | ||
|
|
405c802607 | ||
|
|
91b5256c57 | ||
|
|
6ae32c696a | ||
|
|
9afc62d087 | ||
|
|
c3835de38a | ||
|
|
52caa2f38a | ||
|
|
04af1a3917 | ||
|
|
e1f9b8b3a7 | ||
|
|
cfb48969af | ||
|
|
0cf5b93a0a | ||
|
|
d99baf332c | ||
|
|
7e919a543c | ||
|
|
eb19a77848 | ||
|
|
b885382a63 | ||
|
|
9e15ebb402 | ||
|
|
f145b0cffd | ||
|
|
c254db7637 | ||
|
|
5a0c67c4b8 | ||
|
|
ec6219752d | ||
|
|
d246850787 | ||
|
|
e60e5bff63 | ||
|
|
873fe34b31 | ||
|
|
e3979c2098 | ||
|
|
68a44776bd | ||
|
|
613cfaf0b4 | ||
|
|
de917ebb95 | ||
|
|
501e0adcdb | ||
|
|
a2544f9496 | ||
|
|
b51f6e073c | ||
|
|
52e9d94f93 | ||
|
|
fc262355ca | ||
|
|
7537ba2b44 | ||
|
|
86daa8930e | ||
|
|
635eb1d8e9 | ||
|
|
bd0e2036e0 | ||
|
|
b0d3c3a674 | ||
|
|
dacd080639 | ||
|
|
8e2e87d638 | ||
|
|
e389502ffb | ||
|
|
1c3a60047c | ||
|
|
62162747e7 | ||
|
|
189d8c9d9c | ||
|
|
f45adb995c | ||
|
|
7954d6782e | ||
|
|
59db6ceeb1 | ||
|
|
a0bfbe4d8f | ||
|
|
e674f57bb6 | ||
|
|
1897248bda | ||
|
|
051a31594f | ||
|
|
dc6e0f4b9e | ||
|
|
df3f2fff88 | ||
|
|
8e5e79054e | ||
|
|
3cc8b470a6 | ||
|
|
f1becf7e4b | ||
|
|
a3546b52f8 | ||
|
|
823ccc274e | ||
|
|
ff672b2db3 | ||
|
|
778aed9966 | ||
|
|
c5b2a848fa | ||
|
|
d0e3b1d4e2 | ||
|
|
505ff536f9 | ||
|
|
db577cd445 | ||
|
|
149587b85b | ||
|
|
670a92723a | ||
|
|
130c3e6b75 | ||
|
|
3c578fa87e | ||
|
|
8df962a6ed | ||
|
|
2a194e21a0 | ||
|
|
9753c741b9 | ||
|
|
7c483a0eba | ||
|
|
0ba9fedf1a | ||
|
|
2c54b15a5f | ||
|
|
2a229c8cb8 | ||
|
|
40f9e4e8e2 | ||
|
|
245e12cca7 | ||
|
|
8019d39545 | ||
|
|
a1632c6116 | ||
|
|
c72d0b2cbb | ||
|
|
e6125361f9 | ||
|
|
b7e45b3a48 | ||
|
|
6add99f8d2 | ||
|
|
750c5d2a61 | ||
|
|
e571ccf3f4 | ||
|
|
b8573a7e33 | ||
|
|
bc5da9b367 | ||
|
|
b3dab0a406 | ||
|
|
2a022d997b | ||
|
|
5870b979a8 | ||
|
|
bdb8243602 | ||
|
|
b46f099a3f | ||
|
|
63bfad401f | ||
|
|
e11b7a0414 | ||
|
|
065f9e0269 | ||
|
|
4b1f5aba80 | ||
|
|
71447b94fb | ||
|
|
3dc511c71d | ||
|
|
36de604a5b | ||
|
|
2a5e9a15e4 | ||
|
|
d7fec5e1d3 | ||
|
|
7d8d587bc0 | ||
|
|
9a5d5c45f5 | ||
|
|
25e5baf5f0 | ||
|
|
c8db91b7b4 | ||
|
|
702cc9993a | ||
|
|
bad5ee167b | ||
|
|
b6e277980f | ||
|
|
878c863af4 | ||
|
|
9be4f150ef | ||
|
|
00251c8921 | ||
|
|
5af650fc6d | ||
|
|
2b770a029b | ||
|
|
bee2720faa | ||
|
|
fd0873c61f | ||
|
|
ee3d16f150 | ||
|
|
4b858cf5d1 | ||
|
|
09e15e8c9d | ||
|
|
2128e2f44b | ||
|
|
27a9374ef3 | ||
|
|
1cdec11e24 | ||
|
|
3ac624b795 | ||
|
|
a97b0c32ab | ||
|
|
bcf722e637 | ||
|
|
8c22b8aef6 | ||
|
|
fc4105c8a8 | ||
|
|
ea564a6a5e | ||
|
|
9809b0b061 | ||
|
|
b987970870 | ||
|
|
a3d6e82dbd | ||
|
|
3dafd9e898 | ||
|
|
5cd83e689e | ||
|
|
5ce903af6e | ||
|
|
bab3ebec14 | ||
|
|
3ff195f702 | ||
|
|
e459e5bf0a | ||
|
|
217bc445ff | ||
|
|
1c87024840 | ||
|
|
3470e6112b | ||
|
|
e312b99296 | ||
|
|
cc0a6690bf | ||
|
|
5fe962216a | ||
|
|
01686c6294 | ||
|
|
bf2e0b2c6f | ||
|
|
cee40f8af9 | ||
|
|
940627d008 | ||
|
|
719ea9c228 | ||
|
|
f61a7ef222 | ||
|
|
e06b5dfe12 | ||
|
|
e1aea42e45 | ||
|
|
82e9a5e47d | ||
|
|
5f6eaa5278 | ||
|
|
d701ffb478 | ||
|
|
a00e517a81 | ||
|
|
8868ad67e4 | ||
|
|
301e652376 | ||
|
|
dc0198a7e4 | ||
|
|
ef6fe2ecee | ||
|
|
46e6382b69 | ||
|
|
087fbf08f6 | ||
|
|
d4f722d5b2 | ||
|
|
0e7cd694eb | ||
|
|
bf75bfec48 | ||
|
|
1c544ee941 | ||
|
|
70a43f3088 | ||
|
|
9cf9d2be83 | ||
|
|
7e473d38d3 | ||
|
|
6d834d325e | ||
|
|
f6890ed007 | ||
|
|
431f2c5abd | ||
|
|
6274ca4266 | ||
|
|
d92c8c6aff | ||
|
|
72c00f39c1 | ||
|
|
2675b7ca26 | ||
|
|
10d0162378 | ||
|
|
3c6c5692b8 | ||
|
|
e044d99710 | ||
|
|
22a6a83c54 | ||
|
|
cd476b27f8 | ||
|
|
9f13684d70 | ||
|
|
6d25cb844b | ||
|
|
36133d8ac4 | ||
|
|
b6a33f8ce1 | ||
|
|
78c1d4a92c | ||
|
|
7f1e2bb8dd | ||
|
|
2f3e85bc37 | ||
|
|
8a94422246 | ||
|
|
ae832ce532 | ||
|
|
1e52e7b90c | ||
|
|
67085d732a | ||
|
|
f36c65661c | ||
|
|
e2b7d84e96 | ||
|
|
271f476d08 | ||
|
|
e2f314d613 | ||
|
|
8eb22ea620 | ||
|
|
55f590c1d1 | ||
|
|
5e5658e68f | ||
|
|
013c4ed476 | ||
|
|
2f1d1c8b2f | ||
|
|
1cd08b883c | ||
|
|
4e98fb20e2 | ||
|
|
045645e5f1 | ||
|
|
8e4955bb23 | ||
|
|
e66afbbbe0 | ||
|
|
2841c5135d | ||
|
|
bf52f4a83c | ||
|
|
14e076c5bb | ||
|
|
ea8a5a9e17 | ||
|
|
230418a75d | ||
|
|
16415aa39f | ||
|
|
985723ed94 | ||
|
|
a82f66a9b0 | ||
|
|
e422a38e4c | ||
|
|
11fff1ccf5 | ||
|
|
3cc7d1c81a | ||
|
|
56189cd814 | ||
|
|
a9945899c6 | ||
|
|
bc6478f651 | ||
|
|
34ab6c8a89 | ||
|
|
c63b5bd8fb | ||
|
|
8a35ce0e98 | ||
|
|
f77f68a5ed | ||
|
|
bed08daede | ||
|
|
09ebcf1779 | ||
|
|
02af06ea5f | ||
|
|
026d47cd35 | ||
|
|
c63714822f | ||
|
|
26aa81a8b1 | ||
|
|
1ecc34a0b1 | ||
|
|
ee03cef14f | ||
|
|
e51d93e2f5 | ||
|
|
7d33524042 | ||
|
|
605a751571 | ||
|
|
b7cb3d93a4 | ||
|
|
20160ff1d5 | ||
|
|
3766d40394 | ||
|
|
0dd3c845eb | ||
|
|
8dc457fda2 | ||
|
|
0ef9610e70 | ||
|
|
5c92699f5f | ||
|
|
771fae623d | ||
|
|
6351f00ff1 | ||
|
|
55cbc66508 | ||
|
|
9f969944d5 | ||
|
|
aa2f40c3bb | ||
|
|
a309d2dcac | ||
|
|
87c1ab7988 | ||
|
|
319c481abb | ||
|
|
229d56e37a | ||
|
|
7d230594de | ||
|
|
75a4a48d1f | ||
|
|
9e864012ae | ||
|
|
783f1e62cc | ||
|
|
e728b96600 | ||
|
|
fe03035112 | ||
|
|
515c0b526f | ||
|
|
7c6fa8f8f7 | ||
|
|
42656b3aa1 | ||
|
|
89b7fc906a | ||
|
|
0c4f50090a | ||
|
|
720e94f3da | ||
|
|
321e9eb919 | ||
|
|
655601169b | ||
|
|
361e370fe0 | ||
|
|
86ec5c8342 | ||
|
|
45acd5e0e8 | ||
|
|
774ddb58bd | ||
|
|
4dee11a089 | ||
|
|
43e3ac0dc6 | ||
|
|
02f654cbce | ||
|
|
e1baadba84 | ||
|
|
e2a662eed8 | ||
|
|
e1a93805db | ||
|
|
af920e1e6f | ||
|
|
863e989c25 |
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
@@ -2,7 +2,9 @@
|
||||
|
||||
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
|
||||
|
||||
2. Make sure you're using a special branch just for this pull request. (Sometimes people unknowingly use a default branch, then later update that branch, which updates the pull request with the other changes if it hasn't been merged yet.)
|
||||
2. **Make sure you're using a special branch just for this pull request**. (In git, 1 PR = 1 branch. If you update the branch the PR will be updated.)
|
||||
|
||||
3. Clear this template before submitting your PR.
|
||||
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
|
||||
|
||||
4. Clear this template before submitting your PR.
|
||||
|
||||
|
||||
249
.github/workflows/build.yml
vendored
249
.github/workflows/build.yml
vendored
@@ -16,28 +16,38 @@ on:
|
||||
- requested
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
Build-Windows:
|
||||
runs-on: windows-2025
|
||||
name: Build - Windows
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
env:
|
||||
VS_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
# The VulkanSDK libs for Windows is manually generated using build_windows_vulkan_libs.ps1 + attached to issue #8925.
|
||||
# (we have a .yml workflow in commit history if it becomes ever useful to create this on CI too)
|
||||
- name: Install Dependencies
|
||||
shell: powershell
|
||||
run: |
|
||||
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.32.8-VC.zip" -OutFile "SDL2-devel-2.32.8-VC.zip"
|
||||
Expand-Archive -Path SDL2-devel-2.32.8-VC.zip
|
||||
echo "SDL2_DIR=$(pwd)\SDL2-devel-2.32.8-VC\SDL2-2.32.8\" >>${env:GITHUB_ENV}
|
||||
|
||||
|
||||
Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL3-devel-3.2.18-VC.zip" -OutFile "SDL3-devel-3.2.18-VC.zip"
|
||||
Expand-Archive -Path SDL3-devel-3.2.18-VC.zip
|
||||
echo "SDL3_DIR=$(pwd)\SDL3-devel-3.2.18-VC\SDL3-3.2.18\" >>${env:GITHUB_ENV}
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip
|
||||
Expand-Archive -Path vulkan-sdk-1.1.121.2.zip
|
||||
echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV}
|
||||
Invoke-WebRequest -Uri "https://github.com/user-attachments/files/22464296/vulkan_windows_libs_1.4.326.zip" -OutFile vulkan_windows_libs_1.4.326.zip
|
||||
Expand-Archive -Path vulkan_windows_libs_1.4.326.zip
|
||||
echo "VULKAN_SDK=$(pwd)\vulkan_windows_libs_1.4.326\" >>${env:GITHUB_ENV}
|
||||
|
||||
- name: Fix Projects
|
||||
shell: powershell
|
||||
@@ -59,7 +69,7 @@ jobs:
|
||||
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
|
||||
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
|
||||
g++ -I. -Wall -Wformat -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
|
||||
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -o example_null.exe examples/example_null/main.cpp -L. -limgui
|
||||
g++ -I. -Wall -Wformat -DIMGUI_API='__declspec(dllimport)' -DIMGUI_IMPL_API= -o example_null.exe examples/example_null/main.cpp -L. -limgui
|
||||
rm -f example_null.exe libimgui.* example_single_file.*
|
||||
|
||||
- name: Build example_null (extra warnings, msvc 64-bit)
|
||||
@@ -104,7 +114,7 @@ jobs:
|
||||
echo #include "misc/single_file/imgui_single_file.h" >> example_single_file.cpp
|
||||
|
||||
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
|
||||
cl.exe /DIMGUI_API=__declspec(dllimport) /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
||||
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
||||
|
||||
# Win64 examples are more frequently compilted than the Win32 examples.
|
||||
# More of the Win32 examples requires 'workflow_run' to reduce waste.
|
||||
@@ -255,10 +265,18 @@ jobs:
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
|
||||
Linux:
|
||||
Build-Linux:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build - Linux
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
@@ -325,7 +343,7 @@ jobs:
|
||||
EOF
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
|
||||
- name: Build example_null (with large ImDrawIdx + custom ImTextureID)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -338,6 +356,21 @@ jobs:
|
||||
EOF
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
// Test build ImTextureID defined as a struct
|
||||
struct SomeType { int a = 0; int b = 0; };
|
||||
#define ImTextureID SomeType
|
||||
#define ImTextureID_Invalid SomeType()
|
||||
inline bool operator==(const SomeType& lhs, const SomeType& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; }
|
||||
inline bool operator!=(const SomeType& lhs, const SomeType& rhs) { return lhs.a != rhs.a || lhs.b != rhs.b; }
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
@@ -472,10 +505,18 @@ jobs:
|
||||
- name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
||||
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
|
||||
|
||||
MacOS:
|
||||
Build-MacOS:
|
||||
runs-on: macos-latest
|
||||
name: Build - MacOS
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
@@ -484,7 +525,7 @@ jobs:
|
||||
- name: Build example_null (extra warnings, clang 64-bit)
|
||||
run: make -C examples/example_null WITH_EXTRA_WARNINGS=1
|
||||
|
||||
- name: Build example_null (single file build)
|
||||
- name: Build macOS example_null (single file build)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -495,7 +536,7 @@ jobs:
|
||||
EOF
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (single file build, c++20)
|
||||
- name: Build macOS example_null (single file build, c++20)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -506,7 +547,7 @@ jobs:
|
||||
EOF
|
||||
clang++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (without c++ runtime)
|
||||
- name: Build macOS example_null (without c++ runtime)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
@@ -517,49 +558,57 @@ jobs:
|
||||
EOF
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_glfw_opengl2
|
||||
- name: Build macOS example_glfw_opengl2
|
||||
run: make -C examples/example_glfw_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_glfw_opengl3
|
||||
- name: Build macOS example_glfw_opengl3
|
||||
run: make -C examples/example_glfw_opengl3
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_glfw_metal
|
||||
- name: Build macOS example_glfw_metal
|
||||
run: make -C examples/example_glfw_metal
|
||||
|
||||
- name: Build example_sdl2_metal
|
||||
- name: Build macOS example_sdl2_metal
|
||||
run: make -C examples/example_sdl2_metal
|
||||
|
||||
- name: Build example_sdl2_opengl2
|
||||
- name: Build macOS example_sdl2_opengl2
|
||||
run: make -C examples/example_sdl2_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_sdl2_opengl3
|
||||
- name: Build macOS example_sdl2_opengl3
|
||||
run: make -C examples/example_sdl2_opengl3
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_sdl3_opengl3
|
||||
- name: Build macOS example_sdl3_opengl3
|
||||
run: make -C examples/example_sdl3_opengl3
|
||||
|
||||
- name: Build example_apple_metal
|
||||
- name: Build macOS example_apple_metal
|
||||
run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build example_apple_opengl2
|
||||
- name: Build macOS example_apple_opengl2
|
||||
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
Build-iOS:
|
||||
runs-on: macos-14
|
||||
name: Build - iOS
|
||||
|
||||
iOS:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build example_apple_metal
|
||||
run: |
|
||||
# Code signing is required, but we disable it because it is irrelevant for CI builds.
|
||||
xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
||||
|
||||
Emscripten:
|
||||
Build-Emscripten:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build - Emscripten
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
@@ -597,12 +646,148 @@ jobs:
|
||||
emcmake cmake -B build -DCMAKE_BUILD_TYPE=Release examples/example_glfw_wgpu
|
||||
cmake --build build
|
||||
|
||||
Android:
|
||||
Build-Android:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build - Android
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build example_android_opengl3
|
||||
run: |
|
||||
cd examples/example_android_opengl3/android
|
||||
gradle assembleDebug --stacktrace
|
||||
|
||||
Test-Windows:
|
||||
runs-on: windows-2025
|
||||
name: Test - Windows
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
env:
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
continue-on-error: true
|
||||
with:
|
||||
fetch-depth: 1
|
||||
repository: ocornut/imgui_test_engine
|
||||
path: ${{ github.workspace }}/imgui_test_engine
|
||||
submodules: true
|
||||
|
||||
- name: Fix Tests Projects
|
||||
shell: powershell
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine
|
||||
run: |
|
||||
# WARNING: This will need updating if toolset/sdk change in project files!
|
||||
gci -recurse -filter "*.vcxproj" | ForEach-Object {
|
||||
# Fix SDK and toolset for most samples.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
}
|
||||
|
||||
- name: Build Tests
|
||||
shell: cmd
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" imgui_test_suite.vcxproj /p:Platform=x64 /p:Configuration=Release /p:ClFlags=/WX -maxcpucount:%NUMBER_OF_PROCESSORS%'
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 tests
|
||||
|
||||
- name: Check for Docking
|
||||
id: check_docking
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run Viewport Tests
|
||||
if: steps.check_docking.outputs.has_dock == 'true'
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: Release/imgui_test_suite.exe -nogui -nopause -v2 -ve4 -viewport-mock viewport
|
||||
|
||||
Test-Linux:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test - Linux
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/imgui
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
repository: ocornut/imgui_test_engine
|
||||
path: ${{ github.workspace }}/imgui_test_engine
|
||||
submodules: true
|
||||
|
||||
- name: Build Tests
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: make -j$(nproc)
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
|
||||
|
||||
- name: Check for Docking
|
||||
id: check_docking
|
||||
working-directory: ${{ github.workspace }}/imgui
|
||||
run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run Viewport Tests
|
||||
if: steps.check_docking.outputs.has_dock == 'true'
|
||||
working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport
|
||||
|
||||
# Test-MacOS:
|
||||
# runs-on: macos-latest
|
||||
# name: Test - MacOS
|
||||
#
|
||||
# defaults:
|
||||
# run:
|
||||
# working-directory: ${{ github.workspace }}/imgui
|
||||
#
|
||||
# steps:
|
||||
# - uses: actions/checkout@v6
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/imgui
|
||||
#
|
||||
# - uses: actions/checkout@v6
|
||||
# with:
|
||||
# fetch-depth: 1
|
||||
# repository: ocornut/imgui_test_engine
|
||||
# path: ${{ github.workspace }}/imgui_test_engine
|
||||
# submodules: true
|
||||
#
|
||||
# - name: Build Tests
|
||||
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
# run: make -j$(nproc)
|
||||
#
|
||||
# - name: Run Tests
|
||||
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
# run: ./imgui_test_suite -nogui -nopause -v2 -ve4 tests
|
||||
#
|
||||
# - name: Check for Docking
|
||||
# id: check_docking
|
||||
# working-directory: ${{ github.workspace }}/imgui
|
||||
# run: echo "has_dock=$(grep -q "#define IMGUI_HAS_DOCK" imgui.h && echo true || echo false)" >> $GITHUB_OUTPUT
|
||||
#
|
||||
# - name: Run Viewport Tests
|
||||
# if: steps.check_docking.outputs.has_dock == 'true'
|
||||
# working-directory: ${{ github.workspace }}/imgui_test_engine/imgui_test_suite
|
||||
# run: ./imgui_test_suite -nogui -nopause -v2 -ve4 -viewport-mock viewport
|
||||
|
||||
38
.github/workflows/build_windows_vulkan_libs.ps1
vendored
Normal file
38
.github/workflows/build_windows_vulkan_libs.ps1
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# This is current meant to be run manually, occasionally:
|
||||
# - Run then zip the contents of vulkanArtifact/ into e.g. vulkan_windows_libs_1.4.326
|
||||
# - Upload as an attachment to https://github.com/ocornut/imgui/pull/8925 then change filename in build.yml
|
||||
# - There is a build_windows_vulkan_libs.yml in commit history that we removed thinking this is run so rarely we don't need to pollute CI UI with it.
|
||||
|
||||
# Set default vulkan version if none provided
|
||||
if (-not $env:VULKAN_TAG) { $env:VULKAN_TAG = "1.4.326" }
|
||||
|
||||
# Create output folder
|
||||
mkdir vulkanArtifact
|
||||
|
||||
# Download Vulkan Headers
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Headers-$($env:VULKAN_TAG).zip
|
||||
Expand-Archive -Path Vulkan-Headers-$($env:VULKAN_TAG).zip
|
||||
|
||||
# Copy Vulkan Headers to artifact folder
|
||||
|
||||
cp -R Vulkan-Headers-$($env:VULKAN_TAG)\Vulkan-Headers-$($env:VULKAN_TAG)\include vulkanArtifact\Include
|
||||
|
||||
# Download Vulkan Loader
|
||||
|
||||
Invoke-WebRequest -Uri "https://github.com/KhronosGroup/Vulkan-Loader/archive/refs/tags/v$($env:VULKAN_TAG).zip" -OutFile Vulkan-Loader-$($env:VULKAN_TAG).zip
|
||||
Expand-Archive -Path Vulkan-Loader-$($env:VULKAN_TAG).zip
|
||||
|
||||
# Build Vulkan Loader x64
|
||||
|
||||
cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build64 -D UPDATE_DEPS=On -A x64
|
||||
cmake --build VulkanLoader-build64
|
||||
mkdir vulkanArtifact\Lib
|
||||
copy VulkanLoader-build64\loader\Debug\vulkan-1.lib vulkanArtifact\Lib
|
||||
|
||||
# Build Vulkan Loader win32
|
||||
|
||||
cmake -S Vulkan-Loader-$($env:VULKAN_TAG)\Vulkan-Loader-$($env:VULKAN_TAG) -B VulkanLoader-build32 -D UPDATE_DEPS=On -A Win32
|
||||
cmake --build VulkanLoader-build32
|
||||
mkdir vulkanArtifact\Lib32
|
||||
copy VulkanLoader-build32\loader\Debug\vulkan-1.lib vulkanArtifact\Lib32
|
||||
2
.github/workflows/static-analysis.yml
vendored
2
.github/workflows/static-analysis.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
PVS-Studio:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
## OSX artifacts
|
||||
## Misc artifacts
|
||||
.DS_Store
|
||||
.claude
|
||||
.vscode
|
||||
|
||||
## Dear ImGui artifacts
|
||||
imgui.ini
|
||||
@@ -12,6 +14,7 @@ imgui*.ini
|
||||
examples/*/Debug/*
|
||||
examples/*/Release/*
|
||||
examples/*/x64/*
|
||||
examples/*.tmp
|
||||
|
||||
## Visual Studio artifacts
|
||||
.vs
|
||||
@@ -46,14 +49,14 @@ examples/example_glfw_opengl3/web/*
|
||||
examples/example_glfw_wgpu/web/*
|
||||
examples/example_glfw_wgpu/external/*
|
||||
examples/example_sdl2_opengl3/web/*
|
||||
examples/example_sdl2_wgpu/web/*
|
||||
examples/example_sdl3_opengl3/web/*
|
||||
examples/example_sdl3_wgpu/web/*
|
||||
|
||||
## JetBrains IDE artifacts
|
||||
.idea
|
||||
cmake-build-*
|
||||
|
||||
## VS code artifacts
|
||||
.vscode
|
||||
|
||||
## Unix executables from our example Makefiles
|
||||
examples/example_apple_metal/example_apple_metal
|
||||
examples/example_apple_opengl2/example_apple_opengl2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2025 Omar Cornut
|
||||
Copyright (c) 2014-2026 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
// [X] Platform: Clipboard support (from Allegro 5.1.12).
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: The renderer is suboptimal as we need to convert vertices manually.
|
||||
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: Allegro5 cannot enable/disable LINEAR bitmap flags after creation.
|
||||
// [ ] Platform: Missing gamepad support.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
@@ -21,6 +22,10 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others cannot be supported by Allegro5). (#9378)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() and platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-08-12: Inputs: fixed missing support for ImGuiKey_PrintScreen under Windows, as raw Allegro 5 does not receive it.
|
||||
// 2025-08-12: Added ImGui_ImplAllegro5_SetDisplay() function to change current ALLEGRO_DISPLAY, as Allegro applications often need to do that.
|
||||
// 2025-07-07: Fixed texture update broken on some platforms where ALLEGRO_LOCK_WRITEONLY needed all texels to be rewritten.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_DestroyFontsTexture().
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
@@ -133,7 +138,10 @@ static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
|
||||
}
|
||||
}
|
||||
|
||||
// Render function.
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplAllegro5_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
@@ -149,6 +157,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
// Backup Allegro state that will be modified
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ALLEGRO_TRANSFORM last_transform = *al_get_current_transform();
|
||||
ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform();
|
||||
int last_clip_x, last_clip_y, last_clip_w, last_clip_h;
|
||||
@@ -205,8 +214,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplAllegro5_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplAllegro5_SetupRenderState(draw_data);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -267,8 +275,6 @@ void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex)
|
||||
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
||||
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
|
||||
ALLEGRO_BITMAP* cpu_bitmap = al_create_bitmap(tex->Width, tex->Height);
|
||||
al_set_new_bitmap_flags(new_bitmap_flags);
|
||||
al_set_new_bitmap_format(new_bitmap_format);
|
||||
IM_ASSERT(cpu_bitmap != nullptr && "Backend failed to create texture!");
|
||||
|
||||
// Upload pixels
|
||||
@@ -278,10 +284,15 @@ void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex)
|
||||
al_unlock_bitmap(cpu_bitmap);
|
||||
|
||||
// Convert software texture to hardware texture.
|
||||
al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
|
||||
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA);
|
||||
ALLEGRO_BITMAP* gpu_bitmap = al_clone_bitmap(cpu_bitmap);
|
||||
al_destroy_bitmap(cpu_bitmap);
|
||||
IM_ASSERT(gpu_bitmap != nullptr && "Backend failed to create texture!");
|
||||
|
||||
al_set_new_bitmap_flags(new_bitmap_flags);
|
||||
al_set_new_bitmap_format(new_bitmap_format);
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)gpu_bitmap);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
@@ -476,26 +487,16 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
bd->Display = display;
|
||||
bd->LastCursor = ALLEGRO_SYSTEM_MOUSE_CURSOR_NONE;
|
||||
|
||||
// Create custom vertex declaration.
|
||||
// Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 floats.
|
||||
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
|
||||
ALLEGRO_VERTEX_ELEMENT elems[] =
|
||||
{
|
||||
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, pos) },
|
||||
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, uv) },
|
||||
{ ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ImDrawVertAllegro, col) },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
|
||||
ImGui_ImplAllegro5_SetDisplay(display);
|
||||
|
||||
#if ALLEGRO_HAS_CLIPBOARD
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
#if ALLEGRO_HAS_CLIPBOARD
|
||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText;
|
||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText;
|
||||
#endif
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplAllegro5_DrawCallback_ResetRenderState;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -505,6 +506,7 @@ void ImGui_ImplAllegro5_Shutdown()
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplAllegro5_InvalidateDeviceObjects();
|
||||
if (bd->VertexDecl)
|
||||
@@ -515,9 +517,38 @@ void ImGui_ImplAllegro5_Shutdown()
|
||||
io.BackendPlatformName = io.BackendRendererName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplAllegro5_SetDisplay(ALLEGRO_DISPLAY* display)
|
||||
{
|
||||
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
|
||||
bd->Display = display;
|
||||
|
||||
if (bd->VertexDecl)
|
||||
{
|
||||
al_destroy_vertex_decl(bd->VertexDecl);
|
||||
bd->VertexDecl = nullptr;
|
||||
}
|
||||
|
||||
if (bd->Display && !bd->VertexDecl)
|
||||
{
|
||||
// Create custom vertex declaration.
|
||||
// Unfortunately Allegro doesn't support 32-bits packed colors so we have to convert them to 4 floats.
|
||||
// We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
|
||||
ALLEGRO_VERTEX_ELEMENT elems[] =
|
||||
{
|
||||
{ ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, pos) },
|
||||
{ ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ImDrawVertAllegro, uv) },
|
||||
{ ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ImDrawVertAllegro, col) },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
|
||||
}
|
||||
}
|
||||
|
||||
// ev->keyboard.modifiers seems always zero so using that...
|
||||
static void ImGui_ImplAllegro5_UpdateKeyModifiers()
|
||||
{
|
||||
@@ -659,6 +690,11 @@ void ImGui_ImplAllegro5_NewFrame()
|
||||
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
// Allegro 5 doesn't receive PrintScreen under Windows
|
||||
#ifdef _WIN32
|
||||
io.AddKeyEvent(ImGuiKey_PrintScreen, (::GetAsyncKeyState(VK_SNAPSHOT) & 0x8000) != 0);
|
||||
#endif
|
||||
|
||||
// Setup mouse cursor shape
|
||||
ImGui_ImplAllegro5_UpdateMouseCursor();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: Allegro5 cannot enable/disable LINEAR bitmap flags after creation.
|
||||
// [ ] Platform: Missing gamepad support.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
@@ -32,12 +33,13 @@ IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event);
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_SetDisplay(ALLEGRO_DISPLAY* display);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplAllegro5_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378)
|
||||
// 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: DirectX10: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2025-05-07: DirectX10: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
|
||||
// 2025-01-06: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
@@ -73,7 +76,8 @@ struct ImGui_ImplDX10_Data
|
||||
ID3D10InputLayout* pInputLayout;
|
||||
ID3D10Buffer* pVertexConstantBuffer;
|
||||
ID3D10PixelShader* pPixelShader;
|
||||
ID3D10SamplerState* pFontSampler;
|
||||
ID3D10SamplerState* pTexSamplerLinear;
|
||||
ID3D10SamplerState* pTexSamplerNearest;
|
||||
ID3D10RasterizerState* pRasterizerState;
|
||||
ID3D10BlendState* pBlendState;
|
||||
ID3D10DepthStencilState* pDepthStencilState;
|
||||
@@ -140,7 +144,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
|
||||
device->VSSetShader(bd->pVertexShader);
|
||||
device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
device->PSSetShader(bd->pPixelShader);
|
||||
device->PSSetSamplers(0, 1, &bd->pFontSampler);
|
||||
device->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
|
||||
device->GSSetShader(nullptr);
|
||||
|
||||
// Setup render state
|
||||
@@ -150,6 +154,11 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
|
||||
device->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX10_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX10_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); bd->pd3dDevice->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); }
|
||||
static void ImGui_ImplDX10_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); bd->pd3dDevice->PSSetSamplers(0, 1, &bd->pTexSamplerNearest); }
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
@@ -174,7 +183,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D10_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.ByteWidth = (UINT)bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
@@ -188,7 +197,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D10_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.ByteWidth = (UINT)bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
if (device->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
@@ -257,7 +266,6 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplDX10_RenderState render_state;
|
||||
render_state.Device = bd->pd3dDevice;
|
||||
render_state.SamplerDefault = bd->pFontSampler;
|
||||
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
|
||||
@@ -275,8 +283,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplDX10_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX10_SetupRenderState(draw_data, device);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -324,18 +331,18 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
static void ImGui_ImplDX10_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData;
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
backend_tex->pTexture->Release();
|
||||
backend_tex->pTextureView->Release();
|
||||
IM_DELETE(backend_tex);
|
||||
if (ImGui_ImplDX10_Texture* backend_tex = (ImGui_ImplDX10_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D10ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
backend_tex->pTextureView->Release();
|
||||
backend_tex->pTexture->Release();
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex)
|
||||
@@ -563,7 +570,9 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
||||
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -579,7 +588,8 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplDX10_DestroyTexture(tex);
|
||||
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
|
||||
if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
|
||||
if (bd->pTexSamplerNearest) { bd->pTexSamplerNearest->Release(); bd->pTexSamplerNearest = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
@@ -606,6 +616,9 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX10_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX10_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX10_DrawCallback_SetSamplerNearest;
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
@@ -630,13 +643,16 @@ void ImGui_ImplDX10_Shutdown()
|
||||
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
@@ -41,8 +41,9 @@ IMGUI_IMPL_API void ImGui_ImplDX10_UpdateTexture(ImTextureData* tex);
|
||||
struct ImGui_ImplDX10_RenderState
|
||||
{
|
||||
ID3D10Device* Device;
|
||||
ID3D10SamplerState* SamplerDefault;
|
||||
ID3D10Buffer* VertexConstantBuffer;
|
||||
//ID3D10SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
|
||||
//ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: DirectX11: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX11_RenderState. (#9378)
|
||||
// 2026-01-19: DirectX11: Added 'SamplerNearest' in ImGui_ImplDX11_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: DirectX11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2025-05-07: DirectX11: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
|
||||
// 2025-01-06: DirectX11: Expose VertexConstantBuffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handler.
|
||||
@@ -76,12 +79,14 @@ struct ImGui_ImplDX11_Data
|
||||
ID3D11InputLayout* pInputLayout;
|
||||
ID3D11Buffer* pVertexConstantBuffer;
|
||||
ID3D11PixelShader* pPixelShader;
|
||||
ID3D11SamplerState* pFontSampler;
|
||||
ID3D11SamplerState* pTexSamplerLinear;
|
||||
ID3D11SamplerState* pTexSamplerNearest;
|
||||
ID3D11RasterizerState* pRasterizerState;
|
||||
ID3D11BlendState* pBlendState;
|
||||
ID3D11DepthStencilState* pDepthStencilState;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
ImGui_ImplDX11_RenderState* RenderState; // == (ImGui_ImplDX11_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState during rendering.
|
||||
|
||||
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
@@ -99,7 +104,7 @@ static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
|
||||
static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
|
||||
@@ -143,7 +148,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
|
||||
device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
|
||||
device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
|
||||
device_ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
|
||||
device_ctx->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
|
||||
device_ctx->GSSetShader(nullptr, nullptr, 0);
|
||||
device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
@@ -156,6 +161,11 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
|
||||
device_ctx->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX11_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX11_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); bd->RenderState->DeviceContext->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); }
|
||||
static void ImGui_ImplDX11_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); bd->RenderState->DeviceContext->PSSetSamplers(0, 1, &bd->pTexSamplerNearest); }
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
@@ -180,7 +190,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.ByteWidth = (UINT)bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
@@ -193,7 +203,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.ByteWidth = (UINT)bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
@@ -271,9 +281,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
ImGui_ImplDX11_RenderState render_state;
|
||||
render_state.Device = bd->pd3dDevice;
|
||||
render_state.DeviceContext = bd->pd3dDeviceContext;
|
||||
render_state.SamplerDefault = bd->pFontSampler;
|
||||
render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
@@ -289,8 +298,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplDX11_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX11_SetupRenderState(draw_data, device);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -316,7 +324,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
|
||||
// Restore modified DX state
|
||||
device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||
@@ -340,18 +348,18 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
static void ImGui_ImplDX11_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData;
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
backend_tex->pTextureView->Release();
|
||||
backend_tex->pTexture->Release();
|
||||
IM_DELETE(backend_tex);
|
||||
if (ImGui_ImplDX11_Texture* backend_tex = (ImGui_ImplDX11_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->pTextureView == (ID3D11ShaderResourceView*)(intptr_t)tex->TexID);
|
||||
backend_tex->pTextureView->Release();
|
||||
backend_tex->pTexture->Release();
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex)
|
||||
@@ -578,7 +586,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -595,7 +605,8 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplDX11_DestroyTexture(tex);
|
||||
|
||||
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
|
||||
if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
|
||||
if (bd->pTexSamplerNearest) { bd->pTexSamplerNearest->Release(); bd->pTexSamplerNearest = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
@@ -622,6 +633,9 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX11_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX11_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX11_DrawCallback_SetSamplerNearest;
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
@@ -649,14 +663,17 @@ void ImGui_ImplDX11_Shutdown()
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
@@ -44,8 +44,9 @@ struct ImGui_ImplDX11_RenderState
|
||||
{
|
||||
ID3D11Device* Device;
|
||||
ID3D11DeviceContext* DeviceContext;
|
||||
ID3D11SamplerState* SamplerDefault;
|
||||
ID3D11Buffer* VertexConstantBuffer;
|
||||
//ID3D11SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
|
||||
//ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
|
||||
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
|
||||
// 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965)
|
||||
// 2025-09-29: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-19: Fixed build on MinGW. (#8702, #4594)
|
||||
// 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2025-05-07: DirectX12: Honor draw_data->FramebufferScale to allow for custom backends and experiment using it (consistently with other renderer backends, even though in normal condition it is not set under Windows).
|
||||
@@ -56,7 +62,7 @@
|
||||
|
||||
// DirectX
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <dxgi1_5.h>
|
||||
#include <d3dcompiler.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||
@@ -86,23 +92,36 @@ struct ImGui_ImplDX12_Texture
|
||||
struct ImGui_ImplDX12_Data
|
||||
{
|
||||
ImGui_ImplDX12_InitInfo InitInfo;
|
||||
ImGui_ImplDX12_RenderState* RenderState;
|
||||
|
||||
IDXGIFactory5* pdxgiFactory;
|
||||
ID3D12Device* pd3dDevice;
|
||||
ID3D12RootSignature* pRootSignature;
|
||||
ID3D12PipelineState* pPipelineState;
|
||||
ID3D12RootSignature* pRootSignatureLinear;
|
||||
ID3D12RootSignature* pRootSignatureNearest;
|
||||
ID3D12PipelineState* pPipelineStateLinear;
|
||||
ID3D12PipelineState* pPipelineStateNearest;
|
||||
ID3D12CommandQueue* pCommandQueue;
|
||||
bool commandQueueOwned;
|
||||
DXGI_FORMAT RTVFormat;
|
||||
DXGI_FORMAT DSVFormat;
|
||||
ID3D12DescriptorHeap* pd3dSrvDescHeap;
|
||||
ID3D12Fence* Fence;
|
||||
UINT64 FenceLastSignaledValue;
|
||||
HANDLE FenceEvent;
|
||||
UINT numFramesInFlight;
|
||||
bool tearingSupport;
|
||||
bool LegacySingleDescriptorUsed;
|
||||
|
||||
ID3D12CommandAllocator* pTexCmdAllocator;
|
||||
ID3D12GraphicsCommandList* pTexCmdList;
|
||||
ID3D12Resource* pTexUploadBuffer;
|
||||
UINT pTexUploadBufferSize;
|
||||
void* pTexUploadBufferMapped;
|
||||
|
||||
ImGui_ImplDX12_RenderBuffers* pFrameResources;
|
||||
UINT frameIndex;
|
||||
|
||||
ImGui_ImplDX12_Texture FontTexture;
|
||||
bool LegacySingleDescriptorUsed;
|
||||
|
||||
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
|
||||
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
@@ -127,10 +146,22 @@ struct VERTEX_CONSTANT_BUFFER_DX12
|
||||
};
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr)
|
||||
static void ImGui_ImplDX12_SetupSamplerLinear(ID3D12GraphicsCommandList* command_list)
|
||||
{
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
command_list->SetPipelineState(bd->pPipelineStateLinear);
|
||||
command_list->SetGraphicsRootSignature(bd->pRootSignatureLinear);
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX12_SetupSamplerNearest(ID3D12GraphicsCommandList* command_list)
|
||||
{
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
command_list->SetPipelineState(bd->pPipelineStateNearest);
|
||||
command_list->SetGraphicsRootSignature(bd->pRootSignatureNearest);
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr)
|
||||
{
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
|
||||
VERTEX_CONSTANT_BUFFER_DX12 vertex_constant_buffer;
|
||||
@@ -168,12 +199,11 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
|
||||
command_list->IASetVertexBuffers(0, 1, &vbv);
|
||||
D3D12_INDEX_BUFFER_VIEW ibv = {};
|
||||
ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress();
|
||||
ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
ibv.SizeInBytes = (UINT)fr->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
|
||||
command_list->IASetIndexBuffer(&ibv);
|
||||
command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
command_list->SetPipelineState(bd->pPipelineState);
|
||||
command_list->SetGraphicsRootSignature(bd->pRootSignature);
|
||||
ImGui_ImplDX12_SetupSamplerLinear(command_list);
|
||||
command_list->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
|
||||
|
||||
// Setup blend factor
|
||||
@@ -189,6 +219,11 @@ static inline void SafeRelease(T*& res)
|
||||
res = nullptr;
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX12_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX12_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_SetupSamplerLinear(bd->RenderState->CommandList); }
|
||||
static void ImGui_ImplDX12_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_SetupSamplerNearest(bd->RenderState->CommandList); }
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list)
|
||||
{
|
||||
@@ -286,7 +321,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
|
||||
ImGui_ImplDX12_RenderState render_state;
|
||||
render_state.Device = bd->pd3dDevice;
|
||||
render_state.CommandList = command_list;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
@@ -303,7 +338,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplDX12_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX12_SetupRenderState(draw_data, command_list, fr);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -330,26 +365,26 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX12_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData;
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID);
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle);
|
||||
SafeRelease(backend_tex->pTextureResource);
|
||||
backend_tex->hFontSrvCpuDescHandle.ptr = 0;
|
||||
backend_tex->hFontSrvGpuDescHandle.ptr = 0;
|
||||
IM_DELETE(backend_tex);
|
||||
if (ImGui_ImplDX12_Texture* backend_tex = (ImGui_ImplDX12_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->hFontSrvGpuDescHandle.ptr == (UINT64)tex->TexID);
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, backend_tex->hFontSrvCpuDescHandle, backend_tex->hFontSrvGpuDescHandle);
|
||||
SafeRelease(backend_tex->pTextureResource);
|
||||
backend_tex->hFontSrvCpuDescHandle.ptr = 0;
|
||||
backend_tex->hFontSrvGpuDescHandle.ptr = 0;
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||
@@ -428,58 +463,53 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||
UINT upload_pitch_dst = (upload_pitch_src + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
||||
UINT upload_size = upload_pitch_dst * upload_h;
|
||||
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = upload_size;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
if (bd->pTexUploadBuffer == nullptr || upload_size > bd->pTexUploadBufferSize)
|
||||
{
|
||||
if (bd->pTexUploadBufferMapped)
|
||||
{
|
||||
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
|
||||
bd->pTexUploadBuffer->Unmap(0, &range);
|
||||
bd->pTexUploadBufferMapped = nullptr;
|
||||
}
|
||||
SafeRelease(bd->pTexUploadBuffer);
|
||||
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = upload_size;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
// FIXME-OPT: Can upload buffer be reused?
|
||||
ID3D12Resource* uploadBuffer = nullptr;
|
||||
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
// Create temporary command list and execute immediately
|
||||
ID3D12Fence* fence = nullptr;
|
||||
hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&bd->pTexUploadBuffer));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
HANDLE event = ::CreateEvent(0, 0, 0, 0);
|
||||
IM_ASSERT(event != nullptr);
|
||||
D3D12_RANGE range = {0, upload_size};
|
||||
hr = bd->pTexUploadBuffer->Map(0, &range, &bd->pTexUploadBufferMapped);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
bd->pTexUploadBufferSize = upload_size;
|
||||
}
|
||||
|
||||
// FIXME-OPT: Create once and reuse?
|
||||
ID3D12CommandAllocator* cmdAlloc = nullptr;
|
||||
hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// FIXME-OPT: Can be use the one from user? (pass ID3D12GraphicsCommandList* to ImGui_ImplDX12_UpdateTextures)
|
||||
ID3D12GraphicsCommandList* cmdList = nullptr;
|
||||
hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, nullptr, IID_PPV_ARGS(&cmdList));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
bd->pTexCmdAllocator->Reset();
|
||||
bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr);
|
||||
ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList;
|
||||
|
||||
// Copy to upload buffer
|
||||
void* mapped = nullptr;
|
||||
D3D12_RANGE range = { 0, upload_size };
|
||||
hr = uploadBuffer->Map(0, &range, &mapped);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
for (int y = 0; y < upload_h; y++)
|
||||
memcpy((void*)((uintptr_t)mapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
|
||||
uploadBuffer->Unmap(0, &range);
|
||||
memcpy((void*)((uintptr_t)bd->pTexUploadBufferMapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
|
||||
|
||||
if (need_barrier_before_copy)
|
||||
{
|
||||
@@ -496,7 +526,7 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
|
||||
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
||||
{
|
||||
srcLocation.pResource = uploadBuffer;
|
||||
srcLocation.pResource = bd->pTexUploadBuffer;
|
||||
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srcLocation.PlacedFootprint.Footprint.Width = upload_w;
|
||||
@@ -520,26 +550,20 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||
cmdList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
hr = cmdList->Close();
|
||||
HRESULT hr = cmdList->Close();
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12CommandQueue* cmdQueue = bd->pCommandQueue;
|
||||
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
|
||||
hr = cmdQueue->Signal(fence, 1);
|
||||
hr = cmdQueue->Signal(bd->Fence, ++bd->FenceLastSignaledValue);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// FIXME-OPT: Suboptimal?
|
||||
// - To remove this may need to create NumFramesInFlight x ImGui_ImplDX12_FrameContext in backend data (mimick docking version)
|
||||
// - Store per-frame in flight: upload buffer?
|
||||
// - Where do cmdList and cmdAlloc fit?
|
||||
fence->SetEventOnCompletion(1, event);
|
||||
::WaitForSingleObject(event, INFINITE);
|
||||
bd->Fence->SetEventOnCompletion(bd->FenceLastSignaledValue, bd->FenceEvent);
|
||||
::WaitForSingleObject(bd->FenceEvent, INFINITE);
|
||||
|
||||
cmdList->Release();
|
||||
cmdAlloc->Release();
|
||||
::CloseHandle(event);
|
||||
fence->Release();
|
||||
uploadBuffer->Release();
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
|
||||
@@ -552,9 +576,16 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return false;
|
||||
if (bd->pPipelineState)
|
||||
if (bd->pPipelineStateLinear)
|
||||
ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
|
||||
HRESULT hr = ::CreateDXGIFactory1(IID_PPV_ARGS(&bd->pdxgiFactory));
|
||||
IM_ASSERT(hr == S_OK);
|
||||
|
||||
BOOL allow_tearing = FALSE;
|
||||
bd->pdxgiFactory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing, sizeof(allow_tearing));
|
||||
bd->tearingSupport = (allow_tearing == TRUE);
|
||||
|
||||
// Create the root signature
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE descRange = {};
|
||||
@@ -578,26 +609,26 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
D3D12_STATIC_SAMPLER_DESC staticSampler = {};
|
||||
staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler.MipLODBias = 0.f;
|
||||
staticSampler.MaxAnisotropy = 0;
|
||||
staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
|
||||
staticSampler.MinLOD = 0.f;
|
||||
staticSampler.MaxLOD = D3D12_FLOAT32_MAX;
|
||||
staticSampler.ShaderRegister = 0;
|
||||
staticSampler.RegisterSpace = 0;
|
||||
staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
D3D12_STATIC_SAMPLER_DESC staticSampler[1] = {};
|
||||
staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
staticSampler[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler[0].MipLODBias = 0.f;
|
||||
staticSampler[0].MaxAnisotropy = 0;
|
||||
staticSampler[0].ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
staticSampler[0].BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
|
||||
staticSampler[0].MinLOD = 0.f;
|
||||
staticSampler[0].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
staticSampler[0].ShaderRegister = 0;
|
||||
staticSampler[0].RegisterSpace = 0;
|
||||
staticSampler[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC desc = {};
|
||||
desc.NumParameters = _countof(param);
|
||||
desc.pParameters = param;
|
||||
desc.NumStaticSamplers = 1;
|
||||
desc.pStaticSamplers = &staticSampler;
|
||||
desc.pStaticSamplers = &staticSampler[0];
|
||||
desc.Flags =
|
||||
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
|
||||
@@ -614,7 +645,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
// (2) there exists a version of d3d12.dll for Windows 7 (D3D12On7) in one of the following directories.
|
||||
// See https://github.com/ocornut/imgui/pull/3696 for details.
|
||||
const char* localD3d12Paths[] = { ".\\d3d12.dll", ".\\d3d12on7\\d3d12.dll", ".\\12on7\\d3d12.dll" }; // A. current directory, B. used by some games, C. used in Microsoft D3D12On7 sample
|
||||
for (int i = 0; i < IM_ARRAYSIZE(localD3d12Paths); i++)
|
||||
for (int i = 0; i < IM_COUNTOF(localD3d12Paths); i++)
|
||||
if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != nullptr)
|
||||
break;
|
||||
|
||||
@@ -634,7 +665,15 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK)
|
||||
return false;
|
||||
|
||||
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
|
||||
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureLinear));
|
||||
blob->Release();
|
||||
|
||||
// Nearest sampler
|
||||
staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK)
|
||||
return false;
|
||||
|
||||
bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureNearest));
|
||||
blob->Release();
|
||||
}
|
||||
|
||||
@@ -647,7 +686,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
||||
psoDesc.NodeMask = 1;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
psoDesc.pRootSignature = bd->pRootSignature;
|
||||
psoDesc.pRootSignature = bd->pRootSignatureLinear;
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
psoDesc.RTVFormats[0] = bd->RTVFormat;
|
||||
@@ -770,12 +809,36 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
desc.BackFace = desc.FrontFace;
|
||||
}
|
||||
|
||||
HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState));
|
||||
HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateLinear));
|
||||
if (result_pipeline_state != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
pixelShaderBlob->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
psoDesc.pRootSignature = bd->pRootSignatureNearest;
|
||||
|
||||
result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateNearest));
|
||||
vertexShaderBlob->Release();
|
||||
pixelShaderBlob->Release();
|
||||
if (result_pipeline_state != S_OK)
|
||||
return false;
|
||||
|
||||
// Create command allocator and command list for ImGui_ImplDX12_UpdateTexture()
|
||||
hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&bd->pTexCmdAllocator));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, bd->pTexCmdAllocator, nullptr, IID_PPV_ARGS(&bd->pTexCmdList));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
hr = bd->pTexCmdList->Close();
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Create fence.
|
||||
hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&bd->Fence));
|
||||
IM_ASSERT(hr == S_OK);
|
||||
bd->FenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
IM_ASSERT(bd->FenceEvent != nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -785,11 +848,27 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return;
|
||||
|
||||
SafeRelease(bd->pdxgiFactory);
|
||||
if (bd->commandQueueOwned)
|
||||
SafeRelease(bd->pCommandQueue);
|
||||
bd->commandQueueOwned = false;
|
||||
SafeRelease(bd->pRootSignature);
|
||||
SafeRelease(bd->pPipelineState);
|
||||
SafeRelease(bd->pRootSignatureLinear);
|
||||
SafeRelease(bd->pRootSignatureNearest);
|
||||
SafeRelease(bd->pPipelineStateLinear);
|
||||
SafeRelease(bd->pPipelineStateNearest);
|
||||
|
||||
if (bd->pTexUploadBufferMapped)
|
||||
{
|
||||
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
|
||||
bd->pTexUploadBuffer->Unmap(0, &range);
|
||||
bd->pTexUploadBufferMapped = nullptr;
|
||||
}
|
||||
SafeRelease(bd->pTexUploadBuffer);
|
||||
SafeRelease(bd->pTexCmdList);
|
||||
SafeRelease(bd->pTexCmdAllocator);
|
||||
SafeRelease(bd->Fence);
|
||||
CloseHandle(bd->FenceEvent);
|
||||
bd->FenceEvent = nullptr;
|
||||
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
@@ -838,18 +917,24 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
|
||||
init_info = &bd->InitInfo;
|
||||
|
||||
bd->pd3dDevice = init_info->Device;
|
||||
IM_ASSERT(init_info->CommandQueue != NULL);
|
||||
IM_ASSERT(init_info->CommandQueue != nullptr);
|
||||
bd->pCommandQueue = init_info->CommandQueue;
|
||||
bd->RTVFormat = init_info->RTVFormat;
|
||||
bd->DSVFormat = init_info->DSVFormat;
|
||||
bd->numFramesInFlight = init_info->NumFramesInFlight;
|
||||
bd->pd3dSrvDescHeap = init_info->SrvDescriptorHeap;
|
||||
bd->tearingSupport = false;
|
||||
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx12";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX12_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX12_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX12_DrawCallback_SetSamplerNearest;
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
if (init_info->SrvDescriptorAllocFn == nullptr)
|
||||
ImGui_ImplDX12_InitLegacySingleDescriptorMode(init_info);
|
||||
@@ -894,6 +979,7 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
|
||||
bool ret = ImGui_ImplDX12_Init(&init_info);
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
bd->commandQueueOwned = true;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures; // Using legacy ImGui_ImplDX12_Init() call with 1 SRV descriptor we cannot support multiple textures.
|
||||
|
||||
@@ -906,14 +992,15 @@ void ImGui_ImplDX12_Shutdown()
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
// Clean up windows and device objects
|
||||
ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
delete[] bd->pFrameResources;
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
@@ -922,7 +1009,7 @@ void ImGui_ImplDX12_NewFrame()
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX12_Init()?");
|
||||
|
||||
if (!bd->pPipelineState)
|
||||
if (!bd->pPipelineStateLinear)
|
||||
if (!ImGui_ImplDX12_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplDX12_CreateDeviceObjects() failed!");
|
||||
}
|
||||
|
||||
@@ -24,6 +24,12 @@
|
||||
#include <dxgiformat.h> // DXGI_FORMAT
|
||||
#include <d3d12.h> // D3D12_CPU_DESCRIPTOR_HANDLE
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#endif
|
||||
|
||||
// Initialization data, for ImGui_ImplDX12_Init()
|
||||
struct ImGui_ImplDX12_InitInfo
|
||||
{
|
||||
@@ -64,7 +70,7 @@ IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
@@ -76,4 +82,8 @@ struct ImGui_ImplDX12_RenderState
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplDX9_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
|
||||
@@ -160,6 +163,11 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplDX9_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplDX9_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); }
|
||||
static void ImGui_ImplDX9_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); }
|
||||
|
||||
// Render function.
|
||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
@@ -182,14 +190,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (device->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
|
||||
if (device->CreateVertexBuffer((UINT)bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (device->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
if (device->CreateIndexBuffer((UINT)bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -267,8 +275,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplDX9_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -323,43 +330,6 @@ static bool ImGui_ImplDX9_CheckFormatSupport(LPDIRECT3DDEVICE9 pDevice, D3DFORMA
|
||||
return support;
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx9";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
|
||||
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDevice->AddRef();
|
||||
bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
||||
static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, const ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
|
||||
{
|
||||
@@ -427,14 +397,15 @@ void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID;
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
||||
backend_tex->Release();
|
||||
if (tex->TexID != ImTextureID_Invalid)
|
||||
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
|
||||
{
|
||||
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
||||
backend_tex->Release();
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
@@ -471,6 +442,50 @@ void ImGui_ImplDX9_NewFrame()
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx9";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplDX9_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplDX9_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplDX9_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDevice->AddRef();
|
||||
bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -31,7 +31,7 @@ IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.)
|
||||
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Multiple Dear ImGui contexts support.
|
||||
// Missing features or Issues:
|
||||
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -29,6 +29,14 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-21: Added a Win32-specific implementation of ImGui_ImplGlfw_GetContentScaleXXXX functions for legacy GLFW 3.2.
|
||||
// 2026-03-25: Mouse cursor is properly restored if changed by user app/code while using glfwSetInputMode(..., GLFW_CURSOR_DISABLED) or ImGuiConfigFlags_NoMouseCursorChange. Amend change from 2025-12-10.
|
||||
// 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225)
|
||||
// 2025-12-12: Added IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND to forcefully disable either.
|
||||
// 2025-12-10: Avoid repeated glfwSetCursor()/glfwSetInputMode() calls when unnecessary. Lowers overhead for very high framerates (e.g. 10k+ FPS).
|
||||
// 2025-11-06: Lower minimum requirement to GLFW 3.0. Though a recent version e.g GLFW 3.4 is highly recommended.
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. FramebufferScale are always reported as 1.0 on X11. (#8920, #8921)
|
||||
// 2025-07-08: Made ImGui_ImplGlfw_GetContentScaleForWindow(), ImGui_ImplGlfw_GetContentScaleForMonitor() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
|
||||
// 2025-06-18: Added support for multiple Dear ImGui contexts. (#8676, #8239, #8069)
|
||||
// 2025-06-11: Added ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window) and ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor) helper to facilitate making DPI-aware apps.
|
||||
@@ -98,26 +106,51 @@
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
|
||||
#endif
|
||||
|
||||
#if defined(__has_include)
|
||||
#if !__has_include(<X11/Xlib.h>) || !__has_include(<X11/extensions/Xrandr.h>)
|
||||
#define IMGUI_IMPL_GLFW_DISABLE_X11
|
||||
#endif
|
||||
#if !__has_include(<wayland-client.h>)
|
||||
#define IMGUI_IMPL_GLFW_DISABLE_WAYLAND
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// GLFW
|
||||
#if !defined(IMGUI_IMPL_GLFW_DISABLE_X11) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
|
||||
#define GLFW_HAS_X11 1
|
||||
#else
|
||||
#define GLFW_HAS_X11 0
|
||||
#endif
|
||||
#if !defined(IMGUI_IMPL_GLFW_DISABLE_WAYLAND) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
|
||||
#define GLFW_HAS_WAYLAND 1
|
||||
#else
|
||||
#define GLFW_HAS_WAYLAND 0
|
||||
#endif
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef APIENTRY
|
||||
#ifndef GLFW_EXPOSE_NATIVE_WIN32
|
||||
#ifndef GLFW_EXPOSE_NATIVE_WIN32 // for glfwGetWin32Window()
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h> // for glfwGetWin32Window()
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#ifndef GLFW_EXPOSE_NATIVE_COCOA
|
||||
#include <GLFW/glfw3native.h>
|
||||
#elif defined(__APPLE__)
|
||||
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
||||
#include <GLFW/glfw3native.h>
|
||||
#elif GLFW_HAS_X11
|
||||
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
#undef Status // X11 headers are leaking this.
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h> // for usleep()
|
||||
#endif
|
||||
@@ -135,6 +168,7 @@
|
||||
|
||||
// We gather version tests as define in order to easily see which features are version-dependent.
|
||||
#define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)
|
||||
#define GLFW_HAS_CREATECURSOR (GLFW_VERSION_COMBINED >= 3100) // 3.1+ glfwCreateCursor()
|
||||
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale
|
||||
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
|
||||
#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
|
||||
@@ -144,25 +178,26 @@
|
||||
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
|
||||
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
|
||||
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
|
||||
#define GLFW_HAS_GETPLATFORM (GLFW_VERSION_COMBINED >= 3400) // 3.4+ glfwGetPlatform()
|
||||
|
||||
// Map GLFWWindow* to ImGuiContext*.
|
||||
// Map GLFWWindow* to ImGuiContext*.
|
||||
// - Would be simpler if we could use glfwSetWindowUserPointer()/glfwGetWindowUserPointer(), but this is a single and shared resource.
|
||||
// - Would be simpler if we could use e.g. std::map<> as well. But we don't.
|
||||
// - This is not particularly optimized as we expect size to be small and queries to be rare.
|
||||
struct ImGui_ImplGlfw_WindowToContext { GLFWwindow* Window; ImGuiContext* Context; };
|
||||
static ImVector<ImGui_ImplGlfw_WindowToContext> g_ContextMap;
|
||||
static void ImGui_ImplGlfw_ContextMap_Add(GLFWwindow* window, ImGuiContext* ctx) { g_ContextMap.push_back(ImGui_ImplGlfw_WindowToContext{ window, ctx }); }
|
||||
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); return; } }
|
||||
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); if (g_ContextMap.empty()) g_ContextMap.clear(); return; } }
|
||||
static ImGuiContext* ImGui_ImplGlfw_ContextMap_Get(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) return entry.Context; return nullptr; }
|
||||
|
||||
// GLFW data
|
||||
enum GlfwClientApi
|
||||
{
|
||||
GlfwClientApi_Unknown,
|
||||
GlfwClientApi_OpenGL,
|
||||
GlfwClientApi_Vulkan,
|
||||
GlfwClientApi_Unknown, // Anything else fits here.
|
||||
};
|
||||
|
||||
// GLFW data
|
||||
struct ImGui_ImplGlfw_Data
|
||||
{
|
||||
ImGuiContext* Context;
|
||||
@@ -170,8 +205,12 @@ struct ImGui_ImplGlfw_Data
|
||||
GlfwClientApi ClientApi;
|
||||
double Time;
|
||||
GLFWwindow* MouseWindow;
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||
GLFWcursor* LastMouseCursor;
|
||||
#endif
|
||||
ImVec2 LastValidMousePos;
|
||||
bool IsWayland;
|
||||
bool InstalledCallbacks;
|
||||
bool CallbacksChainForAllWindows;
|
||||
char BackendPlatformName[32];
|
||||
@@ -216,6 +255,23 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData(GLFWwindow* window)
|
||||
}
|
||||
|
||||
// Functions
|
||||
static bool ImGui_ImplGlfw_IsWayland()
|
||||
{
|
||||
#if !GLFW_HAS_WAYLAND
|
||||
return false;
|
||||
#elif GLFW_HAS_GETPLATFORM
|
||||
return glfwGetPlatform() == GLFW_PLATFORM_WAYLAND;
|
||||
#else
|
||||
const char* version = glfwGetVersionString();
|
||||
if (strstr(version, "Wayland") == nullptr) // e.g. Ubuntu 22.04 ships with GLFW 3.3.6 compiled without Wayland
|
||||
return false;
|
||||
#ifdef GLFW_EXPOSE_NATIVE_X11
|
||||
if (glfwGetX11Display() != nullptr)
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode);
|
||||
@@ -365,7 +421,6 @@ static bool ImGui_ImplGlfw_ShouldChainCallback(ImGui_ImplGlfw_Data* bd, GLFWwind
|
||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||
|
||||
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
||||
|
||||
@@ -411,7 +466,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||
{
|
||||
const char char_names[] = "`-=[]\\,;\'./";
|
||||
const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 };
|
||||
IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys));
|
||||
IM_ASSERT(IM_COUNTOF(char_names) == IM_COUNTOF(char_keys));
|
||||
if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); }
|
||||
else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); }
|
||||
else if (key_name[0] >= 'a' && key_name[0] <= 'z') { key = GLFW_KEY_A + (key_name[0] - 'a'); }
|
||||
@@ -594,7 +649,7 @@ void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)
|
||||
bd->PrevUserCallbackMonitor = nullptr;
|
||||
}
|
||||
|
||||
// Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user.
|
||||
// Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user).
|
||||
// This is 'false' by default meaning we only chain callbacks for the main viewport.
|
||||
// We cannot set this to 'true' by default because user callbacks code may be not testing the 'window' parameter of their callback.
|
||||
// If you set this to 'true' your user callback code will need to make sure you are testing the 'window' parameter.
|
||||
@@ -624,12 +679,15 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
|
||||
bd->Context = ImGui::GetCurrentContext();
|
||||
bd->Window = window;
|
||||
bd->Time = 0.0;
|
||||
bd->IsWayland = ImGui_ImplGlfw_IsWayland();
|
||||
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
@@ -649,6 +707,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
|
||||
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
|
||||
// Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||
bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
|
||||
@@ -667,6 +726,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||
#endif
|
||||
glfwSetErrorCallback(prev_error_callback);
|
||||
#endif
|
||||
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
|
||||
(void)glfwGetError(nullptr);
|
||||
#endif
|
||||
@@ -735,7 +795,9 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
{
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
if (bd->InstalledCallbacks)
|
||||
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
||||
@@ -743,10 +805,10 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
if (bd->CanvasSelector)
|
||||
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
|
||||
#endif
|
||||
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
|
||||
|
||||
#endif
|
||||
// Windows: restore our WndProc hook
|
||||
#ifdef _WIN32
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
@@ -758,6 +820,7 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
ImGui_ImplGlfw_ContextMap_Remove(bd->Window);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
@@ -798,7 +861,10 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
bd->LastMouseCursor = nullptr; // Invalidate so that if user changes underlying cursor we will update it next time we can.
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||
// (those braces are here to reduce diff with multi-viewports support in 'docking' branch)
|
||||
@@ -806,14 +872,25 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||
GLFWwindow* window = bd->Window;
|
||||
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
if (bd->LastMouseCursor != nullptr)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
bd->LastMouseCursor = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
GLFWcursor* cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
|
||||
if (bd->LastMouseCursor != cursor)
|
||||
{
|
||||
glfwSetCursor(window, cursor);
|
||||
bd->LastMouseCursor = cursor;
|
||||
}
|
||||
#endif
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
}
|
||||
@@ -872,11 +949,26 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||
#undef MAP_ANALOG
|
||||
}
|
||||
|
||||
// For GFLW 3.2 + Windows: include a simplified non-monitor aware version of ImGui_ImplWin32_GetDpiScaleForMonitor().
|
||||
// This is merely a band-aid to make using GLFW 3.2 a little bit nicer, but prefer to use GLFW 3.3+ or the full correct functions from the Win32 backend.
|
||||
#if !GLFW_HAS_PER_MONITOR_DPI && defined(_WIN32) && !defined(NOGDI)
|
||||
static float ImGui_ImplWin32_GetLegacyDpiScale() { const HDC dc = ::GetDC(nullptr); UINT xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); ::ReleaseDC(nullptr, dc); return (float)xdpi / 96.0f; }
|
||||
static void glfwGetWindowContentScale(GLFWwindow*, float* x_scale, float* y_scale) { *x_scale = *y_scale = ImGui_ImplWin32_GetLegacyDpiScale(); }
|
||||
static void glfwGetMonitorContentScale(GLFWmonitor*, float* x_scale, float* y_scale) { *x_scale = *y_scale = ImGui_ImplWin32_GetLegacyDpiScale(); }
|
||||
#undef GLFW_HAS_PER_MONITOR_DPI
|
||||
#define GLFW_HAS_PER_MONITOR_DPI 1
|
||||
#endif
|
||||
|
||||
// - On Windows the process needs to be marked DPI-aware!! SDL2 doesn't do it by default. You can call ::SetProcessDPIAware() or call ImGui_ImplWin32_EnableDpiAwareness() from Win32 backend.
|
||||
// - Apple platforms use FramebufferScale so we always return 1.0f.
|
||||
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
|
||||
float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
|
||||
{
|
||||
#if GLFW_HAS_WAYLAND
|
||||
if (ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window))
|
||||
if (bd->IsWayland)
|
||||
return 1.0f;
|
||||
#endif
|
||||
#if GLFW_HAS_PER_MONITOR_DPI && !(defined(__APPLE__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__))
|
||||
float x_scale, y_scale;
|
||||
glfwGetWindowContentScale(window, &x_scale, &y_scale);
|
||||
@@ -889,6 +981,10 @@ float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
|
||||
|
||||
float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor)
|
||||
{
|
||||
#if GLFW_HAS_WAYLAND
|
||||
if (ImGui_ImplGlfw_IsWayland()) // We can't access our bd->IsWayland cache for a monitor.
|
||||
return 1.0f;
|
||||
#endif
|
||||
#if GLFW_HAS_PER_MONITOR_DPI && !(defined(__APPLE__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__))
|
||||
float x_scale, y_scale;
|
||||
glfwGetMonitorContentScale(monitor, &x_scale, &y_scale);
|
||||
@@ -905,10 +1001,17 @@ static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window,
|
||||
int display_w, display_h;
|
||||
glfwGetWindowSize(window, &w, &h);
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
|
||||
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
|
||||
#if GLFW_HAS_WAYLAND
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||
if (!bd->IsWayland)
|
||||
fb_scale_x = fb_scale_y = 1.0f;
|
||||
#endif
|
||||
if (out_size != nullptr)
|
||||
*out_size = ImVec2((float)w, (float)h);
|
||||
if (out_framebuffer_scale != nullptr)
|
||||
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
|
||||
*out_framebuffer_scale = ImVec2(fb_scale_x, fb_scale_y);
|
||||
}
|
||||
|
||||
void ImGui_ImplGlfw_NewFrame()
|
||||
@@ -924,7 +1027,7 @@ void ImGui_ImplGlfw_NewFrame()
|
||||
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
|
||||
double current_time = glfwGetTime();
|
||||
if (current_time <= bd->Time)
|
||||
current_time = bd->Time + 0.00001f;
|
||||
current_time = bd->Time + 0.00001;
|
||||
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Multiple Dear ImGui contexts support.
|
||||
// Missing features or Issues:
|
||||
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -47,7 +48,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* wi
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
|
||||
|
||||
// GFLW callbacks options:
|
||||
// GLFW callbacks options:
|
||||
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -39,7 +41,7 @@ IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData,
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif
|
||||
@@ -67,7 +69,7 @@ IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -16,9 +18,14 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
|
||||
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
|
||||
// 2026-04-03: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplMetal_RenderDrawData() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture().
|
||||
// 2025-02-03: Metal: Crash fix. (#8367)
|
||||
// 2024-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419).
|
||||
// 2025-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419).
|
||||
// 2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'.
|
||||
// 2022-07-05: Metal: Add dispatch synchronization.
|
||||
// 2022-06-30: Metal: Use __bridge for ARC based systems.
|
||||
@@ -75,6 +82,7 @@
|
||||
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor; // framebuffer descriptor for current frame; transient
|
||||
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
|
||||
@property (nonatomic, strong) NSMutableArray<MetalBuffer*>* bufferCache;
|
||||
@property (nonatomic, strong) NSObject* bufferCacheLock;
|
||||
@property (nonatomic, assign) double lastBufferCachePurge;
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device;
|
||||
@@ -125,38 +133,6 @@ bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
|
||||
|
||||
#pragma mark - Dear ImGui Metal Backend API
|
||||
|
||||
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_metal";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||
bd->SharedMetalContext.device = device;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_Shutdown()
|
||||
{
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
IM_UNUSED(bd);
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
ImGui_ImplMetal_DestroyBackendData();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor)
|
||||
{
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
@@ -210,10 +186,12 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
|
||||
|
||||
[commandEncoder setRenderPipelineState:renderPipelineState];
|
||||
|
||||
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
|
||||
[commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
|
||||
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:vertexBufferOffset atIndex:0];
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
|
||||
// Metal Render function.
|
||||
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
|
||||
{
|
||||
@@ -270,8 +248,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplMetal_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, vertexBufferOffset);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -285,8 +262,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
||||
// Clamp to viewport as setScissorRect() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
if (pcmd->ElemCount == 0) // drawIndexedPrimitives() validation doesn't accept this
|
||||
@@ -303,7 +280,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
||||
[commandEncoder setScissorRect:scissorRect];
|
||||
|
||||
// Bind texture, Draw
|
||||
if (ImTextureID tex_id = pcmd->GetTexID())
|
||||
ImTextureID tex_id = pcmd->GetTexID();
|
||||
if (tex_id != ImTextureID_Invalid)
|
||||
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(void*)(intptr_t)(tex_id) atIndex:0];
|
||||
|
||||
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
|
||||
@@ -322,28 +300,26 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
||||
MetalContext* sharedMetalContext = bd->SharedMetalContext;
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
@synchronized(sharedMetalContext.bufferCache)
|
||||
{
|
||||
[sharedMetalContext.bufferCache addObject:vertexBuffer];
|
||||
[sharedMetalContext.bufferCache addObject:indexBuffer];
|
||||
}
|
||||
});
|
||||
@synchronized(sharedMetalContext.bufferCacheLock)
|
||||
{
|
||||
[sharedMetalContext.bufferCache addObject:vertexBuffer];
|
||||
[sharedMetalContext.bufferCache addObject:indexBuffer];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData);
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
|
||||
backend_tex.metalTexture = nil;
|
||||
if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
|
||||
{
|
||||
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
|
||||
backend_tex.metalTexture = nil;
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_UpdateTexture(ImTextureData* tex)
|
||||
@@ -425,6 +401,44 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
ImGui_ImplMetal_Data* bd = IM_NEW(ImGui_ImplMetal_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_metal";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal_DrawCallback_ResetRenderState;
|
||||
|
||||
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||
bd->SharedMetalContext.device = device;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal_Shutdown()
|
||||
{
|
||||
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
|
||||
IM_UNUSED(bd);
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplMetal_DestroyDeviceObjects();
|
||||
ImGui_ImplMetal_DestroyBackendData();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
}
|
||||
|
||||
#pragma mark - MetalBuffer implementation
|
||||
|
||||
@implementation MetalBuffer
|
||||
@@ -508,6 +522,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
{
|
||||
self.renderPipelineStateCache = [NSMutableDictionary dictionary];
|
||||
self.bufferCache = [NSMutableArray array];
|
||||
self.bufferCacheLock = [[NSObject alloc] init];
|
||||
_lastBufferCachePurge = GetMachAbsoluteTimeInSeconds();
|
||||
}
|
||||
return self;
|
||||
@@ -515,9 +530,9 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
|
||||
{
|
||||
uint64_t now = GetMachAbsoluteTimeInSeconds();
|
||||
double now = GetMachAbsoluteTimeInSeconds();
|
||||
|
||||
@synchronized(self.bufferCache)
|
||||
@synchronized(self.bufferCacheLock)
|
||||
{
|
||||
// Purge old buffers that haven't been useful for a while
|
||||
if (now - self.lastBufferCachePurge > 1.0)
|
||||
|
||||
102
backends/imgui_impl_null.cpp
Normal file
102
backends/imgui_impl_null.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// dear imgui: Null Platform+Renderer Backends
|
||||
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-11-17: Initial version.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_null.h"
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
||||
#endif
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplNull_Init()
|
||||
{
|
||||
ImGui_ImplNullPlatform_Init();
|
||||
ImGui_ImplNullRender_Init();
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown()
|
||||
{
|
||||
ImGui_ImplNullRender_Shutdown();
|
||||
ImGui_ImplNullPlatform_Shutdown();
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame()
|
||||
{
|
||||
ImGui_ImplNullPlatform_NewFrame();
|
||||
ImGui_ImplNullRender_NewFrame();
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasMouseCursors;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2(1920, 1080);
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
|
||||
return true;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures;
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame()
|
||||
{
|
||||
}
|
||||
|
||||
static void ImGui_ImplNullRender_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantDestroy)
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplNullRender_UpdateTexture(tex);
|
||||
}
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
34
backends/imgui_impl_null.h
Normal file
34
backends/imgui_impl_null.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// dear imgui: Null Platform+Renderer Backends
|
||||
// This is designed if you need to use a blind Dear Imgui context with no input and no output.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
|
||||
// Null = NullPlatform + NullRender
|
||||
IMGUI_IMPL_API bool ImGui_ImplNull_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplNull_NewFrame();
|
||||
|
||||
// Null platform only (single screen, fixed timestep, no inputs)
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullPlatform_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullPlatform_NewFrame();
|
||||
|
||||
// Null renderer only (no output)
|
||||
IMGUI_IMPL_API bool ImGui_ImplNullRender_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplNullRender_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -6,6 +6,7 @@
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [ ] Renderer: Use of DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest is emulated by poking to glTexParameter(), as legacy OpenGL doesn't have glBindSampler().
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -25,6 +26,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802)
|
||||
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture().
|
||||
// 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
@@ -84,6 +88,9 @@
|
||||
// OpenGL data
|
||||
struct ImGui_ImplOpenGL2_Data
|
||||
{
|
||||
bool UseTexParameterToSetSampler;
|
||||
GLuint NextSampler;
|
||||
|
||||
ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
@@ -95,34 +102,6 @@ static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL2_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_opengl2";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_NewFrame()
|
||||
{
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
@@ -133,6 +112,7 @@ void ImGui_ImplOpenGL2_NewFrame()
|
||||
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
|
||||
{
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
|
||||
@@ -150,6 +130,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
bd->NextSampler = GL_LINEAR;
|
||||
|
||||
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
||||
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
|
||||
@@ -174,12 +155,18 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
|
||||
|
||||
// OpenGL2 Render function.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
||||
// This is in order to be able to run within an OpenGL engine that doesn't do so.
|
||||
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
@@ -223,8 +210,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplOpenGL2_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -241,7 +227,17 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
|
||||
GLuint pcmd_texture = (GLuint)(intptr_t)pcmd->GetTexID();
|
||||
glBindTexture(GL_TEXTURE_2D, pcmd_texture);
|
||||
|
||||
// Emulate sampler change (even though it is technically part of texture data)
|
||||
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
|
||||
if (bd->UseTexParameterToSetSampler)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
|
||||
}
|
||||
}
|
||||
@@ -270,7 +266,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
const void* pixels = tex->GetPixels();
|
||||
GLuint gl_texture_id = 0;
|
||||
@@ -339,6 +335,42 @@ void ImGui_ImplOpenGL2_DestroyDeviceObjects()
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_Init()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_opengl2";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL2_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [ ] Renderer: Use of DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest is emulated by poking to glTexParameter(), as legacy OpenGL doesn't have glBindSampler().
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -37,7 +38,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792)
|
||||
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures (#8802) + restore non-WebGL/ES update path that doesn't require a CPU-side copy.
|
||||
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL3_CreateFontsTexture() and ImGui_ImplOpenGL3_DestroyFontsTexture().
|
||||
@@ -39,7 +43,7 @@
|
||||
// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
|
||||
// 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333)
|
||||
// 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224)
|
||||
// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530)
|
||||
// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns nullptr. (#6154, #4445, #3530)
|
||||
// 2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224)
|
||||
// 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes).
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
@@ -246,8 +250,13 @@ struct ImGui_ImplOpenGL3_Data
|
||||
GLsizeiptr VertexBufferSize;
|
||||
GLsizeiptr IndexBufferSize;
|
||||
bool HasPolygonMode;
|
||||
bool HasBindSampler;
|
||||
bool HasClipOrigin;
|
||||
bool UseBufferSubData;
|
||||
bool UseTexParameterToSetSampler;
|
||||
GLuint NextSampler; // Used if !HasBindSampler && UseTexParameterToSetSampler.
|
||||
GLuint TexSamplers[2]; // Used if IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER && HasBindSimpler (0=linear, 1=nearest).
|
||||
|
||||
ImVector<char> TempBuffer;
|
||||
|
||||
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
@@ -288,7 +297,8 @@ struct ImGui_ImplOpenGL3_VtxAttribState
|
||||
bool ImGui_ImplOpenGL3_InitLoader();
|
||||
bool ImGui_ImplOpenGL3_InitLoader()
|
||||
{
|
||||
// Initialize our loader
|
||||
// Lazily initialize our loader if not already done
|
||||
// (to facilitate handling multiple DLL boundaries and multiple context shutdowns we call this from all main entry points)
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
if (glGetIntegerv == nullptr && imgl3wInit() != 0)
|
||||
{
|
||||
@@ -299,143 +309,20 @@ bool ImGui_ImplOpenGL3_InitLoader()
|
||||
return true;
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||
static void ImGui_ImplOpenGL3_ShutdownLoader()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Initialize loader
|
||||
if (!ImGui_ImplOpenGL3_InitLoader())
|
||||
return false;
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_opengl3";
|
||||
|
||||
// Query for GL version (e.g. 320 for GL 3.2)
|
||||
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GLES 2
|
||||
bd->GlVersion = 200;
|
||||
bd->GlProfileIsES2 = true;
|
||||
IM_UNUSED(gl_version_str);
|
||||
#else
|
||||
// Desktop or GLES 3
|
||||
GLint major = 0;
|
||||
GLint minor = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
if (major == 0 && minor == 0)
|
||||
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &bd->MaxTextureSize);
|
||||
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
bd->GlProfileIsES3 = true;
|
||||
#else
|
||||
if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
|
||||
bd->GlProfileIsES3 = true;
|
||||
#endif
|
||||
|
||||
#if defined(GL_CONTEXT_PROFILE_MASK)
|
||||
if (!bd->GlProfileIsES3 && bd->GlVersion >= 320)
|
||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
|
||||
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
|
||||
#endif
|
||||
|
||||
bd->UseBufferSubData = false;
|
||||
/*
|
||||
// Query vendor to enable glBufferSubData kludge
|
||||
#ifdef _WIN32
|
||||
if (const char* vendor = (const char*)glGetString(GL_VENDOR))
|
||||
if (strncmp(vendor, "Intel", 5) == 0)
|
||||
bd->UseBufferSubData = true;
|
||||
#endif
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_DEBUG
|
||||
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2/IsEs3 = %d/%d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
|
||||
#endif
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||
if (bd->GlVersion >= 320)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = (int)bd->MaxTextureSize;
|
||||
|
||||
// Store GLSL version string so we can refer to it later in case we recreate shaders.
|
||||
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
|
||||
if (glsl_version == nullptr)
|
||||
{
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
glsl_version = "#version 100";
|
||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
glsl_version = "#version 300 es";
|
||||
#elif defined(__APPLE__)
|
||||
glsl_version = "#version 150";
|
||||
#else
|
||||
glsl_version = "#version 130";
|
||||
#endif
|
||||
}
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
|
||||
strcpy(bd->GlslVersionString, glsl_version);
|
||||
strcat(bd->GlslVersionString, "\n");
|
||||
|
||||
// Make an arbitrary GL call (we don't actually need the result)
|
||||
// IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
|
||||
GLint current_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
|
||||
|
||||
// Detect extensions we support
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
|
||||
#endif
|
||||
bd->HasClipOrigin = (bd->GlVersion >= 450);
|
||||
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
|
||||
GLint num_extensions = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
|
||||
for (GLint i = 0; i < num_extensions; i++)
|
||||
{
|
||||
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0)
|
||||
bd->HasClipOrigin = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
IM_DELETE(bd);
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
imgl3wShutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Functions
|
||||
void ImGui_ImplOpenGL3_NewFrame()
|
||||
{
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
if (!bd->ShaderHandle)
|
||||
if (!ImGui_ImplOpenGL3_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
||||
@@ -495,8 +382,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
|
||||
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
||||
if (bd->HasBindSampler)
|
||||
glBindSampler(0, bd->TexSamplers[0]); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
||||
#endif
|
||||
|
||||
(void)vertex_array_object;
|
||||
@@ -515,6 +402,11 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col)));
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[0]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; } }
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[1]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; } }
|
||||
|
||||
// OpenGL3 Render function.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
||||
// This is in order to be able to run within an OpenGL engine that doesn't do so.
|
||||
@@ -526,7 +418,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
||||
@@ -543,7 +435,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
|
||||
GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
|
||||
GLuint last_sampler; if (bd->HasBindSampler) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
|
||||
#endif
|
||||
GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
|
||||
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||
@@ -629,8 +521,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplOpenGL3_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -648,6 +539,15 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
// Bind texture, Draw
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
|
||||
|
||||
// Emulate sampler change (even though it is technically part of texture data)
|
||||
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
|
||||
if (!bd->HasBindSampler && bd->UseTexParameterToSetSampler)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
|
||||
}
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||
if (bd->GlVersion >= 320)
|
||||
GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset));
|
||||
@@ -668,7 +568,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
|
||||
if (bd->HasBindSampler)
|
||||
glBindSampler(0, last_sampler);
|
||||
#endif
|
||||
glActiveTexture(last_active_texture);
|
||||
@@ -730,7 +630,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
const void* pixels = tex->GetPixels();
|
||||
GLuint gl_texture_id = 0;
|
||||
@@ -829,6 +729,7 @@ static bool CheckProgram(GLuint handle, const char* desc)
|
||||
|
||||
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
||||
// Backup GL state
|
||||
@@ -1012,6 +913,20 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
glGenBuffers(1, &bd->VboHandle);
|
||||
glGenBuffers(1, &bd->ElementsHandle);
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
if (bd->HasBindSampler)
|
||||
{
|
||||
glGenSamplers(2, &bd->TexSamplers[0]);
|
||||
for (int sampler_n = 0; sampler_n < 2; sampler_n++)
|
||||
{
|
||||
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_MIN_FILTER, (sampler_n == 0) ? GL_LINEAR : GL_NEAREST));
|
||||
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_MAG_FILTER, (sampler_n == 0) ? GL_LINEAR : GL_NEAREST));
|
||||
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glSamplerParameteri(bd->TexSamplers[sampler_n], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Restore modified GL state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
@@ -1027,7 +942,9 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
|
||||
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
if (bd->TexSamplers[0]) { glDeleteSamplers(2, &bd->TexSamplers[0]); bd->TexSamplers[0] = bd->TexSamplers[1] = 0; }
|
||||
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
|
||||
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
|
||||
if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
|
||||
@@ -1038,6 +955,142 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||
ImGui_ImplOpenGL3_DestroyTexture(tex);
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Initialize loader
|
||||
if (!ImGui_ImplOpenGL3_InitLoader())
|
||||
return false;
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_opengl3";
|
||||
|
||||
// Query for GL version (e.g. 320 for GL 3.2)
|
||||
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GLES 2
|
||||
bd->GlVersion = 200;
|
||||
bd->GlProfileIsES2 = true;
|
||||
IM_UNUSED(gl_version_str);
|
||||
#else
|
||||
// Desktop or GLES 3
|
||||
GLint major = 0;
|
||||
GLint minor = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
if (major == 0 && minor == 0)
|
||||
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &bd->MaxTextureSize);
|
||||
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
bd->GlProfileIsES3 = true;
|
||||
#else
|
||||
if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
|
||||
bd->GlProfileIsES3 = true;
|
||||
#endif
|
||||
|
||||
#if defined(GL_CONTEXT_PROFILE_MASK)
|
||||
if (!bd->GlProfileIsES3 && bd->GlVersion >= 320)
|
||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
|
||||
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
|
||||
#endif
|
||||
|
||||
bd->UseBufferSubData = false;
|
||||
/*
|
||||
// Query vendor to enable glBufferSubData kludge
|
||||
#ifdef _WIN32
|
||||
if (const char* vendor = (const char*)glGetString(GL_VENDOR))
|
||||
if (strncmp(vendor, "Intel", 5) == 0)
|
||||
bd->UseBufferSubData = true;
|
||||
#endif
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_DEBUG
|
||||
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2/IsEs3 = %d/%d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
|
||||
#endif
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||
if (bd->GlVersion >= 320)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = (int)bd->MaxTextureSize;
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest;
|
||||
|
||||
// Store GLSL version string so we can refer to it later in case we recreate shaders.
|
||||
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
|
||||
if (glsl_version == nullptr)
|
||||
{
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
glsl_version = "#version 100";
|
||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
glsl_version = "#version 300 es";
|
||||
#elif defined(__APPLE__)
|
||||
glsl_version = "#version 150";
|
||||
#else
|
||||
glsl_version = "#version 130";
|
||||
#endif
|
||||
}
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
|
||||
strcpy(bd->GlslVersionString, glsl_version);
|
||||
strcat(bd->GlslVersionString, "\n");
|
||||
|
||||
// Make an arbitrary GL call (we don't actually need the result)
|
||||
// IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
|
||||
GLint current_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
|
||||
|
||||
// Detect extensions we support
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
|
||||
#endif
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
bd->HasBindSampler = (bd->GlVersion >= 330 || bd->GlProfileIsES3);
|
||||
#endif
|
||||
bd->HasClipOrigin = (bd->GlVersion >= 450);
|
||||
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
|
||||
GLint num_extensions = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
|
||||
for (GLint i = 0; i < num_extensions; i++)
|
||||
{
|
||||
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0)
|
||||
bd->HasClipOrigin = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
|
||||
ImGui_ImplOpenGL3_ShutdownLoader();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
@@ -40,7 +40,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// Configuration flags to add in your imconfig file:
|
||||
|
||||
@@ -180,6 +180,7 @@ typedef khronos_uint8_t GLubyte;
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
@@ -400,9 +401,15 @@ GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum
|
||||
#ifndef GL_VERSION_3_3
|
||||
#define GL_VERSION_3_3 1
|
||||
#define GL_SAMPLER_BINDING 0x8919
|
||||
typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
|
||||
typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
|
||||
GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
|
||||
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
|
||||
GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_3 */
|
||||
#ifndef GL_VERSION_4_1
|
||||
@@ -483,7 +490,7 @@ GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
|
||||
|
||||
/* gl3w internal state */
|
||||
union ImGL3WProcs {
|
||||
GL3WglProc ptr[60];
|
||||
GL3WglProc ptr[63];
|
||||
struct {
|
||||
PFNGLACTIVETEXTUREPROC ActiveTexture;
|
||||
PFNGLATTACHSHADERPROC AttachShader;
|
||||
@@ -503,6 +510,7 @@ union ImGL3WProcs {
|
||||
PFNGLCREATESHADERPROC CreateShader;
|
||||
PFNGLDELETEBUFFERSPROC DeleteBuffers;
|
||||
PFNGLDELETEPROGRAMPROC DeleteProgram;
|
||||
PFNGLDELETESAMPLERSPROC DeleteSamplers;
|
||||
PFNGLDELETESHADERPROC DeleteShader;
|
||||
PFNGLDELETETEXTURESPROC DeleteTextures;
|
||||
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
|
||||
@@ -515,6 +523,7 @@ union ImGL3WProcs {
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
|
||||
PFNGLFLUSHPROC Flush;
|
||||
PFNGLGENBUFFERSPROC GenBuffers;
|
||||
PFNGLGENSAMPLERSPROC GenSamplers;
|
||||
PFNGLGENTEXTURESPROC GenTextures;
|
||||
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
|
||||
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
|
||||
@@ -535,6 +544,7 @@ union ImGL3WProcs {
|
||||
PFNGLPIXELSTOREIPROC PixelStorei;
|
||||
PFNGLPOLYGONMODEPROC PolygonMode;
|
||||
PFNGLREADPIXELSPROC ReadPixels;
|
||||
PFNGLSAMPLERPARAMETERIPROC SamplerParameteri;
|
||||
PFNGLSCISSORPROC Scissor;
|
||||
PFNGLSHADERSOURCEPROC ShaderSource;
|
||||
PFNGLTEXIMAGE2DPROC TexImage2D;
|
||||
@@ -569,6 +579,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
||||
#define glCreateShader imgl3wProcs.gl.CreateShader
|
||||
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
|
||||
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
|
||||
#define glDeleteSamplers imgl3wProcs.gl.DeleteSamplers
|
||||
#define glDeleteShader imgl3wProcs.gl.DeleteShader
|
||||
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
|
||||
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
|
||||
@@ -581,6 +592,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
||||
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
|
||||
#define glFlush imgl3wProcs.gl.Flush
|
||||
#define glGenBuffers imgl3wProcs.gl.GenBuffers
|
||||
#define glGenSamplers imgl3wProcs.gl.GenSamplers
|
||||
#define glGenTextures imgl3wProcs.gl.GenTextures
|
||||
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
|
||||
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
|
||||
@@ -601,6 +613,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
||||
#define glPixelStorei imgl3wProcs.gl.PixelStorei
|
||||
#define glPolygonMode imgl3wProcs.gl.PolygonMode
|
||||
#define glReadPixels imgl3wProcs.gl.ReadPixels
|
||||
#define glSamplerParameteri imgl3wProcs.gl.SamplerParameteri
|
||||
#define glScissor imgl3wProcs.gl.Scissor
|
||||
#define glShaderSource imgl3wProcs.gl.ShaderSource
|
||||
#define glTexImage2D imgl3wProcs.gl.TexImage2D
|
||||
@@ -701,7 +714,11 @@ static void close_libgl(void)
|
||||
|
||||
static int is_library_loaded(const char* name, void** lib)
|
||||
{
|
||||
#if defined(__HAIKU__)
|
||||
*lib = NULL; // no support for RTLD_NOLOAD on Haiku.
|
||||
#else
|
||||
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||
#endif
|
||||
return *lib != NULL;
|
||||
}
|
||||
|
||||
@@ -819,6 +836,7 @@ static int parse_version(void)
|
||||
}
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc);
|
||||
static void clear_procs();
|
||||
|
||||
int imgl3wInit(void)
|
||||
{
|
||||
@@ -838,6 +856,7 @@ int imgl3wInit2(GL3WGetProcAddressProc proc)
|
||||
void imgl3wShutdown(void)
|
||||
{
|
||||
close_libgl();
|
||||
clear_procs();
|
||||
}
|
||||
|
||||
int imgl3wIsSupported(int major, int minor)
|
||||
@@ -870,6 +889,7 @@ static const char *proc_names[] = {
|
||||
"glCreateShader",
|
||||
"glDeleteBuffers",
|
||||
"glDeleteProgram",
|
||||
"glDeleteSamplers",
|
||||
"glDeleteShader",
|
||||
"glDeleteTextures",
|
||||
"glDeleteVertexArrays",
|
||||
@@ -882,6 +902,7 @@ static const char *proc_names[] = {
|
||||
"glEnableVertexAttribArray",
|
||||
"glFlush",
|
||||
"glGenBuffers",
|
||||
"glGenSamplers",
|
||||
"glGenTextures",
|
||||
"glGenVertexArrays",
|
||||
"glGetAttribLocation",
|
||||
@@ -902,6 +923,7 @@ static const char *proc_names[] = {
|
||||
"glPixelStorei",
|
||||
"glPolygonMode",
|
||||
"glReadPixels",
|
||||
"glSamplerParameteri",
|
||||
"glScissor",
|
||||
"glShaderSource",
|
||||
"glTexImage2D",
|
||||
@@ -923,6 +945,13 @@ static void load_procs(GL3WGetProcAddressProc proc)
|
||||
imgl3wProcs.ptr[i] = proc(proc_names[i]);
|
||||
}
|
||||
|
||||
static void clear_procs()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = nullptr;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-06-27: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-06-12: ImGui_ImplOSX_HandleEvent() only process event for window containing our view. (#8644)
|
||||
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
|
||||
@@ -147,9 +148,11 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view);
|
||||
NSWindow* window = view.window;
|
||||
if (!window)
|
||||
return;
|
||||
NSRect contentRect = [window contentRectForFrameRect:window.frame];
|
||||
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
|
||||
_imeRect = [window convertRectToScreen:rect];
|
||||
{
|
||||
NSRect contentRect = [window contentRectForFrameRect:window.frame];
|
||||
NSRect rect = NSMakeRect(_posX, contentRect.size.height - _posY, 0, 0);
|
||||
_imeRect = [window convertRectToScreen:rect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
@@ -514,9 +517,12 @@ void ImGui_ImplOSX_Shutdown()
|
||||
ImGui_ImplOSX_DestroyBackendData();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
}
|
||||
|
||||
static void ImGui_ImplOSX_UpdateMouseCursor()
|
||||
@@ -625,9 +631,9 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
|
||||
// Setup display size
|
||||
if (view)
|
||||
{
|
||||
const float dpi = (float)[view.window backingScaleFactor];
|
||||
const float fb_scale = (float)[view.window backingScaleFactor];
|
||||
io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height);
|
||||
io.DisplayFramebufferScale = ImVec2(dpi, dpi);
|
||||
io.DisplayFramebufferScale = ImVec2(fb_scale, fb_scale);
|
||||
}
|
||||
|
||||
// Setup time step
|
||||
|
||||
@@ -21,12 +21,18 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369)
|
||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_MOUSEMOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. (#8921)
|
||||
// 2025-07-08: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
|
||||
// 2025-06-11: Added ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window) and ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index) helper to facilitate making DPI-aware apps.
|
||||
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
|
||||
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
|
||||
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
||||
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650)
|
||||
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650)
|
||||
// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode.
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler.
|
||||
@@ -137,7 +143,7 @@
|
||||
struct ImGui_ImplSDL2_Data
|
||||
{
|
||||
SDL_Window* Window;
|
||||
Uint32 WindowID;
|
||||
Uint32 WindowID; // Stored in ImGuiViewport::PlatformHandle. Use SDL_GetWindowFromID() to get SDL_Window* from Uint32 WindowID.
|
||||
SDL_Renderer* Renderer;
|
||||
Uint64 Time;
|
||||
char* ClipboardTextData;
|
||||
@@ -150,7 +156,7 @@ struct ImGui_ImplSDL2_Data
|
||||
SDL_Cursor* MouseLastCursor;
|
||||
int MouseLastLeaveFrame;
|
||||
bool MouseCanUseGlobalState;
|
||||
bool MouseCanUseCapture;
|
||||
ImGui_ImplSDL2_MouseCaptureMode MouseCaptureMode;
|
||||
|
||||
// Gamepad handling
|
||||
ImVector<SDL_GameController*> Gamepads;
|
||||
@@ -175,7 +181,10 @@ static const char* ImGui_ImplSDL2_GetClipboardText(ImGuiContext*)
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||
if (SDL_HasClipboardText())
|
||||
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||
else
|
||||
bd->ClipboardTextData = nullptr;
|
||||
return bd->ClipboardTextData;
|
||||
}
|
||||
|
||||
@@ -365,7 +374,6 @@ static ImGuiViewport* ImGui_ImplSDL2_GetViewportForWindowID(Uint32 window_id)
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
|
||||
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
@@ -459,7 +467,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||
bd->MouseLastLeaveFrame = ImGui::GetFrameCount() + 1;
|
||||
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
|
||||
io.AddFocusEvent(true);
|
||||
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
|
||||
if (window_event == SDL_WINDOWEVENT_FOCUS_LOST)
|
||||
io.AddFocusEvent(false);
|
||||
return true;
|
||||
}
|
||||
@@ -484,6 +492,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
||||
|
||||
// Obtain compiled and runtime versions
|
||||
SDL_version ver_compiled;
|
||||
@@ -507,13 +516,16 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
bd->MouseCanUseGlobalState = false;
|
||||
bd->MouseCanUseCapture = false;
|
||||
bd->MouseCaptureMode = ImGui_ImplSDL2_MouseCaptureMode_Disabled;
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
for (const char* item : capture_and_global_state_whitelist)
|
||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
||||
bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true;
|
||||
{
|
||||
bd->MouseCanUseGlobalState = true;
|
||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL2_MouseCaptureMode_Enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
@@ -628,6 +640,7 @@ void ImGui_ImplSDL2_Shutdown()
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
@@ -638,9 +651,18 @@ void ImGui_ImplSDL2_Shutdown()
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_SetMouseCaptureMode(ImGui_ImplSDL2_MouseCaptureMode mode)
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
if (mode == ImGui_ImplSDL2_MouseCaptureMode_Disabled && bd->MouseCaptureMode != ImGui_ImplSDL2_MouseCaptureMode_Disabled)
|
||||
SDL_CaptureMouse(SDL_FALSE);
|
||||
bd->MouseCaptureMode = mode;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMouseData()
|
||||
{
|
||||
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
|
||||
@@ -649,8 +671,12 @@ static void ImGui_ImplSDL2_UpdateMouseData()
|
||||
// We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
// - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside.
|
||||
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture.
|
||||
if (bd->MouseCanUseCapture)
|
||||
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue on X11 we we wait until mouse has moved to begin capture.
|
||||
if (bd->MouseCaptureMode == ImGui_ImplSDL2_MouseCaptureMode_Enabled)
|
||||
{
|
||||
SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
else if (bd->MouseCaptureMode == ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag)
|
||||
{
|
||||
bool want_capture = false;
|
||||
for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++)
|
||||
@@ -662,6 +688,7 @@ static void ImGui_ImplSDL2_UpdateMouseData()
|
||||
SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||
const bool is_app_focused = (bd->Window == focused_window);
|
||||
#else
|
||||
SDL_Window* focused_window = bd->Window;
|
||||
const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
|
||||
#endif
|
||||
if (is_app_focused)
|
||||
@@ -670,15 +697,20 @@ static void ImGui_ImplSDL2_UpdateMouseData()
|
||||
if (io.WantSetMousePos)
|
||||
SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
|
||||
|
||||
// (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
|
||||
// (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_MOUSEMOTION already provides this when hovered or captured)
|
||||
// Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature.
|
||||
SDL_Window* hovered_window = SDL_GetMouseFocus();
|
||||
const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0;
|
||||
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
|
||||
if (hovered_window == nullptr && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
|
||||
{
|
||||
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
|
||||
int window_x, window_y, mouse_x_global, mouse_y_global;
|
||||
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
|
||||
SDL_GetWindowPosition(bd->Window, &window_x, &window_y);
|
||||
io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
|
||||
int mouse_x, mouse_y;
|
||||
int window_x, window_y;
|
||||
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
|
||||
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
|
||||
mouse_x -= window_x;
|
||||
mouse_y -= window_y;
|
||||
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,13 +749,21 @@ float ImGui_ImplSDL2_GetContentScaleForWindow(SDL_Window* window)
|
||||
return ImGui_ImplSDL2_GetContentScaleForDisplay(SDL_GetWindowDisplayIndex(window));
|
||||
}
|
||||
|
||||
// SDL_GetDisplayDPI() seems rather unreliable on Linux.
|
||||
float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_index)
|
||||
{
|
||||
const char* sdl_driver = SDL_GetCurrentVideoDriver();
|
||||
if (sdl_driver && strcmp(sdl_driver, "wayland") == 0)
|
||||
return 1.0f;
|
||||
#if SDL_HAS_PER_MONITOR_DPI
|
||||
#if !defined(__APPLE__) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__)
|
||||
float dpi = 0.0f;
|
||||
if (SDL_GetDisplayDPI(display_index, &dpi, nullptr, nullptr) == 0)
|
||||
{
|
||||
if (dpi < 96.0f)
|
||||
dpi = 96.0f;
|
||||
return dpi / 96.0f;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
IM_UNUSED(display_index);
|
||||
@@ -850,7 +890,7 @@ static void ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(SDL_Window* window,
|
||||
if (out_size != nullptr)
|
||||
*out_size = ImVec2((float)w, (float)h);
|
||||
if (out_framebuffer_scale != nullptr)
|
||||
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / w, (float)display_h / h) : ImVec2(1.0f, 1.0f);
|
||||
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL2_NewFrame()
|
||||
@@ -868,7 +908,7 @@ void ImGui_ImplSDL2_NewFrame()
|
||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||
if (current_time <= bd->Time)
|
||||
current_time = bd->Time + 1;
|
||||
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
|
||||
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / (double)frequency) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
if (bd->MouseLastLeaveFrame && bd->MouseLastLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
|
||||
|
||||
@@ -47,4 +47,11 @@ IMGUI_IMPL_API float ImGui_ImplSDL2_GetContentScaleForDisplay(int display_ind
|
||||
enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
|
||||
|
||||
// (Advanced, for X11 users) Override Mouse Capture mode. Mouse capture allows receiving updated mouse position after clicking inside our window and dragging outside it.
|
||||
// Having this 'Enabled' is in theory always better. But, on X11 if you crash/break to debugger while capture is active you may temporarily lose access to your mouse.
|
||||
// The best solution is to setup your debugger to automatically release capture, e.g. 'setxkbmap -option grab:break_actions && xdotool key XF86Ungrab' or via a GDB script. See #3650.
|
||||
// But you may independently decide on X11, when a debugger is attached, to set this value to ImGui_ImplSDL2_MouseCaptureMode_Disabled.
|
||||
enum ImGui_ImplSDL2_MouseCaptureMode { ImGui_ImplSDL2_MouseCaptureMode_Enabled, ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag, ImGui_ImplSDL2_MouseCaptureMode_Disabled };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL2_SetMouseCaptureMode(ImGui_ImplSDL2_MouseCaptureMode mode);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -20,13 +20,20 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL3_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||
// 2025-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
|
||||
// 2025-10-22: Fixed Platform_OpenInShellFn() return value (unused in core).
|
||||
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414)
|
||||
// 2025-06-27: IME: avoid calling SDL_StartTextInput() again if already active. (#8727)
|
||||
// 2025-04-22: IME: honor ImGuiPlatformImeData->WantTextInput as an alternative way to call SDL_StartTextInput(), without IME being necessarily visible.
|
||||
// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561)
|
||||
// 2025-03-30: Update for SDL3 api changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801)
|
||||
// 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set.
|
||||
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
||||
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650)
|
||||
// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650)
|
||||
// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode.
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler.
|
||||
@@ -108,6 +115,8 @@ struct ImGui_ImplSDL3_Data
|
||||
|
||||
// IME handling
|
||||
SDL_Window* ImeWindow;
|
||||
ImGuiPlatformImeData ImeData;
|
||||
bool ImeDirty;
|
||||
|
||||
// Mouse handling
|
||||
Uint32 MouseWindowID;
|
||||
@@ -116,7 +125,7 @@ struct ImGui_ImplSDL3_Data
|
||||
SDL_Cursor* MouseLastCursor;
|
||||
int MousePendingLeaveFrame;
|
||||
bool MouseCanUseGlobalState;
|
||||
bool MouseCanUseCapture;
|
||||
ImGui_ImplSDL3_MouseCaptureMode MouseCaptureMode;
|
||||
|
||||
// Gamepad handling
|
||||
ImVector<SDL_Gamepad*> Gamepads;
|
||||
@@ -135,13 +144,19 @@ static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData()
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL3_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||
}
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplSDL3_UpdateIme();
|
||||
|
||||
// Functions
|
||||
static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||
if (SDL_HasClipboardText())
|
||||
bd->ClipboardTextData = SDL_GetClipboardText();
|
||||
else
|
||||
bd->ClipboardTextData = nullptr;
|
||||
return bd->ClipboardTextData;
|
||||
}
|
||||
|
||||
@@ -150,16 +165,38 @@ static void ImGui_ImplSDL3_SetClipboardText(ImGuiContext*, const char* text)
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data)
|
||||
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
|
||||
SDL_Window* window = SDL_GetWindowFromID(window_id);
|
||||
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
bd->ImeData = *data;
|
||||
bd->ImeDirty = true;
|
||||
ImGui_ImplSDL3_UpdateIme();
|
||||
}
|
||||
|
||||
// We discard viewport passed via ImGuiPlatformImeData and always call SDL_StartTextInput() on SDL_GetKeyboardFocus().
|
||||
static void ImGui_ImplSDL3_UpdateIme()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
ImGuiPlatformImeData* data = &bd->ImeData;
|
||||
SDL_Window* window = SDL_GetKeyboardFocus();
|
||||
|
||||
// Stop previous input
|
||||
if ((!(data->WantVisible || data->WantTextInput) || bd->ImeWindow != window) && bd->ImeWindow != nullptr)
|
||||
{
|
||||
SDL_StopTextInput(bd->ImeWindow);
|
||||
bd->ImeWindow = nullptr;
|
||||
}
|
||||
if ((!bd->ImeDirty && bd->ImeWindow == window) || (window == nullptr))
|
||||
return;
|
||||
|
||||
// Start/update current input
|
||||
bd->ImeDirty = false;
|
||||
if (data->WantVisible)
|
||||
{
|
||||
SDL_Rect r;
|
||||
@@ -336,18 +373,10 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
|
||||
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0);
|
||||
}
|
||||
|
||||
|
||||
static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
|
||||
}
|
||||
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
|
||||
bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
@@ -470,6 +499,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
IM_UNUSED(sdl_gl_context); // Unused in this branch
|
||||
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
||||
|
||||
const int ver_linked = SDL_GetVersion();
|
||||
|
||||
@@ -489,20 +519,23 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
bd->MouseCanUseGlobalState = false;
|
||||
bd->MouseCanUseCapture = false;
|
||||
bd->MouseCaptureMode = ImGui_ImplSDL3_MouseCaptureMode_Disabled;
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
for (const char* item : capture_and_global_state_whitelist)
|
||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
||||
bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true;
|
||||
{
|
||||
bd->MouseCanUseGlobalState = true;
|
||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL3_MouseCaptureMode_Enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
|
||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText;
|
||||
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData;
|
||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; };
|
||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url); };
|
||||
|
||||
// Gamepad handling
|
||||
bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst;
|
||||
@@ -530,22 +563,18 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
||||
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
|
||||
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
|
||||
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
|
||||
// you can ignore SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
|
||||
#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
|
||||
// you can ignore SDL_EVENT_MOUSE_BUTTON_DOWN events coming right after a SDL_EVENT_WINDOW_FOCUS_GAINED)
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
#endif
|
||||
|
||||
// From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710)
|
||||
#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE
|
||||
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should technically be a SDL_GLContext but due to typedef it is sane to keep it void* in public interface.
|
||||
bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||
{
|
||||
IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
|
||||
return ImGui_ImplSDL3_Init(window, nullptr, sdl_gl_context);
|
||||
}
|
||||
|
||||
@@ -589,6 +618,7 @@ void ImGui_ImplSDL3_Shutdown()
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
if (bd->ClipboardTextData)
|
||||
SDL_free(bd->ClipboardTextData);
|
||||
@@ -599,9 +629,18 @@ void ImGui_ImplSDL3_Shutdown()
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode mode)
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
if (mode == ImGui_ImplSDL3_MouseCaptureMode_Disabled && bd->MouseCaptureMode != ImGui_ImplSDL3_MouseCaptureMode_Disabled)
|
||||
SDL_CaptureMouse(false);
|
||||
bd->MouseCaptureMode = mode;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL3_UpdateMouseData()
|
||||
{
|
||||
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
|
||||
@@ -610,8 +649,12 @@ static void ImGui_ImplSDL3_UpdateMouseData()
|
||||
// We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below)
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
// - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside.
|
||||
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture.
|
||||
if (bd->MouseCanUseCapture)
|
||||
// - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue on X11 we we wait until mouse has moved to begin capture.
|
||||
if (bd->MouseCaptureMode == ImGui_ImplSDL3_MouseCaptureMode_Enabled)
|
||||
{
|
||||
SDL_CaptureMouse(bd->MouseButtonsDown != 0);
|
||||
}
|
||||
else if (bd->MouseCaptureMode == ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag)
|
||||
{
|
||||
bool want_capture = false;
|
||||
for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++)
|
||||
@@ -632,16 +675,20 @@ static void ImGui_ImplSDL3_UpdateMouseData()
|
||||
if (io.WantSetMousePos)
|
||||
SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y);
|
||||
|
||||
// (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured)
|
||||
// (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured)
|
||||
// Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature.
|
||||
SDL_Window* hovered_window = SDL_GetMouseFocus();
|
||||
const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window);
|
||||
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
|
||||
if (hovered_window == nullptr && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode)
|
||||
{
|
||||
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
|
||||
float mouse_x_global, mouse_y_global;
|
||||
float mouse_x, mouse_y;
|
||||
int window_x, window_y;
|
||||
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
|
||||
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
|
||||
SDL_GetWindowPosition(focused_window, &window_x, &window_y);
|
||||
io.AddMousePosEvent(mouse_x_global - window_x, mouse_y_global - window_y);
|
||||
mouse_x -= (float)window_x;
|
||||
mouse_y -= (float)window_y;
|
||||
io.AddMousePosEvent(mouse_x, mouse_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -778,15 +825,24 @@ static void ImGui_ImplSDL3_UpdateGamepads()
|
||||
static void ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(SDL_Window* window, ImVec2* out_size, ImVec2* out_framebuffer_scale)
|
||||
{
|
||||
int w, h;
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||
w = h = 0;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
float fb_scale_x = SDL_GetWindowDisplayScale(window); // Seems more reliable during resolution change (#8703)
|
||||
float fb_scale_y = fb_scale_x;
|
||||
#else
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSizeInPixels(window, &display_w, &display_h);
|
||||
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
|
||||
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
|
||||
#endif
|
||||
|
||||
if (out_size != nullptr)
|
||||
*out_size = ImVec2((float)w, (float)h);
|
||||
if (out_framebuffer_scale != nullptr)
|
||||
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / w, (float)display_h / h) : ImVec2(1.0f, 1.0f);
|
||||
*out_framebuffer_scale = ImVec2(fb_scale_x, fb_scale_y);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDL3_NewFrame()
|
||||
@@ -804,7 +860,7 @@ void ImGui_ImplSDL3_NewFrame()
|
||||
Uint64 current_time = SDL_GetPerformanceCounter();
|
||||
if (current_time <= bd->Time)
|
||||
current_time = bd->Time + 1;
|
||||
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
|
||||
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / (double)frequency) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
if (bd->MousePendingLeaveFrame && bd->MousePendingLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
|
||||
@@ -816,6 +872,7 @@ void ImGui_ImplSDL3_NewFrame()
|
||||
|
||||
ImGui_ImplSDL3_UpdateMouseData();
|
||||
ImGui_ImplSDL3_UpdateMouseCursor();
|
||||
ImGui_ImplSDL3_UpdateIme();
|
||||
|
||||
// Update game controllers (if enabled and available)
|
||||
ImGui_ImplSDL3_UpdateGamepads();
|
||||
|
||||
@@ -44,4 +44,11 @@ IMGUI_IMPL_API bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event);
|
||||
enum ImGui_ImplSDL3_GamepadMode { ImGui_ImplSDL3_GamepadMode_AutoFirst, ImGui_ImplSDL3_GamepadMode_AutoAll, ImGui_ImplSDL3_GamepadMode_Manual };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
|
||||
|
||||
// (Advanced, for X11 users) Override Mouse Capture mode. Mouse capture allows receiving updated mouse position after clicking inside our window and dragging outside it.
|
||||
// Having this 'Enabled' is in theory always better. But, on X11 if you crash/break to debugger while capture is active you may temporarily lose access to your mouse.
|
||||
// The best solution is to setup your debugger to automatically release capture, e.g. 'setxkbmap -option grab:break_actions && xdotool key XF86Ungrab' or via a GDB script. See #3650.
|
||||
// But you may independently decide on X11, when a debugger is attached, to set this value to ImGui_ImplSDL3_MouseCaptureMode_Disabled.
|
||||
enum ImGui_ImplSDL3_MouseCaptureMode { ImGui_ImplSDL3_MouseCaptureMode_Enabled, ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag, ImGui_ImplSDL3_MouseCaptureMode_Disabled };
|
||||
IMGUI_IMPL_API void ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode mode);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
|
||||
|
||||
// CHANGELOG
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262)
|
||||
// 2025-11-26: macOS version can use MSL shaders in order to support macOS 10.14+ (vs Metallib shaders requiring macOS 14+). Requires calling SDL_CreateGPUDevice() with SDL_GPU_SHADERFORMAT_MSL.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created.
|
||||
// 2025-08-08: *BREAKING* Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988)
|
||||
// 2025-08-08: Expose SamplerDefault and SamplerCurrent in ImGui_ImplSDLGPU3_RenderState. Allow callback to change sampler.
|
||||
// 2025-06-25: Mapping transfer buffer for texture update use cycle=true. Fixes artifacts e.g. on Metal backend.
|
||||
@@ -54,11 +60,16 @@ struct ImGui_ImplSDLGPU3_Data
|
||||
{
|
||||
ImGui_ImplSDLGPU3_InitInfo InitInfo;
|
||||
|
||||
// Render state
|
||||
ImGui_ImplSDLGPU3_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
|
||||
SDL_GPUSampler* CurrentSampler = nullptr;
|
||||
|
||||
// Graphics pipeline & shaders
|
||||
SDL_GPUShader* VertexShader = nullptr;
|
||||
SDL_GPUShader* FragmentShader = nullptr;
|
||||
SDL_GPUGraphicsPipeline* Pipeline = nullptr;
|
||||
SDL_GPUSampler* TexSampler = nullptr;
|
||||
SDL_GPUSampler* TexSamplerLinear = nullptr;
|
||||
SDL_GPUSampler* TexSamplerNearest = nullptr;
|
||||
SDL_GPUTransferBuffer* TexTransferBuffer = nullptr;
|
||||
uint32_t TexTransferBufferSize = 0;
|
||||
|
||||
@@ -81,10 +92,10 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplSDLGPU3_RenderState* render_state, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
|
||||
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
render_state->SamplerCurrent = render_state->SamplerCurrent = bd->TexSampler;
|
||||
bd->CurrentSampler = bd->TexSamplerLinear;
|
||||
|
||||
// Bind graphics pipeline
|
||||
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
|
||||
@@ -127,8 +138,7 @@ static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer*
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
|
||||
// FIXME-OPT: Not optimal, but this is fairly rarely called.
|
||||
SDL_WaitForGPUIdle(v->Device);
|
||||
// There is no need for calling SDL_WaitForGPUIdle here, as SDL3 will handle deferred buffer deletion automatically.
|
||||
SDL_ReleaseGPUBuffer(v->Device, *buffer);
|
||||
SDL_ReleaseGPUTransferBuffer(v->Device, *transferbuffer);
|
||||
|
||||
@@ -169,8 +179,8 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
|
||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||
ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData;
|
||||
|
||||
uint32_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
uint32_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
uint32_t vertex_size = (uint32_t)draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
uint32_t index_size = (uint32_t)draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
if (fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size)
|
||||
CreateOrResizeBuffers(&fd->VertexBuffer, &fd->VertexTransferBuffer, &fd->VertexBufferSize, vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
|
||||
if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size)
|
||||
@@ -211,6 +221,11 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
|
||||
SDL_EndGPUCopyPass(copy_pass);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerLinear; }
|
||||
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerNearest; }
|
||||
|
||||
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
@@ -233,10 +248,9 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplSDLGPU3_RenderState render_state;
|
||||
render_state.Device = bd->InitInfo.Device;
|
||||
render_state.SamplerDefault = render_state.SamplerCurrent = bd->TexSampler;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
|
||||
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
@@ -250,9 +264,8 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
|
||||
if (pcmd->UserCallback == ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
@@ -265,8 +278,8 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
|
||||
// Clamp to viewport as SDL_SetGPUScissor() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
@@ -281,7 +294,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
|
||||
// Bind DescriptorSet with font or user texture
|
||||
SDL_GPUTextureSamplerBinding texture_sampler_binding;
|
||||
texture_sampler_binding.texture = (SDL_GPUTexture*)(intptr_t)pcmd->GetTexID();
|
||||
texture_sampler_binding.sampler = render_state.SamplerCurrent;
|
||||
texture_sampler_binding.sampler = bd->CurrentSampler;
|
||||
SDL_BindGPUFragmentSamplers(render_pass, 0, &texture_sampler_binding, 1);
|
||||
|
||||
// Draw
|
||||
@@ -300,14 +313,16 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
|
||||
// We perform a call to SDL_SetGPUScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
|
||||
SDL_Rect scissor_rect { 0, 0, fb_width, fb_height };
|
||||
SDL_SetGPUScissor(render_pass, &scissor_rect);
|
||||
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID();
|
||||
if (raw_tex != nullptr)
|
||||
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
|
||||
if (tex->GetTexID() != ImTextureID_Invalid)
|
||||
if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
|
||||
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
@@ -338,7 +353,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
|
||||
texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
|
||||
SDL_GPUTexture* raw_tex = SDL_CreateGPUTexture(v->Device, &texture_info);
|
||||
IM_ASSERT(raw_tex != nullptr && "Failed to create font texture, call SDL_GetError() for more info");
|
||||
IM_ASSERT(raw_tex != nullptr && "Failed to create texture, call SDL_GetError() for more info");
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)raw_tex);
|
||||
@@ -368,7 +383,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
|
||||
transferbuffer_info.size = upload_size + 1024;
|
||||
bd->TexTransferBufferSize = upload_size + 1024;
|
||||
bd->TexTransferBuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
|
||||
IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information");
|
||||
IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create transfer buffer, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
// Copy to transfer buffer
|
||||
@@ -451,14 +466,31 @@ static void ImGui_ImplSDLGPU3_CreateShaders()
|
||||
#ifdef __APPLE__
|
||||
else
|
||||
{
|
||||
vertex_shader_info.entrypoint = "main0";
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
vertex_shader_info.code = metallib_vertex;
|
||||
vertex_shader_info.code_size = sizeof(metallib_vertex);
|
||||
fragment_shader_info.entrypoint = "main0";
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
fragment_shader_info.code = metallib_fragment;
|
||||
fragment_shader_info.code_size = sizeof(metallib_fragment);
|
||||
SDL_GPUShaderFormat supported_formats = SDL_GetGPUShaderFormats(v->Device);
|
||||
if (supported_formats & SDL_GPU_SHADERFORMAT_METALLIB)
|
||||
{
|
||||
// Using metallib blobs (macOS 14+, iOS)
|
||||
vertex_shader_info.entrypoint = "main0";
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
vertex_shader_info.code = metallib_vertex;
|
||||
vertex_shader_info.code_size = sizeof(metallib_vertex);
|
||||
fragment_shader_info.entrypoint = "main0";
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
fragment_shader_info.code = metallib_fragment;
|
||||
fragment_shader_info.code_size = sizeof(metallib_fragment);
|
||||
}
|
||||
else if (supported_formats & SDL_GPU_SHADERFORMAT_MSL)
|
||||
{
|
||||
// macOS: using MSL source
|
||||
vertex_shader_info.entrypoint = "main0";
|
||||
vertex_shader_info.format = SDL_GPU_SHADERFORMAT_MSL;
|
||||
vertex_shader_info.code = msl_vertex;
|
||||
vertex_shader_info.code_size = sizeof(msl_vertex);
|
||||
fragment_shader_info.entrypoint = "main0";
|
||||
fragment_shader_info.format = SDL_GPU_SHADERFORMAT_MSL;
|
||||
fragment_shader_info.code = msl_fragment;
|
||||
fragment_shader_info.code_size = sizeof(msl_fragment);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bd->VertexShader = SDL_CreateGPUShader(v->Device, &vertex_shader_info);
|
||||
@@ -557,7 +589,7 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
|
||||
|
||||
ImGui_ImplSDLGPU3_DestroyDeviceObjects();
|
||||
|
||||
if (bd->TexSampler == nullptr)
|
||||
if (bd->TexSamplerLinear == nullptr)
|
||||
{
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
SDL_GPUSamplerCreateInfo sampler_info = {};
|
||||
@@ -573,9 +605,14 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
|
||||
sampler_info.enable_anisotropy = false;
|
||||
sampler_info.max_anisotropy = 1.0f;
|
||||
sampler_info.enable_compare = false;
|
||||
bd->TexSamplerLinear = SDL_CreateGPUSampler(v->Device, &sampler_info);
|
||||
IM_ASSERT(bd->TexSamplerLinear != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
|
||||
|
||||
bd->TexSampler = SDL_CreateGPUSampler(v->Device, &sampler_info);
|
||||
IM_ASSERT(bd->TexSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information");
|
||||
sampler_info.min_filter = SDL_GPU_FILTER_NEAREST;
|
||||
sampler_info.mag_filter = SDL_GPU_FILTER_NEAREST;
|
||||
sampler_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
|
||||
bd->TexSamplerNearest = SDL_CreateGPUSampler(v->Device, &sampler_info);
|
||||
IM_ASSERT(bd->TexSamplerNearest != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
|
||||
}
|
||||
|
||||
ImGui_ImplSDLGPU3_CreateGraphicsPipeline();
|
||||
@@ -610,7 +647,8 @@ void ImGui_ImplSDLGPU3_DestroyDeviceObjects()
|
||||
if (bd->TexTransferBuffer) { SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer); bd->TexTransferBuffer = nullptr; }
|
||||
if (bd->VertexShader) { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr; }
|
||||
if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr; }
|
||||
if (bd->TexSampler) { SDL_ReleaseGPUSampler(v->Device, bd->TexSampler); bd->TexSampler = nullptr; }
|
||||
if (bd->TexSamplerLinear) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerLinear); bd->TexSamplerLinear = nullptr; }
|
||||
if (bd->TexSamplerNearest) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerNearest); bd->TexSamplerNearest = nullptr; }
|
||||
if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr; }
|
||||
}
|
||||
|
||||
@@ -627,6 +665,11 @@ bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest;
|
||||
|
||||
IM_ASSERT(info->Device != nullptr);
|
||||
IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID);
|
||||
|
||||
@@ -640,11 +683,14 @@ void ImGui_ImplSDLGPU3_Shutdown()
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplSDLGPU3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
@@ -653,7 +699,7 @@ void ImGui_ImplSDLGPU3_NewFrame()
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?");
|
||||
|
||||
if (!bd->TexSampler)
|
||||
if (!bd->TexSamplerLinear)
|
||||
ImGui_ImplSDLGPU3_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
// Initialization data, for ImGui_ImplSDLGPU_Init()
|
||||
// - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat to query the right value
|
||||
// - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat() to query the right value
|
||||
struct ImGui_ImplSDLGPU3_InitInfo
|
||||
{
|
||||
SDL_GPUDevice* Device = nullptr;
|
||||
SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1;
|
||||
SDL_GPUDevice* Device = nullptr;
|
||||
SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1;
|
||||
SDL_GPUSwapchainComposition SwapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR; // Only used in multi-viewports mode.
|
||||
SDL_GPUPresentMode PresentMode = SDL_GPU_PRESENTMODE_VSYNC; // Only used in multi-viewports mode.
|
||||
};
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
@@ -46,7 +48,7 @@ IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data,
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
@@ -55,8 +57,6 @@ IMGUI_IMPL_API void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex);
|
||||
struct ImGui_ImplSDLGPU3_RenderState
|
||||
{
|
||||
SDL_GPUDevice* Device;
|
||||
SDL_GPUSampler* SamplerDefault; // Default sampler (bilinear filtering)
|
||||
SDL_GPUSampler* SamplerCurrent; // Current sampler (may be changed by callback)
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -221,6 +221,40 @@ const uint8_t metallib_fragment[3787] = {
|
||||
148,161,0,0,0,0,109,97,105,110,48,97,105,114,46,115,97,109,112,108,101,95,116,101,120,116,117,114,101,95,50,100,46,118,52,102,51,50,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,
|
||||
112,112,108,101,45,109,97,99,111,115,120,49,52,46,48,46,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
};
|
||||
static uint8_t msl_vertex[800] =
|
||||
{
|
||||
35,105,110,99,108,117,100,101,32,60,109,101,116,97,108,95,115,116,100,108,105,98,62,10,35,105,110,99,108,117,100,101,32,60,115,105,109,100,47,115,105,109,100,46,104,62,10,10,117,115,
|
||||
105,110,103,32,110,97,109,101,115,112,97,99,101,32,109,101,116,97,108,59,10,10,115,116,114,117,99,116,32,95,57,10,123,10,32,32,32,32,102,108,111,97,116,52,32,67,111,108,111,114,59,
|
||||
10,32,32,32,32,102,108,111,97,116,50,32,85,86,59,10,125,59,10,10,115,116,114,117,99,116,32,85,66,79,10,123,10,32,32,32,32,102,108,111,97,116,50,32,117,83,99,97,108,101,59,10,32,32,
|
||||
32,32,102,108,111,97,116,50,32,117,84,114,97,110,115,108,97,116,101,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,111,117,116,10,123,10,32,32,32,32,102,108,111,
|
||||
97,116,52,32,79,117,116,95,67,111,108,111,114,32,91,91,117,115,101,114,40,108,111,99,110,48,41,93,93,59,10,32,32,32,32,102,108,111,97,116,50,32,79,117,116,95,85,86,32,91,91,117,115,
|
||||
101,114,40,108,111,99,110,49,41,93,93,59,10,32,32,32,32,102,108,111,97,116,52,32,103,108,95,80,111,115,105,116,105,111,110,32,91,91,112,111,115,105,116,105,111,110,93,93,59,10,125,
|
||||
59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,105,110,10,123,10,32,32,32,32,102,108,111,97,116,50,32,97,80,111,115,32,91,91,97,116,116,114,105,98,117,116,101,40,48,41,93,
|
||||
93,59,10,32,32,32,32,102,108,111,97,116,50,32,97,85,86,32,91,91,97,116,116,114,105,98,117,116,101,40,49,41,93,93,59,10,32,32,32,32,102,108,111,97,116,52,32,97,67,111,108,111,114,32,
|
||||
91,91,97,116,116,114,105,98,117,116,101,40,50,41,93,93,59,10,125,59,10,10,118,101,114,116,101,120,32,109,97,105,110,48,95,111,117,116,32,109,97,105,110,48,40,109,97,105,110,48,95,105,
|
||||
110,32,105,110,32,91,91,115,116,97,103,101,95,105,110,93,93,44,32,99,111,110,115,116,97,110,116,32,85,66,79,38,32,117,98,111,32,91,91,98,117,102,102,101,114,40,48,41,93,93,41,10,123,
|
||||
10,32,32,32,32,109,97,105,110,48,95,111,117,116,32,111,117,116,32,61,32,123,125,59,10,32,32,32,32,95,57,32,79,117,116,32,61,32,123,125,59,10,32,32,32,32,79,117,116,46,67,111,108,111,
|
||||
114,32,61,32,105,110,46,97,67,111,108,111,114,59,10,32,32,32,32,79,117,116,46,85,86,32,61,32,105,110,46,97,85,86,59,10,32,32,32,32,111,117,116,46,103,108,95,80,111,115,105,116,105,
|
||||
111,110,32,61,32,102,108,111,97,116,52,40,40,105,110,46,97,80,111,115,32,42,32,117,98,111,46,117,83,99,97,108,101,41,32,43,32,117,98,111,46,117,84,114,97,110,115,108,97,116,101,44,
|
||||
32,48,46,48,44,32,49,46,48,41,59,10,32,32,32,32,111,117,116,46,103,108,95,80,111,115,105,116,105,111,110,46,121,32,42,61,32,40,45,49,46,48,41,59,10,32,32,32,32,111,117,116,46,79,117,
|
||||
116,95,67,111,108,111,114,32,61,32,79,117,116,46,67,111,108,111,114,59,10,32,32,32,32,111,117,116,46,79,117,116,95,85,86,32,61,32,79,117,116,46,85,86,59,10,32,32,32,32,114,101,116,
|
||||
117,114,110,32,111,117,116,59,10,125,10,10,
|
||||
};
|
||||
static uint8_t msl_fragment[580] =
|
||||
{
|
||||
35,105,110,99,108,117,100,101,32,60,109,101,116,97,108,95,115,116,100,108,105,98,62,10,35,105,110,99,108,117,100,101,32,60,115,105,109,100,47,115,105,109,100,46,104,62,10,10,117,115,
|
||||
105,110,103,32,110,97,109,101,115,112,97,99,101,32,109,101,116,97,108,59,10,10,115,116,114,117,99,116,32,95,49,49,10,123,10,32,32,32,32,102,108,111,97,116,52,32,67,111,108,111,114,
|
||||
59,10,32,32,32,32,102,108,111,97,116,50,32,85,86,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,111,117,116,10,123,10,32,32,32,32,102,108,111,97,116,52,32,102,67,
|
||||
111,108,111,114,32,91,91,99,111,108,111,114,40,48,41,93,93,59,10,125,59,10,10,115,116,114,117,99,116,32,109,97,105,110,48,95,105,110,10,123,10,32,32,32,32,102,108,111,97,116,52,32,
|
||||
73,110,95,67,111,108,111,114,32,91,91,117,115,101,114,40,108,111,99,110,48,41,93,93,59,10,32,32,32,32,102,108,111,97,116,50,32,73,110,95,85,86,32,91,91,117,115,101,114,40,108,111,99,
|
||||
110,49,41,93,93,59,10,125,59,10,10,102,114,97,103,109,101,110,116,32,109,97,105,110,48,95,111,117,116,32,109,97,105,110,48,40,109,97,105,110,48,95,105,110,32,105,110,32,91,91,115,116,
|
||||
97,103,101,95,105,110,93,93,44,32,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,62,32,115,84,101,120,116,117,114,101,32,91,91,116,101,120,116,117,114,101,40,48,41,93,93,
|
||||
44,32,115,97,109,112,108,101,114,32,115,84,101,120,116,117,114,101,83,109,112,108,114,32,91,91,115,97,109,112,108,101,114,40,48,41,93,93,41,10,123,10,32,32,32,32,109,97,105,110,48,
|
||||
95,111,117,116,32,111,117,116,32,61,32,123,125,59,10,32,32,32,32,95,49,49,32,73,110,32,61,32,123,125,59,10,32,32,32,32,73,110,46,67,111,108,111,114,32,61,32,105,110,46,73,110,95,67,
|
||||
111,108,111,114,59,10,32,32,32,32,73,110,46,85,86,32,61,32,105,110,46,73,110,95,85,86,59,10,32,32,32,32,111,117,116,46,102,67,111,108,111,114,32,61,32,73,110,46,67,111,108,111,114,
|
||||
32,42,32,115,84,101,120,116,117,114,101,46,115,97,109,112,108,101,40,115,84,101,120,116,117,114,101,83,109,112,108,114,44,32,73,110,46,85,86,41,59,10,32,32,32,32,114,101,116,117,114,
|
||||
110,32,111,117,116,59,10,125,10,10,
|
||||
};
|
||||
#elif TARGET_OS_IPHONE
|
||||
const uint8_t metallib_vertex[3876] = {
|
||||
77,84,76,66,1,0,2,0,7,0,0,130,18,0,1,0,36,15,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,12,1,0,0,0,0,0,0,8,0,0,0,0,0,0,0,20,1,0,0,0,0,0,0,16,
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: SDLRenderer2 does not support changing SDL_SCALE_MODE while rendering.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
@@ -24,6 +26,10 @@
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others cannot be supported). (#9378)
|
||||
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer2_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture().
|
||||
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
||||
// 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
@@ -70,39 +76,6 @@ static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData()
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLRenderer2_Data* bd = IM_NEW(ImGui_ImplSDLRenderer2_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer2";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
// Clear out any viewports and cliprect set by the user
|
||||
@@ -118,6 +91,9 @@ void ImGui_ImplSDLRenderer2_NewFrame()
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
|
||||
void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
|
||||
{
|
||||
// If there's a scale factor set by the user, use that instead
|
||||
@@ -180,8 +156,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -264,10 +239,9 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID;
|
||||
if (sdl_texture == nullptr)
|
||||
return;
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
if (tex->TexID != ImTextureID_Invalid)
|
||||
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
@@ -290,6 +264,44 @@ void ImGui_ImplSDLRenderer2_DestroyDeviceObjects()
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLRenderer2_Data* bd = IM_NEW(ImGui_ImplSDLRenderer2_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer2";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer2_DrawCallback_ResetRenderState;
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer2_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// Missing features or Issues:
|
||||
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks: SDLRenderer2 does not support changing SDL_SCALE_MODE while rendering.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -39,7 +41,7 @@ IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_d
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
@@ -24,6 +24,10 @@
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture().
|
||||
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
||||
// 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
@@ -57,6 +61,9 @@ struct ImGui_ImplSDLRenderer3_Data
|
||||
SDL_Renderer* Renderer; // Main viewport's renderer
|
||||
ImVector<SDL_FColor> ColorBuffer;
|
||||
|
||||
// Render State
|
||||
SDL_ScaleMode CurrentScaleMode;
|
||||
|
||||
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
@@ -68,39 +75,6 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLRenderer3_Data* bd = IM_NEW(ImGui_ImplSDLRenderer3_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer3";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
// Clear out any viewports and cliprect set by the user
|
||||
@@ -134,6 +108,11 @@ static int SDL_RenderGeometryRaw8BitColor(SDL_Renderer* renderer, ImVector<SDL_F
|
||||
return SDL_RenderGeometryRaw(renderer, texture, xy, xy_stride, color3, sizeof(*color3), uv, uv_stride, num_vertices, indices, num_indices, size_indices);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR; }
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_NEAREST; }
|
||||
|
||||
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
@@ -200,8 +179,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -227,6 +205,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
||||
|
||||
// Bind texture, Draw
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
SDL_SetTextureScaleMode(tex, bd->CurrentScaleMode);
|
||||
SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex,
|
||||
xy, (int)sizeof(ImDrawVert),
|
||||
color, (int)sizeof(ImDrawVert),
|
||||
@@ -251,7 +230,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
@@ -280,10 +259,9 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||
{
|
||||
SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID;
|
||||
if (sdl_texture == nullptr)
|
||||
return;
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
if (tex->TexID != ImTextureID_Invalid)
|
||||
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
||||
SDL_DestroyTexture(sdl_texture);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
@@ -306,6 +284,46 @@ void ImGui_ImplSDLRenderer3_DestroyDeviceObjects()
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(renderer != nullptr && "SDL_Renderer not initialized!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDLRenderer3_Data* bd = IM_NEW(ImGui_ImplSDLRenderer3_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer3";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_Shutdown()
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
@@ -39,7 +39,7 @@ IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_d
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
@@ -27,6 +27,27 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends.
|
||||
// - When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
// - Before: ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)
|
||||
// - After: ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)
|
||||
// - Kept inline redirection function that ignores the sampler.
|
||||
// - When creating your own descriptor pool (instead of letting backend creates its own):
|
||||
// - Before: need at least IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.
|
||||
// - After: need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.
|
||||
// + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
|
||||
// 2026-03-11: Vulkan: Added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying extra dynamic states to add when creating the VkPipeline. (#9211)
|
||||
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Vulkan: Helper ImGui_ImplVulkanH_DestroyWindow() does not call vkDestroySurfaceKHR(): as surface is created by caller of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent that we don't destroy it. (#9163)
|
||||
// 2026-01-05: [Helpers] *BREAKING CHANGE*: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)
|
||||
// 2025-11-24: [Helpers] Vulkan: Helper for creating a swap-chain (used by examples and multi-viewports) selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784)
|
||||
// 2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008)
|
||||
// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo.
|
||||
// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.
|
||||
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
|
||||
// 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111)
|
||||
// 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840)
|
||||
// 2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772)
|
||||
// 2025-06-27: Vulkan: Fixed validation errors during texture upload/update by aligning upload size to 'nonCoherentAtomSize'. (#8743, #8744)
|
||||
@@ -37,8 +58,8 @@
|
||||
// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
|
||||
// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
|
||||
// 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)
|
||||
// 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
|
||||
// 2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
|
||||
// 2025-01-06: [Helpers] Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
|
||||
// 2024-12-11: [Helpers] Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
|
||||
// 2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)
|
||||
// 2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||
// 2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
|
||||
@@ -46,7 +67,7 @@
|
||||
// 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
|
||||
// 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
|
||||
// 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
|
||||
// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
|
||||
// 2024-01-19: [Helpers] Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
|
||||
// 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189).
|
||||
// 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238)
|
||||
// 2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.
|
||||
@@ -74,16 +95,16 @@
|
||||
// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||
// 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().
|
||||
// 2019-04-04: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
|
||||
// 2019-04-04: [Helpers] Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
|
||||
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
|
||||
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
|
||||
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
|
||||
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
||||
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
|
||||
// 2018-08-25: [Helpers] Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
|
||||
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example.
|
||||
// 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||
// 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
|
||||
// 2018-03-03: [Helpers] Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
|
||||
// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
@@ -106,6 +127,14 @@
|
||||
#pragma warning (disable: 4127) // condition expression is constant
|
||||
#endif
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
||||
#pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
|
||||
#endif
|
||||
|
||||
// Forward Declarations
|
||||
struct ImGui_ImplVulkan_FrameRenderBuffers;
|
||||
struct ImGui_ImplVulkan_WindowRenderBuffers;
|
||||
@@ -115,11 +144,11 @@ void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulka
|
||||
void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);
|
||||
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
|
||||
|
||||
// Vulkan prototypes for use with custom loaders
|
||||
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
|
||||
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h)
|
||||
#if defined(VK_NO_PROTOTYPES) && !defined(VOLK_H_)
|
||||
#define IMGUI_IMPL_VULKAN_USE_LOADER
|
||||
static bool g_FunctionsLoaded = false;
|
||||
@@ -247,18 +276,24 @@ struct ImGui_ImplVulkan_Texture
|
||||
struct ImGui_ImplVulkan_Data
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo VulkanInitInfo;
|
||||
ImGui_ImplVulkan_RenderState* RenderState; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
|
||||
VkDeviceSize BufferMemoryAlignment;
|
||||
VkDeviceSize NonCoherentAtomSize;
|
||||
VkPipelineCreateFlags PipelineCreateFlags;
|
||||
VkDescriptorSetLayout DescriptorSetLayout;
|
||||
VkDescriptorSetLayout DescriptorSetLayoutTexture;
|
||||
VkDescriptorSetLayout DescriptorSetLayoutSampler;
|
||||
VkPipelineLayout PipelineLayout;
|
||||
VkPipeline Pipeline;
|
||||
VkPipeline Pipeline; // pipeline for main render pass (created by app)
|
||||
VkShaderModule ShaderModuleVert;
|
||||
VkShaderModule ShaderModuleFrag;
|
||||
VkDescriptorPool DescriptorPool;
|
||||
ImVector<VkFormat> PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array
|
||||
|
||||
// Texture management
|
||||
VkSampler TexSampler;
|
||||
VkSampler SamplerLinear;
|
||||
VkSampler SamplerNearest;
|
||||
VkDescriptorSet SamplerLinearDS;
|
||||
VkDescriptorSet SamplerNearestDS;
|
||||
VkCommandPool TexCommandPool;
|
||||
VkCommandBuffer TexCommandBuffer;
|
||||
|
||||
@@ -298,7 +333,7 @@ void main()
|
||||
*/
|
||||
static uint32_t __glsl_shader_vert_spv[] =
|
||||
{
|
||||
0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x07230203,0x00010000,0x0008000b,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
|
||||
0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
|
||||
0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
|
||||
@@ -311,10 +346,10 @@ static uint32_t __glsl_shader_vert_spv[] =
|
||||
0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x00000001,
|
||||
0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000000b,
|
||||
0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,
|
||||
0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047,
|
||||
0x00000019,0x00000002,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00050048,0x0000001e,
|
||||
0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000001,0x00000023,0x00000008,
|
||||
0x00030047,0x0000001e,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
|
||||
0x0000001e,0x00000001,0x00030047,0x00000019,0x00000002,0x00050048,0x00000019,0x00000000,
|
||||
0x0000000b,0x00000000,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00030047,0x0000001e,
|
||||
0x00000002,0x00050048,0x0000001e,0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,
|
||||
0x00000001,0x00000023,0x00000008,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
|
||||
0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017,
|
||||
0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,
|
||||
0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015,
|
||||
@@ -346,39 +381,44 @@ static uint32_t __glsl_shader_vert_spv[] =
|
||||
/*
|
||||
#version 450 core
|
||||
layout(location = 0) out vec4 fColor;
|
||||
layout(set=0, binding=0) uniform sampler2D sTexture;
|
||||
layout(set=0, binding=0) uniform texture2D _Texture;
|
||||
layout(set=1, binding=0) uniform sampler _Sampler;
|
||||
layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
fColor = In.Color * texture(sampler2D(_Texture, _Sampler), In.UV.st);
|
||||
}
|
||||
*/
|
||||
static uint32_t __glsl_shader_frag_spv[] =
|
||||
{
|
||||
0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x07230203,0x00010000,0x0008000b,0x00000023,0x00000000,0x00020011,0x00000001,0x0006000b,
|
||||
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
|
||||
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
|
||||
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
|
||||
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
|
||||
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
|
||||
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574,
|
||||
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,
|
||||
0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021,
|
||||
0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
|
||||
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
|
||||
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,
|
||||
0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,
|
||||
0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,
|
||||
0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,
|
||||
0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,
|
||||
0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000,
|
||||
0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018,
|
||||
0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,
|
||||
0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,
|
||||
0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017,
|
||||
0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a,
|
||||
0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085,
|
||||
0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x000100fd,
|
||||
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000015,0x7865545f,0x65727574,
|
||||
0x00000000,0x00050005,0x00000019,0x6d61535f,0x72656c70,0x00000000,0x00040047,0x00000009,
|
||||
0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,0x00000000,0x00040047,0x00000015,
|
||||
0x00000021,0x00000000,0x00040047,0x00000015,0x00000022,0x00000000,0x00040047,0x00000019,
|
||||
0x00000021,0x00000000,0x00040047,0x00000019,0x00000022,0x00000001,0x00020013,0x00000002,
|
||||
0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,
|
||||
0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007,0x0004003b,0x00000008,
|
||||
0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,0x00000002,0x0004001e,0x0000000b,
|
||||
0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,0x0000000b,0x0004003b,0x0000000c,
|
||||
0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,0x00000001,0x0004002b,0x0000000e,
|
||||
0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,0x00000007,0x00090019,0x00000013,
|
||||
0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x00040020,
|
||||
0x00000014,0x00000000,0x00000013,0x0004003b,0x00000014,0x00000015,0x00000000,0x0002001a,
|
||||
0x00000017,0x00040020,0x00000018,0x00000000,0x00000017,0x0004003b,0x00000018,0x00000019,
|
||||
0x00000000,0x0003001b,0x0000001b,0x00000013,0x0004002b,0x0000000e,0x0000001d,0x00000001,
|
||||
0x00040020,0x0000001e,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,0x00000000,
|
||||
0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,0x0000000f,
|
||||
0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000013,0x00000016,0x00000015,
|
||||
0x0004003d,0x00000017,0x0000001a,0x00000019,0x00050056,0x0000001b,0x0000001c,0x00000016,
|
||||
0x0000001a,0x00050041,0x0000001e,0x0000001f,0x0000000d,0x0000001d,0x0004003d,0x0000000a,
|
||||
0x00000020,0x0000001f,0x00050057,0x00000007,0x00000021,0x0000001c,0x00000020,0x00050085,
|
||||
0x00000007,0x00000022,0x00000012,0x00000021,0x0003003e,0x00000009,0x00000022,0x000100fd,
|
||||
0x00010038
|
||||
};
|
||||
|
||||
@@ -461,9 +501,7 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
|
||||
// Bind pipeline:
|
||||
{
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
}
|
||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
|
||||
// Bind Vertex And Index Buffer:
|
||||
if (draw_data->TotalVtxCount > 0)
|
||||
@@ -475,31 +513,33 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
|
||||
}
|
||||
|
||||
// Setup viewport:
|
||||
{
|
||||
VkViewport viewport;
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = (float)fb_width;
|
||||
viewport.height = (float)fb_height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
||||
}
|
||||
VkViewport viewport;
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = (float)fb_width;
|
||||
viewport.height = (float)fb_height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
||||
|
||||
// Setup scale and translation:
|
||||
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
{
|
||||
float scale[2];
|
||||
scale[0] = 2.0f / draw_data->DisplaySize.x;
|
||||
scale[1] = 2.0f / draw_data->DisplaySize.y;
|
||||
float translate[2];
|
||||
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
|
||||
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
|
||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
|
||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
|
||||
}
|
||||
float constants[4];
|
||||
constants[0] = 2.0f / draw_data->DisplaySize.x; // Scale
|
||||
constants[1] = 2.0f / draw_data->DisplaySize.y;
|
||||
constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate
|
||||
constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];
|
||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, constants);
|
||||
|
||||
// Setup sampler
|
||||
vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplVulkan_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }
|
||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
|
||||
{
|
||||
@@ -571,16 +611,16 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
vkUnmapMemory(v->Device, rb->IndexBufferMemory);
|
||||
}
|
||||
|
||||
// Setup desired Vulkan state
|
||||
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplVulkan_RenderState render_state;
|
||||
render_state.CommandBuffer = command_buffer;
|
||||
render_state.Pipeline = pipeline;
|
||||
render_state.PipelineLayout = bd->PipelineLayout;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
// Setup desired Vulkan state
|
||||
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
@@ -588,7 +628,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
VkDescriptorSet last_desc_set = VK_NULL_HANDLE;
|
||||
VkDescriptorSet last_image_view = VK_NULL_HANDLE;
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
@@ -599,12 +639,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplVulkan_DrawCallback_ResetRenderState)
|
||||
{
|
||||
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
|
||||
last_image_view = VK_NULL_HANDLE;
|
||||
}
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
last_desc_set = VK_NULL_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -615,8 +656,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
// Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
@@ -628,11 +669,11 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
||||
|
||||
// Bind DescriptorSet with font or user texture
|
||||
VkDescriptorSet desc_set = (VkDescriptorSet)pcmd->GetTexID();
|
||||
if (desc_set != last_desc_set)
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &desc_set, 0, nullptr);
|
||||
last_desc_set = desc_set;
|
||||
// Bind DescriptorSets for image view (font or user texture) and samplers
|
||||
VkDescriptorSet image_view = (VkDescriptorSet)pcmd->GetTexID();
|
||||
if (image_view != last_image_view)
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &image_view, 0, nullptr);
|
||||
last_image_view = image_view;
|
||||
|
||||
// Draw
|
||||
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
|
||||
@@ -641,7 +682,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
global_idx_offset += draw_list->IdxBuffer.Size;
|
||||
global_vtx_offset += draw_list->VtxBuffer.Size;
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
|
||||
// Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
|
||||
// Our last values will leak into user/application rendering IF:
|
||||
@@ -656,22 +697,22 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
|
||||
static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData;
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
|
||||
vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);
|
||||
vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);
|
||||
vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);
|
||||
IM_DELETE(backend_tex);
|
||||
if (ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
|
||||
vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);
|
||||
vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);
|
||||
vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
|
||||
@@ -735,7 +776,7 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
|
||||
}
|
||||
|
||||
// Create the Descriptor Set
|
||||
backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);
|
||||
@@ -884,29 +925,35 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
|
||||
|
||||
static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
// Create the shader modules
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
if (bd->ShaderModuleVert == VK_NULL_HANDLE)
|
||||
{
|
||||
VkShaderModuleCreateInfo vert_info = {};
|
||||
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
|
||||
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
|
||||
VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert);
|
||||
VkShaderModuleCreateInfo default_vert_info = {};
|
||||
default_vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
default_vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
|
||||
default_vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
|
||||
VkShaderModuleCreateInfo* p_vert_info = (v->CustomShaderVertCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderVertCreateInfo : &default_vert_info;
|
||||
VkResult err = vkCreateShaderModule(device, p_vert_info, allocator, &bd->ShaderModuleVert);
|
||||
check_vk_result(err);
|
||||
}
|
||||
if (bd->ShaderModuleFrag == VK_NULL_HANDLE)
|
||||
{
|
||||
VkShaderModuleCreateInfo frag_info = {};
|
||||
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
|
||||
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
|
||||
VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag);
|
||||
VkShaderModuleCreateInfo default_frag_info = {};
|
||||
default_frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
default_frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
|
||||
default_frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
|
||||
VkShaderModuleCreateInfo* p_frag_info = (v->CustomShaderFragCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderFragCreateInfo : &default_frag_info;
|
||||
VkResult err = vkCreateShaderModule(device, p_frag_info, allocator, &bd->ShaderModuleFrag);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
|
||||
#if !defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING) && !(defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering))
|
||||
typedef void VkPipelineRenderingCreateInfoKHR;
|
||||
#endif
|
||||
|
||||
static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, const ImGui_ImplVulkan_PipelineInfo* info)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_CreateShaderModules(device, allocator);
|
||||
@@ -964,7 +1011,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo ms_info = {};
|
||||
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT;
|
||||
ms_info.rasterizationSamples = (info->MSAASamples != 0) ? info->MSAASamples : VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkPipelineColorBlendAttachmentState color_attachment[1] = {};
|
||||
color_attachment[0].blendEnable = VK_TRUE;
|
||||
@@ -984,41 +1031,88 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
|
||||
blend_info.attachmentCount = 1;
|
||||
blend_info.pAttachments = color_attachment;
|
||||
|
||||
VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||
ImVector<VkDynamicState> dynamic_states = info->ExtraDynamicStates;
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
||||
VkPipelineDynamicStateCreateInfo dynamic_state = {};
|
||||
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states);
|
||||
dynamic_state.pDynamicStates = dynamic_states;
|
||||
dynamic_state.dynamicStateCount = dynamic_states.Size;
|
||||
dynamic_state.pDynamicStates = dynamic_states.Data;
|
||||
|
||||
VkGraphicsPipelineCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
info.flags = bd->PipelineCreateFlags;
|
||||
info.stageCount = 2;
|
||||
info.pStages = stage;
|
||||
info.pVertexInputState = &vertex_info;
|
||||
info.pInputAssemblyState = &ia_info;
|
||||
info.pViewportState = &viewport_info;
|
||||
info.pRasterizationState = &raster_info;
|
||||
info.pMultisampleState = &ms_info;
|
||||
info.pDepthStencilState = &depth_info;
|
||||
info.pColorBlendState = &blend_info;
|
||||
info.pDynamicState = &dynamic_state;
|
||||
info.layout = bd->PipelineLayout;
|
||||
info.renderPass = renderPass;
|
||||
info.subpass = subpass;
|
||||
VkGraphicsPipelineCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
create_info.flags = bd->PipelineCreateFlags;
|
||||
create_info.stageCount = 2;
|
||||
create_info.pStages = stage;
|
||||
create_info.pVertexInputState = &vertex_info;
|
||||
create_info.pInputAssemblyState = &ia_info;
|
||||
create_info.pViewportState = &viewport_info;
|
||||
create_info.pRasterizationState = &raster_info;
|
||||
create_info.pMultisampleState = &ms_info;
|
||||
create_info.pDepthStencilState = &depth_info;
|
||||
create_info.pColorBlendState = &blend_info;
|
||||
create_info.pDynamicState = &dynamic_state;
|
||||
create_info.layout = bd->PipelineLayout;
|
||||
create_info.renderPass = info->RenderPass;
|
||||
create_info.subpass = info->Subpass;
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
if (bd->VulkanInitInfo.UseDynamicRendering)
|
||||
{
|
||||
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
|
||||
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be nullptr");
|
||||
info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo;
|
||||
info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
|
||||
IM_ASSERT(info->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
|
||||
IM_ASSERT(info->PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr");
|
||||
create_info.pNext = &info->PipelineRenderingCreateInfo;
|
||||
create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
|
||||
}
|
||||
#endif
|
||||
|
||||
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
|
||||
VkPipeline pipeline;
|
||||
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline);
|
||||
check_vk_result(err);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDescriptorSetLayout* p_layout, VkDescriptorType descriptor_type)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
|
||||
VkDescriptorSetLayoutBinding binding[1] = {};
|
||||
binding[0].descriptorType = descriptor_type;
|
||||
binding[0].descriptorCount = 1;
|
||||
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
VkDescriptorSetLayoutCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = binding;
|
||||
VkResult err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, p_layout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
static VkDescriptorSet ImGui_ImplVulkan_CreateSamplerDS(VkSampler sampler)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
|
||||
VkDescriptorSet descriptor_set;
|
||||
VkDescriptorSetAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &bd->DescriptorSetLayoutSampler;
|
||||
VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
|
||||
check_vk_result(err);
|
||||
|
||||
VkDescriptorImageInfo desc_image = {};
|
||||
desc_image.sampler = sampler;
|
||||
VkWriteDescriptorSet sampler_write_desc = {};
|
||||
sampler_write_desc.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
sampler_write_desc.dstSet = descriptor_set;
|
||||
sampler_write_desc.descriptorCount = 1;
|
||||
sampler_write_desc.dstBinding = 0;
|
||||
sampler_write_desc.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
sampler_write_desc.pImageInfo = &desc_image;
|
||||
vkUpdateDescriptorSets(v->Device, 1, &sampler_write_desc, 0, nullptr);
|
||||
return descriptor_set;
|
||||
}
|
||||
|
||||
bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
@@ -1027,9 +1121,33 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
VkResult err;
|
||||
|
||||
if (!bd->TexSampler)
|
||||
if (!bd->DescriptorSetLayoutTexture)
|
||||
ImGui_ImplVulkan_CreateDescriptorSetLayout(&bd->DescriptorSetLayoutTexture, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
|
||||
if (!bd->DescriptorSetLayoutSampler)
|
||||
ImGui_ImplVulkan_CreateDescriptorSetLayout(&bd->DescriptorSetLayoutSampler, VK_DESCRIPTOR_TYPE_SAMPLER);
|
||||
|
||||
if (v->DescriptorPoolSize != 0)
|
||||
{
|
||||
IM_ASSERT(v->DescriptorPoolSize >= IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE);
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, v->DescriptorPoolSize },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = v->DescriptorPoolSize + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE;
|
||||
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
err = vkCreateDescriptorPool(v->Device, &pool_info, v->Allocator, &bd->DescriptorPool);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Create samplers
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
if (!bd->SamplerLinear || !bd->SamplerNearest)
|
||||
{
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
VkSamplerCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
info.magFilter = VK_FILTER_LINEAR;
|
||||
@@ -1041,37 +1159,16 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
info.minLod = -1000;
|
||||
info.maxLod = 1000;
|
||||
info.maxAnisotropy = 1.0f;
|
||||
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSampler);
|
||||
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->SamplerLinear);
|
||||
check_vk_result(err);
|
||||
}
|
||||
bd->SamplerLinearDS = ImGui_ImplVulkan_CreateSamplerDS(bd->SamplerLinear);
|
||||
|
||||
if (!bd->DescriptorSetLayout)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding binding[1] = {};
|
||||
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
binding[0].descriptorCount = 1;
|
||||
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
VkDescriptorSetLayoutCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = binding;
|
||||
err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
if (v->DescriptorPoolSize != 0)
|
||||
{
|
||||
IM_ASSERT(v->DescriptorPoolSize >= IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE);
|
||||
VkDescriptorPoolSize pool_size = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, v->DescriptorPoolSize };
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = v->DescriptorPoolSize;
|
||||
pool_info.poolSizeCount = 1;
|
||||
pool_info.pPoolSizes = &pool_size;
|
||||
|
||||
err = vkCreateDescriptorPool(v->Device, &pool_info, v->Allocator, &bd->DescriptorPool);
|
||||
info.magFilter = VK_FILTER_NEAREST;
|
||||
info.minFilter = VK_FILTER_NEAREST;
|
||||
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->SamplerNearest);
|
||||
check_vk_result(err);
|
||||
bd->SamplerNearestDS = ImGui_ImplVulkan_CreateSamplerDS(bd->SamplerNearest);
|
||||
}
|
||||
|
||||
if (!bd->PipelineLayout)
|
||||
@@ -1081,10 +1178,10 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
push_constants[0].offset = sizeof(float) * 0;
|
||||
push_constants[0].size = sizeof(float) * 4;
|
||||
VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
|
||||
VkDescriptorSetLayout set_layout[2] = { bd->DescriptorSetLayoutTexture, bd->DescriptorSetLayoutSampler };
|
||||
VkPipelineLayoutCreateInfo layout_info = {};
|
||||
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.setLayoutCount = 2;
|
||||
layout_info.pSetLayouts = set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants;
|
||||
@@ -1092,7 +1189,13 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, &bd->Pipeline, v->Subpass);
|
||||
// Create pipeline
|
||||
bool create_main_pipeline = (v->PipelineInfoMain.RenderPass != VK_NULL_HANDLE);
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
create_main_pipeline |= (v->UseDynamicRendering && v->PipelineInfoMain.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR);
|
||||
#endif
|
||||
if (create_main_pipeline)
|
||||
ImGui_ImplVulkan_CreateMainPipeline(&v->PipelineInfoMain);
|
||||
|
||||
// Create command pool/buffer for texture upload
|
||||
if (!bd->TexCommandPool)
|
||||
@@ -1117,6 +1220,34 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* pipeline_info_in)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
if (bd->Pipeline)
|
||||
{
|
||||
vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator);
|
||||
bd->Pipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoMain;
|
||||
if (pipeline_info != pipeline_info_in)
|
||||
*pipeline_info = *pipeline_info_in;
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = &pipeline_info->PipelineRenderingCreateInfo;
|
||||
if (v->UseDynamicRendering && pipeline_rendering_create_info->pColorAttachmentFormats != nullptr)
|
||||
{
|
||||
// Deep copy buffer to reduce error-rate for end user (#8282)
|
||||
ImVector<VkFormat> formats;
|
||||
formats.resize((int)pipeline_rendering_create_info->colorAttachmentCount);
|
||||
memcpy(formats.Data, pipeline_rendering_create_info->pColorAttachmentFormats, (size_t)formats.size_in_bytes());
|
||||
formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats);
|
||||
pipeline_rendering_create_info->pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data;
|
||||
}
|
||||
#endif
|
||||
bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, pipeline_info);
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
@@ -1130,10 +1261,12 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
|
||||
|
||||
if (bd->TexCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }
|
||||
if (bd->TexCommandPool) { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }
|
||||
if (bd->TexSampler) { vkDestroySampler(v->Device, bd->TexSampler, v->Allocator); bd->TexSampler = VK_NULL_HANDLE; }
|
||||
if (bd->SamplerLinear) { vkDestroySampler(v->Device, bd->SamplerLinear, v->Allocator); bd->SamplerLinear = VK_NULL_HANDLE; }
|
||||
if (bd->SamplerNearest) { vkDestroySampler(v->Device, bd->SamplerNearest, v->Allocator); bd->SamplerNearest = VK_NULL_HANDLE; }
|
||||
if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
|
||||
if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
|
||||
if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
|
||||
if (bd->DescriptorSetLayoutTexture) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayoutTexture, v->Allocator); bd->DescriptorSetLayoutTexture = VK_NULL_HANDLE; }
|
||||
if (bd->DescriptorSetLayoutSampler) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayoutSampler, v->Allocator); bd->DescriptorSetLayoutSampler = VK_NULL_HANDLE; }
|
||||
if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
|
||||
if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
|
||||
if (bd->DescriptorPool) { vkDestroyDescriptorPool(v->Device, bd->DescriptorPool, v->Allocator); bd->DescriptorPool = VK_NULL_HANDLE; }
|
||||
@@ -1229,18 +1362,24 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplVulkan_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplVulkan_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplVulkan_DrawCallback_SetSamplerNearest;
|
||||
|
||||
// Sanity checks
|
||||
IM_ASSERT(info->Instance != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->Device != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->Queue != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->MinImageCount >= 2);
|
||||
IM_ASSERT(info->ImageCount >= info->MinImageCount);
|
||||
if (info->DescriptorPool != VK_NULL_HANDLE) // Either DescriptorPool or DescriptorPoolSize must be set, not both!
|
||||
IM_ASSERT(info->DescriptorPoolSize == 0);
|
||||
else
|
||||
IM_ASSERT(info->DescriptorPoolSize > 0);
|
||||
IM_ASSERT(info->MinImageCount >= 2);
|
||||
IM_ASSERT(info->ImageCount >= info->MinImageCount);
|
||||
if (info->UseDynamicRendering == false)
|
||||
IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
|
||||
if (info->UseDynamicRendering)
|
||||
IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE);
|
||||
|
||||
bd->VulkanInitInfo = *info;
|
||||
|
||||
@@ -1248,17 +1387,6 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
|
||||
vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties);
|
||||
bd->NonCoherentAtomSize = properties.limits.nonCoherentAtomSize;
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
if (v->PipelineRenderingCreateInfo.pColorAttachmentFormats != NULL)
|
||||
{
|
||||
// Deep copy buffer to reduce error-rate for end user (#8282)
|
||||
VkFormat* formats_copy = (VkFormat*)IM_ALLOC(sizeof(VkFormat) * v->PipelineRenderingCreateInfo.colorAttachmentCount);
|
||||
memcpy(formats_copy, v->PipelineRenderingCreateInfo.pColorAttachmentFormats, sizeof(VkFormat) * v->PipelineRenderingCreateInfo.colorAttachmentCount);
|
||||
v->PipelineRenderingCreateInfo.pColorAttachmentFormats = formats_copy;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ImGui_ImplVulkan_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplVulkan_CreateDeviceObjects() failed!"); // <- Can't be hit yet.
|
||||
|
||||
@@ -1270,15 +1398,14 @@ void ImGui_ImplVulkan_Shutdown()
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplVulkan_DestroyDeviceObjects();
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
IM_FREE((void*)const_cast<VkFormat*>(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pColorAttachmentFormats));
|
||||
#endif
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
@@ -1305,7 +1432,7 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
|
||||
|
||||
// Register a texture by creating a descriptor
|
||||
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
|
||||
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)
|
||||
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
@@ -1318,28 +1445,36 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = pool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &bd->DescriptorSetLayout;
|
||||
alloc_info.pSetLayouts = &bd->DescriptorSetLayoutTexture;
|
||||
VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Update the Descriptor Set:
|
||||
if (descriptor_set != VK_NULL_HANDLE)
|
||||
{
|
||||
VkDescriptorImageInfo desc_image[1] = {};
|
||||
desc_image[0].sampler = sampler;
|
||||
desc_image[0].imageView = image_view;
|
||||
desc_image[0].imageLayout = image_layout;
|
||||
VkWriteDescriptorSet write_desc[1] = {};
|
||||
write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write_desc[0].dstSet = descriptor_set;
|
||||
write_desc[0].descriptorCount = 1;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
write_desc[0].pImageInfo = desc_image;
|
||||
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, nullptr);
|
||||
}
|
||||
return descriptor_set;
|
||||
}
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)
|
||||
{
|
||||
IM_UNUSED(sampler);
|
||||
return ImGui_ImplVulkan_AddTexture(image_view, image_layout);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
@@ -1369,7 +1504,7 @@ void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulk
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
|
||||
//-------------------------------------------------------------------------
|
||||
// You probably do NOT need to use or care about those functions.
|
||||
// Those functions only exist because:
|
||||
@@ -1379,7 +1514,7 @@ void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulk
|
||||
// but it is too much code to duplicate everywhere so we exceptionally expose them.
|
||||
//
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
|
||||
// You may read this code to learn about Vulkan, but it is recommended you use your own custom tailored code to do equivalent work.
|
||||
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@@ -1557,7 +1692,7 @@ int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_m
|
||||
}
|
||||
|
||||
// Also destroy old swap chain and in-flight frames data, if any.
|
||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count)
|
||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage)
|
||||
{
|
||||
VkResult err;
|
||||
VkSwapchainKHR old_swapchain = wd->Swapchain;
|
||||
@@ -1596,10 +1731,15 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
info.imageFormat = wd->SurfaceFormat.format;
|
||||
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
|
||||
info.imageArrayLayers = 1;
|
||||
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | image_usage;
|
||||
info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
|
||||
info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform;
|
||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
|
||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
else if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
|
||||
info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
|
||||
else
|
||||
IM_ASSERT(false && "No supported composite alpha mode found!");
|
||||
info.presentMode = wd->PresentMode;
|
||||
info.clipped = VK_TRUE;
|
||||
info.oldSwapchain = old_swapchain;
|
||||
@@ -1623,7 +1763,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
check_vk_result(err);
|
||||
VkImage backbuffers[16] = {};
|
||||
IM_ASSERT(wd->ImageCount >= min_image_count);
|
||||
IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));
|
||||
IM_ASSERT(wd->ImageCount < IM_COUNTOF(backbuffers));
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
|
||||
check_vk_result(err);
|
||||
|
||||
@@ -1641,15 +1781,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
// Create the Render Pass
|
||||
if (wd->UseDynamicRendering == false)
|
||||
{
|
||||
VkAttachmentDescription attachment = {};
|
||||
attachment.format = wd->SurfaceFormat.format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = wd->ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
VkAttachmentDescription attachment = wd->AttachmentDesc;
|
||||
if (attachment.format == VK_FORMAT_UNDEFINED)
|
||||
attachment.format = wd->SurfaceFormat.format;
|
||||
VkAttachmentReference color_attachment = {};
|
||||
color_attachment.attachment = 0;
|
||||
color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
@@ -1724,11 +1858,14 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
}
|
||||
|
||||
// Create or resize window
|
||||
void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
|
||||
// - 2025/09/26: v1.92.4 added a trailing 'VkImageUsageFlags image_usage' parameter which is usually VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.
|
||||
void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count, VkImageUsageFlags image_usage)
|
||||
{
|
||||
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
|
||||
(void)instance;
|
||||
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
|
||||
IM_ASSERT(wd->Surface != VK_NULL_HANDLE);
|
||||
IM_UNUSED(instance);
|
||||
|
||||
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count, image_usage);
|
||||
ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
|
||||
|
||||
// FIXME: to submit the command buffer, we need a queue. In the examples folder, the ImGui_ImplVulkanH_CreateOrResizeWindow function is called
|
||||
@@ -1738,7 +1875,6 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
|
||||
VkCommandPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
pool_info.queueFamilyIndex = queue_family;
|
||||
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
VkResult err = vkCreateCommandPool(device, &pool_info, allocator, &command_pool);
|
||||
check_vk_result(err);
|
||||
|
||||
@@ -1810,6 +1946,7 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
IM_UNUSED(instance);
|
||||
vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
|
||||
//vkQueueWaitIdle(bd->Queue);
|
||||
|
||||
@@ -1822,9 +1959,11 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
|
||||
vkDestroyPipeline(device, wd->Pipeline, allocator);
|
||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
|
||||
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
|
||||
|
||||
*wd = ImGui_ImplVulkanH_Window();
|
||||
wd->RenderPass = VK_NULL_HANDLE;
|
||||
wd->Swapchain = VK_NULL_HANDLE;
|
||||
wd->Width = wd->Height = 0;
|
||||
wd->FrameIndex = wd->ImageCount = wd->SemaphoreCount = wd->SemaphoreIndex = 0;
|
||||
//vkDestroySurfaceKHR(instance, wd->Surface, allocator); // v1.92.6 (~2026-01-16): because wd->Surface is user provided we don't attempt to destroy it ourself.
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
@@ -41,9 +41,20 @@
|
||||
// If you have no idea what this is, leave it alone!
|
||||
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
||||
|
||||
// Convenience support for Volk
|
||||
// [Configuration] Convenience support for Volk
|
||||
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
|
||||
// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,
|
||||
// for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')
|
||||
//#define IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <Volk/volk.h>
|
||||
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <volk.h> // Default
|
||||
// Reminder: make those changes in your imconfig.h file, not here!
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#endif
|
||||
|
||||
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
|
||||
#define VK_NO_PROTOTYPES
|
||||
@@ -54,7 +65,11 @@
|
||||
|
||||
// Vulkan includes
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME
|
||||
#include IMGUI_IMPL_VULKAN_VOLK_FILENAME
|
||||
#else
|
||||
#include <volk.h>
|
||||
#endif
|
||||
#else
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
@@ -63,7 +78,20 @@
|
||||
#endif
|
||||
|
||||
// Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
|
||||
#define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (8) // Minimum per atlas
|
||||
#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE (8) // Minimum per atlas
|
||||
#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE (2) // Minimum for linear + nearest
|
||||
|
||||
// Specify settings to create pipeline and swapchain
|
||||
struct ImGui_ImplVulkan_PipelineInfo
|
||||
{
|
||||
VkRenderPass RenderPass; // Ignored if using dynamic rendering
|
||||
uint32_t Subpass; //
|
||||
VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
|
||||
ImVector<VkDynamicState> ExtraDynamicStates; // Optional, allows to insert more dynamic states into our VkPipeline
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR
|
||||
#endif
|
||||
};
|
||||
|
||||
// Initialization data, for ImGui_ImplVulkan_Init()
|
||||
// [Please zero-clear before use!]
|
||||
@@ -72,7 +100,7 @@
|
||||
// and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
|
||||
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
|
||||
// - About dynamic rendering:
|
||||
// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
|
||||
// - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.
|
||||
struct ImGui_ImplVulkan_InitInfo
|
||||
{
|
||||
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)
|
||||
@@ -82,29 +110,32 @@ struct ImGui_ImplVulkan_InitInfo
|
||||
uint32_t QueueFamily;
|
||||
VkQueue Queue;
|
||||
VkDescriptorPool DescriptorPool; // See requirements in note above; ignored if using DescriptorPoolSize > 0
|
||||
VkRenderPass RenderPass; // Ignored if using dynamic rendering
|
||||
uint32_t DescriptorPoolSize; // Optional: set to create internal ImageView descriptor pool automatically instead of using DescriptorPool.
|
||||
uint32_t MinImageCount; // >= 2
|
||||
uint32_t ImageCount; // >= MinImageCount
|
||||
VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
|
||||
VkPipelineCache PipelineCache; // Optional
|
||||
|
||||
// (Optional)
|
||||
VkPipelineCache PipelineCache;
|
||||
uint32_t Subpass;
|
||||
|
||||
// (Optional) Set to create internal descriptor pool instead of using DescriptorPool
|
||||
uint32_t DescriptorPoolSize;
|
||||
// Pipeline
|
||||
ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user)
|
||||
//VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead
|
||||
//uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead
|
||||
//VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead
|
||||
//VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead
|
||||
|
||||
// (Optional) Dynamic Rendering
|
||||
// Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
|
||||
// Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo.
|
||||
bool UseDynamicRendering;
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo;
|
||||
#endif
|
||||
|
||||
// (Optional) Allocation, Debugging
|
||||
const VkAllocationCallbacks* Allocator;
|
||||
void (*CheckVkResultFn)(VkResult err);
|
||||
VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory.
|
||||
|
||||
// (Optional) Customize default vertex/fragment shaders.
|
||||
// - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults.
|
||||
// - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage.
|
||||
VkShaderModuleCreateInfo CustomShaderVertCreateInfo;
|
||||
VkShaderModuleCreateInfo CustomShaderFragCreateInfo;
|
||||
};
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
@@ -114,15 +145,22 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111)
|
||||
// The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR))
|
||||
// Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering.
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info);
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// Register a texture (VkDescriptorSet == ImTextureID)
|
||||
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem
|
||||
// Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
|
||||
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout);
|
||||
// Register a texture (VkDescriptorSet for a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE == ImTextureID)
|
||||
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); // Ignore VkSampler
|
||||
#endif
|
||||
|
||||
// Optional: load Vulkan functions with a custom function loader
|
||||
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
|
||||
@@ -143,6 +181,7 @@ struct ImGui_ImplVulkan_RenderState
|
||||
// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.
|
||||
//
|
||||
// You probably do NOT need to use or care about those functions.
|
||||
// WE DO NOT PROVIDE STRONG GUARANTEES OF BACKWARD/FORWARD COMPATIBILITY.
|
||||
// Those functions only exist because:
|
||||
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
|
||||
// 2) the multi-viewport / platform window implementation needs them internally.
|
||||
@@ -151,20 +190,18 @@ struct ImGui_ImplVulkan_RenderState
|
||||
//
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain,
|
||||
// render pass, frame buffers, etc.). You may read this code if you are curious, but
|
||||
// it is recommended you use you own custom tailored code to do equivalent work.
|
||||
//
|
||||
// We don't provide a strong guarantee that we won't change those functions API.
|
||||
// it is recommended you use your own custom tailored code to do equivalent work.
|
||||
//
|
||||
// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used
|
||||
// by the regular ImGui_ImplVulkan_XXX functions).
|
||||
// by the regular ImGui_ImplVulkan_XXX functions.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
struct ImGui_ImplVulkanH_Frame;
|
||||
struct ImGui_ImplVulkanH_Window;
|
||||
|
||||
// Helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator);
|
||||
IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
|
||||
IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
|
||||
IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance);
|
||||
@@ -194,30 +231,48 @@ struct ImGui_ImplVulkanH_FrameSemaphores
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
|
||||
struct ImGui_ImplVulkanH_Window
|
||||
{
|
||||
int Width;
|
||||
int Height;
|
||||
VkSwapchainKHR Swapchain;
|
||||
VkSurfaceKHR Surface;
|
||||
VkSurfaceFormatKHR SurfaceFormat;
|
||||
VkPresentModeKHR PresentMode;
|
||||
VkRenderPass RenderPass;
|
||||
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
|
||||
bool UseDynamicRendering;
|
||||
bool ClearEnable;
|
||||
VkClearValue ClearValue;
|
||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
||||
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
||||
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
|
||||
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
|
||||
// Input
|
||||
bool UseDynamicRendering;
|
||||
VkSurfaceKHR Surface; // Surface created and destroyed by caller.
|
||||
VkSurfaceFormatKHR SurfaceFormat;
|
||||
VkPresentModeKHR PresentMode;
|
||||
VkAttachmentDescription AttachmentDesc; // RenderPass creation: main attachment description.
|
||||
VkClearValue ClearValue; // RenderPass creation: clear value when using VK_ATTACHMENT_LOAD_OP_CLEAR.
|
||||
|
||||
// Internal
|
||||
int Width; // Generally same as passed to ImGui_ImplVulkanH_CreateOrResizeWindow()
|
||||
int Height;
|
||||
VkSwapchainKHR Swapchain;
|
||||
VkRenderPass RenderPass;
|
||||
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
|
||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
||||
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
||||
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
|
||||
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
|
||||
ImVector<ImGui_ImplVulkanH_Frame> Frames;
|
||||
ImVector<ImGui_ImplVulkanH_FrameSemaphores> FrameSemaphores;
|
||||
|
||||
ImGui_ImplVulkanH_Window()
|
||||
{
|
||||
memset((void*)this, 0, sizeof(*this));
|
||||
PresentMode = (VkPresentModeKHR)~0; // Ensure we get an error if user doesn't set this.
|
||||
ClearEnable = true;
|
||||
|
||||
// Parameters to create SwapChain
|
||||
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; // Ensure we get an error if user doesn't set this.
|
||||
|
||||
// Parameters to create RenderPass
|
||||
AttachmentDesc.format = VK_FORMAT_UNDEFINED; // Will automatically use wd->SurfaceFormat.format.
|
||||
AttachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
AttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
AttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
AttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
AttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
AttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
AttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// dear imgui: Renderer for WebGPU
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW)
|
||||
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
|
||||
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
@@ -8,6 +8,8 @@
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
@@ -18,6 +20,11 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257)
|
||||
// 2026-03-09: Removed support for Emscripten < 4.0.10. (#9281)
|
||||
// 2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465)
|
||||
// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes.
|
||||
// 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083)
|
||||
@@ -45,24 +52,20 @@
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
|
||||
#endif
|
||||
#else
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_wgpu.h"
|
||||
#include <limits.h>
|
||||
#include <webgpu/webgpu.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
// One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
|
||||
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK must be defined!
|
||||
#endif
|
||||
#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#error Emscripten <4.0.10 with '-sUSE_WEBGPU=1' is not supported anymore.
|
||||
#endif
|
||||
|
||||
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
|
||||
// Using type alias until WGPU adopts the same naming convention (#8369)
|
||||
using WGPUProgrammableStageDescriptor = WGPUComputeState;
|
||||
@@ -81,11 +84,13 @@ struct ImGui_ImplWGPU_Texture
|
||||
|
||||
struct RenderResources
|
||||
{
|
||||
WGPUSampler Sampler = nullptr; // Sampler for textures
|
||||
WGPUBuffer Uniforms = nullptr; // Shader uniforms
|
||||
WGPUBindGroup CommonBindGroup = nullptr; // Resources bind-group to bind the common resources to pipeline
|
||||
ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
|
||||
WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
|
||||
WGPUSampler SamplerLinear = nullptr; // Bilinear sampler
|
||||
WGPUSampler SamplerNearest = nullptr; // Nearest/point sampler
|
||||
WGPUBuffer Uniforms = nullptr; // Shader uniforms
|
||||
WGPUBindGroup CommonBindGroupLinear = nullptr; // Common bind-group bound to group 0 (uniforms + SamplerLinear)
|
||||
WGPUBindGroup CommonBindGroupNearest = nullptr; // Common bind-group bound to group 0 (uniforms + SamplerNearest)
|
||||
ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
|
||||
WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
|
||||
};
|
||||
|
||||
struct FrameResources
|
||||
@@ -112,6 +117,7 @@ struct ImGui_ImplWGPU_Data
|
||||
WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined;
|
||||
WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined;
|
||||
WGPURenderPipeline pipelineState = nullptr;
|
||||
ImGui_ImplWGPU_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
|
||||
|
||||
RenderResources renderResources;
|
||||
FrameResources* pFrameResources = nullptr;
|
||||
@@ -184,6 +190,60 @@ fn main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
}
|
||||
)";
|
||||
|
||||
// Same shader as __shader_vert_wgsl[] but compiled as SPIRV.
|
||||
// 'wgslc -o vert.spv vert.wgsl' + 'binary_to_compressed_c -u8 -nocompress vert.spv'
|
||||
static const unsigned char __shader_vert_spirv[1996] =
|
||||
{
|
||||
3,2,35,7,0,3,1,0,1,0,23,0,90,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,12,0,0,0,0,0,78,0,0,0,109,97,105,110,0,0,0,0,8,0,0,0,12,0,0,0,13,0,0,0,16,0,0,0,18,0,0,0,19,
|
||||
0,0,0,21,0,0,0,71,0,4,0,4,0,0,0,6,0,0,0,16,0,0,0,72,0,5,0,3,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,71,0,3,0,3,0,0,0,2,0,0,0,71,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,1,0,0,0,33,0,0,0,0,0,
|
||||
0,0,71,0,3,0,1,0,0,0,24,0,0,0,71,0,4,0,8,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,12,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,13,0,0,0,30,0,0,0,2,0,0,0,71,0,4,0,16,0,0,0,11,0,0,0,0,0,0,0,71,0,4,0,18,
|
||||
0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,21,0,0,0,11,0,0,0,1,0,0,0,21,0,4,0,6,0,0,0,32,0,0,0,0,0,0,0,23,0,4,0,5,0,0,0,6,0,0,0,4,0,0,0,43,0,4,0,6,0,0,0,7,0,
|
||||
0,0,5,0,0,0,28,0,4,0,4,0,0,0,5,0,0,0,7,0,0,0,30,0,3,0,3,0,0,0,4,0,0,0,32,0,4,0,2,0,0,0,2,0,0,0,3,0,0,0,59,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,22,0,3,0,11,0,0,0,32,0,0,0,23,0,4,0,10,0,0,0,
|
||||
11,0,0,0,2,0,0,0,32,0,4,0,9,0,0,0,1,0,0,0,10,0,0,0,59,0,4,0,9,0,0,0,8,0,0,0,1,0,0,0,59,0,4,0,9,0,0,0,12,0,0,0,1,0,0,0,23,0,4,0,15,0,0,0,11,0,0,0,4,0,0,0,32,0,4,0,14,0,0,0,1,0,0,0,15,
|
||||
0,0,0,59,0,4,0,14,0,0,0,13,0,0,0,1,0,0,0,32,0,4,0,17,0,0,0,3,0,0,0,15,0,0,0,59,0,4,0,17,0,0,0,16,0,0,0,3,0,0,0,59,0,4,0,17,0,0,0,18,0,0,0,3,0,0,0,32,0,4,0,20,0,0,0,3,0,0,0,10,0,0,0,
|
||||
59,0,4,0,20,0,0,0,19,0,0,0,3,0,0,0,32,0,4,0,22,0,0,0,3,0,0,0,11,0,0,0,59,0,4,0,22,0,0,0,21,0,0,0,3,0,0,0,30,0,5,0,24,0,0,0,15,0,0,0,15,0,0,0,10,0,0,0,30,0,5,0,25,0,0,0,10,0,0,0,10,
|
||||
0,0,0,15,0,0,0,33,0,4,0,27,0,0,0,24,0,0,0,25,0,0,0,32,0,4,0,30,0,0,0,7,0,0,0,24,0,0,0,46,0,3,0,24,0,0,0,31,0,0,0,32,0,4,0,33,0,0,0,7,0,0,0,15,0,0,0,43,0,4,0,6,0,0,0,34,0,0,0,0,0,0,
|
||||
0,24,0,4,0,36,0,0,0,15,0,0,0,4,0,0,0,43,0,4,0,11,0,0,0,40,0,0,0,0,0,0,0,43,0,4,0,11,0,0,0,41,0,0,0,0,0,128,63,43,0,4,0,6,0,0,0,44,0,0,0,1,0,0,0,32,0,4,0,47,0,0,0,7,0,0,0,10,0,0,0,43,
|
||||
0,4,0,6,0,0,0,48,0,0,0,2,0,0,0,33,0,4,0,52,0,0,0,36,0,0,0,6,0,0,0,43,0,4,0,6,0,0,0,55,0,0,0,16,0,0,0,32,0,4,0,57,0,0,0,2,0,0,0,5,0,0,0,43,0,4,0,6,0,0,0,66,0,0,0,32,0,0,0,43,0,4,0,6,
|
||||
0,0,0,72,0,0,0,48,0,0,0,19,0,2,0,79,0,0,0,33,0,3,0,80,0,0,0,79,0,0,0,54,0,5,0,24,0,0,0,23,0,0,0,0,0,0,0,27,0,0,0,55,0,3,0,25,0,0,0,26,0,0,0,248,0,2,0,28,0,0,0,59,0,5,0,30,0,0,0,29,
|
||||
0,0,0,7,0,0,0,31,0,0,0,65,0,5,0,33,0,0,0,32,0,0,0,29,0,0,0,34,0,0,0,57,0,5,0,36,0,0,0,35,0,0,0,37,0,0,0,34,0,0,0,81,0,5,0,10,0,0,0,38,0,0,0,26,0,0,0,0,0,0,0,80,0,6,0,15,0,0,0,39,0,
|
||||
0,0,38,0,0,0,40,0,0,0,41,0,0,0,145,0,5,0,15,0,0,0,42,0,0,0,35,0,0,0,39,0,0,0,62,0,4,0,32,0,0,0,42,0,0,0,0,0,0,0,65,0,5,0,33,0,0,0,43,0,0,0,29,0,0,0,44,0,0,0,81,0,5,0,15,0,0,0,45,0,
|
||||
0,0,26,0,0,0,2,0,0,0,62,0,4,0,43,0,0,0,45,0,0,0,0,0,0,0,65,0,5,0,47,0,0,0,46,0,0,0,29,0,0,0,48,0,0,0,81,0,5,0,10,0,0,0,49,0,0,0,26,0,0,0,1,0,0,0,62,0,4,0,46,0,0,0,49,0,0,0,0,0,0,0,
|
||||
61,0,5,0,24,0,0,0,50,0,0,0,29,0,0,0,0,0,0,0,254,0,2,0,50,0,0,0,56,0,1,0,54,0,5,0,36,0,0,0,37,0,0,0,0,0,0,0,52,0,0,0,55,0,3,0,6,0,0,0,51,0,0,0,248,0,2,0,53,0,0,0,134,0,5,0,6,0,0,0,54,
|
||||
0,0,0,51,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,56,0,0,0,1,0,0,0,34,0,0,0,54,0,0,0,61,0,5,0,5,0,0,0,58,0,0,0,56,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,59,0,0,0,58,0,0,0,128,0,5,0,6,0,0,0,60,0,
|
||||
0,0,55,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,61,0,0,0,60,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,62,0,0,0,1,0,0,0,34,0,0,0,61,0,0,0,61,0,5,0,5,0,0,0,63,0,0,0,62,0,0,0,0,0,0,0,124,0,4,0,15,0,0,
|
||||
0,64,0,0,0,63,0,0,0,128,0,5,0,6,0,0,0,65,0,0,0,66,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,67,0,0,0,65,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,68,0,0,0,1,0,0,0,34,0,0,0,67,0,0,0,61,0,5,0,5,0,0,0,
|
||||
69,0,0,0,68,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,70,0,0,0,69,0,0,0,128,0,5,0,6,0,0,0,71,0,0,0,72,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,73,0,0,0,71,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,74,0,0,0,
|
||||
1,0,0,0,34,0,0,0,73,0,0,0,61,0,5,0,5,0,0,0,75,0,0,0,74,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,76,0,0,0,75,0,0,0,80,0,7,0,36,0,0,0,77,0,0,0,59,0,0,0,64,0,0,0,70,0,0,0,76,0,0,0,254,0,2,0,77,
|
||||
0,0,0,56,0,1,0,54,0,5,0,79,0,0,0,78,0,0,0,0,0,0,0,80,0,0,0,248,0,2,0,81,0,0,0,61,0,5,0,10,0,0,0,82,0,0,0,8,0,0,0,0,0,0,0,61,0,5,0,10,0,0,0,83,0,0,0,12,0,0,0,0,0,0,0,61,0,5,0,15,0,0,
|
||||
0,84,0,0,0,13,0,0,0,0,0,0,0,80,0,6,0,25,0,0,0,85,0,0,0,82,0,0,0,83,0,0,0,84,0,0,0,57,0,5,0,24,0,0,0,86,0,0,0,23,0,0,0,85,0,0,0,81,0,5,0,15,0,0,0,87,0,0,0,86,0,0,0,0,0,0,0,62,0,4,0,
|
||||
16,0,0,0,87,0,0,0,0,0,0,0,81,0,5,0,15,0,0,0,88,0,0,0,86,0,0,0,1,0,0,0,62,0,4,0,18,0,0,0,88,0,0,0,0,0,0,0,81,0,5,0,10,0,0,0,89,0,0,0,86,0,0,0,2,0,0,0,62,0,4,0,19,0,0,0,89,0,0,0,0,0,
|
||||
0,0,62,0,4,0,21,0,0,0,41,0,0,0,0,0,0,0,253,0,1,0,56,0,1,0,
|
||||
};
|
||||
|
||||
// Same shader as __shader_frag_wgsl[] but compiled as SPIRV.
|
||||
// 'wgslc -o frag.spv frag.wgsl' + 'binary_to_compressed_c -u8 -nocompress frag.spv'
|
||||
static const unsigned char __shader_frag_spirv[1392] =
|
||||
{
|
||||
3,2,35,7,0,3,1,0,1,0,23,0,60,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,48,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,9,0,4,0,0,0,51,0,0,0,109,
|
||||
97,105,110,0,0,0,0,15,0,0,0,18,0,0,0,19,0,0,0,22,0,0,0,16,0,3,0,51,0,0,0,7,0,0,0,71,0,4,0,4,0,0,0,6,0,0,0,16,0,0,0,72,0,5,0,3,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,71,0,3,0,3,0,0,0,2,0,0,
|
||||
0,71,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,1,0,0,0,33,0,0,0,0,0,0,0,71,0,3,0,1,0,0,0,24,0,0,0,71,0,4,0,8,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,8,0,0,0,33,0,0,0,1,0,0,0,71,0,4,0,11,0,0,
|
||||
0,34,0,0,0,1,0,0,0,71,0,4,0,11,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,15,0,0,0,11,0,0,0,15,0,0,0,71,0,4,0,18,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,22,0,0,0,30,
|
||||
0,0,0,0,0,0,0,21,0,4,0,6,0,0,0,32,0,0,0,0,0,0,0,23,0,4,0,5,0,0,0,6,0,0,0,4,0,0,0,43,0,4,0,6,0,0,0,7,0,0,0,5,0,0,0,28,0,4,0,4,0,0,0,5,0,0,0,7,0,0,0,30,0,3,0,3,0,0,0,4,0,0,0,32,0,4,0,
|
||||
2,0,0,0,2,0,0,0,3,0,0,0,59,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,26,0,2,0,10,0,0,0,32,0,4,0,9,0,0,0,0,0,0,0,10,0,0,0,59,0,4,0,9,0,0,0,8,0,0,0,0,0,0,0,22,0,3,0,14,0,0,0,32,0,0,0,25,0,9,0,13,
|
||||
0,0,0,14,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,32,0,4,0,12,0,0,0,0,0,0,0,13,0,0,0,59,0,4,0,12,0,0,0,11,0,0,0,0,0,0,0,23,0,4,0,17,0,0,0,14,0,0,0,4,0,0,0,32,0,4,0,16,
|
||||
0,0,0,1,0,0,0,17,0,0,0,59,0,4,0,16,0,0,0,15,0,0,0,1,0,0,0,59,0,4,0,16,0,0,0,18,0,0,0,1,0,0,0,23,0,4,0,21,0,0,0,14,0,0,0,2,0,0,0,32,0,4,0,20,0,0,0,1,0,0,0,21,0,0,0,59,0,4,0,20,0,0,0,
|
||||
19,0,0,0,1,0,0,0,32,0,4,0,23,0,0,0,3,0,0,0,17,0,0,0,59,0,4,0,23,0,0,0,22,0,0,0,3,0,0,0,30,0,5,0,25,0,0,0,17,0,0,0,17,0,0,0,21,0,0,0,33,0,4,0,27,0,0,0,17,0,0,0,25,0,0,0,27,0,3,0,34,
|
||||
0,0,0,13,0,0,0,23,0,4,0,38,0,0,0,14,0,0,0,3,0,0,0,32,0,4,0,40,0,0,0,2,0,0,0,5,0,0,0,43,0,4,0,6,0,0,0,41,0,0,0,0,0,0,0,43,0,4,0,6,0,0,0,42,0,0,0,4,0,0,0,19,0,2,0,52,0,0,0,33,0,3,0,53,
|
||||
0,0,0,52,0,0,0,54,0,5,0,17,0,0,0,24,0,0,0,0,0,0,0,27,0,0,0,55,0,3,0,25,0,0,0,26,0,0,0,248,0,2,0,28,0,0,0,81,0,5,0,17,0,0,0,29,0,0,0,26,0,0,0,1,0,0,0,61,0,5,0,13,0,0,0,30,0,0,0,11,0,
|
||||
0,0,0,0,0,0,61,0,5,0,10,0,0,0,31,0,0,0,8,0,0,0,0,0,0,0,81,0,5,0,21,0,0,0,32,0,0,0,26,0,0,0,2,0,0,0,86,0,5,0,34,0,0,0,33,0,0,0,30,0,0,0,31,0,0,0,87,0,6,0,17,0,0,0,35,0,0,0,33,0,0,0,
|
||||
32,0,0,0,0,0,0,0,133,0,5,0,17,0,0,0,36,0,0,0,29,0,0,0,35,0,0,0,79,0,8,0,38,0,0,0,37,0,0,0,36,0,0,0,36,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,65,0,6,0,40,0,0,0,39,0,0,0,1,0,0,0,41,0,0,0,42,0,
|
||||
0,0,61,0,5,0,5,0,0,0,43,0,0,0,39,0,0,0,0,0,0,0,81,0,5,0,6,0,0,0,44,0,0,0,43,0,0,0,0,0,0,0,124,0,4,0,14,0,0,0,45,0,0,0,44,0,0,0,80,0,6,0,38,0,0,0,46,0,0,0,45,0,0,0,45,0,0,0,45,0,0,0,
|
||||
12,0,7,0,38,0,0,0,47,0,0,0,48,0,0,0,26,0,0,0,37,0,0,0,46,0,0,0,81,0,5,0,14,0,0,0,49,0,0,0,36,0,0,0,3,0,0,0,80,0,5,0,17,0,0,0,50,0,0,0,47,0,0,0,49,0,0,0,254,0,2,0,50,0,0,0,56,0,1,0,
|
||||
54,0,5,0,52,0,0,0,51,0,0,0,0,0,0,0,53,0,0,0,248,0,2,0,54,0,0,0,61,0,5,0,17,0,0,0,55,0,0,0,15,0,0,0,0,0,0,0,61,0,5,0,17,0,0,0,56,0,0,0,18,0,0,0,0,0,0,0,61,0,5,0,21,0,0,0,57,0,0,0,19,
|
||||
0,0,0,0,0,0,0,80,0,6,0,25,0,0,0,58,0,0,0,55,0,0,0,56,0,0,0,57,0,0,0,57,0,5,0,17,0,0,0,59,0,0,0,24,0,0,0,58,0,0,0,62,0,4,0,22,0,0,0,59,0,0,0,0,0,0,0,253,0,1,0,56,0,1,0,
|
||||
};
|
||||
|
||||
static void SafeRelease(ImDrawIdx*& res)
|
||||
{
|
||||
if (res)
|
||||
@@ -240,9 +300,11 @@ static void SafeRelease(WGPUShaderModule& res)
|
||||
}
|
||||
static void SafeRelease(RenderResources& res)
|
||||
{
|
||||
SafeRelease(res.Sampler);
|
||||
SafeRelease(res.SamplerLinear);
|
||||
SafeRelease(res.SamplerNearest);
|
||||
SafeRelease(res.Uniforms);
|
||||
SafeRelease(res.CommonBindGroup);
|
||||
SafeRelease(res.CommonBindGroupLinear);
|
||||
SafeRelease(res.CommonBindGroupNearest);
|
||||
SafeRelease(res.ImageBindGroupLayout);
|
||||
};
|
||||
|
||||
@@ -254,31 +316,42 @@ static void SafeRelease(FrameResources& res)
|
||||
SafeRelease(res.VertexBufferHost);
|
||||
}
|
||||
|
||||
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const char* wgsl_source)
|
||||
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source)
|
||||
{
|
||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||
IM_UNUSED(bd);
|
||||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUShaderSourceWGSL wgsl_desc = {};
|
||||
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
|
||||
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
|
||||
#else
|
||||
WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
|
||||
wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
||||
wgsl_desc.code = wgsl_source;
|
||||
#endif
|
||||
|
||||
WGPUShaderModuleDescriptor desc = {};
|
||||
desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&wgsl_desc);
|
||||
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
|
||||
|
||||
WGPUProgrammableStageDescriptor stage_desc = {};
|
||||
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
|
||||
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
||||
#endif
|
||||
return stage_desc;
|
||||
}
|
||||
|
||||
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length)
|
||||
{
|
||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||
|
||||
WGPUShaderSourceSPIRV spirv_desc = {};
|
||||
spirv_desc.chain.sType = WGPUSType_ShaderSourceSPIRV;
|
||||
spirv_desc.code = (const uint32_t *)spirv_binary;
|
||||
spirv_desc.codeSize = ((uint32_t)(spirv_length / 4));
|
||||
|
||||
WGPUShaderModuleDescriptor desc = {};
|
||||
desc.nextInChain = (WGPUChainedStruct*)&spirv_desc;
|
||||
|
||||
WGPUProgrammableStageDescriptor stage_desc = {};
|
||||
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
|
||||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
||||
#else
|
||||
stage_desc.entryPoint = "main";
|
||||
#endif
|
||||
return stage_desc;
|
||||
}
|
||||
|
||||
@@ -353,15 +426,19 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
|
||||
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert));
|
||||
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx));
|
||||
wgpuRenderPassEncoderSetPipeline(ctx, bd->pipelineState);
|
||||
wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroup, 0, nullptr);
|
||||
wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr);
|
||||
|
||||
// Setup blend factor
|
||||
WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
|
||||
wgpuRenderPassEncoderSetBlendConstant(ctx, &blend_color);
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplWGPU_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplWGPU_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); wgpuRenderPassEncoderSetBindGroup(bd->RenderState->RenderPassEncoder, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr); }
|
||||
static void ImGui_ImplWGPU_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); wgpuRenderPassEncoderSetBindGroup(bd->RenderState->RenderPassEncoder, 0, bd->renderResources.CommonBindGroupNearest, 0, nullptr); }
|
||||
|
||||
// Render function
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
@@ -397,10 +474,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
WGPUBufferDescriptor vb_desc =
|
||||
{
|
||||
nullptr,
|
||||
"Dear ImGui Vertex buffer",
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPU_STRLEN,
|
||||
#endif
|
||||
{ "Dear ImGui Vertex buffer", WGPU_STRLEN, },
|
||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
|
||||
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
|
||||
false
|
||||
@@ -424,10 +498,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
WGPUBufferDescriptor ib_desc =
|
||||
{
|
||||
nullptr,
|
||||
"Dear ImGui Index buffer",
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPU_STRLEN,
|
||||
#endif
|
||||
{ "Dear ImGui Index buffer", WGPU_STRLEN, },
|
||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
|
||||
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
|
||||
false
|
||||
@@ -451,8 +522,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
}
|
||||
int64_t vb_write_size = MEMALIGN((char*)vtx_dst - (char*)fr->VertexBufferHost, 4);
|
||||
int64_t ib_write_size = MEMALIGN((char*)idx_dst - (char*)fr->IndexBufferHost, 4);
|
||||
wgpuQueueWriteBuffer(bd->defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
|
||||
wgpuQueueWriteBuffer(bd->defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
|
||||
wgpuQueueWriteBuffer(bd->defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, (size_t)vb_write_size);
|
||||
wgpuQueueWriteBuffer(bd->defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, (size_t)ib_write_size);
|
||||
|
||||
// Setup desired render state
|
||||
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
|
||||
@@ -462,7 +533,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
ImGui_ImplWGPU_RenderState render_state;
|
||||
render_state.Device = bd->wgpuDevice;
|
||||
render_state.RenderPassEncoder = pass_encoder;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
@@ -478,8 +549,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
if (pcmd->UserCallback == ImGui_ImplWGPU_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
@@ -490,12 +560,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
ImTextureID tex_id = pcmd->GetTexID();
|
||||
ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id), 0);
|
||||
WGPUBindGroup bind_group = (WGPUBindGroup)bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash);
|
||||
if (!bind_group)
|
||||
{
|
||||
bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id);
|
||||
bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, bind_group);
|
||||
}
|
||||
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr);
|
||||
if (!bind_group && tex_id != 0)
|
||||
if ((bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id)) != 0)
|
||||
bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, bind_group);
|
||||
if (bind_group)
|
||||
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr);
|
||||
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
@@ -504,8 +573,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
// Clamp to viewport as wgpuRenderPassEncoderSetScissorRect() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
@@ -527,24 +596,23 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
}
|
||||
image_bind_groups.Data.resize(0);
|
||||
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
platform_io.Renderer_RenderState = bd->RenderState = nullptr;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData;
|
||||
if (backend_tex == nullptr)
|
||||
return;
|
||||
if (ImGui_ImplWGPU_Texture* backend_tex = (ImGui_ImplWGPU_Texture*)tex->BackendUserData)
|
||||
{
|
||||
IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID);
|
||||
wgpuTextureViewRelease(backend_tex->TextureView);
|
||||
wgpuTextureRelease(backend_tex->Texture);
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
IM_ASSERT(backend_tex->TextureView == (WGPUTextureView)(intptr_t)tex->TexID);
|
||||
wgpuTextureViewRelease(backend_tex->TextureView);
|
||||
wgpuTextureRelease(backend_tex->Texture);
|
||||
IM_DELETE(backend_tex);
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
|
||||
void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
||||
@@ -560,11 +628,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
||||
|
||||
// Create texture
|
||||
WGPUTextureDescriptor tex_desc = {};
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
tex_desc.label = { "Dear ImGui Texture", WGPU_STRLEN };
|
||||
#else
|
||||
tex_desc.label = "Dear ImGui Texture";
|
||||
#endif
|
||||
tex_desc.dimension = WGPUTextureDimension_2D;
|
||||
tex_desc.size.width = tex->Width;
|
||||
tex_desc.size.height = tex->Height;
|
||||
@@ -605,20 +669,12 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
||||
|
||||
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUTexelCopyTextureInfo dst_view = {};
|
||||
#else
|
||||
WGPUImageCopyTexture dst_view = {};
|
||||
#endif
|
||||
dst_view.texture = backend_tex->Texture;
|
||||
dst_view.mipLevel = 0;
|
||||
dst_view.origin = { (uint32_t)upload_x, (uint32_t)upload_y, 0 };
|
||||
dst_view.aspect = WGPUTextureAspect_All;
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUTexelCopyBufferLayout layout = {};
|
||||
#else
|
||||
WGPUTextureDataLayout layout = {};
|
||||
#endif
|
||||
layout.offset = 0;
|
||||
layout.bytesPerRow = tex->Width * tex->BytesPerPixel;
|
||||
layout.rowsPerImage = upload_h;
|
||||
@@ -636,10 +692,7 @@ static void ImGui_ImplWGPU_CreateUniformBuffer()
|
||||
WGPUBufferDescriptor ub_desc =
|
||||
{
|
||||
nullptr,
|
||||
"Dear ImGui Uniform buffer",
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPU_STRLEN,
|
||||
#endif
|
||||
{ "Dear ImGui Uniform buffer", WGPU_STRLEN, },
|
||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
|
||||
MEMALIGN(sizeof(Uniforms), 16),
|
||||
false
|
||||
@@ -696,14 +749,15 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc);
|
||||
|
||||
// Create the vertex shader
|
||||
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__shader_vert_wgsl);
|
||||
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl);
|
||||
if (!vertex_shader_desc.module) vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_vert_spirv, sizeof(__shader_vert_spirv));
|
||||
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
|
||||
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
|
||||
|
||||
// Vertex input configuration
|
||||
WGPUVertexAttribute attribute_desc[] =
|
||||
{
|
||||
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
|
||||
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
|
||||
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
|
||||
@@ -724,7 +778,8 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
graphics_pipeline_desc.vertex.buffers = buffer_layouts;
|
||||
|
||||
// Create the pixel shader
|
||||
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__shader_frag_wgsl);
|
||||
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl);
|
||||
if (!pixel_shader_desc.module) pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_frag_spirv, sizeof(__shader_frag_spirv));
|
||||
|
||||
// Create the blending setup
|
||||
WGPUBlendState blend_state = {};
|
||||
@@ -751,11 +806,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
// Create depth-stencil State
|
||||
WGPUDepthStencilState depth_stencil_state = {};
|
||||
depth_stencil_state.format = bd->depthStencilFormat;
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
|
||||
#else
|
||||
depth_stencil_state.depthWriteEnabled = false;
|
||||
#endif
|
||||
depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
|
||||
depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
|
||||
depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
|
||||
@@ -773,29 +824,35 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
|
||||
ImGui_ImplWGPU_CreateUniformBuffer();
|
||||
|
||||
// Create sampler
|
||||
// Create samplers (Linear/Nearest)
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
WGPUSamplerDescriptor sampler_desc = {};
|
||||
sampler_desc.minFilter = WGPUFilterMode_Linear;
|
||||
sampler_desc.magFilter = WGPUFilterMode_Linear;
|
||||
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
|
||||
sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge;
|
||||
sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge;
|
||||
sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge;
|
||||
sampler_desc.maxAnisotropy = 1;
|
||||
bd->renderResources.Sampler = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
|
||||
sampler_desc.minFilter = WGPUFilterMode_Linear;
|
||||
sampler_desc.magFilter = WGPUFilterMode_Linear;
|
||||
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
|
||||
bd->renderResources.SamplerLinear = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
|
||||
sampler_desc.minFilter = WGPUFilterMode_Nearest;
|
||||
sampler_desc.magFilter = WGPUFilterMode_Nearest;
|
||||
sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
|
||||
bd->renderResources.SamplerNearest = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
|
||||
|
||||
// Create resource bind group
|
||||
// Create resource bind groups (one per sampler, otherwise identical)
|
||||
WGPUBindGroupEntry common_bg_entries[] =
|
||||
{
|
||||
{ nullptr, 0, bd->renderResources.Uniforms, 0, MEMALIGN(sizeof(Uniforms), 16), 0, 0 },
|
||||
{ nullptr, 1, 0, 0, 0, bd->renderResources.Sampler, 0 },
|
||||
{ nullptr, 1, 0, 0, 0, bd->renderResources.SamplerLinear, 0 },
|
||||
};
|
||||
WGPUBindGroupDescriptor common_bg_descriptor = {};
|
||||
common_bg_descriptor.layout = bg_layouts[0];
|
||||
common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry);
|
||||
common_bg_descriptor.entries = common_bg_entries;
|
||||
bd->renderResources.CommonBindGroup = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
|
||||
bd->renderResources.CommonBindGroupLinear = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
|
||||
common_bg_entries[1].sampler = bd->renderResources.SamplerNearest;
|
||||
bd->renderResources.CommonBindGroupNearest = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
|
||||
bd->renderResources.ImageBindGroupLayout = bg_layouts[1];
|
||||
|
||||
SafeRelease(vertex_shader_desc.module);
|
||||
@@ -833,18 +890,25 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
io.BackendRendererName = "imgui_impl_webgpu_emscripten";
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
io.BackendRendererName = "imgui_impl_webgpu_dawn";
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
io.BackendRendererName = "imgui_impl_webgpu_wgpu";
|
||||
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Emscripten)"; // compiled & linked using EMSCRIPTEN with "--use-port=emdawnwebgpu" flag
|
||||
#else
|
||||
io.BackendRendererName = "imgui_impl_webgpu";
|
||||
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)";
|
||||
#endif
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)";
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
io.BackendRendererName = "imgui_impl_wgpu (WGVK, Native)";
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplWGPU_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplWGPU_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplWGPU_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->initInfo = *init_info;
|
||||
bd->wgpuDevice = init_info->Device;
|
||||
bd->defaultQueue = wgpuDeviceGetQueue(bd->wgpuDevice);
|
||||
@@ -853,11 +917,7 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
|
||||
bd->numFramesInFlight = init_info->NumFramesInFlight;
|
||||
bd->frameIndex = UINT_MAX;
|
||||
|
||||
bd->renderResources.Sampler = nullptr;
|
||||
bd->renderResources.Uniforms = nullptr;
|
||||
bd->renderResources.CommonBindGroup = nullptr;
|
||||
bd->renderResources.ImageBindGroups.Data.reserve(100);
|
||||
bd->renderResources.ImageBindGroupLayout = nullptr;
|
||||
|
||||
// Create buffers with a default size (they will later be grown as needed)
|
||||
bd->pFrameResources = new FrameResources[bd->numFramesInFlight];
|
||||
@@ -880,6 +940,7 @@ void ImGui_ImplWGPU_Shutdown()
|
||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
delete[] bd->pFrameResources;
|
||||
@@ -892,6 +953,7 @@ void ImGui_ImplWGPU_Shutdown()
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
@@ -903,6 +965,176 @@ void ImGui_ImplWGPU_NewFrame()
|
||||
IM_ASSERT(0 && "ImGui_ImplWGPU_CreateDeviceObjects() failed!");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal Helpers
|
||||
// Those are currently used by our example applications.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
|
||||
{
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
|
||||
#else
|
||||
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status)
|
||||
{
|
||||
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
return (status == WGPUSurfaceGetCurrentTextureStatus_Timeout || status == WGPUSurfaceGetCurrentTextureStatus_Outdated || status == WGPUSurfaceGetCurrentTextureStatus_Lost);
|
||||
#else
|
||||
return (status == WGPUSurfaceGetCurrentTextureStatus_Timeout || status == WGPUSurfaceGetCurrentTextureStatus_Outdated || status == WGPUSurfaceGetCurrentTextureStatus_Lost || status == WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helpers to obtain a string
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WGPUErrorType_Validation: return "Validation";
|
||||
case WGPUErrorType_OutOfMemory: return "OutOfMemory";
|
||||
case WGPUErrorType_Unknown: return "Unknown";
|
||||
case WGPUErrorType_Internal: return "Internal";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WGPUDeviceLostReason_Unknown: return "Unknown";
|
||||
case WGPUDeviceLostReason_Destroyed: return "Destroyed";
|
||||
case WGPUDeviceLostReason_CallbackCancelled: return "CallbackCancelled";
|
||||
case WGPUDeviceLostReason_FailedCreation: return "FailedCreation";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
#elif !defined(__EMSCRIPTEN__)
|
||||
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case WGPULogLevel_Error: return "Error";
|
||||
case WGPULogLevel_Warn: return "Warn";
|
||||
case WGPULogLevel_Info: return "Info";
|
||||
case WGPULogLevel_Debug: return "Debug";
|
||||
case WGPULogLevel_Trace: return "Trace";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WGPUBackendType_WebGPU: return "WebGPU";
|
||||
case WGPUBackendType_D3D11: return "D3D11";
|
||||
case WGPUBackendType_D3D12: return "D3D12";
|
||||
case WGPUBackendType_Metal: return "Metal";
|
||||
case WGPUBackendType_Vulkan: return "Vulkan";
|
||||
case WGPUBackendType_OpenGL: return "OpenGL";
|
||||
case WGPUBackendType_OpenGLES: return "OpenGLES";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WGPUAdapterType_DiscreteGPU: return "DiscreteGPU";
|
||||
case WGPUAdapterType_IntegratedGPU: return "IntegratedGPU";
|
||||
case WGPUAdapterType_CPU: return "CPU";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter)
|
||||
{
|
||||
WGPUAdapterInfo info = {};
|
||||
wgpuAdapterGetInfo(adapter, &info);
|
||||
printf("description: \"%.*s\"\n", (int)info.description.length, info.description.data);
|
||||
printf("vendor: \"%.*s\", vendorID: %x\n", (int)info.vendor.length, info.vendor.data, info.vendorID);
|
||||
printf("architecture: \"%.*s\"\n", (int) info.architecture.length, info.architecture.data);
|
||||
printf("device: \"%.*s\", deviceID: %x\n", (int)info.device.length, info.device.data, info.deviceID);
|
||||
printf("backendType: \"%s\"\n", ImGui_ImplWGPU_GetBackendTypeName(info.backendType));
|
||||
printf("adapterType: \"%s\"\n", ImGui_ImplWGPU_GetAdapterTypeName(info.adapterType));
|
||||
wgpuAdapterInfoFreeMembers(info);
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// MacOS specific: is necessary to compile with "-x objective-c++" flags
|
||||
// (e.g. using cmake: set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++") )
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <QuartzCore/CAMetalLayer.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info)
|
||||
{
|
||||
WGPUSurfaceDescriptor surface_descriptor = {};
|
||||
WGPUSurface surface = {};
|
||||
#if defined(__APPLE__) && TARGET_OS_OSX
|
||||
if (strcmp(info->System, "cocoa") == 0)
|
||||
{
|
||||
IM_ASSERT(info->RawWindow != nullptr);
|
||||
NSWindow* ns_window = (NSWindow*)info->RawWindow;
|
||||
id metal_layer = [CAMetalLayer layer];
|
||||
[ns_window.contentView setWantsLayer : YES] ;
|
||||
[ns_window.contentView setLayer : metal_layer] ;
|
||||
WGPUSurfaceSourceMetalLayer surface_src_metal = {};
|
||||
surface_src_metal.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
|
||||
surface_src_metal.layer = metal_layer;
|
||||
surface_descriptor.nextInChain = &surface_src_metal.chain;
|
||||
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
|
||||
}
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
if (strcmp(info->System, "wayland") == 0)
|
||||
{
|
||||
IM_ASSERT(info->RawDisplay != nullptr && info->RawSurface != nullptr);
|
||||
WGPUSurfaceSourceWaylandSurface surface_src_wayland = {};
|
||||
surface_src_wayland.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
|
||||
surface_src_wayland.display = info->RawDisplay;
|
||||
surface_src_wayland.surface = info->RawSurface;
|
||||
surface_descriptor.nextInChain = &surface_src_wayland.chain;
|
||||
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
|
||||
}
|
||||
else if (strcmp(info->System, "x11") == 0)
|
||||
{
|
||||
IM_ASSERT(info->RawDisplay != nullptr && info->RawWindow != nullptr);
|
||||
WGPUSurfaceSourceXlibWindow surface_src_xlib = {};
|
||||
surface_src_xlib.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
|
||||
surface_src_xlib.display = info->RawDisplay;
|
||||
surface_src_xlib.window = (uint64_t)info->RawWindow;
|
||||
surface_descriptor.nextInChain = &surface_src_xlib.chain;
|
||||
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
if (strcmp(info->System, "win32") == 0)
|
||||
{
|
||||
IM_ASSERT(info->RawWindow != nullptr && info->RawInstance != nullptr);
|
||||
WGPUSurfaceSourceWindowsHWND surface_src_hwnd = {};
|
||||
surface_src_hwnd.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
|
||||
surface_src_hwnd.hinstance = info->RawInstance;
|
||||
surface_src_hwnd.hwnd = info->RawWindow;
|
||||
surface_descriptor.nextInChain = &surface_src_hwnd.chain;
|
||||
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
|
||||
}
|
||||
#else
|
||||
IM_ASSERT(0 && "Unsupported WebGPU native platform!");
|
||||
#endif
|
||||
return surface;
|
||||
}
|
||||
#endif // #ifndef __EMSCRIPTEN__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
// dear imgui: Renderer for WebGPU
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW)
|
||||
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
|
||||
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
||||
|
||||
// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten),
|
||||
// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided.
|
||||
// When targeting native platforms:
|
||||
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK *must* be provided.
|
||||
// When targeting Emscripten:
|
||||
// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN and requires Emscripten 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
|
||||
// - Emscripten < 4.0.10 is not supported anymore (old '-sUSE_WEBGPU=1' option).
|
||||
// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten.
|
||||
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
|
||||
// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
|
||||
// This requirement may be removed once WebGPU stabilizes and backends converge on a unified interface.
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
@@ -27,12 +32,21 @@
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Setup Emscripten default if not specified.
|
||||
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#include <emscripten/version.h>
|
||||
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
#endif
|
||||
|
||||
#include <webgpu/webgpu.h>
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
|
||||
#include <webgpu/wgpu.h> // WGPULogLevel
|
||||
#endif
|
||||
|
||||
// Initialization data, for ImGui_ImplWGPU_Init()
|
||||
struct ImGui_ImplWGPU_InitInfo
|
||||
{
|
||||
WGPUDevice Device;
|
||||
WGPUDevice Device = nullptr;
|
||||
int NumFramesInFlight = 3;
|
||||
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
|
||||
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
|
||||
@@ -56,7 +70,7 @@ IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURen
|
||||
IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
@@ -68,4 +82,38 @@ struct ImGui_ImplWGPU_RenderState
|
||||
WGPURenderPassEncoder RenderPassEncoder;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal Helpers
|
||||
// Those are currently used by our example applications.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// (Optional) Helper to wrap some of the Dawn/WGPU/Emscripten quirks
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status);
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status); // Return whether the texture is suboptimal and may need to be recreated.
|
||||
|
||||
// (Optional) Helper for debugging/logging
|
||||
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter);
|
||||
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type);
|
||||
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
|
||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
|
||||
#endif
|
||||
|
||||
// (Optional) Helper to create a surface on macOS/Wayland/X11/Window
|
||||
#ifndef __EMSCRIPTEN__
|
||||
struct ImGui_ImplWGPU_CreateSurfaceInfo
|
||||
{
|
||||
WGPUInstance Instance;
|
||||
const char* System; // "cocoa" | "wayland" | "x11" | "win32"
|
||||
void* RawWindow; // NSWindow* | 0 | Window | HWND
|
||||
void* RawDisplay; // 0 | wl_display* | Display* | 0
|
||||
void* RawSurface; // | wl_surface* | 0 | 0
|
||||
void* RawInstance; // 0 | 0 | 0 | HINSTANCE
|
||||
};
|
||||
WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceInfo* info);
|
||||
#endif // #ifndef __EMSCRIPTEN__
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
|
||||
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
|
||||
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
|
||||
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594)
|
||||
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||
@@ -123,6 +128,7 @@ struct ImGui_ImplWin32_Data
|
||||
HMODULE XInputDLL;
|
||||
PFN_XInputGetCapabilities XInputGetCapabilities;
|
||||
PFN_XInputGetState XInputGetState;
|
||||
DWORD XInputPacketNumber;
|
||||
#endif
|
||||
|
||||
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
@@ -177,7 +183,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
|
||||
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||
ImGui_ImplWin32_UpdateKeyboardCodePage(io);
|
||||
|
||||
// Set platform dependent data in viewport
|
||||
// Our mouse update function expect PlatformHandle to be filled for the main viewport
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
|
||||
IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch
|
||||
@@ -193,7 +199,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
|
||||
"xinput1_2.dll", // DirectX SDK
|
||||
"xinput1_1.dll" // DirectX SDK
|
||||
};
|
||||
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
|
||||
for (int n = 0; n < IM_COUNTOF(xinput_dll_names); n++)
|
||||
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
|
||||
{
|
||||
bd->XInputDLL = dll;
|
||||
@@ -222,6 +228,7 @@ void ImGui_ImplWin32_Shutdown()
|
||||
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
// Unload XInput library
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
@@ -232,6 +239,7 @@ void ImGui_ImplWin32_Shutdown()
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
@@ -352,6 +360,9 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
|
||||
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
|
||||
return;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
if (bd->XInputPacketNumber != 0 && bd->XInputPacketNumber == xinput_state.dwPacketNumber)
|
||||
return;
|
||||
bd->XInputPacketNumber = xinput_state.dwPacketNumber;
|
||||
|
||||
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
|
||||
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }
|
||||
@@ -401,7 +412,7 @@ void ImGui_ImplWin32_NewFrame()
|
||||
// Setup time step
|
||||
INT64 current_time = 0;
|
||||
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
|
||||
io.DeltaTime = (float)((double)(current_time - bd->Time) / (double)bd->TicksPerSecond);
|
||||
bd->Time = current_time;
|
||||
|
||||
// Update OS mouse position
|
||||
@@ -644,8 +655,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
|
||||
bd->MouseTrackedArea = area;
|
||||
}
|
||||
POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) };
|
||||
if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates.
|
||||
return 0;
|
||||
if (msg == WM_NCMOUSEMOVE) // WM_NCMOUSEMOVE are absolute coordinates.
|
||||
::ScreenToClient(hwnd, &mouse_pos);
|
||||
io.AddMouseSourceEvent(mouse_source);
|
||||
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);
|
||||
return 0;
|
||||
@@ -765,6 +776,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
|
||||
case WM_SETFOCUS:
|
||||
case WM_KILLFOCUS:
|
||||
io.AddFocusEvent(msg == WM_SETFOCUS);
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
bd->XInputPacketNumber = 0; // FIXME: Technically, calling io.ClearInputKeys() directly would require this as well.
|
||||
#endif
|
||||
return 0;
|
||||
case WM_INPUTLANGCHANGE:
|
||||
ImGui_ImplWin32_UpdateKeyboardCodePage(io);
|
||||
@@ -779,10 +793,28 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
|
||||
else
|
||||
{
|
||||
wchar_t wch = 0;
|
||||
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1);
|
||||
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 2, &wch, 1);
|
||||
io.AddInputCharacter(wch);
|
||||
}
|
||||
return 0;
|
||||
case WM_IME_COMPOSITION:
|
||||
{
|
||||
// Handling WM_IME_COMPOSITION ensure that WM_IME_CHAR value is correct even for MBCS apps.
|
||||
// (see #9099, #3653 and https://stackoverflow.com/questions/77450354 topics)
|
||||
LRESULT result = ::DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
return (lParam & GCS_RESULTSTR) ? 1 : result;
|
||||
}
|
||||
case WM_IME_CHAR:
|
||||
if (::IsWindowUnicode(hwnd) == FALSE)
|
||||
{
|
||||
if (::IsDBCSLeadByte(HIBYTE(wParam)))
|
||||
wParam = (WPARAM)MAKEWORD(HIBYTE(wParam), LOBYTE(wParam));
|
||||
wchar_t wch = 0;
|
||||
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 2, &wch, 1);
|
||||
io.AddInputCharacterUTF16(wch);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
case WM_SETCURSOR:
|
||||
// This is required to restore cursor when transitioning from e.g resize borders to client area.
|
||||
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor(io, bd->LastMouseCursor))
|
||||
@@ -806,7 +838,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
|
||||
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
// neither of which we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
|
||||
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
|
||||
@@ -898,7 +930,7 @@ float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
||||
{
|
||||
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
||||
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||
return xdpi / 96.0f;
|
||||
return (float)xdpi / 96.0f;
|
||||
}
|
||||
}
|
||||
#ifndef NOGDI
|
||||
@@ -908,7 +940,7 @@ float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
||||
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||
::ReleaseDC(nullptr, dc);
|
||||
#endif
|
||||
return xdpi / 96.0f;
|
||||
return (float)xdpi / 96.0f;
|
||||
}
|
||||
|
||||
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
|
||||
|
||||
@@ -26,7 +26,7 @@ IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||
|
||||
// Win32 message handler your application need to call.
|
||||
// Win32 message handler your application needs to call.
|
||||
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
@@ -40,7 +40,7 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
|
||||
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
// neither of which we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||
|
||||
@@ -34,6 +34,8 @@ Instructions to rebuild imgui_impl_sdlgpu3_shaders.h
|
||||
xcrun -sdk macosx metallib -o vertex.metallib -c vertex.ir
|
||||
xcrun -sdk macosx metallib -o fragment.metallib -c fragment.ir
|
||||
|
||||
note: use .metal outputs for updating msl_vertex / msl_fragment variables, and use .metallib outputs for metallib_vertex / metallib_fragment variables
|
||||
|
||||
Proceed to step 4
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#version 450 core
|
||||
layout(location = 0) out vec4 fColor;
|
||||
|
||||
layout(set=0, binding=0) uniform sampler2D sTexture;
|
||||
layout(set=0, binding=0) uniform texture2D _Texture;
|
||||
layout(set=1, binding=0) uniform sampler _Sampler;
|
||||
|
||||
layout(location = 0) in struct {
|
||||
vec4 Color;
|
||||
@@ -10,5 +11,5 @@ layout(location = 0) in struct {
|
||||
|
||||
void main()
|
||||
{
|
||||
fColor = In.Color * texture(sTexture, In.UV.st);
|
||||
fColor = In.Color * texture(sampler2D(_Texture, _Sampler), In.UV.st);
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ List of Renderer Backends:
|
||||
List of high-level Frameworks Backends (combining Platform + Renderer):
|
||||
|
||||
imgui_impl_allegro5.cpp
|
||||
imgui_impl_null.cpp
|
||||
|
||||
Emscripten is also supported!
|
||||
The SDL2+GL, SDL3+GL, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
|
||||
@@ -254,8 +255,8 @@ void MyImGuiBackend_RenderDrawData(ImDrawData* draw_data)
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
MyEngineSetupenderState();
|
||||
if (pcmd->UserCallback == platform_io.DrawCallback_ResetRenderState)
|
||||
MyEngineSetupSenderState();
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
@@ -336,7 +337,7 @@ void MyImGuiBackend_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Create texture based on tex->Width, tex->Height.
|
||||
// - Most backends only support tex->Format == ImTextureFormat_RGBA32.
|
||||
// - Backends for particularly memory constrainted platforms may support tex->Format == ImTextureFormat_Alpha8.
|
||||
// - Backends for particularly memory constrained platforms may support tex->Format == ImTextureFormat_Alpha8.
|
||||
|
||||
// Upload all texture pixels
|
||||
// - Read from our CPU-side copy of the texture and copy to your graphics API.
|
||||
|
||||
@@ -35,6 +35,916 @@ HOW TO UPDATE?
|
||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||
- Please report any issue!
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.8 WIP (In Progress)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- DrawList:
|
||||
- Obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
|
||||
which is part of our new standard draw callbacks. (#9378)
|
||||
Redirecting the earlier value into the later one when set, so both old and new code should work.
|
||||
- Backends:
|
||||
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
|
||||
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
|
||||
- When creating your own descriptor pool (instead of letting backend creates its own):
|
||||
- Before: need at least IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.
|
||||
- After: need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.
|
||||
+ IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
|
||||
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
- Before: ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)
|
||||
- After: ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)
|
||||
- Kept inline redirection function that ignores the sampler (will obsolete).
|
||||
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from ImGui_ImplXXXX_RenderState.
|
||||
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
|
||||
If there is a legit need/request for them or any render state we can always add them back.
|
||||
|
||||
Other Changes:
|
||||
|
||||
- DrawList:
|
||||
- Added room in ImGuiPlatformIO for standard backend-agnostic draw callbacks. Those callbacks
|
||||
are setup/provided by the backend and available in most of our standard backends.
|
||||
They allow backend-agnostic code from e.g. switching to a Nearest/Point sampler without
|
||||
messing with custom Renderer-specific callbacks.
|
||||
platform_io.DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||
platform_io.DrawCallback_SetSamplerLinear; // Request to set current texture sampling to Linear
|
||||
platform_io.DrawCallback_SetSamplerNearest; // Request to set current texture sampling to Nearest/Point
|
||||
Note that some backends might not support all callbacks.
|
||||
(#9378, #9371, #3590, #8926, #2973, #7485, #7468, #6969, #5118, #7616, #9173, #8322, #7230,
|
||||
#5999, #6452, #5156, #7342, #7592, #7511)
|
||||
- Made AddCallback() user data default to Null for convenience.
|
||||
- InputText:
|
||||
- InputTextMultiline: fixed an issue processing deactivation logic when an active
|
||||
multi-line edit is clipped due to being out of view.
|
||||
- Fixed a crash when toggling ReadOnly while active. (#9354)
|
||||
- CharFilter callback event sets CursorPos/SelectionStart/SelectionEnd. (#816)
|
||||
- Tables:
|
||||
- Fixed issues reporting ideal size to parent window/container: (#9352, #7651)
|
||||
- When both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested.
|
||||
- When vertical scrollbar was not at the top, the computation was often incorrect.
|
||||
- Windows:
|
||||
- Fixed a single-axis auto-resizing feedback loop issue with nested containers
|
||||
and varying scrollbar visibility. (#9352)
|
||||
- Detect and report error when calling End() instead of EndPopup() on a popup. (#9351)
|
||||
- Child windows with only ImGuiChildFlags_AutoResizeY flag keep using the proportional
|
||||
default ItemWidth. (#9355)
|
||||
- Multi-Select:
|
||||
- Fixed an issue using Multi-Select within a Table causing column width measurement to
|
||||
be invalid when trailing column contents is not submitted in the last row. (#9341, #8250)
|
||||
- Fixed an issue using Multi-Select within a Table with the right-most column visible,
|
||||
which could lead to an extra vertical offset in the Header row. (#8250)
|
||||
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect1d mode while scrolling.
|
||||
Notably, using mouse wheel while holding a box-selection could lead items close to windows
|
||||
edges from not being correctly unselected. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Box-Select: improved dirty/unclip rectangle logic for ImGuiMultiSelectFlags_BoxSelect2d.
|
||||
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect2d mode, where
|
||||
items out of view wouldn't be properly selected while scrolling while mouse cursor
|
||||
is hovering outside of selection scope. (#7994, #1861, #6518)
|
||||
- Box-Select: fixed an issue where items out of horizontal view would sometimes lead
|
||||
to incorrect merging of sequential selection requests while also scrolling fast
|
||||
enough to overlap multiple rows during a frame. (#7994, #1861, #6518)
|
||||
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect2d mode in a Table
|
||||
while relying on the TableNextColumn() return value to perform coarse clipping. (#7994)
|
||||
- Box-Select: disabled merging consecutive selection requests as we have no reliable
|
||||
way of detecting if user has submitted all consecutives items without clipping gaps,
|
||||
and ImGuiSelectionUserData is technically opaque storage. (#7994, #1861)
|
||||
(we will probably bring this back as a minor optimization if we have a way to for
|
||||
user to tell us ImGuiSelectionUserData are indices)
|
||||
- Box-Select: fixes for using accross nested child windows. (#8364)
|
||||
- Box-Select + Clipper: fixed an issue selecting items while scrolling while a clipper
|
||||
active. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Box-Select + Tables: fixed an issue using box-selection in a tables with
|
||||
items straying out of columns boundaries. (#7994, #2221)
|
||||
- Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table
|
||||
before layout has been locked (first row or headers row submitted). (#8250)
|
||||
- Style:
|
||||
- Fixed vertical scrollbar top coordinates when using thick borders on windows
|
||||
with no title bar and no menu bar. (#9366)
|
||||
- Fonts:
|
||||
- imgui_freetype: add FreeType headers & compiled version in 'About Dear ImGui' details.
|
||||
- Assert when using MergeMode with an explicit size over a target font with an implicit
|
||||
size, as scale factor are likely erroneous. (#9361)
|
||||
- Clipper:
|
||||
- Improved error reporting when misusing the clipper inside a table (prioritize
|
||||
reporting the common clipper error over a table sanity check assert). (#9350)
|
||||
- Tweaked assert triggering when first item height measurement fails, and made it
|
||||
a better recoverable error. (#9350)
|
||||
- Misc:
|
||||
- Minor optimization: reduce redudant label scanning in common widgets.
|
||||
- Added missing Test Engine hooks for PlotXXX(), VSliderXXX(), TableHeader().
|
||||
- Backends:
|
||||
- Added support for new standardized draw callbacks in most backends: (#9378)
|
||||
- Allegro5: Reset n/a n/a
|
||||
- DX9: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX10: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX11: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX12: Reset SetSamplerLinear SetSamplerNearest
|
||||
- Metal: Reset *missing* *missing*
|
||||
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
|
||||
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
|
||||
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
|
||||
- SDLRenderer2: Reset n/a n/a
|
||||
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
|
||||
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
|
||||
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
|
||||
(Vulkan backend by @yaz0r, others by @ocornut)
|
||||
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
|
||||
functions for legacy GLFW 3.2. (#9003)
|
||||
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
|
||||
to validation issue. (#9343) [@Hunam6]
|
||||
- Metal: use a dedicated `bufferCacheLock` to avoid crashing when `bufferCache` is
|
||||
replaced by a new object while being used for `@synchronize()`. (#9367) [@andygrundman]
|
||||
- SDL2: made `ImGui_ImplSDL2_GetContentScaleForWindow()`/`ImGui_ImplSDL2_GetContentScaleForDisplay()`
|
||||
helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value
|
||||
and this breaks scaling border size. (#9369)
|
||||
- WebGPU: always use SPIR-V shader on WGVK, as it cannot be detected at runtime. (#9316, #9246, #9257)
|
||||
- Examples:
|
||||
- Update VS toolset in all .vcxproj from VS2015 (v140) to VS2017 (v141). The later is the
|
||||
first that supports vcpkg. Onward we will likely stop testing building the library with VS2015.
|
||||
- GLFW+Vulkan, SDL2+Vulkan, SDL3+Vulkan, Win32+Vulkan: reworked to create a descriptor pool with:
|
||||
- IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.
|
||||
- IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.7 (Released 2026-04-02)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.7
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Separator: fixed a legacy quirk where `Separator()` was submitting a zero-height
|
||||
item for layout purpose, even though it draws a 1-pixel separator.
|
||||
The fix could affect code e.g. computing height from multiple widgets in order to
|
||||
allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
|
||||
The "Console" example had such a bug:
|
||||
float footer_height = style.ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||
BeginChild("ScrollingRegion", { 0, -footer_height });
|
||||
Should be:
|
||||
float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing();
|
||||
BeginChild("ScrollingRegion", { 0, -footer_height });
|
||||
When such idiom was used and assuming zero-height Separator, it is likely that
|
||||
in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
|
||||
- Multi-Select: renamed `ImGuiMultiSelectFlags_SelectOnClick` to `ImGuiMultiSelectFlags_SelectOnAuto`.
|
||||
Kept inline redirection enum (will obsolete).
|
||||
- Combo(), ListBox(): commented out legacy signatures which were obsoleted in 1.90
|
||||
(Nov 2023), when the getter callback type was changed from:
|
||||
bool (*getter)(void* user_data, int idx, const char** out_text)
|
||||
To:
|
||||
const char* (*getter)(void* user_data, int idx)
|
||||
|
||||
Other Changes:
|
||||
|
||||
- TreeNode:
|
||||
- Moved `TreeNodeGetOpen()` helper to public API. I was hesitant to make this public
|
||||
because I intend to provide a more generic and feature-full version, but in the meanwhile
|
||||
this will do. (#3823, #9251, #7553, #6754, #5423, #2958, #2079, #1947, #1131, #722)
|
||||
- In 'Demo->Property Editor' demonstrate a way to perform tree clipping by fast-forwarding
|
||||
through non-visible chunks. (#3823, #9251, #6990, #6042)
|
||||
Using SetNextItemStorageID() + TreeNodeGetOpen() makes this notably easier than
|
||||
it was prior to 1.91.
|
||||
- InputText:
|
||||
- Shift+Enter in multi-line editor always adds a new line, regardless of
|
||||
`ImGuiInputTextFlags_CtrlEnterForNewLine` being set or not. (#9239)
|
||||
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing Enter will
|
||||
deactivate/reactivate the item in order for e.g. `IsItemDeactivatedAfterEdit()`
|
||||
signals to be emitted the same way regardless of that setting. (#9001, #9115)
|
||||
- Fixed a glitch when using `ImGuiInputTextFlags_ElideLeft` where the local x offset
|
||||
would be incorrect during the deactivation frame. (#9298)
|
||||
- Fixed a crash introduced in 1.92.6 when handling `ImGuiInputTextFlags_CallbackResize`
|
||||
in certain situations. (#9174)
|
||||
- Fixed selection highlight Y1 offset being very slightly off (since 1.92.3). (#9311) [@v-ein]
|
||||
- InputTextMultiline: fixed an issue introduced in 1.92.3 where line count calculated
|
||||
for vertical scrollbar range would be +1 when the widget is inactive, word-wrap is
|
||||
disabled and the text buffer ends with '\n'. Fixed a similar issue related to clipping
|
||||
large amount of text.
|
||||
- InputTextMultiline: avoid going through reactivation code and fixed losing revert value
|
||||
when activating scrollbar.
|
||||
- InputTextMultiline: fixed an issue where edit buffer wouldn't be reapplied to back
|
||||
buffer on the `IsItemDeactivatedAfterEdit()` frame. This could create issues when
|
||||
using the idiom of not applying edits before `IsItemDeactivatedAfterEdit()`.
|
||||
(#9308, #8915, #8273)
|
||||
- Tables:
|
||||
- Allow reordering columns by dragging them in the context menu. (#9312)
|
||||
- Context menu now presents columns in display order. (#9312)
|
||||
- Fixed and clarified the behavior of using `TableSetupScrollFreeze()` with columns>1,
|
||||
and where some of the columns within that range were Hidable.
|
||||
- Before: `TableSetupScrollFreeze(N, 0)`: include the N left-most visible columns as
|
||||
part of the scroll freeze. So if you intentionally hide columns <N, the scroll
|
||||
freeze area would start covering the subsequent/following columns (N+1) etc.
|
||||
- After: `TableSetupScrollFreeze(N, 0)`: include the N left-most columns (regardless of visibility),
|
||||
as part of the scroll freeze. So if you intentionally hide columns <N, the scroll
|
||||
freeze area will cover less columns.
|
||||
- This is generally more sane and logical.
|
||||
- Fixed dragging a header to reorder outside of visible bounds (due to horizontal scrolling)
|
||||
from losing active id.
|
||||
- Angled Headers: angled section for column being reordered via the regular headers
|
||||
stays highlighted during reordering.
|
||||
- Style:
|
||||
- Fonts: fixed an issue introduced in 1.92.6 where `style.FontBaseSize` would be
|
||||
cleared during the first frame if no fonts was explicitly added before.
|
||||
- Border sizes are now scaled (and rounded) by `ScaleAllSizes()`.
|
||||
- When using large values with `ScallAllSizes()`, the following items thickness
|
||||
are scaled to integer amounts:
|
||||
- `InputText()` caret/cursor thickness. (#7031)
|
||||
- `CloseButton()` thickness.
|
||||
- `TextLink()` underline thickness.
|
||||
- `ColorButton()` border thickness.
|
||||
- `Separator()` thickness, via scaling newly added `style.SeparatorSize`. (#2657, #9263)
|
||||
- Nav:
|
||||
- Popups: Shift+F10 or Menu key can now open popups menus when using
|
||||
`BeginPopupContextItem()`, `BeginPopupContextWindow()` or `OpenPopupOnItemClick()`.
|
||||
(#8803, #9270) [@exelix11, @ocornut]
|
||||
- Changed Gamepad mapping for "Activate with Text Input" action: (#8803, #787)
|
||||
- Previously: press North button (PS4/PS5 triangle, Switch X, Xbox Y).
|
||||
- Now: long press (hold) Activate button (PS4/PS5 cross, Switch B, Xbox A) for ~0.60 secs.
|
||||
This is rarely used, somehow easier to discover, and frees a button for other uses.
|
||||
See updated Gamepad Control Sheets: https://www.dearimgui.com/controls_sheets
|
||||
- Short Gamepad Activation press on InputText() always activate with Text Input mode.
|
||||
- Popups: pressing North button (PS4/PS5 triangle, SwitchX, Xbox Y) also open popups menus.
|
||||
- Multi-Select:
|
||||
- Added `ImGuiMultiSelectFlags_SelectOnClickAlways` mode (rarely used).
|
||||
This prevents Drag and Drop of multiple items, but it allows to start a new Box-Selection
|
||||
from inside an existing selection (Excel style). (#9307, #1861)
|
||||
- Clipper:
|
||||
- Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false.
|
||||
- Added `UserIndex` helper storage. This is solely a convenience for cases where
|
||||
you may want to carry an index around.
|
||||
- Always pulls current context on `ImGuiListClipper::Begin()`, consistent with public
|
||||
API design, and avoids issues with clipper instances outliving contexts. (#9324, #5856)
|
||||
- Scrollbar:
|
||||
- Implemented a custom tweak to extend hit-testing bounding box when window is sitting
|
||||
at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the
|
||||
mouse at the extreme of the screen will reach the scrollbar. (#9276)
|
||||
- Fixed an issue which could lead initial click to move the current scroll by a pixel.
|
||||
- Button:
|
||||
- Moved `ImGuiButtonFlags_AllowOverlap` from imgui_internal.h to imgui.h,
|
||||
as a convenience for when using e.g. `InvisibleButton()`.
|
||||
- Focus: fixed fallback "Debug" window temporarily taking focus and setting `io.WantCaptureKeyboard`
|
||||
for one frame on e.g. application boot if no other windows are submitted. (#9243)
|
||||
- DrawList:
|
||||
- PathArcTo(): fixed erroneous segment count for pathologically small arcs on large
|
||||
circles. (#9331, #9313) [@thedmd, @epajarre]
|
||||
- Memory:
|
||||
- Discard/GC of ImDrawList buffers for unused windows favor restoring them to
|
||||
~Size*1.05 instead of Capacity when awakening again. Facilitate releasing ImDrawList
|
||||
buffers after unusual usage spike. (#9303)
|
||||
- Fixed `GetForegroundDrawList()`/`GetBackgroundDrawList()` per-viewport buffers not being
|
||||
collected when unused for `io.ConfigMemoryCompactTimer` amount of time. (#9303)
|
||||
- Demo: fixed `IMGUI_DEMO_MARKER` locations for examples applets. (#9261, #3689) [@pthom]
|
||||
- Misc: added missing ImVec2/ImVec4 operators. (#9339, #8258) [@dkosmari, @ArashPartow]
|
||||
- Internals:
|
||||
- ButtonBehavior: fixed internal/low-level `ImGuiButtonFlags_PressedOnRelease`
|
||||
(as well as equivalent `ImGuiSelectableFlags_SelectOnRelease` for Selectable) from
|
||||
not taking current active id. `ImGuiButtonFlags_NoHoldingActiveID` allows that.
|
||||
This was only used internally by MenuItem().
|
||||
- Backends:
|
||||
- DirectX9, OpenGL2, OpenGL3, Metal, SDLGPU3, SDLRenderer2, SDLRenderer3: fixed easy-to-fix
|
||||
issues in code assuming ImTextureID_Invalid is always defined to 0. (#9295, #9310)
|
||||
- GLFW: mouse cursor is properly restored if changed by user app/code while using
|
||||
`glfwSetInputMode(..., GLFW_CURSOR_DISABLED)` or `ImGuiConfigFlags_NoMouseCursorChange`.
|
||||
Amend optimization done in 1.92.6.
|
||||
- SDLGPU3: removed unnecessary call to `SDL_WaitForGPUIdle()` when releasing
|
||||
vertex/index buffers. (#9262) [@jaenis]
|
||||
- WebGPU: fixed version check for Emscripten 5.0.0+.
|
||||
- WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
|
||||
- WebGPU: added support for WGVK native backend via `IMGUI_IMPL_WEBGPU_BACKEND_WGVK`,
|
||||
using SPIRV shaders if WGSL is not available. (#9316, #9246, #9257) [@r-lyeh]
|
||||
(WGVK is a lightweight alternative to Dawn or WGPU for native applications,
|
||||
which is easier to build/setup, see: https://github.com/manuel5975p/WGVK)
|
||||
- Examples:
|
||||
- Emscripten: added `tabindex=-1` to canvas in our shell_minimal.htm. Without it,
|
||||
the canvas was not focusable in the DOM, which in turn make some backends
|
||||
(e.g. pongasoft/emscripten-glfw) not receive focus loss events. (#9259) [@pthom]
|
||||
- Emscripten: fixed minor rendering issues with our HTML shell. (#9281) [@ypujante]
|
||||
- hidden small blue outline when canvas is focused on Chrome.
|
||||
- hidden scrollbar in Firefox.
|
||||
- Vulkan: added `ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[]` to allow specifying
|
||||
extra dynamic states to add when creating the VkPipeline. (#9211) [@DziubanMaciej]
|
||||
- Vulkan: `ImGui_ImplVulkan_AddTexture()` skips updating descriptor_set if failing
|
||||
to allocate one. (#8677) [@micb25]
|
||||
- WebGPU: fixed undefined behaviors in example code for requesting adapter
|
||||
and device. (#9246, #9256) [@r-lyeh]
|
||||
- SDL2+WebGPU: fixed hi-dpi handling. (#9300) [@ypujante]
|
||||
- GLFW/SDL2/SDL3+WebGPU: added support for WGVK. (#9316, #9246, #9257) [@r-lyeh, @ocornut]
|
||||
- GLFW/SDL2/SDL3+WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.6 (2026-02-17)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.6
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Fonts:
|
||||
- `AddFontDefault()` now automatically selects an embedded font between:
|
||||
- `AddFontDefaultBitmap()`: classic pixel-clean font. Recommended at Size 13px with no scaling.
|
||||
- `AddFontDefaultVector()`: new scalable font. Recommended at any higher size.
|
||||
- The default selection is based on (style.FontSizeBase * FontScaleMain * FontScaleDpi)
|
||||
reaching a small threshold, but old codebases may not set any of them properly.
|
||||
As as a result, it is likely that old codebase may still default to AddFontDefaultBitmap().
|
||||
- Prefer explicitly calling either of them based on your own logic!
|
||||
You can call `AddFontDefaultBitmap()` to ensure legacy behavior.
|
||||
- Fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which did
|
||||
erroneously make a copy of the font data, essentially defeating the purpose
|
||||
of this flag and wasting memory (undetected since July 2015 and now spotted
|
||||
by @TellowKrinkle, this is perhaps the oldest bug in Dear ImGui history,
|
||||
albeit for a rarely used feature!) (#9086, #8465)
|
||||
HOWEVER, fixing this bug is likely to surface bugs in user/app code:
|
||||
- Prior to 1.92, font data only needs to be available during the `atlas->AddFontXXX()` call.
|
||||
Since 1.92, font data needs to available until `atlas->RemoveFont()`, or more typically
|
||||
until a shutdown of the owning context or font atlas.
|
||||
- The fact that handling of `FontDataOwnedByAtlas = false` was broken bypassed
|
||||
the issue altogether.
|
||||
- Removed `ImFontConfig::PixelSnapV` added in 1.92 which turns out is unnecessary
|
||||
(and was mis-documented). Post-rescale `GlyphOffset` is always rounded.
|
||||
- Popups: changed compile-time `ImGuiPopupFlags popup_flags = 1` default value to be `= 0` for
|
||||
`BeginPopupContextItem()`, `BeginPopupContextWindow()`, `BeginPopupContextVoid()`, `OpenPopupOnItemClick()`.
|
||||
The default value has same meaning before and after. (#9157, #9146)
|
||||
- Before this version, those functions had a `ImGuiPopupFlags popup_flags = 1` default
|
||||
value in their function signature. This was introduced by a change on 2020/06/23 (1.77)
|
||||
while changing the signature from `int mouse_button` to `ImGuiPopupFlags popup_flags`
|
||||
and trying to preserve then-legacy behavior.
|
||||
- We have now changed this behavior to: cleanup a very old API quirk, facilitate use by
|
||||
bindings, and to remove the last and error-prone non-zero default value. Also because we
|
||||
deemed it extremely rare to use those helper functions with the Left mouse button!
|
||||
As using the LMB would generally be triggered via another widget,
|
||||
e.g. a Button() + a OpenPopup()/BeginPopup() call.
|
||||
- Before: The default = 1 means `ImGuiPopupFlags_MouseButtonRight`.
|
||||
Explicitly passing a literal 0 means `ImGuiPopupFlags_MouseButtonLeft`.
|
||||
- After: The default = 0 means `ImGuiPopupFlags_MouseButtonRight`.
|
||||
Explicitly passing a literal 1 also means `ImGuiPopupFlags_MouseButtonRight`.
|
||||
(if legacy behavior are enabled) or will assert (if legacy behavior are disabled).
|
||||
- TL;DR: if you don't want to use right mouse button for popups, always specify it
|
||||
explicitly using a named `ImGuiPopupFlags_MouseButtonXXXX` value.
|
||||
Recap:
|
||||
- BeginPopupContextItem("foo"); // Behavior unchanged (use Right button)
|
||||
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft); // Behavior unchanged (use Left button)
|
||||
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft | xxx); // Behavior unchanged (use Left button + flags)
|
||||
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonRight | xxx); // Behavior unchanged (use Right button + flags)
|
||||
- BeginPopupContextItem("foo", 1); // Behavior unchanged (as a courtesy we legacy interpret 1 as ImGuiPopupFlags_MouseButtonRight, will assert if disabling legacy behaviors.
|
||||
- BeginPopupContextItem("foo", 0); // !! Behavior changed !! Was Left button. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft.
|
||||
- BeginPopupContextItem("foo", ImGuiPopupFlags_NoReopen); // !! Behavior changed !! Was Left button + flags. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft | xxx.
|
||||
- Commented out legacy names obsoleted in 1.90 (Sept 2023):
|
||||
- `BeginChildFrame()` --> `BeginChild()` with `ImGuiChildFlags_FrameStyle` flag.
|
||||
- `EndChildFrame()` --> `EndChild()`.
|
||||
- `ShowStackToolWindow()` --> `ShowIDStackToolWindow()`.
|
||||
- `IM_OFFSETOF()` --> `offsetof()`.
|
||||
- `IM_FLOOR()` --> `IM_TRUNC()` [internal, for positive values only]
|
||||
- Hashing: handling of "###" operator to reset to seed within a string identifier
|
||||
doesn't include the "###" characters in the output hash anymore:
|
||||
Before: `GetID("Hello###World") == GetID("###World") != GetID("World")`
|
||||
After: `GetID("Hello###World") == GetID("###World") == GetID("World")`
|
||||
- This has the property of facilitating concatenating and manipulating
|
||||
identifiers using "###", and will allow fixing other dangling issues.
|
||||
- This will invalidate hashes (stored in .ini data) for Tables and Windows
|
||||
that are using the "###" operators. (#713, #1698)
|
||||
- Renamed helper macro `IM_ARRAYSIZE()` -> `IM_COUNTOF()`. Kept redirection/legacy name.
|
||||
- Backends:
|
||||
- Vulkan: optional `ImGui_ImplVulkanH_DestroyWindow()` helper used by our example
|
||||
code does not call `vkDestroySurfaceKHR()`: because surface is created by caller
|
||||
of `ImGui_ImplVulkanH_CreateOrResizeWindow()`, it is more consistent. (#9163)
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Fonts:
|
||||
- Added `AddFontDefaultVector()`: a new embedded monospace scalable font: ProggyForever!
|
||||
From https://github.com/ocornut/proggyforever:
|
||||
"ProggyForever is an MIT-licensed partial reimplementation of the ProggyVector
|
||||
font (originally by Tristan Grimmer), which itself is a vector-based
|
||||
reinterpretation of the ProggyClean bitmap font that happily served as
|
||||
Dear ImGui default font for over 10 years." [...]
|
||||
"I commissioned Thiebault Courot to recreate this, applied various minor tweaks
|
||||
and fixes, and reworked his editing pipeline toward shipping FontForge source
|
||||
files so we can allow and track future changes."
|
||||
- TL;DR; there was no strictly MIT-licensed matching font. We made it!
|
||||
- The font data was carefully subsetted, trimmed and compressed so the embedded
|
||||
data is ~14 KB. Embedding a scalable default font ensures that Dear ImGui can
|
||||
be easily and readily used in all contexts, even without file system access.
|
||||
- Expect minor fixes/improvements in following releases.
|
||||
- As always you can opt-out of the embedded font data if desired.
|
||||
- `AddFontDefault()` now automatically selects an embedded font between
|
||||
the classic pixel-looking one and the new scalable one.
|
||||
Prefer calling `AddFontDefaultVector()` or `AddFontDefaultBitmap()` explicitly.
|
||||
- Fixed a crash when trying to use `AddFont()` with `MergeMode==true` on a font that
|
||||
has already been rendered. (#9162) [@ocornut, @cyfewlp]
|
||||
- Fixed an issue where using `PushFont()` from the implicit/fallback "Debug" window
|
||||
when its recorded state is collapsed would incorrectly early out. This would break
|
||||
e.g. using direct draw-list calls such as `GetForegroundDrawList()` with current font.
|
||||
(#9210, #8865)
|
||||
- Fixed an issue related to `EllipsisChar` handling, while changing
|
||||
font loader or font loader flags dynamically in Style->Fonts menus.
|
||||
- imgui_freetype: fixed overwriting `ImFontConfig::PixelSnapH` when hinting
|
||||
is enabled, creating side-effects when later disabling hinting or
|
||||
dynamically switching to stb_truetype rasterizer.
|
||||
- Adding new fonts after removing all fonts mid-frame properly updates current state.
|
||||
- Textures:
|
||||
- Fixed a building issue when `ImTextureID` is defined as a struct.
|
||||
- Fixed displaying texture # in Metrics/Debugger window.
|
||||
- Menus:
|
||||
- Fixed `MenuItem()` label position and `BeginMenu()` arrow/icon/popup positions,
|
||||
when used inside a line with a baseline offset.
|
||||
- Made navigation into menu-bar auto wrap on X axis. (#9178)
|
||||
- TreeNode:
|
||||
- Fixed highlight position when used inside a line with a large text baseline offset.
|
||||
(it never quite worked in this situation; but then most of the time the text
|
||||
baseline offset ends up being zero or `FramePadding.y` for a given line).
|
||||
- Tables:
|
||||
- Fixed an issue where a very thin scrolling table would advance parent layout
|
||||
slightly differently depending on its visibility (caused by a mismatch
|
||||
between hard minimum window size and table minimum size).
|
||||
- Fixed an issue where submitting non-integer row heights would eventually
|
||||
advance table parent layout by +0/+1 depending on its visibility.
|
||||
- Fixed losing stored display order when reducing column count or when .ini
|
||||
data has missing or duplicate values. (#9108, #4046)
|
||||
- ColorEdit:
|
||||
- Added R/G/B/A color markers next to each component (enabled by default).
|
||||
- Added `ImGuiColorEditFlags_NoColorMarkers` to disable them.
|
||||
- Added `style.ColorMarkerSize` to configure width of color component markers.
|
||||
- Sliders, Drags:
|
||||
- Added `ImGuiSliderFlags_ColorMarkers` to opt-in adding R/G/B/A color markers
|
||||
next to each components, in multi-components functions.
|
||||
- Added a way to select a specific marker color.
|
||||
- InputText:
|
||||
- InputTextMultiline(): fixed a minor bug where Shift+Wheel would allow a small
|
||||
horizontal scroll offset when there should be none. (#9249)
|
||||
- ImGuiInputTextCallbackData: `SelectAll()` also sets `CursorPos` to `SelectionEnd`.
|
||||
- ImGuiInputTextCallbackData: Added `SetSelection()` helper.
|
||||
- ImGuiInputTextCallbackData: Added `ID` and `EventActivated` members. (#9174)
|
||||
- Text, InputText:
|
||||
- Reworked word-wrapping logic:
|
||||
- Try to not wrap in the middle of contiguous punctuation. (#8139, #8439, #9094)
|
||||
- Try to not wrap between a punctuation and a digit. (#8503)
|
||||
- Inside `InputTextMultiline()` with WordWrap enabled: prefer keeping blanks at
|
||||
the end of a line rather than at the beginning of next line. (#8990, #3237)
|
||||
- Fixed low-level word-wrapping function reading from `*text_end` when passed
|
||||
a string range. (#9107) [@achabense]
|
||||
- Changed `RenderTextEllipsis()` logic to not trim trailing blanks before
|
||||
the ellipsis, making ellipsis position more consistent and not arbitrary
|
||||
hiding the possibility of multiple blanks. (#9229)
|
||||
- Nav:
|
||||
- Fixed remote/shortcut InputText() not teleporting mouse cursor when
|
||||
nav cursor is visible and `io.ConfigNavMoveSetMousePos` is enabled.
|
||||
- Fixed a looping/wrapping issue when used in menu layer. (#9178)
|
||||
- Fixed speed scale for resizing/moving with keyboard/gamepad. We incorrectly
|
||||
used `io.DisplayFramebufferScale` as a scaling factor (very old code),
|
||||
effectively making those actions faster on macOS/iOS retina screens.
|
||||
(changed this to use a style scale factor that's not fully formalized yet)
|
||||
- Fixed an UBSan warning when using in a `ImGuiListClipper` region . (#9160)
|
||||
- Scrollbar: fixed a code-path leading to a divide-by-zero (which would not be
|
||||
noticeable by user but detected by sanitizers). (#9089) [@judicaelclair]
|
||||
- InvisibleButton: allow calling with size (0,0) to fit to available content
|
||||
size. (#9166, #7623)
|
||||
- Tooltips, Disabled: fixed `EndDisabledOverrideReenable()` assertion when
|
||||
nesting a tooltip in a disabled block. (#9180, #7640) [@RegimantasSimkus]
|
||||
- Added `GetItemFlags()` in public API for consistency and to expose generic
|
||||
flags of last submitted item. (#9127)
|
||||
- Misc: fixed build on ARM64/ARM64EC targets trying to use SSE/immintrin.h.
|
||||
(#9209, #5943, #4091) [@navvyswethgraphics]
|
||||
- Log/Capture:
|
||||
- Fixed erroneously injecting extra carriage returns in output text buffer
|
||||
when `ItemSpacing.y` > `FramePadding.y + 1` while emitting items.
|
||||
- Images:
|
||||
- Added `style.ImageRounding`, `ImGuiStyleVar_ImageRounding `to configure
|
||||
rounding of `Image()` widgets. (#2942, #845)
|
||||
- `ImageButton()` doesn't use a clamped `style.FrameRounding` value but instead
|
||||
adjust inner image rounding when `FramePadding > `FrameRounding`. (#2942, #845)
|
||||
- Shortcuts:
|
||||
- IsItemHovered() without `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem`
|
||||
doesn't filter out the signal when activated item is a shortcut remote activation;
|
||||
(which mimics what's done internally in the `ItemHoverable()` function). (#9138)
|
||||
- Fixed tooltip placement being affected for a frame when located over an item
|
||||
activated by `SetNextItemShortcut()`. (#9138)
|
||||
- Error Handling:
|
||||
- Improved error handling and recovery for `EndMenu()`/`EndCombo()`. (#1651, #9165, #8499)
|
||||
- Improved error handling and recovery for `TableSetupColumn()`.
|
||||
- Debug Tools:
|
||||
- Debug Log: fixed incorrectly printing characters in IO log when submitting
|
||||
non-ASCII values to `io.AddInputCharacter()`. (#9099)
|
||||
- Debug Log: can output to debugger on Windows via Win32 `OutputDebugString()` (#5855)
|
||||
- Demo:
|
||||
- Slightly improve `Selectable()` demos. (#9193)
|
||||
- Backends:
|
||||
- DirectX10: added `SamplerNearest` in `ImGui_ImplDX10_RenderState`.
|
||||
(+renamed `SamplerDefault` to `SamplerLinear`, which was tagged as beta API)
|
||||
- DirectX11: added `SamplerNearest` in ImGui_ImplDX11_RenderState.
|
||||
(+renamed `SamplerDefault` to `SamplerLinear`, which was tagged as beta API)
|
||||
- GLFW: Avoid repeated `glfwSetCursor()` / `glfwSetInputMode()` unnecessary calls.
|
||||
Lowers overhead for very high framerates (e.g. 10k+ FPS). [@maxliani]
|
||||
- GLFW: Added `IMGUI_IMPL_GLFW_DISABLE_X11` / `IMGUI_IMPL_GLFW_DISABLE_WAYLAND` to
|
||||
forcefully disable either. (#9109, #9116)
|
||||
Try to set them automatically if headers are not accessible. (#9225)
|
||||
- OpenGL3: Fixed embedded loader multiple init/shutdown cycles broken on some
|
||||
platforms. (#8792, #9112)
|
||||
- SDL2, SDL3: changed `GetClipboardText()` handler to return NULL on error aka
|
||||
clipboard contents is not text. Consistent with other backends. (#9168)
|
||||
- SDL2, SDL3: systems other than X11 are back to starting mouse capture on mouse down
|
||||
(reverts 1.91.9 change). Only X11 requires waiting for a drag by default (not ideal,
|
||||
but a better default for X11 users). Waiting for a drag to start mouse capture leads to
|
||||
input drops when dragging after clicking on the edge of a window.
|
||||
(#3650, #6410, #9235, #3956, #3835)
|
||||
- SDL2, SDL3: added `ImGui_ImplSDL2_SetMouseCaptureMode()`/`ImGui_ImplSDL3_SetMouseCaptureMode()`
|
||||
function for X11 users to disable mouse capturing/grabbing. (#3650, #6410, #9235, #3956, #3835)
|
||||
- When attached to a debugger may want to call:
|
||||
- `ImGui_ImplSDL3_SetMouseCaptureMode(ImGui_ImplSDL3_MouseCaptureMode_Disabled);`
|
||||
- But you can also configure your system or debugger to automatically release
|
||||
mouse grab when crashing/breaking in debugger, e.g.
|
||||
- console: `setxkbmap -option grab:break_actions && xdotool key XF86Ungrab`
|
||||
- or use a GDB script to call `SDL_CaptureMouse(false)`. See #3650.
|
||||
- On platforms other than X11 this is unnecessary.
|
||||
- SDL_GPU3: added `SamplerNearest` in `ImGui_ImplSDLGPU3_RenderState`.
|
||||
- SDL_GPU3: macOS version can use MSL shaders in order to support macOS 10.14+
|
||||
(vs Metallib shaders requiring macOS 14+). Requires application calling
|
||||
`SDL_CreateGPUDevice()` with `SDL_GPU_SHADERFORMAT_MSL`. (#9076) [@Niminem]
|
||||
- Vulkan: helper for creating a swapchain (used by examples and multi-viewports)
|
||||
selects `VkSwapchainCreateInfoKHR`'s `compositeAlpha` value based on
|
||||
`cap.supportedCompositeAlpha`, which seems to be required on some Android
|
||||
devices. (#8784) [@FelixStach]
|
||||
- WebGPU: fixes for Emscripten 5.0.0 (note: current examples do not build with 5.0.1).
|
||||
- Win32: handle `WM_IME_CHAR`/`WM_IME_COMPOSITION` to support Unicode inputs on
|
||||
MBCS (non-Unicode) Windows. (#9099, #3653, #5961) [@ulhc, @ocornut, @Othereum]
|
||||
- Win32: minor optimization not submitting gamepad input if packet number has not
|
||||
changed (reworked previous 1.92.4). (#9202, #8556) [@AhmedSamyMousa, @MidTerm-CN]
|
||||
- Examples:
|
||||
- Win32+DirectX12: ignore seemingly incorrect `D3D12_MESSAGE_ID_FENCE_ZERO_WAIT`
|
||||
warning on startups on some setups. (#9084, #9093) [@RT2Code, @LeoGautheron]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.5 (Released 2025-11-20)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.5
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Keys: commented out legacy names which were obsoleted in 1.89.0 (August 2022).
|
||||
- ImGuiKey_ModCtrl --> ImGuiMod_Ctrl
|
||||
- ImGuiKey_ModShift --> ImGuiMod_Shift
|
||||
- ImGuiKey_ModAlt --> ImGuiMod_Alt
|
||||
- ImGuiKey_ModSuper --> ImGuiMod_Super
|
||||
- IO: commented out legacy io.ClearInputCharacters() obsoleted in 1.89.8 (Aug 2023).
|
||||
Using io.ClearInputKeys() is enough.
|
||||
- BeginChild: commented out legacy names which were obsoleted in 1.90.0 (Nov 2023),
|
||||
1.90.9 (July 2024), 1.91.1 (August 2024). (#462, #7687)
|
||||
- ImGuiChildFlags_Border --> ImGuiChildFlags_Borders
|
||||
- ImGuiWindowFlags_NavFlattened --> ImGuiChildFlags_NavFlattened (moved to ImGuiChildFlags).
|
||||
- ImGuiWindowFlags_AlwaysUseWindowPadding --> ImGuiChildFlags_AlwaysUseWindowPadding (moved to ImGuiChildFlags).
|
||||
So:
|
||||
- BeginChild(name, size, 0, ImGuiWindowFlags_NavFlattened) --> BeginChild(name, size, ImGuiChildFlags_NavFlattened, 0)
|
||||
- BeginChild(name, size, 0, ImGuiWindowFlags_AlwaysUseWindowPadding) --> BeginChild(name, size, ImGuiChildFlags_AlwaysUseWindowPadding, 0)
|
||||
- Commented out legacy SetItemAllowOverlap() obsoleted in 1.89.7: this never worked right.
|
||||
Use SetNextItemAllowOverlap() _before_ item instead.
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Windows:
|
||||
- Config flag io.ConfigWindowsMoveFromTitleBarOnly is now latched during
|
||||
Begin(), effectively allowing to change the value on a per-window basis.
|
||||
(although there is a better internal mechanism for it).
|
||||
- Fixed single-axis auto-sizing (via double-clicking a border or passing
|
||||
0.0f on one axis of SetNextWindowSize() call) to take account of remaining
|
||||
scrollbar on the other axis. (#9060)
|
||||
- Fixed an issue where repeated calls to SetNextWindowSize() using 0.0f
|
||||
to auto-size on a given axis would keep marking ini settings as dirty.
|
||||
- Tables:
|
||||
- Fixed a bug where nesting BeginTable()->Begin()->BeginTable() would
|
||||
result in temporarily incorrect state, which would lead to bugs to side effects
|
||||
in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005)
|
||||
EndTable() was mistakenly restoring a wrong current table.
|
||||
- Angled headers: fixed an auto-resize feedback loop that could
|
||||
affect tables with empty non-resizing columns using angled headers, making
|
||||
them typically flicker back and forth between +0 and +1 pixels.
|
||||
- Disabled: fixed a bug when a previously enabled item that got nav focus
|
||||
and then turns disabled could still be activated using keyboard. (#9036)
|
||||
- InputText:
|
||||
- When buffer is not resizable, trying to paste contents that cannot
|
||||
fit will now truncate text to nearest UTF-8 codepoint boundaries,
|
||||
instead of completely ignoring the paste. (#9029)
|
||||
- Avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter
|
||||
keys in order to allow e.g. external Shortcut override behavior. (#9004)
|
||||
- When using a callback to reduce/manipulate the value of BufTextLen,
|
||||
we do not require anymore that CursorPos be clamped by user code. (#9029)
|
||||
- Fixed an assert when using ImGuiInputTextFlags_ReadOnly and making
|
||||
underlying contents shorter while text is selected. (#9069, #3237)
|
||||
(regression from 1.92.3)
|
||||
- InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and
|
||||
resizing the parent window while keeping the multi-line field active (which is
|
||||
most typically achieved when resizing programmatically or via a docking layout
|
||||
reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut]
|
||||
- Nav:
|
||||
- Reworked PageUp/PageDown logic to pick same-page top/bottom page based
|
||||
on inner rectangle rather than clipping rectangle, ensuring consistent
|
||||
(but occasionally less practical) navigation result when a window is
|
||||
partially out of screen. (#787)
|
||||
- Improved/clarified behavior when requesting PageUp/PageDown from a
|
||||
focused item which is outside of visible boundaries: now ends up one
|
||||
page away from focused item. (#9079)
|
||||
- Clipper: fixed an issue when using up/down from an item outside of
|
||||
visible bound and using the clipper. (#9079)
|
||||
- Fonts:
|
||||
- Calling ImFontAtlas::Clear() mid-frame without re-adding a font will
|
||||
lead to a more explicit crash.
|
||||
- Textures:
|
||||
- Fixed an issue preventing multi-contexts from using each others' fonts
|
||||
if context 2 runs after context 1's Render() function. (#9039)
|
||||
- MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default
|
||||
right-click processing, which selects item on mouse down and is designed for
|
||||
context-menus. (#8200, #9015)
|
||||
- Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() when
|
||||
triggered by some widgets e.g. Checkbox(), Selectable() and many others, which
|
||||
cleared ActiveId at the same time as editing. (#9028)
|
||||
Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited().
|
||||
- Misc: standardized casing of keyboard mods in comments and demo, showing
|
||||
as e.g. "Ctrl" instead of "CTRL".
|
||||
- CI: Added Dear ImGui Test Suite to CI builds. [@rokups]
|
||||
- Drag and Drop:
|
||||
- Added ImGuiDragDropFlags_AcceptDrawAsHovered to make accepting item render
|
||||
as hovered, which can allow using e.g. Button() as drop target. (#8632)
|
||||
- Pressing Escape while carrying a payload automatically cancel the
|
||||
active drag and drop. (#9071)
|
||||
- Style: added ImGuiCol_DragDropTargetBg, style.DragDropTargetRounding,
|
||||
style.DragDropTargetBorderSize and style.DragDropTargetPadding to configure
|
||||
the drop target highlight. (#9056) [@aaronkirkham]
|
||||
- Demo: About Box: emit infos to convey when IM_ASSERT() macro is disabled,
|
||||
- so users don't miss out on programming errors being reported.
|
||||
- so it is included in config/build info submitted in new GitHub Issues.
|
||||
- Debug Tools:
|
||||
- Fixed DebugTextEncoding() potentially reading out of bounds when
|
||||
provided a trailing truncated UTF-8 sequence.
|
||||
- Metrics: fixed table and columns rect highlight from display when
|
||||
debug/metrics window is not in the same viewport as the table.
|
||||
- Backends:
|
||||
- NULL: added imgui_impl_null platform/renderer backend.
|
||||
This is designed if you need to run e.g. context with no input or no output.
|
||||
- GLFW: fixed building on Linux platforms where Wayland headers
|
||||
are not available. (#9024, #8969, #8921, #8920) [@jagot]
|
||||
- GLFW: lower minimum requirement from GLFW 3.1 to GLFW 3.0. Though
|
||||
a recent version e.g GLFW 3.4 is highly recommended! (#9055) [@Clownacy]
|
||||
- GLFW: fixed last `ImGui_ImplGlfw_Shutdown()` not immediately clearing the context
|
||||
map, which would be detected by leak trackers. (#9075, #8676, #8239, #8069) [@erincatto]
|
||||
- SDL3: fixed Platform_OpenInShellFn() return value (the return value
|
||||
was unused in core but might be used by a direct caller). (#9027) [@achabense]
|
||||
- SDL3: fixed an issue with missing characters events when an already active text
|
||||
field changes viewports. (#9054)
|
||||
- Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to
|
||||
Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk]
|
||||
- WebGPU: update to compile with Dawn and Emscripten's 4.0.10+
|
||||
'--use-port=emdawnwebgpu' ports. (#8381, #8898, #7435) [@brutpitt, @trbabb]
|
||||
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
|
||||
- WebGPU: added various internal/optional helpers to wrap some of the
|
||||
Dawn/WGPU/Emscripten debacle quirks: (#8381) [@brutpitt]
|
||||
- ImGui_ImplWGPU_CreateWGPUSurfaceHelper().
|
||||
- ImGui_ImplWGPU_IsSurfaceStatusError(), ImGui_ImplWGPU_IsSurfaceStatusSubOptimal().
|
||||
- ImGui_ImplWGPU_DebugPrintAdapterInfo(),
|
||||
- ImGui_ImplWGPU_GetBackendTypeName(), ImGui_ImplWGPU_GetAdapterTypeName(),
|
||||
ImGui_ImplWGPU_GetDeviceLostReasonName(), ImGui_ImplWGPU_GetErrorTypeName(),
|
||||
ImGui_ImplWGPU_GetLogLevelName().
|
||||
- Win32: Revert 1.92.4 change of comparing dwPacketNumber, which prevents
|
||||
refreshing accurate gamepad info after focus-out + io.ClearInputKeys(). (#8556)
|
||||
- Examples:
|
||||
- NULL: update examples_null to use imgui_impl_null (which is a bit overengineering
|
||||
but somehow consistent).
|
||||
- GLFW+WebGPU: update example for latest specs, to work on Emscripten 4.0.10+,
|
||||
latest Dawn-Native and WGPU-Native. (#8381, #8567, #8191, #7435) [@brutpitt]
|
||||
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
|
||||
during surface resize. (#8381)
|
||||
- SDL2+WebGPU: added new example (Emscripten + native Dawn/WGPU). (#8381) [@brutpitt]
|
||||
- SDL3+WebGPU: added new example (Emscripten + native Dawn/WGPU). (#8381) [@brutpitt]
|
||||
- Win32+OpenGL3: enable DPI awareness. (#9083)
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.4 (Released 2025-10-14)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.4
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Backends:
|
||||
- TreeNode, Selectable, Clipper: commented out legacy names obsoleted in
|
||||
1.89.7 (July 2023) and 1.89.9 (Sept 2023):
|
||||
ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap
|
||||
ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap
|
||||
ImGuiListClipper::IncludeRangeByIndices() --> ImGuiListClipper::IncludeItemsByIndex()
|
||||
- Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo:
|
||||
init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass
|
||||
init_info.Subpass --> init_info.PipelineInfoMain.Subpass
|
||||
init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples
|
||||
init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo
|
||||
It makes things more consistent and was desirable to introduce new settings for
|
||||
secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz]
|
||||
- Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo
|
||||
(introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()`
|
||||
so it should not affect many users). (#8110, #8111)
|
||||
- Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a
|
||||
`VkImageUsageFlags image_usage` argument.
|
||||
It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults
|
||||
to that when the value is 0. In theory the function is an internal helper but
|
||||
since it's used by our examples some may have used it. (#8946, #8111, #8686)
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Windows: added lower-right resize grip on child windows using both
|
||||
ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani]
|
||||
The grip is not visible before hovering to reduce clutter.
|
||||
- Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when
|
||||
using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983)
|
||||
- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers()
|
||||
helpers to null all handlers. (#8945, #2769)
|
||||
- Tables: changed ImGuiTableFlags_NoBordersInBody behavior to not draw border in
|
||||
body even when resizing. (#8893)
|
||||
- Inputs:
|
||||
- Shortcuts: added support for combining ImGuiInputFlags_RouteFocused
|
||||
(which is the default route) with ImGuiInputFlags_RouteOverActive, allowing
|
||||
to steal shortcuts from active item without using global routing. (#9004)
|
||||
- InputText:
|
||||
- Fixed single-line InputText() not applying fine character clipping
|
||||
properly (regression in 1.92.3). (#8967) [@Cyphall]
|
||||
- Fixed an infinite loop error happening if a custom input text
|
||||
callback modifies/clear BufTextLen before calling InsertChars().
|
||||
(regression from 1.92.3). Note that this never really worked correctly, but
|
||||
previously it would only temporary wreck cursor position, and since 1.92.3 it
|
||||
would go in an infinite loop. (#8994, #3237)
|
||||
- Textures:
|
||||
- Fixed a crash if texture status is set to ImTextureStatus_WantDestroy by a backend
|
||||
after it had already been destroyed. This would typically happen when calling
|
||||
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
|
||||
- Allowed backend to destroy texture while inside the NewFrame/EndFrame
|
||||
scope. Basically if a backend decide to destroy a texture that we didn't request
|
||||
to destroy (for e.g. freeing resources) the texture is immediately set to
|
||||
a ImTextureStatus_WantCreate status again. (#8811)
|
||||
- Fixed an issue preventing multi-contexts sharing a ImFontAtlas from
|
||||
being possible to destroy in any order.
|
||||
- Fixed not updating ImTextureData's RefCount when destroying a context
|
||||
using a shared ImFontAtlas, leading standard backends to not properly
|
||||
free texture resources. (#8975) [@icrashstuff]
|
||||
- Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section.
|
||||
- Misc: Relaxed internal assert in MarkItemEdited() to allow for more use cases. (#8997)
|
||||
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
|
||||
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
|
||||
See misc/debuggers/ for details. (#8950) [@mentlerd]
|
||||
- CI: updated Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
|
||||
- Docs: updated FAQ with new "What is the difference between Dear ImGui and
|
||||
traditional UI toolkits?" entry. (#8862)
|
||||
- Backends:
|
||||
- All backends call ImGuiPlatformIO::ClearPlatformHandlers() and
|
||||
ClearRendererHandlers() on shutdown, so as not to leave function pointers
|
||||
which may be dangling when using backend in e.g. DLL. (#8945, #2769)
|
||||
- DirectX12: reuse a command list and allocator for texture uploads instead
|
||||
of recreating them each time. (#8963, #8465) [@RT2Code]
|
||||
- DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
||||
(presumably fixes old hard-to-repro crash issues such as #3463, #5018)
|
||||
- DirectX12: Reuse texture upload buffer and grow it only when
|
||||
necessary. (#9002) [@RT2Code]
|
||||
- DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
|
||||
- OpenGL3: fixed GL loader to work on Haiku OS which does not support
|
||||
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
|
||||
- GLFW: fixed build on platform that are neither Windows, macOS or
|
||||
known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion]
|
||||
- SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our
|
||||
window is hovered, as the event data is reliable and enough in this case.
|
||||
- Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786)
|
||||
- Essentially a workaround for SDL3 bug which will be fixed in SDL 3.3.0.
|
||||
- Better perf on X11 as querying global position requires a round trip to X11 server.
|
||||
- Win32: minor optimization not submitting gamepad io again if
|
||||
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
|
||||
- Vulkan: added a way to specify custom shaders by filling init fields
|
||||
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
|
||||
- DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
|
||||
ensure that a texture in ImTextureStatus_WantDestroy state always turn to
|
||||
ImTextureStatus_Destroyed even if your underlying graphics data was already
|
||||
destroyed. (#8977)
|
||||
- Examples:
|
||||
- SDL2+DirectX11: Try WARP software driver if hardware driver is
|
||||
not available. (#5924, #5562)
|
||||
- SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
|
||||
- Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
||||
- Made examples's main.cpp consistent with returning 1 on error.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.3 (Released 2025-09-17)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.3
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Fonts: fixed merging a font and specifying a font target in DstFont
|
||||
that's not the last added font (regression in 1.92). (#8912)
|
||||
- Fonts: fixed an assertion failure when a rectangle entry has been reused
|
||||
1024 times (e.g. due to constant change of font size). (#8906) [@cfillion]
|
||||
- Clipper, Tables: added ImGuiListClipperFlags_NoSetTableRowCounters as a way to
|
||||
disable the assumption that 1 clipper item == 1 table row, which breaks when
|
||||
e.g. using clipper with ItemsHeight=1 in order to clip in pixel units. (#8886)
|
||||
- Scrollbar, Style: added configurable style.ScrollbarPadding value and corresponding
|
||||
ImGuiStyleVar_ScrollbarPadding enum, instead of an hard-coded computed default. (#8895)
|
||||
- Nav: fixed Ctrl+Tab window appearing as empty when the sole active and focused
|
||||
window has the ImGuiWindowFlags_NoNavFocus flag. (#8914)
|
||||
- Nav: fixed a crash that could occur when opening a popup following the processing
|
||||
of a global shortcut while no windows were focused.
|
||||
- Bullet: fixed tessellation which looked out of place in very large sizes.
|
||||
- InputText: added ImGuiInputTextFlags_WordWrap flag to word-wrap multi-line buffers.
|
||||
(#3237, #952, #1062, #7363). Current caveats:
|
||||
- This is marked as beta because not being tested enough.
|
||||
Please report any incorrect cursor movement, selection behavior etc. bug to #3237.
|
||||
- Wrapping style is not ideal. Wrapping of long words/sections (e.g. words
|
||||
larger than total available width) may be particularly unpleasing.
|
||||
- Wrapping width needs to always account for the possibility of a vertical scrollbar.
|
||||
- It is currently much slower than regular text fields:
|
||||
- Ballpark estimate of cost on my 2019 desktop PC:
|
||||
For a 100 KB text buffer: +~0.3 ms/+~1.0 ms (Optimized vs Debug builds).
|
||||
- The CPU cost is very roughly proportional to text length, so a 10 KB buffer
|
||||
should cost about ten times less.
|
||||
- InputText, InputInt, InputFloat: fixed an issue where using Escape to revert
|
||||
would not write back the reverted value during the IsItemDeactivatedAfterEdit()
|
||||
frame if the provided input buffer doesn't store temporary edits.
|
||||
(regression in 1.91.7) (#8915, #8273)
|
||||
- InputText: fixed an issue where using Escape with ImGuiInputTextFlags_EscapeClearsAll
|
||||
would not write back the cleared value during the IsItemDeactivatedAfterEdit()
|
||||
frame if the provided input buffer doesn't store temporary edits. (#8915, #8273)
|
||||
- InputText: allow passing an empty string with buf_size==0. (#8907)
|
||||
In theory the buffer size should always account for a zero-terminator, but idioms
|
||||
such as using InputTextMultiline() with ImGuiInputTextFlags_ReadOnly to display
|
||||
a text blob are facilitated by allowing this.
|
||||
- InputText: refactored internals to simplify and optimizing rendering of selection.
|
||||
Very large selection (e.g. 1 MB) now take less overhead.
|
||||
- InputText: revert a change in 1.79 where pressing Down or PageDown on the last line
|
||||
of a multi-line buffer without a trailing carriage return would keep the cursor
|
||||
unmoved. We revert back to move to the end of line in this situation.
|
||||
- InputText: fixed pressing End (without Shift) in a multi-line selection from
|
||||
mistakenly moving cursor based on selection start.
|
||||
- Focus, InputText: fixed an issue where SetKeyboardFocusHere() did not work
|
||||
on InputTextMultiline() fields with ImGuiInputTextFlags_AllowTabInput, since
|
||||
they normally inhibit activation to allow tabbing through multiple items. (#8928)
|
||||
- Selectable: added ImGuiSelectableFlags_SelectOnNav to auto-select an item when
|
||||
moved into, unless Ctrl is held. (automatic when in a BeginMultiSelect() block).
|
||||
- TabBar: fixed an issue were forcefully selecting a tab using internal API would
|
||||
be ignored on first/appearing frame before tabs are submitted (#8929, #6681)
|
||||
- DrawList: fixed CloneOutput() unnecessarily taking a copy of the ImDrawListSharedData
|
||||
pointer, which could to issue when deleting the cloned list. (#8894, #1860)
|
||||
- DrawList: made AddCallback() assert when passing a null callback.
|
||||
- Debug Tools: ID Stack Tool: fixed using fixed-size buffers preventing long identifiers
|
||||
from being displayed in the tool. (#8905, #4631)
|
||||
- Debug Tools: ID Stack Tool: when ### is used, uncontributing prefix before the ###
|
||||
is now skipped. (#8904, #4631)
|
||||
- Debug Tools: ID Stack Tool: added option to hex-encode non-ASCII characters in
|
||||
output path. (#8904, #4631)
|
||||
- Debug Tools: ID Stack Tool: fixed a crash when using PushOverrideID(0) during
|
||||
a query. (#8937, #4631)
|
||||
- Debug Tools: Fixed assertion failure when opening a combo box while using
|
||||
io.ConfigDebugBeginReturnValueOnce/ConfigDebugBeginReturnValueLoop. (#8931) [@harrymander]
|
||||
- Demo: tweaked ShowFontSelector() and ShowStyleSelector() to update selection
|
||||
while navigating and to not close popup automatically.
|
||||
- CI: Updates Windows CI to use a more recent VulkanSDK. (#8925, #8778) [@yaz0r]
|
||||
- Examples: Android: Android+OpenGL3: update Gradle project (#8888, #8878) [@scribam]
|
||||
- Examples: GLFW+OpenGL2, GLFW+Vulkan, GLFW+Metal, Win32+Vulkan: Fixed not applying
|
||||
content scale consistently with other examples. (#8921, #8756)
|
||||
- Backends: GLFW: distinguish X11 vs Wayland to fix various scaling issues.
|
||||
(#8920, #8921) [@TheBrokenRail, @pthom, @ocornut]
|
||||
- window/monitor content scales are always reported as 1.0 on Wayland.
|
||||
- framebuffer scales are always reported as 1.0 on X11.
|
||||
- Backends: SDL2: window/monitor content scales are always reported as 1.0 on Wayland.
|
||||
(#8920, #8921) [@TheBrokenRail, @pthom, @ocornut]
|
||||
- Backends: SDL3: use SDL_GetWindowDisplayScale() on Mac to obtain DisplayFrameBufferScale,
|
||||
fixing incorrect values during resolution changes e.g. going fullscreen.
|
||||
(#8703, #4414) [@jclounge]
|
||||
- Backends: SDL_GPU: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and
|
||||
PresentMode to configure how secondary viewports are created. Currently only used
|
||||
multi-viewport mode. (#8892) [@PTSVU]
|
||||
- Backends: Vulkan: added ImGui_ImplVulkan_CreateMainPipeline() to recreate pipeline
|
||||
without reinitializing backend. (#8110, #8111) [@SuperRonan]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.2b (Released 2025-08-13)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.2b
|
||||
|
||||
Changes:
|
||||
|
||||
- Fixed IsItemHovered() failing on disabled items and items that have no
|
||||
identifier (e.g. Text() calls) when holding mouse button. (#8877, #8883)
|
||||
[Regression in 1.92.2].
|
||||
- Made IsItemHovered() on holding mouse button down on disabled items not
|
||||
leak between items when the window cannot be moved.
|
||||
- Backends: Allegro5: Fixed texture format setup which didn't work on all
|
||||
setups/drivers. (#8770, #8465)
|
||||
- Backends: Allegro5: Added ImGui_ImplAllegro5_SetDisplay() function to
|
||||
change current ALLEGRO_DISPLAY, as Allegro applications often need to do that.
|
||||
- Backends: Allegro5: Fixed missing support for ImGuiKey_PrintScreen
|
||||
under Windows, as raw Allegro 5 does not receive it.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.2 (Released 2025-08-11)
|
||||
-----------------------------------------------------------------------
|
||||
@@ -253,7 +1163,7 @@ Breaking changes:
|
||||
which font input is providing which glyph.
|
||||
- Fonts: **IMPORTANT** on Thread Safety:
|
||||
- A few functions such as font->CalcTextSizeA() were by sheer luck (== accidentally)
|
||||
thread-safe even thou we had never provided that guarantee before. They are
|
||||
thread-safe even though we had never provided that guarantee before. They are
|
||||
definitively not thread-safe anymore as new glyphs may be loaded.
|
||||
|
||||
- Textures:
|
||||
@@ -291,7 +1201,7 @@ Breaking changes:
|
||||
to 4096 but that limit isn't necessary anymore, and Renderer_TextureMaxWidth covers this)
|
||||
However you may set TexMinWidth = TexMaxWidth for the same effect.
|
||||
- Fonts: if you create and manage ImFontAtlas instances yourself (instead of relying on
|
||||
ImGuiContext to create one, you'll need to call ImFontAtlasUpdateNewFrame() yourself.
|
||||
ImGuiContext to create one), you'll need to call ImFontAtlasUpdateNewFrame() yourself.
|
||||
An assert will trigger if you don't.
|
||||
- Fonts: obsoleted ImGui::SetWindowFontScale() which is not useful anymore. Prefer using
|
||||
PushFont(NULL, style.FontSizeBase * factor) or to manipulate other scaling factors.
|
||||
@@ -1006,6 +1916,7 @@ Breaking changes:
|
||||
- Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before).
|
||||
- io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). Use IsKeyDown() instead.
|
||||
- io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
|
||||
- GetKeyIndex() is removed (obsoleted March 2022). The indirection is now unnecessary.
|
||||
- Pre-1.87 backends are not supported:
|
||||
- backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields.
|
||||
- backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields.
|
||||
@@ -1073,7 +1984,7 @@ Breaking changes:
|
||||
allows casting any pointer/integer type without warning:
|
||||
- May warn: ImGui::Image((void*)MyTextureData, ...);
|
||||
- May warn: ImGui::Image((void*)(intptr_t)MyTextureData, ...);
|
||||
- Won't warn: ImGui::Image((ImTextureID)(intptr_t)MyTextureData), ...);
|
||||
- Won't warn: ImGui::Image((ImTextureID)(intptr_t)MyTextureData, ...);
|
||||
- Note that you can always define ImTextureID to be your own high-level structures
|
||||
(with dedicated constructors and extra render parameters) if you like.
|
||||
- IO: moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
|
||||
@@ -4443,7 +5354,7 @@ Breaking Changes:
|
||||
- ShowTestWindow() -> use ShowDemoWindow()
|
||||
- IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow)
|
||||
- IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)
|
||||
- SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f)
|
||||
- SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f))
|
||||
- GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing()
|
||||
- ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg
|
||||
- ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding
|
||||
|
||||
@@ -72,7 +72,7 @@ OSX + OpenGL2 example. <BR>
|
||||
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
|
||||
|
||||
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
|
||||
GLFW + WebGPU example. Supports Emscripten (web) or Dawn (desktop) <BR>
|
||||
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
|
||||
Note that the 'example_glfw_opengl3' and 'example_sdl2_opengl3' examples also supports Emscripten!
|
||||
|
||||
@@ -109,9 +109,11 @@ Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
|
||||
|
||||
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
|
||||
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
|
||||
= main.cpp <BR>
|
||||
= main.cpp + imgui_impl_null.cpp<BR>
|
||||
This is used to quickly test compilation of core imgui files in as many setups as possible.
|
||||
Because this application doesn't create a window nor a graphic context, there's no graphics output.
|
||||
Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but
|
||||
it is similarly easy to create a skeleton application without the null backend.
|
||||
|
||||
[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/) <BR>
|
||||
SDL2 + DirectX11 example, Windows only. <BR>
|
||||
@@ -149,8 +151,17 @@ SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
|
||||
This is quite long and tedious, because: Vulkan. <BR>
|
||||
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
|
||||
|
||||
[example_sdl2_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_wgpu/) <BR>
|
||||
SDL2 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_wgpu.cpp
|
||||
(note that the 'example_sdl2_opengl3' example also supports Emscripten!)
|
||||
|
||||
[example_sdl3_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_directx11/) <BR>
|
||||
SDL3 + DirectX11 examples, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_dx11.cpp <BR>
|
||||
|
||||
[example_sdl3_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_metal/) <BR>
|
||||
SDL3 + Metal example (Mac). <BR>
|
||||
SDL3 + Metal example, Mac only. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm <BR>
|
||||
|
||||
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/) <BR>
|
||||
@@ -173,6 +184,11 @@ SDL3 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
|
||||
This is quite long and tedious, because: Vulkan. <BR>
|
||||
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
|
||||
|
||||
[example_sdl3_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_wgpu/) <BR>
|
||||
SDL3 + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_wgpu.cpp
|
||||
(note that the 'example_sdl3_opengl3' example also supports Emscripten!)
|
||||
|
||||
[example_win32_directx9/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx9/) <BR>
|
||||
DirectX9 example, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp
|
||||
|
||||
200
docs/FAQ.md
200
docs/FAQ.md
@@ -13,18 +13,19 @@ or view this file with any Markdown viewer.
|
||||
:---------------------------------------------------------- |
|
||||
| [Where is the documentation?](#q-where-is-the-documentation) |
|
||||
| [What is this library called?](#q-what-is-this-library-called) |
|
||||
| [What is the difference between Dear ImGui and traditional UI toolkits?](#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits) |
|
||||
| [Which version should I get?](#q-which-version-should-i-get) |
|
||||
| **Q&A: Integration** |
|
||||
| **[How to get started?](#q-how-to-get-started)** |
|
||||
| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)** |
|
||||
| [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) |
|
||||
| [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display) |
|
||||
| [How can I create my own backend?](q-how-can-i-create-my-own-backend)
|
||||
| [How can I create my own backend?](#q-how-can-i-create-my-own-backend)
|
||||
| [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
||||
| **Q&A: Usage** |
|
||||
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>Why is the wrong widget reacting when I click on one?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
|
||||
| **[About the ID Stack system...](#q-about-the-id-stack-system)**<br>**[How can I have multiple widgets with the same label?](#q-how-can-i-have-multiple-widgets-with-the-same-label) (using `##` or `PushID()`)**<br>**[How can I have widgets with an empty label?](#q-how-can-i-have-widgets-with-an-empty-label) (using `##`)**<br>**[How can I animate the label of an existing widget?](#q-how-can-i-change-the-label-of-an-existing-widget) (using `###`)**<br>**[General description of the label and ID Stack system.](#general-description-of-the-label-and-id-stack-system)** |
|
||||
| [How can I display an image?](#q-how-can-i-display-an-image)<br>[What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)|
|
||||
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
|
||||
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
|
||||
@@ -54,6 +55,7 @@ or view this file with any Markdown viewer.
|
||||
- Handy [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide to integrate Dear ImGui in an existing application.
|
||||
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
|
||||
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
- See pthom's online [imgui_explorer](https://pthom.github.io/imgui_explorer) which is a web version of the demo with a source code browser.
|
||||
- See documentation: [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md), [Examples](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md), [Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
||||
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
|
||||
- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
|
||||
@@ -75,6 +77,60 @@ or view this file with any Markdown viewer.
|
||||
|
||||
---
|
||||
|
||||
### Q: What is the difference between Dear ImGui and traditional UI toolkits?
|
||||
|
||||
Here's a very simplified comparison between the approach taken by Dear ImGui vs traditional toolkits:
|
||||
|
||||
| Dear ImGui | Qt/GTK/WPF... |
|
||||
|--------------------------|--------------------------|
|
||||
| UI fully issued on every update. | UI issued once then later modified. |
|
||||
| UI layout is fully dynamic and can change at any time.<BR>UI is generally emitted programmatically, which empowers reflecting a dynamic set of data. | UI layout is mostly static.<BR>UI may be emitted programmatically or from data created by offline tools. UI need extra code to evolve, which is often tedious and error-prone if it needs to be reflecting dynamic data and systems. |
|
||||
| Application can submit UI based on arbitrary logic and then forget about it. | Application needs more bookkeeping of UI elements. |
|
||||
| UI library stores minimal amounts of data. At one point in time, it typically doesn't know or remember which other widgets are displayed and which widgets are coming next. As a result, certain layout features (alignment, resizing) are not as easy to implement or require ad-hoc code. | UI library stores entire widgets tree and state. UI library can use this retained data to easily layout things. |
|
||||
| UI code may be added anywhere.<BR>You can even create UI to edit a local variable! | UI code needs to be added in dedicated spots. |
|
||||
| UI layout/logic/action/data bindings are all nearby in the code. | UI layout/logic/action/data bindings in distinct functions, files or formats. |
|
||||
| Data is naturally always synchronized. | Use callback/signal/slot for synchronizing data (error-prone). |
|
||||
| API is simple and easy to learn. In particular, doing basic things is very easy. | API is more complex and specialized. |
|
||||
| API is low-level (raw language types). | API are higher-level (more abstractions, advanced language features). |
|
||||
| Less fancy look and feel. | Standard look and feel. |
|
||||
| Compile yourself. Easy to debug, hack, modify, study. | Mostly use precompiled libraries. Compiling, modifying or studying is daunting if not impossible. |
|
||||
| Run on every platform. | Run on limited desktop platforms. |
|
||||
|
||||
Idiomatic Dear ImGui code:
|
||||
```cpp
|
||||
if (ImGui::Button("Save"))
|
||||
MySaveFunction();
|
||||
|
||||
ImGui::SliderFloat("Slider", &m_MyValue, 0.0f, 1.0f);
|
||||
```
|
||||
Idiomatic code with traditional toolkit:
|
||||
```cpp
|
||||
UiButton* button = new UiButton("Save");
|
||||
button->OnClick = &MySaveFunction;
|
||||
parent->Add(button);
|
||||
|
||||
UiSlider* slider = new UiSlider("Slider");
|
||||
slider->SetRange(0.0f, 1.0f);
|
||||
slider->BindData<float>(&m_MyValue);
|
||||
parent->Add(slider);
|
||||
```
|
||||
This is only meant to give you a intuitive feeling of the main differences, but pros & cons go deeper than that.
|
||||
|
||||
Some of those properties are typically associated to the umbrella term "IMGUI", but the term has no simple and well-agreed definition. There are many erroneous statements and misunderstandings with what IMGUI means. It is partly caused by the fact that most popular IMGUI implementations (including Dear ImGui) have originated from game industry needs and have targeted specific use cases, causing people to conflate IMGUI properties with what a specific library does. However, it is perfectly possible to implement an IMGUI library that would have very different properties than e.g. Dear ImGui. My take on defining what an IMGUI is:
|
||||
|
||||
**IMGUI refers to the API: literally the interface between the application and the UI system.**
|
||||
- An IMGUI API favors the application code owning its data and being the single source of truth for it.
|
||||
- An IMGUI API tries to minimize the application having to retain/manage data related to the UI system.
|
||||
- An IMGUI API tries to minimize the UI system having to retain/manage data related to the application.
|
||||
- Synchronization between application data and UI data is natural and less error-prone.
|
||||
|
||||
**IMGUI does NOT refer to the implementation. Whatever happens inside the UI library code doesn't matter.**
|
||||
<BR>Also see: [Links to many articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki/#about-the-imgui-paradigm).
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
||||
### Q: Which version should I get?
|
||||
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
|
||||
|
||||
@@ -207,15 +263,19 @@ ctx->RSSetScissorRects(1, &r);
|
||||
|
||||
# Q&A: Usage
|
||||
|
||||
### Q: About the ID Stack system...
|
||||
### Q: Why is my widget not reacting when I click on it?
|
||||
### Q: Why is the wrong widget reacting when I click on one?
|
||||
### Q: How can I have widgets with an empty label?
|
||||
### Q: How can I have multiple widgets with the same label?
|
||||
### Q: How can I have multiple windows with the same label?
|
||||
## Q: About the ID Stack system...
|
||||
|
||||
**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!**
|
||||
<br>**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!**
|
||||
<br>Read the questions in this section for a more general understand of how labels and ID works in Dear ImGui.
|
||||
|
||||
TL;DR;
|
||||
- Widgets labels are also used to compute Widgets unique identifiers.
|
||||
- Unique identifiers are hashes of the label + of the parent scope (e.g. parent window or parent tree node labels).
|
||||
- You can use `PushID()` to append to the identifier without making it visible.
|
||||
- You can use `"##something"` in a label to append to the identifier without making it visible.
|
||||
- You can use `"###something"` in a label to make the identifier ignore the visible part.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://github.com/user-attachments/assets/776a8315-1164-4178-9a8c-df52e0ff28aa"></td>
|
||||
@@ -246,16 +306,99 @@ ImGui::End();
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
A primer on labels and the ID Stack...
|
||||
### Q: How can I have multiple widgets with the same label?
|
||||
|
||||
A. When widgets are in a same scope and finite, you can use a `"##something"` suffix which will be part of the identifier but not visible as a label.
|
||||
|
||||
```cpp
|
||||
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
|
||||
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons
|
||||
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons
|
||||
```
|
||||
|
||||
B. More generally, e.g. in loops, you can use `PushID()/PopID()` to push a prefix which will be part of the identifier.
|
||||
|
||||
```cpp
|
||||
// Using PushID() with a string
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
MyObject* obj = Objects[i];
|
||||
PushID(obj->Name);
|
||||
Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
|
||||
PopID();
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
// Using PushID() with an index
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
PushID(i);
|
||||
Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
|
||||
PopID();
|
||||
}
|
||||
```
|
||||
|
||||
### Q: How can I have widgets with an empty label?
|
||||
|
||||
If you want to completely hide the label, but still need an ID:
|
||||
|
||||
```cpp
|
||||
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
|
||||
```
|
||||
##### [Return to Index](#index)
|
||||
|
||||
### Q: How can I make a label dynamic?
|
||||
|
||||
Dear ImGui is very dynamic so you can submit different widgets every frame.
|
||||
However, in order to preserve widget state (eg. which tree node is open; which button is focused) the library internaly refers to their unique ID.
|
||||
|
||||
Occasionally you might want to change a label while preserving a constant ID. This allows you to change/animate labels while persisting associated state.
|
||||
For example, you may want to include varying information in a window title bar or button label.
|
||||
|
||||
Using "###" exclude the preceeding part from ID computation:
|
||||
```cpp
|
||||
Button("Hello###ID"); // Label = "Enable", ID = hash of (..., "ID")
|
||||
Button("World###ID"); // Label = "Disable", ID = hash of (..., "ID") // Same ID, different label
|
||||
```
|
||||
Using a same ID ensure that associated related e.g. weither the widget is focused, won't be lost when the label changes.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://github.com/user-attachments/assets/2bf18756-e122-498d-bbd4-5c44bb1018d5"></td>
|
||||
<td>
|
||||
<pre lang="cpp">
|
||||
// Window label has animating FPS counter
|
||||
// Window ID stays the same = hash of "MyGame"
|
||||
char buf[128];
|
||||
sprintf(buf, "My game (%.1f FPS)###MyGame", io.Framerate);
|
||||
ImGui::Begin(buf);
|
||||
|
||||
// Label changes between "Enable" and "Disable"
|
||||
// ID stays the same = hash of ("MyGame", "MyButton")
|
||||
if (ImGui::Button(enabled ? "Disable###MyButton" : "Enable###MyButton", { -FLT_MIN, 0.0f }))
|
||||
enabled = !enabled;
|
||||
|
||||
ImGui::End();
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
(Hint: I'd suggest wrapping sprintf in something more compact to use, e.g. [ocornut/Str](https://github.com/ocornut/Str) for what I personally use).
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
### General description of the label and ID Stack system
|
||||
|
||||
Dear ImGui internally needs to uniquely identify UI elements.
|
||||
Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
|
||||
Interactive widgets (such as calls to Button buttons) need a unique ID.
|
||||
Elements that are typically not clickable (such as calls to Text() functions) don't need an ID.
|
||||
Interactive widgets (such as calls to Button() functions) need a unique ID.
|
||||
|
||||
**Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR>
|
||||
Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
|
||||
|
||||
Since Dear ImGui 1.85, you can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
|
||||
You can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
|
||||
|
||||

|
||||
|
||||
@@ -309,20 +452,7 @@ Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo
|
||||
Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window
|
||||
End();
|
||||
```
|
||||
- If you want to completely hide the label, but still need an ID:
|
||||
```cpp
|
||||
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
|
||||
```
|
||||
- Occasionally/rarely you might want to change a label while preserving a constant ID. This allows
|
||||
you to animate labels. For example, you may want to include varying information in a window title bar,
|
||||
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
|
||||
```cpp
|
||||
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
|
||||
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same ID, different label
|
||||
|
||||
sprintf(buf, "My game (%f FPS)###MyGame", fps);
|
||||
Begin(buf); // Variable title, ID = hash of "MyGame"
|
||||
```
|
||||
- Solving ID conflict in a more general manner:
|
||||
Use `PushID()` / `PopID()` to create scopes and manipulate the ID stack, as to avoid ID conflicts
|
||||
within the same window. This is the most convenient way of distinguishing ID when iterating and
|
||||
@@ -603,22 +733,28 @@ Since 1.92 (June 2025) fonts may be dynamically used at any size.
|
||||
|
||||
**Scaling fonts**
|
||||
|
||||
Select default size:
|
||||
```cpp
|
||||
style.FontSizeBase = 20.0f;
|
||||
```
|
||||
Scale all fonts:
|
||||
```cpp
|
||||
style.FontScaleDpi = 2.0f;
|
||||
```
|
||||
|
||||
To change font size:
|
||||
```cpp
|
||||
ImGui::PushFont(NULL, 42.0f);
|
||||
ImGui::PushFont(NULL, 42.0f); // This will be multiplied by style.FontScaleDpi
|
||||
```
|
||||
To change font and font size:
|
||||
```cpp
|
||||
ImGui::PushFont(new_font, 42.0f);
|
||||
```
|
||||
To scale all fonts:
|
||||
```cpp
|
||||
style.FontScaleDpi = 2.0f;
|
||||
```
|
||||
|
||||
In `docking` branch or with multi-viewports:
|
||||
```cpp
|
||||
io.ConfigDpiScaleFonts = true; // [Experimental] Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now.
|
||||
io.ConfigDpiScaleViewports = true; // [Experimental] Scale Dear ImGui and Platform Windows when Monitor DPI changes.
|
||||
io.ConfigDpiScaleFonts = true; // (Docking branch only) Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now.
|
||||
io.ConfigDpiScaleViewports = true; // (Docking branch only) Scale Dear ImGui and Platform Windows when Monitor DPI changes.
|
||||
```
|
||||
|
||||
**Scaling style** (paddings, spacings, thicknesses)
|
||||
|
||||
@@ -2,10 +2,20 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/FONTS
|
||||
|
||||
## Dear ImGui: Using Fonts
|
||||
|
||||
The code in imgui.cpp embeds a copy of [ProggyClean.ttf](http://proggyfonts.net) (by Tristan Grimmer),
|
||||
a 13 pixels high, pixel-perfect font used by default. We embed it in the source code so you can use Dear ImGui without any file system access. ProggyClean does not scale smoothly, therefore it is recommended that you load your own file when using Dear ImGui in an application aiming to look nice and wanting to support multiple resolutions.
|
||||
The code in Dear ImGui embeds a copy of [ProggyClean.ttf](https://github.com/bluescan/proggyfonts) by Tristan Grimmer,
|
||||
a 13 pixels high, pixel-perfect font used by default. ProggyClean does not scale very nicely.
|
||||
|
||||
You may also load external .TTF/.OTF files.
|
||||
The code in Dear ImGui embeds a partial copy of [ProggyForever.ttf](https://github.com/ocornut/proggyforever) by Disco Hello & Tristan Grimmer,
|
||||
a new font mimicking ProggyClean which does scale nicely.
|
||||
|
||||
We embed fonts in the code so you can use Dear ImGui without any file system access.
|
||||
If you don't use them you can set `IMGUI_DISABLE_DEFAULT_FONT` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file to ship binaries without the fonts and save about ~26 KB.
|
||||
|
||||
Calling io.Fonts->AddFontDefaultVector() loads ProggyForever.
|
||||
Calling io.Fonts->AddFontDefaultBitmap() loads ProggyClean.
|
||||
Calling io.Fonts->AddFontDefault() selects one based on the expected default font size (when `style.FontSizeBase * style.FontScaleMain * style.FontSizeDpi >= 15` we use ProggyForever).
|
||||
|
||||
You may also load external .TTF/.OTF files, see instructions on this page.
|
||||
In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) folder you can find a few suggested fonts, provided as a convenience.
|
||||
|
||||
**Also read the FAQ:** https://www.dearimgui.com/faq (there is a Fonts section!)
|
||||
@@ -89,7 +99,10 @@ See [#8465](https://github.com/ocornut/imgui/issues/8465) for more details.
|
||||
|
||||
## How should I handle DPI in my application?
|
||||
|
||||
See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application).
|
||||
Since 1.92, with an updated backend, you can set `style.FontScaleDpi = your_content_scale;` to scale all fonts.
|
||||
<BR>You can call `style.ScaleAllSizes(xxx)` at init time or every frame at the beginning of your main loop to scale sizes/paddings.
|
||||
<BR>Since 1.92, with an updated backend, macOS style pixel/backing style scale is automatically handled.
|
||||
<BR>See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application) for more details.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -97,10 +110,22 @@ See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-s
|
||||
|
||||
## Fonts Loading Instructions
|
||||
|
||||
**Select base size**
|
||||
```cpp
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.FontSizeBase = 20.0f;
|
||||
```
|
||||
|
||||
**Load default font:**
|
||||
```cpp
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
io.Fonts->AddFontDefaultVector(); // Load embedded scalable font.
|
||||
```
|
||||
```cpp
|
||||
io.Fonts->AddFontDefaultBitmap(); // Load embedded bitmap font (legacy).
|
||||
```
|
||||
```cpp
|
||||
io.Fonts->AddFontDefault(); // Load embedded font (legacy: auto-selected between the two above).
|
||||
```
|
||||
|
||||
**Load .TTF/.OTF file with:**
|
||||
@@ -145,12 +170,11 @@ ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
|
||||
🆕 **Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary.**
|
||||
```cpp
|
||||
// Load a first font
|
||||
ImFont* font = io.Fonts->AddFontDefault();
|
||||
ImFont* font = io.Fonts->AddFontDefaultVector();
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 0.0f, &config); // Merge into first font to add e.g. Asian characters
|
||||
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 0.0f, &config); // Merge into first font to add Icons
|
||||
io.Fonts->Build();
|
||||
```
|
||||
:rewind: **Before 1.92, or without an up to date backend:**
|
||||
```cpp
|
||||
@@ -203,7 +227,7 @@ if (ImGui::Button(u8"ロード"))
|
||||
{
|
||||
// do stuff
|
||||
}
|
||||
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::InputText("string", buf, IM_COUNTOF(buf));
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
```
|
||||
|
||||
@@ -229,6 +253,7 @@ ImFontConfig font_cfg;
|
||||
font_cfg.FontDataOwnedByAtlas = false;
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg);
|
||||
```
|
||||
IMPORTANT: Since 1.92, when using `FontDataOwnedByAtlas = false`, font data needs to available until `atlas->RemoveFont()`, or more typically until a shutdown of the owning context or font atlas. It was not immediately noticeable in 1.92.0 due to a bug in handling `FontDataOwnedByAtlas = false`, which was fixed in 1.92.6.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
@@ -269,7 +294,7 @@ Example Setup:
|
||||
// Merge icons into default tool font
|
||||
#include "IconsFontAwesome.h"
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
io.Fonts->AddFontDefaultVector();
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
|
||||
@@ -426,7 +451,7 @@ As an alternative to rendering colorful glyphs using imgui_freetype with `ImGuiF
|
||||
#### Pseudo-code:
|
||||
```cpp
|
||||
// Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font
|
||||
ImFont* font = io.Fonts->AddFontDefault();
|
||||
ImFont* font = io.Fonts->AddFontDefaultVector();
|
||||
int rect_ids[2];
|
||||
rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1);
|
||||
rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
|
||||
@@ -439,7 +464,7 @@ unsigned char* tex_pixels = nullptr;
|
||||
int tex_width, tex_height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
|
||||
|
||||
for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
|
||||
for (int rect_n = 0; rect_n < IM_COUNTOF(rect_ids); rect_n++)
|
||||
if (const ImTextureRect* rect = io.Fonts->GetCustomRect(rect_ids[rect_n]))
|
||||
{
|
||||
// Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
|
||||
@@ -539,7 +564,20 @@ You can use the `UTF-8 Encoding viewer` in `Metrics/Debugger` to verify the cont
|
||||
|
||||
## Credits/Licenses For Fonts Included In Repository
|
||||
|
||||
Some fonts files are available in the `misc/fonts/` folder:
|
||||
Embedded in source code:
|
||||
|
||||
**ProggyClean.ttf**, by Tristan Grimmer
|
||||
<br>MIT License
|
||||
<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1, PixelSnapH = true)
|
||||
<br>https://github.com/bluescan/proggyfonts
|
||||
|
||||
**ProggyForever.ttf**, by Disco Hello, Tristan Grimmer
|
||||
<BR>MIT License
|
||||
<BR>https://github.com/ocornut/proggyforever
|
||||
|
||||
Extra fonts files are available in the `misc/fonts/` folder.
|
||||
Compared to 2014 when they were first introduced, we now have better font support and we embed ProggyForever.
|
||||
I believe all the files here are unnecessary nowadays. You can find font yourself. They might eventually be removed.
|
||||
|
||||
**Roboto-Medium.ttf**, by Christian Robetson
|
||||
<br>Apache License 2.0
|
||||
@@ -554,15 +592,10 @@ Some fonts files are available in the `misc/fonts/` folder:
|
||||
<br>Apache License 2.0
|
||||
<br>https://www.fontsquirrel.com/fonts/droid-sans
|
||||
|
||||
**ProggyClean.ttf**, by Tristan Grimmer
|
||||
<br>MIT License
|
||||
<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1)
|
||||
<br>http://www.proggyfonts.net/
|
||||
|
||||
**ProggyTiny.ttf**, by Tristan Grimmer
|
||||
<br>MIT License
|
||||
<br>(recommended loading setting: Size = 10.0, GlyphOffset.y = +1)
|
||||
<br>http://www.proggyfonts.net/
|
||||
<br>https://github.com/bluescan/proggyfonts
|
||||
|
||||
**Karla-Regular.ttf**, by Jonathan Pinhorn
|
||||
<br>SIL OPEN FONT LICENSE Version 1.1
|
||||
@@ -588,15 +621,14 @@ Some fonts files are available in the `misc/fonts/` folder:
|
||||
|
||||
#### MONOSPACE FONTS
|
||||
|
||||
Pixel Perfect:
|
||||
- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
|
||||
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font (also include an .inl file to use directly in dear imgui.)
|
||||
<img width="1172" height="715" alt="image" src="https://github.com/user-attachments/assets/c9702534-4877-41c9-ae0d-252933c26ced" />
|
||||
|
||||
Regular:
|
||||
- Google Noto Mono Fonts https://www.google.com/get/noto/
|
||||
- Typefaces for source code beautification https://github.com/chrissimpkins/codeface
|
||||
- Programmation fonts http://s9w.github.io/font_compare/
|
||||
- Inconsolata http://www.levien.com/type/myfonts/inconsolata.html
|
||||
- Proggy Fonts, by Tristan Grimmer https://github.com/bluescan/proggyfonts
|
||||
- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font
|
||||
- Google Noto Mono Fonts: https://www.google.com/get/noto/
|
||||
- Typefaces for source code beautification: https://github.com/chrissimpkins/codeface
|
||||
- Programmation fonts: http://s9w.github.io/font_compare/
|
||||
- Inconsolata: http://www.levien.com/type/myfonts/inconsolata.html
|
||||
- Adobe Source Code Pro: Monospaced font family for ui & coding environments https://github.com/adobe-fonts/source-code-pro
|
||||
- Monospace/Fixed Width Programmer's Fonts http://www.lowing.org/fonts/
|
||||
|
||||
|
||||
@@ -39,10 +39,12 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
|
||||
|
||||
### Usage
|
||||
|
||||
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h). **No specific build process is required**. You can add the .cpp files into your existing project.
|
||||
**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (`imgui*.cpp`, `imgui*.h`). **No specific build process is required**: you can add all files into your existing project.
|
||||
|
||||
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
|
||||
|
||||
C++20 users wishing to use a module may the use [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
|
||||
|
||||
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
|
||||
|
||||
After Dear ImGui is set up in your application, you can use it from \_anywhere\_ in your program loop:
|
||||
@@ -50,11 +52,11 @@ After Dear ImGui is set up in your application, you can use it from \_anywhere\_
|
||||
ImGui::Text("Hello, world %d", 123);
|
||||
if (ImGui::Button("Save"))
|
||||
MySaveFunction();
|
||||
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::InputText("string", buf, IM_COUNTOF(buf));
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
```
|
||||

|
||||

|
||||
<img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" />
|
||||
<img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" />
|
||||
|
||||
```cpp
|
||||
// Create a window called "My First Tool", with a menu bar.
|
||||
@@ -88,7 +90,7 @@ for (int n = 0; n < 50; n++)
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
```
|
||||

|
||||

|
||||
|
||||
Dear ImGui allows you to **create elaborate tools** as well as very short-lived ones. On the extreme side of short-livedness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweak variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game-making editor/framework, etc.
|
||||
|
||||
@@ -107,35 +109,11 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG
|
||||
|
||||
### Demo
|
||||
|
||||
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. [Here's how the demo looks](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
|
||||
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
|
||||
- [imgui_explorer](https://pthom.github.io/imgui_explorer): Web version of the demo w/ source code browser, courtesy of [@pthom](https://github.com/pthom).
|
||||
|
||||
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
|
||||
- [imgui-demo-binaries-20250625.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20250625.zip) (Windows, 1.92.0, built 2025/06/25, master) or [older binaries](https://www.dearimgui.com/binaries).
|
||||
|
||||
The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)).
|
||||
|
||||
### Getting Started & Integration
|
||||
|
||||
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details.
|
||||
|
||||
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
|
||||
|
||||
Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles, which is essentially what Backends are doing. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that: setting up a window and using backends. If you follow the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide it should in theory take you less than an hour to integrate Dear ImGui. **Make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
|
||||
|
||||
Officially maintained backends/bindings (in repository):
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
||||
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
|
||||
- Frameworks: Allegro5, Emscripten.
|
||||
|
||||
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
|
||||
- Languages: C, C# and: Beef, ChaiScript, CovScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Nim, Odin, Pascal, PureBasic, Python, ReaScript, Ruby, Rust, Swift, Zig...
|
||||
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
|
||||
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or newer/experimental [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
|
||||
|
||||
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
||||
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
||||
|
||||
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
||||
- [imgui-demo-binaries-20260225.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20260225.zip) (Windows, 1.92.6, built 2026/02/25, master) or [older binaries](https://www.dearimgui.com/binaries).
|
||||
|
||||
### Gallery
|
||||
|
||||
@@ -150,6 +128,35 @@ For a list of third-party widgets and extensions, check out the [Useful Extensio
|
||||
| Custom engine [erhe](https://github.com/tksuoran/erhe) (docking branch)<BR>[](https://user-images.githubusercontent.com/994606/147875067-a848991e-2ad2-4fd3-bf71-4aeb8a547bcf.png) | Custom engine for [Wonder Boy: The Dragon's Trap](http://www.TheDragonsTrap.com) (2017)<BR>[](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) |
|
||||
| Custom engine (untitled)<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) | Tracy Profiler ([github](https://github.com/wolfpld/tracy))<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v176/tracy_profiler.png) |
|
||||
|
||||
### Getting Started & Integration
|
||||
|
||||
See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details.
|
||||
|
||||
On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more imgui_impl_xxxx files instead of rewriting them: this will be less work for you, and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
|
||||
|
||||
Integrating Dear ImGui within your custom engine is a matter of mainly 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can create/update textures and render textured triangles. This is exactly what backends are doing.
|
||||
- The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications setting up a window and using standard backends.
|
||||
- The [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide has instructions to integrate imgui into an existing application using standard backends. It should in theory take you less than an hour to integrate Dear ImGui into your existing codebase where support libraries are linked. Less if you read carefully.
|
||||
- The [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md) guide explains what backends are doing, and has instructions to implement a custom backend. You can also refer to the source code of our ~20 backends to understand how they work.
|
||||
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
|
||||
|
||||
Officially maintained backends (in repository):
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
||||
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
|
||||
- Frameworks: Allegro5, Emscripten.
|
||||
|
||||
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
|
||||
- Languages: C, C# and: Beef, ChaiScript, CovScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Nim, Odin, Pascal, PureBasic, Python, ReaScript, Ruby, Rust, Swift, Zig...
|
||||
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Defold, Diligent Engine, Ebiten, Flexium, GML/Game Maker Studio, GLEQ, Godot, GTK3, Irrlicht Engine, JUCE, LÖVE+LUA, Mach Engine, Magnum, Marmalade, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS/Switch/WiiU (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, raylib, SFML, Sokol, Unity, Unreal Engine 4/5, UWP, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
|
||||
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
|
||||
|
||||
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
||||
|
||||
[](https://github.com/ocornut/imgui/wiki/Useful-Extensions)
|
||||
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot), [ImPlot3d](https://github.com/brenocq/implot3d) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
||||
|
||||
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
||||
|
||||
### Support, Frequently Asked Questions (FAQ)
|
||||
|
||||
See: [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) where common questions are answered.
|
||||
@@ -203,7 +210,7 @@ Dear ImGui is using software and services provided free of charge for open sourc
|
||||
Credits
|
||||
-------
|
||||
|
||||
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://tearaway.mediamolecule.com) (PS Vita).
|
||||
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://youtu.be/w0oxBviRGlU) (PS Vita).
|
||||
|
||||
Recurring contributors include Rokas Kupstys [@rokups](https://github.com/rokups) (2020-2022): a good portion of work on automation system and regression tests now available in [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
||||
|
||||
@@ -211,7 +218,8 @@ Maintenance/support contracts, sponsoring invoices and other B2B transactions ar
|
||||
|
||||
Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
|
||||
|
||||
Embeds [ProggyClean.ttf](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
|
||||
Embeds [ProggyClean](https://www.proggyfonts.net) font by Tristan Grimmer (MIT license).
|
||||
<br>Embeds [ProggyForever](https://github.com/ocornut/proggyforever) fonts by Disco Hello, Tristan Grimmer (MIT license).
|
||||
<br>Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).
|
||||
|
||||
Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Special thanks to Alex Evans, Patrick Doane, Marco Koegler for kindly helping. Also thank you to everyone posting feedback, questions and patches on GitHub.
|
||||
|
||||
@@ -2,12 +2,14 @@ dear imgui
|
||||
ISSUES & TODO LIST
|
||||
|
||||
Issue numbers (#) refer to GitHub issues listed at https://github.com/ocornut/imgui/issues/XXXX
|
||||
|
||||
THIS LIST IS NOT WELL MAINTAINED. MOST OF THE WORK HAPPENS ON GITHUB NOWADAYS.
|
||||
|
||||
The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point they usually exist on the github issue tracker).
|
||||
It's mostly a bunch of personal notes, probably incomplete. Feel free to query if you have any questions.
|
||||
|
||||
- doc: add a proper documentation system (maybe relying on automation? #435)
|
||||
- doc: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.).
|
||||
- doc: add a proper documentation system (maybe relying on automation? #435)
|
||||
- doc/tips: tips of the day: website? applet in imgui_club?
|
||||
|
||||
- window: preserve/restore relative focus ordering (persistent or not), and e.g. of multiple reappearing windows (#2304) -> also see docking reference to same #.
|
||||
@@ -29,9 +31,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero.
|
||||
- window/tabbing: add a way to signify that a window or docked window requires attention (e.g. blinking title bar, trying to click behind a modal).
|
||||
- window/id_stack: add e.g. window->GetIDFromPath() with support for leading / and ../ (#1390, #331) -> model from test engine.
|
||||
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose lots of issues (#2424, #1463)
|
||||
|
||||
! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose various issues (#2424, #1463)
|
||||
- scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse)
|
||||
- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet.
|
||||
- scrolling: forward mouse wheel scrolling to parent window when at the edge of scrolling limits? (useful for listbox,tables?)
|
||||
- scrolling/style: shadows on scrollable areas to denote that there is more contents (see e.g. DaVinci Resolve ui)
|
||||
|
||||
@@ -51,43 +53,36 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395)
|
||||
- widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h.
|
||||
- widgets: add always-allow-overlap mode. This should perhaps be the default? one problem is that highlight after mouse-wheel scrolling gets deferred, makes scrolling more flickery.
|
||||
- widgets: start exposing PushItemFlag() and ImGuiItemFlags
|
||||
- widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
|
||||
- widgets: activate by identifier (trigger button, focus given id)
|
||||
- widgets: custom glyph/shapes replacements for stock shapes. (also #6090 #2431 #2235 #6517)
|
||||
- widgets: coloredit: keep reporting as active when picker is on?
|
||||
- widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
|
||||
- widgets: group/ScalarN functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
|
||||
- selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
|
||||
- selectable: generic BeginSelectable()/EndSelectable() mechanism. (work out alongside range-select branch)
|
||||
- selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
|
||||
|
||||
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
|
||||
- input text: preserve scrolling when unfocused?
|
||||
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
|
||||
- input text: expose CursorPos in char filter event (#816)
|
||||
- input text: try usage idiom of using InputText with data only exposed through get/set accessors, without extraneous copy/alloc. (#3009)
|
||||
- input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return nullptr if not active (available in internals)
|
||||
- input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
|
||||
- input text: hover tooltip could show unclamped text
|
||||
- input text: support for INSERT key to toggle overwrite mode. currently disabled because stb_textedit behavior is unsatisfactory on multi-line. (#2863)
|
||||
- input text: option to Tab after an Enter validation.
|
||||
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
|
||||
- input text: easier ways to update buffer (from source char*) while owned. preserve some sort of cursor position for multi-line text.
|
||||
- input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725)
|
||||
- input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependent). actually a very old bug but no one appears to have noticed it.
|
||||
- input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
|
||||
- input text: decorrelate display layout from inputs with custom template - e.g. what's the easiest way to implement a nice IP/Mac address input editor?
|
||||
- input text: global callback system so user can plug in an expression evaluator easily. (#1691)
|
||||
- input text: callback system (global) so user can plug in an expression evaluator easily. (#1691)
|
||||
- input text: force scroll to end or scroll to a given line/contents (so user can implement a log or a search feature)
|
||||
- input text: a way to preview completion (e.g. disabled text completing from the cursor)
|
||||
- input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there.
|
||||
- input text: a way for the user to provide syntax coloring.
|
||||
- input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count.
|
||||
- input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
|
||||
- input text multi-line: support for copy/cut without selection (copy/cut current line?)
|
||||
- input text multi-line: line numbers? status bar? (follow up on #200)
|
||||
- input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725)
|
||||
- input text multi-line: better horizontal scrolling support (#383, #1224)
|
||||
- input text multi-line: single call to AddText() should be coarse clipped on InputTextEx() end.
|
||||
- input number: optional range min/max for Input*() functions
|
||||
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
|
||||
- input number: use mouse wheel to step up/down
|
||||
@@ -112,11 +107,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
!- color: the color conversion helpers/types are a mess and needs sorting out.
|
||||
- color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
|
||||
|
||||
- plot: full featured plot/graph api w/ scrolling, zooming etc. --> promote using ImPlot
|
||||
- (plot: deleted all other todo lines on 2023-06-28)
|
||||
|
||||
- clipper: ability to disable the clipping through a simple flag/bool.
|
||||
- clipper: ability to run without knowing full count in advance.
|
||||
- clipper: horizontal clipping support. (#2580)
|
||||
|
||||
- separator: expose flags (#759)
|
||||
@@ -142,22 +133,19 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- knob: rotating knob widget (#942)
|
||||
- drag float: support for reversed drags (min > max) (removed is_locked, also see fdc526e)
|
||||
- drag float: up/down axis
|
||||
- drag float: power != 0.0f with current value being outside the range keeps the value stuck.
|
||||
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
|
||||
|
||||
- combo: a way/helper to customize the combo preview (#1658) -> experimental BeginComboPreview()
|
||||
- combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
|
||||
- listbox: multiple selection (WIP range-select branch)
|
||||
- listbox: unselect option (#1208)
|
||||
- listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (WIP range-select branch)
|
||||
- listbox: user may want to initial scroll to focus on the one selected value?
|
||||
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
|
||||
- listbox: scrolling should track modified selection.
|
||||
- listbox: future api should allow to enable horizontal scrolling (#2510)
|
||||
|
||||
!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
|
||||
- modals: make modal title bar blink when trying to click outside the modal
|
||||
- modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups.
|
||||
- modals: make modal title bar blink when trying to click outside the modal.
|
||||
- modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups. (#402)
|
||||
- popups: if the popup functions took explicit ImGuiID it would allow the user to manage the scope of those ID. (#331)
|
||||
- popups: clicking outside (to close popup) and holding shouldn't drag window below.
|
||||
- popups: add variant using global identifier similar to Begin/End (#402)
|
||||
@@ -199,7 +187,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- style: FramePadding could be different for up vs down (#584)
|
||||
- style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
|
||||
- style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
|
||||
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
|
||||
- style: gradients fill (#4722, #1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
|
||||
- style editor: color child window height expressed in multiple of line height.
|
||||
|
||||
- log: improve logging of ArrowButton, ListBox, TabItem
|
||||
@@ -215,7 +203,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
|
||||
|
||||
- drag and drop: focus drag target window on hold (even without open)
|
||||
- drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725)
|
||||
- drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233
|
||||
- drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. (see 2018/01/11 post in #143)
|
||||
- drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725)
|
||||
@@ -248,7 +235,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- font: make it easier to submit own bitmap font (same texture, another texture?). (#2127, #2575)
|
||||
- font: MemoryTTF taking ownership confusing/not obvious, maybe default should be opposite?
|
||||
- font: storing MinAdvanceX per font would allow us to skip calculating line width (under a threshold of character count) in loops looking for block width
|
||||
- font/demo: demonstrate use of ImFontGlyphRangesBuilder.
|
||||
- font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
|
||||
- font/draw: need to be able to specify wrap start position.
|
||||
- font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines). also see #3349.
|
||||
@@ -274,12 +260,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- nav: NavFlattened: ESC on a flattened child should select something.
|
||||
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
|
||||
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
|
||||
- nav: simulate right-click or context activation? (SHIFT+F10, keyboard Menu key?)
|
||||
- nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
|
||||
- nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
|
||||
- nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.
|
||||
- nav/menus: allow pressing Menu to leave a sub-menu.
|
||||
- nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
|
||||
! nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
|
||||
- nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it?
|
||||
- nav/menus: main menu bar currently cannot restore a nullptr focus. Could save NavWindow at the time of being focused, similarly to what popup do?
|
||||
- nav/menus: Alt,Up could open the first menu (e.g. "File") currently it tends to nav into the window/collapse menu. Do do that we would need custom transition?
|
||||
@@ -298,7 +283,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- misc: no way to run a root-most GetID() with ImGui:: api since there's always a Debug window in the stack. (mentioned in #2960)
|
||||
- misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
|
||||
- misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682)
|
||||
- misc: use more size_t in public api?
|
||||
- misc: support for string view/range instead of char* would e.g. facilitate usage with Rust (#683, #3038, WIP string_view branch)
|
||||
|
||||
- demo: demonstrate using PushStyleVar() in more details.
|
||||
@@ -309,15 +293,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
|
||||
- examples: window minimize, maximize (#583)
|
||||
- examples: provide a zero frame-rate/idle example.
|
||||
- examples: dx11/dx12: try to use new swapchain blit models (#2970)
|
||||
- examples: dx11/dx12: try to use new swapchain blit models (#2970, #9031)
|
||||
- backends: report it better when not able to create texture?
|
||||
- backends: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
|
||||
- backends: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)
|
||||
- backends: opengl: could use a single vertex buffer and glBufferSubData for uploads?
|
||||
- backends: opengl: explicitly disable GL_STENCIL_TEST in bindings.
|
||||
- backends: vulkan: viewport: support for synchronized swapping of multiple swap chains.
|
||||
- backends: bgfx: https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0
|
||||
- backends: emscripten: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
|
||||
- backends: emscripten: dedicated backend? (#8178, #9120, eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
|
||||
|
||||
- bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h) (--> use https://github.com/dearimgui/dear_bindings)
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
See BACKENDS and EXAMPLES files in the docs/ folder, or on the web at: https://github.com/ocornut/imgui/tree/master/docs
|
||||
New to Dear ImGui?
|
||||
- Check out the Getting Started guide: https://github.com/ocornut/imgui/wiki/Getting-Started
|
||||
- About Backends: docs/BACKENDS.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md
|
||||
- About Examples: docs/EXAMPLES.md file, or on the web: https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md
|
||||
|
||||
Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app).
|
||||
Examples = Standalone applications showcasing integration with platforms/graphics api.
|
||||
|
||||
Some Examples have extra README files in their respective directory, please check them too!
|
||||
A few Examples have extra README files in their respective directory, please check them too!
|
||||
|
||||
Once Dear ImGui is running (in either examples or your own application/game/engine),
|
||||
run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API.
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -28,7 +28,7 @@ int main(int, char**)
|
||||
al_install_mouse();
|
||||
al_init_primitives_addon();
|
||||
al_set_new_display_flags(ALLEGRO_RESIZABLE);
|
||||
ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
|
||||
ALLEGRO_DISPLAY* display = al_create_display(1280, 800);
|
||||
al_set_window_title(display, "Dear ImGui Allegro 5 example");
|
||||
ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
|
||||
al_register_event_source(queue, al_get_display_event_source(display));
|
||||
@@ -49,14 +49,16 @@ int main(int, char**)
|
||||
ImGui_ImplAllegro5_Init(display);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
.cxx
|
||||
.externalNativeBuild
|
||||
build/
|
||||
*.iml
|
||||
|
||||
.idea
|
||||
.gradle
|
||||
.idea
|
||||
.DS_Store
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
# Android Studio puts a Gradle wrapper here, that we don't want:
|
||||
gradle/
|
||||
!gradle/libs.versions.toml
|
||||
gradlew*
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "33.0.2"
|
||||
ndkVersion "25.2.9519653"
|
||||
namespace 'imgui.example.android'
|
||||
compileSdk 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId "imgui.example.android"
|
||||
namespace "imgui.example.android"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 33
|
||||
minSdk 24
|
||||
targetSdk 36
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
@@ -21,26 +21,17 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget="11"
|
||||
jvmTarget = '11'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "../../CMakeLists.txt"
|
||||
path file('../../CMakeLists.txt')
|
||||
version '3.22.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:label="ImGuiExample"
|
||||
|
||||
@@ -1,24 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.8.0'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[versions]
|
||||
agp = "8.12.0"
|
||||
kotlin = "2.0.21"
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
|
||||
@@ -1 +1,22 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
include ':app'
|
||||
|
||||
@@ -151,42 +151,45 @@ void Init(struct android_app* app)
|
||||
ImGui_ImplAndroid_Init(g_App->window);
|
||||
ImGui_ImplOpenGL3_Init("#version 300 es");
|
||||
|
||||
// Setup scaling
|
||||
float main_scale = 2.0f;
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale.
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Android: The TTF files have to be placed into the assets/ directory (android/app/src/main/assets), we use our GetAssetData() helper to retrieve them.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
|
||||
// We load the default font with increased size to improve readability on many devices with "high" DPI.
|
||||
// FIXME: Put some effort into DPI awareness.
|
||||
// Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transferred by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
|
||||
ImFontConfig font_cfg;
|
||||
font_cfg.SizePixels = 22.0f;
|
||||
io.Fonts->AddFontDefault(&font_cfg);
|
||||
//void* font_data;
|
||||
//int font_data_size;
|
||||
//void* font_data;
|
||||
//int font_data_size;
|
||||
//ImFont* font;
|
||||
//font_data_size = GetAssetData("segoeui.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("DroidSans.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 15.0f);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
//font_data_size = GetAssetData("ArialUni.ttf", &font_data);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 18.0f);
|
||||
//font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size);
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Arbitrary scale-up
|
||||
// FIXME: Put some effort into DPI awareness
|
||||
ImGui::GetStyle().ScaleAllSizes(3.0f);
|
||||
|
||||
g_Initialized = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,14 +69,16 @@
|
||||
ImGui_ImplMetal_Init(_device);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
@@ -94,7 +96,7 @@
|
||||
|
||||
-(void)loadView
|
||||
{
|
||||
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)];
|
||||
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 800)];
|
||||
}
|
||||
|
||||
-(void)viewDidLoad
|
||||
|
||||
@@ -57,14 +57,16 @@
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
@@ -169,9 +171,9 @@
|
||||
-(NSWindow*)window
|
||||
{
|
||||
if (_window != nil)
|
||||
return (_window);
|
||||
return _window;
|
||||
|
||||
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 720.0);
|
||||
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 800.0);
|
||||
|
||||
_window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES];
|
||||
[_window setTitle:@"Dear ImGui OSX+OpenGL2 Example"];
|
||||
@@ -179,7 +181,7 @@
|
||||
[_window setOpaque:YES];
|
||||
[_window makeKeyAndOrderFront:NSApp];
|
||||
|
||||
return (_window);
|
||||
return _window;
|
||||
}
|
||||
|
||||
-(void)setupMenu
|
||||
|
||||
@@ -27,44 +27,33 @@ static void glfw_error_callback(int error, const char* description)
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Setup window
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
// Create window with graphics context
|
||||
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Metal example", nullptr, nullptr);
|
||||
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+Metal example", nullptr, nullptr);
|
||||
if (window == nullptr)
|
||||
return 1;
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
id <MTLDevice> device = MTLCreateSystemDefaultDevice();
|
||||
id <MTLCommandQueue> commandQueue = [device newCommandQueue];
|
||||
|
||||
@@ -72,6 +61,24 @@ int main(int, char**)
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplMetal_Init(device);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
NSWindow *nswin = glfwGetCocoaWindow(window);
|
||||
CAMetalLayer *layer = [CAMetalLayer layer];
|
||||
layer.device = device;
|
||||
|
||||
@@ -21,6 +21,7 @@ SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
LINUX_GL_LIBS = -lGL
|
||||
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
@@ -32,7 +33,7 @@ LIBS =
|
||||
|
||||
ifeq ($(UNAME_S), Linux) #LINUX
|
||||
ECHO_MESSAGE = "Linux"
|
||||
LIBS += -lGL `pkg-config --static --libs glfw3`
|
||||
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
|
||||
|
||||
CXXFLAGS += `pkg-config --cflags glfw3`
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -40,7 +40,8 @@ int main(int, char**)
|
||||
return 1;
|
||||
|
||||
// Create window with graphics context
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example", nullptr, nullptr);
|
||||
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+OpenGL2 example", nullptr, nullptr);
|
||||
if (window == nullptr)
|
||||
return 1;
|
||||
glfwMakeContextCurrent(window);
|
||||
@@ -57,19 +58,26 @@ int main(int, char**)
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -92,7 +92,7 @@ int main(int, char**)
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
@@ -102,15 +102,17 @@ int main(int, char**)
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -193,7 +193,8 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
@@ -201,7 +202,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
pool_info.maxSets = 0;
|
||||
for (VkDescriptorPoolSize& pool_size : pool_sizes)
|
||||
pool_info.maxSets += pool_size.descriptorCount;
|
||||
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
|
||||
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||
check_vk_result(err);
|
||||
@@ -212,11 +213,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
// Your real engine/app may not use them.
|
||||
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
|
||||
{
|
||||
wd->Surface = surface;
|
||||
|
||||
// Check for WSI support
|
||||
VkBool32 res;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
|
||||
if (res != VK_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||
@@ -226,7 +225,8 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
|
||||
// Select Surface Format
|
||||
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
wd->Surface = surface;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
|
||||
// Select Present Mode
|
||||
#ifdef APP_USE_UNLIMITED_FRAME_RATE
|
||||
@@ -234,12 +234,12 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
|
||||
#else
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
|
||||
#endif
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// Create SwapChain, RenderPass, Framebuffer, etc.
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
@@ -256,9 +256,10 @@ static void CleanupVulkan()
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void CleanupVulkanWindow()
|
||||
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
|
||||
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
@@ -357,7 +358,8 @@ int main(int, char**)
|
||||
|
||||
// Create window with Vulkan context
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Vulkan example", nullptr, nullptr);
|
||||
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||
GLFWwindow* window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "Dear ImGui GLFW+Vulkan example", nullptr, nullptr);
|
||||
if (!glfwVulkanSupported())
|
||||
{
|
||||
printf("GLFW: Vulkan Not Supported\n");
|
||||
@@ -393,6 +395,11 @@ int main(int, char**)
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForVulkan(window, true);
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
@@ -404,24 +411,26 @@ int main(int, char**)
|
||||
init_info.Queue = g_Queue;
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.RenderPass = wd->RenderPass;
|
||||
init_info.Subpass = 0;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
|
||||
init_info.PipelineInfoMain.Subpass = 0;
|
||||
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
@@ -450,7 +459,7 @@ int main(int, char**)
|
||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||
{
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
g_SwapChainRebuild = false;
|
||||
}
|
||||
@@ -524,7 +533,7 @@ int main(int, char**)
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow();
|
||||
CleanupVulkanWindow(&g_MainWindowData);
|
||||
CleanupVulkan();
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
# Building for desktop (WebGPU-native) with Dawn:
|
||||
# Building for desktop with Dawn:
|
||||
# 1. git clone https://github.com/google/dawn dawn
|
||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/Debug/example_glfw_wgpu[.exe]
|
||||
# * build/example_glfw_wgpu[.exe]
|
||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGPU-Native:
|
||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||
# 2. unzip the downloaded file in your_preferred_folder
|
||||
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
||||
# 4. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGVK (MUCH EASIER)
|
||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||
|
||||
# Building for Emscripten:
|
||||
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||
# 2. Install Ninja build system
|
||||
# 3. emcmake cmake -G Ninja -B build
|
||||
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
|
||||
# 3. cmake --build build
|
||||
# 4. emrun build/index.html
|
||||
|
||||
cmake_minimum_required(VERSION 3.10.2)
|
||||
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
|
||||
project(imgui_example_glfw_wgpu C CXX)
|
||||
|
||||
set(IMGUI_EXECUTABLE example_glfw_wgpu)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
||||
@@ -25,93 +42,182 @@ set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
||||
# Dear ImGui
|
||||
set(IMGUI_DIR ../../)
|
||||
|
||||
# Libraries
|
||||
set(IMGUI_EXAMPLE_SOURCE_FILES
|
||||
# Example code
|
||||
main.cpp
|
||||
# Dear ImGui Backend files
|
||||
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
|
||||
# Dear ImGui files
|
||||
${IMGUI_DIR}/imgui.cpp
|
||||
${IMGUI_DIR}/imgui_draw.cpp
|
||||
${IMGUI_DIR}/imgui_demo.cpp
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
)
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
|
||||
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
||||
else()
|
||||
# cannot use contrib.glfw3 prior to 3.1.57
|
||||
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
|
||||
endif()
|
||||
set(LIBRARIES glfw)
|
||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Default to --use-port=emdawnwebgpu. You can override to provide your own local port.")
|
||||
else()
|
||||
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
||||
endif()
|
||||
|
||||
if(NOT IMGUI_EMSCRIPTEN_GLFW3)
|
||||
# Defaults to contrib.glfw3 because Emscripten version is > 3.1.57
|
||||
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
||||
endif()
|
||||
|
||||
set(LIBRARIES glfw)
|
||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||
else() # Native/Desktop build
|
||||
|
||||
# Check DAWN/WGPU/WGVK directory
|
||||
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
|
||||
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
|
||||
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||
endif()
|
||||
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
|
||||
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||
endif()
|
||||
|
||||
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
||||
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
|
||||
endif()
|
||||
|
||||
find_package(glfw3 REQUIRED)
|
||||
|
||||
if(IMGUI_DAWN_DIR)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
||||
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
||||
if(Dawn_FOUND)
|
||||
message("Dawn Installation has been found!")
|
||||
set(LIBRARIES dawn::webgpu_dawn glfw ${OS_LIBRARIES})
|
||||
else()
|
||||
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
|
||||
|
||||
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
|
||||
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
|
||||
|
||||
option(DAWN_USE_GLFW OFF) # disable builtin GLFW in DAWN when we use SDL2 / SDL3
|
||||
|
||||
# Dawn builds many things by default - disable things we don't need
|
||||
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
|
||||
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
|
||||
option(TINT_BUILD_DOCS "Build documentation" OFF)
|
||||
option(TINT_BUILD_TESTS "Build tests" OFF)
|
||||
if(NOT APPLE)
|
||||
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
|
||||
endif()
|
||||
if(WIN32)
|
||||
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
|
||||
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
|
||||
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
|
||||
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
|
||||
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
|
||||
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
|
||||
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
|
||||
endif()
|
||||
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
|
||||
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
|
||||
if(LINUX)
|
||||
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
|
||||
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
|
||||
|
||||
set(LIBRARIES webgpu_dawn glfw)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(IMGUI_WGPU_DIR)
|
||||
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
||||
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
||||
if(WIN32)
|
||||
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(OS_LIBRARIES "-lm -ldl")
|
||||
endif()
|
||||
|
||||
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(IMGUI_WGVK_DIR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
||||
|
||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_DIR}/backends
|
||||
)
|
||||
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_GLFW_WGPU")
|
||||
|
||||
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
|
||||
if (MSVC)
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
|
||||
else()
|
||||
# Dawn wgpu desktop
|
||||
set(DAWN_FETCH_DEPENDENCIES ON)
|
||||
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
|
||||
if (NOT IMGUI_DAWN_DIR)
|
||||
message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR")
|
||||
endif()
|
||||
|
||||
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
|
||||
|
||||
# Dawn builds many things by default - disable things we don't need
|
||||
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
|
||||
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
|
||||
option(TINT_BUILD_DOCS "Build documentation" OFF)
|
||||
option(TINT_BUILD_TESTS "Build tests" OFF)
|
||||
if (NOT APPLE)
|
||||
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
|
||||
endif()
|
||||
if(WIN32)
|
||||
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
|
||||
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
|
||||
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
|
||||
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
|
||||
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" OFF)
|
||||
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
|
||||
endif()
|
||||
|
||||
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
|
||||
|
||||
set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw)
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
|
||||
endif()
|
||||
|
||||
add_executable(example_glfw_wgpu
|
||||
main.cpp
|
||||
# backend files
|
||||
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
|
||||
# Dear ImGui files
|
||||
${IMGUI_DIR}/imgui.cpp
|
||||
${IMGUI_DIR}/imgui_draw.cpp
|
||||
${IMGUI_DIR}/imgui_demo.cpp
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
)
|
||||
IF(NOT EMSCRIPTEN)
|
||||
target_compile_definitions(example_glfw_wgpu PUBLIC
|
||||
"IMGUI_IMPL_WEBGPU_BACKEND_DAWN"
|
||||
)
|
||||
endif()
|
||||
target_include_directories(example_glfw_wgpu PUBLIC
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_DIR}/backends
|
||||
)
|
||||
# In this example IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU internal define is set according to:
|
||||
# EMSCRIPTEN: by used FLAG
|
||||
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
||||
# NATIVE: by used SDK installation directory
|
||||
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
||||
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
|
||||
|
||||
target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES})
|
||||
if(NOT EMSCRIPTEN) # WegGPU-Native settings
|
||||
# Set IMGUI_IMPL_WEBGPU_BACKEND_XXXX based on the SDK (directory) used
|
||||
if(IMGUI_DAWN_DIR)
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||
if(NOT Dawn_FOUND)
|
||||
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
||||
endif()
|
||||
endif()
|
||||
if(IMGUI_WGPU_DIR)
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
||||
endif()
|
||||
if(IMGUI_WGVK_DIR)
|
||||
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
|
||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
|
||||
if (MSVC)
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Emscripten settings
|
||||
if(EMSCRIPTEN)
|
||||
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
|
||||
target_compile_options(example_glfw_wgpu PUBLIC
|
||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
||||
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES})
|
||||
|
||||
else() # Emscripten settings
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||
|
||||
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_GLFW3}")
|
||||
endif()
|
||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
||||
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
||||
|
||||
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
|
||||
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
|
||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
||||
"-sWASM=1"
|
||||
"-sASYNCIFY=1"
|
||||
"-sALLOW_MEMORY_GROWTH=1"
|
||||
"-sNO_EXIT_RUNTIME=0"
|
||||
"-sASSERTIONS=1"
|
||||
"-sDISABLE_EXCEPTION_CATCHING=1"
|
||||
"-sNO_FILESYSTEM=1"
|
||||
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
|
||||
)
|
||||
endif()
|
||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
||||
target_link_options(example_glfw_wgpu PRIVATE
|
||||
"-sUSE_WEBGPU=1"
|
||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
||||
"-sWASM=1"
|
||||
"-sALLOW_MEMORY_GROWTH=1"
|
||||
"-sNO_EXIT_RUNTIME=0"
|
||||
"-sASSERTIONS=1"
|
||||
"-sDISABLE_EXCEPTION_CATCHING=1"
|
||||
"-sNO_FILESYSTEM=1"
|
||||
)
|
||||
set_target_properties(example_glfw_wgpu PROPERTIES OUTPUT_NAME "index")
|
||||
# copy our custom index.html to build directory
|
||||
add_custom_command(TARGET example_glfw_wgpu POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $<TARGET_FILE_DIR:example_glfw_wgpu>
|
||||
)
|
||||
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
|
||||
endif()
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
# This Makefile assumes you have loaded emscripten's environment.
|
||||
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
|
||||
#
|
||||
# Running `make` will produce three files:
|
||||
# - web/index.html (current stored in the repository)
|
||||
# Running `make -f Makefile.emscripten` will produce three files:
|
||||
# - web/index.html
|
||||
# - web/index.js
|
||||
# - web/index.wasm
|
||||
#
|
||||
@@ -16,11 +16,11 @@
|
||||
CC = emcc
|
||||
CXX = em++
|
||||
WEB_DIR = web
|
||||
EXE = $(WEB_DIR)/index.js
|
||||
EXE = $(WEB_DIR)/index.html
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.cpp
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
CPPFLAGS =
|
||||
@@ -34,8 +34,15 @@ EMS =
|
||||
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
||||
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
|
||||
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
|
||||
LDFLAGS += -s USE_WEBGPU=1
|
||||
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
|
||||
LDFLAGS += -s WASM=1
|
||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||
LDFLAGS += -s ASYNCIFY=1
|
||||
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
||||
LDFLAGS += -s ASSERTIONS=1
|
||||
|
||||
# Using Dawn-based WebGPU port (requires Emscripten >= 4.0.10)
|
||||
EMS += --use-port=emdawnwebgpu
|
||||
LDFLAGS += --use-port=emdawnwebgpu
|
||||
|
||||
# Build as single file (binary text encoded in .html file)
|
||||
#LDFLAGS += -sSINGLE_FILE
|
||||
@@ -60,7 +67,7 @@ endif
|
||||
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
#CPPFLAGS += -g
|
||||
CPPFLAGS += -Wall -Wformat -Os $(EMS)
|
||||
#LDFLAGS += --shell-file shell_minimal.html
|
||||
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
|
||||
LDFLAGS += $(EMS)
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,141 @@
|
||||
## How to Build
|
||||
## How to Build
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Using CMake
|
||||
#### Building for desktop (WebGPU-native) with Google Dawn:
|
||||
1. `git clone https://github.com/google/dawn dawn`
|
||||
2. `cmake -B build -DIMGUI_DAWN_DIR=dawn`
|
||||
3. `cmake --build build`
|
||||
The resulting binary will be found at one of the following locations:
|
||||
* build/Debug/example_glfw_wgpu[.exe]
|
||||
* build/example_glfw_wgpu[.exe]
|
||||
|
||||
#### Building for desktop (WebGPU-Native) with WGPU:
|
||||
1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||
2. unzip the downloaded file in `your_preferred_folder`
|
||||
3. `cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder` ("full path" or "relative" starting from current directory)
|
||||
4. `cmake --build build`
|
||||
The resulting binary will be found at one of the following locations:
|
||||
* build/Debug/example_glfw_wgpu[.exe]
|
||||
* build/example_glfw_wgpu[.exe]
|
||||
|
||||
#### Building for Emscripten:
|
||||
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||
2. Install Ninja build system
|
||||
3. `emcmake cmake -G Ninja -B build`
|
||||
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
|
||||
4. `cmake --build build`
|
||||
|
||||
#### Sync Emscripten with latest Google Dawn:
|
||||
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
|
||||
https://github.com/google/dawn/releases
|
||||
Unpack it in your preferred folder and to replace the step 3 with:
|
||||
|
||||
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
|
||||
|
||||
**N.B.**
|
||||
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
|
||||
|
||||
|
||||
---
|
||||
|
||||
### CMake by step
|
||||
|
||||
#### Generate Dawn Native:
|
||||
|
||||
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||
|
||||
#### Generate WGPU Native:
|
||||
|
||||
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||
|
||||
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
||||
|
||||
#### Generate Emscripten:
|
||||
|
||||
- `emcmake cmake -G Ninja -B where_to_build_dir`\
|
||||
CMake checks the EMSCRIPEN version then:
|
||||
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||
- if EMS < 4.0.10 the build aborts (`-sUSE_WEBGPU=1` is no longer supported by our examples and our WGPU backend)
|
||||
|
||||
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
||||
|
||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
||||
- https://github.com/google/dawn/releases
|
||||
|
||||
#### Build time
|
||||
|
||||
Once the procedure for the specific builder is generated, the build command is **always the same**:
|
||||
|
||||
- Build using CMake
|
||||
- `cmake --build where_to_build_dir`
|
||||
- It will use selected builder to build the example.
|
||||
|
||||
- Build explicitly:
|
||||
- `cd where_to_build_dir`
|
||||
- `ninja`
|
||||
- This is the builder chosen during the generation phase
|
||||
|
||||
---
|
||||
|
||||
### CMake useful options
|
||||
#### Generator types (alternative to **ninja** builder):
|
||||
- `-G Ninja` to build with __ninja__ builder
|
||||
- `-G "Unix Makefiles"` to build with __make__ builder
|
||||
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
|
||||
- **Native build only**
|
||||
- Not **officially** supported to build Google Dawn
|
||||
|
||||
Example:
|
||||
- using **make** instead **ninja**:
|
||||
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||
|
||||
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
|
||||
|
||||
#### Directories
|
||||
- The directory path can be absolute or relative (starting from the current directory)
|
||||
- It's necessary to use different `where_to_build_dir` for different CMake generations
|
||||
|
||||
|
||||
#### Build type
|
||||
The default build type is **Debug**
|
||||
It is possible to use a different build type using:
|
||||
- `-DCMAKE_BUILD_TYPE=Release`
|
||||
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
|
||||
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
|
||||
|
||||
Example:
|
||||
- building **Release**:
|
||||
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
|
||||
|
||||
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
|
||||
|
||||
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
|
||||
- e.g. CLang search in path specified from the following environment variables:
|
||||
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
|
||||
- library files: LIBRARY_PATH
|
||||
|
||||
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
|
||||
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
|
||||
|
||||
Examples:
|
||||
|
||||
- using **vcpkg** package manager it's necessary adding:
|
||||
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
|
||||
|
||||
- full cmake command using **vcpkg** package manager:
|
||||
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
|
||||
|
||||
---
|
||||
|
||||
|
||||
### Using makefile
|
||||
|
||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||
|
||||
@@ -10,6 +147,8 @@
|
||||
|
||||
- Requires recent Emscripten as WGPU is still a work-in-progress API.
|
||||
|
||||
---
|
||||
|
||||
## How to Run
|
||||
|
||||
To run on a local machine:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Dear ImGui: standalone example application for using GLFW + WebGPU
|
||||
// Dear ImGui: standalone example application for GLFW + WebGPU
|
||||
// - Emscripten is supported for publishing on web. See https://emscripten.org.
|
||||
// - Dawn is used as a WebGPU implementation on desktop.
|
||||
|
||||
@@ -12,54 +12,44 @@
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_wgpu.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/html5_webgpu.h>
|
||||
#else
|
||||
#include <webgpu/webgpu_glfw.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <webgpu/webgpu.h>
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||
#endif
|
||||
|
||||
// Global WebGPU required states
|
||||
static WGPUInstance wgpu_instance = nullptr;
|
||||
static WGPUDevice wgpu_device = nullptr;
|
||||
static WGPUSurface wgpu_surface = nullptr;
|
||||
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
|
||||
static WGPUSwapChain wgpu_swap_chain = nullptr;
|
||||
static int wgpu_swap_chain_width = 1280;
|
||||
static int wgpu_swap_chain_height = 720;
|
||||
#include <webgpu/webgpu.h>
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
#endif
|
||||
|
||||
// Data
|
||||
static WGPUInstance wgpu_instance = nullptr;
|
||||
static WGPUDevice wgpu_device = nullptr;
|
||||
static WGPUSurface wgpu_surface = nullptr;
|
||||
static WGPUQueue wgpu_queue = nullptr;
|
||||
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
|
||||
static int wgpu_surface_width = 1280;
|
||||
static int wgpu_surface_height = 800;
|
||||
|
||||
// Forward declarations
|
||||
static bool InitWGPU(GLFWwindow* window);
|
||||
static void CreateSwapChain(int width, int height);
|
||||
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window);
|
||||
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
{
|
||||
printf("GLFW Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
static void wgpu_error_callback(WGPUErrorType error_type, const char* message, void*)
|
||||
static void ResizeSurface(int width, int height)
|
||||
{
|
||||
const char* error_type_lbl = "";
|
||||
switch (error_type)
|
||||
{
|
||||
case WGPUErrorType_Validation: error_type_lbl = "Validation"; break;
|
||||
case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break;
|
||||
case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break;
|
||||
case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break;
|
||||
default: error_type_lbl = "Unknown";
|
||||
}
|
||||
printf("%s error: %s\n", error_type_lbl, message);
|
||||
wgpu_surface_configuration.width = wgpu_surface_width = width;
|
||||
wgpu_surface_configuration.height = wgpu_surface_height = height;
|
||||
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
|
||||
}
|
||||
|
||||
// Main code
|
||||
@@ -72,19 +62,23 @@ int main(int, char**)
|
||||
// Make sure GLFW does not initialize any graphics context.
|
||||
// This needs to be done explicitly later.
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
|
||||
|
||||
// Create window
|
||||
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
|
||||
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
|
||||
GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
|
||||
if (window == nullptr)
|
||||
return 1;
|
||||
|
||||
// Initialize the WebGPU environment
|
||||
if (!InitWGPU(window))
|
||||
{
|
||||
if (window)
|
||||
glfwDestroyWindow(window);
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
return 1;
|
||||
}
|
||||
CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height);
|
||||
|
||||
glfwShowWindow(window);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
@@ -98,6 +92,11 @@ int main(int, char**)
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOther(window, true);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
@@ -106,26 +105,27 @@ int main(int, char**)
|
||||
ImGui_ImplWGPU_InitInfo init_info;
|
||||
init_info.Device = wgpu_device;
|
||||
init_info.NumFramesInFlight = 3;
|
||||
init_info.RenderTargetFormat = wgpu_preferred_fmt;
|
||||
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
|
||||
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
|
||||
ImGui_ImplWGPU_Init(&init_info);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
|
||||
//io.Fonts->AddFontDefault();
|
||||
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
#endif
|
||||
@@ -160,11 +160,24 @@ int main(int, char**)
|
||||
// React to changes in screen size
|
||||
int width, height;
|
||||
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
|
||||
if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height)
|
||||
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
||||
ResizeSurface(width, height);
|
||||
|
||||
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
|
||||
WGPUSurfaceTexture surface_texture;
|
||||
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
|
||||
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
|
||||
{
|
||||
ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
CreateSwapChain(width, height);
|
||||
ImGui_ImplWGPU_CreateDeviceObjects();
|
||||
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
|
||||
abort();
|
||||
}
|
||||
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
|
||||
{
|
||||
if (surface_texture.texture)
|
||||
wgpuTextureRelease(surface_texture.texture);
|
||||
if (width > 0 && height > 0)
|
||||
ResizeSurface(width, height);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
@@ -212,17 +225,21 @@ int main(int, char**)
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
// Tick needs to be called in Dawn to display validation errors
|
||||
wgpuDeviceTick(wgpu_device);
|
||||
#endif
|
||||
WGPUTextureViewDescriptor view_desc = {};
|
||||
view_desc.format = wgpu_surface_configuration.format;
|
||||
view_desc.dimension = WGPUTextureViewDimension_2D ;
|
||||
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
|
||||
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
|
||||
view_desc.aspect = WGPUTextureAspect_All;
|
||||
|
||||
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
|
||||
|
||||
WGPURenderPassColorAttachment color_attachments = {};
|
||||
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
||||
color_attachments.loadOp = WGPULoadOp_Clear;
|
||||
color_attachments.storeOp = WGPUStoreOp_Store;
|
||||
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
|
||||
color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
|
||||
color_attachments.view = texture_view;
|
||||
|
||||
WGPURenderPassDescriptor render_pass_desc = {};
|
||||
render_pass_desc.colorAttachmentCount = 1;
|
||||
@@ -238,14 +255,16 @@ int main(int, char**)
|
||||
|
||||
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
||||
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
||||
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
|
||||
wgpuQueueSubmit(queue, 1, &cmd_buffer);
|
||||
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
wgpuSwapChainPresent(wgpu_swap_chain);
|
||||
wgpuSurfacePresent(wgpu_surface);
|
||||
// Tick needs to be called in Dawn to display validation errors
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
wgpuDeviceTick(wgpu_device);
|
||||
#endif
|
||||
|
||||
wgpuTextureViewRelease(color_attachments.view);
|
||||
#endif
|
||||
wgpuTextureViewRelease(texture_view);
|
||||
wgpuRenderPassEncoderRelease(pass);
|
||||
wgpuCommandEncoderRelease(encoder);
|
||||
wgpuCommandBufferRelease(cmd_buffer);
|
||||
@@ -259,92 +278,282 @@ int main(int, char**)
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
wgpuSurfaceUnconfigure(wgpu_surface);
|
||||
wgpuSurfaceRelease(wgpu_surface);
|
||||
wgpuQueueRelease(wgpu_queue);
|
||||
wgpuDeviceRelease(wgpu_device);
|
||||
wgpuInstanceRelease(wgpu_instance);
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
static WGPUAdapter RequestAdapter(WGPUInstance instance)
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
|
||||
{
|
||||
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
|
||||
wgpu::Adapter acquired_adapter;
|
||||
wgpu::RequestAdapterOptions adapter_options;
|
||||
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
|
||||
{
|
||||
if (status == WGPURequestAdapterStatus_Success)
|
||||
*(WGPUAdapter*)(pUserData) = adapter;
|
||||
else
|
||||
printf("Could not get WebGPU adapter: %s\n", message);
|
||||
};
|
||||
WGPUAdapter adapter;
|
||||
wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
|
||||
{
|
||||
auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData)
|
||||
{
|
||||
if (status == WGPURequestDeviceStatus_Success)
|
||||
*(WGPUDevice*)(pUserData) = device;
|
||||
else
|
||||
printf("Could not get WebGPU device: %s\n", message);
|
||||
if (status != wgpu::RequestAdapterStatus::Success)
|
||||
{
|
||||
printf("Failed to get an adapter: %s\n", message.data);
|
||||
return;
|
||||
}
|
||||
acquired_adapter = std::move(adapter);
|
||||
};
|
||||
WGPUDevice device;
|
||||
wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device);
|
||||
return device;
|
||||
|
||||
// Synchronously (wait until) acquire Adapter
|
||||
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
|
||||
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
|
||||
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
|
||||
return acquired_adapter.MoveToCHandle();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool InitWGPU(GLFWwindow* window)
|
||||
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
|
||||
{
|
||||
wgpu::Instance instance = wgpuCreateInstance(nullptr);
|
||||
// Set device callback functions
|
||||
wgpu::DeviceDescriptor device_desc;
|
||||
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
|
||||
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
|
||||
);
|
||||
device_desc.SetUncapturedErrorCallback(
|
||||
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
|
||||
);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
wgpu_device = emscripten_webgpu_get_device();
|
||||
if (!wgpu_device)
|
||||
return false;
|
||||
#else
|
||||
WGPUAdapter adapter = RequestAdapter(instance.Get());
|
||||
if (!adapter)
|
||||
return false;
|
||||
wgpu_device = RequestDevice(adapter);
|
||||
#endif
|
||||
wgpu::Device acquired_device;
|
||||
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
|
||||
{
|
||||
if (status != wgpu::RequestDeviceStatus::Success)
|
||||
{
|
||||
printf("Failed to get an device: %s\n", message.data);
|
||||
return;
|
||||
}
|
||||
acquired_device = std::move(local_device);
|
||||
};
|
||||
|
||||
// Synchronously (wait until) get Device
|
||||
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
|
||||
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
|
||||
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
||||
return acquired_device.MoveToCHandle();
|
||||
}
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestAdapterStatus_Success)
|
||||
{
|
||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||
*extAdapter = adapter;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestDeviceStatus_Success)
|
||||
{
|
||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||
*extDevice = device;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Request_device status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
|
||||
}
|
||||
}
|
||||
|
||||
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
||||
{
|
||||
WGPURequestAdapterOptions adapter_options = {};
|
||||
|
||||
WGPUAdapter local_adapter = nullptr;
|
||||
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
||||
adapterCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||
adapterCallbackInfo.callback = handle_request_adapter;
|
||||
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||
|
||||
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||
return local_adapter;
|
||||
}
|
||||
|
||||
static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
||||
{
|
||||
WGPUDevice local_device = nullptr;
|
||||
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
||||
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||
deviceCallbackInfo.callback = handle_request_device;
|
||||
deviceCallbackInfo.userdata1 = &local_device;
|
||||
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
IM_ASSERT(local_device && "Error on Device request");
|
||||
return local_device;
|
||||
}
|
||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
|
||||
bool InitWGPU(GLFWwindow* window)
|
||||
{
|
||||
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
|
||||
|
||||
// Google DAWN backend: Adapter and Device acquisition, Surface creation
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
wgpu::InstanceDescriptor instance_desc = {};
|
||||
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
|
||||
instance_desc.requiredFeatureCount = 1;
|
||||
instance_desc.requiredFeatures = &timedWaitAny;
|
||||
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
|
||||
|
||||
wgpu::Adapter adapter = RequestAdapter(instance);
|
||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
|
||||
|
||||
wgpu_device = RequestDevice(instance, adapter);
|
||||
|
||||
// Create the surface.
|
||||
#ifdef __EMSCRIPTEN__
|
||||
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
||||
html_surface_desc.selector = "#canvas";
|
||||
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
|
||||
canvas_desc.selector = "#canvas";
|
||||
|
||||
wgpu::SurfaceDescriptor surface_desc = {};
|
||||
surface_desc.nextInChain = &html_surface_desc;
|
||||
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
|
||||
|
||||
wgpu::Adapter adapter = {};
|
||||
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
|
||||
surface_desc.nextInChain = &canvas_desc;
|
||||
wgpu_surface = instance.CreateSurface(&surface_desc).MoveToCHandle();
|
||||
#else
|
||||
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
|
||||
if (!surface)
|
||||
wgpu_surface = CreateWGPUSurface(instance.Get(), window);
|
||||
#endif
|
||||
if (!wgpu_surface)
|
||||
return false;
|
||||
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
|
||||
|
||||
// Moving Dawn objects into WGPU handles
|
||||
wgpu_instance = instance.MoveToCHandle();
|
||||
|
||||
WGPUSurfaceCapabilities surface_capabilities = {};
|
||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
|
||||
|
||||
preferred_fmt = surface_capabilities.formats[0];
|
||||
|
||||
// WGPU backend: Adapter and Device acquisition, Surface creation
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
WGPUInstanceDescriptor instanceDesc = {};
|
||||
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
|
||||
instanceDesc.requiredFeatureCount = 1;
|
||||
instanceDesc.requiredFeatures = &timedWaitAny;
|
||||
wgpu_instance = wgpuCreateInstance(&instanceDesc);
|
||||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
wgpuSetLogCallback(
|
||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||
);
|
||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||
#endif
|
||||
|
||||
wgpu_instance = instance.MoveToCHandle();
|
||||
wgpu_surface = surface.MoveToCHandle();
|
||||
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
||||
|
||||
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
|
||||
wgpu_device = RequestDevice(wgpu_instance, adapter);
|
||||
|
||||
// Create the surface.
|
||||
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
||||
if (!wgpu_surface)
|
||||
return false;
|
||||
|
||||
WGPUSurfaceCapabilities surface_capabilities = {};
|
||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
||||
|
||||
preferred_fmt = surface_capabilities.formats[0];
|
||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
|
||||
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
||||
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
|
||||
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
|
||||
wgpu_surface_configuration.width = wgpu_surface_width;
|
||||
wgpu_surface_configuration.height = wgpu_surface_height;
|
||||
wgpu_surface_configuration.device = wgpu_device;
|
||||
wgpu_surface_configuration.format = preferred_fmt;
|
||||
|
||||
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
|
||||
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CreateSwapChain(int width, int height)
|
||||
// GLFW helper to create a WebGPU surface, used only in WGPU-Native. DAWN-Native already has a built-in function
|
||||
// As of today (2025/10) there is no "official" support in GLFW to create a surface for WebGPU backend
|
||||
// This stub uses "low level" GLFW calls to acquire information from a specific Window Manager.
|
||||
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
|
||||
#ifndef __EMSCRIPTEN__
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
#define GLFW_HAS_X11_OR_WAYLAND 1
|
||||
#else
|
||||
#define GLFW_HAS_X11_OR_WAYLAND 0
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#undef APIENTRY
|
||||
#ifndef GLFW_EXPOSE_NATIVE_WIN32 // for glfwGetWin32Window()
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
#elif GLFW_HAS_X11_OR_WAYLAND
|
||||
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#endif
|
||||
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
|
||||
#if defined(__has_include) && __has_include(<wayland-client.h>)
|
||||
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
#undef Status // X11 headers are leaking this and also 'Success', 'Always', 'None', all used in DAWN api. Add #undef if necessary.
|
||||
|
||||
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
|
||||
{
|
||||
if (wgpu_swap_chain)
|
||||
wgpuSwapChainRelease(wgpu_swap_chain);
|
||||
wgpu_swap_chain_width = width;
|
||||
wgpu_swap_chain_height = height;
|
||||
WGPUSwapChainDescriptor swap_chain_desc = {};
|
||||
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
swap_chain_desc.format = wgpu_preferred_fmt;
|
||||
swap_chain_desc.width = width;
|
||||
swap_chain_desc.height = height;
|
||||
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
|
||||
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
|
||||
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
|
||||
create_info.Instance = instance;
|
||||
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
{
|
||||
create_info.System = "cocoa";
|
||||
create_info.RawWindow = (void*)glfwGetCocoaWindow(window);
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND)
|
||||
{
|
||||
create_info.System = "wayland";
|
||||
create_info.RawDisplay = (void*)glfwGetWaylandDisplay();
|
||||
create_info.RawSurface = (void*)glfwGetWaylandWindow(window);
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
|
||||
{
|
||||
create_info.System = "x11";
|
||||
create_info.RawWindow = (void*)glfwGetX11Window(window);
|
||||
create_info.RawDisplay = (void*)glfwGetX11Display();
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||
{
|
||||
create_info.System = "win32";
|
||||
create_info.RawWindow = (void*)glfwGetWin32Window(window);
|
||||
create_info.RawInstance = (void*)::GetModuleHandle(NULL);
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#else
|
||||
#error "Unsupported WebGPU native platform!"
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
#endif // #ifndef __EMSCRIPTEN__
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
||||
<title>Dear ImGui Emscripten+GLFW+WebGPU example</title>
|
||||
<style>
|
||||
body { margin: 0; background-color: black }
|
||||
.emscripten {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
margin: 0px;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
<script type='text/javascript'>
|
||||
var Module;
|
||||
(async () => {
|
||||
Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function() {
|
||||
return function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.log(text);
|
||||
};
|
||||
})(),
|
||||
printErr: function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.error(text);
|
||||
},
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
|
||||
return canvas;
|
||||
})(),
|
||||
setStatus: function(text) {
|
||||
console.log("status: " + text);
|
||||
},
|
||||
monitorRunDependencies: function(left) {
|
||||
// no run dependencies to log
|
||||
}
|
||||
};
|
||||
window.onerror = function() {
|
||||
console.log("onerror: " + event);
|
||||
};
|
||||
|
||||
// Initialize the graphics adapter
|
||||
{
|
||||
if (!navigator.gpu) {
|
||||
throw Error("WebGPU not supported.");
|
||||
}
|
||||
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
const device = await adapter.requestDevice();
|
||||
Module.preinitializedWebGPUDevice = device;
|
||||
}
|
||||
|
||||
{
|
||||
const js = document.createElement('script');
|
||||
js.async = true;
|
||||
js.src = "index.js";
|
||||
document.body.appendChild(js);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -48,7 +48,7 @@ int main(int argc, char** argv)
|
||||
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
||||
#endif
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
|
||||
glutInitWindowSize(1280, 720);
|
||||
glutInitWindowSize(1280, 800);
|
||||
glutCreateWindow("Dear ImGui GLUT+OpenGL2 Example");
|
||||
|
||||
// Setup GLUT display function
|
||||
@@ -78,16 +78,17 @@ int main(int argc, char** argv)
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
ImGui_ImplGLUT_InstallFuncs();
|
||||
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
179
examples/example_null/example_null.vcxproj
Normal file
179
examples/example_null/example_null.vcxproj
Normal file
@@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{1A0BF63C-18EF-4BAE-A8DA-055481B11F5D}</ProjectGuid>
|
||||
<RootNamespace>example_win32_directx11</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\backends\imgui_impl_null.h" />
|
||||
<ClInclude Include="..\..\imconfig.h" />
|
||||
<ClInclude Include="..\..\imgui.h" />
|
||||
<ClInclude Include="..\..\imgui_internal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\backends\imgui_impl_null.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui.cpp" />
|
||||
<ClCompile Include="..\..\imgui_demo.cpp" />
|
||||
<ClCompile Include="..\..\imgui_draw.cpp" />
|
||||
<ClCompile Include="..\..\imgui_tables.cpp" />
|
||||
<ClCompile Include="..\..\imgui_widgets.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\misc\debuggers\imgui.natstepfilter" />
|
||||
<None Include="..\..\misc\debuggers\imgui.natvis" />
|
||||
<None Include="..\README.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
57
examples/example_null/example_null.vcxproj.filters
Normal file
57
examples/example_null/example_null.vcxproj.filters
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="imgui">
|
||||
<UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sources">
|
||||
<UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\imgui.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\imgui_internal.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\backends\imgui_impl_null.h">
|
||||
<Filter>sources</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_demo.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_draw.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_tables.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_widgets.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\backends\imgui_impl_null.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.txt" />
|
||||
<None Include="..\..\misc\debuggers\imgui.natvis">
|
||||
<Filter>imgui</Filter>
|
||||
</None>
|
||||
<None Include="..\..\misc\debuggers\imgui.natstepfilter">
|
||||
<Filter>imgui</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -4,23 +4,26 @@
|
||||
#include "imgui.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// For imgui_impl_null: use relative filename + embed implementation directly by including the .cpp file.
|
||||
// This is to simplify casual building of this example from all sorts of test scripts.
|
||||
#include "../../backends/imgui_impl_null.h"
|
||||
#include "../../backends/imgui_impl_null.cpp"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
IMGUI_CHECKVERSION();
|
||||
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Build atlas
|
||||
//unsigned char* tex_pixels = nullptr;
|
||||
//int tex_w, tex_h;
|
||||
//io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
|
||||
ImGui_ImplNullPlatform_Init();
|
||||
ImGui_ImplNullRender_Init();
|
||||
|
||||
for (int n = 0; n < 20; n++)
|
||||
{
|
||||
printf("NewFrame() %d\n", n);
|
||||
io.DisplaySize = ImVec2(1920, 1080);
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
ImGui_ImplNullPlatform_NewFrame();
|
||||
ImGui_ImplNullRender_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
static float f = 0.0f;
|
||||
@@ -33,6 +36,8 @@ int main(int, char**)
|
||||
}
|
||||
|
||||
printf("DestroyContext()\n");
|
||||
ImGui_ImplNullRender_Shutdown();
|
||||
ImGui_ImplNullPlatform_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,27 +29,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -39,7 +39,7 @@ int main(int, char**)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
@@ -50,11 +50,11 @@ int main(int, char**)
|
||||
// Setup window
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_SysWMinfo wmInfo;
|
||||
@@ -83,21 +83,23 @@ int main(int, char**)
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForD3D(window);
|
||||
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
@@ -210,6 +212,7 @@ int main(int, char**)
|
||||
bool CreateDeviceD3D(HWND hWnd)
|
||||
{
|
||||
// Setup swap chain
|
||||
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
sd.BufferCount = 2;
|
||||
@@ -230,7 +233,10 @@ bool CreateDeviceD3D(HWND hWnd)
|
||||
//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
|
||||
if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
|
||||
HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
|
||||
if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available.
|
||||
res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
|
||||
if (res != S_OK)
|
||||
return false;
|
||||
|
||||
CreateRenderTarget();
|
||||
|
||||
@@ -30,14 +30,16 @@ int main(int, char**)
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
@@ -51,7 +53,7 @@ int main(int, char**)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Inform SDL that we will be using metal for rendering. Without this hint initialization of metal renderer may fail.
|
||||
@@ -60,7 +62,7 @@ int main(int, char**)
|
||||
// Enable native IME.
|
||||
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error creating window: %s\n", SDL_GetError());
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -31,7 +31,7 @@ int main(int, char**)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
@@ -47,11 +47,11 @@ int main(int, char**)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
|
||||
@@ -72,21 +72,23 @@ int main(int, char**)
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -36,7 +36,7 @@ int main(int, char**)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
@@ -81,18 +81,18 @@ int main(int, char**)
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
|
||||
if (gl_context == nullptr)
|
||||
{
|
||||
printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_GL_MakeCurrent(window, gl_context);
|
||||
@@ -112,22 +112,24 @@ int main(int, char**)
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
@@ -29,27 +29,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -184,4 +184,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -33,7 +33,7 @@ int main(int, char**)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
@@ -44,17 +44,17 @@ int main(int, char**)
|
||||
// Create window with SDL_Renderer graphics context
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
|
||||
if (renderer == nullptr)
|
||||
{
|
||||
SDL_Log("Error creating SDL_Renderer!");
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
//SDL_RendererInfo info;
|
||||
//SDL_GetRendererInfo(renderer, &info);
|
||||
@@ -74,21 +74,23 @@ int main(int, char**)
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
|
||||
ImGui_ImplSDLRenderer2_Init(renderer);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -187,4 +187,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -184,7 +184,8 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
@@ -192,7 +193,7 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
pool_info.maxSets = 0;
|
||||
for (VkDescriptorPoolSize& pool_size : pool_sizes)
|
||||
pool_info.maxSets += pool_size.descriptorCount;
|
||||
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
|
||||
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||
check_vk_result(err);
|
||||
@@ -203,11 +204,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
// Your real engine/app may not use them.
|
||||
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
|
||||
{
|
||||
wd->Surface = surface;
|
||||
|
||||
// Check for WSI support
|
||||
VkBool32 res;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
|
||||
if (res != VK_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||
@@ -217,7 +216,8 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
|
||||
// Select Surface Format
|
||||
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
wd->Surface = surface;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
|
||||
// Select Present Mode
|
||||
#ifdef APP_USE_UNLIMITED_FRAME_RATE
|
||||
@@ -225,12 +225,12 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
|
||||
#else
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
|
||||
#endif
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// Create SwapChain, RenderPass, Framebuffer, etc.
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
@@ -247,9 +247,10 @@ static void CleanupVulkan()
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void CleanupVulkanWindow()
|
||||
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
|
||||
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
@@ -349,7 +350,7 @@ int main(int, char**)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
@@ -360,11 +361,11 @@ int main(int, char**)
|
||||
// Create window with Vulkan graphics context
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ImVector<const char*> extensions;
|
||||
@@ -403,7 +404,7 @@ int main(int, char**)
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForVulkan(window);
|
||||
@@ -416,24 +417,26 @@ int main(int, char**)
|
||||
init_info.Queue = g_Queue;
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.RenderPass = wd->RenderPass;
|
||||
init_info.Subpass = 0;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
|
||||
init_info.PipelineInfoMain.Subpass = 0;
|
||||
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
@@ -476,7 +479,7 @@ int main(int, char**)
|
||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||
{
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
g_SwapChainRebuild = false;
|
||||
}
|
||||
@@ -545,7 +548,7 @@ int main(int, char**)
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow();
|
||||
CleanupVulkanWindow(&g_MainWindowData);
|
||||
CleanupVulkan();
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
214
examples/example_sdl2_wgpu/CMakeLists.txt
Normal file
214
examples/example_sdl2_wgpu/CMakeLists.txt
Normal file
@@ -0,0 +1,214 @@
|
||||
# Building for desktop with Dawn:
|
||||
# 1. git clone https://github.com/google/dawn dawn
|
||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGPU-Native:
|
||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||
# 2. unzip the downloaded file in your_preferred_folder
|
||||
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
||||
# 4. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGVK (MUCH EASIER)
|
||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||
|
||||
# Building for Emscripten:
|
||||
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||
# 2. Install Ninja build system
|
||||
# 3. emcmake cmake -G Ninja -B build
|
||||
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
|
||||
# 3. cmake --build build
|
||||
# 4. emrun build/index.html
|
||||
|
||||
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
|
||||
project(imgui_example_sdl2_wgpu C CXX)
|
||||
|
||||
set(IMGUI_EXECUTABLE example_sdl2_wgpu)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
||||
|
||||
# Dear ImGui
|
||||
set(IMGUI_DIR ../../)
|
||||
|
||||
# ImGui example commons source files
|
||||
set(IMGUI_EXAMPLE_SOURCE_FILES
|
||||
main.cpp
|
||||
# backend files
|
||||
${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
|
||||
# Dear ImGui files
|
||||
${IMGUI_DIR}/imgui.cpp
|
||||
${IMGUI_DIR}/imgui_draw.cpp
|
||||
${IMGUI_DIR}/imgui_demo.cpp
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
)
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Default to --use-port=emdawnwebgpu. You can override to provide your own local port.")
|
||||
else()
|
||||
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
||||
endif()
|
||||
|
||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||
else() # Native/Desktop build
|
||||
|
||||
# Check DAWN/WGPU/WGVK directory
|
||||
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
|
||||
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
|
||||
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||
endif()
|
||||
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
|
||||
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||
endif()
|
||||
|
||||
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
||||
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
|
||||
endif()
|
||||
|
||||
find_package(SDL2 REQUIRED) # SDL_MAIN_HANDLED
|
||||
|
||||
if(IMGUI_DAWN_DIR)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
||||
find_package(Threads) # required from Dawn installation
|
||||
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
||||
if(Dawn_FOUND)
|
||||
message("Dawn Installation has been found!")
|
||||
set(LIBRARIES dawn::webgpu_dawn ${OS_LIBRARIES})
|
||||
else()
|
||||
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
|
||||
|
||||
option(DAWN_USE_GLFW OFF) # disable builtin GLFW in DAWN when we use SDL2 / SDL3
|
||||
|
||||
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
|
||||
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
|
||||
|
||||
# Dawn builds many things by default - disable things we don't need
|
||||
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
|
||||
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
|
||||
option(TINT_BUILD_DOCS "Build documentation" OFF)
|
||||
option(TINT_BUILD_TESTS "Build tests" OFF)
|
||||
if(NOT APPLE)
|
||||
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
|
||||
endif()
|
||||
if(WIN32)
|
||||
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
|
||||
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
|
||||
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
|
||||
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
|
||||
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
|
||||
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
|
||||
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
|
||||
endif()
|
||||
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
|
||||
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
|
||||
if(LINUX)
|
||||
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
|
||||
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
|
||||
|
||||
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(IMGUI_WGPU_DIR)
|
||||
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
||||
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
||||
if(WIN32)
|
||||
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(OS_LIBRARIES "-lm -ldl")
|
||||
endif()
|
||||
|
||||
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(IMGUI_WGVK_DIR)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
||||
|
||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_DIR}/backends
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_SDL2_WGPU")
|
||||
|
||||
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
|
||||
if (MSVC)
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
|
||||
else()
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
|
||||
endif()
|
||||
|
||||
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
|
||||
# EMSCRIPTEN: by used FLAG
|
||||
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
|
||||
# NATIVE: by used SDK installation directory
|
||||
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
|
||||
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
|
||||
|
||||
if(NOT EMSCRIPTEN) # WegGPU-Native settings
|
||||
if(IMGUI_DAWN_DIR)
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||
if(NOT Dawn_FOUND)
|
||||
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
||||
endif()
|
||||
endif()
|
||||
if(IMGUI_WGPU_DIR)
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
||||
endif()
|
||||
if(IMGUI_WGVK_DIR)
|
||||
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
|
||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
|
||||
if (MSVC)
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} ${SDL2_LIBRARIES})
|
||||
else() # Emscripten settings
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
||||
|
||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=2")
|
||||
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
|
||||
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
|
||||
"-sUSE_SDL=2"
|
||||
"-sWASM=1"
|
||||
"-sASYNCIFY=1"
|
||||
"-sALLOW_MEMORY_GROWTH=1"
|
||||
"-sNO_EXIT_RUNTIME=0"
|
||||
"-sASSERTIONS=1"
|
||||
"-sDISABLE_EXCEPTION_CATCHING=1"
|
||||
"-sNO_FILESYSTEM=1"
|
||||
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
|
||||
)
|
||||
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
|
||||
endif()
|
||||
99
examples/example_sdl2_wgpu/Makefile.emscripten
Normal file
99
examples/example_sdl2_wgpu/Makefile.emscripten
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# Makefile to use with emscripten
|
||||
# See https://emscripten.org/docs/getting_started/downloads.html
|
||||
# for installation instructions.
|
||||
#
|
||||
# This Makefile assumes you have loaded emscripten's environment.
|
||||
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
|
||||
#
|
||||
# Running `make -f Makefile.emscripten` will produce three files:
|
||||
# - web/index.html
|
||||
# - web/index.js
|
||||
# - web/index.wasm
|
||||
#
|
||||
# All three are needed to run the demo.
|
||||
|
||||
CC = emcc
|
||||
CXX = em++
|
||||
WEB_DIR = web
|
||||
EXE = $(WEB_DIR)/index.html
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
CPPFLAGS =
|
||||
LDFLAGS =
|
||||
EMS =
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## EMSCRIPTEN OPTIONS
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
||||
EMS += -s USE_SDL=2
|
||||
EMS += -s DISABLE_EXCEPTION_CATCHING=1
|
||||
LDFLAGS += -s WASM=1
|
||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||
LDFLAGS += -s ASYNCIFY=1
|
||||
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
||||
LDFLAGS += -s ASSERTIONS=1
|
||||
|
||||
# Using Dawn-based WebGPU port (requires Emscripten >= 4.0.10)
|
||||
EMS += --use-port=emdawnwebgpu
|
||||
LDFLAGS += --use-port=emdawnwebgpu
|
||||
|
||||
# Build as single file (binary text encoded in .html file)
|
||||
#LDFLAGS += -sSINGLE_FILE
|
||||
|
||||
# Emscripten allows preloading a file or folder to be accessible at runtime.
|
||||
# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
|
||||
# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
|
||||
# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
|
||||
USE_FILE_SYSTEM ?= 0
|
||||
ifeq ($(USE_FILE_SYSTEM), 0)
|
||||
LDFLAGS += -s NO_FILESYSTEM=1
|
||||
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
|
||||
endif
|
||||
ifeq ($(USE_FILE_SYSTEM), 1)
|
||||
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
|
||||
endif
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## FINAL BUILD FLAGS
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
#CPPFLAGS += -g
|
||||
CPPFLAGS += -Wall -Wformat -Os $(EMS)
|
||||
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
|
||||
LDFLAGS += $(EMS)
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## BUILD RULES
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
%.o:%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/backends/%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
all: $(EXE)
|
||||
@echo Build complete for $(EXE)
|
||||
|
||||
$(WEB_DIR):
|
||||
mkdir $@
|
||||
|
||||
serve: all
|
||||
python3 -m http.server -d $(WEB_DIR)
|
||||
|
||||
$(EXE): $(OBJS) $(WEB_DIR)
|
||||
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) $(OBJS) $(WEB_DIR)/*.js $(WEB_DIR)/*.wasm $(WEB_DIR)/*.wasm.pre
|
||||
163
examples/example_sdl2_wgpu/README.md
Normal file
163
examples/example_sdl2_wgpu/README.md
Normal file
@@ -0,0 +1,163 @@
|
||||
## How to Build
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Using CMake
|
||||
#### Building for desktop (WebGPU-native) with Google Dawn:
|
||||
1. `git clone https://github.com/google/dawn dawn`
|
||||
2. `cmake -B build -DIMGUI_DAWN_DIR=dawn`
|
||||
3. `cmake --build build`
|
||||
The resulting binary will be found at one of the following locations:
|
||||
* build/Debug/example_sdl2_wgpu[.exe]
|
||||
* build/example_sdl2_wgpu[.exe]
|
||||
|
||||
#### Building for desktop (WebGPU-Native) with WGPU:
|
||||
1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||
2. unzip the downloaded file in `your_preferred_folder`
|
||||
3. `cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder` ("full path" or "relative" starting from current directory)
|
||||
4. `cmake --build build`
|
||||
The resulting binary will be found at one of the following locations:
|
||||
* build/Debug/example_sdl2_wgpu[.exe]
|
||||
* build/example_sdl2_wgpu[.exe]
|
||||
|
||||
#### Building for Emscripten:
|
||||
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||
2. Install Ninja build system
|
||||
3. `emcmake cmake -G Ninja -B build`
|
||||
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
|
||||
4. `cmake --build build`
|
||||
|
||||
#### Sync Emscripten with latest Google Dawn:
|
||||
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
|
||||
https://github.com/google/dawn/releases
|
||||
Unpack it in your preferred folder and to replace the step 3 with:
|
||||
|
||||
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
|
||||
|
||||
**N.B.**
|
||||
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
|
||||
|
||||
|
||||
---
|
||||
|
||||
### CMake by step
|
||||
|
||||
#### Generate Dawn Native:
|
||||
|
||||
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||
|
||||
#### Generate WGPU Native:
|
||||
|
||||
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||
|
||||
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
||||
|
||||
#### Generate Emscripten:
|
||||
|
||||
- `emcmake cmake -G Ninja -B where_to_build_dir`\
|
||||
CMake checks the EMSCRIPEN version then:
|
||||
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||
- if EMS < 4.0.10 the build aborts (`-sUSE_WEBGPU=1` is no longer supported by our examples and our WGPU backend)
|
||||
|
||||
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
||||
|
||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
||||
- https://github.com/google/dawn/releases
|
||||
|
||||
#### Build time
|
||||
|
||||
Once the procedure for the specific builder is generated, the build command is **always the same**:
|
||||
|
||||
- Build using CMake
|
||||
- `cmake --build where_to_build_dir`
|
||||
- It will use selected builder to build the example.
|
||||
|
||||
- Build explicitly:
|
||||
- `cd where_to_build_dir`
|
||||
- `ninja`
|
||||
- This is the builder chosen during the generation phase
|
||||
|
||||
---
|
||||
|
||||
### CMake useful options
|
||||
#### Generator types (alternative to **ninja** builder):
|
||||
- `-G Ninja` to build with __ninja__ builder
|
||||
- `-G "Unix Makefiles"` to build with __make__ builder
|
||||
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
|
||||
- **Native build only**
|
||||
- Not **officially** supported to build Google Dawn
|
||||
|
||||
Example:
|
||||
- using **make** instead **ninja**:
|
||||
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||
|
||||
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
|
||||
|
||||
#### Directories
|
||||
- The directory path can be absolute or relative (starting from the current directory)
|
||||
- It's necessary to use different `where_to_build_dir` for different CMake generations
|
||||
|
||||
|
||||
#### Build type
|
||||
The default build type is **Debug**
|
||||
It is possible to use a different build type using:
|
||||
- `-DCMAKE_BUILD_TYPE=Release`
|
||||
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
|
||||
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
|
||||
|
||||
Example:
|
||||
- building **Release**:
|
||||
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
|
||||
|
||||
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
|
||||
|
||||
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
|
||||
- e.g. CLang search in path specified from the following environment variables:
|
||||
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
|
||||
- library files: LIBRARY_PATH
|
||||
|
||||
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
|
||||
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
|
||||
|
||||
Examples:
|
||||
|
||||
- using **vcpkg** package manager it's necessary adding:
|
||||
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
|
||||
|
||||
- full cmake command using **vcpkg** package manager:
|
||||
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
|
||||
|
||||
---
|
||||
|
||||
|
||||
### Using makefile
|
||||
|
||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||
|
||||
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
||||
|
||||
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
|
||||
|
||||
- Then build using `make -f Makefile.emscripten` while in the `example_glfw_wgpu/` directory.
|
||||
|
||||
- Requires recent Emscripten as WGPU is still a work-in-progress API.
|
||||
|
||||
---
|
||||
|
||||
## How to Run
|
||||
|
||||
To run on a local machine:
|
||||
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
|
||||
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
|
||||
- Otherwise, generally you will need a local webserver:
|
||||
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
|
||||
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
|
||||
- Emscripten SDK has a handy `emrun` command: `emrun web/example_glfw_wgpu.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
|
||||
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
|
||||
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
|
||||
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).
|
||||
526
examples/example_sdl2_wgpu/main.cpp
Normal file
526
examples/example_sdl2_wgpu/main.cpp
Normal file
@@ -0,0 +1,526 @@
|
||||
// Dear ImGui: standalone example application for using SDL2 + WebGPU
|
||||
// - Emscripten is supported for publishing on web. See https://emscripten.org.
|
||||
// - Dawn is used as a WebGPU implementation on desktop.
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl2.h"
|
||||
#include "imgui_impl_wgpu.h"
|
||||
#include <stdio.h>
|
||||
#include <SDL.h>
|
||||
|
||||
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||
#endif
|
||||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
#endif
|
||||
|
||||
// Data
|
||||
static WGPUInstance wgpu_instance = nullptr;
|
||||
static WGPUDevice wgpu_device = nullptr;
|
||||
static WGPUSurface wgpu_surface = nullptr;
|
||||
static WGPUQueue wgpu_queue = nullptr;
|
||||
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
|
||||
static int wgpu_surface_width = 1280;
|
||||
static int wgpu_surface_height = 800;
|
||||
|
||||
// Forward declarations
|
||||
static bool InitWGPU(SDL_Window* window);
|
||||
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window);
|
||||
|
||||
static void ResizeSurface(int width, int height)
|
||||
{
|
||||
wgpu_surface_configuration.width = wgpu_surface_width = width;
|
||||
wgpu_surface_configuration.height = wgpu_surface_height = height;
|
||||
wgpuSurfaceConfigure(wgpu_surface, (WGPUSurfaceConfiguration*)&wgpu_surface_configuration);
|
||||
}
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
|
||||
|
||||
// Create window with graphics context
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
|
||||
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+WebGPU example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wgpu_surface_width, wgpu_surface_height, window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Initialize WGPU
|
||||
InitWGPU(window);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForOther(window);
|
||||
ImGui_ImplWGPU_InitInfo init_info;
|
||||
init_info.Device = wgpu_device;
|
||||
init_info.NumFramesInFlight = 3;
|
||||
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
|
||||
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
|
||||
ImGui_ImplWGPU_Init(&init_info);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
#endif
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
|
||||
// You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
|
||||
io.IniFilename = nullptr;
|
||||
EMSCRIPTEN_MAINLOOP_BEGIN
|
||||
#else
|
||||
while (!done)
|
||||
#endif
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
}
|
||||
|
||||
// React to changes in screen size
|
||||
int width, height;
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
||||
ResizeSurface(width, height);
|
||||
|
||||
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
|
||||
WGPUSurfaceTexture surface_texture;
|
||||
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
|
||||
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
|
||||
{
|
||||
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
|
||||
abort();
|
||||
}
|
||||
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
|
||||
{
|
||||
if (surface_texture.texture)
|
||||
wgpuTextureRelease(surface_texture.texture);
|
||||
if (width > 0 && height > 0)
|
||||
ResizeSurface(width, height);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplWGPU_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
WGPUTextureViewDescriptor view_desc = {};
|
||||
view_desc.format = wgpu_surface_configuration.format;
|
||||
view_desc.dimension = WGPUTextureViewDimension_2D;
|
||||
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
|
||||
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
|
||||
view_desc.aspect = WGPUTextureAspect_All;
|
||||
|
||||
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
|
||||
|
||||
WGPURenderPassColorAttachment color_attachments = {};
|
||||
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
||||
color_attachments.loadOp = WGPULoadOp_Clear;
|
||||
color_attachments.storeOp = WGPUStoreOp_Store;
|
||||
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
|
||||
color_attachments.view = texture_view;
|
||||
|
||||
WGPURenderPassDescriptor render_pass_desc = {};
|
||||
render_pass_desc.colorAttachmentCount = 1;
|
||||
render_pass_desc.colorAttachments = &color_attachments;
|
||||
render_pass_desc.depthStencilAttachment = nullptr;
|
||||
|
||||
WGPUCommandEncoderDescriptor enc_desc = {};
|
||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
|
||||
|
||||
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
|
||||
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
|
||||
wgpuRenderPassEncoderEnd(pass);
|
||||
|
||||
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
||||
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
||||
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
wgpuSurfacePresent(wgpu_surface);
|
||||
// Tick needs to be called in Dawn to display validation errors
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
wgpuDeviceTick(wgpu_device);
|
||||
#endif
|
||||
#endif
|
||||
wgpuTextureViewRelease(texture_view);
|
||||
wgpuRenderPassEncoderRelease(pass);
|
||||
wgpuCommandEncoderRelease(encoder);
|
||||
wgpuCommandBufferRelease(cmd_buffer);
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_MAINLOOP_END;
|
||||
#endif
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplWGPU_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
wgpuSurfaceUnconfigure(wgpu_surface);
|
||||
wgpuSurfaceRelease(wgpu_surface);
|
||||
wgpuQueueRelease(wgpu_queue);
|
||||
wgpuDeviceRelease(wgpu_device);
|
||||
wgpuInstanceRelease(wgpu_instance);
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
|
||||
{
|
||||
wgpu::Adapter acquired_adapter;
|
||||
wgpu::RequestAdapterOptions adapter_options;
|
||||
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
|
||||
{
|
||||
if (status != wgpu::RequestAdapterStatus::Success)
|
||||
{
|
||||
printf("Failed to get an adapter: %s\n", message.data);
|
||||
return;
|
||||
}
|
||||
acquired_adapter = std::move(adapter);
|
||||
};
|
||||
|
||||
// Synchronously (wait until) acquire Adapter
|
||||
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
|
||||
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
|
||||
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
|
||||
return acquired_adapter.MoveToCHandle();
|
||||
}
|
||||
|
||||
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
|
||||
{
|
||||
// Set device callback functions
|
||||
wgpu::DeviceDescriptor device_desc;
|
||||
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
|
||||
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
|
||||
);
|
||||
device_desc.SetUncapturedErrorCallback(
|
||||
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
|
||||
);
|
||||
|
||||
wgpu::Device acquired_device;
|
||||
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
|
||||
{
|
||||
if (status != wgpu::RequestDeviceStatus::Success)
|
||||
{
|
||||
printf("Failed to get an device: %s\n", message.data);
|
||||
return;
|
||||
}
|
||||
acquired_device = std::move(local_device);
|
||||
};
|
||||
|
||||
// Synchronously (wait until) get Device
|
||||
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
|
||||
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
|
||||
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
||||
return acquired_device.MoveToCHandle();
|
||||
}
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestAdapterStatus_Success)
|
||||
{
|
||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||
*extAdapter = adapter;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestDeviceStatus_Success)
|
||||
{
|
||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||
*extDevice = device;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
|
||||
}
|
||||
}
|
||||
|
||||
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
||||
{
|
||||
WGPURequestAdapterOptions adapter_options = {};
|
||||
|
||||
WGPUAdapter local_adapter = nullptr;
|
||||
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
||||
adapterCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||
adapterCallbackInfo.callback = handle_request_adapter;
|
||||
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||
|
||||
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||
return local_adapter;
|
||||
}
|
||||
|
||||
static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
||||
{
|
||||
WGPUDevice local_device = nullptr;
|
||||
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
||||
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||
deviceCallbackInfo.callback = handle_request_device;
|
||||
deviceCallbackInfo.userdata1 = &local_device;
|
||||
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
IM_ASSERT(local_device && "Error on Device request");
|
||||
return local_device;
|
||||
}
|
||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
|
||||
static bool InitWGPU(SDL_Window* window)
|
||||
{
|
||||
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
|
||||
|
||||
// Google DAWN backend: Adapter and Device acquisition, Surface creation
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
wgpu::InstanceDescriptor instance_desc = {};
|
||||
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
|
||||
instance_desc.requiredFeatureCount = 1;
|
||||
instance_desc.requiredFeatures = &timedWaitAny;
|
||||
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
|
||||
|
||||
wgpu::Adapter adapter = RequestAdapter(instance);
|
||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
|
||||
|
||||
wgpu_device = RequestDevice(instance, adapter);
|
||||
|
||||
// Create the surface.
|
||||
#ifdef __EMSCRIPTEN__
|
||||
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
|
||||
canvas_desc.selector = "#canvas";
|
||||
|
||||
wgpu::SurfaceDescriptor surface_desc = {};
|
||||
surface_desc.nextInChain = &canvas_desc;
|
||||
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
|
||||
#else
|
||||
wgpu::Surface surface = CreateWGPUSurface(instance.Get(), window);
|
||||
#endif
|
||||
if (!surface)
|
||||
return false;
|
||||
|
||||
// Moving Dawn objects into WGPU handles
|
||||
wgpu_instance = instance.MoveToCHandle();
|
||||
wgpu_surface = surface.MoveToCHandle();
|
||||
|
||||
WGPUSurfaceCapabilities surface_capabilities = {};
|
||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
|
||||
|
||||
preferred_fmt = surface_capabilities.formats[0];
|
||||
|
||||
// WGPU backend: Adapter and Device acquisition, Surface creation
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
WGPUInstanceDescriptor instanceDesc = {};
|
||||
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
|
||||
instanceDesc.requiredFeatureCount = 1;
|
||||
instanceDesc.requiredFeatures = &timedWaitAny;
|
||||
wgpu_instance = wgpuCreateInstance(&instanceDesc);
|
||||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
wgpuSetLogCallback(
|
||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||
);
|
||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||
#endif
|
||||
|
||||
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
||||
|
||||
wgpu_device = RequestDevice(wgpu_instance, adapter);
|
||||
|
||||
// Create the surface.
|
||||
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
||||
if (!wgpu_surface)
|
||||
return false;
|
||||
|
||||
WGPUSurfaceCapabilities surface_capabilities = {};
|
||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
||||
|
||||
preferred_fmt = surface_capabilities.formats[0];
|
||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
|
||||
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
||||
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
|
||||
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
|
||||
wgpu_surface_configuration.width = wgpu_surface_width;
|
||||
wgpu_surface_configuration.height = wgpu_surface_height;
|
||||
wgpu_surface_configuration.device = wgpu_device;
|
||||
wgpu_surface_configuration.format = preferred_fmt;
|
||||
|
||||
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
|
||||
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// SDL2 helper to create a WebGPU surface (exclusively!) for Native/Desktop applications: available only together with WebGPU/WGPU backend
|
||||
// As of today (2025/10/31) there is no "official" support in SDL2 to create a surface for WebGPU backend.
|
||||
// This stub uses "low level" SDL2 calls to acquire information from a specific Window Manager.
|
||||
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
|
||||
#ifndef __EMSCRIPTEN__
|
||||
|
||||
#include <SDL_syswm.h>
|
||||
#undef Status // X11 headers are leaking this and also 'Success', 'Always', 'None', all used in DAWN api. Add #undef if necessary.
|
||||
|
||||
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
|
||||
{
|
||||
SDL_SysWMinfo sysWMInfo;
|
||||
SDL_VERSION(&sysWMInfo.version);
|
||||
SDL_GetWindowWMInfo(window, &sysWMInfo);
|
||||
|
||||
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
|
||||
create_info.Instance = instance;
|
||||
#if defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
{
|
||||
create_info.System = "cocoa";
|
||||
create_info.RawWindow = (void*)sysWMInfo.info.cocoa.window;
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#elif defined(SDL_VIDEO_DRIVER_WAYLAND) || defined(SDL_VIDEO_DRIVER_X11)
|
||||
const char* sdl_driver = SDL_GetCurrentVideoDriver();
|
||||
if (sdl_driver && strcmp(sdl_driver, "wayland") == 0)
|
||||
{
|
||||
create_info.System = "wayland";
|
||||
create_info.RawDisplay = (void*)sysWMInfo.info.wl.display;
|
||||
create_info.RawSurface = (void*)sysWMInfo.info.wl.surface;
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
create_info.System = "x11";
|
||||
create_info.RawWindow = (void*)sysWMInfo.info.x11.window;
|
||||
create_info.RawDisplay = (void*)sysWMInfo.info.x11.display;
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#elif defined(SDL_VIDEO_DRIVER_WINDOWS)
|
||||
{
|
||||
create_info.System = "win32";
|
||||
create_info.RawWindow = (void*)sysWMInfo.info.win.window;
|
||||
create_info.RawInstance = (void*)sysWMInfo.info.win.hinstance;
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#else
|
||||
#error "Unsupported WebGPU native platform!"
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
#endif // #ifndef __EMSCRIPTEN__
|
||||
8
examples/example_sdl3_directx11/build_win32.bat
Normal file
8
examples/example_sdl3_directx11/build_win32.bat
Normal file
@@ -0,0 +1,8 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
@set OUT_DIR=Debug
|
||||
@set OUT_EXE=example_sdl3_directx11
|
||||
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
|
||||
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp
|
||||
@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib shell32.lib
|
||||
mkdir %OUT_DIR%
|
||||
cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user