@@ 100,6 100,13 @@ type ResourceGroup
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 ()
@@ 38,6 38,7 @@ using import tukan.hash
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 @@ FETCH_UV_OFFSET := 0.5
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_SIZE := (1 << MAX_CASCADE_DEPTH)
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 @@ let
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 @@ buffer sector-in : Sectors
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 smp-screen : sampler2D
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 @@ fn generate-quad (v00 v01 v10 v11)
# 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 lod-skirt? (p sector-flags)
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 @@ fn visualize-buffer (uv)
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 @@ inline main ()
#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 @@ inline main ()
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 @@ inline main ()
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 @@ inline main ()
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