Harbor

Changelog b1db35768aa9

add recording backend harness

@sky · 1 month ago · parent 539510020405
1 added 2 modified 0 deleted
compiler/executor.odin modified

Diff hidden because this file has more than 800 lines.

tests/compiler_executor_test.odin +38 -213 modified
4 unchanged lines hidden
5 5 import ir "../render_ir"
6 6 import "core:testing"
7 7
8 - mock_shader_desc: bk.Shader_Module_Desc
9 - mock_planned_begin_pass_count: int
10 - mock_planned_end_pass_count: int
11 - mock_planned_draw_count: int
12 - mock_planned_vertex_count: u32
13 - mock_planned_instance_count: u32
14 - mock_planned_bound_vertex_buffer: bk.Buffer_Handle
15 - mock_planned_bound_index_buffer: bk.Buffer_Handle
16 - mock_planned_bound_pipeline: bk.Pipeline_Handle
17 - mock_planned_bound_descriptor: bk.Descriptor_Handle
18 - mock_planned_push_constant_size: u32
19 - mock_planned_indexed_count: u32
20 - mock_planned_trace: [32]string
21 - mock_planned_trace_count: int
22 -
23 - mock_planned_trace_add :: proc(name: string) {
24 - if mock_planned_trace_count < len(mock_planned_trace) {
25 - mock_planned_trace[mock_planned_trace_count] = name
26 - mock_planned_trace_count += 1
27 - }
28 - }
29 -
30 - mock_create_shader_module :: proc(desc: bk.Shader_Module_Desc) -> (bk.Shader_Handle, bool) {
31 - mock_shader_desc = desc
32 - return bk.Shader_Handle(77), true
33 - }
34 -
35 - mock_destroy_shader :: proc(handle: bk.Shader_Handle) {}
36 -
37 - mock_planned_begin_render_pass :: proc(ctx: bk.Frame_Context, desc: bk.Render_Pass_Begin_Desc) {
38 - mock_planned_begin_pass_count += 1
39 - mock_planned_trace_add("begin_render_pass")
40 - }
41 -
42 - mock_planned_begin_default_pass :: proc(ctx: bk.Frame_Context, clear_color: [4]f32) {
43 - mock_planned_begin_pass_count += 1
44 - mock_planned_trace_add("begin_default_pass")
45 - }
46 -
47 - mock_planned_end_render_pass :: proc(ctx: bk.Frame_Context) {
48 - mock_planned_end_pass_count += 1
49 - mock_planned_trace_add("end_render_pass")
50 - }
51 -
52 - mock_planned_set_viewport :: proc(ctx: bk.Frame_Context, x, y, w, h: f32) {
53 - mock_planned_trace_add("set_viewport")
54 - }
55 -
56 - mock_planned_set_scissor :: proc(ctx: bk.Frame_Context, x, y: i32, w, h: u32) {
57 - mock_planned_trace_add("set_scissor")
58 - }
59 -
60 - mock_planned_get_extent :: proc() -> bk.Extent {
61 - return {width = 640, height = 480}
62 - }
63 -
64 - mock_planned_create_graphics_pipeline :: proc(
65 - desc: bk.Pipeline_Desc,
66 - ) -> (
67 - bk.Pipeline_Handle,
68 - bool,
69 - ) {
70 - return bk.Pipeline_Handle(31), true
71 - }
72 -
73 - mock_planned_destroy_graphics_pipeline :: proc(handle: bk.Pipeline_Handle) {}
74 -
75 - mock_planned_bind_graphics_pipeline :: proc(ctx: bk.Frame_Context, handle: bk.Pipeline_Handle) {
76 - mock_planned_bound_pipeline = handle
77 - mock_planned_trace_add("bind_pipeline")
78 - }
79 -
80 - mock_planned_bind_descriptor_set :: proc(
81 - ctx: bk.Frame_Context,
82 - pipeline: bk.Pipeline_Handle,
83 - set: bk.Descriptor_Handle,
84 - index: u32,
85 - ) {
86 - mock_planned_bound_descriptor = set
87 - mock_planned_trace_add("bind_descriptor")
88 - }
89 -
90 - mock_planned_push_constants :: proc(
91 - ctx: bk.Frame_Context,
92 - pipeline: bk.Pipeline_Handle,
93 - stages: bk.Shader_Stage_Flags,
94 - offset, size: u32,
95 - data: rawptr,
96 - ) {
97 - mock_planned_push_constant_size = size
98 - mock_planned_trace_add("push_constants")
99 - }
100 -
101 - mock_planned_bind_vertex_buffer :: proc(ctx: bk.Frame_Context, handle: bk.Buffer_Handle) {
102 - mock_planned_bound_vertex_buffer = handle
103 - mock_planned_trace_add("bind_vertex_buffer")
104 - }
105 -
106 - mock_planned_bind_index_buffer :: proc(ctx: bk.Frame_Context, handle: bk.Buffer_Handle) {
107 - mock_planned_bound_index_buffer = handle
108 - mock_planned_trace_add("bind_index_buffer")
109 - }
110 -
111 - mock_planned_draw :: proc(
112 - ctx: bk.Frame_Context,
113 - vertex_count, instance_count: u32,
114 - first_vertex: u32,
115 - first_instance: u32,
116 - ) {
117 - mock_planned_draw_count += 1
118 - mock_planned_vertex_count = vertex_count
119 - mock_planned_instance_count = instance_count
120 - mock_planned_trace_add("draw")
121 - }
122 -
123 - mock_planned_draw_indexed :: proc(
124 - ctx: bk.Frame_Context,
125 - index_count, instance_count: u32,
126 - first_index: u32,
127 - vertex_offset: i32,
128 - first_instance: u32,
129 - ) {
130 - mock_planned_draw_count += 1
131 - mock_planned_indexed_count = index_count
132 - mock_planned_instance_count = instance_count
133 - mock_planned_trace_add("draw_indexed")
134 - }
135 -
136 - mock_planned_destroy_buffer :: proc(handle: bk.Buffer_Handle) {}
137 -
138 - mock_planned_destroy_render_pass :: proc(handle: bk.Render_Pass_Handle) {}
139 -
140 - mock_planned_destroy_framebuffer :: proc(handle: bk.Framebuffer_Handle) {}
141 -
142 - mock_planned_backend :: proc() -> bk.Backend {
143 - return {
144 - begin_render_pass = mock_planned_begin_render_pass,
145 - begin_default_pass = mock_planned_begin_default_pass,
146 - end_render_pass = mock_planned_end_render_pass,
147 - set_viewport = mock_planned_set_viewport,
148 - set_scissor = mock_planned_set_scissor,
149 - get_extent = mock_planned_get_extent,
150 - create_graphics_pipeline = mock_planned_create_graphics_pipeline,
151 - destroy_graphics_pipeline = mock_planned_destroy_graphics_pipeline,
152 - bind_graphics_pipeline = mock_planned_bind_graphics_pipeline,
153 - push_constants = mock_planned_push_constants,
154 - bind_descriptor_set = mock_planned_bind_descriptor_set,
155 - bind_vertex_buffer = mock_planned_bind_vertex_buffer,
156 - bind_index_buffer = mock_planned_bind_index_buffer,
157 - draw = mock_planned_draw,
158 - draw_indexed = mock_planned_draw_indexed,
159 - destroy_buffer = mock_planned_destroy_buffer,
160 - destroy_render_pass = mock_planned_destroy_render_pass,
161 - destroy_framebuffer = mock_planned_destroy_framebuffer,
162 - destroy_shader = mock_destroy_shader,
163 - }
164 - }
165 -
166 - reset_planned_mock :: proc() {
167 - mock_planned_begin_pass_count = 0
168 - mock_planned_end_pass_count = 0
169 - mock_planned_draw_count = 0
170 - mock_planned_vertex_count = 0
171 - mock_planned_instance_count = 0
172 - mock_planned_bound_vertex_buffer = bk.NULL_BUFFER
173 - mock_planned_bound_index_buffer = bk.NULL_BUFFER
174 - mock_planned_bound_pipeline = bk.NULL_PIPELINE
175 - mock_planned_bound_descriptor = bk.NULL_DESCRIPTOR
176 - mock_planned_push_constant_size = 0
177 - mock_planned_indexed_count = 0
178 - mock_planned_trace_count = 0
179 - }
180 -
181 8 mock_imported_draw_resolver :: proc(
182 9 user_data: rawptr,
183 10 frame: ^ir.Frame_IR,
286 unchanged lines hidden
470 297 `,
471 298 )
472 299
473 - backend := bk.Backend {
474 - create_shader_module = mock_create_shader_module,
475 - destroy_shader = mock_destroy_shader,
476 - }
300 + rec := recording_backend_init()
301 + defer recording_backend_destroy(&rec)
302 + backend := recording_backend_use(&rec)
477 303 state := compiler.init_execution_state(&backend)
478 304 defer compiler.destroy_execution_state(&state)
479 305
1 unchanged lines hidden
481 307 module, module_ok := compiler.prepared_shader(&state, shader_handle)
482 308 testing.expect(t, module_ok)
483 309 testing.expect_value(t, module, bk.Shader_Handle(77))
484 - testing.expect_value(t, mock_shader_desc.stage, bk.Shader_Stage.Compute)
485 - testing.expect_value(t, mock_shader_desc.format, bk.REQUIRED_SHADER_FORMAT)
486 - testing.expect_value(t, mock_shader_desc.name, "compute.comp")
487 - testing.expect(t, len(mock_shader_desc.data) > 0)
310 + testing.expect_value(t, rec.shader_desc.stage, bk.Shader_Stage.Compute)
311 + testing.expect_value(t, rec.shader_desc.format, bk.REQUIRED_SHADER_FORMAT)
312 + testing.expect_value(t, rec.shader_desc.name, "compute.comp")
313 + testing.expect(t, len(rec.shader_desc.data) > 0)
488 314 }
489 315
490 316 @(test)
491 317 test_compiler_executes_planned_vertex_stream_draw :: proc(t: ^testing.T) {
492 - reset_planned_mock()
318 + rec := recording_backend_init()
319 + defer recording_backend_destroy(&rec)
493 320 frame := ir.init_frame_ir()
494 321 defer ir.destroy_frame_ir(&frame)
495 322
12 unchanged lines hidden
508 335 }
509 336 _ = ir.add_draw_packet(&frame, pass, pipeline, .Vertex_Stream, packet, instance_count = 2)
510 337
511 - backend := mock_planned_backend()
338 + backend := recording_backend_use(&rec)
512 339 state := compiler.init_execution_state(&backend)
513 340 defer compiler.destroy_execution_state_views(&state)
514 341 append(
34 unchanged lines hidden
549 376 )
550 377
551 378 testing.expect(t, compiler.execute_prepared_planned_commands(&state, &frame, {}, {0, 0, 0, 1}))
552 - testing.expect_value(t, mock_planned_begin_pass_count, 1)
553 - testing.expect_value(t, mock_planned_end_pass_count, 1)
554 - testing.expect_value(t, mock_planned_draw_count, 1)
555 - testing.expect_value(t, mock_planned_vertex_count, u32(6))
556 - testing.expect_value(t, mock_planned_instance_count, u32(2))
557 - testing.expect_value(t, mock_planned_bound_vertex_buffer, bk.Buffer_Handle(12))
558 - testing.expect_value(t, mock_planned_bound_pipeline, bk.Pipeline_Handle(31))
379 + testing.expect_value(t, rec.begin_pass_count, 1)
380 + testing.expect_value(t, rec.end_pass_count, 1)
381 + testing.expect_value(t, rec.draw_count, 1)
382 + testing.expect_value(t, rec.vertex_count, u32(6))
383 + testing.expect_value(t, rec.instance_count, u32(2))
384 + testing.expect_value(t, rec.bound_vertex_buffer, bk.Buffer_Handle(12))
385 + testing.expect_value(t, rec.bound_pipeline, bk.Pipeline_Handle(31))
559 386
560 - reset_planned_mock()
387 + recording_backend_reset(&rec)
561 388 imported_frame := ir.init_frame_ir()
562 389 defer ir.destroy_frame_ir(&imported_frame)
563 390
30 unchanged lines hidden
594 421 {0, 0, 0, 1},
595 422 ),
596 423 )
597 - testing.expect_value(t, mock_planned_draw_count, 1)
598 - testing.expect_value(t, mock_planned_indexed_count, u32(36))
599 - testing.expect_value(t, mock_planned_bound_pipeline, bk.Pipeline_Handle(91))
600 - testing.expect_value(t, mock_planned_bound_descriptor, bk.Descriptor_Handle(92))
601 - testing.expect_value(t, mock_planned_bound_vertex_buffer, bk.Buffer_Handle(93))
602 - testing.expect_value(t, mock_planned_bound_index_buffer, bk.Buffer_Handle(94))
603 - testing.expect_value(t, mock_planned_push_constant_size, u32(16))
424 + testing.expect_value(t, rec.draw_count, 1)
425 + testing.expect_value(t, rec.indexed_count, u32(36))
426 + testing.expect_value(t, rec.bound_pipeline, bk.Pipeline_Handle(91))
427 + testing.expect_value(t, rec.bound_descriptor, bk.Descriptor_Handle(92))
428 + testing.expect_value(t, rec.bound_vertex_buffer, bk.Buffer_Handle(93))
429 + testing.expect_value(t, rec.bound_index_buffer, bk.Buffer_Handle(94))
430 + testing.expect_value(t, rec.push_constant_size, u32(16))
604 431
605 - expected := [?]string {
606 - "begin_default_pass",
607 - "set_viewport",
608 - "set_scissor",
609 - "bind_pipeline",
610 - "bind_descriptor",
611 - "push_constants",
612 - "bind_vertex_buffer",
613 - "bind_index_buffer",
614 - "draw_indexed",
615 - "end_render_pass",
616 - }
617 - testing.expect_value(t, mock_planned_trace_count, len(expected))
618 - for event, i in expected {
619 - testing.expect_value(t, mock_planned_trace[i], event)
432 + expected := [?]Recording_Call_Kind {
433 + .Begin_Default_Pass,
434 + .Set_Viewport,
435 + .Set_Scissor,
436 + .Set_Scissor,
437 + .Bind_Pipeline,
438 + .Bind_Descriptor,
439 + .Push_Constants,
440 + .Bind_Vertex_Buffer,
441 + .Bind_Index_Buffer,
442 + .Draw_Indexed,
443 + .End_Render_Pass,
620 444 }
445 + recording_expect_kinds(t, &rec, expected[:])
621 446 }
tests/recording_backend.odin +503 -0 added
1 + package gpu_tests
2 +
3 + import bk "../backend"
4 + import compiler "../compiler"
5 + import "core:mem"
6 + import "core:testing"
7 +
8 + Recording_Call_Kind :: enum {
9 + Begin_Frame,
10 + End_Frame,
11 + Begin_Render_Pass,
12 + Begin_Default_Pass,
13 + End_Render_Pass,
14 + Set_Viewport,
15 + Set_Scissor,
16 + Create_Buffer,
17 + Destroy_Buffer,
18 + Create_Graphics_Pipeline,
19 + Destroy_Graphics_Pipeline,
20 + Bind_Pipeline,
21 + Bind_Descriptor,
22 + Push_Constants,
23 + Bind_Vertex_Buffer,
24 + Bind_Index_Buffer,
25 + Draw,
26 + Draw_Indexed,
27 + Create_Shader,
28 + Destroy_Shader,
29 + }
30 +
31 + Recording_Call :: struct {
32 + kind: Recording_Call_Kind,
33 +
34 + frame_index: u32,
35 +
36 + x_i: i32,
37 + y_i: i32,
38 + width_u: u32,
39 + height_u: u32,
40 + x_f: f32,
41 + y_f: f32,
42 + width_f: f32,
43 + height_f: f32,
44 +
45 + pipeline: bk.Pipeline_Handle,
46 + descriptor: bk.Descriptor_Handle,
47 + descriptor_index: u32,
48 + buffer: bk.Buffer_Handle,
49 +
50 + push_constant_size: u32,
51 + push_constant_bytes: [compiler.IMPORTED_PUSH_CONSTANT_CAP]u8,
52 +
53 + vertex_count: u32,
54 + index_count: u32,
55 + instance_count: u32,
56 + first_vertex: u32,
57 + first_index: u32,
58 + vertex_offset: i32,
59 + first_instance: u32,
60 + }
61 +
62 + Recording_Buffer :: struct {
63 + handle: bk.Buffer_Handle,
64 + data: []u8,
65 + mapped: bool,
66 + }
67 +
68 + Recording_Backend_State :: struct {
69 + calls: [dynamic]Recording_Call,
70 + buffers: [dynamic]Recording_Buffer,
71 +
72 + shader_desc: bk.Shader_Module_Desc,
73 + extent: bk.Extent,
74 +
75 + next_buffer: u64,
76 + next_pipeline: u64,
77 + next_shader: u64,
78 + current_frame_index: u32,
79 + next_frame_index: u32,
80 +
81 + begin_pass_count: int,
82 + end_pass_count: int,
83 + draw_count: int,
84 + vertex_count: u32,
85 + indexed_count: u32,
86 + instance_count: u32,
87 + bound_vertex_buffer: bk.Buffer_Handle,
88 + bound_index_buffer: bk.Buffer_Handle,
89 + bound_pipeline: bk.Pipeline_Handle,
90 + bound_descriptor: bk.Descriptor_Handle,
91 + push_constant_size: u32,
92 + }
93 +
94 + @(thread_local) recording_active: ^Recording_Backend_State
95 +
96 + recording_backend_init :: proc() -> Recording_Backend_State {
97 + return {
98 + calls = make([dynamic]Recording_Call, 0, 128),
99 + buffers = make([dynamic]Recording_Buffer, 0, 16),
100 + extent = {width = 640, height = 480},
101 + next_buffer = 12,
102 + next_pipeline = 31,
103 + next_shader = 77,
104 + }
105 + }
106 +
107 + recording_backend_destroy :: proc(rec: ^Recording_Backend_State) {
108 + if rec == nil {
109 + return
110 + }
111 + for &buffer in rec.buffers {
112 + if buffer.data != nil {
113 + delete(buffer.data)
114 + }
115 + }
116 + delete(rec.calls)
117 + delete(rec.buffers)
118 + rec^ = {}
119 + if recording_active == rec {
120 + recording_active = nil
121 + }
122 + }
123 +
124 + recording_backend_reset :: proc(rec: ^Recording_Backend_State) {
125 + if rec == nil {
126 + return
127 + }
128 + clear(&rec.calls)
129 + rec.begin_pass_count = 0
130 + rec.end_pass_count = 0
131 + rec.draw_count = 0
132 + rec.vertex_count = 0
133 + rec.indexed_count = 0
134 + rec.instance_count = 0
135 + rec.bound_vertex_buffer = bk.NULL_BUFFER
136 + rec.bound_index_buffer = bk.NULL_BUFFER
137 + rec.bound_pipeline = bk.NULL_PIPELINE
138 + rec.bound_descriptor = bk.NULL_DESCRIPTOR
139 + rec.push_constant_size = 0
140 + rec.shader_desc = {}
141 + }
142 +
143 + recording_backend_use :: proc(rec: ^Recording_Backend_State) -> bk.Backend {
144 + recording_active = rec
145 + return {
146 + begin_frame = recording_begin_frame,
147 + end_frame = recording_end_frame,
148 + get_extent = recording_get_extent,
149 + current_frame_index = recording_current_frame_index,
150 +
151 + begin_render_pass = recording_begin_render_pass,
152 + begin_default_pass = recording_begin_default_pass,
153 + end_render_pass = recording_end_render_pass,
154 + set_viewport = recording_set_viewport,
155 + set_scissor = recording_set_scissor,
156 +
157 + create_buffer = recording_create_buffer,
158 + create_buffer_staged = recording_create_buffer_staged,
159 + destroy_buffer = recording_destroy_buffer,
160 + map_buffer = recording_map_buffer,
161 + unmap_buffer = recording_unmap_buffer,
162 + get_buffer_mapped = recording_get_buffer_mapped,
163 +
164 + create_graphics_pipeline = recording_create_graphics_pipeline,
165 + destroy_graphics_pipeline = recording_destroy_graphics_pipeline,
166 + bind_graphics_pipeline = recording_bind_graphics_pipeline,
167 + push_constants = recording_push_constants,
168 + bind_descriptor_set = recording_bind_descriptor_set,
169 + bind_vertex_buffer = recording_bind_vertex_buffer,
170 + bind_index_buffer = recording_bind_index_buffer,
171 + draw = recording_draw,
172 + draw_indexed = recording_draw_indexed,
173 +
174 + create_shader_module = recording_create_shader_module,
175 + destroy_shader = recording_destroy_shader,
176 +
177 + destroy_render_pass = recording_destroy_render_pass,
178 + destroy_framebuffer = recording_destroy_framebuffer,
179 + }
180 + }
181 +
182 + recording_expect_kinds :: proc(
183 + t: ^testing.T,
184 + rec: ^Recording_Backend_State,
185 + expected: []Recording_Call_Kind,
186 + ) {
187 + testing.expect_value(t, len(rec.calls), len(expected))
188 + if len(rec.calls) != len(expected) {
189 + return
190 + }
191 + for kind, i in expected {
192 + testing.expect_value(t, rec.calls[i].kind, kind)
193 + }
194 + }
195 +
196 + recording_record :: proc(call: Recording_Call) {
197 + if recording_active == nil {
198 + return
199 + }
200 + append(&recording_active.calls, call)
201 + }
202 +
203 + recording_begin_frame :: proc(clear_color: [4]f32) -> (bk.Frame_Context, bool) {
204 + _ = clear_color
205 + rec := recording_active
206 + if rec == nil {
207 + return {}, false
208 + }
209 + rec.current_frame_index = rec.next_frame_index
210 + ctx := bk.Frame_Context {frame_index = rec.current_frame_index}
211 + recording_record({kind = .Begin_Frame, frame_index = ctx.frame_index})
212 + return ctx, true
213 + }
214 +
215 + recording_end_frame :: proc(ctx: bk.Frame_Context) -> bool {
216 + rec := recording_active
217 + if rec != nil {
218 + rec.next_frame_index = (ctx.frame_index + 1) % bk.MAX_FRAMES_IN_FLIGHT
219 + }
220 + recording_record({kind = .End_Frame, frame_index = ctx.frame_index})
221 + return false
222 + }
223 +
224 + recording_current_frame_index :: proc() -> u32 {
225 + if recording_active == nil {
226 + return 0
227 + }
228 + return recording_active.current_frame_index
229 + }
230 +
231 + recording_begin_render_pass :: proc(ctx: bk.Frame_Context, desc: bk.Render_Pass_Begin_Desc) {
232 + _ = desc
233 + if recording_active != nil {
234 + recording_active.begin_pass_count += 1
235 + }
236 + recording_record({kind = .Begin_Render_Pass, frame_index = ctx.frame_index})
237 + }
238 +
239 + recording_begin_default_pass :: proc(ctx: bk.Frame_Context, clear_color: [4]f32) {
240 + _ = clear_color
241 + if recording_active != nil {
242 + recording_active.begin_pass_count += 1
243 + }
244 + recording_record({kind = .Begin_Default_Pass, frame_index = ctx.frame_index})
245 + }
246 +
247 + recording_end_render_pass :: proc(ctx: bk.Frame_Context) {
248 + if recording_active != nil {
249 + recording_active.end_pass_count += 1
250 + }
251 + recording_record({kind = .End_Render_Pass, frame_index = ctx.frame_index})
252 + }
253 +
254 + recording_set_viewport :: proc(ctx: bk.Frame_Context, x, y, w, h: f32) {
255 + recording_record({kind = .Set_Viewport, frame_index = ctx.frame_index, x_f = x, y_f = y, width_f = w, height_f = h})
256 + }
257 +
258 + recording_set_scissor :: proc(ctx: bk.Frame_Context, x, y: i32, w, h: u32) {
259 + recording_record({kind = .Set_Scissor, frame_index = ctx.frame_index, x_i = x, y_i = y, width_u = w, height_u = h})
260 + }
261 +
262 + recording_get_extent :: proc() -> bk.Extent {
263 + if recording_active == nil {
264 + return {width = 640, height = 480}
265 + }
266 + return recording_active.extent
267 + }
268 +
269 + recording_find_buffer :: proc(
270 + rec: ^Recording_Backend_State,
271 + handle: bk.Buffer_Handle,
272 + ) -> (^Recording_Buffer, bool) {
273 + if rec == nil {
274 + return nil, false
275 + }
276 + for &buffer in rec.buffers {
277 + if buffer.handle == handle {
278 + return &buffer, true
279 + }
280 + }
281 + return nil, false
282 + }
283 +
284 + recording_create_buffer :: proc(desc: bk.Buffer_Desc) -> (bk.Buffer_Handle, bool) {
285 + rec := recording_active
286 + if rec == nil {
287 + return bk.NULL_BUFFER, false
288 + }
289 + size := int(desc.size)
290 + if size <= 0 {
291 + size = 1
292 + }
293 + handle := bk.Buffer_Handle(rec.next_buffer)
294 + rec.next_buffer += 1
295 + append(&rec.buffers, Recording_Buffer {handle = handle, data = make([]u8, size)})
296 + recording_record({kind = .Create_Buffer, buffer = handle})
297 + return handle, true
298 + }
299 +
300 + recording_create_buffer_staged :: proc(
301 + data: rawptr,
302 + size: int,
303 + usage: bk.Buffer_Usage_Flags,
304 + ) -> (
305 + bk.Buffer_Handle,
306 + bool,
307 + ) {
308 + _ = usage
309 + handle, ok := recording_create_buffer({size = u64(size)})
310 + if ok && data != nil {
311 + if buffer, buffer_ok := recording_find_buffer(recording_active, handle); buffer_ok {
312 + mem.copy(raw_data(buffer.data), data, size)
313 + }
314 + }
315 + return handle, ok
316 + }
317 +
318 + recording_destroy_buffer :: proc(handle: bk.Buffer_Handle) {
319 + rec := recording_active
320 + if rec != nil {
321 + for &buffer, i in rec.buffers {
322 + if buffer.handle == handle {
323 + if buffer.data != nil {
324 + delete(buffer.data)
325 + }
326 + unordered_remove(&rec.buffers, i)
327 + break
328 + }
329 + }
330 + }
331 + recording_record({kind = .Destroy_Buffer, buffer = handle})
332 + }
333 +
334 + recording_map_buffer :: proc(handle: bk.Buffer_Handle) -> rawptr {
335 + buffer, ok := recording_find_buffer(recording_active, handle)
336 + if !ok {
337 + return nil
338 + }
339 + buffer.mapped = true
340 + return raw_data(buffer.data)
341 + }
342 +
343 + recording_unmap_buffer :: proc(handle: bk.Buffer_Handle) {
344 + if buffer, ok := recording_find_buffer(recording_active, handle); ok {
345 + buffer.mapped = false
346 + }
347 + }
348 +
349 + recording_get_buffer_mapped :: proc(handle: bk.Buffer_Handle) -> rawptr {
350 + buffer, ok := recording_find_buffer(recording_active, handle)
351 + if !ok || !buffer.mapped {
352 + return nil
353 + }
354 + return raw_data(buffer.data)
355 + }
356 +
357 + recording_create_graphics_pipeline :: proc(desc: bk.Pipeline_Desc) -> (bk.Pipeline_Handle, bool) {
358 + _ = desc
359 + rec := recording_active
360 + if rec == nil {
361 + return bk.NULL_PIPELINE, false
362 + }
363 + handle := bk.Pipeline_Handle(rec.next_pipeline)
364 + rec.next_pipeline += 1
365 + recording_record({kind = .Create_Graphics_Pipeline, pipeline = handle})
366 + return handle, true
367 + }
368 +
369 + recording_destroy_graphics_pipeline :: proc(handle: bk.Pipeline_Handle) {
370 + recording_record({kind = .Destroy_Graphics_Pipeline, pipeline = handle})
371 + }
372 +
373 + recording_bind_graphics_pipeline :: proc(ctx: bk.Frame_Context, handle: bk.Pipeline_Handle) {
374 + if recording_active != nil {
375 + recording_active.bound_pipeline = handle
376 + }
377 + recording_record({kind = .Bind_Pipeline, frame_index = ctx.frame_index, pipeline = handle})
378 + }
379 +
380 + recording_bind_descriptor_set :: proc(
381 + ctx: bk.Frame_Context,
382 + pipeline: bk.Pipeline_Handle,
383 + set: bk.Descriptor_Handle,
384 + index: u32,
385 + ) {
386 + if recording_active != nil {
387 + recording_active.bound_descriptor = set
388 + }
389 + recording_record({
390 + kind = .Bind_Descriptor,
391 + frame_index = ctx.frame_index,
392 + pipeline = pipeline,
393 + descriptor = set,
394 + descriptor_index = index,
395 + })
396 + }
397 +
398 + recording_push_constants :: proc(
399 + ctx: bk.Frame_Context,
400 + pipeline: bk.Pipeline_Handle,
401 + stages: bk.Shader_Stage_Flags,
402 + offset, size: u32,
403 + data: rawptr,
404 + ) {
405 + _ = stages
406 + _ = offset
407 + call := Recording_Call {
408 + kind = .Push_Constants,
409 + frame_index = ctx.frame_index,
410 + pipeline = pipeline,
411 + push_constant_size = size,
412 + }
413 + if data != nil && size <= compiler.IMPORTED_PUSH_CONSTANT_CAP {
414 + mem.copy(&call.push_constant_bytes[0], data, int(size))
415 + }
416 + if recording_active != nil {
417 + recording_active.push_constant_size = size
418 + }
419 + recording_record(call)
420 + }
421 +
422 + recording_bind_vertex_buffer :: proc(ctx: bk.Frame_Context, handle: bk.Buffer_Handle) {
423 + if recording_active != nil {
424 + recording_active.bound_vertex_buffer = handle
425 + }
426 + recording_record({kind = .Bind_Vertex_Buffer, frame_index = ctx.frame_index, buffer = handle})
427 + }
428 +
429 + recording_bind_index_buffer :: proc(ctx: bk.Frame_Context, handle: bk.Buffer_Handle) {
430 + if recording_active != nil {
431 + recording_active.bound_index_buffer = handle
432 + }
433 + recording_record({kind = .Bind_Index_Buffer, frame_index = ctx.frame_index, buffer = handle})
434 + }
435 +
436 + recording_draw :: proc(
437 + ctx: bk.Frame_Context,
438 + vertex_count, instance_count: u32,
439 + first_vertex: u32,
440 + first_instance: u32,
441 + ) {
442 + if recording_active != nil {
443 + recording_active.draw_count += 1
444 + recording_active.vertex_count = vertex_count
445 + recording_active.instance_count = instance_count
446 + }
447 + recording_record({
448 + kind = .Draw,
449 + frame_index = ctx.frame_index,
450 + vertex_count = vertex_count,
451 + instance_count = instance_count,
452 + first_vertex = first_vertex,
453 + first_instance = first_instance,
454 + })
455 + }
456 +
457 + recording_draw_indexed :: proc(
458 + ctx: bk.Frame_Context,
459 + index_count, instance_count: u32,
460 + first_index: u32,
461 + vertex_offset: i32,
462 + first_instance: u32,
463 + ) {
464 + if recording_active != nil {
465 + recording_active.draw_count += 1
466 + recording_active.indexed_count = index_count
467 + recording_active.instance_count = instance_count
468 + }
469 + recording_record({
470 + kind = .Draw_Indexed,
471 + frame_index = ctx.frame_index,
472 + index_count = index_count,
473 + instance_count = instance_count,
474 + first_index = first_index,
475 + vertex_offset = vertex_offset,
476 + first_instance = first_instance,
477 + })
478 + }
479 +
480 + recording_create_shader_module :: proc(desc: bk.Shader_Module_Desc) -> (bk.Shader_Handle, bool) {
481 + rec := recording_active
482 + if rec == nil {
483 + return bk.NULL_SHADER, false
484 + }
485 + rec.shader_desc = desc
486 + handle := bk.Shader_Handle(rec.next_shader)
487 + rec.next_shader += 1
488 + recording_record({kind = .Create_Shader})
489 + return handle, true
490 + }
491 +
492 + recording_destroy_shader :: proc(handle: bk.Shader_Handle) {
493 + _ = handle
494 + recording_record({kind = .Destroy_Shader})
495 + }
496 +
497 + recording_destroy_render_pass :: proc(handle: bk.Render_Pass_Handle) {
498 + _ = handle
499 + }
500 +
501 + recording_destroy_framebuffer :: proc(handle: bk.Framebuffer_Handle) {
502 + _ = handle
503 + }