Forráskód Böngészése

Made submitting several batches work properly and updated bunnymark port

Karl Zylinski 6 hónapja
szülő
commit
0c484c1817
3 módosított fájl, 74 hozzáadás és 48 törlés
  1. 31 5
      examples/raylib_ports/bunnymark/bunnymark.odin
  2. 41 31
      karl2d.odin
  3. 2 12
      render_backend_d3d11.odin

+ 31 - 5
examples/raylib_ports/bunnymark/bunnymark.odin

@@ -5,12 +5,16 @@ package karl2d_bunnymark
 import k2 "../../.."
 import "core:math/rand"
 import "core:log"
+import "core:fmt"
+import "core:time"
 
 MAX_BUNNIES :: 50000
 
 Bunny :: struct {
 	position: k2.Vec2,
 	speed: k2.Vec2,
+	rot: f32,
+	rot_speed: f32,
 	color: k2.Color,
 }
 
@@ -20,13 +24,18 @@ main :: proc() {
 	SCREEN_WIDTH :: 800
 	SCREEN_HEIGHT :: 450
 
-	k2.init(SCREEN_WIDTH, SCREEN_HEIGHT, "bunnymark (raylib port)")
+	k2.init(SCREEN_WIDTH, SCREEN_HEIGHT, "bunnymark (raylib port)", window_creation_flags = { .Resizable })
 
 	tex_bunny := k2.load_texture_from_file("wabbit_alpha.png")
 
 	bunnies: [dynamic]Bunny
+	prev_time := time.now()
 
 	for !k2.shutdown_wanted() {
+		cur_time := time.now()
+		dt := f32(time.duration_seconds(time.diff(prev_time, cur_time)))
+		prev_time = cur_time
+
 		if k2.mouse_button_is_held(.Left) {
 			for _ in 0..<100 {
 				append(&bunnies, Bunny {
@@ -35,6 +44,7 @@ main :: proc() {
 						rand.float32_range(-250, 250)/60,
 						rand.float32_range(-250, 250)/60,
 					},
+					rot_speed = rand.float32_range(-5, 5),
 					color = {
 						u8(rand.int_max(190) + 50),
 						u8(rand.int_max(160) + 80),
@@ -47,21 +57,37 @@ main :: proc() {
 
 		for &b in bunnies {
 			b.position += b.speed
+			b.rot += b.rot_speed
 
-			if (b.position.x + f32(tex_bunny.width/2) > f32(k2.get_screen_width())) || ((b.position.x + f32(tex_bunny.width/2)) < 0) {
+			if b.position.x > f32(k2.get_screen_width()) || b.position.x < 0 {
 				b.speed.x *= -1
+				b.rot_speed = rand.float32_range(-5, 5)
 			}
 
-			if (b.position.y + f32(tex_bunny.height/2) > f32(k2.get_screen_height())) || ((b.position.y + f32(tex_bunny.height/2)) < 0) {
+			if b.position.y > f32(k2.get_screen_height()) || b.position.y < 0 {
 				b.speed.y *= -1
+				b.rot_speed = rand.float32_range(-5, 5)
 			}
 		}
 
 		k2.process_events()
-		k2.clear(k2.RL_RAYWHITE)
+		k2.clear(k2.RL_WHITE)
+
+		src := k2.Rect {
+			0, 0,
+			f32(tex_bunny.width), f32(tex_bunny.height),
+		}
 
 		for &b in bunnies {
-			k2.draw_texture(tex_bunny, b.position, b.color)
+			dest := src
+			dest.x = b.position.x 
+			dest.y = b.position.y
+			k2.draw_texture_ex(tex_bunny, src, dest, {dest.w/2, dest.h/2}, b.rot, b.color)
+		}
+		
+		if k2.key_went_down(.B) {
+			fmt.println(len(bunnies))
+			fmt.println(1/dt)
 		}
 
 		k2.present()

+ 41 - 31
karl2d.odin

@@ -59,6 +59,7 @@ init :: proc(window_width: int, window_height: int, window_title: string,
 	s.shape_drawing_texture = rb.load_texture(white_rect[:], 16, 16)
 
 	s.default_shader = load_shader(string(DEFAULT_SHADER_SOURCE))
+	s.batch_shader = s.default_shader
 
 	return s
 }
@@ -205,8 +206,9 @@ set_window_flags :: proc(flags: Window_Flags) {
 // - set_camera
 // - set_shader
 // - set_shader_constant
+// - set_scissor_rect
 // - draw_texture_* IF previous draw did not use the same texture (1)
-// - draw_rect_*, draw_circle_* IF previous draw did not use the shapes drawing texture (2)
+// - draw_rect_*, draw_circle_*, draw_line IF previous draw did not use the shapes drawing texture (2)
 // 
 // (1) When drawing textures, the current texture is fed into the active shader. Everything within
 //     the same batch must use the same texture. So drawing with a new texture will draw the current
@@ -217,10 +219,11 @@ set_window_flags :: proc(flags: Window_Flags) {
 //     before drawing a shape will break up the batches. TODO: Add possibility to customize shape
 //     drawing texture so that you can put it into an atlas.
 //
-// TODO: Name of this proc? submit_current_batch, flush_current_batch, draw_current_batch
+// The batch has maximum size of VERTEX_BUFFER_MAX bytes. The shader dictates how big a vertex is
+// so the maximum number of vertices that can be drawn in each batch is
+// VERTEX_BUFFER_MAX / shader.vertex_size
 draw_current_batch :: proc() {
-	shader := s.batch_shader.? or_else s.default_shader
-	rb.draw(shader, s.batch_texture, s.proj_matrix * s.view_matrix, s.batch_scissor, s.vertex_buffer_cpu[:s.vertex_buffer_cpu_used])
+	rb.draw(s.batch_shader, s.batch_texture, s.proj_matrix * s.view_matrix, s.batch_scissor, s.vertex_buffer_cpu[:s.vertex_buffer_cpu_used])
 	s.vertex_buffer_cpu_used = 0
 }
 
@@ -306,7 +309,11 @@ set_gamepad_vibration :: proc(gamepad: Gamepad_Index, left: f32, right: f32) {
 //---------//
 
 draw_rect :: proc(r: Rect, c: Color) {
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 6 > len(s.vertex_buffer_cpu) {
+		draw_current_batch()
+	}
+
+	if s.batch_texture != s.shape_drawing_texture {
 		draw_current_batch()
 	}
 
@@ -325,7 +332,11 @@ draw_rect_vec :: proc(pos: Vec2, size: Vec2, c: Color) {
 }
 
 draw_rect_ex :: proc(r: Rect, origin: Vec2, rot: f32, c: Color) {
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 6 > len(s.vertex_buffer_cpu) {
+		draw_current_batch()
+	}
+
+	if s.batch_texture != s.shape_drawing_texture {
 		draw_current_batch()
 	}
 
@@ -417,7 +428,11 @@ draw_rect_outline :: proc(r: Rect, thickness: f32, color: Color) {
 }
 
 draw_circle :: proc(center: Vec2, radius: f32, color: Color, segments := 16) {
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 3 * segments > len(s.vertex_buffer_cpu) {
+		draw_current_batch()
+	}
+
+	if s.batch_texture != s.shape_drawing_texture {
 		draw_current_batch()
 	}
 
@@ -428,7 +443,6 @@ draw_circle :: proc(center: Vec2, radius: f32, color: Color, segments := 16) {
 		sr := (f32(s)/f32(segments)) * 2*math.PI
 		rot := linalg.matrix2_rotate(sr)
 		p := center + rot * Vec2{radius, 0}
-			
 
 		batch_vertex(prev, {0, 0}, color)
 		batch_vertex(p, {1, 0}, color)
@@ -488,10 +502,16 @@ draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotati
 		return
 	}
 
-	if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.handle {
+	if s.vertex_buffer_cpu_used + s.batch_shader.vertex_size * 6 > len(s.vertex_buffer_cpu) {
 		draw_current_batch()
 	}
 
+	if s.batch_texture != tex.handle {
+		draw_current_batch()
+	}
+	
+	s.batch_texture = tex.handle
+
 	flip_x, flip_y: bool
 	src := src
 	dst := dst
@@ -514,7 +534,6 @@ draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rotati
 		dst.h *= -1
 	}
 
-	s.batch_texture = tex.handle
 	tl, tr, bl, br: Vec2
 
 	// Rotation adapted from Raylib's "DrawTexturePro"
@@ -713,12 +732,18 @@ get_default_shader :: proc() -> Shader {
 }
 
 set_shader :: proc(shader: Maybe(Shader)) {
-	if maybe_handle_equal(shader, s.batch_shader) {
-		return
+	if shd, shd_ok := shader.?; shd_ok {
+		if shd.handle == s.batch_shader.handle {
+			return
+		}
+	} else {
+		if s.batch_shader.handle == s.default_shader.handle {
+			return
+		}
 	}
 
 	draw_current_batch()
-	s.batch_shader = shader
+	s.batch_shader = shader.? or_else s.default_shader
 }
 
 set_shader_constant :: proc(shd: Shader, loc: Shader_Constant_Location, val: any) {
@@ -1038,7 +1063,7 @@ State :: struct {
 
 	shape_drawing_texture: Texture_Handle,
 	batch_camera: Maybe(Camera),
-	batch_shader: Maybe(Shader),
+	batch_shader: Shader,
 	batch_scissor: Maybe(Rect),
 	batch_texture: Texture_Handle,
 
@@ -1226,10 +1251,10 @@ batch_vertex :: proc(v: Vec2, uv: Vec2, color: Color) {
 	v := v
 
 	if s.vertex_buffer_cpu_used == len(s.vertex_buffer_cpu) {
-		panic("Must dispatch here")
+		draw_current_batch()
 	}
 
-	shd := s.batch_shader.? or_else s.default_shader
+	shd := s.batch_shader
 
 	base_offset := s.vertex_buffer_cpu_used
 	pos_offset := shd.default_input_offsets[.Position]
@@ -1274,21 +1299,6 @@ s: ^State
 win: Window_Interface
 rb: Render_Backend_Interface
 
-maybe_handle_equal :: proc(m1: Maybe($T), m2: Maybe(T)) -> bool {
-	if m1 == nil && m2 == nil {
-		return true
-	}
-
-	m1v, m1v_ok := m1.?
-	m2v, m2v_ok := m2.?
-
-	if !m1v_ok || !m2v_ok {
-		return false
-	}
-
-	return m1v.handle == m2v.handle
-}
-
 get_shader_input_default_type :: proc(name: string, type: Shader_Input_Type) -> Shader_Default_Inputs {
 	if name == "POS" && type == .Vec2 {
 		return .Position

+ 2 - 12
render_backend_d3d11.odin

@@ -184,10 +184,6 @@ d3d11_clear :: proc(color: Color) {
 
 d3d11_present :: proc() {
 	ch(s.swapchain->Present(1, {}))
-	if s.odd_frame {
-		s.vertex_buffer_offset = 0
-	}
-	s.odd_frame = !s.odd_frame
 }
 
 d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scissor: Maybe(Rect), vertex_buffer: []u8) {
@@ -214,7 +210,7 @@ d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scisso
 	{
 		gpu_map := slice.from_ptr((^u8)(vb_data.pData), VERTEX_BUFFER_MAX)
 		copy(
-			gpu_map[s.vertex_buffer_offset:s.vertex_buffer_offset+len(vertex_buffer)],
+			gpu_map,
 			vertex_buffer,
 		)
 	}
@@ -223,7 +219,7 @@ d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scisso
 	dc->IASetPrimitiveTopology(.TRIANGLELIST)
 
 	dc->IASetInputLayout(d3d_shd.input_layout)
-	vertex_buffer_offset := u32(s.vertex_buffer_offset)
+	vertex_buffer_offset: u32
 	vertex_buffer_stride := u32(shd.vertex_size)
 	dc->IASetVertexBuffers(0, 1, &s.vertex_buffer_gpu, &vertex_buffer_stride, &vertex_buffer_offset)
 
@@ -293,7 +289,6 @@ d3d11_draw :: proc(shd: Shader, texture: Texture_Handle, view_proj: Mat4, scisso
 	dc->OMSetBlendState(s.blend_state, nil, ~u32(0))
 
 	dc->Draw(u32(len(vertex_buffer)/shd.vertex_size), 0)
-	s.vertex_buffer_offset += len(vertex_buffer)
 	log_messages()
 }
 
@@ -576,16 +571,11 @@ D3D11_State :: struct {
 	blend_state: ^d3d11.IBlendState,
 	sampler_state: ^d3d11.ISamplerState,
 
-	// 0 or 1
-	odd_frame: bool,
-
 	textures: hm.Handle_Map(D3D11_Texture, Texture_Handle, 1024*10),
 	shaders: hm.Handle_Map(D3D11_Shader, Shader_Handle, 1024*10),
 
 	info_queue: ^d3d11.IInfoQueue,
 	vertex_buffer_gpu: ^d3d11.IBuffer,
-
-	vertex_buffer_offset: int,
 }
 
 create_swapchain :: proc(w, h: int) {