From 187359f747e6be6fc9bac3d52620a0e3af33d580 Mon Sep 17 00:00:00 2001 From: James Bulman Date: Sat, 4 Oct 2025 21:42:04 +0100 Subject: [PATCH] Drawing a textured quad Added new assets Loaded all texture assets into game state Loaded the basic pipeline Setup a hard-coded quad to test drawing Created a very jank vertex struct Added ReadEntireFile for filesystem Added getting file size from file handle Added a descriptor pool to each in flight frame Changed Vk_BufferCreate to handle multiple uses Added shader building to the windows.bat build script --- assets/npc_00.png | Bin 0 -> 801 bytes assets/oath_corner_inner.png | Bin 0 -> 409 bytes assets/path_corner.png | Bin 0 -> 520 bytes assets/path_middle.png | Bin 0 -> 483 bytes assets/path_middle_edge.png | Bin 0 -> 453 bytes assets/saloon_ext.png | Bin 0 -> 4144 bytes assets/tile_detail_0.png | Bin 0 -> 208 bytes assets/tile_detail_1.png | Bin 0 -> 329 bytes assets/tile_detail_2.png | Bin 0 -> 358 bytes assets/tile_detail_3.png | Bin 0 -> 351 bytes assets/tile_detail_4.png | Bin 0 -> 223 bytes assets/tile_detail_5.png | Bin 0 -> 368 bytes assets/tile_detail_6.png | Bin 0 -> 317 bytes assets/tile_dirt_0.png | Bin 0 -> 462 bytes assets/tile_dirt_1.png | Bin 0 -> 494 bytes code/first.c | 81 +++++++++++++++- code/game/core.c | 88 ++++++++++++++++-- code/game/core.h | 36 +++++-- code/os/core.c | 16 ++++ code/os/filesystem.h | 4 + code/os/impl/windows/filesystem.c | 13 +++ code/vulkan/core.c | 150 ++++++++++++++++++++++++++---- code/vulkan/core.h | 78 +++++++++++----- code/vulkan/functions.h | 14 +++ code/vulkan/shaders/basic.frag | 12 +++ code/vulkan/shaders/basic.vert | 28 ++++++ windows.bat | 7 ++ 27 files changed, 470 insertions(+), 57 deletions(-) create mode 100644 assets/npc_00.png create mode 100644 assets/oath_corner_inner.png create mode 100644 assets/path_corner.png create mode 100644 assets/path_middle.png create mode 100644 assets/path_middle_edge.png create mode 100644 assets/saloon_ext.png create mode 100644 assets/tile_detail_0.png create mode 100644 assets/tile_detail_1.png create mode 100644 assets/tile_detail_2.png create mode 100644 assets/tile_detail_3.png create mode 100644 assets/tile_detail_4.png create mode 100644 assets/tile_detail_5.png create mode 100644 assets/tile_detail_6.png create mode 100644 assets/tile_dirt_0.png create mode 100644 assets/tile_dirt_1.png create mode 100644 code/vulkan/shaders/basic.frag create mode 100644 code/vulkan/shaders/basic.vert diff --git a/assets/npc_00.png b/assets/npc_00.png new file mode 100644 index 0000000000000000000000000000000000000000..2ec78e1e0c56ad077a8dfc688bfa1093fb1261ea GIT binary patch literal 801 zcmV++1K#|JP)k00001b5ch_0Itp) z=>Px%+et)0R7i=Xl}|_%aTLctv#1AgoD~Wj%vNzp$~{PJDV`)mJak(y4_>?_M8`Y? zVuVTxMG{m9EkR%j>p7M^coNGMHgJOp|LnT1yHSGcst3cSgU&d=*>PLw3j=Sy^S
f}R=++ZXnxi~!x zLo6$9rl-b{6}Nd!PmMD@H4Z>JUny+EWjF^TDM?n`ynOzcbuG^Q{yP9Xdoskj7H3_H z^X}~nWW_D4QrKy7;iF!mDCYh5N3Q|6GJ4PCj&eCX9d}Kg*}GnlD7++83UuEjrfsp7%rHB@TDS$P82K^)p->1r7mF?k zCN680R)2??D8RzmUvrmHJrD>$e)Hr4$Zyi*QCUl7&iK=3fk1%X&XaQxI*4goXR}*7 zF-8h632&lkU{tomYsm~v9#wp1gUgAGXIiGR|MaybCHAB4D8t&#b)$J3E!0ER|1 z)C<*o+iNB~6#$?@QBYfYq%r`trAM-wY?t2#6&}7hEu&s#8-TPR#_5lx+25&UDu)C9HcPCverMN*UIM?8Cf5$N{$>2veTM}2agHrL|2Et0Z zZ#3w&vWw6AegHiB7XXsdEdbi8qGa=b2rnm`zsj|;3%6ULjVJ)wJf;x9?N)%?`5hQt f7_m{wi8JsQQ=(7c5&?u_00000NkvXXu0mjfaPMRJ literal 0 HcmV?d00001 diff --git a/assets/oath_corner_inner.png b/assets/oath_corner_inner.png new file mode 100644 index 0000000000000000000000000000000000000000..3ee040d852f5a879264f27bf6bcfdef1de52df1b GIT binary patch literal 409 zcmV;K0cQS*P)Px$Q%OWYR5*=wlf7<(Fc8OoAPW@)7Ghw^8$}(mr9+24M4zXsI`qXDDx@OIP9Y+e z=n$Rbki?Vke8>Gij^y+GdHMM@yuH3K9W1)tu*@Ugd!~b>sv7{D82~~ox%6*3QWZ~p ze0>AlG&?ik%s^E)=ynrg$tgD;0od=h&I}=+R&^65Nl}s&Px$!bwCyR5*=olfQ1;Fc8LnHdup{ErF0x!$4avg`cETvUKX$Aw!>|50W86mJ9`o z4o#*4MS;Fa3^;b82$C(SHUVd#Poaw3Lh$~4_wl=9@7vc;2Y_wWAhxX=hDN`50t}7z zXQb&%@$w;OTl@2+BJoegw$0sE4N8LV-%VQz;tXW ztA;OUp8+_(xNO11w_Yw#dw1w`4HE#$JnQ(%Ji|Fhy(yT?<|uiq&gn9^& zXwjDuN}`~L^u_0#!;BKjJVPljUq9>~qC4kUFBbq5tJ{{vxld;E<7jJ?QpewT`~$KFH`h1Ro1)!1*}O6sr`Cq`a={Y_nJ_tuFV-Xg0000< KMNUMnLSTZ78t|q7 literal 0 HcmV?d00001 diff --git a/assets/path_middle.png b/assets/path_middle.png new file mode 100644 index 0000000000000000000000000000000000000000..53d815c28bf73185c8199838e5519b078a7c8102 GIT binary patch literal 483 zcmV<90UZ8`P)Px$ok>JNR5*=&lg*B!Kn#Sxpq_|EfC$PD5~I28OYiIKW6W)oNSS2SivZDxvBVw{ z_re^Oo7*nCTxB-y*U!0Y9OLMTV@p<)bd3YRraAigzFpOb2mofYO~?wMab!h_#v;O> z-=6>hly4KhhL)~z*fhr&gPErR5n&wtv&ld3p{m(z6Xt24d*)t}JTS6pP9!4uzU5HW zxDSBj|K|dY!lksIW)6r{@?q^iW1W;{GX?RtSG}xh{&qBGSGJsADm*!21LH4bpAX(F-`R0nm9 Z<1d(#UHa$NT+sjk002ovPDHLkV1iB2;i>=t literal 0 HcmV?d00001 diff --git a/assets/path_middle_edge.png b/assets/path_middle_edge.png new file mode 100644 index 0000000000000000000000000000000000000000..dff3b8c4640719c93fbe2da9559ddd3d1185fc5c GIT binary patch literal 453 zcmV;$0XqJPP)Px$e@R3^R5*=&kv(qPKoEsL5(~kk$pt|JtaKe$snSJ-3KfYPAH*jJV7qW316JoE z&41T}ZHI(lz+23Rc=&xbr7`cs#&ihQn2y_(4O_XSqQhV=qQxi%t z;5rARm?+Ul#qwS}FC8ANf8X^@wMG|X>T>0Z<)m3oFpBAS2C0)cN;IJl3OUVk(kvg` zuGYMoq2c0r>0+sM8wd!vCW0U4{6R_zM1maI4A@)wP@*~|L9`3mTDzC?eNX_eram%m z_(rhS;vXTq4g5b3Mlp4{A{fP_8G9c1GJQ@c6NDTk+O7A|WIyLjJoG>e6nUq-00`wf ve63NUsmm4p&Y+YcO0=8WZfbNfb~640r@CTLvWosW00000NkvXXu0mjf!}-Y* literal 0 HcmV?d00001 diff --git a/assets/saloon_ext.png b/assets/saloon_ext.png new file mode 100644 index 0000000000000000000000000000000000000000..3705ef2e798b6085eadc41404317763fd9422105 GIT binary patch literal 4144 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 Ef@5o;MgRZ+ literal 0 HcmV?d00001 diff --git a/assets/tile_detail_3.png b/assets/tile_detail_3.png new file mode 100644 index 0000000000000000000000000000000000000000..892b79ff59ccf36aeef361ece9f0cfc4bb8c8ea5 GIT binary patch literal 351 zcmV-l0igbgP)Px$8A(JzR5*?8kiSa9P!z_0i9(b32Rl@Aw+w0Kyo4{{=o5&m(9J>I1Xq#nb+oVI z(xFvowhRu27?XP`Z5?VZxrK_Lqu+GTIefqK-2?ynwXFK_aNApEd4Yd)2!O0gPA_h( z@5}((&B7N#znz`EA0^O$EHCg~59}@4ofYWu{(1>;a(1~fiB-o35JAM-YpRFsjxcKZ z@vfJhU)@;%b{vXsmKOk|$wY4l3^Rb^dN{7f!Tzr9*_y6q21J7vb6v}-L{=qPUJ!?( zs{#GNFp^3ckTjXVVvejzrsEOQ@rW!hsMD?=F<7NgNTqOEt*>^8R5PSfhN(XoM#d52 xP#ibr$)=0fdU{Ep4M45>UkwH8z^3_6^a-xpa-jpdh(Z7W002ovPDHLkV1hMvm8uPyMC1qSxaMy9I?7 zh}`R#5x8$kcNfD0!L2MVjJ%9dB1Px$DoI2^R5*>jk}q$~BbYT!vjj7>gak+BEM{(|!H@|)!OW&6uo%SD_7wY9VU{$cp|UgYHn;x>iksZL_T`;(&pkPCu9}aB$$UIa^7r*BKoA6N zfI;teDR-mk!q30Er~(UcG+lIoHGnZ@b+Ur(?vKfA;{&ZSU@3u?{qwuSPW`F^XI2o| zVHC5E4oqen|JdYG1p>agZZPOImXG)C0$?8vJN0)lueYu;)7TJI!~`by8p$#f6np1v(@mQ_e7oQ?QU_2*hn0n#}I` z7Nt^|B-&N(fNepmt$wHZX+8Ni#;i)CoG;0UO=lMsu#*Usx)!k30s9A|v8g@DZoT^e O0000Px#_en%SR5*>*QY{O@Kp1{D42z3{B{A%xaV9~QmIb3fK?Z`wxFQI{pI{WsT86Ns z(Kv&}F&J0|mSH*5D|chM8GX|o?>(O!@b{yLm*Z;80pR(#qd(s%A5p@n;^mek=uOtO zKoXK1M83;OHS%4av^-Q2Zl(in=vuWx03dY$QWr#aOOp3q zBCxxbB`CJb#QphBDLYa{u;-X@mKQK|4W47}DMs0y*o)*K2vZh>Da-N#L71}B`Esd> zSVi3E0Ywx`ZuD6Qycl+3D%j99%(hq7YDz#8gee06&oSd)u~M|!9-7VzmJed`H_=o< P00000NkvXXu0mjf41a>V literal 0 HcmV?d00001 diff --git a/assets/tile_dirt_0.png b/assets/tile_dirt_0.png new file mode 100644 index 0000000000000000000000000000000000000000..cc5209a38ce9dc8497603a3474f91ba752602d42 GIT binary patch literal 462 zcmV;<0WtoGP)Px$h)G02R5*=olVNTgAq<7TWf%fWQ*9NgH|u$Np`NVLDyt+D2pG0MSe)4^BaHxK zKR^4K!=K;3uB8Z7gw@)+b$}SxOO{vl=*kw)YHxnaJ~EI@kK4 z!F!O;1Y>XK24Jy<);l>Rwp@vTbN5VI?=7(*#?2V$li)36V2eb{1* zpY~gD6(Jt|C}B2mUvul7^Ye?AG@CmU#iOSb!EEnYRhZ5?EPlm@prBi>)cT>SRFT1; zil}tjEMtf5FqXY+PGXMYp07*qoM6N<$ Eg2g@4hyVZp literal 0 HcmV?d00001 diff --git a/assets/tile_dirt_1.png b/assets/tile_dirt_1.png new file mode 100644 index 0000000000000000000000000000000000000000..51431e6b127043eedd48618f5bc8e8acd36dcb6b GIT binary patch literal 494 zcmVPx$s7XXYR5*=QlkKh=ArOWiVRjFD&}JJG@2uC;8|syrn3^hw5m@XG3f1{H1m^u3 zcE5i9c&1di-tP2T4|{ScgsAw%F^P=6*Xg(dV9u8-xfIsJ9=|vM=2@6TI2~6))Y11l z>tRp$QqGqvra#K1j7M9ot3}gUn4Ab;6`gv~Xoq9?I z0KYg)h)OPHT<+ETt=2a51=WfnL}e0b5<*nAT1lx8LU z@QcHmhA>SZZ^$VXa(>{Jg?ScIDp)aWr4pj@#@mV+gRC)ZwYD=^29y3cm&V5QJUe2q ztyZ>D(HO^B&JVWI?)6wr_|lO=N9|fW^^VTYlJf&#EZ#_=o1`%gDc<|xgB8OhGQ2n) z*JdIB&u!%HmSxcFtX}I?(jUeL z9sXQz_ZDqWft^KT#JRa0J~vbos_9>ZO~UzdMKz6;?q&R^BWOl7wePyKgs6n5W6QueUq?)8QA#U(^68Q%kJo-2eap07*qoM6N<$f~{KV6#xJL literal 0 HcmV?d00001 diff --git a/code/first.c b/code/first.c index 4f5b271..6b8cd35 100644 --- a/code/first.c +++ b/code/first.c @@ -29,9 +29,33 @@ int main(int argc, char **argv) { Vk_Setup(window); + G_State *game = 0; + { + M_Arena *arena = M_ArenaAlloc(GB(64), .initial = MB(4)); + game = M_ArenaPush(arena, G_State); - M_Arena *garena = M_ArenaAlloc(GB(64), .initial = MB(4)); - G_ImagesLoad(garena); + game->arena = arena; + + G_ImagesLoad(game); + G_PipelinesLoad(game); + + Vk_Buffer *vbo = &game->vbo; + vbo->size = KB(4096); + vbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + vbo->host_visible = true; + + Vk_BufferCreate(vbo); + + G_Vertex *vertices = cast(G_Vertex *) vbo->data; + + vertices[0] = (G_Vertex) { -0.25f, -0.25f, 1.0f, 1.0f, 0.0f, 0.0f, 0xFFFFFFFF, 0}; + vertices[1] = (G_Vertex) { 0.25f, -0.25f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0}; + vertices[2] = (G_Vertex) { -0.25f, 0.25f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0}; + + vertices[3] = (G_Vertex) { 0.25f, -0.25f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0}; + vertices[4] = (G_Vertex) { 0.25f, 0.25f, 1.0f, 1.0f, 1.0f, 1.0f, 0xFFFFFFFF, 0}; + vertices[5] = (G_Vertex) { -0.25f, 0.25f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0}; + } bool running = true; while (running) { @@ -69,6 +93,59 @@ int main(int argc, char **argv) { vk.CmdBeginRendering(cmd, &rendering_info); + Vk_Pipeline *basic = &game->pipelines[0]; + + VkDescriptorSet set; + VkDescriptorSetAllocateInfo alloc_info = { 0 }; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = frame->descriptors; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &basic->layout.set; + + vk.AllocateDescriptorSets(vk.device, &alloc_info, &set); + + // 'update' the descriptor sets for binding + { + VkWriteDescriptorSet writes[2] = { 0 }; + + VkDescriptorBufferInfo vbo_info = { 0 }; + vbo_info.buffer = game->vbo.handle; + vbo_info.offset = 0; + vbo_info.range = 256; + + VkDescriptorImageInfo image_info = { 0 }; + image_info.imageView = game->images[6].image.view; + image_info.sampler = vk.sampler; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[0].dstSet = set; + writes[0].dstBinding = 0; + writes[0].descriptorCount = 1; + writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + writes[0].pBufferInfo = &vbo_info; + + writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[1].dstSet = set; + writes[1].dstBinding = 1; + writes[1].descriptorCount = 1; + writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[1].pImageInfo = &image_info; + + vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0); + } + + vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle); + vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0); + + VkViewport viewport = { 0, 0, (F32) w, (F32) h, 0.0f, 1.0f }; + VkRect2D scissor = { 0, 0, w, h }; + + vk.CmdSetViewport(cmd, 0, 1, &viewport); + vk.CmdSetScissor(cmd, 0, 1, &scissor); + + vk.CmdDraw(cmd, 6, 1, 0, 0); + vk.CmdEndRendering(cmd); Vk_FrameEnd(); diff --git a/code/game/core.c b/code/game/core.c index 3a63d7a..7caf30e 100644 --- a/code/game/core.c +++ b/code/game/core.c @@ -1,9 +1,14 @@ -void G_ImagesLoad(M_Arena *arena) { - M_TempScope(1, &arena) { +void G_ImagesLoad(G_State *game) { + M_TempScope(0, 0) { FS_List assets = FS_PathList(temp.arena, S("assets")); - Vk_Buffer staging = Vk_BufferCreate(MB(256), true /* host_visible */); + Vk_Buffer staging = { 0 }; + staging.size = MB(256); + staging.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + staging.host_visible = true; + + Vk_BufferCreate(&staging); U8 *base = staging.data; U64 offset = 0; @@ -14,12 +19,16 @@ void G_ImagesLoad(M_Arena *arena) { for (FS_Entry *it = assets.first; it != 0; it = it->next) { if (Str8_EndsWith(it->basename, S("png"))) { + if (Str8_Equal(it->basename, S("saloon_ext.png"), 0)) { + printf("IMAGE SALOON == %d\n", n_images); + } + n_images += 1; } } VkBufferImageCopy copy = { 0 }; - G_Image *images = M_ArenaPush(arena, G_Image, .count = n_images); + game->images = M_ArenaPush(game->arena, G_Image, .count = n_images); n_images = 0; // Image upload is sbi_load -> copy to staging -> upload to gpu texture @@ -30,7 +39,7 @@ void G_ImagesLoad(M_Arena *arena) { stbi_uc *data = stbi_load((const char *) it->path.data, &w, &h, &c, 4); if (data) { - G_Image *image = &images[n_images]; + G_Image *image = &game->images[n_images]; U64 image_sz = 4 * w * h; @@ -56,7 +65,7 @@ void G_ImagesLoad(M_Arena *arena) { n_images += 1; - image->name = Str8_Copy(arena, Str8_RemoveAfterLast(it->basename, '.')); + image->name = Str8_Copy(game->arena, Str8_RemoveAfterLast(it->basename, '.')); image->image.width = w; image->image.height = h; @@ -117,3 +126,70 @@ void G_ImagesLoad(M_Arena *arena) { Vk_CommandBufferSubmit(cmds, true /* wait */); } } + +void G_PipelinesLoad(G_State *game) { + game->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1); + + Vk_Pipeline *basic = &game->pipelines[0]; + + VkShaderModule vshader = 0, fshader = 0; + M_TempScope(0, 0) { + Str8 vshader_code = FS_ReadEntireFile(temp.arena, S("assets/shaders/basic.vert.spv")); + Str8 fshader_code = FS_ReadEntireFile(temp.arena, S("assets/shaders/basic.frag.spv")); + + VkShaderModuleCreateInfo create_info = { 0 }; + create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + create_info.pCode = (U32 *) vshader_code.data; + create_info.codeSize = vshader_code.count; + + vk.CreateShaderModule(vk.device, &create_info, 0, &vshader); + + create_info.pCode = (U32 *) fshader_code.data; + create_info.codeSize = fshader_code.count; + + vk.CreateShaderModule(vk.device, &create_info, 0, &fshader); + } + + // Create pipeline layout, its insane what you have to do for this because the ALREADY KNOW + // all of this information + { + VkDescriptorSetLayoutBinding bindings[2] = { 0 }; + + bindings[0].binding = 0; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[0].descriptorCount = 1; + bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + + bindings[1].binding = 1; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[1].descriptorCount = 1; + bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkDescriptorSetLayoutCreateInfo set_info = { 0 }; + set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + set_info.bindingCount = 2; + set_info.pBindings = bindings; + + vk.CreateDescriptorSetLayout(vk.device, &set_info, 0, &basic->layout.set); + + VkPipelineLayoutCreateInfo layout_create = { 0 }; + layout_create.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_create.setLayoutCount = 1; + layout_create.pSetLayouts = &basic->layout.set; + + vk.CreatePipelineLayout(vk.device, &layout_create, 0, &basic->layout.pipeline); + } + + basic->targets.items[0] = vk.swapchain.format.format; + basic->targets.count = 1; + + basic->shaders.count = 2; + + basic->shaders.items[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + basic->shaders.items[0].handle = vshader; + + basic->shaders.items[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + basic->shaders.items[1].handle = fshader; + + Vk_PipelineCreate(basic); +} diff --git a/code/game/core.h b/code/game/core.h index 63d9c47..37df55b 100644 --- a/code/game/core.h +++ b/code/game/core.h @@ -1,16 +1,34 @@ #if !defined(LD_GAME_CORE_H_) #define LD_GAME_CORE_H_ -typedef struct G_Image G_Image; -struct G_Image { - Vk_Image image; - - Str8 name; - - U32 width; - U32 height; +typedef struct G_Vertex G_Vertex; +struct G_Vertex { + F32 x, y, z, w; + F32 u, v; + U32 c; + U32 pad; }; -function void G_ImagesLoad(M_Arena *arena); +typedef struct G_Image G_Image; +struct G_Image { + Str8 name; + Vk_Image image; +}; + +typedef struct G_State G_State; +struct G_State { + M_Arena *arena; + + U32 n_images; + G_Image *images; + + U32 n_pipelines; + Vk_Pipeline *pipelines; + + Vk_Buffer vbo; +}; + +function void G_ImagesLoad(G_State *game); +function void G_PipelinesLoad(G_State *game); #endif // LD_GAME_CORE_H_ diff --git a/code/os/core.c b/code/os/core.c index e442952..15ce626 100644 --- a/code/os/core.c +++ b/code/os/core.c @@ -1,3 +1,19 @@ #if OS_WINDOWS #include "impl/windows/core.c" #endif + + +Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path) { + Str8 result = { 0 }; + + OS_Handle file = FS_FileOpen(path, FS_ACCESS_READ); + if (file.v[0]) { + result.count = FS_FileSize(file); + result.data = M_ArenaPush(arena, U8, .count = result.count); + + FS_FileRead(file, result.data, result.count, 0); + FS_FileClose(file); + } + + return result; +} diff --git a/code/os/filesystem.h b/code/os/filesystem.h index 180966e..23694f4 100644 --- a/code/os/filesystem.h +++ b/code/os/filesystem.h @@ -13,6 +13,8 @@ function void FS_FileClose(OS_Handle file); function void FS_FileRead(OS_Handle file, void *ptr, U64 size, U64 offset); function void FS_FileWrite(OS_Handle file, void *ptr, U64 size, U64 offset); +function U64 FS_FileSize(OS_Handle file); + typedef U32 FS_EntryType; enum { FS_ENTRY_TYPE_FILE = 0, @@ -42,4 +44,6 @@ struct FS_List { function FS_List FS_PathList(M_Arena *arena, Str8 path); +function Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path); + #endif // LD_OS_FILESYSTEM_H_ diff --git a/code/os/impl/windows/filesystem.c b/code/os/impl/windows/filesystem.c index 5b960ff..3f6575f 100644 --- a/code/os/impl/windows/filesystem.c +++ b/code/os/impl/windows/filesystem.c @@ -83,6 +83,19 @@ void FS_FileWrite(OS_Handle file, void *ptr, U64 size, U64 offset) { } } +U64 FS_FileSize(OS_Handle file) { + U64 result = 0; + HANDLE hFile = cast(HANDLE) file.v[0]; + if (hFile) { + DWORD dwLow, dwHigh; + dwLow = GetFileSize(hFile, &dwHigh); + + result = ((U64) dwHigh << 32) | ((U64) dwLow); + } + + return result; +} + FS_List FS_PathList(M_Arena *arena, Str8 path) { FS_List result = { 0 }; diff --git a/code/vulkan/core.c b/code/vulkan/core.c index fa27a51..01201e2 100644 --- a/code/vulkan/core.c +++ b/code/vulkan/core.c @@ -354,6 +354,23 @@ bool Vk_Setup(SDL_Window *window) { err = Min(vk.CreateFence(vk.device, &fence, 0, &frame->scratch[s].fence), err); } + // Descriptor pool + VkDescriptorPoolSize pool_sizes[2] = { 0 }; + + pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_sizes[0].descriptorCount = 2048; + + pool_sizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + pool_sizes[1].descriptorCount = 2048; + + VkDescriptorPoolCreateInfo descriptor_pool = { 0 }; + descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool.maxSets = 1024; + descriptor_pool.poolSizeCount = 2; + descriptor_pool.pPoolSizes = pool_sizes; + + vk.CreateDescriptorPool(vk.device, &descriptor_pool, 0, &frame->descriptors); + VkSemaphoreCreateInfo semaphore = { 0 }; semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -364,6 +381,16 @@ bool Vk_Setup(SDL_Window *window) { vk.err = err; } + { + VkSamplerCreateInfo create_info = { 0 }; + create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + create_info.magFilter = VK_FILTER_NEAREST; + create_info.minFilter = VK_FILTER_NEAREST; + create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + + vk.CreateSampler(vk.device, &create_info, 0, &vk.sampler); + } + result = (vk.err == VK_SUCCESS); return result; } @@ -376,6 +403,7 @@ Vk_Frame *Vk_FrameBegin(SDL_Window *window) { vk.ResetFences(vk.device, 1, &frame->fence); vk.ResetCommandPool(vk.device, frame->pool, 0); + vk.ResetDescriptorPool(vk.device, frame->descriptors, 0); VkResult res = vk.AcquireNextImageKHR(vk.device, vk.swapchain.handle, UINT64_MAX, frame->acquire, 0, &frame->image); (void) res; // @Todo: check res to see if swapchain is out of date and rebuild @@ -492,9 +520,7 @@ void Vk_CommandBufferSubmit(Vk_CommandBuffer *cmds, B32 wait) { vk.QueueSubmit(vk.queue.handle, 1, &submit_info, cmds->fence); - if (wait) { - vk.DeviceWaitIdle(vk.device); - } + if (wait) { vk.DeviceWaitIdle(vk.device); } } #define VK_HOST_VISIBLE_FLAGS (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) @@ -532,31 +558,27 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty return result; } -Vk_Buffer Vk_BufferCreate(U64 size, B32 host_visible) { - Vk_Buffer result = { 0 }; - +void Vk_BufferCreate(Vk_Buffer *buffer) { VkBufferCreateInfo create_info = { 0 }; create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - create_info.size = size; + create_info.usage = buffer->usage; + create_info.size = buffer->size; - vk.CreateBuffer(vk.device, &create_info, 0, &result.handle); + vk.CreateBuffer(vk.device, &create_info, 0, &buffer->handle); VkMemoryRequirements req; - vk.GetBufferMemoryRequirements(vk.device, result.handle, &req); + vk.GetBufferMemoryRequirements(vk.device, buffer->handle, &req); - VkMemoryPropertyFlags usage = host_visible ? VK_HOST_VISIBLE_FLAGS : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + VkMemoryPropertyFlags usage = buffer->host_visible ? VK_HOST_VISIBLE_FLAGS : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - result.size = req.size; - result.memory = Vk_Allocate(&req, usage); + buffer->size = req.size; + buffer->memory = Vk_Allocate(&req, usage); - vk.BindBufferMemory(vk.device, result.handle, result.memory, 0); + vk.BindBufferMemory(vk.device, buffer->handle, buffer->memory, 0); - if (host_visible) { - vk.MapMemory(vk.device, result.memory, 0, result.size, 0, &result.data); + if (buffer->host_visible) { + vk.MapMemory(vk.device, buffer->memory, 0, buffer->size, 0, &buffer->data); } - - return result; } void Vk_ImageCreate(Vk_Image *image) { @@ -595,3 +617,95 @@ void Vk_ImageCreate(Vk_Image *image) { vk.CreateImageView(vk.device, &view_info, 0, &image->view); } + +void Vk_PipelineCreate(Vk_Pipeline *pipeline) { + VkPipelineInputAssemblyStateCreateInfo ia = { 0 }; + ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineShaderStageCreateInfo shaders[8] = { 0 }; + for (U32 it = 0; it < pipeline->shaders.count; ++it) { + shaders[it].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shaders[it].stage = pipeline->shaders.items[it].stage; + shaders[it].module = pipeline->shaders.items[it].handle; + shaders[it].pName = "main"; + } + + VkPipelineVertexInputStateCreateInfo vi = { 0 }; + vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + // This will be updated later using dynamic commands but we still need to supply one here for + // some reason + VkViewport viewport = { 0, 0, 10, 10, 0, 1 }; + VkRect2D scissor = { 0, 0, 10, 10 }; + + VkPipelineViewportStateCreateInfo vp = { 0 }; + vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vp.viewportCount = 1; + vp.pViewports = &viewport; + vp.scissorCount = 1; + vp.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rs = { 0 }; + rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rs.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo ms = { 0 }; + ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineDepthStencilStateCreateInfo ds = { 0 }; + ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + + VkPipelineColorBlendAttachmentState blend = { 0 }; + blend.blendEnable = VK_TRUE; + blend.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + blend.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend.colorBlendOp = VK_BLEND_OP_ADD; + blend.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + blend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + blend.alphaBlendOp = VK_BLEND_OP_ADD; + blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo om = { 0 }; + om.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + om.attachmentCount = 1; + om.pAttachments = &blend; + + VkDynamicState dynamic_state[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo dyn = { 0 }; + dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dyn.dynamicStateCount = ArraySize(dynamic_state); + dyn.pDynamicStates = dynamic_state; + + VkFormat formats[8]; + for (U32 it = 0; it < pipeline->targets.count; ++it) { + formats[it] = pipeline->targets.items[it]; + } + + VkPipelineRenderingCreateInfo rendering_info = { 0 }; + rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + rendering_info.colorAttachmentCount = pipeline->targets.count; + rendering_info.pColorAttachmentFormats = formats; + + VkGraphicsPipelineCreateInfo create_info = { 0 }; + create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + create_info.pNext = &rendering_info; + create_info.stageCount = pipeline->shaders.count; + create_info.pStages = shaders; + create_info.pVertexInputState = &vi; + create_info.pInputAssemblyState = &ia; + create_info.pViewportState = &vp; + create_info.pRasterizationState = &rs; + create_info.pMultisampleState = &ms; + create_info.pDepthStencilState = &ds; + create_info.pColorBlendState = &om; + create_info.pDynamicState = &dyn; + create_info.layout = pipeline->layout.pipeline; + + vk.CreateGraphicsPipelines(vk.device, 0, 1, &create_info, 0, &pipeline->handle); +} diff --git a/code/vulkan/core.h b/code/vulkan/core.h index 8c5cc9e..b6849bf 100644 --- a/code/vulkan/core.h +++ b/code/vulkan/core.h @@ -25,26 +25,6 @@ #define VK_MAX_FRAMES_IN_FLIGHT 8 #define VK_NUM_SCRATCH 8 -typedef struct Vk_CommandBuffer Vk_CommandBuffer; -struct Vk_CommandBuffer { - VkCommandBuffer handle; - VkFence fence; -}; - -typedef struct Vk_Frame Vk_Frame; -struct Vk_Frame { - VkCommandPool pool; - VkCommandBuffer cmd; - - VkSemaphore acquire, complete; - VkFence fence; - - U32 next_scratch; - Vk_CommandBuffer scratch[VK_NUM_SCRATCH]; - - U32 image; // swapchain image index -}; - typedef struct Vk_Image Vk_Image; struct Vk_Image { VkDeviceMemory memory; @@ -60,14 +40,65 @@ struct Vk_Image { typedef struct Vk_Buffer Vk_Buffer; struct Vk_Buffer { + VkBuffer handle; + VkDeviceMemory memory; VkDeviceSize size; - VkBuffer handle; + VkBufferUsageFlags usage; + B32 host_visible; void *data; // if mapped host visible memory }; +typedef struct Vk_Shader Vk_Shader; +struct Vk_Shader { + VkShaderModule handle; + VkShaderStageFlags stage; +}; + +typedef struct Vk_Pipeline Vk_Pipeline; +struct Vk_Pipeline { + VkPipeline handle; + + struct { + VkPipelineLayout pipeline; + VkDescriptorSetLayout set; + } layout; + + struct { + VkFormat items[8]; + U32 count; + } targets; + + struct { + Vk_Shader items[8]; + U32 count; + } shaders; +}; + +typedef struct Vk_CommandBuffer Vk_CommandBuffer; +struct Vk_CommandBuffer { + VkCommandBuffer handle; + VkFence fence; +}; + +typedef struct Vk_Frame Vk_Frame; +struct Vk_Frame { + VkCommandPool pool; + VkCommandBuffer cmd; + + VkDescriptorPool descriptors; + + VkSemaphore acquire, complete; + VkFence fence; + + U32 next_scratch; + Vk_CommandBuffer scratch[VK_NUM_SCRATCH]; + + U32 image; // swapchain image index +}; + typedef struct Vk_Context Vk_Context; struct Vk_Context { void *lib; @@ -110,6 +141,8 @@ struct Vk_Context { U32 width; U32 height; } swapchain; + + VkSampler sampler; }; extern Vk_Context vk; @@ -122,6 +155,7 @@ function void Vk_FrameEnd(); function Vk_CommandBuffer *Vk_CommandBufferPush(); function void Vk_CommandBufferSubmit(Vk_CommandBuffer *cmds, B32 wait); -function Vk_Buffer Vk_BufferCreate(U64 size, B32 host_visible); +function void Vk_BufferCreate(Vk_Buffer *buffer); +function void Vk_ImageCreate(Vk_Image *image); #endif // LD_VULKAN_CORE_H_ diff --git a/code/vulkan/functions.h b/code/vulkan/functions.h index 9103cf9..afd5e41 100644 --- a/code/vulkan/functions.h +++ b/code/vulkan/functions.h @@ -48,6 +48,20 @@ VK_FUNC(GetImageMemoryRequirements); VK_FUNC(BindImageMemory); VK_FUNC(MapMemory); + VK_FUNC(CreateGraphicsPipelines); + VK_FUNC(CreateShaderModule); + VK_FUNC(CreateDescriptorSetLayout); + VK_FUNC(CreatePipelineLayout); + VK_FUNC(CmdBindPipeline); + VK_FUNC(CreateDescriptorPool); + VK_FUNC(ResetDescriptorPool); + VK_FUNC(AllocateDescriptorSets); + VK_FUNC(CmdBindDescriptorSets); + VK_FUNC(UpdateDescriptorSets); + VK_FUNC(CreateSampler); + VK_FUNC(CmdDraw); + VK_FUNC(CmdSetViewport); + VK_FUNC(CmdSetScissor); VK_FUNC(CmdCopyBufferToImage); VK_FUNC(CmdPipelineBarrier2); diff --git a/code/vulkan/shaders/basic.frag b/code/vulkan/shaders/basic.frag new file mode 100644 index 0000000..8886c82 --- /dev/null +++ b/code/vulkan/shaders/basic.frag @@ -0,0 +1,12 @@ +#version 460 core + +layout(location = 0) in vec2 frag_uv; +layout(location = 1) in vec4 frag_c; + +layout(location = 0) out vec4 framebuffer; + +layout(binding = 1) uniform sampler2D u_image; + +void main() { + framebuffer = frag_c * texture(u_image, frag_uv); +} diff --git a/code/vulkan/shaders/basic.vert b/code/vulkan/shaders/basic.vert new file mode 100644 index 0000000..f0b8dfe --- /dev/null +++ b/code/vulkan/shaders/basic.vert @@ -0,0 +1,28 @@ +#version 460 core + +#extension GL_EXT_scalar_block_layout : enable + +struct Vertex { + vec4 p; + vec2 uv; + uint c; + uint pad; +}; + +layout(binding = 0, scalar) +readonly buffer Vertices { + Vertex vtx[]; +}; + +layout(location = 0) out vec2 frag_uv; +layout(location = 1) out vec4 frag_c; + +void main() { + Vertex v = vtx[gl_VertexIndex]; + + gl_Position = v.p; + + frag_uv = v.uv; + frag_c = vec4((v.c >> 24) & 0xFF, (v.c >> 16) & 0xFF, (v.c >> 8) & 0xFF, (v.c >> 0) & 0xFF) / 255.0f; + frag_c = frag_c.abgr; +} diff --git a/windows.bat b/windows.bat index a5a4012..e1b3c00 100644 --- a/windows.bat +++ b/windows.bat @@ -58,6 +58,13 @@ IF %assets% equ 1 ( xcopy /Y /Q "..\assets" "assets" ) +ECHO [Building shaders] + +IF NOT EXIST "assets\shaders" ( MKDIR "assets\shaders" ) + +glslangValidator -o "assets\shaders\basic.vert.spv" --target-env vulkan1.3 "..\code\vulkan\shaders\basic.vert" +glslangValidator -o "assets\shaders\basic.frag.spv" --target-env vulkan1.3 "..\code\vulkan\shaders\basic.frag" + ECHO [Building source] SET COMPILER_OPTS=-nologo -W4 -I"deps\SDL3\include" -I"deps\stb" -I"%VULKAN_SDK%\Include"