# HG changeset patch # User Leonard Ritter # Date 1645447455 -3600 # Mon Feb 21 13:44:15 2022 +0100 # Node ID 1ec8b4c14e0bca88e6b4d94882b3a1c3a80fb2e5 # Parent 918c1c3d6146ab0b9b3c453161b8f7d31aa4c7e3 * spread terrain meshing over multiple frames diff --git a/lib/tukan/ResourceGroup.sc b/lib/tukan/ResourceGroup.sc --- a/lib/tukan/ResourceGroup.sc +++ b/lib/tukan/ResourceGroup.sc @@ -100,6 +100,13 @@ run-stage; type+ ResourceGroup + inline static-array (self T size func) + 'static self (array T size) + inline () + arrayof T + va-map func + va-range size + inline program (self ...) 'static self GL.Program inline () diff --git a/testing/test_cascade_dmc_cc_vvf.sc b/testing/test_cascade_dmc_cc_vvf.sc --- a/testing/test_cascade_dmc_cc_vvf.sc +++ b/testing/test_cascade_dmc_cc_vvf.sc @@ -38,6 +38,7 @@ using import tukan.spherical using import tukan.ResourceGroup using import tukan.logcell +using import tukan.Screen using import .testfragment let RG = (ResourceGroup "RG") @@ -69,6 +70,7 @@ FOG_RATE := 0.02 # 50% at 100 units let MAX_VERTICES = (20 * (1 << 20)) +MAX_SECTORS_PER_FRAME := 64 << 5 let WORLD_SIZE = (uvec3 256) let WORLD_SCALE = (vec3 256.0) @@ -93,7 +95,7 @@ CASCADE_CENTER := (CASCADE_SIZE // 2) let BINDING_BUF_SECTOR_IN = 1 -let BINDING_BUF_FACE_BRIDGE_IN = 2 +let BINDING_BUF_SECTOR_INOUT = 2 let BINDING_BUF_VERTEX_IN = 3 let BINDING_BUF_VERTEX_OUT = 4 let BINDING_BUF_DRAW_VOXELS_CMD = 5 @@ -148,6 +150,8 @@ struct Sector plain key : u32 flags : u32 # six face bits indicating where the next highest LOD level is + offset-min = 0xffffffff:u32 # index of first triangle in triangle buffer + offset-max = 0:u32 # index after last triangle in triangle buffer struct Sectors plain keys : (array Sector) @@ -156,9 +160,9 @@ binding = BINDING_BUF_SECTOR_IN \ readonly coherent -buffer face-bridge-in : Sectors - binding = BINDING_BUF_FACE_BRIDGE_IN - \ readonly coherent +buffer sector-inout : Sectors + binding = BINDING_BUF_SECTOR_INOUT + \ coherent buffer vertex-in : Vertices binding = BINDING_BUF_VERTEX_IN @@ -174,9 +178,6 @@ uniform mouse-state : i32 location = UNIFORM_MOUSE_STATE -uniform sector-offset : u32 - location = UNIFORM_SECTOR_OFFSET - fn simple-sphere (p) (length p) - 0.5 @@ -1142,6 +1143,9 @@ # generate quad let ofs = (atomicAdd vertex-out.count 6) + sector := (sector-inout.keys @ gl_WorkGroupID.x) + atomicMin sector.offset-min ofs + atomicMax sector.offset-max (ofs + 6) entries := vertex-out.entries static-if USE_FLAT_SHADING n0 := (triangle-normal v00.pos v11.pos v10.pos) @@ -1186,9 +1190,9 @@ fn generate-cell-verts () local_size NATIVE_LANE_WIDTH 1 1 - sector := (copy (sector-in.keys @ (gl_WorkGroupID.x + sector-offset))) + sector := (sector-inout.keys @ gl_WorkGroupID.x) sector-flags := (copy sector.flags) - let lvl sectorpos... = (decode-cell sector.key) + let lvl sectorpos... = (decode-cell (copy sector.key)) #let lvl sectorpos... = (decode-cell 1:u32) lsectorpos := (ivec3 sectorpos...) sectorlod := (MAX_CASCADE_DEPTH - lvl) @@ -1673,9 +1677,18 @@ return col -fn shader (uv) - #mixdown uv - visualize-buffer uv +inout uv : vec2 (location = 0) +fn present-vert () + uv.out = + ((Screen.set-vertex-position) * 0.5) + 0.5 + ; + +fn present-frag () + uv := (deref uv.in) + out_Color = + #mixdown uv + visualize-buffer uv + ; ################################################################################ @@ -1827,14 +1840,25 @@ #debug = true global rg : (Option RG) + global terrain-doublebuffer-index = 0 + + struct TerrainJob plain + sectors-processed = 0:usize + + inline reset (self) + self.sectors-processed = 0 + inline fresh? (self) + self.sectors-processed == 0 + inline ready? (self) + self.sectors-processed >= (countof sectors) + + global terrain-job : TerrainJob + 'reset terrain-job fn per-frame-setup (size pg-test frame) let rg = 'force-unwrap rg - from (methodsof rg) let static program compute-program indirect-draw-arrays-setup - - GL.BindTextureUnit 0 fb-scene-color - GL.Uniform smp-screen 0 + from (methodsof rg) let static static-array program compute-program indirect-draw-arrays-setup let world = static GL.Texture @@ -1892,64 +1916,65 @@ GL.DispatchCompute (unpack (((WORLD_SIZE >> (lod as u32)) + GROUP_SIZE - 1) // GROUP_SIZE)) GL.MemoryBarrier (GL.TEXTURE_FETCH_BARRIER_BIT | GL.SHADER_IMAGE_ACCESS_BARRIER_BIT) - # update terrain - - collect-sectors; - sector-count := (countof sectors) - if (frame % 120 == 0) - print (sector-count as i32) "sectors" - let sector_buffer_sz = ((sizeof Sector) * SECTOR_CAPACITY) - let sector_buffer = - static GL.Buffer - inline () - let buf = (GL.Buffer) - GL.NamedBufferData buf (i32 sector_buffer_sz) null GL.DYNAMIC_READ - buf - GL.NamedBufferSubData sector_buffer 0 - i32 (sector-count * (sizeof Sector)) - & (sectors @ 0) - let vertex_buffer_sz = ((sizeof Vertices) + (sizeof Vertex) * MAX_VERTICES) - let vertex_buffer = - static GL.Buffer + let vertex_buffers = + static-array GL.Buffer 3 inline () let buf = (GL.Buffer) GL.NamedBufferData buf (i32 vertex_buffer_sz) null GL.STREAM_COPY + GL.ClearNamedBufferSubData buf GL.R32UI 0 (sizeof u32) GL.RED_INTEGER GL.UNSIGNED_INT null + buf + + let sector_buffer_sz = ((sizeof Sector) * SECTOR_CAPACITY) + let sector_buffers = + static-array GL.Buffer 2 + inline () + let buf = (GL.Buffer) + GL.NamedBufferData buf (i32 sector_buffer_sz) null GL.STREAM_COPY buf - do - # clear vertex buffer count - let ptr = - GL.MapNamedBufferRange vertex_buffer 0 (sizeof u32) - | GL.MAP_WRITE_BIT - GL.MAP_INVALIDATE_BUFFER_BIT - #GL.MAP_UNSYNCHRONIZED_BIT - let ptr = (bitcast ptr (mutable pointer Vertices)) - ptr.count = 0:u32 - GL.UnmapNamedBuffer vertex_buffer + # update terrain + + next-terrain-doublebuffer-index := terrain-doublebuffer-index ^ 1 + next_sector_buffer := sector_buffers @ next-terrain-doublebuffer-index + next_vertex_buffer := vertex_buffers @ next-terrain-doublebuffer-index + + if ('fresh? terrain-job) + collect-sectors; + GL.NamedBufferSubData next_sector_buffer 0 + i32 ((countof sectors) * (sizeof Sector)) + & (sectors @ 0) + GL.ClearNamedBufferSubData next_vertex_buffer GL.R32UI 0 (sizeof u32) GL.RED_INTEGER GL.UNSIGNED_INT null + sector-count := (countof sectors) + if ((cpu_shglobals.frame % 120) == 0) + print ((countof sectors) as i32) "sectors" + GL.BindBufferRange GL.SHADER_STORAGE_BUFFER BINDING_BUF_VERTEX_OUT - vertex_buffer + next_vertex_buffer \ 0:i64 (i64 vertex_buffer_sz) + sectors-to-process := (min MAX_SECTORS_PER_FRAME (sector-count as i32 - terrain-job.sectors-processed as i32)) GL.BindBufferRange GL.SHADER_STORAGE_BUFFER - BINDING_BUF_SECTOR_IN - sector_buffer - \ 0:i64 (i64 (sector-count * (sizeof Sector))) + BINDING_BUF_SECTOR_INOUT + next_sector_buffer + \ (i64 (terrain-job.sectors-processed * (sizeof Sector))) (i64 (sectors-to-process * (sizeof Sector))) GL.BindTextureUnit 1 world let pg-gen-cell = (compute-program generate-cell-verts) GL.UseProgram pg-gen-cell GL.Uniform smp-world 1 - MAX_WORKGROUPS := 32768:u32 - for i in (range 0:u32 (sector-count as u32) MAX_WORKGROUPS) - offset := i - GL.Uniform sector-offset offset - sz := (min MAX_WORKGROUPS (sector-count as u32 - i)) - GL.DispatchCompute sz 1 1 + GL.DispatchCompute (sectors-to-process as u32) 1 1 + terrain-job.sectors-processed += sectors-to-process GL.MemoryBarrier GL.SHADER_STORAGE_BARRIER_BIT + if ('ready? terrain-job) + 'reset terrain-job + terrain-doublebuffer-index ^= 1 + ############# + vertex_buffer := vertex_buffers @ terrain-doublebuffer-index + inline print-in-count () let ptr = GL.MapNamedBufferRange vertex_buffer 0 (sizeof u32) @@ -1996,8 +2021,6 @@ GL.STENCIL_BUFFER_BIT GL.UseProgram pg-rasterize - #GL.BindTextureUnit 1 world - #GL.Uniform smp-world 1 GL.BindVertexArray vao-empty exec-draw-arrays GL.TRIANGLES @@ -2005,11 +2028,21 @@ GL.Disable GL.CULL_FACE GL.BindFramebuffer GL.FRAMEBUFFER 0 + let screen = (static Screen) + let pg-presentfb = + program + vertex = present-vert + fragment = present-frag + GL.UseProgram pg-presentfb + GL.BindTextureUnit 0 fb-scene-color + GL.Uniform smp-screen 0 + 'draw screen + let per-frame-setup = static-typify per-frame-setup ivec2 GL.Program i32 rg = (RG) - _ per-frame-setup shader + per-frame-setup fn program () render-fragment-shader main