From b4ba1f491bd0ce2e688e5f07340de24210b20614 Mon Sep 17 00:00:00 2001 From: matthew Date: Fri, 18 Jul 2025 07:37:52 +1000 Subject: [PATCH] basic model rendering completed --- assets/models/cube.m3d | Bin 0 -> 223 bytes assets/shaders/gradient.comp.spv | Bin 2972 -> 2944 bytes assets/shaders/gui.frag.spv | Bin 1744 -> 1716 bytes assets/shaders/gui.vert.spv | Bin 4216 -> 4188 bytes assets/shaders/pbr.frag.spv | Bin 0 -> 1624 bytes assets/shaders/pbr.vert.spv | Bin 0 -> 2176 bytes assets/shaders/triangle.frag.spv | Bin 1708 -> 1680 bytes assets/shaders/triangle.vert.spv | Bin 2600 -> 2572 bytes src/gears/main.d | 5 - src/gears/renderer.d | 252 ++++++++++++++++++------------- src/gears/vulkan.d | 13 +- src/generated/assets_codegen.d | 9 ++ src/shaders/gradient.comp.glsl | 1 - src/shaders/gui.frag.glsl | 1 - src/shaders/gui.vert.glsl | 1 - src/shaders/pbr.frag.glsl | 16 ++ src/shaders/pbr.vert.glsl | 20 +++ src/shaders/triangle.frag.glsl | 1 - src/shaders/triangle.vert.glsl | 1 - 19 files changed, 201 insertions(+), 119 deletions(-) create mode 100644 assets/models/cube.m3d create mode 100644 assets/shaders/pbr.frag.spv create mode 100644 assets/shaders/pbr.vert.spv create mode 100644 src/shaders/pbr.frag.glsl create mode 100644 src/shaders/pbr.vert.glsl diff --git a/assets/models/cube.m3d b/assets/models/cube.m3d new file mode 100644 index 0000000000000000000000000000000000000000..a10dee65ba453115ee57cea1b7c95b67ab3becff GIT binary patch literal 223 zcmV<503iP}L`_fM0001ZUh{BubkSe{fd+eq^E?dB`8oMT3eKfTsSIvKsi_Q(#l@Mq z1q=+%zK#JPbu0`z|9!cP{!1`a{;%e;_+On{@n4+b_T literal 0 HcmV?d00001 diff --git a/assets/shaders/gradient.comp.spv b/assets/shaders/gradient.comp.spv index 23de3cb0cb8c082eb8f8b21df4c356750711966c..8a334e2389a1de3748e8df00123090c4a0becc16 100644 GIT binary patch delta 10 RcmbOu-XK0<*~UY+xBwXV1lRxo delta 36 qcmZn=pCdkDnIt=dyHC7pL`Zy6XPTjcpE*AjgyM=ectc}~G*Z>+F1W*6~ delta 36 qcmdnOdx3YtEJ=0-cb|CIh>-ZC(zLYHqWGdzAeow%oVszkEE@prSq&Zl diff --git a/assets/shaders/gui.vert.spv b/assets/shaders/gui.vert.spv index 07752bfc08f202537a96f6b56a15e26899e05a9a..96f037c9359486e11fa3f4cebbd0ea77014c972c 100644 GIT binary patch delta 10 ScmeyNa7SUnvW-ZC(zLYHqWGdzAeow%oVs!GPJRFYJq}R- diff --git a/assets/shaders/pbr.frag.spv b/assets/shaders/pbr.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..50f14035334c366ec9d811a65a8d35691cc3265e GIT binary patch literal 1624 zcmZvbQBTxR5QXp3?t-ich=3sC0*V?F;)5C!qc4cnWEGRe#J8sI7HHCK*KQZ}Kl+1w zG4Xu2En5;V8RnjuIWxC2v(C)ktZ6k&+bo#JrZ~%H#x!(oo0ipHx7R%w=YxZ1&z}-; z!#FmOm__}$(#SA~5**hgZOM{kMY1N@kld5(N%kd=BumNzZ&u>yZ$|pJlDcNjcwPVK z>xrMF$s~zR(`@K}p9FDq8ikqs^Z32vW3PMU_eUdtod1eLKaP^nA4FN$&!da*GEW&7 zCH;6Zs0TEass8S!Y1+5H%Yw7RG)^c$ zvT&?8$9}&j3};!ocODGFtj;Oya7J;^56{zB0hUYOdJ^75|K4W7j}OD(OrK@*(a&Bm z9K~VwDGXFGFJkHON%%9L@CX~*G#%-WK^|sNpfBL9Eo+h_dbz)#=netM4IDgEHOpWfr=zz5?m>N%#PJGuEj z?wtDjxYzk$_;5T`rRNpD>VKWjZ;F0WZ$**B?uh3|b6?Y~CEby%>wWz0z^Kcd@i%BR80NRhc$;f(mUe8!f|(Vu z8``2<(!^4?e()pITP+>Lk^{^>Oh>|b zQsOP$iP;jqD@`73)U0+MJ8uKCD;)aPk)|fx9cggI-PN6M#10qC4q$`JUQ~U2pgZ%! zMl5*0wDFFIx;G@u2tSw|!uCQtN=|lz!w&qBr78VdR(9aJg!#Xbmpb6TV!xF91G2?} A(EtDd literal 0 HcmV?d00001 diff --git a/assets/shaders/pbr.vert.spv b/assets/shaders/pbr.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..4733175f136947239f1ad605dec8290afe71b7b4 GIT binary patch literal 2176 zcmY+FX-^bE5QZD}Kt(`AJP{Z1M)3k;Vl**8Mw3-c7LDH~Us z_vxO-u{X8V?^{QAR~2kya&^kIC(N{&F`LG%c{6Dyw4F9>tAlQ@yFMxh>l>R7@R&6X z>xj>sS+M)2z7L}$1I$R~C5w`?l1q|h$%^EfF+Q{48M${H2Ivwh3qG=2fMpLcPH!*hvBIFk;Y+~WN|o1inw1UU*n@Z zm0yze)A6A0&{C%Q-CKI|wC=EccR{g^XOAr(C1sLlVyCP>wXl4WmA&Mr zPA10Lc#~{fX)@eSMrD-s<0BiD#5PXTBU?*#poT2&M=g^q9Ofg3scSwi!+xGxJ2jRa zDBLy|go8By6s7N7-4xeW9(Yy}kL1^|eF=n#S(5G@M1#1f$2gvtVH)-0gFKakjisMG zNlPF4x?M!yULQvLJe+*=xfdM{)3|sWM>?@|zVv=C{$7r`g!OHi+tP2MGA@!xFL1Sn zWBq?_%g&AWB?0H(litcRDqF(QD>&Bw@eMn3@3veVv!}Xcnk;)TwPqH@jlW8RnM-O7 z5vXR&2K{^`D|?pLo?{l^(4Hd(j(&TNJsk5F=$k%MR~DE)*D-wt6USZXr@xEu?W#By z@%-J<8` zb7r;gNXW}M;5iA4_*2r@$W1($S%bsAAWeR62Qzzc-k;gSpLd>@=HAp`SzgQ@9Jwx5 zJRGrL=Fs~xXRc;VbGhQ-@CEz&Ur<%9RKA>BU*tkKuTvTDB?ow=;x5YTs`mJ;RvZ{V zF!Ractn1R;YXYLSJf>ea#N$W5$a%B!gC{4L8D>!zW|o}9-jN3T*fs5W13a-{<`<4w z=9O5^S(hdb4qq_8op50K$t-hM{2x|(dV(Fy|21!atUbN;cCh>XHRg%_*0=*R%);-t sn3nW&vCPP63G?$(EVFV(!aOo_FBAdB$NQhtp83JXT!H`SHcusg0hNriSpWb4 literal 0 HcmV?d00001 diff --git a/assets/shaders/triangle.frag.spv b/assets/shaders/triangle.frag.spv index 2bd01d0491a6e45eb28b133009d4e92179b08181..e179e7034060ccc79b9c0cb5af03f916f72e0559 100644 GIT binary patch delta 10 ScmZ3(JArq?q>bzTu>t@Y8wA?` delta 36 qcmbQhyM}kdBuRD#cb|CIh>-ZC(zLYHqWGdzAeow%oVu}}kqrRiISi@* diff --git a/assets/shaders/triangle.vert.spv b/assets/shaders/triangle.vert.spv index 7f35aa68308f43c54377350acb0d2c4299fc5eb7..b7669bd0b2de3f7d7fa171a85635481ea1ea089b 100644 GIT binary patch delta 10 RcmZ1>(jziq(#CaFoB$X<1YrOG delta 36 qcmeAXSs^lEk|aBWyHC7pL`Zy6XPTkmF%LxGE_zf=r diff --git a/src/gears/main.d b/src/gears/main.d index afc8383..c500f64 100644 --- a/src/gears/main.d +++ b/src/gears/main.d @@ -7,11 +7,6 @@ import r = renderer; import util; import core.simd; -struct Floats -{ - f32 r = 0.0, g = 0.0, b = 0.0, a = 0.0; -} - void main() { p.Window window = p.CreateWindow("Video Game", 1920, 1080); diff --git a/src/gears/renderer.d b/src/gears/renderer.d index 8e7e857..7fe0e8f 100644 --- a/src/gears/renderer.d +++ b/src/gears/renderer.d @@ -6,6 +6,7 @@ import alloc; import vulkan; import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepCompute, Dispatch, FinishFrame, BeginFrame; import assets; +import std.math.traits : isNaN; import u = util; import p = platform; @@ -28,6 +29,8 @@ enum Format : VkFormat RG_F32 = VK_FORMAT_R32G32_SFLOAT, RGB_F32 = VK_FORMAT_R32G32B32_SFLOAT, RGBA_F32 = VK_FORMAT_R32G32B32A32_SFLOAT, + RGBA_UINT = VK_FORMAT_B8G8R8A8_UINT, + RGBA_UNORM = VK_FORMAT_R8G8B8A8_UNORM, } alias FMT = Format; @@ -74,6 +77,7 @@ struct Renderer u32[] ui_index_buf; u32 ui_count; + Pipeline pbr_pipeline; Pipeline triangle_pipeline; Pipeline compute_pipeline; Pipeline ui_pipeline; @@ -173,6 +177,19 @@ Init(p.Window* window) ], }; + GfxPipelineInfo pbr_info = { + vertex_shader: "shaders/pbr.vert", + frag_shader: "shaders/pbr.frag", + input_rate_stride: Vertex.sizeof, + vertex_attributes: [ + { binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 }, + { binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.n.offsetof }, + { binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.uv.offsetof }, + { binding: 0, location: 3, format: FMT.RGBA_UNORM, offset: Vertex.col.offsetof }, + ], + }; + + rd.pbr_pipeline = BuildGfxPipeline(&rd, &pbr_info); rd.triangle_pipeline = BuildGfxPipeline(&rd, &triangle_info); rd.ui_pipeline = BuildGfxPipeline(&rd, &ui_info); rd.compute_pipeline = BuildCompPipeline(&rd, "shaders/gradient.comp"); @@ -207,18 +224,144 @@ Cycle(Renderer* rd) BindUIBuffers(rd); - DrawIndexed(rd, 6, rd.ui_count); + DrawIndexed(rd, 6, rd.ui_count, 0); Bind(rd, &rd.triangle_pipeline); Draw(rd, 3, 1); + Bind(rd, &rd.pbr_pipeline); + + DrawModel(rd, &rd.yoder); + success = FinishFrame(rd); } return success; } +pragma(inline): void +DrawModel(Renderer* rd, Model* model) +{ + BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer); + + foreach(i, part; model.parts) + { + DrawIndexed(rd, part.length, 1, part.offset); + } +} + +pragma(inline): void +CopyVertex(Vec4* dst, m3dv_t* src) +{ + asm + { + mov R8, src; + mov R9, dst; + movups XMM0, src.x.offsetof[R8]; + movups dst.x.offsetof[R9], XMM0; + } + +debug +{ + assert(dst.x == src.x && dst.y == src.y && dst.z == src.z && dst.w == src.w, "Vertex copy failed"); + assert(!isNaN(dst.x) && !isNaN(dst.y) && !isNaN(dst.z) && !isNaN(dst.w), "Vertex contains NaN"); +} +} + +pragma(inline): bool +BeginFrame(Renderer* rd) +{ + return BeginFrame(&rd.vk); +} + +pragma(inline): bool +FinishFrame(Renderer* rd) +{ + return FinishFrame(&rd.vk); +} + +pragma(inline): void +Dispatch(Renderer* rd) +{ + Dispatch(&rd.vk); +} + +pragma(inline): void +PrepCompute(Renderer* rd) +{ + PrepCompute(&rd.vk); +} + +pragma(inline): void +SetUniform(Renderer* rd, GlobalUniforms* uniforms) +{ + SetUniform(&rd.vk, uniforms); +} + +pragma(inline): void +BeginRender(Renderer* rd) +{ + BeginRender(&rd.vk); +} + +pragma(inline): void +BindUIBuffers(Renderer* rd) +{ + BindUIBuffers(&rd.vk); +} + +pragma(inline): void +DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count, u32 index_offset) +{ + DrawIndexed(&rd.vk, index_count, instance_count, index_offset); +} + +pragma(inline): void +Draw(Renderer* rd, u32 index_count, u32 instance_count) +{ + Draw(&rd.vk, index_count, instance_count); +} + +pragma(inline): void +Bind(Renderer* rd, Pipeline* pipeline) +{ + Bind(&rd.vk, pipeline); +} + +void +DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col) +{ + rd.ui_vertex_buf[rd.ui_count].p0.x = p0_x; + rd.ui_vertex_buf[rd.ui_count].p0.y = p0_y; + rd.ui_vertex_buf[rd.ui_count].p1.x = p1_x; + rd.ui_vertex_buf[rd.ui_count].p1.y = p1_y; + rd.ui_vertex_buf[rd.ui_count].col = col; + + u32 index_count = rd.ui_count * 6; + + rd.ui_index_buf[index_count+0] = index_count+0; + rd.ui_index_buf[index_count+1] = index_count+1; + rd.ui_index_buf[index_count+2] = index_count+2; + rd.ui_index_buf[index_count+3] = index_count+1; + rd.ui_index_buf[index_count+4] = index_count+2; + rd.ui_index_buf[index_count+5] = index_count+3; + + rd.ui_count += 1; +} + +pragma(inline): Pipeline +BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) +{ + return CreateGraphicsPipeline(&rd.vk, info); +} + +pragma(inline): Pipeline +BuildCompPipeline(Renderer* rd, string compute) +{ + return CreateComputePipeline(&rd.vk, compute); +} + Model LoadModel(Renderer* rd, string name) { @@ -298,7 +441,7 @@ LoadModel(Renderer* rd, string name) { if (last == u64.max) { - model.parts[index].mat = mat_lookup[m3d.face[i].materialid]; + model.parts[index].mat = m3d.face[i].materialid != u32.max ? mat_lookup[m3d.face[i].materialid] : 0; model.parts[index].offset = 0; last = m3d.face[i].materialid; } @@ -369,111 +512,6 @@ LoadModel(Renderer* rd, string name) return model; } -pragma(inline): void -CopyVertex(Vec4* dst, m3dv_t* src) -{ - asm - { - mov R8, src; - mov R9, dst; - movups XMM0, src.x.offsetof[R8]; - movups dst.x.offsetof[R9], XMM0; - } -} - -pragma(inline): bool -BeginFrame(Renderer* rd) -{ - return BeginFrame(&rd.vk); -} - -pragma(inline): bool -FinishFrame(Renderer* rd) -{ - return FinishFrame(&rd.vk); -} - -pragma(inline): void -Dispatch(Renderer* rd) -{ - Dispatch(&rd.vk); -} - -pragma(inline): void -PrepCompute(Renderer* rd) -{ - PrepCompute(&rd.vk); -} - -pragma(inline): void -SetUniform(Renderer* rd, GlobalUniforms* uniforms) -{ - SetUniform(&rd.vk, uniforms); -} - -pragma(inline): void -BeginRender(Renderer* rd) -{ - BeginRender(&rd.vk); -} - -pragma(inline): void -BindUIBuffers(Renderer* rd) -{ - BindUIBuffers(&rd.vk); -} - -pragma(inline): void -DrawIndexed(Renderer* rd, u32 index_count, u32 instance_count) -{ - DrawIndexed(&rd.vk, index_count, instance_count); -} - -pragma(inline): void -Draw(Renderer* rd, u32 index_count, u32 instance_count) -{ - Draw(&rd.vk, index_count, instance_count); -} - -pragma(inline): void -Bind(Renderer* rd, Pipeline* pipeline) -{ - Bind(&rd.vk, pipeline); -} - -void -DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col) -{ - rd.ui_vertex_buf[rd.ui_count].p0.x = p0_x; - rd.ui_vertex_buf[rd.ui_count].p0.y = p0_y; - rd.ui_vertex_buf[rd.ui_count].p1.x = p1_x; - rd.ui_vertex_buf[rd.ui_count].p1.y = p1_y; - rd.ui_vertex_buf[rd.ui_count].col = col; - - u32 index_count = rd.ui_count * 6; - - rd.ui_index_buf[index_count+0] = index_count+0; - rd.ui_index_buf[index_count+1] = index_count+1; - rd.ui_index_buf[index_count+2] = index_count+2; - rd.ui_index_buf[index_count+3] = index_count+1; - rd.ui_index_buf[index_count+4] = index_count+2; - rd.ui_index_buf[index_count+5] = index_count+3; - - rd.ui_count += 1; -} - -pragma(inline): Pipeline -BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) -{ - return CreateGraphicsPipeline(&rd.vk, info); -} - -pragma(inline): Pipeline -BuildCompPipeline(Renderer* rd, string compute) -{ - return CreateComputePipeline(&rd.vk, compute); -} - void Destroy(Renderer* rd) { diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d index 745476c..3ab09cf 100644 --- a/src/gears/vulkan.d +++ b/src/gears/vulkan.d @@ -316,6 +316,15 @@ BindUIBuffers(Vulkan* vk) vkCmdBindVertexBuffers(vk.cmds[vk.frame_index], 0, 1, &vk.ui_vert_buf.buffer, &offset); } +void +BindBuffers(Vulkan* vk, Buffer* index_buffer, Buffer* vertex_buffer) +{ + VkDeviceSize offset = 0; + + vkCmdBindIndexBuffer(vk.cmds[vk.frame_index], index_buffer.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindVertexBuffers(vk.cmds[vk.frame_index], 0, 1, &vertex_buffer.buffer, &offset); +} + MappedBuffer!(T) CreateMappedBuffer(T)(Vulkan* vk, BufferType type, u64 count) { @@ -541,9 +550,9 @@ Draw(Vulkan* vk, u32 index_count, u32 instance_count) } void -DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count) +DrawIndexed(Vulkan* vk, u32 index_count, u32 instance_count, u32 index_offset) { - vkCmdDrawIndexed(vk.cmds[vk.frame_index], index_count, instance_count, 0, 0, 0); + vkCmdDrawIndexed(vk.cmds[vk.frame_index], index_count, instance_count, index_offset, 0, 0); } bool diff --git a/src/generated/assets_codegen.d b/src/generated/assets_codegen.d index 5469113..b3f00e5 100644 --- a/src/generated/assets_codegen.d +++ b/src/generated/assets_codegen.d @@ -11,16 +11,19 @@ enum AssetType : u32 alias AT = AssetType; static immutable string[] MODEL_FILES = [ + "models/cube.m3d", "models/test_char.m3d", "models/yoda.m3d", ]; static immutable string[] MODEL_NAMES = [ + "models/cube", "models/test_char", "models/yoda", ]; static immutable u64[] MODEL_HASHES = [ + 16487010975852376380, 13826959199295087925, 4559395153940738542, ]; @@ -28,25 +31,31 @@ static immutable u64[] MODEL_HASHES = [ static immutable string[] SHADER_FILES = [ "shaders/gui.frag.spv", "shaders/triangle.vert.spv", + "shaders/pbr.frag.spv", "shaders/gui.vert.spv", "shaders/gradient.comp.spv", "shaders/triangle.frag.spv", + "shaders/pbr.vert.spv", ]; static immutable string[] SHADER_NAMES = [ "shaders/gui.frag", "shaders/triangle.vert", + "shaders/pbr.frag", "shaders/gui.vert", "shaders/gradient.comp", "shaders/triangle.frag", + "shaders/pbr.vert", ]; static immutable u64[] SHADER_HASHES = [ 15780387719315455808, 8769314645675479020, + 2230071466542309169, 14797956403837654625, 16130483095684998267, 6282520872716708711, + 8518761701216801634, ]; static immutable string[] TEXTURE_FILES = [ diff --git a/src/shaders/gradient.comp.glsl b/src/shaders/gradient.comp.glsl index ce38a5b..8fd4a55 100644 --- a/src/shaders/gradient.comp.glsl +++ b/src/shaders/gradient.comp.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #include "structures.layout" diff --git a/src/shaders/gui.frag.glsl b/src/shaders/gui.frag.glsl index 500f07f..5907081 100644 --- a/src/shaders/gui.frag.glsl +++ b/src/shaders/gui.frag.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require diff --git a/src/shaders/gui.vert.glsl b/src/shaders/gui.vert.glsl index 6e4c839..8a1828b 100644 --- a/src/shaders/gui.vert.glsl +++ b/src/shaders/gui.vert.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require diff --git a/src/shaders/pbr.frag.glsl b/src/shaders/pbr.frag.glsl new file mode 100644 index 0000000..776ab70 --- /dev/null +++ b/src/shaders/pbr.frag.glsl @@ -0,0 +1,16 @@ +#version 460 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_nonuniform_qualifier : require + +#include "structures.layout" + +layout (location = 0) in vec4 in_col; +layout (location = 1) in vec2 in_uv; + +layout (location = 0) out vec4 FragColor; + +void main() +{ + FragColor = in_col; +} diff --git a/src/shaders/pbr.vert.glsl b/src/shaders/pbr.vert.glsl new file mode 100644 index 0000000..ea0519a --- /dev/null +++ b/src/shaders/pbr.vert.glsl @@ -0,0 +1,20 @@ +#version 460 + +#extension GL_GOOGLE_include_directive : require +#extension GL_EXT_nonuniform_qualifier : require + +#include "structures.layout" + +layout (location = 0) in vec4 in_pos; +layout (location = 1) in vec4 in_normal; +layout (location = 2) in vec2 in_uv; +layout (location = 3) in vec4 in_col; + +layout (location = 0) out vec4 out_col; +layout (location = 1) out vec2 out_uv; + +void main() +{ + gl_Position = in_pos; + out_col = in_col; +} diff --git a/src/shaders/triangle.frag.glsl b/src/shaders/triangle.frag.glsl index e752f65..99b6836 100644 --- a/src/shaders/triangle.frag.glsl +++ b/src/shaders/triangle.frag.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require diff --git a/src/shaders/triangle.vert.glsl b/src/shaders/triangle.vert.glsl index cc359d2..d7372ae 100644 --- a/src/shaders/triangle.vert.glsl +++ b/src/shaders/triangle.vert.glsl @@ -1,6 +1,5 @@ #version 460 -#extension GL_EXT_buffer_reference : require #extension GL_GOOGLE_include_directive : require #extension GL_EXT_nonuniform_qualifier : require