From 92980fba0df30aae88f17d93503b33c61b752eae Mon Sep 17 00:00:00 2001 From: matthew Date: Sat, 9 Aug 2025 14:11:18 +1000 Subject: [PATCH] commit before deleting shaders --- assets/shaders/gradient.comp.spv | Bin 4404 -> 2140 bytes assets/shaders/gui.frag.spv | Bin 3160 -> 1336 bytes assets/shaders/gui.vert.spv | Bin 5648 -> 3772 bytes assets/shaders/pbr.frag.spv | Bin 8184 -> 7956 bytes src/gears/game.d | 131 +-------- src/gears/vulkan.d | 483 ++++++++++++++++--------------- src/shaders/gui.frag.glsl | 14 +- src/shaders/gui.layout | 5 + src/shaders/gui.vert.glsl | 56 ++-- src/shaders/pbr.frag.glsl | 6 +- src/shaders/pbr.vert.glsl | 25 ++ src/shaders/structures.layout | 60 +--- src/shared/util.d | 17 ++ 13 files changed, 346 insertions(+), 451 deletions(-) create mode 100644 src/shaders/gui.layout diff --git a/assets/shaders/gradient.comp.spv b/assets/shaders/gradient.comp.spv index f0d9fd667bcb46dbaad5035d0057a8e6140d8503..7ca20858e3be52260cf6a680a04866b83e951a4f 100644 GIT binary patch delta 218 zcmdm@bVopvnMs+Qft8Vgn}L@hoB;v^8JHLtCu$lpa!!nvWenLkm7CEp1Sl1pm|KvO zTI83SSd>~^!oc9pzyj380MyICAOpl8z8H{J1Y(BCjI654EDRuhAU-1ygXBScB_IX? z5I=15T8_nxo>D+7gMdN`K%ro;BmW326o$thZ)73+N-%Q59uq=HLLduH;vgHGIN*dGq=;aKR(+2;5LCRaEhRJ$F6gS0bIyO(KGWS+;?Yx+(fCNTGuj<}9hGZeG#ZUa zgum+fYo4DI-x*Cfdv$4L=}fQRICK8OS;5hhQ4DjoJ<;B1T=JNxm1J%3-J-)Ha(yKF zRP=>tRa6&kh`tixyjL}d-RETVGHwaofO+S z`GR@2(d=vAbZIfnCuyx^Y1=G=e0=9J#t*${D{joynvkuV_OzGSee8IT+$-yQ(hV1vgjWOd!w!XgEONC9iSmxU6r1i}_akZHp zIhkpauceKmrXxkka(39lxtfvhh>f{gzCq+5mf0qGr%@-M8_J}X~z<133-NDYnz9Ei%#Od+& z-DY3h4c4iWxxIqn3ufORY}8{Faf^*Tb~eE5dz=q2`yQ79%)ZB!0OJf$cP_xDJT@O- z+-Lk20*w0$wiIBTd9b?y#(f35Ct^O_*Kl6w%!~bU4!DcRoLyv=on6zzvuhYNSj-B{ zW;!RCx*c))J0?1y3e=cUy;vOikbIa?MMUfo>C^$kUXjjhz##mYK}E#EpZs9t#DAAK zxxg=bowo!G|0l)qC;wqZ9T2aGj_CzGD2|SAxbU@p4tWE<( z=!u;%-)7`n0`VrsqFY!U+a=t;N(Q#0MMF__PBS<<_xFD|0C){ z)XKzp->lXH$?ON5TIjq9VAIlbalS42*>6jn_Xr$+bbj-L*;y_m?-kAJ_Hy^Q`(O}t zFY2q1pEJgaMSlt5TalA{PCm}1>H7nn`@nB;>{sPajXk2>qGh4nYwCkREav^4e2KCD zmt0e2>Y$T{d(7V*?r_ul9`zW$^niX{opOiyJwiNpn|R);r$ylAGcB38(B~QH;6Eu3 zZ$w2z9QdEAb5fl3k8)PTXGCDk2-$K!E1CMt)apMc8QgrHmrVW8=LPBDR{urG#DV{< z8deMbhbBgkFNrE5z7hWPL9eI9S@ep}%OWs(MP_b%E8Zu1Iw$_Rh&Rb*!r40S@gMz6 zE_e(d>bxP&q7Jr;A~5P8TWQm9=PrIvSjM82mGl)A6La$ z^nuS65g2_S+uW~79zGjy3j;3{%YB>^fmzIT$-`&mhO-Z1Zb}FHL31LJ1 vy`kgBcd$9a?LIC`=02iNir*E{JNm5n`y%qyrQ?eojC^(u;s5FdxFq@y>8Xv| diff --git a/assets/shaders/gui.frag.spv b/assets/shaders/gui.frag.spv index d9f1e3dbc6ea9ff19a655c8bfae12767a462571a..6568e895a26c3e79b62465136be2dc434b782bd0 100644 GIT binary patch literal 1336 zcmZvbZEMqD6o#KQP4`mw=5%wL)^ziIGW?(-h{EVJ4vG^B`Z0tyj6j-}B%AsJ{CEB! zzX;yflZ54iXPljL?&rMRJ*RbAhl|EtFkQ21o|{rOP0K9E?V66Y{%|xr&Wp+M%U3VR zSTl}IBxhY&ZCP|0#wiasq#M#5>3!)F>5+6pb>uBd9sRXrf2&E`tQdb7_~+;T@Ix@3 z&x5@9nM6Snr%^D8vuIqzR}pzjjl4J=Czq3Ef~$-s57)S6Su=|0M=+ixvrIl1{6_OE zE~1kn33DMG%Xbt`=Sh@(j>0U;i!%4NazAF_#c5cCXZmyov5(8EvX0MQ z*U7bW*#+33!G+zNX5sgr#~1XX3BBwKEDi%@%6^%>D$-q z_&_myc;^{%L#q0&y)6_Lt^42ZFceud|wap#*UKJndop`s3so$&ox*t2|m&FYF z5pxT$y55tIP~VqjR=uZ3^8dFd_@mT3mPN>A1~Kt+2Rk~D(!-O|gBre{;C1{!K6SsUo)6`d15Quw0QOfKeiz>>eJMO~7JxSIoNUY7ft%Bm;j%ye3{3UlZRHzb<}Lye-}p zzc1bs6Yvx9tBOgC6>*@yC9S{fP+hZX2E*|2k4IsaXLXiL@?sYLTt{g#N#a8K3+M+= zpALqP!_j;mment59HvPYhvTG(M^$nfpT}wKl5CXLW8a{sNd6sqx;yvC>nfZS(MdSU zQ;DXhKkk-fAbHVX%R0X?gET*m(jS^LmPQd89GlZ5ejd)Esz}a+u3CF)J}>g0IAfkU zEq*IjPYpahAwGt=eNaAMOy%j*~cZnnk?cxldb|JX5@`&9y9D5tq7MVBc*Z znHp?pJ)B14xOnki;LtpcM)5RHWng`I??W+l;@uw=(ev+S(TSeG#-k4oquD%-izjiU zj8%iv8`kcdZ|liK!K{7H_Dh4;XAYx(j^eYb=D@ApJ6gYws<=oZ`%cTs1_rhD&}|xw zx{s5|q%LDyPwc35Igdwm8rj^`6P!9n>2W;H!>UQy)DxXwYp3LG(NSv`Z{fM{rQT6G zpGKb2`7#4-&S_LG44i%yef!3~0Ub+j`u04xZy?;oxIhe>|3w3OmKgMSIZZN+QAv?q z?Jhb$t-LXF?COpk*auo4=2=-qS=IQiSWK{)<>NSAw7QLpJ#V7%2$L}}0{h+Y>>>NE z{f^MQ)u*x{KHnFTleVqQKsMZYQw$+<{)HTz&(nc)%qqki9q7}^)SbPL?MQ~4ALsP_ zkYDx#!*5^g{OB*=5BX(3F#LWMyE6nW_M3;%ci8>mVZ;Xe)5GX7u)oCAWL@i)7;^G< zBT5eJtaAo(Z?ri65cbSA{@l;W3;(X2cl5+S&;0v(W*>df>X8@v!2W-@(dzg}Wpzs{cDF4;+{O->S%t1ie@AN{K}7C1w1UwCK9P4vOicG( zj4ip5nQ4d^eXYdkh-<-|a?@9){Bl#_@_<@n* zZLJVEIgob&M4Ng!=H9&}D`);c<~%UD-qnh~%k`f2+z*^w$jlnpretP>{vkeR`%o)A z3ywW9zoEg<^V^+!(O>A1nJF;z{HAA5JoL!S7})1}J@V4u5Pki(5Z?4Fq1^SNn3?!m NT5=-)Bku>|e*vNR9yI^} diff --git a/assets/shaders/gui.vert.spv b/assets/shaders/gui.vert.spv index 42d46a6d5e9c7d9936a7e48ab1e9773cc4ab496b..df1c78bc0ccfd86522c5ae6e93779754256d4c73 100644 GIT binary patch literal 3772 zcmZXV`Fa#p5XC#oOppK(5yEDiB#H|d5dotJWRk!TjU*V2xDL%s6IwexV^1f9xDZ4H zw`cMNd?5ev`#ityTd^H)zB5&Is_ItVt<%>#KH!ylyg_fb_q&&myDA`zwS|S+{H1!M-L7}iyHQY&!Z@fm!z5^=;d(&ajzU}*H=?y> zF`%S~VqYb%l=Ze8Bx%?PC@-eu4NIoMM!gemYSx^i|D|>kra?80{Eni^*?N}z)pisl zR|7u@Iw`Sb@0ennowR=2k8ar{%*)!txQ;7`n|UmI;kZufCz>Iz$Ho%a2;wwI;QGC@ zj%&B_`t0FKRHyx5V=it68~L17@tvgczxwRAYT??h&;C2^KlSI_9L4$zj?3$pyz85;{aGCMXl*@T8|Q6#QnR&j{^~<%`5L~Kt+g!%NxnSd z%KC$6;A?flG;GCU2Qr=-86U>!k~=%|ahK$qiNf}5sFlWzU^|c7i*GH8wtXetzwAQD z$JuFXy_r@_W(v=`;21i2Mf7ENcX1|<=MK*%{++p1e}zj_Q#^NQRA87rCY`>qc^~+T zHhuyRH-6TK%~@l!7ucLbF`qNQ=8e>p#aKac4gvoqmq$cc&yda246~N+ZrpSLo3O?!(k3H!){BKET-PE)Brk&qx-UxHBj~_`A z&m9@j?{!Hy>-S^n+&_5ov3XN))caJDxyZqf%^QQm|Ai#6_-%h~NXL)Oo%IC<@i!&$ z(Gxb`6?)0fzu#Mx&U|o|-;z!acf2i0F5HMT-n6X|A7Ea-+suQXzOnh{*}78c)L^a= zu^Y}N_pWr_5FEMKn~uZ(jnm1sGkheS!QK2t5+6Mm2X`4T$FI&oEH$wCUNFw;EfU9> zG3fa(F(pZ2c?-h={bO?nk9FB6yKMgN7UQd3HvcP&{sm`WP<6f;yxa4tbx`t%z&pa` z%{(jcUY6BiMRHUi2EOTX#vQ++7~b%60^FED4b}t4ob>UMz`HT~xOCpl1LfmCArJ$< z=(q{#ye071aj!}z79VxkCpeq;HR;7Vr({#-zRQ1IIx+B8=d|?hI%mWYi;p_&KOA+q z+iwb!LRItfhR+G?E4=mcw&Tq{FPnZJx?V0wCkEbPE=s4C^*beMKGOD6{2)?1U_z1}P0h{Z=8?h~BVc}IG&&bzXyV|~s`CkEc?yeGZ8&Q)>5 z;-e1t6plLV>!MKH*K4xbS9t5?ed+LKFG;6g+t&}I69aECA4;c|^}8&cIC%QteZUdV z_vdqg?;_{RH?c189ku(7O$`2C3n6IS6F>LQ6>Ez<0{;Fgwu!b7~YsMxHe=4~qaKEfS>aRPVy~VyG zaHjB8F?>6}6*dL-rkMMk^VwRymrXuA_mlbV3GhRL^|2+LK3an9<$dW}g7xu(bozj| zJ|0N7K8m?NipOVtJd{p;&gXsnBpaSS7WGBq4m=j<58orfdgMO*EOZ3c%wA#>|F`~2 HObY)1;vhG3 literal 5648 zcmaKv>2_2_5XWzrWP-AY3W|s^0YwExR74b&AjAQU5)HxK@iKFhxp*@(&JyB|EaHZu z;_egp6h43-d;}lCZ!YI}j{jfZu1PzGV|$9K`q$dkeS2bI+2-MBXdqeq)tqwvtLGT}XO)ykAc8d!5V5N0U}3Sv*v)CX127*?(Fu&vjE=%Wih~ zGm`*k)GjY`YIHm0?gILdn;Ckgku{hVwV9z}1?4`>6Q6WGp3~M`9P^crLBfjBtT6RB zm9+9Ur3%e)WNeLg+DRLAp~KE!BhT@)-kDC{AbroqnJ8v|mNpNh?M_^;Bt09q16w!C zdNyXrnX~ApDPGDN$Kq@zKgV|74>)TfO-_{O<4!AGl=pJyPe098<2dKosGBwKi8y)+ z?4(d^UW=ZxbgpL8WRJvf&hh-QG^v|qDc?{p#$O&cn?V;>l&zI;{sniBOVZibDe>uA zTuoa4-4{5knZ=c)*2v`GV!8j*BF>xd;6N)raj18eMfY7y$MelBX+4?5s@Tcv@U1w% zeUEf!XO+z7xX{D9x`laOzNaI}Vy8>P9{WoCiMW%r(pWc%Jr6}-EI*GP#@wsv>}!8&0_^QYH3|hO`9RxJb5=< z-{PDx@0!gWKd|q__c!W%MV&l$*kOXB`9?L#mae+Xi$7 z+)0u3#Xi7(4lwov_G^HV8|=3LD|+mAapunlHzs14zA0DTj7~|W2Wlg;$jQS0j5zV^ z&-A7ELH7<}CkOU(;-Q`2YU~AXM_;lR-0%3c-o`tHZ+?D*&KCM!kj;FN@nr_oMPKqA zbbl9MXJO}E!#?2jLhoH--@GX-+qYr(f~^r5w#;Lr0mk0&+Yw-PUONNK&TDso*?Bz} zVB8V%jRzR-64-$N<1GR^7+}0TV3PsHHvu*kV7xV8M?}nrwBffQ?FL@5F=e@j814BObm=#4>%g(@yTaT|JZQ3K2fwhH)prAj7Vdj8EuymDh8> zVb{mi!pKPuV(_8Ywc^x+*y}Y8&u506yFVZTXD{fy-(d6(zCpxVtBGANPTZ(CKIA11 zeM|&qGu$MZg+FJ8joFz07LS?#ErCwmJNoqdrE_N1*MwxwnEc#1Wa|f=-xaezBbnOR zxdYF8oiir>1#x`A=?|UXA&Y-WGX0w!o!=!e;$IQRm%BtfdMvW|W0LVTJ9@=q+_6M5 z{V{_PNwebCBQ}USbK>O0P95}`$CwK_Qjyj;{>LS-XYlpX>*C~P-^`&Qj*Xlny5UW6 ze2nmg@FNd7UlZpX@TCWIeiOp8$^VYX{X5=9oe@kX%=;u8~ zj!z|%<5K;O2`9&A-XC9bpkMG9IX;(ssXbdx?#mbQ!S5CkIlmNVfs+&cB7oM2UIu=T z>@4B*_}oVODke{}xe8f=%QO&s@; z#XbB}2xoxrTJd!v?w;v4^yzo@>3jP0lGh(rcHU{;%7>JjH|9DK@7+(Tc)j>Wk8KeD zL;g34v;LMpHvSIXCZb2=eTw65+$0(kZ4!~2+1)GxH=kQ2ZxJy^^SMnj_>}Un$E_mb z!0DI0g8ij>^g>fg}T(Y{trkF`+rnA*o27w4~etrAKO9E zVG((dt+&S{_xJy}FmUskl*}20^M67*xb^>}Wa7Z-za$Pu|MWs#>YHs%pA8@O#$B8e z5pQ!q59h!<%=anD%nD!596da9&fa{VmW&U++;4Pz?S8|}cUm$&`0@^*W8>RBDq{A` z=Na*5MJq+%7XO^biJy^-j_rBzvgl+uE2?}=)n4I<`@ep2+0 Jej#^@{sk6LAaMWy diff --git a/assets/shaders/pbr.frag.spv b/assets/shaders/pbr.frag.spv index 23992e99fddf660d0457e77cc5f069e494458a1a..33e0b49ebf8454b59985863d664a419b245f3204 100644 GIT binary patch delta 283 zcmexiKgEuhnMs+Qft8Vgn}L^sX(I1@)_)8P42&B$^0V3g0kVQK5>rx(Lh~}y@{4kd z85r1r5F`!)1v!bysTuh>Km`n}49pB5oxwoN3WSWC|FY$?1cH<@0kH>A2&PRL$Oi#; z1{SauMIf6IiLV5b1OkveBTxb)4>AMH-@KRGo7EI#6dMpL0G0fON`u6#p?r`_Kw2aj vI2rx}X^>jR$rA;HCkF^}h=OecihyK5IzW8J&AEcJIVZo7lGw~5^Mx4zeB~|F delta 535 zcmYk3&q@MO6vodu&L4Az5@``_O4lu0g+{A_7AevLNErs2VGrON1Y)}u(Id#Ld!tsZ z6ten$ml^0>4)>hzJKuNj<-W96r>S3RMizKhwbasi`W93?vt+s44qK6`-mrf=m|j2J z-%Y0DC$mrsoOm4dZwAB3NCOs_Zzy}h1Fa<6gp+cY(UPDGL4~Y|R&j1+CplD&W6?Jt z74(S+csyL6eN-=lW2{0!2O5c0LxY{nG04mi`h>e_#l%pWQ7;J{xc__Jp4K!gu?q4R|O)6JZ) zBoLx2Ax6GxccQieE9V$nf$10B92e{889XEuhMswNyxaP#b 0 ? 1 : 0), + pPushConstantRanges: (push_const_size > 0 ? &const_range : null), + }; + + PipelineLayout layout; + VkResult result = vkCreatePipelineLayout(vk.device, &layout_info, null, &layout); + VkCheckA("CreatePipelineLayout failure", result); + + return layout; +} + bool InitConversionPipeline(Vulkan* vk) { Push(vk, SI.Pipelines); - VkDescriptorBindingFlags[] binding_flags; - binding_flags[] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; - - VkDescriptorSetLayoutBindingFlagsCreateInfo flag_info = { - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, - bindingCount: cast(u32)binding_flags.length, - pBindingFlags: binding_flags.ptr, - }; - VkDescriptorSetLayoutBinding[] layout_bindings = [ { binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT }, { binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_COMPUTE_BIT }, ]; - VkDescriptorSetLayoutCreateInfo set_info = { - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - pNext: &flag_info, - bindingCount: cast(u32)layout_bindings.length, - pBindings: layout_bindings.ptr, - flags: VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + vk.conv_desc_layout = CreateDescSetLayout(vk, layout_bindings); + vk.conv_desc_set = AllocDescSet(vk, vk.conv_desc_layout); + vk.conv_pipeline_layout = CreatePipelineLayout(vk, [vk.conv_desc_layout], ConvPushConst.sizeof, true); + + u32 channels = 1; + CompPipelineInfo conv_info = { + shader: "shaders/convert.comp.spv", + layout: vk.conv_pipeline_layout, + spec: { + data: &channels, + size: u32.sizeof, + entries: [ + { + constantID: 0, + size: u32.sizeof, + offset: 0, + } + ], + }, }; - VkResult result = vkCreateDescriptorSetLayout(vk.device, &set_info, null, &vk.conv_desc_layout); - bool success = VkCheck("InitConversionPipeline failure: vkCreateDescriptorSetLayout error", result); + vk.r_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - if (success) - { - VkDescriptorSetAllocateInfo alloc_info = { - sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - descriptorSetCount: 1, - pSetLayouts: &vk.conv_desc_layout, - descriptorPool: vk.desc_pool, - }; + channels = 2; + vk.rg_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - result = vkAllocateDescriptorSets(vk.device, &alloc_info, &vk.conv_desc_set); - success = VkCheck("InitConversionPipeline failure: vkAllocateDescriptorSets error", result); - } - - if (success) - { - VkPushConstantRange const_range = { - offset: 0, - size: cast(VkDeviceSize)ConvPushConst.sizeof, - stageFlags: VK_SHADER_STAGE_COMPUTE_BIT, - }; - - VkPipelineLayoutCreateInfo layout_info = { - sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - setLayoutCount: 1, - pSetLayouts: &vk.conv_desc_layout, - pushConstantRangeCount: 1, - pPushConstantRanges: &const_range, - }; - - result = vkCreatePipelineLayout(vk.device, &layout_info, null, &vk.conv_pipeline_layout); - success = VkCheck("InitConversionPipeline failure: vkCreatePipelineLayout error", result); - } - - if (success) - { - u32 channels = 1; - - CompPipelineInfo conv_info = { - shader: "shaders/convert.comp.spv", - layout: &vk.conv_pipeline_layout, - spec: { - data: &channels, - size: u32.sizeof, - entries: [ - { - constantID: 0, - size: u32.sizeof, - offset: 0, - } - ], - }, - }; - - vk.r_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - - channels = 2; - vk.rg_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - - channels = 3; - vk.rgb_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); - } + channels = 3; + vk.rgb_to_rgba_pipeline = CreateComputePipeline(vk, &conv_info); return success; } void -CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visible) +CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visible, bool dynamic = false) { assert(type != BT.None, "CreateBuffer failure: type is None"); + u64 buffer_size = (dynamic ? size * FRAME_OVERLAP : size); + VkBufferCreateInfo buffer_info = { sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, usage: type, - size: size, + size: buffer_size, }; VmaAllocationCreateInfo alloc_info = { @@ -558,7 +594,8 @@ CreateBuffer(Vulkan* vk, Buffer* buf, BufferType type, u64 size, bool host_visib // TODO: handle errors here then reallocate buffer assert(VkCheck("CreateBuffer failure: vmaCreateBuffer error", result), "CreateBuffer failure"); - buf.size = size; + buf.size = buffer_size; + buf.dynamic = dynamic; } void @@ -932,22 +969,11 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data) BeginComputePass(vk); - vkCmdBindDescriptorSets( - vk.comp_cmd, - VK_PIPELINE_BIND_POINT_COMPUTE, - vk.conv_pipeline_layout, - 0, - 1, - &vk.conv_desc_set, - 0, - null - ); + Pipeline pipeline = ch == 1 ? vk.r_to_rgba_pipeline : + ch == 2 ? vk.rg_to_rgba_pipeline : + vk.rgb_to_rgba_pipeline; - VkPipeline pipeline = ch == 1 ? vk.r_to_rgba_pipeline.handle : - ch == 2 ? vk.rg_to_rgba_pipeline.handle : - vk.rgb_to_rgba_pipeline.handle; - - vkCmdBindPipeline(vk.comp_cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); + Bind(vk, pipeline, vk.conv_desc_set); ConvPushConst pc = { x: w, @@ -1106,68 +1132,12 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, Format format, ImageU view.usage = usage; } -u32 -Pop(Vulkan* vk, DescType type) -{ - DescBindings* bindings = vk.desc_bindings.ptr + type; - - assert(bindings.count > 0, "Pop failure: no free bindings remaining"); - bindings.count -= 1; - - return bindings.free[bindings.count]; -} - void -Push(Vulkan* vk, u32 index, DescType type) -{ - DescBindings* bindings = vk.desc_bindings.ptr + type; - - bindings.free[bindings.count] = index; - bindings.count += 1; -} - -u32 -Pop(Vulkan* vk, string name, DescType type) -{ - DescBindings* bindings = vk.desc_bindings.ptr + type; - - u32 index; - auto result = bindings.lookup_table[name]; - if (!result.ok) - { - // TODO: handle unbinding assets (maybe) - assert(bindings.count > 0, "Pop failure: no free bindings remaining"); - bindings.count -= 1; - index = bindings.free[bindings.count]; - } - else - { - index = result.value; - } - - return index; -} - -void -Push(Vulkan* vk, string name, DescType type) -{ - DescBindings* bindings = vk.desc_bindings.ptr + type; - auto result = Delete(&bindings.lookup_table, name); - if (result.ok) - { - assert(bindings.count < bindings.free.length, "Push failure: attempt to push a binding into a full stack"); - - bindings.free[bindings.count] = result.value; - bindings.count += 1; - } -} - -void -PushConstants(Vulkan* vk, PushConst* pc) +PushConstants(Vulkan* vk, PipelineLayout layout, PushConst* pc) { vkCmdPushConstants( vk.cmds[vk.frame_index], - vk.pipeline_layout, + layout, VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT|VK_SHADER_STAGE_COMPUTE_BIT, 0, PushConst.sizeof, @@ -1383,44 +1353,71 @@ Copy(VkCommandBuffer cmd, VkImage src, VkImage dst, VkImageLayout src_layout, Vk } void -Bind(Vulkan* vk, PipelineHandle* pipeline) +Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet[] sets) { - if (vk.last_pipeline[vk.frame_index] == null || vk.last_pipeline[vk.frame_index] != pipeline.handle) - { - vkCmdBindPipeline(vk.cmds[vk.frame_index], pipeline.type, pipeline.handle); - vk.last_pipeline[vk.frame_index] = pipeline.handle; - } + assert(pipeline_handle > 0, "Bind failure: pipeline is 0"); + PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_handle; + BindPipeline(vk, pipeline); vkCmdBindDescriptorSets( vk.cmds[vk.frame_index], pipeline.type, - vk.pipeline_layout, + pipeline.layout, 0, - cast(u32)vk.desc_sets.length, - vk.desc_sets.ptr, + cast(u32)sets.length, + sets.ptr, 0, null ); +} - VkViewport viewport = { - x: 0.0, - y: 0.0, - width: cast(f32)vk.swapchain_extent.width, - height: cast(f32)vk.swapchain_extent.height, - minDepth: 0.0, - maxDepth: 1.0, - }; +void +Bind(Vulkan* vk, Pipeline pipeline_handle, DescSet set) +{ + assert(pipeline_handle > 0, "Bind failure: pipeline is 0"); + PipelineHandles* pipeline = vk.pipeline_handles.ptr + pipeline_handle; + BindPipeline(vk, pipeline); + + vkCmdBindDescriptorSets( + vk.cmds[vk.frame_index], + pipeline.type, + pipeline.layout, + 0, + 1, + &set, + 0, + null + ); +} - vkCmdSetViewport(vk.cmds[vk.frame_index], 0, 1, &viewport); +pragma(inline): void +BindPipeline(Vulkan* vk, PipelineHandles* pipeline) +{ + if (vk.last_pipeline[vk.frame_index] == 0 || vk.last_pipeline[vk.frame_index] != pipeline_handle) + { + vkCmdBindPipeline(vk.cmds[vk.frame_index], pipeline.type, pipeline.handle); + vk.last_pipeline[vk.frame_index] = pipeline_handle; - VkRect2D scissor = { - extent: { - width: vk.swapchain_extent.width, - height: vk.swapchain_extent.height, - }, - }; + VkViewport viewport = { + x: 0.0, + y: 0.0, + width: cast(f32)vk.swapchain_extent.width, + height: cast(f32)vk.swapchain_extent.height, + minDepth: 0.0, + maxDepth: 1.0, + }; - vkCmdSetScissor(vk.cmds[vk.frame_index], 0, 1, &scissor); + vkCmdSetViewport(vk.cmds[vk.frame_index], 0, 1, &viewport); + + VkRect2D scissor = { + extent: { + width: vk.swapchain_extent.width, + height: vk.swapchain_extent.height, + }, + }; + + vkCmdSetScissor(vk.cmds[vk.frame_index], 0, 1, &scissor); + } } pragma(inline): void @@ -1725,7 +1722,6 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) pDynamicState: &dyn_info, stageCount: cast(u32)shader_info.length, pStages: shader_info.ptr, - layout: vk.pipeline_layout, renderPass: vk.render_pass, }; @@ -1740,7 +1736,7 @@ CreateComputePipeline(Vulkan* vk, CompPipelineInfo* comp_info) { VkComputePipelineCreateInfo info = { sType: VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - layout: comp_info.layout ? *comp_info.layout : vk.pipeline_layout, + layout: comp_info.layout, stage: { sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage: VK_SHADER_STAGE_COMPUTE_BIT, @@ -1769,11 +1765,17 @@ CreateComputePipeline(Vulkan* vk, CompPipelineInfo* comp_info) info.stage.pSpecializationInfo = &spec_info; } - PipelineHandle pipeline = { type: VK_PIPELINE_BIND_POINT_COMPUTE }; + PipelineHandles* pipeline = vk.pipeline_handles.ptr + vk.pipeline_count; + pipeline.type = VK_PIPELINE_BIND_POINT_COMPUTE; + pipeline.layout = comp_info.layout; + + Pipeline pipeline_handle = vk.pipeline_count; + vk.pipeline_count += 1; + VkResult result = vkCreateComputePipelines(vk.device, null, 1, &info, null, &pipeline.handle); assert(VkCheck("CreateComputePipeline failure", result), "Unable to build pipeline"); - return pipeline; + return pipeline_handle; } void @@ -1809,7 +1811,7 @@ SetUniform(Vulkan* vk, GlobalUniforms* globals) sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, dstSet: vk.desc_sets[DT.Shared], dstBinding: 0, - descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 1, pBufferInfo: &buffer_info, }; @@ -1874,8 +1876,8 @@ Destroy(Vulkan* vk) Destroy(vk, &vk.draw_image); Destroy(vk, &vk.depth_image); break; - case SI.Descriptors: - Destroy(vk.desc_pool, vk.desc_layouts, vk.pipeline_layout, vk.nearest_sampler, vk.device); + case SI.DescriptorPools: + DestroyDescriptorPools(vk); break; case SI.Buffers: Destroy(vk, &vk.transfer_buf); @@ -1893,6 +1895,25 @@ Destroy(Vulkan* vk) } } +void +DestroyDescriptorPools(Vulkan* vk) +{ + vkDestroyDescriptorPool(vk.device, vk.active_pool, null); + + Node!(VkDescriptorPool)* node = vk.full_pools.first; + for(;;) + { + if (node == null) + { + break; + } + + vkDestroyDescriptorPool(vk.device, node.value, null); + + node = node.next; + } +} + void DestroyPipelines(Vulkan* vk) { @@ -1916,7 +1937,7 @@ DestroyPipelines(Vulkan* vk) vkDestroyPipeline(vk.device, vk.rg_to_rgba_pipeline.handle, null); } - if (vk.rgb_to_rgba_pipeline.handle) + if (vk.rgb_to_rgba_pipeline.handle) { vkDestroyPipeline(vk.device, vk.rgb_to_rgba_pipeline.handle, null); } @@ -1938,15 +1959,21 @@ Destroy(Vulkan* vk, Buffer* buf) bool InitDescriptors(Vulkan* vk) { - Push(vk, SI.Descriptors); + Push(vk, SI.DescriptorPools); bool success = true; + PushDescriptorPool(vk); +} + +void +PushDescriptorPool(Vulkan* vk) +{ VkDescriptorPoolSize[] pool_sizes = [ { type: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 4096 }, { type: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: 4096 }, - { type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 4096 }, + { type: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, descriptorCount: 4096 }, + { type: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 4096 }, { type: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 4096 }, { type: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 4096 }, ]; @@ -1955,18 +1982,36 @@ InitDescriptors(Vulkan* vk) sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, poolSizeCount: cast(u32)pool_sizes.length, pPoolSizes: pool_sizes.ptr, - maxSets: 12, - flags: VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT, + maxSets: MAX_SETS, }; - VkResult result = vkCreateDescriptorPool(vk.device, &pool_info, null, &vk.desc_pool); + VkDescriptorPool pool; + VkResult result = vkCreateDescriptorPool(vk.device, &pool_info, null, &pool); success = VkCheck("vkCreateDescriptorPool failure", result); + assert(success, "vkCreateDescriptorPool error"); + + if (vk.active_pool == null || vk.active_pool == VK_NULL_HANDLE) + { + Node!(VkDescriptorPool)* node = Alloc!(Node!(VkDescriptorPool)); + node.value = vk.active_pool; + PushFront(&g.full_pools, node, null); + } + + vk.active_pool = pool; +} + + + +bool +InitDescriptors(Vulkan* vk) +{ + if (success) { VkDescriptorSetLayoutBinding[] shared_bindings = [ - { binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, - { binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, + { binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, + { binding: 1, descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, { binding: 2, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, { binding: 3, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, { binding: 4, descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL }, @@ -2069,26 +2114,6 @@ InitDescriptors(Vulkan* vk) success = VkCheck("vkCreatePipelineLayout failure", result); } - if (success) - { - foreach(i; cast(u64)DT.min .. cast(u64)DT.max) - { - vk.desc_bindings[i].lookup_table = CreateHashTable!(string, u32)(8); - - u32 DESC_MAX_BINDINGS = 512; - vk.desc_bindings[i].free = AllocArray!(u32)(&vk.arena, DESC_MAX_BINDINGS); - - u32 free_count = 0; - for(i32 j = DESC_MAX_BINDINGS-1; j >= 0; j -= 1) - { - vk.desc_bindings[i].free[j] = cast(u32)free_count; - free_count += 1; - } - - vk.desc_bindings[i].count = free_count; - } - } - if (success) { VkPhysicalDeviceProperties props; diff --git a/src/shaders/gui.frag.glsl b/src/shaders/gui.frag.glsl index 5907081..93b5149 100644 --- a/src/shaders/gui.frag.glsl +++ b/src/shaders/gui.frag.glsl @@ -1,17 +1,19 @@ #version 460 #extension GL_GOOGLE_include_directive : require -#extension GL_EXT_nonuniform_qualifier : require #include "structures.layout" +#include "gui.layout" -layout (location = 0) in vec4 in_color; -layout (location = 1) in vec2 in_uv; -layout (location = 2) flat in uint in_image; +layout (location = 0) in struct FragDataIn { + vec4 color; + vec2 uv; +} FragData; -layout (location = 0) out vec4 out_frag_col; +layout (location = 0) out vec4 FragColor; void main() { - out_frag_col = in_color; + vec4 tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FragData.uv); + FragColor = FragData.color * tex_color; } diff --git a/src/shaders/gui.layout b/src/shaders/gui.layout new file mode 100644 index 0000000..3c38182 --- /dev/null +++ b/src/shaders/gui.layout @@ -0,0 +1,5 @@ +layout (set = 1, binding = 0) uniform texture2D SpriteAtlas; + +layout (push_constant) uniform Constants { + vec2 res; +} PC; diff --git a/src/shaders/gui.vert.glsl b/src/shaders/gui.vert.glsl index 8a1828b..5fe8e20 100644 --- a/src/shaders/gui.vert.glsl +++ b/src/shaders/gui.vert.glsl @@ -1,25 +1,27 @@ #version 460 #extension GL_GOOGLE_include_directive : require -#extension GL_EXT_nonuniform_qualifier : require #include "structures.layout" +#include "gui.layout" -layout (location = 0) in vec2 in_gui_pos_0; -layout (location = 1) in vec2 in_gui_pos_1; -layout (location = 2) in vec4 in_col; -layout (location = 3) in uint in_image; +layout (location = 0) in vec2 in_dst_start; +layout (location = 1) in vec2 in_dst_end; +layout (location = 2) in vec2 in_src_start; +layout (location = 3) in vec2 in_src_end; +layout (location = 4) in vec4 in_col; -layout (location = 0) out vec4 out_color; -layout (location = 1) out vec2 out_uv; -layout (location = 2) out uint out_image; +layout (location = 0) out struct FragDataOut { + vec4 color; + vec2 uv; +} FragData; -vec2 uvs[] = { - vec2(0.0, 1.0), - vec2(0.0, 0.0), - vec2(1.0, 1.0), - vec2(1.0, 0.0) -}; +vec2 Vertices[4] = vec2[4]( + vec2(-1.0, -1.0), + vec2(-1.0, +1.0), + vec2(+1.0, -1.0), + vec2(+1.0, +1.0) +); vec2 rotate(vec2 coords, float theta) { @@ -28,18 +30,24 @@ vec2 rotate(vec2 coords, float theta) void main() { - // Draw with 6 indices, gl_VertexIndex will use the appropriate index, iterates through 0-3 and not 0-5 - vec2 dst_pos = gl_VertexIndex == 0 ? vec2(in_gui_pos_0.x, in_gui_pos_1.y) : - gl_VertexIndex == 1 ? vec2(in_gui_pos_0.x, in_gui_pos_0.y) : - gl_VertexIndex == 2 ? vec2(in_gui_pos_1.x, in_gui_pos_1.y) : - gl_VertexIndex == 3 ? vec2(in_gui_pos_1.x, in_gui_pos_0.y) : vec2(0.0, 0.0); + ivec2 tex_size = textureSize(sampler2D(SpriteAtlas, SamplerNearest), 0); - out_uv = uvs[gl_VertexIndex]; - out_color = in_col; - out_image = in_image; + vec2 dst_half_size = (in_dst_end - in_dst_start) / 2; + vec2 dst_center = (in_dst_end + in_dst_start) / 2; + vec2 dst_pos = (Vertices[gl_VertexIndex] * dst_half_size + dst_center); - gl_Position = vec4(2 * dst_pos.x / G.res.x - 1, - 2 * dst_pos.y / G.res.y - 1, + vec2 src_half_size = (in_src_end - in_src_start) / 2; + vec2 src_center = (in_src_end + in_src_start) / 2; + vec2 src_pos = (Vertices[gl_VertexIndex] * src_half_size + src_center); + + FragData.color = in_col; + FragData.uv = vec2( + in_src_start.x / tex_size.x, + in_src_start + ); + + gl_Position = vec4(2 * dst_pos.x / PC.res.x - 1, + 2 * dst_pos.y / PC.res.y - 1, 0, 1); } diff --git a/src/shaders/pbr.frag.glsl b/src/shaders/pbr.frag.glsl index 2964c89..44b92d9 100644 --- a/src/shaders/pbr.frag.glsl +++ b/src/shaders/pbr.frag.glsl @@ -58,9 +58,8 @@ void main() out_col.a = alpha_col.a; } - FragColor = out_col; + //FragColor = out_col; - /* //TODO: set up OIT again vec4 srgb_col = out_col;// UnPreMultLinearToSRGB(out_col); @@ -75,7 +74,6 @@ void main() } else { - FragColor = vec4(out_col.rgb * out_col.a, out_col.a); // Change to vec4(0.0) to disable tail blending + FragColor = vec4(0.0); //vec4(out_col.rgb * out_col.a, out_col.a); // Change to vec4(0.0) to disable tail blending } - */ } diff --git a/src/shaders/pbr.vert.glsl b/src/shaders/pbr.vert.glsl index b5551b4..4fcf203 100644 --- a/src/shaders/pbr.vert.glsl +++ b/src/shaders/pbr.vert.glsl @@ -5,6 +5,31 @@ #include "structures.layout" +layout (set = 1, binding = 0) uniform texture2D AlbedoTexture; + +layout (set = 1, binding = 1) uniform texture2D AmbientTexture; + +layout (set = 1, binding = 2) uniform texture2D SpecularTexture; + +layout (set = 1, binding = 3) uniform texture2D AlphaTexture; + +layout (set = 1, binding = 4) uniform Material { + vec4 ambient; + vec4 diffuse; + vec4 specular; + bool albedo_has_texture; + bool ambient_has_texture; + bool specular_has_texture; + bool alpha_has_texture; + float shininess; + float alpha; +} Materials[]; + +layout (push_constant) uniform Constants { + mat4 model_matrix; + uint mat_id; +} PC; + layout (location = 0) in vec4 in_col; layout (location = 1) in vec4 in_tangent; layout (location = 2) in vec3 in_pos; diff --git a/src/shaders/structures.layout b/src/shaders/structures.layout index 537d48d..216e707 100644 --- a/src/shaders/structures.layout +++ b/src/shaders/structures.layout @@ -1,60 +1,4 @@ -// **************************************************************************** -// **** STRUCTS MUST BE PACKED IN OPTIMAL PACKING ORDER TO MATCH D STRUCTS **** -// **************************************************************************** +layout (rgba16f, set = 0, binding = 0) uniform image2D DrawImage; -#define OIT_LAYERS 8 +layout (set = 0, binding = 1) uniform sampler SamplerNearest; -layout (set = 0, binding = 0) uniform GlobalUniforms { - mat4 view_matrix; - mat4 projection_matrix; - mat4 projection_view; - vec4 light_color; - vec4 ambient_color; - vec3 light_direction; - vec2 res; -} G; - -layout (set = 0, binding = 1) uniform ShaderUniforms { - float placeholder; -} S; - -layout (rgba16f, set = 0, binding = 2) uniform image2D DrawImage; - -layout (set = 0, binding = 3) uniform sampler SamplerNearest; - -#ifdef COMPOSITE_PASS - -layout (set = 0, binding = 4, rg32ui) uniform restrict readonly uimageBuffer ImageABuffer; - -layout (set = 0, binding = 5, r32ui) uniform restrict readonly uimage2D ImageAux; - -#else - -layout (set = 0, binding = 4, rg32ui) uniform coherent uimageBuffer ImageABuffer; - -layout (set = 0, binding = 5, r32ui) uniform coherent uimage2D ImageAux; - -#endif - -layout (set = 1, binding = 0) uniform texture2D Textures[]; - -layout (set = 2, binding = 0) uniform Material { - vec4 ambient; - vec4 diffuse; - vec4 specular; - uint albedo_texture; - uint ambient_texture; - uint specular_texture; - uint alpha_texture; - bool albedo_has_texture; - bool ambient_has_texture; - bool specular_has_texture; - bool alpha_has_texture; - float shininess; - float alpha; -} Materials[]; - -layout (push_constant) uniform Constants { - mat4 model_matrix; - uint mat_id; -} PC; diff --git a/src/shared/util.d b/src/shared/util.d index ecbb50a..e6e8377 100644 --- a/src/shared/util.d +++ b/src/shared/util.d @@ -8,6 +8,23 @@ import core.simd; import std.conv; import std.string; +struct TrackedSlice(T) +{ + T[] slice; + u32 free_index; +} + +alias TSlice = TrackedSlice; + +TSlice!(T) +InitTrackedSlice(T)(u32 length) +{ + TSlice!(T) tslice; + tslice.slice = AllocArray!(T[])(length); + + return tslice; +} + void Logf(Args...)(string fmt, Args args) {