From 8d50885e922c9693bd75da0b37cfb7d991f3b4c2 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Mon, 19 May 2025 18:13:34 +0200 Subject: [PATCH] Added slang shaders for compute cull and lod sample Adjusted vertex bindings --- shaders/glsl/computecullandlod/cull.comp.spv | Bin 5060 -> 5084 bytes .../glsl/computecullandlod/indirectdraw.vert | 4 +- .../computecullandlod/indirectdraw.vert.spv | Bin 2344 -> 2344 bytes .../hlsl/computecullandlod/indirectdraw.vert | 4 +- .../computecullandlod/indirectdraw.vert.spv | Bin 3408 -> 1864 bytes shaders/slang/computecullandlod/cull.slang | 115 ++++++++++++++++++ .../computecullandlod/indirectdraw.slang | 56 +++++++++ 7 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 shaders/slang/computecullandlod/cull.slang create mode 100644 shaders/slang/computecullandlod/indirectdraw.slang diff --git a/shaders/glsl/computecullandlod/cull.comp.spv b/shaders/glsl/computecullandlod/cull.comp.spv index a90380f98bd809212ba6143eb3c67117899925ed..b8b6bb0cb544f54d78bc5c9512639476aeb780f0 100644 GIT binary patch delta 215 zcmX@2en*{?nMs+Qfq{{Mdn2bi3#U5+GlL=n0|V1!Ul#ev4J=%flUPJ1cd$1pf<`UdA3(kYYltOChd)pUGZ1?)u!7k@CWA7F00MUg7KT6|4Kfu3V0@*? zOIfSI_9X*FnJ3G#X|tvRS(1}u*~BM@un9~qVUwA>gNPvIiVP3{lw=T?Jds6y@(~t+$!l0d zCSPGuVq~8Dn?-i=51@zyYY3|c11p37WJfk(MSq}bW*~NFU||RZ(n>%K0x-Vfb`8}wB-I^gszH2^YL?9_*^PMsxfCW! diff --git a/shaders/glsl/computecullandlod/indirectdraw.vert b/shaders/glsl/computecullandlod/indirectdraw.vert index 4087e1bb..4335228b 100644 --- a/shaders/glsl/computecullandlod/indirectdraw.vert +++ b/shaders/glsl/computecullandlod/indirectdraw.vert @@ -6,8 +6,8 @@ layout (location = 1) in vec3 inNormal; layout (location = 2) in vec3 inColor; // Instanced attributes -layout (location = 4) in vec3 instancePos; -layout (location = 5) in float instanceScale; +layout (location = 3) in vec3 instancePos; +layout (location = 4) in float instanceScale; layout (binding = 0) uniform UBO { diff --git a/shaders/glsl/computecullandlod/indirectdraw.vert.spv b/shaders/glsl/computecullandlod/indirectdraw.vert.spv index bcbf69270ca22321dd3f26fad3fb25950ee2e4be..d94a9ed2cd8f063ee9fe3cbb7292d24a56ed4b12 100644 GIT binary patch delta 130 zcmZ1>v_goJnMs+Qfq{{Mdn2belO+oS1A{vQ3xhO}mIGpDFrS%08Avk$u?GVym&zBsx(1TKmgLoFnKSN{NxWz9Fs3FiA)w@7MaY!EU;LE GnGFEZB@LPY delta 106 zcmZ1>v_goJnMs+Qfq{{MeIutglOQVt1A{vQ3xhO}mIGpz$%RbPjLMUHnUq0q|Yhw-OqdN`oT^rR(>TfgGUs}{LrPc~P!R+6EA9F#UqD1JffIJ1~8LIbiw$ zTRi#zTRdt3TRi48F5=)1u6pELQ`y-8PA$8R$ms2?s3||Qqb~EK2K*L!WW9danIC(} zv3$#_6dCo8i02m&i$>)^ZZN*!!GP&)SooaoSVa7(fQNeUd0`HEVhwxr^||2@kN@dM zJ&qfuAM?1mI41uK;;D&xD*EP4kU^Eu2eMeYi@NEF-oTf1Qz!o5%K_69_)5T8|E0e( zH2bU4(>L}*iX7{%N>bGgPYmWvPU?9gObyH%8JHU2`vRs0V&*ZuStn!|WNe zCI<1Tk$uf$_BD^$*F4VtyPTU=WO}QKm?dPwPV5cIh>!T4%lGgG^O7+??7oCqJPP=kCc>@|7oI&~PVnpq TGlFM7@PTJHi1}NY=0$%1wVQ6* literal 3408 zcmZve`Eyi75XT?MZUW&@L?9~04S0hQEk!I9CD9_OirJW8)E}3)rE4YGRM?=XB_Q4h z;(aUL_wncXi&cI;?@gDF)!FJyf4|++-P1GkD!o0s`m=0JmSvl=Kl$s}ob@E8H^*8p z;O9_ZY_yitdk{S;NEPWr2$roy)*%DPdZd@1_9HB)^4o|$H(OurEU$J@Sy#z9_38Fe zaN%RFsrJfZV?m#SGv`=)p}oQ!oHfj~norI(=i&PDSk^SzdhGFzB*VNz%$?)Q&5_k3 zZ8`JGIi#x8c?J4|qxC$Fx?_2z{X}!V(`vJ8$4MwC+bssG2_>VXO<<~RDI_DgOga~tvT^y^~w5-3#xR~-X;FofPJ zSpBT}kL@O?Jf7#!UhU*XL?ZKeHo-?C^LSptMd3U19F0O~4o1Iwl zc-@uQ5oaszK3lo-&$cgLSM=&=r?E8OEY|nue9^0dpPg?kG+FQ7b~7(GRvL@>u3LEx zhp54O=^h+nbH&+<%_FuhvGK+Fi9G|cyx6{r<;C_|>=4^yal{))IO180cJu1*-Pwsa z0uL838z)QL#a;iyxwi|EapHuZb;detaNRv!T=zQtVqNSd@*Sd5IqTns?$@A(Y-hzL zX0dC<)*^OqLv-Hvu8(|KM)1(K8QIFZiivh3vDfiKDNzxGRWTss){%W^zEx`%zZhaHG(^wVa%L1NdKwVQj0zn()a$q*IT zyMn7^m!rEUxf;I1%xe(Wi+3h$uf(2#_M+#N>`HX^6#iEwtp64wU(Gy>$2H9Ao`LU6 z|8oB$-gWTa1$~CecRRD^B5(dXnYGJ_4Bk2(>SixU!Ma+HMe$k_vKqXNVHMr=Me3_(a3co@!@k4>^gmn zA=W4Cr_hbzyN(#oqsxcSX>?=gV+^rA+U@TPh%x*Y7{eaDh{)I3qdj^laqN2clh@-#&5J{2x=! z^YH%Mg2*}a?`M|N?*48?v|E$*wTTP+zGV08w69~93;S)!-ka instances; + +// Same layout as VkDrawIndexedIndirectCommand +struct IndexedIndirectCommand +{ + uint indexCount; + uint instanceCount; + uint firstIndex; + uint vertexOffset; + uint firstInstance; +}; +RWStructuredBuffer indirectDraws; + +// Binding 2: Uniform block object with matrices +struct UBO +{ + float4x4 projection; + float4x4 modelview; + float4 cameraPos; + float4 frustumPlanes[6]; +}; +ConstantBuffer ubo; + +// Binding 3: Indirect draw stats +struct UBOOut +{ + uint drawCount; + uint lodCount[MAX_LOD_LEVEL_COUNT]; +}; +RWStructuredBuffer uboOut; + +// Binding 4: level-of-detail information +struct LOD +{ + uint firstIndex; + uint indexCount; + float distance; + float _pad0; +}; +StructuredBuffer lods; + +bool frustumCheck(float4 pos, float radius) +{ + // Check sphere against frustum planes + for (int i = 0; i < 6; i++) + { + if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0) + { + return false; + } + } + return true; +} + +[shader("compute")] +[numthreads(16, 1, 1)] +void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID) +{ + uint idx = GlobalInvocationID.x; + uint temp; + + // Clear stats on first invocation + if (idx == 0) + { + InterlockedExchange(uboOut[0].drawCount, 0, temp); + for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++) + { + InterlockedExchange(uboOut[0].lodCount[i], 0, temp); + } + } + + float4 pos = float4(instances[idx].pos.xyz, 1.0); + + // Check if object is within current viewing frustum + if (frustumCheck(pos, 1.0)) + { + indirectDraws[idx].instanceCount = 1; + + // Increase number of indirect draw counts + InterlockedAdd(uboOut[0].drawCount, 1, temp); + + // Select appropriate LOD level based on distance to camera + uint lodLevel = MAX_LOD_LEVEL; + for (uint i = 0; i < MAX_LOD_LEVEL; i++) + { + if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance) + { + lodLevel = i; + break; + } + } + indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex; + indirectDraws[idx].indexCount = lods[lodLevel].indexCount; + // Update stats + InterlockedAdd(uboOut[0].lodCount[lodLevel], 1, temp); + } + else + { + indirectDraws[idx].instanceCount = 0; + } +} \ No newline at end of file diff --git a/shaders/slang/computecullandlod/indirectdraw.slang b/shaders/slang/computecullandlod/indirectdraw.slang new file mode 100644 index 00000000..d051bd6c --- /dev/null +++ b/shaders/slang/computecullandlod/indirectdraw.slang @@ -0,0 +1,56 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float4 Pos : POSITION0; + float3 Normal; + float3 Color; + // Instanced attributes + float3 instancePos; + float instanceScale; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float3 Color; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 modelview; +}; +ConstantBuffer ubo; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.Color = input.Color; + output.Normal = input.Normal; + float4 pos = float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0); + output.Pos = mul(ubo.projection, mul(ubo.modelview, pos)); + float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0)); + float4 lPos = float4(0.0, 10.0, 50.0, 1.0); + output.LightVec = lPos.xyz - pos.xyz; + output.ViewVec = -pos.xyz; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float3 N = normalize(input.Normal); + float3 L = normalize(input.LightVec); + float3 ambient = float3(0.25, 0.25, 0.25); + float3 diffuse = max(dot(N, L), 0.0).xxx; + return float4((ambient + diffuse) * input.Color, 1.0); +} \ No newline at end of file