From 633e6e5105a3320e2caeb6b54c5af870b5cba097 Mon Sep 17 00:00:00 2001 From: hoenking Date: Sun, 21 Dec 2025 10:57:45 +0800 Subject: [PATCH] 16.Index and Staging Buffers --- VulkanTest | Bin 613304 -> 642680 bytes first_app.cpp | 25 +++----- hk_device.cpp | 94 ++++++++++++++-------------- hk_device.hpp | 32 +++++----- hk_model.cpp | 99 +++++++++++++++++++++++++----- hk_model.hpp | 22 +++++-- hk_pipeline.cpp | 22 +++---- hk_pipeline.hpp | 8 +-- hk_swap_chain.cpp | 152 +++++++++++++++++++++++----------------------- hk_swap_chain.hpp | 60 +++++++++--------- 10 files changed, 292 insertions(+), 222 deletions(-) diff --git a/VulkanTest b/VulkanTest index aff8aa9ecb7f1d1877530fa283cd502860ce97c5..3e95a9342dd7204a829a73f65d5d97cb49518b53 100755 GIT binary patch delta 105663 zcmbTf33!di_Xj>R_lj)ditHl0h#(?}J#J#(B2r6`5W7@f)bjt#d+%k?-}C=Jf6o)=Gw(agnKS2{Iq%H8?=3LbDqmAO zb5XU!I`Z1T!=}|S%(tQGS_fCR<~l-gv&_|!!>u`wqA}I<-7J@rJuR2@Jdg$Q4b;yy zb*SZzlZ)j}>QH`(#<;&X(Q-LbZ@Dbfj3237gBw|Z`cO`nQDq^(eAbP%0 z7vpBVY~>O6^j0ugfz0I(+}uL zST8~tZh7JFgBq1cXJj#l5NU= zHSs6Y>H8f>d3DinqAre?R}QGWo{|fJ=~cMDy?c<~F_MMm-EuO>#n$IYR!MbZMX8Q% zBS(m-xGJfb62be}`?0kj^J(^R%>NwUZyy(S=wnNv;;P1qk0PuX1sz{jmQw!g42CPx zBY;hJk9#(NTP`V|6-?Pj&QXt#o{qW0axa%ZiiBGbJbK zPF`#yns*K7zD}(?YNH3GI%9?GW?6kS06gWWc01dtv4_`L+^%h`xTPc8a*mOU6xn_| z!EZT*dN_ZJ+`-0*@1c&8&C<3yQ|uY;=R6{6E96()gH&kTqjWnoT-=5fYT4Qt3+)Z0 zsl+GFTZ*nd$M-q+_iHG#RkswA;xGQ#SX7+BOt(;T*P}e5N{8^2+SbNUD_w6e6(6f? zBAG#crKewAC+n-4)}P_)s`#)8XZZdqp{`FtUcW0o=6_ZRXInG5pNmgu`H9!>mehp^ zOs`*a&Ex}J;#~{SOmSsv$0{2u{yonRx%jYNC-^m&AeXMzii-a+R%D#!4~3^wEHQOw zBx@JS@nZJ?p4Zfwbz?R?&^LF)^#G@u!8-eGr4Vr`>b^%wW}RgnDgvpoFicOXg;7#i z#ffBzvc)v8lDn~@@_GKSYJ__du9dbWCX}lvcETTY@EzXJP~D*s?&M_nm*?<_{$aee zLuERQ&o(ScTOt(;t*}aDqEvHA(i1a~H#cKod8sFA@HAE|M_P`7#GgtG)z^kGgP2N& z64MrWjge^EwVg;y{gE8dKw^^hHj_#tuT>?5B(}Dxq-uKMJ}1IIs#cR0^3By6*un6! zoKEv=)rQbbf_7tdEu=c%?o=f$!{uTrYWs$gvN}^^E9y{V#nueJ^3tK;%1nw%4v?Z- zUy-8XzDVDunsN4p4wj<-WH2!e0xlj}$s~KhI;CIIj6AQBDM2bF@{~%$Zb~Zbb?KK% zTat>Brcm#e#)@RC9;cO}($c!99C|QbR#w}BXGt7v6-O{NmFTGHBV0?hi38U@mU;Y< z-``kK@*OjM_l-r5G;!hn2HgMS#S72kMnv;2rGrSJ?8Fba9wKc$SeIs!8pd30oV%EU zz}+zH21J>(3Rpw#tI{PpgE21)udNokE-%H z9&laW0b!G?!A(M+q|Yb;&r@X@d`f3gEcrMCVStLm6IqzcMWnRc$g#+SkBf?GTNA}qbzVHly;`lx>6bjw7pafyb%V+` zpwGtlEwU+*JfZO98hp8XkbxkZHZD+z<)^H@-0aMsdk692rur2gzHGe<_w$Hii)z>` zmUiP8^W8+s09u1@_i%QvRufHW-8WX$uwsMQ6~o;5z^Oj^zogwK)Cgf?UBvk$>Mx2$ zP)|PLrz-qiPbWLeSnwI15v=Pse4A&Sqo%862Gg-K{IO>XpZ{yHJ~+d>c*U`*-|*#L ze(ciMe5Y4X5X$BS7F02v`S*pevGf?-(z*!i{pJ+^(<{hu*men~u=i`QXYdK&?Yx(= z4aEkV4(o zqo8ryV=F#GKIs*u%%tCulYS{Y*D74sWCyKrK7v;BS~ua(8u`0iMnb9)MkmjHA`fpI z%|1TLhcu1}c}F%0L)dT4p*58dXKCtiY(-z(7ltO(o8M?WSs#d$))n{TV%^UyJU^$2 z-cIlK70FuFpEk=cZrO~|Rr%hnJ5m;Wgb#^{VbzcD4Ka(^{KNSXZR{$u!b3c|Lmb<1 zh|lN{8np5d$+Ew&IC0_T{7DYP-m%ml6D@Vr*6$fOYtXKkwdG6s=(X z!tfJqCq~_3&a6cRzZu_0-x&;O{b_xOM_h%VkBRz?%~ zv+hYsT?zZBfwt#2;`_2*MSM<0u&xLd76-ZUDV;Xi!|iLsfoar>C&X0Y?K_`gWA@t& zleg-!RBu25ksxS@$ZN=Qcw~)F__-Ht*t19ZJJ0r^+^hRx_H&`uk#UdEk#TJNLq0Bk z97}#IJ3z=x@ zn-h#fCrjawb96P!bKrc|>r%=Y9BpU*%-3J@jL`4ZLvX28y+rXd>c*4( z(&-7lKGBn&7rS~;Pg=?^Ci)wSt?d-U{XN--0yaZtKQrN%Nd0+=!K*e5XvxzT;-!H= zyQLe=#5J3f`4U(Z&tqXC{RMS)?j&y^OA_dc05`Xxpe0Z%ZB~HUB+BfEU(j};IWiu> z6?;m4d)GP-Ft{DHn2deVS=`&t2%Hs(E(Yw(2kLuhNhexe(n9U9Df7x0@k zYlzl%takpX{`Dv;E92uH?DWPn%*)BO8HPu?qMWwmVm;B*o;BhDGnVnKDPdx|0}FO- z@#KYgHZykX3%GeXZ@*tAb~>;&yx+jCtojq~R~F4GJ>fS8_TXdd`ZN7=zPzpdmCsOf7p14zKT>~IWf?EVw)=_ z26V|U+D90tF$Zy@1)VR0imD>#U)qYr?UklILx1V9)tWC$Ag%cW{CRY6CF!rl~f@HJhov1FV?p{l6`y`V>@} zYGvG3P4zLZTTIpTAEvtL4O88$6XSkj(fZF{v(xbwJ59IR>B+w>cKTk~+jctkx3}$7 zjH2ugeJ8M?;t`~ZvF?v=+o3>(Pe^7xiv3z$zHj~E`L->_Xi?G9y_#&^>I zkyDAf^9SxuJavRYq;|v7*4g2CcDe8r_EbD?%KT+i#t)CMw_F>}&yN_b7vNGpF$eJE zkbLXgaYOV8+rVpTM3^`mM4Pc;JMy283!-e-4iTTpqJ;578YvEEVi>kg7{r?W zVX;EHd(sNydCtU0_BSSt7;yezVhz6->8#O=obX5`V?_(3<`$ok)`E@S!uO@sewlZT!4%Z$Ro*FE`Qx-J5l*PyJ|Mua8?~$`z;9#{ zdlyUf@41-bn6=0z7gM9H{7HJKYc>X7TPcAkWPitQ^ERtCBVz3TENzqwcAB=^qk_M!(gjdXM>TtkX;v#Q8 zuP(c~nXilT;IroWvRYgD>UksRB~CMHxNkzP98NFh9P>W7UgvXgLtCGNCwaq+8Z3J= zkIxA8)`3~M^iVoTHbhO5;ahD;#TC9RqlROOY~%}L;pEMHcSew7qBS{cGrx&sM{6== zGk2Wt7u8xO^Noe?fEEX%55QWrgcRkp?RO9>PDQebM%H|tH}n1|R>zubBa78VF|_xp z*noq@4J^g{Wxg}U!X}&fw)uXY-L1*GvRETykt`x_V?n$q=NO7LwG?x*<_nbhnxgs! z=&XD&wo3LHul8Y$z^9um9d(ttIx4wpTjc+ccmL4S@uAFxUgh2 z4D>4=V`)-em#jRNbPQH|#~X_tFqyNF; zk7QlUbWYX*iQMLYeCY3ROs2rV58Qi!zeAz5oo{(8QeRqgp5X5ywb`2U05>7^sWs;= zUWk;*n)7pBvcTW*BWupJo4Dggeo?cnSvhF&=T^DO4r-$~@L=(m7RDx9D_OLO_eZgJ zt+k}dV&*rB9Ye8iEyV`Oe2~r5O?=x&5iD~P_gh$-?=V&6hK0^-vP{OYFYdz*UgNhGhu7bA?S;t6XBRc6Ziw(J9!ZM4 zZcAqb;SNxg8iN0gH(yf2aneSxu+dn!a3deMB*<~3H931DUyNk3H92V`-?zliF;ONV z|4|$HO(Z*6lLI$$yQO}PG1g?SjXVO$#xnVpv9QZV-UrEWYtp!p&spjh6ktt8gBCY{ zj@7klB7CE?ao3If&{Cg%)nqoXS6gOlqht%VWYgig>{!VGtJd|fXq~(+IrWz1dMM?f z@Ur^9dBbI%(SL8Su;?Un4~1@ywCZMc=qA>W7ufv2UgPe|{T=pOb6()Bk;=2?JjsV6wZ)qAAYX>m z8f#AYa->#RbLR3J%l#b}T63=3!0kTvbDU$%nzeyPAUVaFcku?^=i_kqt(%G43p}P_ zt-c7edl9hd24DH{Z>-l3(4$bE*~Gx6Z{Yhg=doJyN(-0U>q*vi{1roQ+HSCFWk>eU zRZZ{4R(0aOD+bw>1zt9ouJgGo##Js0OsHo1YBPVlBF=81Tr``?V|WvNS(l5|`1`z> zzN}8HE6?X+eJnTMUYv#rw8$Dk&-3+JGt=rzyTRIiELO4u=ewGgf)yEW%XN&os6DV- zT*W-lxPsV<2;|jV81Ciju!n%Pz1(9p3u@u|MEO8HlwOo8#mp}KlH3g`!Mb0nw7aUt z!ml!X3OdQv^7hqDxfwOe?d@|Cb9KJ83p&eKjE;Oo~{r&svi^$ql! zen4D~jqnv4n$aJ4^9{A>w|wx1jZD9u+il#*9M85|9RBOZ9_$-W-f~k5hE?bH zH?^l<^P)`~T}MI}OJHZW(2QK@P08VtHaB7=wfX0pyVGCz-<#_;xNg-~Xk4aM|1Sh) zdYQCGIc)!F5@=+UG*ha6k1f5czLvMti|20%cPI5thlr(D>vet0b2hSzF&FrsTcTK# zwLJ9mIL{CWAl;(cuNo@z;%T3INYxgfr@U3KE;qs(^@)91*e^}?c#uZ?5p&-l&U&`L$f;vpsmGEdgz zGaj^cgnibh7AvzY9NOE-CE9wo`2MZ)Toxm{T+LmgQNH|81pi=Ll8YY{#`ef`-%V~E zGM9DS^^19Siy+)OQ~ByIE;$SXcR9iI;w?UP`v5tW{HKCI98y3HspWHdzv+Tc2B!4ZB`!YiBvszO-Z@%oyG4w8Pm>0rp z=2fq@-P0l?`J|8&OfK%_v3U)siBHU{ZQs_5WRVGS)uA5^G$8_7_^43*wclDujM!QL^I#D++*)zzZGX+2&oxzel598OfJl-DZn3p!Vm3@V{<;? zY+oOin$7#~OQg5?j(s)gPyCyG1L!GU%iNM3T*HT$`?Jk!_#tx~hJ_Yf3n?Q3+B}jM zm{ijgj(r5VMnT<;6}9Ca!;2SX(vDsfG+`ZsurCyjfMIaqk1@sh$uRqT~3 zM|t3WGn*eGT!L8(_C*MP7#GR|4p-u_2ZH=wDuDEQ#n^T)!K9@;;2+LTImuc4UJo%(UZj(YT6ZYpZa#zgV+9ufKpaQGg$P7I0Z3erxcOH3$s&Pm(ldO|8y;&^o!FQhv89bXaA zNo}i>kLh#NVRKP$w$(YC-#qS7#fTzW7OZXUQYbTZhZ0qS`+Gk)ufV>)g7Cnuv{d50{1^kh7%lFePe#$HG^ zZ}D{t_qnnM8!dVx;}se5-r$SAZVK=g z+s_`1E#lhN^U(AEwTIsKg0|p1Lh8KS#p=IO+e3eT&b)3ZCQrITD?9$&>t(s&FK0IN zTUnG%$`TK|(O{aD|NOfrIu>ZkfAW1it#={QBKjO~6vU;k8dUCpxxUWaf#rlcEZMNa za^Da4_=O+c95lbZkz72)O+QrksD{h(igp!MEc%#aeR(E-{}1!1M*~zXqwW_qEODPy zt?*2q_~R=5)8(iQhaU5tuNPBSxBp?C58;yBIlk5AaP#RO=Rdy@Ls|T39`n;GdY%98 zr@CxTCTGP#Ri;|`m5+13@`lBI9Wb7mfnjkK+qkKCBs-qT57qPGZY87GtV}+qWD6UR zDW1e*4a9h>9viSMf7~rUM!)0B?)(_K7hI_8&>haay$)UfjJD&k`_!v-=m6`E$B;8( z;2k=juPzVwn2f64T!fx=hF>d>VJmRd4;zr1AQ^4wvOms`|HX&V0{-s3G5Wbna2Y$p z{QkX8`pmCiZ7*e0)@!*L=VAh>nE4~C$s-@MVn9bfpzQ#NLa)Cc|K69{Azo=sr0zSh)d$xD5SqXH z@z-Rgt=*qH`ATMo7riaBUruT=dv-#TSyd?wcsyM5|b~lGh*9 zmGwGiMyJCmPk5Tm_AJz_;M!5{@@zNz?zqdF1zIgDkG!-cKH*tAk=dUb*urC4okGe=^0j24h)JP7V!n>n3;O1g zTr9(aC|p4aruj26Emc}xgQM^Nk+`Iz;f6?SSS?R&JerT1U(`1=J?8x z4I8vT%&@1?tnUKzZhPuO=|OSMfo9N8MNdaMlb#dj9BBd*cWy{BUXd*!5RbV6C-3=Zl+T7fYwuC}v zh;f`Y&k-}NBP{Mzle)3X`^CVT^fdeWpd2Q8Ma=c1!R+*09?=Fh z`_V`A2eH?m)@F_On{WD4Kgvd>i{}BI}g6op&j>?aqVS{j;=PF8yS)#VS{eIdy3S{YdPnOFPng;_tfj{VK;E zpmHoPOsZXhBT925-Cyi z9hNj*`cskKp56(aJmd9&JODAgIglI7+ALIi?`s38dDQRC;!p=VPvkbH%{(Gd*PEmF z&}`X!4{HJkrZa1f)qR%Lwj5?@j+L$yCDF8oWkdaGC)!DDkEV_3b$N9r>$OKZ*`t)z zm~L^f`C{iy`nh<}oK{7T*7v7<^(AOobBX_(A>FKK)tv^g8Tn#hcls%R(5kw)5J2ns z8EpIoLP0S|>ejgP3~7S#&2Ie)*+Kda+W7-0GbC=?9`~MZvH4=D;K*Yy>p>u?$I%dx z6G(llJVj}3{4hrM#MoBUAKh9eNp-OU#QjHPeRGTaH&N0Gik&|VeaO2Q!t7>jW(O@iL}jT;{{Y}reP3Pl(eY< zTZRq`hx3p2fRRYgq$&oHd*(6>bYQ*V&mVpD#XzDEh=_T9O*>OEc$)Ee1_ku zrZk!D{L(Uci-4{)n+=_!DOck!#m%mCAFH=Zn`&FiF_BYkgK4ky>heyhSEp&Is1r|X z+b4k=IX*nW5F#S=OfS;oX|pp$bR@+nCWrA|Sq*9*2l{Mg2gLAHi{Yh?Hl8HndeA=l7r4iZ{oF)e59*~4 z!ahAW`1=}s0Bp{r@+5S`7!)FW6KEKnEZQevs+=s|O@Iqa6{ZCEr~&593G{nPe-^V7 zp*A-~Q6d%k0$KOrdd)=UJ9G{EYKj@>pgZW9m?)+t(H8m_U*I+tE6rzF_=_Dvv0)Hmh7LQ-i&JSh)At>V2_kYD4HQ2Np=0#@ zw`#1qnUjaoQp(;PCprwryq^6Ya-AJQy~VlVv=N&ZWjHFZ5}Dc%|_s~aHQBWn{HuaM~e74 zh!)Oo7Nh6TP}Y5=ud3(2oW=%#_65bLs%1rhKMy)sWZ>4-6Dn$olvT8{$XiSwvE{?XmL;(18NxgI}aEAm(rd3qeC!sMrT9- z^_J0emNZQ4Tt-K;IYZ1o%jrDIW)3s2`&fpck;BZVGwBA#h76NIVSkVFDEX!bX`Ca6 zY6LTWrb#I^i;mKF8D^0Ziy3Bqm_Bt6LVbF#rth=g z){671=?eDFr{*D_(s=6J^%ILbel1cp|Gb7Cp!V)4D@CEikW*HRo9pNyHhPU_I@1SR zM`^4Dga~5}&18!PiAya2pCns)Mjwj$yXi=lo@{xxy0Dv;v6d^XuKE5R zxMsKhnrl9iC0+C9{F}j5S>Y;8Jg3l>=AI7@5I6VHE^Kg?Hsy;GW^`}~UfO8If)Jgw zE})YUK<_HRM4Tcn7SQTdhTy?bd+LX3&J}+Y(D5!)amhBZRq7|k71Bg~R$sJG9N;U8 z3n^yila?v?f2&0Ne!9=aSt+q5NjzD_y6EepgvgAczD%5up>=f4;uDrR-!?;EN7^<+ z{~#_NKvX?PbUz4-FF~uP=y;J*M2ChxKt*bZ9kcT7F{!mun=H4jczaB+MicW>gn2?7 z3!xtKP}iG-(siX4nQ`X|XUI((l*#?9>NZk>;{A<9`eAy!$}BueONM1=JzexXg6Lp$ zKTBx+;28XbJVcglvP1`V$ZHc~W*?CdK=Zq}s5kh;}AbKbtbSi48jXEX+A^11#r2PtQOiq9N+L&ko%nU4){S+Z`so zPD1=l>p=sj_?d!q={ToD%7*6pnWpr%_(oa3toK))!#14!PrFoSw&SPrjZ1=MLiuh= z5E{INE$U;Sn=;77%^S(ZCPfy;WS&ZiBul=XvJrW)(R>Lnf+zlr;A$bHSc)S%mRA4< zm4Ayq+k_+E%Uc5mWaF}qM?EcdEbcRoWZjng;MNPEliaEC=Ff1y<5;h$#5euC~_jOzH?|lbxPBo_6C&?h5MB+lWH<= z2$?rD7S^F;;yv-1kHbXL+*Fz^2$6?ev8oJe~J$WOKjr%c_T6XbkNd< z?E07BNWR9I_L}@Ma8_8#4`P7&Ys!#elOL8+rTjX`ZlQ5m$vSH#jZx+{POsRmYvP*= z@vVpW?9&sEC=F{Os%8=2)S?&7wO-50mZLf3kwq4`pN2&^T?H*j5>U5it2&^m9N zn_cY}(yj34E&Rmc->Gxj2;`P;f5==?pCwxqBPK^?y0x^8)d9#W*Yssx8MlFTAFOy%gm6WmKn0sGGo_JW?qfVB628o)5k7@EhEmR z$2r~LCY~*(Zj~X6htLM?)oYn3!vrBBJ*by|DduI{nw+*d2*%}sZRzqbUgDpNG%(?s z^gC!!Y7ByFZ6jT#<qo4{t4g#4eYyUDrl<^l}T|? zs9+E(tAxMXx=P#b;O`I$$wwXOWwbmnbD2k4=xv>TTYfM8aFCxl^AbH}=kWyu@TR9- zu}q6dJeR!kw39%LaO$tY>ds$Z!ytGP&HvR=HkWI(+35WDAB z8lXS10Lqf*sta578*OHXam~a7SIlp;ua|wGbjTM1Qv)@Z28VoMXilK%w%G9-ZKvKH z0*9yF-4tRvD;)0AX?nbJ8Y(jG)8X`%xOblppl3w;2lPAotMGnEYt(Po-C`K1KQC~8 zsA*#ti)u-gJ0d3mY_=W+jl*VZdolPSDyS=p9?}SpGMhT9S{ESb@AMbCSKRv@BeqSr zmw|8*TSh(g!#=bajF?h}7Y@9-%af=zzY%=T6~q6g5C6N~4&vR%beexzoxyPx;e(0E zk&=o!I7034KMXOxuJ8@|T&JIS{+N2B)xpB&A1q1lC=hf0p()_GpSbxC*6hlUPayXVzOFSsYLwqMut%CMh<>?XQWvJ7q}JMdyi(kPgTnFBht}B>x+rml>TI{ zV#j7umYpWIpUmy-8M0MPGvmFaC><>^mpHSLR9`w9g>3Kpi775@yM8w=apSik+z@Fm z5~{KbvI_Y!@aOHUX8WmFYhX=1&VmzCwM}<$i^^Hn;uN%lTW|{60lWnwB@o}^ z_&_WQWZ(AAMoD#Jzp1PVQ>j){LYQflttJTgh&;$>`U5PoU6q?r?t#eLs=55lT*i}wR^UX zX^0~}T_WA4bGT_`jHNf)`2|FYzf2O3!`P7aGjaW8ufyt^uC@HXdp!$zZG*3#xScH4 z)?rOse}&ts7?NbwHZc^`HJNQy|A!d*iE81@lO~8d;cSXm$=Rd_1!nPD2MQ0c5q6BsjrQT{}|Q^VL}zIWhl~4 z1_V%60$D{*68r12dF_wNsw^GK3oMT?1=^}Yht^xCjSbdm;~4VV##KFNyI;($$4>g> zk%f`67kPmgr=ys_(8s)?_ajZy#Nhg@OZ02^Z`tm5YGg`5y%fCVWZ+OXv{jy?)(&L{ zlfq4+q&}lqquA#kAw_&1ij9}q%y)-(4ZKEHGk_gryC>2@HHMeAy z$MuWxdI`B2IH!0fUIIYRlO~F&1}rA96Y}jvJ_OAbCBeo*yhMYltq(nL!83%Z0X9S@ ziOmhzQ!jn=tFF0OyOtVl$`OT;tXpm6?k(Hh+-9baaL7vQ7y@7?bW#-0qi$wnL$-&q zO05uq;iDT}BU$bgJ}!EMIj<3GMcMFanj4*hanKfaM@f)*Jy0xb!fw-gVq!G=i0NC3 zC(-P2RR@G;@?ky~BV<1}TD)k=-qq(qPTCugVreth66f&`H#Kz@=bEukS)=Co_Cq)? zZe-7wzI%#Qo~pIwfdX1vjuObjgL$38^jBuV=|}cLe1CX+W4Q_J%qNU#rcXhW^0J2+ z&#Vg=^Pj41c$)KKSOTL11&w9@cw|g|+og`4thvGb3z}MZqub3B+rd52FU8vS?0a@&ytXDH+I3_h`ke9L>F{0}D|U2b8TxTDnOcVi zn0s|%U)bpouM5_LU4uWl(Swbrw2A26lhx?_eq-o9Cf&hO&$C;bt~9jz2|VGfmwF7J z2Hnq-A=3xQ+g93-+$F^QT%Ei1Jds<$II*iIYe3UPNl(_7zAKt1GXECWux=;6yMv)Y z`){wU$DzV!Gn4VjodH{4w5@DCzr`+|%@!*X*$VoOsPztezxT(;raGXzjVz|G@$4L9 zYH#BirvE0-zaX#8x8Y+Tmf)f(DZDBEc!!N)l^TnIz1Rr)n>f*n4aIg}o!)Fron0tY zf@gOe0;`Z803#-1+Agnkgoy+*?F|@dpgTlSZ#JlRIc}-^bwFDB6OF%|7}MrRt4uBa z3mJZ?wHg>C1$B-lteusf)%l@Er!6#AJ@?mwbdn5}Vn& z_Zy9Gk9u7=PPWGXLpVFcktBHMP2z_n_7mMH3j3kLVpO2^#;8{4)yDK$18Z;oqrzA* zu|FzoW?s}^>gh_ccK~bIdchktUc`9G-DOQanQcswwi@Au-WVAh7_n|~P0GAL&Al%YtrH?JLvSQ9h8_i!|GN-P`B+S|BiV;ESS%X}MqDDr>5)`X>4>`Te4aYIF4!er?CPI=!MV(3P3=J25PeRJa++;GVY|p+J zVvd=Kqs+{Ahk#XN zaX{3}WbfcG zUTqbK+)tRngQvVbpUpt~@A$dD=>KXyGh!l<4>4bw=N^O}i(a2HH8Ej5>SyKdx_Q^FUts>@r$2_@VR((;i6_$RXkCnm0+a!b7v5yYHmU)=Z#+;#71;cosBaA)Xglid-?-L`kEvO6xhEA~*h%l#VM zRR;@i4(^kl8h2?u-sY}BqQ+h1Dal?oKCIWp_bxSJh47F6=vS*9a`U$(>IRZDc>|_KLdzt6}sIvA?kf=DhDD zcg7wXcYWeD?nYI&a+hr0^*_noAaUagxLelMD!Z%TE}<(TyUYseWj=nDEyZbHbI%{y zkCg2(Xa|Cq8MK2Q=CT{Cna;zE%y06xuB#@w;Lfk{rkTZeUA51gh=5zrx(8jAFsmQ_}o*Z(4yRT_0P``u$f808LfNyUlE zqph@;*yXINE+#akWn#?(c1M4$J%n!jb^^QIQS)JcI$LFNS4{k!b!AK1i$lM&b%A$q zJ%G$lG?JW2@&QTaO9hqbK+uO`b{T6FR)ov)cxr$f!Jo0>GSb>}pF0+d<+HlM%XAjk zxUqRH@vMw>bXbQJ?zrs{-Tz?0dOyhzR>Z~9KbW!iblg+}kN!x@5HC;$9&XfB=!t^&bO#}bd;y?{|m-rKT-BZlMO}bp- z25j*VarAF2OGUP^z3Xh={+RXDu?fw@iwc$#jA`5wNyrD|7aj5CyZZ+C1?ti2DrGA>XaUCX;0+E0&q2inY&i ze(61Nx0?Fp1787XW6^S z(XosDwEUjs#mDdvgb1GCOA2$^iRVn$pBhC!oz6dEhP~YM>Ray3EZdOp;|!imyIa$1 zk(T2rtLxaoyhW!QVVAfs6$1-v&1vg@kOUfw%(k=+X>ViEPFwnzpO*g8md-%Brm<*? zE#20V{yfz@&{3DjSbU6(zl2v6U5OXI_JW4Xb}(LkLa+xkg%49nIqkFzBDZX!(bR4TS1sVwrqfx z$GyTU6ue5os};OX!5b93MZwz?yi>uu-1$$Vq#sB*# zH~bVFq~K5mhbuTj!BGm1R&Wai$0#_io#OvHC^xz&I9|bt3htxe{t6zb;2{bgq2SRr zoJKMY<7^4wNeZ5(;28>@qu_Z8UZCK`3SO?@6$)MjZ1w+{hSkcAbqd~~;4KQ?rr@0l z-mTz$3f`~aL$7d};pnS`;iQ63EBL&EFDdwng0Cs~rh;!N_^yI~)v)IOGYt=w8-FVJ zv4Wo{__=~vdz%$x8tfG8s9+Zb`@Hl4nFhZ!CE==M@=&mkg8dX6q~K5mhbuTj!BGm1 zwqp4IOhXIhMvQ{v6x>0yn-(&_=8t_a1KSQ}ON5S(H zygL&0+t z%&Nx{<;JVU{A6g*GC3lzNgC5HcB{xXqiSfSum3SOjm@E9=bI& z)Nn#a%F$>tD#v#v$^9rsQoX^8e8(I=-zfhjJK%={ebQt$`O}T_ku?l-J9ugbIty)% z0(}o3*jxy@(2J04&EF}<`R+v+HM}!jX<+Lgld9*u$+*~pyXph?tq45;TIc0 zOIKlVd!WA6Xc*M61`UHA1Z@SnXDu2Awa-DjX#k`4py!~z`_N<12?b~XG`SEBfL=d< zo+Ri<-eC+0Xwp&S15G#v$$&mOPRMr9rzcSkbm@5vX-`P(e_#MK`+GDDdi@p}2Cerq zA*rCoyM&}o0hskGc2Gcb9}sd7H0O6h&VqjM2O-x%C;Wx61$C={XeIrZkVveEhe6pp zftG3bEU(qmV z(nE|fXu|IhHR#p9AZpOY*c&`0>Az?gwEQW)E(mHQj2M!@5RM=OfEMT&iA;k1mjf8( zjY{|y0_dK~jEn-k@5smpplh5NSqPenFEeI?mVxGieo&o}Qcy21M#@1a_%Korzag4b zlaX$qh9Edy(6gb8OaLve&B%OEeO>Hrfg0;GvMCMVYC}f$fDVI~J`OsiF(a2jM>S*Q z5oqHUjM(=F$1NH01-%-BhCq{yjI;vvjYET=Ye3h4X14`{pqcF%xd0l{k&!!~Q#zqO z&0RBL1%48J)qrofoeA9U7Hj3MYF&`qF`#~CRAEj|IpL9d=-139*l~05Hsj0J$wdesy*B;=oAMGCup`a6chBa z3-oI+?BC4*ZgJswH61w&+NnAe5p*GFF=&|^{y;~$!>bL^5&2Wb2GBBp=mF@O05k@g z69`2GJr#_5py?sVKNOQrq>coD_G$=|1I1OuSkF)i01*rN>%!9l5Ogi9LZ}S}-%?3RS>f4U6P3;IRXosi_)VVz&kJ=N~tOFSBK&YW3AxRwx9R<1u z^nOP?kWT4D=)z8f>;b(Fda5&ej5w5ZCA!G2=y6vR>?Q+V+y|Y|9b)TF*eS%O>G6c- z#ADn+%R%e)Aaqs_!t@D{QUZc$&?Hcj2q`6^ENC9+_FiDBH+tWfr0MSWg>objT|hrn z*pILY{SlG%hqyuUH4NRF0T_k>kOF9SGNF5tpc6{rsd5;?=lFjmw|Z;bOLC?hcK%TF&qmBv;PQU{Rj%Ukmyb=#Mmu@ zVlBp4FD2~%A?$wOqNx79;h))^#YIt3Q7N&|$k518QK_g%v9PEp$*4%NKvB_9si>&M zLPJAELkA5Djg$<3p`nsuk&&X2p`nqXl3`JiVNsE>`h3oQKi$8s=e}OgQ?IjU-{*YK znKS=(cE)8UHy68LF18EgZOfIdb%nAA=V4Csl&VGEg1mgCGMZN^d%!AXOI@W@)2rAv z^0ABOV|UJ1E~6TVT#a?T8Xr2yD_3KGUW1dq0%fZzKu51Bqv(gQAC#^72du&$v6Ozq^pLkB5B>@3KjSAXmR4*` ztx82APeGplvocC?Lez%bc@7)hIeeTVuSVX8+-$=-Y{LMMS0OjgV_@ge&u_?o!vKEA zV*edW3waZA^#`_>KQJid&3`Dn@1Izje_~pH;`6@}Z#qyAfE!7Kb|_nR2j&>>tB`lV z8TgaTvcHs9#b4O!|5mp0zp*$wl?v@dhsdMd%2w~jzV60`dl6gqMJ%0*D8GbV?-J%7 zc|P(S!?4%lsz`{7Y1A@G}j2w26}$(=f7-M>z~5-GP%8Ag zh%cnOVQcShsGy$syV{;8_cc_4uVJLQ@TM4VT6_&#G)@Hzdl^O<@_OVg$P@Y?2&aaH zeGGdO-Us*@wp5%VhW9m$Xq+NuBCqXh*y8$OqWy4MfV>2G9_|ENhf_!8Zy0_!b&N)y zg1i&C?`4R;4Cg+$1*j|Ja-7uQO*Zlhqh`HLZB@Dqi%{7LRaE+llkOu`DI5ZnZaj;>p$NQFH zSO?b{Dhxl`O}`fR-0}@EjGPe6;dO>lejP?W+%W2gG9)r-Y$cJ)v0C$iqgU zeiY_#lwr#V!&%yBOlUODCr4wcjKRsz7{h2lUNsgoGS;yBhvP&FKOSyHo_7QKy8*rt zs}QN|CId%Zmtil6!0B3qVYDLmxfLDVidAwe?v9E)bev&N9f$2=oMG!6hxIoe>wP@V z#>Qj)A`gr*jIb!2`XkRl9y`IX`Q45=zTL0|;{+P_P_$J~M1H4XtGdfD8gUXG7K5c0 zgH?yT$`xbS0`JBuxEmcHFGXI9JPJ3FioX}9d-odlI^>-&?igoFjm5gZ4;|cx4v^R0 zhjn>B)-BGy^O2Y6e3D_SpQO*`4Z|O2<1xrnk+;WTi+=#|lW}cgvSBYn?rM3+um?SC z*oq#;;(ORI+K>l4V%YML5^$=X|EOV$pMrHY1xpEe6LP<)7~E9+5yn(3u|&fNOvHeZ zCn0Z~hCZgDkH-vq%42B%m|>JZX4uTf4ORCz+9UT%LTnONOOoL-RI;H$lCfdwd^+ZE zI<|%BhEayR8M%qm|H2vA08^{#MM&k3B*z@S@1=PKOxk7vv#$1fN19{9s!x6m*6IyB*KCc*Ea$mvRiwAwDw-u@sQ2^@c5PJ(lEp!`_06 z9*M7GH-FtwEy$g3VCfYZHdpipEar`vn~m7I-^5~k6QeCgU@<22mSOYXge`fq;Rx7b z7-3s55uLw-_4*Fx26;{?)^Dky3bqao?%NX$6S_U5hD-TVc6q$U=i;`gPj=6E^H{f(7_(m@4?*e#oX>S zY*8N=D*h9!zE2EW_p>j{+{V8lTr?E6nV_W$KTmCngyEB-( zGwARP+9QuSYuNM7Vx6Bgl<#+jJ?1-1@H@lS_#HkEzBh~zTuO@n9)m=#TJZVr*MfC| zHz~-Qe!|?gV)yt3`{ys%s@rg|IFE^*$8Ps4^4|^T>Wm?5`V{_ ze#eH3ycN0m2UgXehLQItV*WJj&JM$f?l5cx9ayD!j7&PNRh9gO{lDWc!+}M) z0p#^M{~HtPG;B4USln*IR(a7d8ZKgEx?~tpmkgDGyz-J^!?`7%lwvcok(VH^L>_9h z8BsQr+ido7yl=PJY*BVx>o9Fbpo!~T$cs&zEyQ6nA|1F0l8QH34xI9P*=!|VxMtvG zGsC*!nnO1P;R0AkPc-zknHl)ww|ZRo>g;1P{QPVxv9HY*foJFB_OltK$is2}{lxw@ zRf)VEdFEx95Psb4f4R+8j0BZH!0&_JchCF46&Bz&o z3n@cw_Ozk6K7qVxDE_){7-n!776<;bBl)Nwjq)y9_{xVDR|4Lo;!TdB@JBmJMc9-P zi|};hImq*I*`N|Fi%ezIm^epp;Cr1z*`mDg6|0M~`8aU`<3xMpwN8As_QqE(Z+zuK zUV*$8d1^OhFYAUgtZvE{;e)d!TyOC2j_;M-@%=xwJHD@>z}Z8oupT%qMjqM|=Yc)( zO&58bFTQBvVnlIoq&`Z8`{6qxh91@z-|zZj!hMy^*$>~A`{CO%E=XkdS9bixr_s?L z?fvn+&>!FVFTS*g>SG|;ae&$ zJOl^f+iQ?Ae6Plt?A2IG$m50}ZV0}hB3IYo1mYSjkzmvX0$ufw+t1uIF{t~%7*I;s&xeVaE-)QV_alN8;Qmvu{cLzVxw@rhP-;T zvOC9M@s7bI%o|3RgB?Twn;gLD}+d#QDI@ z*d1=gT;8h8{P7rUlrmHAP-e?SWy`+{OYI(<|Ht2txt^qq$Vr$8@_;y;a>ZdTAHcew ztW5PVmJm+Gn{evgfsG|;3I;G0>vt;FKTfgJ5;392l~MjU>XLARk%T3Jv+06lTrWc2 zjvRLzHDaeLulVUW`@#EiR;XW;vP(hOzKpMg0_!Rb?qQb9A75k3=xK;DEreHP|y z7S0c5V<5A!RFF5!R<;0awe_i(0P=`A%7~eR4G($U9GrsB#VVPLRf4<O~^xWvRZ)w*SateX~V=6G0yjcaMkunM~;6l7#j{(1q0l$F(7h%8~FyIXs z@CNj^5$!i(z{MDFF$P?W0l$R-zlG_&g#mBEfHz?=CgDxqCX8}3M!Xp##*xJNHb(q5 zM!W?hF2#sTF=AX?h}nt`x1s~&W*G)th5?shz<6(N!vwcsz_{p8iTBOOeYazfNEz>8 z!0+LGIR?A~1Kx=N@4|px6&NwDOw?AO!}rm_`U@xBTJuEKyn!hk=ASf{xukJ4Mq$!BlkUsQ6gm@QnuJn(Qz#%TC40y$n$HlRU>ai-ibWqGi-35VUCdJ zBac3;Y@LU(2Yjwn#^=h&MV?oOUG)g|5?mQ6K;C!+$AF_K$JLSIqgeknc+-f2x_V{z zJBH4VVOKhi52NGCR*gL2OJ&dd61(7+H~=BfZNS#ufL-k?Oz10RFZ~J={R(@^*H~g- zD_dYAmPjK8gxq-&pPnbN_)ntjlrrK@pOOQno^*z;CdKaLFb1 z3_gsI`+tkw?0esZ^}{7u8gvF!C%0!p;H-col3>Hl`YSWC3gKqbb1jJyM*5S*xDZk3FjO7#UE7w~ClB4_m1S@7artK9+dTgB&BC{NPhP|vU+O*H z$Q)nlJ;s-MPyQD3P0TlY^1v)ztN+XR%#K%I6^u^;oyRfHW?rUq7b<+0NWk0px~T_} zosNc1Usb}6amL^&Kj|qC)WM$r8aRRGM{F?qNsv5}c`EZ-=Ku6>fAYWm_tq2qX99_y z3cYx|=64T7pRq`tUP`^Qx|bPhRIMIo&Ttjlm17^$uSkBTazr6LjPwH1CZxkiZAg9& zB+Lr8xh^>Zr6El%Zf zB;n0cq)Mdkka~D4M+DMzBz$9X;2V>p2`Qwja%3V^BXuGLcf(+jUPRi2bOy=SM>+09 z!V@qZr;q}=D@PjAex%+#lp_VH9O*kG{H(??q^Ap=;LUWTY^04nl~*-VGZI#TR}j*j zNbyKXNa;w~NNbQbA#F$6hji3eIZq*l^is|gq(Y>_NM5~_vl6KdX=ESeOh?*+6y>L! zCy-KIeUb?(c?v1IzjAIz8se{<`;o#gQ_hV@zLzWKi%4pKa%Lc%LCOzM&N?KY zfy$YNRDpB?sS_#W3dA85BlWvdIqyMQjPxDS>w(Hyg>(+dHEa+nkt&edk){krBc!89 zp;swq0#Y8*PNW7TGe|kF2vY7lk=7yIel>EWCZsEdDEAbkBBWNNsB4rv9cdHN8KmG~ z<$e~a4Cy2_9QluY|`dzEsuOrz)lsf@wIZ_o;^mXV2$u?ZM zmm+s8QSOUKkvHQ#QY})@Ez11@QUg-ht;(H) zG&fSYo#W8wc=R_xxjS!H?u=**av}zFC)(VF`WWRt>cY#qyHR-$7T3MX-6K}H&mmRb zhmP)7?pc$R`<6K6_I*IPJCN!oV{tx+fyHCdK7`fquyT)i1dBdFxy?tFTTQ{DM>;+g zDG^I;8v1=qxi5bls{pAa2}>Q!tK5FCVPh-A z%&k}M`LAQpMasQ@1LEJr^oo@`6<>DTSClCCuWzH_JD9_*%6;Rz%Ke`*q-|I-+cCj% zEW#aF??~HsVq4gSZKeVn>-&h^jR_+)?NRRCl~^@v%so=S?=Vp$pYO4XkcyDX zkWL}Bey^PVE%+Qk+TNmeeR+k~RfhFv7xRs76Xzx+XN-Gt`t;=a)+6+9({cX5o=BCVqJNj@i@t z>j%fRDEKDQyk^(LA05|RX6-b+23afYUfr#SI~{o5h~4XR%h&X}+WMu_(YNcUsq8Jz z>UD$HJ-c?8UMC#Z=Z~3A-&yxentH>u)YK;)pO*f_{E4%yq7*a8K5Nn#>%LCM!2i4Y zqZ#Jqp6Z1&%z+rgwm7rTmD3h1m^owaxbV5jBSS++goaLxy=&G#Q=B?!?5=rp&0D;! zy7^{rv=|X;_OpijdiAs3ecHS*6xSQ3ssjD}z-|^?iI=KD3cs-kQl?q{9)5J8iaz$i zYeB75mtn5%Q}~fq?g9PU_Mwkbwh`94XUr=t>lt&1v!q6s*Br1udB(iaR{r%aJk+C? z(W9YM7w3PEAAYFZmR*6*;m2$ftD3uj<==EcAK{PBPo9>Z{I8X?V8Z=(-7_hD)YPdX z#ypk$xM$hiGik*CSXNj+6V%==R_XKRMBk6Qn5y(g-DUkxx=X7m$GqI@3uhA6vz52q z(a+~Ar>SaNbwtiD)}BoB3ddUSuo=nLk*l43T?-~WrQYy1RpIwKps7iBF=E2~SUY2) zlAoISc(P|ap;O0>dva!KQu6!>>KpHo|DW~WqqnjjbZ-slQ}_0idbjIHyzam^h!N^w zmoRnOIc9S5{Pg6EfRXAg@A2wq?S=OF#}r!L)*+X9YtM?c zp0)agel1&QxBRoriT2#}b}K2%9Mz*y_n~QT)E|MNAt0CKN4ahbl{c=luusPOWi5_z|cQ|%e}3nC1zCbyjL^}OZ00M2CVE>>~@F0b##fD)Tem8 zE^b-o30Z_n>_(CAIWD&zUuq8WZeO9xi_z1vrDojaxtqFTL9~TpL1b;#HRWgZYu(1K z*56Cb>-=(8>SfunUcYAjtgBjnu_9hEpK)fnA+va;wf7Zsq<1}@Ux2-Ov$xgpika!% z(5^$XUhQf5%CARj!`cU2v_+*H%xkZTH5%OX*1`l zvTL!a;KyNDy$AGbmfqaW`fv1WP8H5SY-3WB=gvq^!7j5nWM;;MnJPB~!MpV8O`jMu zGi-u&+oN9nt@h<+-`+Jlv3kuqRGMbd4jr=QYVZD5=s+{jx_^aveYbWL;v)`M0BzPA z?>hpm(iP?qzedmGDn8N^E&fqAF8|*8ZiV@!v!z_C@~HJmp80^iYPXLyaHTn+XS1h4 z!?(IYU4@S|Z>71$yY!4^=^h`;ca^!=ncJe9X8&ZpzRG;jmVee7{Hpo9y$RJDUqxTd zJAAAQubNl+WgXScT6gQ{s`vG4N4+&7-yC^I;pbXeo|=}kp20QiB{FKN`ef{wsp`|Q z=pO@Aw)^jz6gG8|Ix=?BsHvX!>Llvwakn95A7M=kGW%G2^Uc+^>}D%&wfUn-yhTkRi~%QCb5azF7xY1xPR zHRl!mT71#!Utpg1&N{4BSm|Z;T5CSjqxdWAHD=|H`nBu}Yr{Kcf6I3a_M4B^nu$Ft zo3MwQMaS@|Xx1O?V%@hH)n#kVURL}%^N}7MUpY`wP^Vu@zOX)8XJ+@z#a(I8k#OU0!^jG=m~?yCJw{o1+d z-yN=5Z|>@uyGRec>Tg|LbMfER*{`G9igmiWGtcw->c8f%-y7yTJu3?J!pnO_zgDmD z`Pck)yn#vQmEm7~%!0S|`phq~>FQu>MUgqBXBMsyV4m@>Os3gbV@Si!ai-Hceazu) z1#K{w_>??=?Y9J%XU)QUC7^DDIj?6?yPn1Ta=jWlwtGoU-U&x<>zR${x%rZ===?#y z*0%h+y62l1Qgf$XOoiw4YkjM!TlceWXms@2_12r_2%~3ptNuKwUDXY*S$W-beX!O2 zE%T9{EhjxSUwUeevF44pOjpl_eV&@PJvEzI^S~ywsXOASsq)l(z?$z-)1&-2K1s}6 z{PP6%qk~rLW~}Dx|Nt8`Bj|t^mESB5B?bg>(gyDm6)4)W*zd> z{Hkhhk4J^-(Z$tm0H^tc6o2jR2`{ z>e%d2q5rLL&sJk?sS8qOPEY^Wmq}d7-!yyv|5Ey5D%Mq&o_1BX_2_@hB3pH;Rdm0( z(#m_+^fM2oV&QJP*UYi2HL2EZ)4c+EKAx)T(5M}EqQW+L$eL1yrT$5p)oTjAL3(d9 zukige4LkcOU0rY`;v?o2);%4LzSf@eju6|r`PQ}v%z%OS--U%;G#~3{iQZF- zv-NA^aosSl(K@ot46|*TZ=IiPX4^^^Sj)DX18mzD;0|Ms7i|>_tZh@UR%ZY1nBw!n z0t}=Wczs$MWs6+LYk9geNG ztBLl-AZJxe2|nAhP~ z#)z0=KG9=;CZ>R=@95Q0n`zxQ)m&x!<#{Wy3`Yv}{xhCs(@XvSJPs5e>J2il+VhR% z`cB7n_9a<{HE5>kX9XskJ^QT4GEB4K16@5LeCkxS8nrn82H?Dd~ zzt&{y*SbXxD{!|t+WtzmVZCni8nD{o)!Vi*+j@DodA0ANY-6OdveB}s%=4Xm+HS9* zrn-pOUMIc!TA@kiU5+jIy@t(NxW{XlXS#hay=07$1~b%?LXp;VfPwiYs;|)>@~0IcPa-%{zJDe*`c@W;`jAVXklqz;W@u^ zq^ioLTiq+L$zrzL z@Xu;Khw?WZUO_(l@yiz5$duX2LWvRUHKwonbQwlh@T2}Ttod2Lc6?}B!#^|=>>n;S zta%%pL2K+@W9^>+8)lhPZpV}F@!?kCS;6b{YsVtJRp+19pOkmuGj38iHt46~rpAR% zoue+~8MyXo{`-Jv9BUUY5iLSHP>rShd>Q395{?|^M zSN>m}{`kLi+V#{*blQd*yLIJW^Gf@_Mey9(26eP2(reYbus zC~#P=N^_LG_*HHJTkuA20sYGG(;n=C_@&QCwNu_7!D2Zw$L!Zz9nD8aHBEXgS2zE& zMGWkP^Ys5S@2ToizGnsXx&PnAbJU{MXj_gSiEy`kWwkNp|L2T-sye;eP+lX{&V?Aw zzQuSzVX`@JvRa>G+=Fu{%=oE%Kp#uaqM2>#)b#nu$rIHI7tfqk{u&IS@tFSj zX!}BcQa07=rO{TYKhmt%x_U*}|5{^MKX>)I!F~yE&L490vF`2Wb&Y+Ih0lafaY>^H z>ideN7sI={ZQc_7T3*scS--5ug^@dbyh7|N)_V5re%7#R^BTu$95C@E=l(AJtvPVN zC2Ku<_G@d=NmiB~OzCQ;vYvRuyvq6v0ru8)hP5)(DeC|0I>faV=ud#E4SMfw$Ipb& z;koW!;r4<;!@9MH*G>Mf7h-3qxewJv@9U50_Mbf;=D+G=%XQYJce-@90{5FC_ATqN zp3}|YwzBn>Yri??^5XS|UQAQxK9PiFwG%(cvg>`P7#;VT>~)nj^ne-C|Bdy=q^ToD zV2?ihI!05tQh(PdJZ_~PFvoT)D>5b}&zY8%^2B`WqZ;$tpq)iJro)Shnq#}KD#XV4=^NM>m%N2#)(2-||LNo9YwmjMUssv>OxlZo+`{FK zJt;U8JTYoPa{5GdByEg3v&Q(>buaZXqD;N~Yp)$OBXy4Y&kc8}uWptLKC;CPD1^LIO zg#-nM`h^81_y?k6EBUAyc)h22@c(EYE6uZvL}?!DY3>)BisrkDYt2yGuH%QzpKU$j za_x<_hz27hIJm^f*!9^F^G(w=5I-Ea!pKrVxZr@bs?zCrdNC!= z2JF%Sf3cvL0W}sjcqzmX0x{0n2!1~u6 zMy=rp2TBL4=>)o&Zn{G1AGRdk=SuNzI*jgDAoU4!E}ci8{HH$9B^}(hRvHuqinr3O zv~!)*rwo$%*|Zug{+uqM2fZfoP4vBVJAIZ8a$O}I#1~3~MEVrnMBlw$>V1MFzKV{g zhrBNJ`i2L3iEg7yt`^_(hScjDA?W%~XqR({6r>bMKqT$8L7YS<()hPjPY1i{dV0V{ ziSM9i(>~WoeBhf>A5Xs~cBwiR{K$Z2dP%V~z~AwECV0hL;t+ZVok+)QlKMRQ0Np_+ zY?k`yq0--Bk6l@+j0N8@po)H?L>hz+lLq_fBpQF&{`8I10bn((U!_J9PaH+Gm9L%5td>q@SZx=(FY6 z|8)l$EO>B-xRl;XH_@YZN`3T5nLrYqMAy-I^mV%=Uf)+l4{#anH%k1Miv__fc&$Pj zq|mna#hLU_x|V*BZld#O{57m+g8S$sy7zAON4xH3fxhF39$_ZkLT{i0MoayEI+5;H{qv&S(9Xf7|wC`6b@mXS*n$3b@2CSm%=uhdOvC@J5X`NnW`pztRz?F0!J@f;q zuclw6qr)X$eJJ%Q9%KFYVL>GWBI!1I4xMv@bg+r8r%%&?H%h&Kl}sR&zK^b;m(tFg z5bweqe9VG)T>y8|CG_Zzq{9ySZd%`yM#m@9HMB*y(+6qan^c4)WkDeW z0za03a(V&XLhq-2Zjla0R!e*={T`h~-}H&p*U^h;^Hv`JKW9PktZ=)9R%Jc^)u-hdM}+v|3z2RqYp~^ zW;&A&9w+_nrpsO9rNGSs{E@h4okkvF2lU@`V3gEXek%1*^!IcM-M3ciGim)-uzIg4 zxLw-6{h8QR$AVi9OF?0@1Uy66(ktl>x|9x`DDmwyPUSo^FzR#ZFPFZXuBI1?U8;=* zH4M;qSTYp$0vbP0@_0g>beK=SLi^t(_4RZ(?Q=xpv*`QjJi5qZSC*<~0e<%CSwyY0 z-%+t&j7(rET}Z!0>p!{I13pT((U)lRZmA#fh4dFruh!Pb|3Vg=W`O>?ecj>Z^&AjA zjSjs>>i5z~biZQ~-$Ku)o%b@Hj-~q@=kY(01y7?uZzTEje!7zG^`+G7n_cMv&ZARf z#fRup+SwrSRdh66PcLiW@!xr$bYS~R8l=&W(uMTfbQN7schFuZq z&{Zd}|LZvpo+J(We=W|SZ>EdsIdl#ED&0;Wqn&ZmUzbMdFND5{PNAo{SdhSvu&TC($Vn%LHDfv*;tVnIQFJ&Pw}G`ZYR9 z8`D=`{}b@2G#LJ!G)SkH&{gyobi@>izxsQLuctHU%&AiUK3z`V(jxKAu;=(+#Dc&? zY0&ov2`Hi$(6#h2+JBnF5BpK#Gw5PE)N49dr^c80o+knLt0@@(t?y8(8<_K@emGr6 z&!znqNPRh-NdH7P(!=nVGrB+h=X!bx&$8k3PZ#(-DFy2o5JUH{OM`U!QM!!YONTxs z?VYB?C(sYlMf7X5zNw}jfO6pTPY50@7LVEZs<-reiXtfv=Cm>pL0gB@|Cr)3}w2XNk4Y1Gzmu^0e(d1Ef)9mm-rGonXaT)(=D{u zWfC9oGS}&yEC_j7I(&_er9Y)J>He2X2YGZ3-AM1G^&jWy0rwps@%oSSwA1Nq7Yn{+ zf&QyK9q?#?H1J&_K0+tZ7wBC2p@9-#L1)srOQrp{bP4^~6%y}iWI+=Pd|#0UbFP$t zAi9-~qcZ}fK83!1khqqvr90?{2TOfGuJoTLcBxnv)G#2QzDRe{;a5oqfy+2RI+`w{ zGw8@5i7%&5(G4r4{jFE)dRLZ;&Xa;dPeGPSr`>cL?LS013|cAiqv$j`g)XMo)6Mh+ z+FT{=W3EAe`uJbUf;GATZlk?}#T~CogL~Hf*K@1A?0D{*@zy@0X?YC}lfv%=+zE=%HEWMTDqD(N0*jKz3*7*po$(z2W^x3 zd35G`;(WSkhq#&U_{d`y?#C$|c77rO@pRCB@vC$U{W)EGNa_P_koJC`ij(L_x}46Z zFVZz0NFb2CSt+Yo)`pbQ&Fclf)O%PtcKvC4MWNNdHNf)k*z?2x;G_t&jif zSrB+c0#4EK^uU{?fxdI0UT0}^6F?eZEq1AV7IeEy0?O&N zbQ67DjMN96mJT=3v2?)QQlCXHqf6 zZ>F>8PI@05@Qw8E8!PeA^k{8;{7+}WGYn8?q`@b2Fx}-o>7bmxkB(}V_K1Ns5 zeeaj{?es+0bN=shRyxRJKtikd09{0TPm&HQ=*e^^y^i+#S=xU{$I@PL(ms>EH;%{u z5*DmsKr8(#9e7SUyz2q!pqSoFSJS`JKEE)2vcw0_rF1O)_hgp@WU%1&2gUjs6WIOL zCOWuHe2Gq>Z;qFEeSJ{JKTqe;`{-(V>_ZYCd|u*LxmXa#f>X49xP|WUnun!9CB2B& z7Z`PY6P^C6_?AZ`KA(PtZlu4XTWQzC1ZfcXn{=>_j;6n-^;0(V1SdW!@f~zA9o{bW z&2$VsWQxQm(sSs1u}d|xpo0OoO_c^gze|TJ=xF*Nol9S!i|O%+(!Pa$iPm?x)iY2@ z>pR_g&i`9kkiY<+Y0^Ok{Rmx2Z=mbx{j|PiuAV^8$E1A(J(bUpQN(8by=G-zN! z9RqqjE**5z(`nxh>0m1zLpReI^nfI3Urf)XE9n2wov=%f_$&+b6I8Tglcj@>3*rJ= zKUqcB_nR*D!ESLnoj|`v>nor-{wunH4w}LK-8}v$vmofAG{~hR=z2PX4oZ;@%IT-* zM!Jx8UXuP==@|O5nbJP-5|+On;gc*VXTWE413i3}G-#u7cT>+74nMTk?Q7^@ddO_4 z$1TG=^~rP*olEO`g?R$LWC3p1>~X(T=>T_2_4pw=kKRC+(6w|K?K4N(H`1eMUz_xo zK)a$?P|AW@x}GkzO9RJT>9Cp(qnqg@x|7bOgH35)M@P_8p78YNQkg7xM+#IKeU7em zNC(r?WB@I6J?-Zu^-=SrKAJA4Q)y$q)a%Fo=v8)`$2k7CvS1klR2K>8xj-63(v#^7 zdNG|#@1Ps$PCD8t{oRo+{iV~H+WPokz=F>iP*0D3QX0g0O9$C>7X2k%O%HrZ;`IZK z^c?2Ue%-{5r=?y$=t$Qmz@FoOItxxSppE6#sd=fp5&Y-`f ztLc%?^7tRoT{@ihtaK1dH_@r|1J6l)0bNVi(&ICwzLS2P){k`3bKK{7sV}9IpU3B) zK3(?fDFKHWkWCveNPPu;7ai;?@!!xfbZ_>TO5Z_e(-}0LE#(=|VHXSPSfH|Gg6;H3 zI-r*{NT#Fcx9AkQg|48-E|mWCGpzIyc#971Eq49Ff>IV-`yvNGKS`T?q`?6?obK|H z#OsG+=?TQsE%ZjZlWw3x{XFq5bxXE%kS_&lDP2V$p!HL?^aL)^`srKR6BkMQR{AB{ zzn|1!wOH!o=@;o-kMa5cB@6ULXWik@m!&}y{T|&(kIIqyV1J39L&wn{)B0ZSy1xla zB)*V7Kv!vF`fA8hPLKf^bmV2y!EsvO5MFmU>lKO5r$44^X-6*mqi?4}FPHXj(1kEI zKm62+1vLy9zf3x4rAz3z0n)(_G;Tug8PJ`}IUxF7x}El2A@%yfXnJ~ibW#B3Ul+8p zpoIZ9=1GIlfzn_N9ZBPl3_ZJTIvul8Tu85@^%K~1|86?w3h_g$Bt93Pzn*|X78Eg{ znXac3UX=#nS4#YDI*InqmwNrEH$A~gbPfFu?Gq^VKhcpc7F@epI!L6Sp$q9=TM%p_E$pqHZF|@LzK8sGIUFKkE@G%R5=)MKgAeDZS&ZJM$W%Q`E60aX_rmZ_r8fAKLo( zpTUA@Z*TzgM!JF?S|s&J!7_oFbRJzwSJQvet@M){IKZLO{x{fj{ErwW1tT^}K-_R~ z8SQ_)c+i_tA4;#L<7j)a)MwFm(s)jU(yOGDZlf<1^Y|YSDgn2>B^|`ln`wRBUUzVw zE~Ihid(S$rr4wj1LgF{m#UsVTH%ojIy>PQj3OZQu7Xv~@NrQPMQXfNqN$W>7>H$T( zE%nYYaTXm(*U~9;w=EK%Mc?OQK?w^A>00^{ZH|@+Yq{ z?-mxsc?$4PB<0c|n_fmY(m&9-w@8Qg?2z~>`gyvJ-cReR?0P`A?v(fxZGHTIodx*} zI7e5|qjyPz2HK*1Bc;R7=xF-N3W;x~6KLPtB>p2h2X^TZIo_8BCF3PvF6|#B{(_F8 zBX&!CHNAmurvIjMCrJCd_egvlT|+nA&f|Z-N(s;pG}Qx2rIYBxbRq4xSK`a*>2yZ4 zw7*DK(BnUlc;`f^FQPLhV*d36jSnTDm;o_#4ZV*JzEk28t0X>&-b?EzvFiT1eI)hm z^b9)SE~!62N4Z!qYM(UFk8sr;?4?_1$H!715+n6tbRzvYokj1ZeeRa{A=T2}=N|EP z+7-cq{+~!d;Jp%%N0-q*{8Jw*_0R5?_!#;yolYknkop38J6%H?HJ*Bx=i#(^j_;NN zJmOa-u!L@*uRSOo2H!9BxpV^kE!|F!JtXlJlO+CQT0eG2PjAAfx*o@W6(q!-ULXHcS@69sfQ#vCKNnZib7{ZH z(&0fmn+~p%c>T~IJ%{t?db)v*cu?vG9O3almIW`MKo203K1;XL(MP3TKQ~xU;1Hce z2Y(^;Ep!GQ`jEsQrz7czdLIANS&&yR9Td_{w0=ObXPq6B`k05sZ_>GR3$34&q~k{( zm-u?Rl#X~r>V3Y%{;%gag$0j(Db`Oy)*ZY}*V6U|srOBg`U!Lt{W4uLMe0ALW2cI{ zd?oGk=~NdB3KJ!un69Cl=&Wf{A9+GLXrgOq{e)&cVD+`s7tpuURdgQRLc6|Wfqt~J z?%?4@=|Df?S$iWLmn1$xXVDoaCBBM2Mz_0EmBcM`9kzOCo* zJ-U% z0_pIoHtC?9PNO5zrG7J=LjO*;(084e_R&vD{9)Ra#RBKA5>QExqub~@I^ZekVA5~w zkUmZq(CgZzzMAg;ySR;hQHU612`0t-q#1z9SMzVUDAppf26*U*ujQm-FoueTwGTUYIC61u)S9xkQ} zDqoUVxTRbR<3A)k^~6S@1Spu~<5| zp|{l6(Z}c(dR`x?_j_65*U^deUOI!m1y4oOGh9f!PO_k!1uyiKfLeMm9-HP_WONlB zkRua(5RXyQ^|5ptol9TkFZDI_Q*@iyr4F(nYKe5{!1LI2hmp&~_tTxr#YJ>Tp7y)NJ;(oHff7*2fO@)|9y3VlqY9*h*>nc|7hOy*9xUhBntr`xd&w#e$gYq(KM0 zh4y(}8gv^j^*$TLVRSm(N#i-8o;fbQUgCY<6o-b2v+0wxtBnP-Mo55JEDZuiibLrN zI*vX`r_s-ilK3JzFihM*m(n?JN&n+Vd+J@PgawUKpqglFjC2sRNg9NW701&@=uEnQ zxYU=@6X+&-0i9PO{dIVZ<9{U!a&M3hBHxyP3v@f3bfeSgm-=-2cRCmL9RG8ZBp_nHbl{WB26PDbT2y{1ci3O$v^qnVZd!m*xCpl_QY@r8$Z{4Zuf9Ru8S%IDI-q!eioQYZd~j;51m za=`SPbP?^Q%juV9NqkEkkN@7YrNHNiOdypGq4&|bbWp0q7txh;6MfknsrNrB{Y|Aq z>0&y|#R6llG-#tAqXWK>4z|*fbiXGgzJz{+##605i@b_%p@*hPe0;ssFQ;7@Ea*K? z0&3{_bj&enP)+C4LGvZPn9ije=rgoBF73k>NPIB;n%JevSnxLk+URlV(!l(ZBc{XY zu1`vR5uHlc(jU@oboZwuKD0slo9Qu*|LH8)%77C3JY7SNeOfxG_)0p+r_B@Mv$Vb> ztGD_aGbBFkYw^o;IekW3AODjYB_RG8X^?tSyn!yD9nVU=IwkeVbO?Qr&ZUPwC-J59 zv$W4?Y5yfG=l?A5&y)u7bTaMRBn>*~SUUW9i7%q_XrFH+zLgHAN4_BO3G{{+c>FJ5 zK{pg-)Krf{8e&T?aNPQh0O9!?} z{U$n>R!b#bKg1q0;8Ia6Xk@@P+8>u#^&DRIiZqC#7t=ZPIl6>?G*{xC=cIi*9Yx={ zOzPu3#_@M03+fs09oBe@{>*N2h zJn6vvT^c+_cm5%+phN!@_gE?M33L)&)*eK0`=o}XdzGXo<9k*T@1S*?nfFIG3^xdyZJs#ohsoz2S8RDLANPPnR zG@VL+PrHg(Fri2q)X;CxZFG+fQlDXy2|Ptt(4Ww?^ko|*UfCsnJ)J^#dDBymzyD*w zV^W|h=nA@n_AQnUt4!%Io^GYR-jezdhtw~i6Y1l08$D)|j>qx8+)El9_7vduJ9NTk z>9CV7rh~gkyt72=Bj^G;jShZW>htNCbg93&O6Df-Q6cZGT@HWYag% z#qK*9liaZ`oYrPUMcZS zbOIf6mDCs0B_8AW+s=aUAPJbTmmSdAwExvo-{k|TkECbNne+*|lOFS-#0L+N_G{== zZGHUzfd#b;m{uhXDzA|SKhaI}y&p+^K(N%GrsL>Y`=maD-bRBk4!>OMUt(|3zoe;h#$T zLi%aCn%+gX(q^s1`?`k91mjqcNSD!B^svvQLD=;YzlhGH`yH10a{3XviQYvghD!SZ zpG&-}iUnI)&_Vw}hmDX1x7JC66#8YlnEsq@pu>(xyx&L;m`VhmMi`L;6+^kXVK0EaS1(+Zl(+A=&{n_B|4WL^p&(P zr=OwQ>5pK~`F~KjbkO&NG>E3}qf_Wbbm$Ed-}7sUPov}MV%nm^Zj|^h=nndhMjrqD zZjyj)jnZKxJ@BMBonAs0&`0SCy2mMr_m7bNCetDGaXOX0>@@a&y~vAMaK~wJ1)WYi zZion+~}}+J8>R(^t5@;RIPQlWw5Dpo4Ff4lX+*@ul>AbUSU) zW~9WQrNik#-%9&<+Lg+JCKha`189`sUQEHbWlmJqNAgwzKu?&pZ;Fr+v$UJ#6%sB<8OG21f+Qi z@N+ym_D<>0=Le~;rKix%bUv;B?MNTY8t8KR>K~o^Gdu zf07QIaZ*2pRu72FX@B}69YIfMmG+7Ba=H-q9RClnpoRhJXKBz*KR`Pt%LI$*aQXtB zONXD6_I30^+V4SWf0~YdkjMWUe~|{Y3@D&m>EGy1dUBh@hsH~Xo9TG^9Gy!ipO^SH zdLJF|kV`u7{Z#@Y9}-Wa6Y1S_KHcXxi7%&9=mvTp-Aa#Wm-v>4rT=8w&-I8DoM1sT zJ@|KN5Km90v*}HA0X^UkiEpM~pnVgh|8M9>I_^)2ccrr6C<|)oJ3A!6|552+D;-6L z{w4Jp^me+G9)CgVtLXi78$J1NPrXZ-Q)B|YI;BAhy`9ddquf$oK|f35!K$9!uAC01 z&(TG6*hOidmniWoJ;w3Bkp*WMP&7>f#$J*J(T|C<>0J6W9r3u-<5A3>V@Xt!_;oss zwi#02K#$Yb$NyFqY-E6cvUK2OlLi^|bh?1vMR(ACc8L$2&H>R;^hUaq9&OtB_kS~_ z!ILP^N5fqDGrEHw>X7=N6p4R=j;2r1*>tp*#Fx>#=yrNg7d!9&J5xGb)kPYl)7LuL z0sRtPP1n+qv!wl1-V&cezd+~FXX#3MR#%raNSrMlly>C+=pNm~o%BpPbB@H9(Is>n zT~CMmNP9I`;-9BO==WSKh-X0uolS>#X9rJ62N`q-y_b%sZ9ODDn;u7((M#z@+I55l zt@C68&Ysdi;C%6Ibkrj8QaYPHLRZuMeWiUneIMFwUbYTDYrfv;5SKvF7&REUb`d?JZTsZYDt#(nn6@Hy!q$< z2P8^RV5LO^2Cl*YF#mOX{td=qI0^m?Td$^ei#AvRcmf;*=fZW&vgiLRB;wO)03&T0 zK(K~99!`f3!4k`@l8uLfCK}jb8#g zN|E@1ge&aXfd)*0Q{gQ5CR__^vETH{-@5q^GWc`E2liV}PJ)x*Be1jr34uNhptgZJ z*ujo)3>*ocf)il{1M1Iz^1)BQ05|eM;b5{j(`i{BXAk~ z9Tsn-4On%e{?>3L910(ing91c65mmf_j7>GG(gqQ0buba+Q1Q57jA?DVG~2@pA3(H z^Wg2g`R9KL60cAo-b@?t=t2WH!du{C_#0gFv%V|U8)s4fEwDY@%!t~f;la$ZfB&Z= zk%@vLxCwUMLIVyprU8=S)o=!U1I~qYOsKvFUIx2vrSa-a@cfTO!nzxENQdL$O85e- zvW*64-<|5y;8-{h&WAt4?AKAtt`c!J^$#_bQo<3592A7Z3O%U(73>e2Zl?j3z|Qa) zH~?1YN&Qpc$?&V6^-?5scF=%gGfW8fgOlLBa6T+Dr+WLH)IS^!g!AAmxVZ(@=fTow zBx;c;f>m-bAxr9D4NriJ;4^R&+{}vV)pk*T7uXP93f*(i}p~2H#$?zsvyoc&P!^W_$E!Er0%$~pdkcdXXS2!JZvZD^A@B!E~mp0Jcp4tQ9 z05}m|2N%O1;0E6O^WW2f21wXT17^b+@N2jRcI`#=_3$>>a3A%rhrMB+-c-+jT*u#< zx5JwI@%(>?gfUC-1^SNE!4Vz<$HF(^3bpS`@VIM;$)HUa-nR z3;;XB|G?R>SAXhX4yVBl@CDddnok2NyHJN{*a^;sufuh47gwq`Jw*LO;ZS%3oCMdx zIdFeB>Mu1vOarV#A{M?0C&L;8s6z%E30J|}VYLDp?-6Vcw{xfdL9jnrD&RlC366!8eDVCxMYsLw+7ATa z`JZu~5}!~|0uLKX9ZXB9{ckuBZas|J3*i{J5K+N9xO#78Hx3<<3;LV z5=b2q;Rv`4J_7R}K=N0S`Ut8IhyCFc_yk-6OASX-hk7Jdz}96n;76GMfRf+9m{C-p z5B~$#!(Ktuu5_8|)8HidF`Pq|3VH=ohjJ8bgqvW!(bOJ)1rvb7uab|$d9X?d>dUD; z1lGMq-VKM!%$~oBq0~X`Iu*=-b#9PPz^<@C7}e*(bKy$32DY!D{!U}4J`i387xLzx z|8+>zqrhk^bx^uV1H{2auwpp1H^Kd2?^{&Q!G-WUxE8jFp#I|9c>Zri!j&cXW88ck z6~w|b;C%Q2Tmk!xr+Vv3>i-0eg?mR*dony97Tm$}|27iFcW40f3Dm(4UIQn>I#JZ# z00+ahcd7po*!&(@G7a0%Rb64jeNp!WH2 zAp8U_gk58(zEX-rIuiCZG(bHZ3!6`-4*Um-{2@w&9UqcaW2rq69t4-c*|7a1s{a8? z!;x^ELIb40f5Rnk`#5T^hZn=vk7>a7Z~#1JD%I!1U*LLpaJ;OYef__d23SW4K@$8H z&VdI`qXEm|{csa(HJ#eypU`;I;P9v9D{vm%eg8d2*bGlw z>$fysiS*~c|B=v1q5+cOU|3L39r9pfSTv97{op7#5q=3bz{c~bzV;oBmpC6YGJlU5 zp`Za)TRTnZnD>tM|lRBtL!l-;_Az@fbP=YJX!Nho*< zixsGYW*QAp2YbPSX4IYp8^DKQd$<-3hkLH1@e-J2U;jUiL?H^aR#Cw#cr+|lq77ET zhOpmis`rD>!O5^=I<@D(E8tQkcK!2Dvztg5E7Jyy)=&pWct4y7H^KR^ zLK-h0PKK2^s?QU$>z|*1GZGajSO=?#s9iaOI;6oP;Uf4TED%%u4>%N#T}S=>B-H)^ zj+Y|gw;nTs@4$6%@CIsEX-)%dggxMDI1x6?r1~s)B%BX_gr$NOG~lp})FA<03a7$q zo2WhKXFFU0i#JodScS%02=kwS@+ea+yEbd z!&Rw%&{nEXfs^4J_#|8mf0CI!|0|FfvW*5%X+;Arfz9F5a3K5@PJ;VoQ~&Ir{ow}q z0j#M;a)90`xW>V{02@oqV_(yQtFUvMv2&5atVAEu7aPy zD&|z*Z7KqIrNBKxIu-sBbs$;NO8*cCQ|BjNsV3Op3ffFt2Tnc4GqHWH;MSPoahTi{o4 zKHLPC!YYGk!d0*?To0SVO8K-yj=cHjzYY@KC@_VCU}rcQ4uBKjNH_&fgfrkYI0w## z3z=ol|3V~6QBVd~!ZmOm+yFPh;zP7YDn7IVy09*64x7TRu%i#2|A9z&qaYd%f|KA_ zI2}%cbKo?%2+o4b;XJq&F7{#9KYv|*Mxp`*Du-#0YGDKTGi(iueW||(tP2Ohrf@9m z2q(kdQY12v2!eOR(Qpx*0$+iP;TpICeh;ho(FBzWXon) zzHl)-238tO?bBdgI0bfuH^AQTezH^$io_Wd#KX7YboeD)1pk1`V2wiB!z$Paeg*f2 zn_yp=+4W~Wg!W)83OwK$a3H)Cj)XVE3GhKU1wIdF!1v%B_$_aC{t1eZP&`6=PzGzm zRd9Fs72FqYg8g9?f7+q(ur53sHiuU*OI6tfT#?v@f&jPx4u>zn@$dsU8U6sL!=j_K zL)mb9I1e^E%C3KY0wqYepr8UC4%fmH;RaX=D+SOVuZA_@ov<-{47P`_9%bv#Prw6- z$0!Jd|AC|77RRVQ5!Q#(U@JHqc8BxfQE&-7S&Bpj5)0s3n1dVOJ+OEv?eR%i2fhIt z!_Qzx_$%xOOIsDu9)%*&8IFbR;3U`!PJ=_>EO;uM2QPw);SF#lSt{6%L>&swz)kRN zSY;UP@k>}2{s9}q8pmme9AP8a5AF?z%gnBSUnJsDFcwaRXTTZoQaBgh3>U!%;WGF< zTm|2QU-9Oj|8J2H45vL*JVATFe^|uddbME#xI1hPJHyWKP}mQSg2Q1coWLx5{--06 zjDlToI(!1ohHt?6@DsQc{tQ>aEl$!7)x&zQAP~=g3nbJ6X^&lD19&)W4oAVx@EkY* zPJ<)iZEyly0H*{>X@i%L$UwmZI0t?Q*TIU#v`3%eHn8ak8qWmwh8^Kh*cXnKA~6Pu zWOy2!4yVA`@CG;^-Vc|+XW$C>He3t8gryBg{6IoHlJ-F36z!odYy_Lay9&UMt_DB#! z{qC!{6Bz1 z5DL!1k?dZ|FVG%k!ENC@xCdMe_k+vfp>Pd69I1OF_XTk5_ zO4y(M&Bjv{)L-V>#VI>U^Y75FVrIWrT+oWW?ak^)8?s=pdFyl~7s8naWcFjjWbLV) z$;Qpd_4?#+*w~Pq440xlTjnJ8iwJvA0sGc3*?@s<$nDr8nx8=WL7L!RSS6p_PKnx` z-_y@}8Vl#+=Y1W8P4VNs9>EoGb7j6iyAgQf=Y2WI672W);^%us!I>Xu18d<>Y~VDU z$NxYvwt5wCCF-BTb-QW8#zLBK?k;jHZ~jJ5xs4LXP*A#s{2VsjL~bXd0gRuM-C^ga z* zRJ5Y;tl(5X+Tbvm1%gN|s+VS>AO{6!QJ{p&@CVurJZOM+s#&HD3iL{=k_;X(r*fn(jtHE^06S)xH3&o5}%h- zfs+}Sqlg2pnl-98r@-Q-KQ- zuIR8B4o#u<&2U2!`H;*>0`G&g#}#lYo+U5fq+QhBvn@@yB99yjOT}4~ScXJud%A9S zz#i~PxExk&M+0WD=QO{9x^M#=3TLoG!MA6_RhYnavQ$ur34BF?p$!da+MYI$Z$*xU zBe8+yup{>HD(u{W>Ranl|5|LY4_tYGCbU9kDf<;Fy40Z#1*RzI+kpni#ef{FVomk$ z;ABkLOONW)|E3M>glo`WppOY*2ef(f--uAhZXo;;S)f3GJxYM1F~A|X7!!UEC+w#F zW(KqY{{JWB$BTsp=)V`P!vtS2v*$niRm?~jb)*55FvD;-z>)^s^0OVj52xTQ+z&Vt z?%0XOE5Z)C!7A()tiUEXrIYOW&z|SFQ*A;)q$i!_m*4;knm{9*jR|z_OdIe%hPP;N z>Q=lbG^F;t&E(H;%0lw{E>bEmWbecH8C7>B3wDw>7?E{1kxh-s*`_qX6|kcX`5l~R zLLO^E^^Wzl$E9!O!!;0Fh9fImmm1{JzfyG|r|9Go+Od<#}-pbhjfrFw%0 z)V>X_s3vRnp!U#_Wa(Tal7>>^8LT#(JgO&ki0@234=1>jEzPLC)`h$mF2T z;p8wos?TAETK4?E{WHO4%Foc-o(eMA$;bN|Y%q&fV4?%HYpy3N_97>&BkzK1Pm*1F zQ+rcB`5x@e%+7m(V1XkQgga5eOIX*A?B9pl18m9XVb{a7#NC{z-TMML6&93|8{xWr z`(222joq# z^+Y`Xm0hSnWgHbugmc+HWBC=TfWgVqeAcC~%f z9y6SofBq-tQX-JuaQGQ3?IrgcK`utS|44EPHqZq7b))*jqp01UeeH&ypluM@wFmh& z>}*0_AB^Y!D}6eK3ZtomS|{>oI1ufHu#SN4ltv*`pB_U4a&XcQ>MstZ_NGzPo(LEB zBUgvw`R~!6624*7p&TxPLo2D>atyUwE6@be;6z38Q~2{+s`nmC_4Ui>m~VpQE8@&)H$okO&QR*}?Rid*eg__IFkq2>f?4-X;-!ybdkrSRuwWP>QGPoGSd z&OjpBhZ1*TXJvA?iPRxBmOK-Fg$>?--(vsBQPJtp}j z&&Lu@f~&gG3Y>)N@eWBfhU!D3Xal3+*!$%Da4FuvD6(<+@zY#U4_jC8X2+l3Fkc`L z&<0zxnextUPL6|PRp=x;4i~4<9;r^D`uGU)7`W7!d>+oqqzMdSd(MyFaG05GUvLu% zB?l@nnMwtjczjNWb@4wSo%v}z4O_>f{sB#R3>*|eJ_uLh;iNnb_3YUrd;SkX!Wh@> zdRP|^n@6y!xz!TmQeub4}Cwbc$e1A1&w*LHC-$RyQ zzY<=Lme`7!<%N6&|Hp+aCJ6*la!!%+RyiM&^X*^e*Ps2dOptBx*9N@hJW0;W<-AMI zpXA(+o_fE=U-Hw~zToQ51kFd#oR;oa2NyXf$a$}vpUK&7_U}6w3;*1{V7pvFm7KK_ ze;*(~&S`Q!D`&kqzxQ_}OMmU*NV$SkIp@jwl$@{2`GuU-=Kel`t};snza|hOS1?=7 zoSe_gxiec!cGCVD&sxsIId_+{rJOzH(e?l9Iv*xi5G&^ea!!}?ZaEjo`7-&}_8!cmCH$3m zFIUhg=O1JR0sg4Zm#x4rcaw7;IS-U`v{Wwfmz>k&oF(UCIp3A@b2&H4St_CT=fC#A zfc$GkjOA=DX9qd=le4>=eSf!9F#Pv~AegNDbBW{Syj;#%ay~5Qi*m01&Fnq>hu;zc zfh1XWOn*&4SI*XQc9U~3_byFYUwxKbdO4@QQdwVmP%eE|&Nt=!Le5|0ELr&bZ1v>q z@Vlh~kKYr5QF5Ln=Y?`!C+A!_pO$mwZ)Vrq^WPEz!4EmB{q_4E8OYgI&I9B;QqGh9 zZMJ*Tyo&Zp&kN6v5Lti0&=9nk)l`Rxn3|0}_Ju$*Vgd83?<$oZg(BmHn7;nVmpi7+@v+iy}8y;NMA7?L5aNpJ|oAvQvF9)*lWZ}iao5dg& zJ}i7$_^}wwVh9U=76B|yvpBHpqRvlaStr6>N+mYTnb@K*Hz-4SgH(3y zu`d6<@XDAkv$(?IDvRqZZm_6eag)U@7Pndaw~O%+%m07e&$|6zZ)pGhepbNlXW2Q zp|6q-_h64wE3Wama(9+^=&WQ^Fz|)4QCse?lCUGULQ&X~8`-3+$>k{uuX1Wi!YtFamXHeoI+Qpr#;%HNh7+@##$&*oF(+2^)= z^Stp&9oQTW1So0fhfSS2VSG$~`hrI)Wc$}F%%9VLF6>xPW+Dtz;L0Zp#ai;a#Fmk&44Or`aeKyyjkv4@LLukdUD&$0 z<$sRKx2_U1uIpH_x|U_+M4LgA!y}@99x+!7x9Qx8Bg$P0EKG$?eKr0pu;kv25Nfgc z8JrMW@$27}``%rs!5O?0s<>;qMiL3)y(JW#SH8maXW&9l2Pc4|hdZB;tYl+EnVGK-#KBUZ7}N~rl~qi>vWfH2C<%`YH?GglS0yTXC&uZ}m_&LrIwifOG@qzOGZeMONv*J_5)i(dJ4 zlyu}BCl(&yBsh*h|(ZlV_al+1+fe!f=U zDDKM{=!lfLi`wjpl$EiQtHO3btI> z2sW^p9Xn#)Ny64@e*RV=Zf*hQA*{xpb>^b�GqmmL4^+3)(t1Y(m_?fRF$SR?4ba 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 w-R`Fj2&^a8PIK!Pzh;n~QiHbZgA%c|me3Gf zvBpwWB~4US)sm>TX^Tdyh_B`U%(?e6=u{6%>RCU|qbKbVcGR*k#@&P=P23Jmx zv&Fi2*kaS;_yrnQX>DiQ<2-}y@mfBIhVTSt@*3FP7E=π-blcInJdiYG-NW?Ljl zq}#Jo)-pd?X$kB~zywtqvBak)UmY?ES_%UfQKMDp{7X2#C%_-`Fu zsZqg>1*BG1jYy;M}uT-G?k&het}i_8W+s&JC5;E6uLEZiu% z=FlkC-^i!un|QiQAT{!xE;XBaYcGoq1}`~DEI*yF=LWuEI4P`#=S7@Y=q*ww*c@zP z>A|Llj8}GzVz(KOa}A}ze5h*`8o}Rl4Py5hU+Efatn?z|fsZnfAy2K~3o-ck3Q;_; zLUZp15Whq-m&rPAsD=W-=jI}Muy@2sL{&GJ-PFkT%#);$B1zd{ezQV^H#?1#VdkT32t&56}tAeAC1$^Fum$DIx< z=VdN?dWzqz80}@OfOcs`EO@D`r~>}M@+$DU#wzSjS8+Fs`trd>6Ak3Ej31}8lD34* zSvfLMnl(j-Y=-x@rVV~n;)8d6%w=s6ma3P$hvYDIz4g+FrFb~843^IrY3O)13Snt7 zvTPbcEHd8~(pKcNiX@lBSGN>bOwAo%f$#;Ds?v#kOQkx_{U}-CClxax$Cux))SeA= zmqut9=#FP=E0|J@g(b*v8~S67aq(p}sJU!gn(0wVCkVEH94Y>o9J#rS9Dym76%A*4 ze`I4*FX;VuLae1T%&r8AD5*)x78+77l++<*vN3Pgflz7G(#&D0;3d_O2aKol-GF+Z zYevh{8S&emynAA6o;KuCkq^Iq+?x%_5T z7J8C<`!)6dzx1{L1Rvv=Q&z|Sc39+ zW&cp4x8srQR zPpDeLzRu&b2YB-drhzOAiA;+q`|t>l9u$$28hpUO9v|UNtBork1|2vX$j&U{33LJ!#@khh%f0 zxzmO`s)QJu4V%k0P?8;z+_r2ZFky3i*)^n-9z<$Pc2M1}(aSI5x&96`GVFjXGOhuy z+91dyDi;}}jnOvQ&TsRM4H~jva{1f_ap4wOB)pu_o}9*6ksVNp4G4Gm6)G5b+W;)2F|S~RBgdQOwLc9cyxz~{D%W61~jiI$64 zp*5$g*{M8p+RuBpOJINP<7?VQgx=goRyY?dN?N!jXOatXb}b3QFhpHCmIR@Dg8#6O z-)tAke%P1e)ZUx2kM?p?he`ZY_pPkiK0ZF_0n5+PEt#kHSWE}-F z?BZU2y|%wdWV9zu`lMK^!aVnigN#Pe_9BF8&D{H;Wu#x0^MSUawnhW|2Ra%Hig)zY zP1@i`cXGtDcd5VMdc}u@(FtO=H?2}B4KJ3U)d_|%Sy&{9qZ1$mS>goAfjku9$K(1!GxpiXpC#4{AUwG}Cp<6Nc|^l10P=R!9u$R>xG z5)3=59&*#TAg_O)i>EV=ZF{N_OENmGG~V+MMMfdr<9!IZl;90#O8$J??j3)9D4vzm zVtMEBmFNTR(QufdQ;uE1EpvFrw1y(jnKtJ0!lqC^UTKAA&iUj3Dhix6BYT?79}kTc zsnuCyL);g53B8eiBnqpunsfoLJ1u}c{KvY>MLS5@h247hG*Jh0>o1V)`#BY0^Ml8}@XZ$VljkG2A8r_LL6f~MOV!uD* zYeshyJIByYtnJ_XmNG`gh)PCru#5jlL&B0G zeqI%x8fau*+5CE!DEG7fdoJ`|*@{@2i`_wJ@R@i=BtB=GMdowXfuEnZ!3k4( zT{wna-G%8%C||X(v7Ad6gpdaOhlQWG=_z_8lsUtAL`)?b$x|yD*qEK-?lfxRr#@QC zj_=ADwkVpiefRV}!FJi2%fRgXe>{tK zUE15b;Uj5Dup+prjWAScu*-JvgG&?G&)fL3r6zV2cD2mJEL9Fo%7|2der+c1b)3gl>Ws%Rwl4=0Q7}kJ8X(&9d__5E9X}(|KO!v z-Gplyx{Xf~;|<$CmueqMTZpoC)JsfvqfPmQRaqXZ&>3|zgo5vE&52swkYchiamFDw zVQY@*Q*T=N!u?k*eb}EiOaE}KFtkA&H#hWT5r2x==UFTM!Mcw<2IHZ_vU5Hc`JJdY z`~43dm61^S)4NceoL!+b=A3$A*ET*oBg(bIXPCgiQxEx!@5zXDX)1%&&AEyEPDVYK znljYPoEy(;tZ(V!XHQy(Ph8*3#o3!N1+lwv1H32_WO7=V zdD8Fj2F?HQ##a7^!}z$(0qoz+e9`6zKUYX4r)?!eFd9&5k&@lSL_C0hy*a@3;AWJ+ z!<<{Nncv+U>iUH}_~mBqza`XlvpsllGjF@an$0Az>hcawp&fESL{hkH}UZZ z7TDANx{0qu@U%Vg)lK{;f`{#iFKpt!ZjEMlHu3)3s`D1x0$72h2`qOL&)7DJo!rDL zZ$HRwcU zC+y@L$<&ZrfGxK#WICwg%Z=QBrzv)eJ$OjI7GypmUnxF@29~d-;k7W^YoFTF?cT`8 z;5Ca3BH8EiwdyDhIld?@t>59Inzq*#*wd}s$Pex`h0d}ExqPh-UaM(0!~mPAyt|P< z-s$f;UM7S5^EPtRF7GDE2OPcf!;KO4;Ou5lkz8f9``ozG1(^9LVG5^ZQ#qZqrC2JCZ5kRnUvOq zVfF~PC6pIt|H%dv^P{^PvP&EIgWYotwTk5=ZBHcMyvOKaMjlOMu^3!3H`qb%d^cqc5i~yXnk$Yr|)fGDClU3<2id9 z8wzS*M)%j=aly98Hy7>)(Xr&3apiL6%UA4cPiyjP`)0JABp+kT1tUR0Nb8oC-!tut zDNLI&4wZ(qPAD4&OvsKen~b!&TSMGd4Lc&(SlD{9>VYxnlKcIuZ;@TMqB-|in*V|J zQp9q^vNbK>k+XAV(pD|-KnFalF_iEd`>V1QoA|T+XW4;G{H)c#c10-!rY!n!w2)Zl zJA{CGUKhg1D;)@+PQ3PkW^CblKIXu%w%?=4U%XBXmd^j5*DoRMi$x^rtuG?6`Z~W+ zWc*0I4Sm;Rj)EOC_nqR`Ra74O0Z9+}di$fisLWkaJbSQZHeqAm065Mv~-c(4f@wTX8;crc}%lmY8uU51O)auii?tcPEhp*_-KL)ueU0jxol zBMx!coc1gUL$BS2>SISO4t17!y&_v8vwW|iOiU~h$I}jlGD!6Kq1vXM8DvE;3BLH` z-J{!{&Y;_#qBA^Ct59e&%ACIsF-pDpzlUe|Ka{1_N)?sPPc4c^Gx9_``3idps`z1gn#;*->(8`x^bbB^Y+BOCbmWBwf?WQT%Gx*mvT zSqEWsJz&1@x*n<{Z4-wc5Wh9e+uk1D2deVIV*%8K-@*SGcgd^i_kZ;%1MiYIB>Mez z*b+-)g->U=pu)_errw$s^e7WuB@@eH+07QL<5%)Vb!;O=h1E&%^gRHL)R$bE)NZu0 zy*Ud)=4qBlM>Wt~s0Mne-XjZSkKB{V7acc6e2!OeBICIYJ18i<;J-HRHfQqu;}M2x z5LWKIbK{9AUM7g4ivSIfeQ0r#dLfXnKGDjnmKuX@AY;7vy%Ti|JER|z88koH82cmd zovcnh__~vuScgoWaB3GDwU+;VDwh4co=1GyjeTU`?|<2peQ)47U$!xXuf@#1bOEa& zu64o+ulecZ%2_bhVs!JH5FryQrj6_QuG96{y-@!1=`J`xsQXpTIsx`h1tTo5caVaR z#B!EP1e&U6-zddo2vtd!edFV=dR2TS?bdSqudkxKjFFb3ctzHDgVyI!<|bCSpR!7k(Z!R?Y3GFVsNq;kVeWSw?|%Y zduwbRO&FtDI4?bGU=bz!!P&X4zkMn*#?bqzh>OAcHuIaY?A>+T<6ImYvW|B>H`nQH zXtBmPe(Br=mral&GmI9tFsfvlPV`_rd+-3tpmZsL(+ zE!W4S?>1jh9<`H?LPf9>HSk*B`LaPKeQS7JklauU<;I)NhWo+DG`Xr4$csGPJQ9?b zT|;Gl?y<_F$Gqyr8LS)BY@`8v-^H3Vmlt2G$qWJ9Uea{o&W*?_e?>Cz%re34(jQfVc4ahPqBQN}&wbFO!y@ALE5ThR}Ar5kl< zZ61FkjDEyN-l)euYpkC+p1M(=jcN9>_5W(Fwtn=gmkQD1bcL9dNB{73MS>k^q34ub zJdhT0Otu+|;~6)jx$n)sbRM60vnJig*WEmX{fmA-FQ{$A`}RJc9x~6#vfz_f`h2?G zv8PMNUWvQk@(Fgv8#w6p%se^dz|$G+wmsLFzJphU3E1)#=u8Ekfgbg2iqTJ5eo4?J z4O1R{&v)M1!H%rr{eM{=vjh<@L~t%|G5mi-SclI<0I z_OG#Vzak=!y&Ssw%IvXu8ZS36)|R(?3mF|R!mGVf!+wI_{nfi_B3@~ZDwd#1atPXr zfs&$6-yBXYO?b#}-C8Vut&m7rh;5ip4+(U(talV*bDgggQiJdO%?F3kU;Y;6Jq7PQ zozZpM^OKsc#LTpQk2Z1s?6E5v;4=Q%jn9<;emz*{n%UN#y!4lz&-LC*nS0 zWS=5O;>#TTCOrGkcH!yn__BS1`~N-$hn^q)K7?Ia$$$NQIxAVphy9V%`{Bx0)zt@K z``kM{B+uEB&+Y0$cCV|eFVeo8dsns3y#o()TghGj^rvyW+MnH8eEeDg)nx&;nPGZJ zu!|+bQGjhK@rtS<`R+e`;0?b1GpyIt*Ya_Z`8ZU**~OCT$mc&)?uxX!porV5y%d!4 z_}e~)#mix}F&zepr>j{7k+_<5=Sw>H^4fO}v9e3@3}ZIsS39kuzw*L=!q}Kg@&scM z&n|7w24B`UXLm@m$KeuNzXIFLU0FH(EpG;|F5j5?z3q+E`_0*yAM`h@5LSO<2gdnHRcR{M5xQhe^_ks!fP&ZStVx z?eD}hC%VhKUwLMcb{u}(_*g&u5QB{LU1rX=LT9}x`{Vp4 zOIe0ERhd3vXBOEGFs7f!?zMRfo50e()$OFwv zX??z~z3_9dXiwi=znHIU5Az*lR)yWof2lA7c*9|==OVteJGzIs?oUTC*F_?_4{a(^ z185N&@D0vzqNqr$LMw@NRUu=gg|X1~|e85Mt=3;XY z4Q6xCis;MqQ*o`1=EGATTKKG9Em_D}fj;`TXdVhpHlJ_Ha_!f$&z)t zM*%~((IAmmPjeRO)ucRh%S#ebL8ijG$Jkr8|!kXRFgV zT0yu((pVpa-<*g2JKvfVi6c(7lH;opjJ-!HK1WM(%PZ{ZAMwuG7wTs*Pzk1MMh=22vmEyyi5MI-gImDN`hFp~0ea z9Q8DuKY{*|*wk~6IP}45tt9R)QI4#A%pdN*7PZ6dB+S|Luf1HIS&lZakXaXyqDG$TwS#c+U2GJA3 zy%i1es`wv=VX-2<6&-HaF%$CH55qo1+43+<#I&aK43$%5s8+P-e}h)$sZ*SJ@bYlh z%XT={?vy+nqm{*-HndUI?ynt=bx{t-I?BVb88|^c(v}X1XgurHt{Zal&93WwQa>15 zlJ~Of61(GTf#mwZm~~4#7^(Nykp6WC7xq;jx zE~M-a$DtVH^C@AXayw)u|?qBUJleB#`I&@+zK`?hp9_^8X9?$}|%v3+mgXXz&JvcNMr#grQ= z*laAjEH-qbL+H1HCejZl@MAK=A7}|sO zV4qL3b{!=>^@$H&ZSK9t-fZqqkLjK|_{b~Gt$XT%W71QbMA2IqBeHtY#@@4#;p+|l z8&ctFfT-1*8rhShdaHMyVQY0}o?&z1-%giKd_Su)L(CpSr?W1H;m2!Iv7{drY|J#9 zzy0ozbm5yMr2lYD+v`0@9(SvYM`rr@Ib`UkW-$h#8W21Q* zi;08Kquqr?LOHQp!g*0Rh*rVa^vfXhWi}O}rgsWAm>~-{*9jEqgK2%kEi@eu4)t~Y zS2q=NnbRHpfcw%B^x>`|bqI~2C&lg|v{7(7DHIBmOF>f3T-FLo=n#V^PSEt8 zm6t1fR=&q*yx%TiNsjFRiSIU{@Hksi;FQtZc3Kms8#}uy`bp2DWe<#iU2n?Ldda zNbZe8#nw!&W4<>WdJI8p{532C=z&3nV zppP|qD)rUauM@=d4`@@vqZ}kpz2Rpq`~amHZoCT_VtNe}MRC+De8bU18wDLe`xyR` z(#hL$Kidez?9Kf6wSo#fJ;vSo!A#nTQh!_8w;X8)NP?-A6Xw*VnCT3gjcYtVj~5v1 zqWx{p-kk09m}tE+o1Ud?z~wFWOhO1jSK@)6B(r!m$e zE9nku2*n%RI407%Vim<2rt27yv6{B^&L91z_5QX?PIE@Fe|G9KoSAEAGG=}BQ>tGo zqIIpHDU7CwIqPUW!=vqx5R(}CjwoD5*R%Vh#H0+&-+mY+wr9}KOovC=7QWI1q^BrO zLla~BJ+l=l{A#Bdzn(_0wWGw!_3*LNM_DUpQj_NW2VQ#JYp=+9G5e|^)@{PbyJ3f8 z3f53`y@3(5Y%C2h+VE0Fgge^3|VAuweHwV*jYt|OpS7Yl( z3a4$fp`p!iyo1@TNZv-rm;KoPa=5X;RFc?m5uj1)G(bA65s)0YF@?2#|4CgUes zi?`9wajYWl$P3r&y10p*JLvz|#S!ubwvTu^2{Hy(#C7k2EE>r2^v4No+XxZ66K%h2 zgc!V&?!q#`eHY!tJ|8aj?4o1X`JqkYlqvWuGz+N zB6l^d>0Nc$n|iCgRqCyeXtEFfqX{k^VAeWfA02I&BP%V<{XGylYjxjGD^SC!wP?^x z^k(CS)Xi$P(kB{QGepE4qRZK>E#iX2&YP^G4%4obwchZ`%-Z_<5qgL^j~MdCTzA|? zo0*6w$LMA@9JfL+*Ue70OR(8S!bR)jG@V@@EG`|V(W4L-_!JBdFo=Voo`e7_upbJv8bQEY!=A{^j3tm|Er!J*WKRm^s_T{ zPp@UX^z?Z+zL1_iC)0Mpa0;?{-5$?nIxZL*S@C*(5>a=ctv4!rVa4Bjif1C!Q6_xdJS8GPu0UH`e1VFvqajv#(qz zCmDY3jkXWPz@N*)*`qJ@aXvpoJj-SKJ)V8}GX0-@#NA;mN|>)=HZv11@zUjixD+|( zDrNx}kWifkva|(MaJZ^hUb-sjZQs zl=Nji#me7kN5k44_V(E)Fcvfles=uT_IZr3qkSHNEA6vZ6qcZU8i&&AoYlpTpUBQwK4cdl2(exfQ zr5G^VFBeZN%$S;V61mmJDn{SO#!hGd?$8i=FLg1OZAu&bh~cDHek}J3hRmZ-jXoCH z=gIA{H{+<7{4nD(%5mh=UdiVe-g`Qu^|t4&sN8B7KTX7>p)}QKScj{~%Rj0nu7zpk zJJ-Y;a(7yvr$GYQPP80uTS9_h1TQ|8}SV5X{R&L4Q5Jl|DrYf{!4?yw?KG#U~Y?ebGp(c7E0j+XWKH<3c}czX$XyC+}Wp;@9o8`AXf79OtjtX@PX}6IV(%KTq6! zifw>JD{X%LNdqHW|A}swf1%2{TmHGbZT3E+yUnp@KBu?YKg;3Rf2Hh$<@#cfKdEbE z6IbZ|{Ai;6#XX6-KgV`=u)%Nn%azIqD|Rx+YTlngs@DZx!gYZwTV4@3TMB%F%N58x zvE7-)v8xD3M_1K_RbYQF*CkHqW-FLB6uVv6Tdc6FP2irc>=tXEZX1b4xUs`5f0=Cw zd&Zr)v9Bz;*q&YOZ##?b9;_347aP}b!doLK? z*TeFSc&{RBt;P;>#15=v*((YwvZ;mw=NeT+CnFn)ZKvHvHh|^`_e$(LdQKEqVga>l zb%BM!&h`A8SFvpBXtO}MThyqG4629^E3;^CNcX1oIE$|!xMb7$;(VS#Q6OI@vm!yq1ScM;3U> zY+`n^j29bxS+qyCy=vLAYN_IyFYAUya&13$_rD8`7IppE)MnW=`X!V_4J8&=O7M{! zwYYqb^^@kj{cB`jqkBSG2)qu1*C|)t-j`8pJ+7a)iLVt|Vy!4vX0JwVpS})hfWbL3{_bjzwD62gtC!vN^*-rzL6jm0nQ6< z`iYTMSr}a*KB~%^wJ1S^dQ#a?CbYG7cF4IZmYwZhY3)~3(nwGf^T8G@KH%EKzB(WV z55%0L#KaC8u0!G%pIhO&G%KQO#PMJ@nayg?^G(s#5g}}##=@5H!9yCd@P#?i@A*?P z)`fPk4vJuhC^LR!KhHSZR-R{sP!ZGw_i4%^I~fudO3!6K*s!|QVxuX`U7%lR7ab~U z=lGIZLDtM@=8W&P+UTER8J5q-AY+Wiyr6k3%Q6f^ke7B27sh(*GD}z}yBS?3;_I_8 zLt1O}Ho4E3TAu}aPeoa;dxAj=bx&~f!OWG&;aZyWF!a8M(U1k=|Zp;|uqM|zjeo|apP(!B#b&IY^3*=YAT<3+VL@FU5hdmHv`i&VU+T62)h38SN) zle3p)r6VVFh1YWm7K7TtntjB3ZP`QCY>pV;j*X#P#gFY^kF&%l?a}*(i(lHaFR=dp zqyzh$x?5XxWPMqUzTOtSfO+1QVXmo3X%KDrDR0ZHID4;!1CrmnSZ0W$o!PM3!}0t@ z^@@BfSDO9b)f*wYbb(L<#K|lFC(J0ecM8+vuL`Q+l|ewyn*RYQRrl%7MTMre=b2i7{-IOn>Ec3n7RBPHi)Y>0b~;XMOJa4H z>vVA?iJ2IiE*>YL5B~juXxc;m`~PqEamLS$;RsI;{_DPFckiyVc2eUN>vKX%izvC^gC$q}p>Sb!S-XFs1 z!_&`_yW!Sp7(E&5(AYM=!jbPMV&`@A>Fklr=v{l}n~u_RrtT#Cc`UBXWn6^ zZ9OXnz6D3#bmq%*=ENELv@WxeO5En2_6`d- zbex7!DA`2g#kPH{hdA>Ni!u1hXW4JFU~Ax5w!_JGJUfY9fpgh1nY~Lp_%widH?rS| zZG?{LU)<%7#MXki;mkCUfAAiwLx+lO z@3B7E(x+2dP{=GSo8`Cd3z7D}W>Zljek$`}@2(d8r?Ta=nYc5Rz29OYN>{y6emz?+ z*QGfXWohG(2EF`sX}%R3-bY6~Epp#y@31@dM8q^Uihd`SOk>08L2+*yd&g@v@+-zk z87>l)$sf5O7GhZ;CVs%GpjAKofDLJJ1u0YsqNN0I1-b-%Yg)F%*!2Nd@VW$bM96eV z5FwgOXMfV#qS_25yn0}_t+=LH|3v_KXOFq2USOhd2Ak2V(Q9R`z|}hG(;T&};3(@q zYWoS&I((Y^)dT%*eIJs$SZtWdZqSut&McI00;$y6M5-ke)U>Rx^KzVcy*4$}62j~y zv?RH~*6y=0Jks~YtQ6L)*XY-Z$VC&$-F>|h?Q2_=#}V3 za(4^&R5rXt=xbSjEVFj#2U#;m*8icO#bReF+9FMSnaZq~Bh8uv+w>IQ&ta444bfpP zYlfq;4*~36U2$SAn@?AZ4rzG0R(zPo-l89hJ2Es?)R>1*YhjtkzA&7g2v>o7fYd66 ze#lzV&#fCiWNDOk5Y-kS*u*+=0h>WFz!xt>G1;QmN34|-dH_}}BI6_6x9TUVE@C}s ze=%_p8_2rEi*FaP4{>zY>toieLn*5B%5SD97uEBk5oha`1tAA&SQ^!OrCaJNCUi@E z#dKW!_%RFe-;Y-sz(*H_*?%_!pYO@*b$>^T%8OZ7nk$AbW-a|};=Q@tSuAoFvozL} zTjQ3nI9gSokK&67v@5PV)wbj;doDtrKbM!lEhoh4r7Y~#B-3hJHYrK=h#!|?rupPO zYv?l8f@xAE!z^r6-I5jX^7v%|Dnp-R@LD_MDG*6SU4zs;M8zzx{-JUvEUnmNd`@4K;sWA&MNc`i&bW9*jq32>;1Ma>LzjT3y3PJ=_#L% zve#_p9@K37sF%ryjn}T&m5W?a4isf-4oK5TDx_nU&@y{ zOqZ{~WS8%h$tK^FbCB;VlTE%6=OLeUh?MVd!}K8z(az*c(L9G)pA|?2E)BFR@FEmA z3sSr;;D}^hz~2YGB4D~y;ObaN-vaCkybJ+< z7$}}yhJb4ZIs|NgMG9Ddh;{Z=sk_~x>J9cYT_@%oVO7|?LAo?91KyM-caTF}#W0!e zqV6$tt2{CB7#nUd`q>3B_}Mk}GXyE`XV=s%2=cI>ttC7E!ouaCdxG_`p7}+J(sQ8o z*>6&mZ^XJkAj%OzzlJEA`|G0A==)NXU`!dLVt(xJP|O{Of{moJ5T!`mI}1@_yzQcd zd)sw#7ot@6w(I0Ch~m>nJo}6NjSb3)`H-UhJt@VMe%9Il$QFBC#nxh_515f&6LT&? zmQ#InSvvH3MHb!4%lbIf@(8m0A?jXYEg9*fw@+dfn=G_7Fa9O~d(MF(y9~d?)vk(N zG5>=!je6P@^90@YaS!XHC+st3I9ds>+OK8!i9sH;qBZ$BTS3_lqkeOg&at0324`ci*uqpDFD00@$ zu^ox_jgeH3*EdG4b(15WpO+OscToY2*iGLPv0_iehq7l~vCU}v^@>}Dd0mmRwDSbE zBvE&RSKRDn=DWdhMTrqrv|!ettC(L!%LqA#$Y3%r$xJdQ$uUVLP6o)EPUD>pZo0UFIW74k2rWmzNf1IMW5v$eW`* zy)<)+p@>wcK?w-UNnMCs_?)Y4$#r=-sf(A-Fv(2-%1Lf3QRs!rHWj~nX^n8>FT`7W zht?2FytO*GFM32mC2>bWIZ@R|t49xs?mpTv_iy1wapC+(W~%{*zYie5ol5c{{4m>Q%-usWSYMv#_3ORdF08didb z#qYsdyA}r5SKDm>N`298iP4q|PXBki4HV--po$*i!w_wXZ+abzt+DG^ZaSqVg+aXG zF)@~KQ7Kdl!d#-Rgkhq4s8)pz5+g&kFt45{O#b?U{CzPp)L>!msTaD5b)nio*Rgdi zq0&4`>IyAPdrGGZiZc*{dq=y`nZvcwbeh-}u2rvGKEbBZ4Onu^E9qK-xEZePqK$>6 zn)X-QpV4hHHQz^>X?-7+N}lHPNGdf`V}%>SSmFQhEY-<&RY5+}&>=H5pGQR}ZL>Op zZ|){Tf7~ApsjdY@4|JB>CVd|HF|tCIx*XSIWZ26d&O+Ex#J#T8@zu3aPD%ZS zq5;v>GFt^5CL!h{{T*QqVL$Vc?vC(DlO9fTgwqhNYCh7z5pHD*cN}Vsh}M!AeI$k& zwJJOl4zMUjE0({xfx=7WZ*C-1OHI-k1nJDL)MJdDHQ%Log)r1SX+FZm*cFID(*g|Afj8ii*le51lY zQ~36Tl$V9=QX=*!e80jED*ULzPbmDf!p|x^U*Q)VJO#DCqYm{D=VdwY_#Zu!&C1Sh6cPV_o!Z#|Jex~s43g4yh zJqq8i@T2i%DKGl{38jG33O}pxe1%_7_$7s3QTTO*-&FXoFL+9+@sAgQQsZ5P|E=%` z3V*EdX9{OZ*K$(0tHM1Leo$&6#qRZvDrz~Q@Y4!EtMGh)>`o;3U^hwhmG6(e`O`YTjBl+Hz_<+;SmatQh2n&V-?;| z;Z0jB{y$EMNKklNg?ChVSA{1jytl&pD}1oRhdH?P|DzlM@G%M>ukc9ESzvL;#gD(TdqY6Kv@Y4!E ztMGhAe4N?~ydPf&PUg?ChVSA{1jytkdh{}&khD-nYgK1|`G6h21b z;}t$h;ZqepUE#A8KG*!h{}&kND-nwnzEt7M6~0p8YZRWL@Qn)pOyS#K@RS1Mt`~s< z;~s_YSNK7NA657Xg`ZaVS%v2-{DQ(SN$&9fSCokB3csoFUlsm`!tW~lZ-qZl_+y1X zQ+Ntf49!X5t_t^1cx8oqE8Jh!gjV;z>pmGTIqGWOtahzKqRo*4H|}GqxFprI!{al80(( z;++ASr}c-f+6`wXcWMaiJW~Ys(&BMX3y;0}YK>f3Aa-wuX#>kyv)j_r zJRyPjf)Ky0M{d_)B-oFT=J--w{&gMsU!V*Au#10+OeX)5&O9V70cPQEwiqHcG82D% zClc7%ix4w#v=9D93@{siKxTqO6aKgia1}Og(}7vxglq<0u1?5aV0aYr1r|gTauGP9 z4k5RIE9w$*Uxx9=X$&>A6jG}p_Eu|X#0`HLA{?07iI5oJv@R$Z7?_BHfm84YY?6U_ zJs<#ZbRP%+oGE`!AGmb@1OVQ`AB)%vtThAz0Iw!P0N{vW5CGVB1Oxy!A4iCDREkDU zf%rygq+}8ywSZagK~ccV(@-$*;&c=YOr3#(fzzPTRN%SUs5!6}CnOVCgdcc646H9u z05EtJ3aF`(%r&S8aLRf@)&c`JARW+iBO&KfKn`poqzIU|1up^p!S5umqS0EczD(0yjUzA9Vs=eoV+h;KC;)g{%VU{0ub#o_kKn0pMCn z$r<1@jgreivl}J1fTJr@@<_(}Q{r3)83j_}3v3-kNu!fn+8nF~Iw2l$e1B7EqEXpD#wiK({3* z7}$Od3I_Jgpkx(r;buy<0!L&~asZezVizUnKq9j#DFRN(!8f(Q@O?NFh=q~tr^E<6 zWu+t-D6fUo2WB6Hih)~?;77HA7mrgi0(kBOB~yT{PoiL8>M0Zqj5$q77BKQ_6b$Tn z9!(sJ{@*zts>XvS1yD6`?DtT$#2--OdU)|i6bzhp6*UD$UPn!Vr8g)^mhnZXseFDD z1p;sXi~@n-zoDkUizO%!xatoS2#ov_ze={U%o32gri zzu5&eXpCe6eGQE41vW3w$SL477e+1ujUJ5L0v@JSnn{?`ab)Rw{0 zQ9wIJf`RSZGZF)w*_jbD@OD>55`hPj7+DMq?g@a^d zBjCJ65D++UF$4tmTnYh!MHUDM%;JnB14~vgG6lG5B{Tv|UyXw{;Nf);7`QhBO$e;D zJ_RZP8J)>U3D9>VBnKL|Fyh=4ZM}^VUts<1j6?#nfQ^AAJ5VFws+}khn4XQc1Rmat zrUdTY2TcKM?Pp{yaI_UQ2KwfrV4(3ZDhzC%l7||D)IW|I1G9jn845UoHV3Xcg@S?U zU!l!`hreN@HE{1aMtTBkoo8eOaCAN+(}2DOC>Ut`4mJR6{sSXhf%PvlasZeGJOkYN zBbo}BGUW;i1{r$|HE52EZ=eQ1QjCm%t8SqNz^q?T17JZ3j0x!WCu#ufd>a)2KDmQ@ zfT@3>0xjS%fkt5DJv13G6Bq-Oe<{u^pFd&bb_=Zzxd`$I4=z7t#0`JMj}RCb@BlCd zIKd5F6u8(OJWf2Atu;-#ib={DH$r>56L!WOgH1(3CsZWtfRV6Tl`tq(AvCfI1}|U% zu$CvGV?8mtdJ)>%8)J+&VXb|ThaaI={fOq~k2rs#nFBDC2N0GXh&eO zKMY({mC*aZ116F}OECLsA4KT1Afn-?QCUnd5`+-^&=X-JLh({4p_hR@!w8)cMo9e# zqK%Hg1O<3Gf-q0alEzji?0$7Zog*5Oq2+X7cYZ9$< zP4Jq;X>3g#uN2fI#4Va=^`i-!hA9^Abkamju`=sIpjgbP>JgS*55smnLLUJ~)F*Up zeJl%s_kp(?5NgEC>q$dGJsT0yx)Gu2KMGfq-3Xb`jj&|QC+8&+mIv(HooI`@JA`He_l|>Ij3?Ud@r06hF@b%T&@AAz350H)0Na^BSjLm1xNifvO zn2Sz^fRhO`OhL0xL9a^zNu5I2BjClU(7^l1Xgb<)Iw^N91%=EZ<)$q_feVOJHn0@< zXaQ=r2wGZ%-taNBvKTd9ObpGJA)jTaZ8~9FmlMNGLD;EP(9~*lztyn(HH77TO4ymT z$Y(9O>^fpdS+xPG-2{W%M9R5sLAS%qx$hRjW`2&g+eWB)8w_a&+HePq4Y&fBorSKs zi!irr)F2xb$R^q;;MU!Q=Iw^Y_P~DjpyqoCE!m5v*@q_Fhxe=qTahl8FykRY@(!W> z9~~kFw>^{)> zD`?{@v^TKz8NwExK@)xrEq#pwfd_!Mfz8iCD`(+T&Z4J%gZ8iW4QhN2z2F?w4Lk=l zo`-RrM_U6kfoJm3hFA+s_!feFi!iY0TVzxSEQA2xLG2fzt&6BN@D#8V==?nj|DI?U zfxeee)+J~Qco9DtQ7wa+$N;t4h-}zp5H}x`wPA8FG5BGv;Knplw#79 zT#DM3qHtgqF!*mI!s;jaZ=!7mFZ!FXn1A42{~^@vKHBs?Y~Vg&zW<_7tcLmm#{zpk zAZ*10XzT&n7U=d6@ed&+@Zv+He?&;ZBUnDLaTyG{49*SPYjkrNVYMEk?H;2UfGdEh z|3iO$g3O)}`UGfv2E%y<$${y>aQrzHcv)hml=h^wTzdm$eam4z;Y4X)C#*Ao!R0Ag zi0fXN<*8Nxe#?c@CoWiPxKcX7l`^*ql+H`3fGM^crP)}PEq150z#Xe64@ysYP~usU zYOO0$au^t6M0{mRH&>=?N);^4JW-G*))}6ZjrPKV$BWX7z{B2@UiGG$rw>+7xW!lk zT>~bUVaeA%fNCoOC`maJKxqkxvk4iQu!J*FdH`4pf2(bD2&FSaD0>uw zbwenn?L)C338m~dFffeLm@q6Ye4mgC3(i^#3OGeC1RR2q$~q-d(013p67w+@8Ey0U%@GKfJ2 zz%wzFCDx^M1lF19z|9h4DJzJj_;bDZ-U{o^_Q27=(t4CltB>>zu&`-BwJhMR##9S# zf)BaYHi7z@P#uXsjirfh{30 zFd29m#&Fw=JmRS~A|CI@Q<@!58A-shFahrajjfQj6`BS3q!kuRDXl4Oj+Jd>8`Q83 zY@rRMS->J7!Akf4(RBxKHQoRJz(42SQ*J~dG;3tq*0xM&G{UttV$Cwm+C(81LM#^I zUSvY!B2Fw^gb-q(5euPBEQDByW!iRUZQ2&P{NA7Qe(nGL{vZF}-{bMQr|0MW{=CoU zo^$R!_a1d`W`D&HK0q-h(f0z1Fxr;`6=M;-^DPQjjCJ8O3Ho4}AbO)4OUoo$su8rg zBk1j41dSg;yJd)?B-65tmesTjdY^XV`-%vqqc$Ou_P_ryMJ@W6X8tj4p5e4_Y7^+*O;n5t6BQ+k zmKC%NPoRlSq62Lb{n^MQMKsXTYcd_Ylj#_vWn7|SQBo4=h)<;bNz2@+bfiwDBYzql z`SiQ9g|sw%O8e|n+P}0kCDDYEs8A9;yr$D+XDW(qrXuQQ(IjRoB8vV#C5e^|vlT;n z3T??0#aK;m@1y4^igga{b6To%Y3tE$54F-(o@b$ZGfxq|^Jz2Ar`ax`#09jXRK?)6 zkdEZf6<tiW0b(Rw9>6XumF@dqd0ArL=#S(nW}LMafU6P5*^r45DiVxwNdOWxz5; ziCRW0qh$pxLs!sNT|wh%Sw_onKhaACl=>jx9?unAa;JGMn~awqgj{N|$4{(WmWhr_H^cu7uFCfR+wg2IkPgoJ03I zM^WV0u=?zvJGp}$Y`1Q zhhj+jlb$vIq$d?xCO%M<%m;LDX&F#Q_x>+h(O-0g|E(A*|E7oKL&a!)NE3Xd7;_)d z?s=>j8Xhacw}C#1ExLgQHYi4aCp}v^>FJS{eotsqKcPajtbU>xL!T;!jHfgK#h_Rf zgQ0*nP$m5wV4$lY^h^3hv`lg_7;{|c`VlR?UFo;^T@50emH~|nikYr6rO`5zmihEC z2VQi&Dc;SXq`1*V3p@RgPaQ>#4aSH)Q z&0XwJ@?3Q)^qxjo=p3TZLtdB-^je8*vxZ%r@7 zX=!RBXp7N1;x_cAgMJS47D}`?y}Nma-a*j?hv0T}_u31!l&&KL`3aS-7pT5;Eui!j zVK8?R23r@p(_QKHUvgJkNmsh}^xj?#qI(%c|C#W*P=o1xdi)!-B|_+}a)=OFy=ek{ z=>0(-dVScJ-s90*a~r)4cf3ilx9COYTeL;!MPXSey)1v5UVOey?-yv9_O@`f(a+`d zvxAm_^fsK{ii@oN!dPmdAMyv#%i{s`KA+x`Cx+1^1`5S{Al)-s7SS?t5KUwdZ53L2 zz9S5g@6djvx8nifLL|{Lm6ipxG`&mr>Rs9;@6s-zWj!sc2Gd*Z_vjt(d-OtEdwLzJzS(Pm_DGl z)*lEFM$1H6Mhz2&tYI|C4{0JF(nM%U-!~{q=&if^NAwDs-o97UGT>u+1x;_;6KR=A zZ{>aIZF|sg`TC!JNTc`fiS+(GKbl^G(|h-HdJkVtOZgvA-XrPWkEAygv{YkgA~E#t zhL#2Np1wX-7=uR9fkf};lWCbt%eqnY=5;h3N2BT86fLW1=`}_u{$pqh(=vsYIkYSq zBMfD(%^Bz5d8@qo#TZuemvd#@xq`^prd&L9nG{XOrS^5B%%0DqWwQf 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 U;j&%lC)swmXqRrU)^%Y0KZPrlPyhe` diff --git a/first_app.cpp b/first_app.cpp index 18d77df..93da035 100644 --- a/first_app.cpp +++ b/first_app.cpp @@ -70,62 +70,53 @@ namespace hk // temporary helper function, creates a 1x1x1 cube centered at offset std::unique_ptr createCubeModel(hk::Device &device, glm::vec3 offset) { - std::vector vertices{ - + Model::Builder modelBuilder{}; + modelBuilder.vertices = { // left face (white) {{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}}, {{-.5f, .5f, .5f}, {.9f, .9f, .9f}}, {{-.5f, -.5f, .5f}, {.9f, .9f, .9f}}, - {{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}}, {{-.5f, .5f, -.5f}, {.9f, .9f, .9f}}, - {{-.5f, .5f, .5f}, {.9f, .9f, .9f}}, // right face (yellow) {{.5f, -.5f, -.5f}, {.8f, .8f, .1f}}, {{.5f, .5f, .5f}, {.8f, .8f, .1f}}, {{.5f, -.5f, .5f}, {.8f, .8f, .1f}}, - {{.5f, -.5f, -.5f}, {.8f, .8f, .1f}}, {{.5f, .5f, -.5f}, {.8f, .8f, .1f}}, - {{.5f, .5f, .5f}, {.8f, .8f, .1f}}, // top face (orange, remember y axis points down) {{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, {{.5f, -.5f, .5f}, {.9f, .6f, .1f}}, {{-.5f, -.5f, .5f}, {.9f, .6f, .1f}}, - {{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, {{.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, - {{.5f, -.5f, .5f}, {.9f, .6f, .1f}}, // bottom face (red) {{-.5f, .5f, -.5f}, {.8f, .1f, .1f}}, {{.5f, .5f, .5f}, {.8f, .1f, .1f}}, {{-.5f, .5f, .5f}, {.8f, .1f, .1f}}, - {{-.5f, .5f, -.5f}, {.8f, .1f, .1f}}, {{.5f, .5f, -.5f}, {.8f, .1f, .1f}}, - {{.5f, .5f, .5f}, {.8f, .1f, .1f}}, // nose face (blue) {{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, {{.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, {{-.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, - {{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, {{.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, - {{.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, // tail face (green) {{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, {{.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, {{-.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, - {{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, {{.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, - {{.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, - }; - for (auto &v : vertices) + for (auto &v : modelBuilder.vertices) { v.position += offset; } - return std::make_unique(device, vertices); + + modelBuilder.indices = {0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 8, 11, 9, + 12, 13, 14, 12, 15, 13, 16, 17, 18, 16, 19, 17, 20, 21, 22, 20, 23, 21}; + + return std::make_unique(device, modelBuilder); } void FirstApp::loadGameObjects() diff --git a/hk_device.cpp b/hk_device.cpp index fc28176..686d75f 100644 --- a/hk_device.cpp +++ b/hk_device.cpp @@ -55,7 +55,7 @@ namespace hk } // class member functions - Device::Device(Window &window) : window{window} + Device::Device(Window &window) : m_window{window} { createInstance(); setupDebugMessenger(); @@ -67,16 +67,16 @@ namespace hk Device::~Device() { - vkDestroyCommandPool(device_, commandPool, nullptr); - vkDestroyDevice(device_, nullptr); + vkDestroyCommandPool(m_device, m_commandPool, nullptr); + vkDestroyDevice(m_device, nullptr); if (enableValidationLayers) { - DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + DestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr); } - vkDestroySurfaceKHR(instance, surface_, nullptr); - vkDestroyInstance(instance, nullptr); + vkDestroySurfaceKHR(m_instance, m_surface, nullptr); + vkDestroyInstance(m_instance, nullptr); } void Device::createInstance() @@ -118,7 +118,7 @@ namespace hk createInfo.pNext = nullptr; } - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) + if (vkCreateInstance(&createInfo, nullptr, &m_instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } @@ -129,36 +129,36 @@ namespace hk void Device::pickPhysicalDevice() { uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr); if (deviceCount == 0) { throw std::runtime_error("failed to find GPUs with Vulkan support!"); } std::cout << "Device count: " << deviceCount << std::endl; std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data()); for (const auto &device : devices) { if (isDeviceSuitable(device)) { - physicalDevice = device; + m_physicalDevice = device; break; } } - if (physicalDevice == VK_NULL_HANDLE) + if (m_physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } - vkGetPhysicalDeviceProperties(physicalDevice, &properties); + vkGetPhysicalDeviceProperties(m_physicalDevice, &properties); std::cout << "physical device: " << properties.deviceName << std::endl; } void Device::createLogicalDevice() { - QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + QueueFamilyIndices indices = findQueueFamilies(m_physicalDevice); std::vector queueCreateInfos; std::set uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily}; @@ -184,16 +184,16 @@ namespace hk createInfo.pQueueCreateInfos = queueCreateInfos.data(); createInfo.pEnabledFeatures = &deviceFeatures; - + // Add device extensions, including portability subset if available (needed for MoltenVK) - std::vector enabledExtensions(deviceExtensions.begin(), deviceExtensions.end()); - + std::vector enabledExtensions(deviceExtensions.begin(), deviceExtensions.end()); + // Check if VK_KHR_portability_subset is available and add it if needed uint32_t extensionCount; - vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr); + vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extensionCount, nullptr); std::vector availableExtensions(extensionCount); - vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data()); - + vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extensionCount, availableExtensions.data()); + for (const auto &extension : availableExtensions) { if (strcmp(extension.extensionName, "VK_KHR_portability_subset") == 0) @@ -202,7 +202,7 @@ namespace hk break; } } - + createInfo.enabledExtensionCount = static_cast(enabledExtensions.size()); createInfo.ppEnabledExtensionNames = enabledExtensions.data(); @@ -218,13 +218,13 @@ namespace hk createInfo.enabledLayerCount = 0; } - if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device_) != VK_SUCCESS) + if (vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device) != VK_SUCCESS) { throw std::runtime_error("failed to create logical device!"); } - vkGetDeviceQueue(device_, indices.graphicsFamily, 0, &graphicsQueue_); - vkGetDeviceQueue(device_, indices.presentFamily, 0, &presentQueue_); + vkGetDeviceQueue(m_device, indices.graphicsFamily, 0, &m_graphicsQueue); + vkGetDeviceQueue(m_device, indices.presentFamily, 0, &m_presentQueue); } void Device::createCommandPool() @@ -237,13 +237,13 @@ namespace hk poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - if (vkCreateCommandPool(device_, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) + if (vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool) != VK_SUCCESS) { throw std::runtime_error("failed to create command pool!"); } } - void Device::createSurface() { window.createWindowSurface(instance, &surface_); } + void Device::createSurface() { m_window.createWindowSurface(m_instance, &m_surface); } bool Device::isDeviceSuitable(VkPhysicalDevice device) { @@ -285,7 +285,7 @@ namespace hk return; VkDebugUtilsMessengerCreateInfoEXT createInfo; populateDebugMessengerCreateInfo(createInfo); - if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) + if (CreateDebugUtilsMessengerEXT(m_instance, &createInfo, nullptr, &m_debugMessenger) != VK_SUCCESS) { throw std::runtime_error("failed to set up debug messenger!"); } @@ -408,7 +408,7 @@ namespace hk indices.graphicsFamilyHasValue = true; } VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface_, &presentSupport); + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport); if (queueFamily.queueCount > 0 && presentSupport) { indices.presentFamily = i; @@ -428,26 +428,26 @@ namespace hk SwapChainSupportDetails Device::querySwapChainSupport(VkPhysicalDevice device) { SwapChainSupportDetails details; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.capabilities); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities); uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, nullptr); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr); if (formatCount != 0) { details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, details.formats.data()); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data()); } uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, nullptr); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr); if (presentModeCount != 0) { details.presentModes.resize(presentModeCount); vkGetPhysicalDeviceSurfacePresentModesKHR( device, - surface_, + m_surface, &presentModeCount, details.presentModes.data()); } @@ -460,7 +460,7 @@ namespace hk for (VkFormat format : candidates) { VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props); + vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &props); if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { @@ -478,7 +478,7 @@ namespace hk uint32_t Device::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { VkPhysicalDeviceMemoryProperties memProperties; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); + vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memProperties); for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { if ((typeFilter & (1 << i)) && @@ -504,25 +504,25 @@ namespace hk bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(device_, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) + if (vkCreateBuffer(m_device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { throw std::runtime_error("failed to create vertex buffer!"); } VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(device_, buffer, &memRequirements); + vkGetBufferMemoryRequirements(m_device, buffer, &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - if (vkAllocateMemory(device_, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) + if (vkAllocateMemory(m_device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) { throw std::runtime_error("failed to allocate vertex buffer memory!"); } - vkBindBufferMemory(device_, buffer, bufferMemory, 0); + vkBindBufferMemory(m_device, buffer, bufferMemory, 0); } VkCommandBuffer Device::beginSingleTimeCommands() @@ -530,11 +530,11 @@ namespace hk VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = commandPool; + allocInfo.commandPool = m_commandPool; allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; - vkAllocateCommandBuffers(device_, &allocInfo, &commandBuffer); + vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer); VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -553,10 +553,10 @@ namespace hk submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; - vkQueueSubmit(graphicsQueue_, 1, &submitInfo, VK_NULL_HANDLE); - vkQueueWaitIdle(graphicsQueue_); + vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(m_graphicsQueue); - vkFreeCommandBuffers(device_, commandPool, 1, &commandBuffer); + vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer); } void Device::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) @@ -606,25 +606,25 @@ namespace hk VkImage &image, VkDeviceMemory &imageMemory) { - if (vkCreateImage(device_, &imageInfo, nullptr, &image) != VK_SUCCESS) + if (vkCreateImage(m_device, &imageInfo, nullptr, &image) != VK_SUCCESS) { throw std::runtime_error("failed to create image!"); } VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(device_, image, &memRequirements); + vkGetImageMemoryRequirements(m_device, image, &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - if (vkAllocateMemory(device_, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) + if (vkAllocateMemory(m_device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) { throw std::runtime_error("failed to allocate image memory!"); } - if (vkBindImageMemory(device_, image, imageMemory, 0) != VK_SUCCESS) + if (vkBindImageMemory(m_device, image, imageMemory, 0) != VK_SUCCESS) { throw std::runtime_error("failed to bind image memory!"); } diff --git a/hk_device.hpp b/hk_device.hpp index 4fd8d1c..0698f89 100644 --- a/hk_device.hpp +++ b/hk_device.hpp @@ -43,15 +43,15 @@ namespace hk Device(Device &&) = delete; Device &operator=(Device &&) = delete; - VkCommandPool getCommandPool() { return commandPool; } - VkDevice device() { return device_; } - VkSurfaceKHR surface() { return surface_; } - VkQueue graphicsQueue() { return graphicsQueue_; } - VkQueue presentQueue() { return presentQueue_; } + VkCommandPool getCommandPool() { return m_commandPool; } + VkDevice device() { return m_device; } + VkSurfaceKHR surface() { return m_surface; } + VkQueue graphicsQueue() { return m_graphicsQueue; } + VkQueue presentQueue() { return m_presentQueue; } - SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(physicalDevice); } + SwapChainSupportDetails getSwapChainSupport() { return querySwapChainSupport(m_physicalDevice); } uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); - QueueFamilyIndices findPhysicalQueueFamilies() { return findQueueFamilies(physicalDevice); } + QueueFamilyIndices findPhysicalQueueFamilies() { return findQueueFamilies(m_physicalDevice); } VkFormat findSupportedFormat( const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); @@ -94,16 +94,16 @@ namespace hk bool checkDeviceExtensionSupport(VkPhysicalDevice device); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); - VkInstance instance; - VkDebugUtilsMessengerEXT debugMessenger; - VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; - Window &window; - VkCommandPool commandPool; + VkInstance m_instance; + VkDebugUtilsMessengerEXT m_debugMessenger; + VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; + Window &m_window; + VkCommandPool m_commandPool; - VkDevice device_; - VkSurfaceKHR surface_; - VkQueue graphicsQueue_; - VkQueue presentQueue_; + VkDevice m_device; + VkSurfaceKHR m_surface; + VkQueue m_graphicsQueue; + VkQueue m_presentQueue; const std::vector validationLayers = {"VK_LAYER_KHRONOS_validation"}; const std::vector deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; diff --git a/hk_model.cpp b/hk_model.cpp index fb549ee..c0252a2 100644 --- a/hk_model.cpp +++ b/hk_model.cpp @@ -4,45 +4,112 @@ #include namespace hk{ - Model::Model(Device &device, const std::vector &vertices) - : device{device} + Model::Model(Device &device, const Builder &builder) + : m_device{device} { - createVertexBuffers(vertices); + createVertexBuffers(builder.vertices); + createIndexBuffers(builder.indices); } Model::~Model() { - vkDestroyBuffer(device.device(), vertexBuffer, nullptr); - vkFreeMemory(device.device(), vertexBufferMemory, nullptr); + vkDestroyBuffer(m_device.device(), m_vertexBuffer, nullptr); + vkFreeMemory(m_device.device(), m_vertexBufferMemory, nullptr); + vkDestroyBuffer(m_device.device(), m_indexBuffer, nullptr); + vkFreeMemory(m_device.device(), m_indexBufferMemory, nullptr); } void Model::createVertexBuffers(const std::vector &vertices) { - vertexCount = static_cast(vertices.size()); - assert(vertexCount >= 3 && "Vertex count must be at least 3"); - VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount; - device.createBuffer( + m_vertexCount = static_cast(vertices.size()); + assert(m_vertexCount >= 3 && "Vertex count must be at least 3"); + VkDeviceSize bufferSize = sizeof(vertices[0]) * m_vertexCount; + + VkBuffer stagingBuffer; + VkDeviceMemory stagingBufferMemory; + m_device.createBuffer( bufferSize, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - vertexBuffer, - vertexBufferMemory + stagingBuffer, + stagingBufferMemory ); void *data; - vkMapMemory(device.device(), vertexBufferMemory, 0, bufferSize, 0, &data); + vkMapMemory(m_device.device(), stagingBufferMemory, 0, bufferSize, 0, &data); memcpy(data, vertices.data(), static_cast(bufferSize)); - vkUnmapMemory(device.device(), vertexBufferMemory); + vkUnmapMemory(m_device.device(), stagingBufferMemory); + + m_device.createBuffer( + bufferSize, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + m_vertexBuffer, + m_vertexBufferMemory + ); + m_device.copyBuffer(stagingBuffer, m_vertexBuffer, bufferSize); + + vkDestroyBuffer(m_device.device(), stagingBuffer, nullptr); + vkFreeMemory(m_device.device(), stagingBufferMemory, nullptr); + } + + void Model::createIndexBuffers(const std::vector &indices) + { + m_indexCount = static_cast(indices.size()); + m_hasIndexBuffer = m_indexCount > 0; + + if (!m_hasIndexBuffer) + return; + + VkDeviceSize bufferSize = sizeof(indices[0]) * m_indexCount; + + VkBuffer stagingBuffer; + VkDeviceMemory stagingBufferMemory; + m_device.createBuffer( + bufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + stagingBuffer, + stagingBufferMemory + ); + void *data; + vkMapMemory(m_device.device(), stagingBufferMemory, 0, bufferSize, 0, &data); + memcpy(data, indices.data(), static_cast(bufferSize)); + vkUnmapMemory(m_device.device(), stagingBufferMemory); + + m_device.createBuffer( + bufferSize, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + m_indexBuffer, + m_indexBufferMemory + ); + m_device.copyBuffer(stagingBuffer, m_indexBuffer, bufferSize); + + vkDestroyBuffer(m_device.device(), stagingBuffer, nullptr); + vkFreeMemory(m_device.device(), stagingBufferMemory, nullptr); } void Model::bind(VkCommandBuffer commandBuffer) { - VkBuffer buffers[] = {vertexBuffer}; + VkBuffer buffers[] = {m_vertexBuffer}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets); + + if (m_hasIndexBuffer) + { + vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT32); + } } void Model::draw(VkCommandBuffer commandBuffer) { - vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0); + if (m_hasIndexBuffer) + { + vkCmdDrawIndexed(commandBuffer, m_indexCount, 1, 0, 0, 0); + } + else + { + vkCmdDraw(commandBuffer, m_vertexCount, 1, 0, 0); + } } std::vector Model::Vertex::getBindingDescriptions() diff --git a/hk_model.hpp b/hk_model.hpp index 22d6550..6ddcc00 100644 --- a/hk_model.hpp +++ b/hk_model.hpp @@ -20,7 +20,13 @@ namespace hk{ static std::vector getAttributeDescriptions(); }; - Model(Device &device, const std::vector &vertices); + struct Builder + { + std::vector vertices; + std::vector indices; + }; + + Model(Device &device, const Builder &builder); ~Model(); Model(const Model &) = delete; @@ -30,10 +36,16 @@ namespace hk{ void draw(VkCommandBuffer commandBuffer); private: void createVertexBuffers(const std::vector &vertices); + void createIndexBuffers(const std::vector &indices); - Device &device; - VkBuffer vertexBuffer; - VkDeviceMemory vertexBufferMemory; - uint32_t vertexCount; + Device &m_device; + VkBuffer m_vertexBuffer; + VkDeviceMemory m_vertexBufferMemory; + uint32_t m_vertexCount; + + bool m_hasIndexBuffer = false; + VkBuffer m_indexBuffer; + VkDeviceMemory m_indexBufferMemory; + uint32_t m_indexCount; }; } \ No newline at end of file diff --git a/hk_pipeline.cpp b/hk_pipeline.cpp index 4c211b9..827c122 100644 --- a/hk_pipeline.cpp +++ b/hk_pipeline.cpp @@ -14,21 +14,21 @@ namespace hk Device& device, const std::string &vertFilePath, const std::string &fragFilePath, - const PipelineConfigInfo& configInfo) : device(device) + const PipelineConfigInfo& configInfo) : m_device(device) { createGraphicPipeline(vertFilePath, fragFilePath, configInfo); } Pipeline::~Pipeline() { - vkDestroyShaderModule(device.device(), vertShaderModule, nullptr); - vkDestroyShaderModule(device.device(), fragShaderModule, nullptr); - vkDestroyPipeline(device.device(), graphicPipeline, nullptr); + vkDestroyShaderModule(m_device.device(), m_vertShaderModule, nullptr); + vkDestroyShaderModule(m_device.device(), m_fragShaderModule, nullptr); + vkDestroyPipeline(m_device.device(), m_graphicPipeline, nullptr); } void Pipeline::bind(VkCommandBuffer commandBuffer) { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicPipeline); + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicPipeline); } void Pipeline::defaultPipelineConfigInfo(PipelineConfigInfo& configInfo) @@ -134,13 +134,13 @@ namespace hk std::vector vertCode = readFile(vertFilePath); std::vector fragCode = readFile(fragFilePath); - createShaderModule(vertCode, &vertShaderModule); - createShaderModule(fragCode, &fragShaderModule); + createShaderModule(vertCode, &m_vertShaderModule); + createShaderModule(fragCode, &m_fragShaderModule); VkPipelineShaderStageCreateInfo shaderStages[2]; shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].module = vertShaderModule; + shaderStages[0].module = m_vertShaderModule; shaderStages[0].pName = "main"; shaderStages[0].flags = 0; shaderStages[0].pNext = nullptr; @@ -148,7 +148,7 @@ namespace hk shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStages[1].module = fragShaderModule; + shaderStages[1].module = m_fragShaderModule; shaderStages[1].pName = "main"; shaderStages[1].flags = 0; shaderStages[1].pNext = nullptr; @@ -184,7 +184,7 @@ namespace hk pipelineInfo.basePipelineIndex = -1; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - if (vkCreateGraphicsPipelines(device.device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicPipeline) != VK_SUCCESS) + if (vkCreateGraphicsPipelines(m_device.device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_graphicPipeline) != VK_SUCCESS) { throw std::runtime_error("failed to create graphics pipeline!"); } @@ -197,7 +197,7 @@ namespace hk createInfo.codeSize = code.size(); createInfo.pCode = reinterpret_cast(code.data()); - if (vkCreateShaderModule(device.device(), &createInfo, nullptr, shaderModule) != VK_SUCCESS) + if (vkCreateShaderModule(m_device.device(), &createInfo, nullptr, shaderModule) != VK_SUCCESS) { throw std::runtime_error("failed to create shader module!"); } diff --git a/hk_pipeline.hpp b/hk_pipeline.hpp index 06a9f6a..a4d6c0f 100644 --- a/hk_pipeline.hpp +++ b/hk_pipeline.hpp @@ -53,9 +53,9 @@ namespace hk void createShaderModule(const std::vector& code, VkShaderModule* shaderModule); - Device& device; - VkPipeline graphicPipeline; - VkShaderModule vertShaderModule; - VkShaderModule fragShaderModule; + Device& m_device; + VkPipeline m_graphicPipeline; + VkShaderModule m_vertShaderModule; + VkShaderModule m_fragShaderModule; }; } \ No newline at end of file diff --git a/hk_swap_chain.cpp b/hk_swap_chain.cpp index 01d7e19..b985081 100644 --- a/hk_swap_chain.cpp +++ b/hk_swap_chain.cpp @@ -13,19 +13,19 @@ namespace hk { SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent) - : device{deviceRef}, windowExtent{extent} + : m_device{deviceRef}, m_windowExtent{extent} { init(); } SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent, std::shared_ptr previous) - : device{deviceRef}, windowExtent{extent}, oldSwapChain{previous} + : m_device{deviceRef}, m_windowExtent{extent}, m_oldSwapChain{previous} { init(); // Reset currentFrame to 0 when creating a new swap chain - currentFrame = 0; + m_currentFrame = 0; // clean up old swap chain - oldSwapChain = nullptr; + m_oldSwapChain = nullptr; } void SwapChain::init() @@ -40,59 +40,59 @@ namespace hk SwapChain::~SwapChain() { - for (auto imageView : swapChainImageViews) + for (auto imageView : m_swapChainImageViews) { - vkDestroyImageView(device.device(), imageView, nullptr); + vkDestroyImageView(m_device.device(), imageView, nullptr); } - swapChainImageViews.clear(); + m_swapChainImageViews.clear(); - if (swapChain != nullptr) + if (m_swapChain != nullptr) { - vkDestroySwapchainKHR(device.device(), swapChain, nullptr); - swapChain = nullptr; + vkDestroySwapchainKHR(m_device.device(), m_swapChain, nullptr); + m_swapChain = nullptr; } - for (int i = 0; i < depthImages.size(); i++) + for (int i = 0; i < m_depthImages.size(); i++) { - vkDestroyImageView(device.device(), depthImageViews[i], nullptr); - vkDestroyImage(device.device(), depthImages[i], nullptr); - vkFreeMemory(device.device(), depthImageMemorys[i], nullptr); + vkDestroyImageView(m_device.device(), m_depthImageViews[i], nullptr); + vkDestroyImage(m_device.device(), m_depthImages[i], nullptr); + vkFreeMemory(m_device.device(), m_depthImageMemorys[i], nullptr); } - for (auto framebuffer : swapChainFramebuffers) + for (auto framebuffer : m_swapChainFramebuffers) { - vkDestroyFramebuffer(device.device(), framebuffer, nullptr); + vkDestroyFramebuffer(m_device.device(), framebuffer, nullptr); } - vkDestroyRenderPass(device.device(), renderPass, nullptr); + vkDestroyRenderPass(m_device.device(), m_renderPass, nullptr); // cleanup synchronization objects - for (size_t i = 0; i < imageAvailableSemaphores.size(); i++) + for (size_t i = 0; i < m_imageAvailableSemaphores.size(); i++) { - vkDestroySemaphore(device.device(), renderFinishedSemaphores[i], nullptr); - vkDestroySemaphore(device.device(), imageAvailableSemaphores[i], nullptr); + vkDestroySemaphore(m_device.device(), m_renderFinishedSemaphores[i], nullptr); + vkDestroySemaphore(m_device.device(), m_imageAvailableSemaphores[i], nullptr); } for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroyFence(device.device(), inFlightFences[i], nullptr); + vkDestroyFence(m_device.device(), m_inFlightFences[i], nullptr); } } VkResult SwapChain::acquireNextImage(uint32_t *imageIndex) { vkWaitForFences( - device.device(), + m_device.device(), 1, - &inFlightFences[currentFrame], + &m_inFlightFences[m_currentFrame], VK_TRUE, std::numeric_limits::max()); // Acquire with a temporary semaphore, we'll use the imageIndex-specific one later VkResult result = vkAcquireNextImageKHR( - device.device(), - swapChain, + m_device.device(), + m_swapChain, std::numeric_limits::max(), - imageAvailableSemaphores[currentFrame % imageAvailableSemaphores.size()], + m_imageAvailableSemaphores[m_currentFrame % m_imageAvailableSemaphores.size()], VK_NULL_HANDLE, imageIndex); @@ -102,17 +102,17 @@ namespace hk VkResult SwapChain::submitCommandBuffers( const VkCommandBuffer *buffers, uint32_t *imageIndex) { - if (imagesInFlight[*imageIndex] != VK_NULL_HANDLE) + if (m_imagesInFlight[*imageIndex] != VK_NULL_HANDLE) { - vkWaitForFences(device.device(), 1, &imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX); + vkWaitForFences(m_device.device(), 1, &m_imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX); } - imagesInFlight[*imageIndex] = inFlightFences[currentFrame]; + m_imagesInFlight[*imageIndex] = m_inFlightFences[m_currentFrame]; VkSubmitInfo submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; // Use the semaphore associated with the currentFrame for waiting (from acquireNextImage) - VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame % imageAvailableSemaphores.size()]}; + VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame % m_imageAvailableSemaphores.size()]}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; @@ -122,12 +122,12 @@ namespace hk submitInfo.pCommandBuffers = buffers; // Use the semaphore associated with this specific image for signaling - VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[*imageIndex]}; + VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[*imageIndex]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - vkResetFences(device.device(), 1, &inFlightFences[currentFrame]); - if (vkQueueSubmit(device.graphicsQueue(), 1, &submitInfo, inFlightFences[currentFrame]) != + vkResetFences(m_device.device(), 1, &m_inFlightFences[m_currentFrame]); + if (vkQueueSubmit(m_device.graphicsQueue(), 1, &submitInfo, m_inFlightFences[m_currentFrame]) != VK_SUCCESS) { throw std::runtime_error("failed to submit draw command buffer!"); @@ -139,22 +139,22 @@ namespace hk presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; - VkSwapchainKHR swapChains[] = {swapChain}; + VkSwapchainKHR swapChains[] = {m_swapChain}; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = imageIndex; - auto result = vkQueuePresentKHR(device.presentQueue(), &presentInfo); + auto result = vkQueuePresentKHR(m_device.presentQueue(), &presentInfo); - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; + m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; return result; } void SwapChain::createSwapChain() { - SwapChainSupportDetails swapChainSupport = device.getSwapChainSupport(); + SwapChainSupportDetails swapChainSupport = m_device.getSwapChainSupport(); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); @@ -169,7 +169,7 @@ namespace hk VkSwapchainCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = device.surface(); + createInfo.surface = m_device.surface(); createInfo.minImageCount = imageCount; createInfo.imageFormat = surfaceFormat.format; @@ -178,7 +178,7 @@ namespace hk createInfo.imageArrayLayers = 1; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - QueueFamilyIndices indices = device.findPhysicalQueueFamilies(); + QueueFamilyIndices indices = m_device.findPhysicalQueueFamilies(); uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily}; if (indices.graphicsFamily != indices.presentFamily) @@ -200,9 +200,9 @@ namespace hk createInfo.presentMode = presentMode; createInfo.clipped = VK_TRUE; - createInfo.oldSwapchain = oldSwapChain == nullptr ? VK_NULL_HANDLE : oldSwapChain->swapChain; + createInfo.oldSwapchain = m_oldSwapChain == nullptr ? VK_NULL_HANDLE : m_oldSwapChain->m_swapChain; - if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &swapChain) != VK_SUCCESS) + if (vkCreateSwapchainKHR(m_device.device(), &createInfo, nullptr, &m_swapChain) != VK_SUCCESS) { throw std::runtime_error("failed to create swap chain!"); } @@ -211,31 +211,31 @@ namespace hk // allowed to create a swap chain with more. That's why we'll first query the final number of // images with vkGetSwapchainImagesKHR, then resize the container and finally call it again to // retrieve the handles. - vkGetSwapchainImagesKHR(device.device(), swapChain, &imageCount, nullptr); - swapChainImages.resize(imageCount); - vkGetSwapchainImagesKHR(device.device(), swapChain, &imageCount, swapChainImages.data()); + vkGetSwapchainImagesKHR(m_device.device(), m_swapChain, &imageCount, nullptr); + m_swapChainImages.resize(imageCount); + vkGetSwapchainImagesKHR(m_device.device(), m_swapChain, &imageCount, m_swapChainImages.data()); - swapChainImageFormat = surfaceFormat.format; - swapChainExtent = extent; + m_swapChainImageFormat = surfaceFormat.format; + m_swapChainExtent = extent; } void SwapChain::createImageViews() { - swapChainImageViews.resize(swapChainImages.size()); - for (size_t i = 0; i < swapChainImages.size(); i++) + m_swapChainImageViews.resize(m_swapChainImages.size()); + for (size_t i = 0; i < m_swapChainImages.size(); i++) { VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = swapChainImages[i]; + viewInfo.image = m_swapChainImages[i]; viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = swapChainImageFormat; + viewInfo.format = m_swapChainImageFormat; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(device.device(), &viewInfo, nullptr, &swapChainImageViews[i]) != + if (vkCreateImageView(m_device.device(), &viewInfo, nullptr, &m_swapChainImageViews[i]) != VK_SUCCESS) { throw std::runtime_error("failed to create texture image view!"); @@ -300,7 +300,7 @@ namespace hk renderPassInfo.dependencyCount = 1; renderPassInfo.pDependencies = &dependency; - if (vkCreateRenderPass(device.device(), &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) + if (vkCreateRenderPass(m_device.device(), &renderPassInfo, nullptr, &m_renderPass) != VK_SUCCESS) { throw std::runtime_error("failed to create render pass!"); } @@ -308,15 +308,15 @@ namespace hk void SwapChain::createFramebuffers() { - swapChainFramebuffers.resize(imageCount()); + m_swapChainFramebuffers.resize(imageCount()); for (size_t i = 0; i < imageCount(); i++) { - std::array attachments = {swapChainImageViews[i], depthImageViews[i]}; + std::array attachments = {m_swapChainImageViews[i], m_depthImageViews[i]}; VkExtent2D swapChainExtent = getSwapChainExtent(); VkFramebufferCreateInfo framebufferInfo = {}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass; + framebufferInfo.renderPass = m_renderPass; framebufferInfo.attachmentCount = static_cast(attachments.size()); framebufferInfo.pAttachments = attachments.data(); framebufferInfo.width = swapChainExtent.width; @@ -324,10 +324,10 @@ namespace hk framebufferInfo.layers = 1; if (vkCreateFramebuffer( - device.device(), + m_device.device(), &framebufferInfo, nullptr, - &swapChainFramebuffers[i]) != VK_SUCCESS) + &m_swapChainFramebuffers[i]) != VK_SUCCESS) { throw std::runtime_error("failed to create framebuffer!"); } @@ -337,14 +337,14 @@ namespace hk void SwapChain::createDepthResources() { VkFormat depthFormat = findDepthFormat(); - swapChainDepthFormat = depthFormat; + m_swapChainDepthFormat = depthFormat; VkExtent2D swapChainExtent = getSwapChainExtent(); - depthImages.resize(imageCount()); - depthImageMemorys.resize(imageCount()); - depthImageViews.resize(imageCount()); + m_depthImages.resize(imageCount()); + m_depthImageMemorys.resize(imageCount()); + m_depthImageViews.resize(imageCount()); - for (int i = 0; i < depthImages.size(); i++) + for (int i = 0; i < m_depthImages.size(); i++) { VkImageCreateInfo imageInfo{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -362,15 +362,15 @@ namespace hk imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.flags = 0; - device.createImageWithInfo( + m_device.createImageWithInfo( imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - depthImages[i], - depthImageMemorys[i]); + m_depthImages[i], + m_depthImageMemorys[i]); VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = depthImages[i]; + viewInfo.image = m_depthImages[i]; viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.format = depthFormat; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; @@ -379,7 +379,7 @@ namespace hk viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(device.device(), &viewInfo, nullptr, &depthImageViews[i]) != VK_SUCCESS) + if (vkCreateImageView(m_device.device(), &viewInfo, nullptr, &m_depthImageViews[i]) != VK_SUCCESS) { throw std::runtime_error("failed to create texture image view!"); } @@ -389,10 +389,10 @@ namespace hk void SwapChain::createSyncObjects() { // Create one set of semaphores for each swapchain image - imageAvailableSemaphores.resize(imageCount()); - renderFinishedSemaphores.resize(imageCount()); - inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); - imagesInFlight.resize(imageCount(), VK_NULL_HANDLE); + m_imageAvailableSemaphores.resize(imageCount()); + m_renderFinishedSemaphores.resize(imageCount()); + m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); + m_imagesInFlight.resize(imageCount(), VK_NULL_HANDLE); VkSemaphoreCreateInfo semaphoreInfo = {}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -403,9 +403,9 @@ namespace hk for (size_t i = 0; i < imageCount(); i++) { - if (vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != + if (vkCreateSemaphore(m_device.device(), &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != + vkCreateSemaphore(m_device.device(), &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) != VK_SUCCESS) { throw std::runtime_error("failed to create synchronization objects for a frame!"); @@ -414,7 +414,7 @@ namespace hk for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateFence(device.device(), &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) + if (vkCreateFence(m_device.device(), &fenceInfo, nullptr, &m_inFlightFences[i]) != VK_SUCCESS) { throw std::runtime_error("failed to create synchronization objects for a frame!"); } @@ -469,7 +469,7 @@ namespace hk } else { - VkExtent2D actualExtent = windowExtent; + VkExtent2D actualExtent = m_windowExtent; actualExtent.width = std::max( capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width)); @@ -483,7 +483,7 @@ namespace hk VkFormat SwapChain::findDepthFormat() { - return device.findSupportedFormat( + return m_device.findSupportedFormat( {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); diff --git a/hk_swap_chain.hpp b/hk_swap_chain.hpp index d05b2ee..d5d4d55 100644 --- a/hk_swap_chain.hpp +++ b/hk_swap_chain.hpp @@ -25,18 +25,18 @@ namespace hk SwapChain(const SwapChain &) = delete; SwapChain &operator=(const SwapChain &) = delete; - VkFramebuffer getFrameBuffer(int index) { return swapChainFramebuffers[index]; } - VkRenderPass getRenderPass() { return renderPass; } - VkImageView getImageView(int index) { return swapChainImageViews[index]; } - size_t imageCount() { return swapChainImages.size(); } - VkFormat getSwapChainImageFormat() { return swapChainImageFormat; } - VkExtent2D getSwapChainExtent() { return swapChainExtent; } - uint32_t width() { return swapChainExtent.width; } - uint32_t height() { return swapChainExtent.height; } + VkFramebuffer getFrameBuffer(int index) { return m_swapChainFramebuffers[index]; } + VkRenderPass getRenderPass() { return m_renderPass; } + VkImageView getImageView(int index) { return m_swapChainImageViews[index]; } + size_t imageCount() { return m_swapChainImages.size(); } + VkFormat getSwapChainImageFormat() { return m_swapChainImageFormat; } + VkExtent2D getSwapChainExtent() { return m_swapChainExtent; } + uint32_t width() { return m_swapChainExtent.width; } + uint32_t height() { return m_swapChainExtent.height; } float extentAspectRatio() { - return static_cast(swapChainExtent.width) / static_cast(swapChainExtent.height); + return static_cast(m_swapChainExtent.width) / static_cast(m_swapChainExtent.height); } VkFormat findDepthFormat(); @@ -45,8 +45,8 @@ namespace hk bool compareSwapFormats(const SwapChain &swapCahin) const { - return swapCahin.swapChainDepthFormat == swapChainDepthFormat && - swapCahin.swapChainImageFormat == swapChainImageFormat; + return swapCahin.m_swapChainDepthFormat == m_swapChainDepthFormat && + swapCahin.m_swapChainImageFormat == m_swapChainImageFormat; } private: @@ -65,30 +65,30 @@ namespace hk const std::vector &availablePresentModes); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities); - VkFormat swapChainImageFormat; - VkFormat swapChainDepthFormat; - VkExtent2D swapChainExtent; + VkFormat m_swapChainImageFormat; + VkFormat m_swapChainDepthFormat; + VkExtent2D m_swapChainExtent; - std::vector swapChainFramebuffers; - VkRenderPass renderPass; + std::vector m_swapChainFramebuffers; + VkRenderPass m_renderPass; - std::vector depthImages; - std::vector depthImageMemorys; - std::vector depthImageViews; - std::vector swapChainImages; - std::vector swapChainImageViews; + std::vector m_depthImages; + std::vector m_depthImageMemorys; + std::vector m_depthImageViews; + std::vector m_swapChainImages; + std::vector m_swapChainImageViews; - Device &device; - VkExtent2D windowExtent; + Device &m_device; + VkExtent2D m_windowExtent; - VkSwapchainKHR swapChain; - std::shared_ptr oldSwapChain; + VkSwapchainKHR m_swapChain; + std::shared_ptr m_oldSwapChain; - std::vector imageAvailableSemaphores; - std::vector renderFinishedSemaphores; - std::vector inFlightFences; - std::vector imagesInFlight; - size_t currentFrame = 0; + std::vector m_imageAvailableSemaphores; + std::vector m_renderFinishedSemaphores; + std::vector m_inFlightFences; + std::vector m_imagesInFlight; + size_t m_currentFrame = 0; }; } // namespace hk