Kaynağa Gözat

More backend migration work

Karl Zylinski 6 ay önce
ebeveyn
işleme
950a2d67a5
2 değiştirilmiş dosya ile 174 ekleme ve 129 silme
  1. 62 49
      backend_d3d11.odin
  2. 112 80
      karl2d.odin

+ 62 - 49
backend_d3d11.odin

@@ -23,12 +23,19 @@ _ :: bmp
 _ :: png
 _ :: tga
 
-make_backend_d3d11 :: proc() -> Rendering_Backend {
-	return {
-		state_size = d3d11_state_size,
-		init = d3d11_init,
-		set_internal_state = d3d11_set_internal_state,
-	}
+BACKEND_D3D11 :: Rendering_Backend {
+	state_size = d3d11_state_size,
+	init = d3d11_init,
+	shutdown = d3d11_shutdown,
+	clear = d3d11_clear,
+	present = d3d11_present,
+	draw_current_batch = d3d11_draw_current_batch,
+	
+	get_swapchain_width = d3d11_get_swapchain_width,
+	get_swapchain_height = d3d11_get_swapchain_height,
+
+
+	set_internal_state = d3d11_set_internal_state,
 }
 
 @(private="file")
@@ -171,10 +178,50 @@ d3d11_init :: proc(state: rawptr, window_handle: uintptr, swapchain_width, swapc
 	s.shape_drawing_texture = _load_texture_from_memory(white_rect[:], 16, 16)
 }
 
+d3d11_shutdown :: proc() {
+	_destroy_texture(s.shape_drawing_texture)
+	_destroy_shader(s.default_shader)
+	s.sampler_state->Release()
+	s.framebuffer_view->Release()
+	s.depth_buffer_view->Release()
+	s.depth_buffer->Release()
+	s.framebuffer->Release()
+	s.device_context->Release()
+	s.vertex_buffer_gpu->Release()
+	//s.constant_buffer->Release()
+	s.depth_stencil_state->Release()
+	s.rasterizer_state->Release()
+	s.swapchain->Release()
+	s.blend_state->Release()
+	delete(s.vertex_buffer_cpu, s.allocator)
+
+	when ODIN_DEBUG {
+		debug: ^d3d11.IDebug
+
+		if ch(s.device->QueryInterface(d3d11.IDebug_UUID, (^rawptr)(&debug))) >= 0 {
+			ch(debug->ReportLiveDeviceObjects({.DETAIL, .IGNORE_INTERNAL}))
+			log_messages()
+		}
+
+		debug->Release()
+	}
+
+	s.device->Release()
+	s.info_queue->Release()
+}
+
 d3d11_set_internal_state :: proc(state: rawptr) {
 	s = (^D3D11_State)(state)
 }
 
+d3d11_get_swapchain_width :: proc() -> int {
+	return s.width
+}
+
+d3d11_get_swapchain_height :: proc() -> int {
+	return s.height
+}
+
 shader_hlsl :: #load("shader.hlsl")
 
 VERTEX_BUFFER_MAX :: 1000000
@@ -266,41 +313,7 @@ D3D11_State :: struct {
 }
 
 
-_shutdown :: proc() {
-	_destroy_texture(s.shape_drawing_texture)
-	_destroy_shader(s.default_shader)
-	s.sampler_state->Release()
-	s.framebuffer_view->Release()
-	s.depth_buffer_view->Release()
-	s.depth_buffer->Release()
-	s.framebuffer->Release()
-	s.device_context->Release()
-	s.vertex_buffer_gpu->Release()
-	//s.constant_buffer->Release()
-	s.depth_stencil_state->Release()
-	s.rasterizer_state->Release()
-	s.swapchain->Release()
-	s.blend_state->Release()
-	delete(s.vertex_buffer_cpu, s.allocator)
-
-	when ODIN_DEBUG {
-		debug: ^d3d11.IDebug
 
-		if ch(s.device->QueryInterface(d3d11.IDebug_UUID, (^rawptr)(&debug))) >= 0 {
-			ch(debug->ReportLiveDeviceObjects({.DETAIL, .IGNORE_INTERNAL}))
-			log_messages()
-		}
-
-		debug->Release()
-	}
-
-	s.device->Release()
-	s.info_queue->Release()
-
-	a := s.allocator
-	free(s, a)
-	s = nil
-}
 
 Color_F32 :: [4]f32
 
@@ -313,7 +326,7 @@ f32_color_from_color :: proc(color: Color) -> Color_F32 {
 	}
 }
 
-_clear :: proc(color: Color) {
+d3d11_clear :: proc(color: Color) {
 	c := f32_color_from_color(color)
 	s.device_context->ClearRenderTargetView(s.framebuffer_view, &c)
 	s.device_context->ClearDepthStencilView(s.depth_buffer_view, {.DEPTH}, 1, 0)
@@ -486,7 +499,7 @@ _draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rot:
 	}
 
 	if s.batch_texture != TEXTURE_NONE && s.batch_texture != tex.id {
-		_draw_current_batch()
+		d3d11_draw_current_batch()
 	}
 
 	r := dst
@@ -548,7 +561,7 @@ _draw_texture_ex :: proc(tex: Texture, src: Rect, dst: Rect, origin: Vec2, rot:
 
 _draw_rectangle :: proc(r: Rect, c: Color) {
 	if s.batch_texture != TEXTURE_NONE && s.batch_texture != s.shape_drawing_texture.id {
-		_draw_current_batch()
+		d3d11_draw_current_batch()
 	}
 
 	s.batch_texture = s.shape_drawing_texture.id
@@ -660,7 +673,7 @@ _set_camera :: proc(camera: Maybe(Camera)) {
 		return
 	}
 
-	_draw_current_batch()
+	d3d11_draw_current_batch()
 	s.batch_camera = camera
 
 	if c, c_ok := camera.?; c_ok {
@@ -688,12 +701,12 @@ _set_shader :: proc(shader: Shader_Handle) {
 		return
 	}
 
-	_draw_current_batch()
+	d3d11_draw_current_batch()
 	s.batch_shader = shader
 }
 
 _set_shader_constant :: proc(shader: Shader_Handle, loc: Shader_Constant_Location, val: $T) {
-	_draw_current_batch()
+	d3d11_draw_current_batch()
 
 	shd := hm.get(&s.shaders, shader)
 
@@ -730,7 +743,7 @@ _set_shader_constant_vec2 :: proc(shader: Shader_Handle, loc: Shader_Constant_Lo
 }
 
 
-_draw_current_batch :: proc() {
+d3d11_draw_current_batch :: proc() {
 	if s.vertex_buffer_cpu_used == s.vertex_buffer_offset {
 		return
 	}
@@ -821,8 +834,8 @@ make_default_projection :: proc(w, h: int) -> matrix[4,4]f32 {
 	return linalg.matrix_ortho3d_f32(0, f32(w), f32(h), 0, 0.001, 2)
 }
 
-_present :: proc() {
-	_draw_current_batch()
+d3d11_present :: proc() {
+	d3d11_draw_current_batch()
 	ch(s.swapchain->Present(1, {}))
 	s.vertex_buffer_offset = 0
 	s.vertex_buffer_cpu_used = 0

+ 112 - 80
karl2d.odin

@@ -5,64 +5,6 @@ import "base:runtime"
 import "core:mem"
 import "core:log"
 
-Rendering_Backend :: struct {
-	state_size: proc() -> int,
-	init: proc(state: rawptr, window_handle: uintptr, swapchain_width, swapchain_height: int,
-		allocator := context.allocator, loc := #caller_location),
-	set_internal_state: proc(state: rawptr),
-}
-
-State :: struct {
-	allocator: runtime.Allocator,
-	custom_context: runtime.Context,
-	rb: Rendering_Backend,
-	rb_state: rawptr,
-	
-
-	keys_went_down: #sparse [Keyboard_Key]bool,
-	keys_went_up: #sparse [Keyboard_Key]bool,
-	keys_is_held: #sparse [Keyboard_Key]bool,
-
-	window: win32.HWND,
-	width: int,
-	height: int,
-
-	run: bool,
-}
-
-VK_MAP := [255]Keyboard_Key {
-	win32.VK_A = .A,
-	win32.VK_B = .B,
-	win32.VK_C = .C,
-	win32.VK_D = .D,
-	win32.VK_E = .E,
-	win32.VK_F = .F,
-	win32.VK_G = .G,
-	win32.VK_H = .H,
-	win32.VK_I = .I,
-	win32.VK_J = .J,
-	win32.VK_K = .K,
-	win32.VK_L = .L,
-	win32.VK_M = .M,
-	win32.VK_N = .N,
-	win32.VK_O = .O,
-	win32.VK_P = .P,
-	win32.VK_Q = .Q,
-	win32.VK_R = .R,
-	win32.VK_S = .S,
-	win32.VK_T = .T,
-	win32.VK_U = .U,
-	win32.VK_V = .V,
-	win32.VK_W = .W,
-	win32.VK_X = .X,
-	win32.VK_Y = .Y,
-	win32.VK_Z = .Z,
-	win32.VK_LEFT = .Left,
-	win32.VK_RIGHT = .Right,
-	win32.VK_UP = .Up,
-	win32.VK_DOWN = .Down,
-}
-
 // Opens a window and initializes some internal state. The internal state will use `allocator` for
 // all dynamically allocated memory. The return value can be ignored unless you need to later call
 // `set_state`.
@@ -130,7 +72,7 @@ init :: proc(window_width: int, window_height: int, window_title: string,
 
 	assert(hwnd != nil, "Failed creating window")
 
-	s.rb = make_backend_d3d11()
+	s.rb = BACKEND_D3D11
 	rb_alloc_error: runtime.Allocator_Error
 	s.rb_state, rb_alloc_error = mem.alloc(s.rb.state_size())
 	log.assertf(rb_alloc_error == nil, "Failed allocating memory for rendering backend: %v", rb_alloc_error)
@@ -138,6 +80,28 @@ init :: proc(window_width: int, window_height: int, window_title: string,
 	return s
 }
 
+// Closes the window and cleans up the internal state.
+shutdown :: proc() {
+	s.rb.shutdown()
+
+	win32.DestroyWindow(s.window)
+
+	a := s.allocator
+	free(s.rb_state, a)
+	free(s, a)
+	s = nil
+}
+
+// Clear the backbuffer with supplied color.
+clear :: proc(color: Color) {
+	s.rb.clear(color)
+}
+
+// Present the backbuffer. Call at end of frame to make everything you've drawn appear on the screen.
+present :: proc() {
+	s.rb.present()
+}
+
 // Call at start or end of frame to process all events that have arrived to the window.
 //
 // WARNING: Not calling this will make your program impossible to interact with.
@@ -153,12 +117,33 @@ process_events :: proc() {
 	}
 }
 
+/* Flushes the current batch. This sends off everything to the GPU that has been queued in the
+current batch. Normally, you do not need to do this manually. It is done automatically when these
+procedures run:
+	present
+	set_camera
+	set_shader
+
+TODO: complete this list and motivate why it needs to happen on those procs (or do that in the
+docs for those procs).
+*/   
+draw_current_batch :: proc() {
+	s.rb.draw_current_batch()
+}
+
+// Can be used to restore the internal state using the pointer returned by `init`. Useful after
+// reloading the library (for example, when doing code hot reload).
+set_internal_state :: proc(state: ^State) {
+	s = state
+	s.rb.set_internal_state(s.rb_state)
+}
+
 get_screen_width :: proc() -> int {
-	return s.width
+	return s.rb.get_swapchain_width()
 }
 
 get_screen_height :: proc() -> int  {
-	return s.height
+	return s.rb.get_swapchain_height()
 }
 
 key_went_down :: proc(key: Keyboard_Key) -> bool {
@@ -173,6 +158,7 @@ key_is_held :: proc(key: Keyboard_Key) -> bool {
 	return s.keys_is_held[key]
 }
 
+// Returns true if the user has tried to close the window.
 window_should_close :: proc() -> bool {
 	return !s.run
 }
@@ -191,34 +177,80 @@ set_window_position :: proc(x: int, y: int) {
 	)
 }
 
+Rendering_Backend :: struct {
+	state_size: proc() -> int,
+	init: proc(state: rawptr, window_handle: uintptr, swapchain_width, swapchain_height: int,
+		allocator := context.allocator, loc := #caller_location),
+	shutdown: proc(),
+	clear: proc(color: Color),
+	present: proc(),
+	draw_current_batch: proc(),
+	set_internal_state: proc(state: rawptr),
 
-@(private="file")
-s: ^State
+	get_swapchain_width: proc() -> int,
+	get_swapchain_height: proc() -> int,
 
-// Closes the window and cleans up the internal state.
-shutdown: proc() : _shutdown
+}
 
-// Clear the backbuffer with supplied color.
-clear: proc(color: Color) : _clear
+State :: struct {
+	allocator: runtime.Allocator,
+	custom_context: runtime.Context,
+	rb: Rendering_Backend,
+	rb_state: rawptr,
+	
+	keys_went_down: #sparse [Keyboard_Key]bool,
+	keys_went_up: #sparse [Keyboard_Key]bool,
+	keys_is_held: #sparse [Keyboard_Key]bool,
 
+	window: win32.HWND,
+	width: int,
+	height: int,
 
-// Present the backbuffer. Call at end of frame to make everything you've drawn appear on the screen.
-present: proc() : _present
+	run: bool,
+}
+
+VK_MAP := [255]Keyboard_Key {
+	win32.VK_A = .A,
+	win32.VK_B = .B,
+	win32.VK_C = .C,
+	win32.VK_D = .D,
+	win32.VK_E = .E,
+	win32.VK_F = .F,
+	win32.VK_G = .G,
+	win32.VK_H = .H,
+	win32.VK_I = .I,
+	win32.VK_J = .J,
+	win32.VK_K = .K,
+	win32.VK_L = .L,
+	win32.VK_M = .M,
+	win32.VK_N = .N,
+	win32.VK_O = .O,
+	win32.VK_P = .P,
+	win32.VK_Q = .Q,
+	win32.VK_R = .R,
+	win32.VK_S = .S,
+	win32.VK_T = .T,
+	win32.VK_U = .U,
+	win32.VK_V = .V,
+	win32.VK_W = .W,
+	win32.VK_X = .X,
+	win32.VK_Y = .Y,
+	win32.VK_Z = .Z,
+	win32.VK_LEFT = .Left,
+	win32.VK_RIGHT = .Right,
+	win32.VK_UP = .Up,
+	win32.VK_DOWN = .Down,
+}
+
+@(private="file")
+s: ^State
+
+// --------------------------------
+// old, non migrated API below
 
-// Flushes the current batch. This sends off everything to the GPU that has been queued in the
-// current batch. Done automatically by `present` (possible to disable). Also done by `set_camera`
-// and `set_scissor_rect` since the batch depends on those options.
-draw_current_batch: proc() : _draw_current_batch
 
-// Returns true if the user has tried to close the window.
 
 
-// Can be used to restore the internal state using the pointer returned by `init`. Useful after
-// reloading the library (for example, when doing code hot reload).
-set_internal_state :: proc(state: ^State) {
-	s = state
-	s.rb.set_internal_state(s.rb_state)
-}
 
 set_window_size: proc(width: int, height: int) : _set_window_size