package render_ir import "core:fmt" import "core:mem" import "core:strings" @(private) trace_begin_pass :: proc(buf: ^strings.Builder, wrote_line: ^bool, ir: ^Frame_IR, pass_handle: Pass_Handle) { pass, ok := get_pass(ir, pass_handle) if !ok { dump_write_line( buf, wrote_line, fmt.aprintf("begin_pass invalid handle=%d", pass_handle, allocator = context.temp_allocator), ) return } dump_write_line( buf, wrote_line, fmt.aprintf( "begin_pass #%d %s name=\"%s\"", pass_handle, format_pass_kind(pass.kind), pass.name, allocator = context.temp_allocator, ), ) } @(private) trace_end_pass :: proc(buf: ^strings.Builder, wrote_line: ^bool, pass_handle: Pass_Handle) { if pass_handle == INVALID_PASS { return } dump_write_line( buf, wrote_line, fmt.aprintf("end_pass #%d", pass_handle, allocator = context.temp_allocator), ) } @(private) trace_bind_pipeline :: proc(buf: ^strings.Builder, wrote_line: ^bool, ir: ^Frame_IR, pipeline_handle: Pipeline_Handle) { pipeline, ok := get_pipeline(ir, pipeline_handle) if !ok { dump_write_line( buf, wrote_line, fmt.aprintf("bind_pipeline invalid handle=%d", pipeline_handle, allocator = context.temp_allocator), ) return } dump_write_line( buf, wrote_line, fmt.aprintf( "bind_pipeline #%d %s name=\"%s\"", pipeline_handle, format_pipeline_kind(pipeline.kind), pipeline.name, allocator = context.temp_allocator, ), ) } @(private) trace_enter_pass :: proc( buf: ^strings.Builder, wrote_line: ^bool, ir: ^Frame_IR, current_pass: ^Pass_Handle, current_pipeline: ^Pipeline_Handle, next_pass: Pass_Handle, ) { if next_pass == INVALID_PASS { dump_write_line(buf, wrote_line, "begin_pass invalid handle=0") current_pass^ = INVALID_PASS current_pipeline^ = INVALID_PIPELINE return } if current_pass^ == next_pass { return } trace_end_pass(buf, wrote_line, current_pass^) trace_begin_pass(buf, wrote_line, ir, next_pass) current_pass^ = next_pass current_pipeline^ = INVALID_PIPELINE } @(private) trace_ensure_pipeline :: proc( buf: ^strings.Builder, wrote_line: ^bool, ir: ^Frame_IR, current_pipeline: ^Pipeline_Handle, next_pipeline: Pipeline_Handle, ) { if next_pipeline == INVALID_PIPELINE { dump_write_line(buf, wrote_line, "bind_pipeline invalid handle=0") current_pipeline^ = INVALID_PIPELINE return } if current_pipeline^ == next_pipeline { return } trace_bind_pipeline(buf, wrote_line, ir, next_pipeline) current_pipeline^ = next_pipeline } trace_frame_ir :: proc(ir: ^Frame_IR, allocator: mem.Allocator = context.allocator) -> string { buf := strings.builder_make(allocator) wrote_line := false current_pass := INVALID_PASS current_pipeline := INVALID_PIPELINE dump_write_line(&buf, &wrote_line, "Trace") for _, i in ir.commands { handle := Command_Handle(i + 1) record, record_ok := get_command_record(ir, handle) if !record_ok { dump_write_line( &buf, &wrote_line, fmt.aprintf("cmd #%d invalid_record", i + 1, allocator = context.temp_allocator), ) continue } switch record.kind { case .Draw: draw, draw_ok := get_draw(ir, handle) if !draw_ok { dump_write_line( &buf, &wrote_line, fmt.aprintf("cmd #%d invalid_draw", i + 1, allocator = context.temp_allocator), ) continue } trace_enter_pass(&buf, &wrote_line, ir, ¤t_pass, ¤t_pipeline, draw.pass) trace_ensure_pipeline(&buf, &wrote_line, ir, ¤t_pipeline, draw.pipeline) if draw_kind_is_packet(draw.kind) { packet := draw.packet dump_write_line( &buf, &wrote_line, fmt.aprintf( "draw_packet kind=%s target=%d layer=%d order=%s sort_key=%d sequence=%d geometry=%s/%d vertices=%d instances=%d", format_draw_kind(draw.kind), packet.target, packet.layer, format_order_mode(packet.order), packet.sort_key, packet.sequence, format_geometry_kind(packet.geometry.kind), packet.geometry.resource, packet.geometry.vertex_count, packet.instances.count, allocator = context.temp_allocator, ), ) continue } dump_write_line( &buf, &wrote_line, fmt.aprintf( "draw vertex_count=%d instance_count=%d", draw.vertex_count, draw.instance_count, allocator = context.temp_allocator, ), ) case .Dispatch: dispatch, dispatch_ok := get_dispatch(ir, handle) if !dispatch_ok { dump_write_line( &buf, &wrote_line, fmt.aprintf("cmd #%d invalid_dispatch", i + 1, allocator = context.temp_allocator), ) continue } trace_enter_pass(&buf, &wrote_line, ir, ¤t_pass, ¤t_pipeline, dispatch.pass) trace_ensure_pipeline(&buf, &wrote_line, ir, ¤t_pipeline, dispatch.pipeline) dump_write_line( &buf, &wrote_line, fmt.aprintf( "dispatch groups=%d,%d,%d shader_id=%d buffers=%s push_constants_size=%d barrier_after=%v", dispatch.groups[0], dispatch.groups[1], dispatch.groups[2], dispatch.shader_id, format_dispatch_buffers(dispatch^), u32(len(dispatch.push_constants)), dispatch.barrier_after, allocator = context.temp_allocator, ), ) } } trace_end_pass(&buf, &wrote_line, current_pass) return strings.to_string(buf) }