From 4fe18195d10e10e21084043d6ed0766f4062cc72 Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 10 Dec 2025 21:19:23 -0600 Subject: [PATCH] begin reworking format utils to take argument arrays instead of only va_list --- src/base/base_string.c | 108 ++++++++++++++------ src/base/base_string.h | 27 ++++- src/gpu/gpu_core.h | 10 +- src/gpu/gpu_dx12/gpu_dx12_core.c | 166 ++++++++++++++++--------------- src/gpu/gpu_shader_core.cgh | 12 ++- 5 files changed, 200 insertions(+), 123 deletions(-) diff --git a/src/base/base_string.c b/src/base/base_string.c index 6015420b..e15f15dd 100644 --- a/src/base/base_string.c +++ b/src/base/base_string.c @@ -531,13 +531,14 @@ String TrimWhitespace(String s) * * FmtEnd (internal): Denote the end of the va_list */ -String FormatStringV(Arena *arena, String fmt, va_list args) +String FormatString(Arena *arena, String fmt, FmtArgArray args) { - u64 final_len = 0; - u8 *final_text = ArenaNext(arena, u8); + String result = ZI; + result.text = ArenaNext(arena, u8); u8 *end = fmt.text + fmt.len; b32 no_more_args = 0; + u64 arg_idx = 0; for (u8 *c = fmt.text; c < end; ++c) { u8 *next = ((c + 1) < end) ? (c + 1) : (u8 *)"\0"; @@ -546,80 +547,92 @@ String FormatStringV(Arena *arena, String fmt, va_list args) b32 escape = !no_more_args && *c == '%' && *next == '%'; if (escape) { - /* Skip the escape '%' char from parsing */ + /* Skip the escaped '%' char from parsing */ ++c; } if (!no_more_args && !escape && *c == '%' && *next == 'F') { - String parsed_str = ZI; - /* Detect arg type and parse to string */ - FmtArg arg = va_arg(args, FmtArg); + String parsed_arg = ZI; + + FmtArg arg = ZI; + if (arg_idx < args.count) + { + arg = args.args[arg_idx]; + ++arg_idx; + } + else + { + no_more_args = 1; + } + switch (arg.kind) { default: { /* Unknown format type */ Assert(0); - parsed_str = PushString(arena, Lit("")); + parsed_arg = PushString(arena, Lit("")); no_more_args = 1; } break; case FmtArgKind_Char: { - parsed_str = StringFromChar(arena, arg.value.c); + parsed_arg = StringFromChar(arena, arg.value.c); } break; case FmtArgKind_String: { - parsed_str = PushString(arena, arg.value.string); + parsed_arg = PushString(arena, arg.value.string); } break; case FmtArgKind_Uint: { - parsed_str = StringFromU64(arena, arg.value.uint, 10, arg.z); + parsed_arg = StringFromU64(arena, arg.value.uint, 10, arg.z); } break; case FmtArgKind_Sint: { - parsed_str = StringFromI64(arena, arg.value.sint, 10, arg.z); + parsed_arg = StringFromI64(arena, arg.value.sint, 10, arg.z); } break; case FmtArgKind_Hex: { - parsed_str = StringFromU64(arena, arg.value.sint, 16, arg.z); + parsed_arg = StringFromU64(arena, arg.value.sint, 16, arg.z); } break; case FmtArgKind_Ptr: { - parsed_str = StringFromPtr(arena, arg.value.ptr); + parsed_arg = StringFromPtr(arena, arg.value.ptr); } break; case FmtArgKind_Float: { - parsed_str = StringFromF64(arena, arg.value.f, arg.p); + parsed_arg = StringFromF64(arena, arg.value.f, arg.p); } break; case FmtArgKind_Handle: { - parsed_str = StringFromhandle(arena, arg.value.handle.h64[0], arg.value.handle.h64[1]); + parsed_arg = StringFromhandle(arena, arg.value.handle.h64[0], arg.value.handle.h64[1]); } break; case FmtArgKind_Uid: { - parsed_str = StringFromUid(arena, arg.value.uid); + parsed_arg = StringFromUid(arena, arg.value.uid); } break; case FmtArgKind_End: { /* Unexpected end. Not enough FMT args passed to function. */ Assert(0); - parsed_str = PushString(arena, Lit("")); + parsed_arg = PushString(arena, Lit("")); no_more_args = 1; } break; } + /* Update final string len / start */ - final_len += parsed_str.len; + final_len += parsed_arg.len; + /* Skip 'F' from parsing */ ++c; } @@ -634,26 +647,63 @@ String FormatStringV(Arena *arena, String fmt, va_list args) #if IsRtcEnabled if (!no_more_args) { - FmtArg last_arg = va_arg(args, FmtArg); - /* End arg not reached. Too many FMT values passed to function. */ + FmtArg last_arg = ZI; + if (arg_idx < args.count) + { + last_arg = args.args[arg_idx]; + } + /* End arg not reached. Too many args supplied. */ Assert(last_arg.kind == FmtArgKind_End); } #endif - return (String) - { - .len = final_len, - .text = final_text - }; + return result; } -String FormatString_(Arena *arena, String fmt, ...) +String FormatStringV_(Arena *arena, String fmt, ...) { va_list args; va_start(args, fmt); - String new_str = FormatStringV(arena, fmt, args); + String result = FormatStringVL(arena, fmt, args); va_end(args); - return new_str; + return result; +} + +FmtArgArray FmtArgsFromVaList(Arena *arena, va_list args) +{ + FmtArgArray result = ZI; + result.args = ArenaNext(arena, FmtArg); + { + b32 done = 0; + while (!done) + { + FmtArg arg = va_arg(args, FmtArg); + *PushStructNoZero(arena, FmtArg) = arg; + ++result.count; + switch (arg.kind) + { + default: + { + /* Last arg reached */ + done = 1; + } break; + + case FmtArgKind_Char: + case FmtArgKind_String: + case FmtArgKind_Uint: + case FmtArgKind_Sint: + case FmtArgKind_Hex: + case FmtArgKind_Ptr: + case FmtArgKind_Float: + case FmtArgKind_Uid: + case FmtArgKind_Handle: + { + /* Continue */ + } break; + } + } + } + return result; } //////////////////////////////////////////////////////////// diff --git a/src/base/base_string.h b/src/base/base_string.h index 83a0afe9..d830f500 100644 --- a/src/base/base_string.h +++ b/src/base/base_string.h @@ -43,6 +43,12 @@ Struct(FmtArg) } value; }; +Struct(FmtArgArray) +{ + u64 count; + FmtArg *args; +}; + //////////////////////////////////////////////////////////// //~ Unicode types @@ -111,10 +117,23 @@ String StringFromList(Arena *arena, StringList l, String separator); #define FmtUid(v, ...) FMTARG(FmtArgKind_Uid, .value.uid = (v), __VA_ARGS__) #define FmtEnd FMTARG(FmtArgKind_End) /* Denotes end of VA list */ -#define StringF(arena, lit, ...) FormatString_((arena), Lit(lit), __VA_ARGS__, FmtEnd) -#define FormatString(arena, fmt, ...) FormatString_((arena), (fmt), __VA_ARGS__, FmtEnd) -String FormatString_(Arena *arena, String fmt, ...); -String FormatStringV(Arena *arena, String fmt, va_list args); +// #define StringF(arena, lit, ...) FormatString_((arena), Lit(lit), __VA_ARGS__, FmtEnd) +// #define FormatString(arena, fmt, ...) FormatString_((arena), (fmt), __VA_ARGS__, FmtEnd) +// String FormatString_(Arena *arena, String fmt, ...); +// String FormatStringV(Arena *arena, String fmt, va_list args); + +String FormatString(Arena *arena, String fmt, FmtArgArray args); +String StringF_(Arena *arena, String fmt, ...); +#define StringF(arena, lit, ...) StringF_((arena), Lit(lit), __VA_ARGS__, FmtEnd) + +FmtArgArray FmtArgsFromVaList(Arena *arena, va_list vl); + + + + + + + //////////////////////////////////////////////////////////// //~ Unicode diff --git a/src/gpu/gpu_core.h b/src/gpu/gpu_core.h index afb3dd91..b7ce5ca0 100644 --- a/src/gpu/gpu_core.h +++ b/src/gpu/gpu_core.h @@ -724,11 +724,11 @@ void G_Compute(G_CommandListHandle cl, ComputeShader cs, Vec3I32 groups); //- Rasterize void G_Rasterize(G_CommandListHandle cl, - VertexShader vs, PixelShader ps, - u32 instances_count, G_IndexBufferDesc index_buffer, - u32 render_targets_count, G_ResourceHandle *render_targets, - Rng3 viewport, Rng2 scissor, - G_RasterMode mode); + VertexShader vs, PixelShader ps, + u32 instances_count, G_IndexBufferDesc index_buffer, + u32 render_targets_count, G_ResourceHandle *render_targets, + Rng3 viewport, Rng2 scissor, + G_RasterMode mode); //- Clear diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index ef073019..69d48e65 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -137,7 +137,7 @@ void G_Bootstrap(void) hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgi_info); if (FAILED(hr)) { - Panic(Lit("Failed to get DXGI debug interface")); + Panic(Lit("Failed to retrieve DXGI debug interface")); } IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, 1); IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, 1); @@ -487,68 +487,75 @@ G_D12_Pipeline *G_D12_PipelineFromDesc(G_D12_PipelineDesc desc) if (ok && (!IsResourceNil(desc.vs.resource) || !IsResourceNil(desc.ps.resource))) { D3D12_RASTERIZER_DESC raster_desc = ZI; - if (desc.is_wireframe) { - raster_desc.FillMode = D3D12_FILL_MODE_WIREFRAME; - } - else - { - raster_desc.FillMode = D3D12_FILL_MODE_SOLID; - } - raster_desc.CullMode = D3D12_CULL_MODE_NONE; - raster_desc.FrontCounterClockwise = 0; - raster_desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; - raster_desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; - raster_desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; - raster_desc.DepthClipEnable = 1; - raster_desc.MultisampleEnable = 0; - raster_desc.AntialiasedLineEnable = 0; - raster_desc.ForcedSampleCount = 0; - raster_desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - - D3D12_BLEND_DESC blend_desc = ZI; - blend_desc.AlphaToCoverageEnable = 0; - blend_desc.IndependentBlendEnable = 0; - blend_desc.RenderTarget[0].BlendEnable = 1; - blend_desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; - blend_desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; - blend_desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - blend_desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - blend_desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; - blend_desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - - D3D12_DEPTH_STENCIL_DESC ds_desc = ZI; - ds_desc.DepthEnable = 0; - ds_desc.StencilEnable = 0; - - String vs = DataFromResource(desc.vs.resource); - String ps = DataFromResource(desc.ps.resource); - - D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = ZI; - pso_desc.pRootSignature = g->bindless_rootsig; - pso_desc.VS.pShaderBytecode = vs.text; - pso_desc.VS.BytecodeLength = vs.len; - pso_desc.PS.pShaderBytecode = ps.text; - pso_desc.PS.BytecodeLength = ps.len; - pso_desc.RasterizerState = raster_desc; - pso_desc.BlendState = blend_desc; - pso_desc.DepthStencilState = ds_desc; - pso_desc.PrimitiveTopologyType = desc.topology_type; - pso_desc.SampleMask = UINT_MAX; - pso_desc.SampleDesc.Count = 1; - pso_desc.SampleDesc.Quality = 0; - for (i32 i = 0; i < (i32)countof(desc.render_target_formats); ++i) - { - StaticAssert(countof(pso_desc.RTVFormats) <= countof(desc.render_target_formats)); - DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(desc.render_target_formats[i]); - if (format != DXGI_FORMAT_UNKNOWN) + if (desc.is_wireframe) { - pso_desc.RTVFormats[pso_desc.NumRenderTargets++] = format; + raster_desc.FillMode = D3D12_FILL_MODE_WIREFRAME; } else { - break; + raster_desc.FillMode = D3D12_FILL_MODE_SOLID; + } + raster_desc.CullMode = D3D12_CULL_MODE_NONE; + raster_desc.FrontCounterClockwise = 0; + raster_desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + raster_desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + raster_desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + raster_desc.DepthClipEnable = 1; + raster_desc.MultisampleEnable = 0; + raster_desc.AntialiasedLineEnable = 0; + raster_desc.ForcedSampleCount = 0; + raster_desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + } + + D3D12_BLEND_DESC blend_desc = ZI; + { + blend_desc.AlphaToCoverageEnable = 0; + blend_desc.IndependentBlendEnable = 0; + blend_desc.RenderTarget[0].BlendEnable = 1; + blend_desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; + blend_desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + blend_desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + blend_desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + blend_desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + blend_desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } + + D3D12_DEPTH_STENCIL_DESC ds_desc = ZI; + { + ds_desc.DepthEnable = 0; + ds_desc.StencilEnable = 0; + } + + String vs = DataFromResource(desc.vs.resource); + String ps = DataFromResource(desc.ps.resource); + D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = ZI; + { + pso_desc.pRootSignature = g->bindless_rootsig; + pso_desc.VS.pShaderBytecode = vs.text; + pso_desc.VS.BytecodeLength = vs.len; + pso_desc.PS.pShaderBytecode = ps.text; + pso_desc.PS.BytecodeLength = ps.len; + pso_desc.RasterizerState = raster_desc; + pso_desc.BlendState = blend_desc; + pso_desc.DepthStencilState = ds_desc; + pso_desc.PrimitiveTopologyType = desc.topology_type; + pso_desc.SampleMask = UINT_MAX; + pso_desc.SampleDesc.Count = 1; + pso_desc.SampleDesc.Quality = 0; + for (i32 i = 0; i < (i32)countof(desc.render_target_formats); ++i) + { + StaticAssert(countof(pso_desc.RTVFormats) <= countof(desc.render_target_formats)); + DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(desc.render_target_formats[i]); + if (format != DXGI_FORMAT_UNKNOWN) + { + pso_desc.RTVFormats[pso_desc.NumRenderTargets++] = format; + } + else + { + break; + } } } hr = ID3D12Device_CreateGraphicsPipelineState(g->device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); @@ -561,11 +568,12 @@ G_D12_Pipeline *G_D12_PipelineFromDesc(G_D12_PipelineDesc desc) else if (ok) { String cs = DataFromResource(desc.cs.resource); - D3D12_COMPUTE_PIPELINE_STATE_DESC pso_desc = ZI; - pso_desc.pRootSignature = g->bindless_rootsig; - pso_desc.CS.pShaderBytecode = cs.text; - pso_desc.CS.BytecodeLength = cs.len; + { + pso_desc.pRootSignature = g->bindless_rootsig; + pso_desc.CS.pShaderBytecode = cs.text; + pso_desc.CS.BytecodeLength = cs.len; + } hr = ID3D12Device_CreateComputePipelineState(g->device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); if (FAILED(hr)) { @@ -2748,7 +2756,7 @@ G_ResourceHandle G_PrepareBackbuffer(G_SwapchainHandle swapchain_handle, G_Forma if (FAILED(hr)) { /* TODO: Don't panic */ - Panic(Lit("Failed to get swapchain buffer")); + Panic(Lit("Failed to retrieve swapchain buffer")); } ZeroStruct(backbuffer); backbuffer->d3d_resource = d3d_resource; @@ -2825,6 +2833,8 @@ void G_CommitBackbuffer(G_ResourceHandle backbuffer_handle, i32 vsync) //////////////////////////////////////////////////////////// //~ Collection worker +/* TODO: Move this to common */ + void G_D12_CollectionWorkerEntry(WaveLaneCtx *lane) { G_QueueKind queue_kind = G_QueueKind_Direct; @@ -2852,8 +2862,8 @@ void G_D12_CollectionWorkerEntry(WaveLaneCtx *lane) G_CopyBufferToBuffer(cl, readback_buff, 0, queue->print_buffer, RNGU64(0, queue->print_buffer_size)); /* Reset counters to 0 */ G_MemorySync(cl, queue->print_buffer, - G_Stage_Copy, G_Access_CopyRead, - G_Stage_Copy, G_Access_CopyWrite + G_Stage_Copy, G_Access_CopyRead, + G_Stage_Copy, G_Access_CopyWrite ); u8 zero[12] = ZI; G_CopyCpuToBuffer(cl, queue->print_buffer, 0, zero, RNGU64(0, sizeof(zero))); @@ -2861,6 +2871,7 @@ void G_D12_CollectionWorkerEntry(WaveLaneCtx *lane) G_CommitCommandList(cl); G_SyncCpu(G_MaskFromQueue(queue_kind)); + u32 attempted_print_bytes_count = *(G_StructFromResource(readback_buff, u32) + 0); u32 prints_count = *(G_StructFromResource(readback_buff, u32) + 1); u32 overflows_count = *(G_StructFromResource(readback_buff, u32) + 2); @@ -2891,49 +2902,44 @@ void G_D12_CollectionWorkerEntry(WaveLaneCtx *lane) at += chars_count; } - FmtArg *args = 0; + FmtArgArray args = ZI; + args.count = args_count; { if (args_count > 0) { - args = PushStructs(scratch.arena, FmtArg, args_count); + args.args = PushStructs(scratch.arena, FmtArg, args_count); for (u32 arg_idx = 0; arg_idx <= args_count; ++arg_idx) { G_FmtArgKind gpu_kind = (G_FmtArgKind)(*at); at += 1; - u32 gpu_data = *(u32 *)at; + + u32 gpu_value = *(u32 *)at; at += 4; - FmtArg *dst = &args[arg_idx]; + FmtArg *dst = &args.args[arg_idx]; switch (gpu_kind) { case G_FmtArgKind_U32: { dst->kind = FmtArgKind_Uint; - dst->value.uint = gpu_data; + dst->value.uint = gpu_value; } break; case G_FmtArgKind_I32: { dst->kind = FmtArgKind_Sint; - dst->value.sint = (i32)gpu_data; + dst->value.sint = (i32)gpu_value; } break; case G_FmtArgKind_F32: { dst->kind = FmtArgKind_Float; - dst->value.f = *(f32 *)&gpu_data; + dst->value.f = *(f32 *)&gpu_value; } break; } } } } - // String final_str = ZI; - // if (args_count > 0) - // { - // } - // else - // { - // final_str = PushString(scratch.arena, fmt); - // } + String final_str = FormatString(scratch.arena, fmt, args); at = (u8 *)AlignU64((u64)at, 4); } diff --git a/src/gpu/gpu_shader_core.cgh b/src/gpu/gpu_shader_core.cgh index 6f9c1f1d..ca382c65 100644 --- a/src/gpu/gpu_shader_core.cgh +++ b/src/gpu/gpu_shader_core.cgh @@ -160,11 +160,12 @@ Struct(G_FmtArg) u32 chunks_count = (buff.char_pos + 3) / 4; u32 alloc_size = 0; - alloc_size += 4; /* Header */ - alloc_size += chunks_count * 4; /* Chunks */ + alloc_size += 4; /* Header */ + alloc_size += chunks_count * 4; /* Chunks */ + /* Atomic fetch + add to base counter */ u32 base; - rw.InterlockedAdd(0, alloc_size, base); /* Write to base counter */ + rw.InterlockedAdd(0, alloc_size, base); u32 pos = base; pos += 4; /* Offset for base counter */ @@ -176,7 +177,7 @@ Struct(G_FmtArg) /* Increment success counter */ rw.InterlockedAdd(4, 1); - /* Store header */ + /* Write header */ { u32 header = 0; header |= (buff.fmt_size << 0) & 0x0000FFFF; @@ -184,7 +185,8 @@ Struct(G_FmtArg) rw.Store(base + pos, header); pos += 4; } - /* Store chunks */ + + /* Write chunks */ for (u32 chunk_idx = 0; chunk_idx < chunks_count; ++chunk_idx) { u32 chunk = buff.char_chunks[chunk_idx];