ui layer testing
This commit is contained in:
parent
2fdf891d49
commit
b74927602c
@ -287,7 +287,7 @@ Struct(GPU_ResourceDesc)
|
|||||||
{
|
{
|
||||||
GPU_Format format;
|
GPU_Format format;
|
||||||
Vec3I32 size;
|
Vec3I32 size;
|
||||||
i32 mip_levels;
|
i32 mip_levels; /* Defaults to 1 (unless GPU_ResourceFlag_MaxMipLevels is set) */
|
||||||
} texture;
|
} texture;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|||||||
@ -990,8 +990,11 @@ JobDef(Build, _, __)
|
|||||||
ret = errors.count > 0;
|
ret = errors.count > 0;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Compile
|
//~ Compile & link
|
||||||
|
|
||||||
|
if (errors.count == 0)
|
||||||
|
{
|
||||||
|
//- Compile
|
||||||
StepParams params_array[3] = ZI;
|
StepParams params_array[3] = ZI;
|
||||||
StepResult results_array[3] = ZI;
|
StepResult results_array[3] = ZI;
|
||||||
|
|
||||||
@ -1017,8 +1020,7 @@ JobDef(Build, _, __)
|
|||||||
job_count += RunJob(Step, .count = countof(params_array), .fence = &job_fence, .sig.params = params_array, .sig.results = results_array);
|
job_count += RunJob(Step, .count = countof(params_array), .fence = &job_fence, .sig.params = params_array, .sig.results = results_array);
|
||||||
YieldOnFence(&job_fence, job_count);
|
YieldOnFence(&job_fence, job_count);
|
||||||
|
|
||||||
////////////////////////////////
|
//- Process compile step results
|
||||||
//~ Process compile step results
|
|
||||||
|
|
||||||
/* Copy meta errors */
|
/* Copy meta errors */
|
||||||
for (M_Error *e = program_result->meta_errors.first; e; e = e->next) M_PushError(arena, &errors, e->token, e->msg);
|
for (M_Error *e = program_result->meta_errors.first; e; e = e->next) M_PushError(arena, &errors, e->token, e->msg);
|
||||||
@ -1045,8 +1047,7 @@ JobDef(Build, _, __)
|
|||||||
if (resource_output.len > 0) EchoLine(resource_output);
|
if (resource_output.len > 0) EchoLine(resource_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
//- Link
|
||||||
//~ Link
|
|
||||||
|
|
||||||
String exe_file = Lit("pp.exe");
|
String exe_file = Lit("pp.exe");
|
||||||
i64 link_elapsed_ns = 0;
|
i64 link_elapsed_ns = 0;
|
||||||
@ -1079,6 +1080,8 @@ JobDef(Build, _, __)
|
|||||||
{
|
{
|
||||||
EchoLine(StringF(arena, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns))));
|
EchoLine(StringF(arena, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns))));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Echo errors
|
//~ Echo errors
|
||||||
|
|||||||
@ -286,6 +286,11 @@ M_LayerList M_LayersFromTokenFiles(Arena *arena, M_TokenFileList lexed)
|
|||||||
{
|
{
|
||||||
entry->kind = kind_plus_1 - 1;
|
entry->kind = kind_plus_1 - 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String err = StringF(arena, "Unexpected token \"%F\"", FmtString(entry_token->s));
|
||||||
|
M_PushError(arena, &layer->errors, entry->name_token, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token = token->next;
|
token = token->next;
|
||||||
|
|||||||
22
src/pp/pp.c
22
src/pp/pp.c
@ -495,6 +495,11 @@ void UpdateUser(P_Window *window)
|
|||||||
g->real_time_ns += g->real_dt_ns;
|
g->real_time_ns += g->real_dt_ns;
|
||||||
g->screen_size = P_GetWindowSize(window);
|
g->screen_size = P_GetWindowSize(window);
|
||||||
|
|
||||||
|
//- Begin UI
|
||||||
|
UI_BeginBuild();
|
||||||
|
UI_Box *pp_root_box = UI_BuildBox(UI_Flag_DrawImage, UI_NilKey);
|
||||||
|
UI_PushParent(pp_root_box);
|
||||||
|
|
||||||
//- Pull latest local sim snapshot
|
//- Pull latest local sim snapshot
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -517,7 +522,7 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
{
|
{
|
||||||
__profn("Blend snapshots");
|
__profn("Blend snapshots");
|
||||||
/* How along are we between sim ticks (0 = start of tick, 1 = end of tick) */
|
/* Determine how far along are we between sim ticks (0 = start of tick, 1 = end of tick) */
|
||||||
f64 tick_progress = 0;
|
f64 tick_progress = 0;
|
||||||
i64 next_tick_expected_ns = g->last_local_to_user_snapshot_published_at_ns + g->average_local_to_user_snapshot_publish_dt_ns;
|
i64 next_tick_expected_ns = g->last_local_to_user_snapshot_published_at_ns + g->average_local_to_user_snapshot_publish_dt_ns;
|
||||||
if (next_tick_expected_ns > g->last_local_to_user_snapshot_published_at_ns)
|
if (next_tick_expected_ns > g->last_local_to_user_snapshot_published_at_ns)
|
||||||
@ -2630,12 +2635,12 @@ void UpdateUser(P_Window *window)
|
|||||||
{
|
{
|
||||||
DelayReleaseGpuResources_Sig *sig = PushStruct(job->arena, DelayReleaseGpuResources_Sig);
|
DelayReleaseGpuResources_Sig *sig = PushStruct(job->arena, DelayReleaseGpuResources_Sig);
|
||||||
job->count = countof(release_resources);
|
job->count = countof(release_resources);
|
||||||
|
job->sig = sig;
|
||||||
sig->begin_fence = render_fence;
|
sig->begin_fence = render_fence;
|
||||||
sig->begin_fence_target = g->gpu_render_fence_target;
|
sig->begin_fence_target = g->gpu_render_fence_target;
|
||||||
sig->resources = PushStructsNoZero(job->arena, GPU_Resource *, job->count);
|
sig->resources = PushStructsNoZero(job->arena, GPU_Resource *, job->count);
|
||||||
sig->flags = GPU_ReleaseFlag_Reuse;
|
sig->flags = GPU_ReleaseFlag_Reuse;
|
||||||
CopyBytes(sig->resources, release_resources, sizeof(release_resources));
|
CopyBytes(sig->resources, release_resources, sizeof(release_resources));
|
||||||
job->sig = sig;
|
|
||||||
}
|
}
|
||||||
CloseJob(job);
|
CloseJob(job);
|
||||||
}
|
}
|
||||||
@ -2645,11 +2650,20 @@ void UpdateUser(P_Window *window)
|
|||||||
ResetArena(g->ui_shape_indices_arena);
|
ResetArena(g->ui_shape_indices_arena);
|
||||||
ResetArena(g->grids_arena);
|
ResetArena(g->grids_arena);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Render UI */
|
||||||
|
UI_PopParent();
|
||||||
|
UI_SetDisplayImage(pp_root_box, g->ui_target);
|
||||||
|
GPU_Resource *ui_render = UI_EndBuild();
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Present
|
||||||
|
|
||||||
Vec2 backbuffer_dst_f = MulXformV2(g->ui_to_screen_xf, VEC2(0, 0));
|
Vec2 backbuffer_dst_f = MulXformV2(g->ui_to_screen_xf, VEC2(0, 0));
|
||||||
Vec2I32 backbuffer_dst = VEC2I32(RoundF32ToI32(backbuffer_dst_f.x), RoundF32ToI32(backbuffer_dst_f.y));
|
Vec2I32 backbuffer_dst = VEC2I32(RoundF32ToI32(backbuffer_dst_f.x), RoundF32ToI32(backbuffer_dst_f.y));
|
||||||
g->gpu_render_fence_target = GPU_PresentSwapchain(g->swapchain, g->ui_target, g->screen_size, backbuffer_dst, VSYNC);
|
g->gpu_render_fence_target = GPU_PresentSwapchain(g->swapchain, ui_render, g->screen_size, backbuffer_dst, VSYNC);
|
||||||
}
|
// g->gpu_render_fence_target = GPU_PresentSwapchain(g->swapchain, g->ui_target, g->screen_size, backbuffer_dst, VSYNC);
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,14 +42,14 @@ MaterialPS_Input VSDef(MaterialVS, Semantic(u32, sv_instanceid), Semantic(u32, s
|
|||||||
|
|
||||||
Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
|
Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
|
||||||
|
|
||||||
MaterialPS_Input output;
|
MaterialPS_Input result;
|
||||||
output.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
result.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
||||||
output.tex = instance.tex;
|
result.tex = instance.tex;
|
||||||
output.grid_id = instance.grid_id;
|
result.grid_id = instance.grid_id;
|
||||||
output.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));
|
result.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));
|
||||||
output.tint_lin = LinearFromSrgbU32(instance.tint_srgb);
|
result.tint_lin = LinearFromSrgbU32(instance.tint_srgb);
|
||||||
output.emittance_lin = LinearFromSrgbVec4(Vec4(instance.light_emittance_srgb, instance.is_light));
|
result.emittance_lin = LinearFromSrgbVec4(Vec4(instance.light_emittance_srgb, instance.is_light));
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Pixel shader
|
//- Pixel shader
|
||||||
@ -58,7 +58,7 @@ MaterialPS_Output PSDef(MaterialPS, MaterialPS_Input input)
|
|||||||
{
|
{
|
||||||
ConstantBuffer<MaterialSig> sig = mat_sig;
|
ConstantBuffer<MaterialSig> sig = mat_sig;
|
||||||
|
|
||||||
MaterialPS_Output output;
|
MaterialPS_Output result;
|
||||||
Vec4 albedo = input.tint_lin;
|
Vec4 albedo = input.tint_lin;
|
||||||
|
|
||||||
/* Texture */
|
/* Texture */
|
||||||
@ -116,10 +116,10 @@ MaterialPS_Output PSDef(MaterialPS, MaterialPS_Input input)
|
|||||||
|
|
||||||
Vec4 emittance = input.emittance_lin * albedo.a;
|
Vec4 emittance = input.emittance_lin * albedo.a;
|
||||||
|
|
||||||
output.sv_target0 = albedo;
|
result.sv_target0 = albedo;
|
||||||
output.sv_target1 = emittance;
|
result.sv_target1 = emittance;
|
||||||
|
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -330,10 +330,10 @@ UiBlitPS_Input VSDef(UiBlitVS, Semantic(u32, sv_vertexid))
|
|||||||
};
|
};
|
||||||
Vec2 vert = unit_quad_verts[sv_vertexid];
|
Vec2 vert = unit_quad_verts[sv_vertexid];
|
||||||
|
|
||||||
UiBlitPS_Input output;
|
UiBlitPS_Input result;
|
||||||
output.sv_position = mul(sig.projection, Vec4(vert, 0, 1));
|
result.sv_position = mul(sig.projection, Vec4(vert, 0, 1));
|
||||||
output.uv = vert + 0.5;
|
result.uv = vert + 0.5;
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Pixel shader
|
//- Pixel shader
|
||||||
@ -343,7 +343,7 @@ UiBlitPS_Output PSDef(UiBlitPS, UiBlitPS_Input input)
|
|||||||
ConstantBuffer<UiBlitSig> sig = ui_blit_sig;
|
ConstantBuffer<UiBlitSig> sig = ui_blit_sig;
|
||||||
SamplerState sampler = UniformSamplerFromRid(sig.sampler);
|
SamplerState sampler = UniformSamplerFromRid(sig.sampler);
|
||||||
|
|
||||||
UiBlitPS_Output output;
|
UiBlitPS_Output result;
|
||||||
Texture2D<Vec4> tex = UniformResourceFromRid(sig.src);
|
Texture2D<Vec4> tex = UniformResourceFromRid(sig.src);
|
||||||
Vec4 color = tex.Sample(sampler, input.uv);
|
Vec4 color = tex.Sample(sampler, input.uv);
|
||||||
|
|
||||||
@ -361,8 +361,8 @@ UiBlitPS_Output PSDef(UiBlitPS, UiBlitPS_Input input)
|
|||||||
color = pow(abs(color), 1/sig.gamma);
|
color = pow(abs(color), 1/sig.gamma);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.sv_target = color;
|
result.sv_target = color;
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -398,12 +398,12 @@ UiRectPS_Input VSDef(UiRectVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_ve
|
|||||||
Vec2 vert = unit_quad_verts[sv_vertexid];
|
Vec2 vert = unit_quad_verts[sv_vertexid];
|
||||||
Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
|
Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
|
||||||
|
|
||||||
UiRectPS_Input output;
|
UiRectPS_Input result;
|
||||||
output.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
result.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
||||||
output.tex = instance.tex;
|
result.tex = instance.tex;
|
||||||
output.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));
|
result.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));
|
||||||
output.tint_srgb = Vec4NormFromU32(instance.tint_srgb);
|
result.tint_srgb = Vec4NormFromU32(instance.tint_srgb);
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Pixel shader
|
//- Pixel shader
|
||||||
@ -411,7 +411,7 @@ UiRectPS_Input VSDef(UiRectVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_ve
|
|||||||
UiRectPS_Output PSDef(UiRectPS, UiRectPS_Input input)
|
UiRectPS_Output PSDef(UiRectPS, UiRectPS_Input input)
|
||||||
{
|
{
|
||||||
ConstantBuffer<UiRectSig> sig = ui_rect_sig;
|
ConstantBuffer<UiRectSig> sig = ui_rect_sig;
|
||||||
UiRectPS_Output output;
|
UiRectPS_Output result;
|
||||||
Vec4 color = input.tint_srgb;
|
Vec4 color = input.tint_srgb;
|
||||||
|
|
||||||
/* Texture */
|
/* Texture */
|
||||||
@ -422,8 +422,8 @@ UiRectPS_Output PSDef(UiRectPS, UiRectPS_Input input)
|
|||||||
color *= tex.Sample(sampler, input.uv);
|
color *= tex.Sample(sampler, input.uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.sv_target0 = color;
|
result.sv_target0 = color;
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -447,17 +447,17 @@ UiShapePS_Input VSDef(UiShapeVS, Semantic(u32, sv_vertexid))
|
|||||||
ConstantBuffer<UiShapeSig> sig = ui_shape_sig;
|
ConstantBuffer<UiShapeSig> sig = ui_shape_sig;
|
||||||
StructuredBuffer<UiShapeVert> verts = UniformResourceFromRid(sig.verts);
|
StructuredBuffer<UiShapeVert> verts = UniformResourceFromRid(sig.verts);
|
||||||
UiShapeVert vert = verts[sv_vertexid];
|
UiShapeVert vert = verts[sv_vertexid];
|
||||||
UiShapePS_Input output;
|
UiShapePS_Input result;
|
||||||
output.sv_position = mul(sig.projection, Vec4(vert.pos.xy, 0, 1));
|
result.sv_position = mul(sig.projection, Vec4(vert.pos.xy, 0, 1));
|
||||||
output.color_srgb = Vec4NormFromU32(vert.color_srgb);
|
result.color_srgb = Vec4NormFromU32(vert.color_srgb);
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Pixel shader
|
//- Pixel shader
|
||||||
|
|
||||||
UiShapePS_Output PSDef(UiShapePS, UiShapePS_Input input)
|
UiShapePS_Output PSDef(UiShapePS, UiShapePS_Input input)
|
||||||
{
|
{
|
||||||
UiShapePS_Output output;
|
UiShapePS_Output result;
|
||||||
output.sv_target = input.color_srgb;
|
result.sv_target = input.color_srgb;
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
228
src/ui/ui.c
228
src/ui/ui.c
@ -7,7 +7,6 @@ UI_FiberState *UI_GetFiberState(void)
|
|||||||
{
|
{
|
||||||
UI_FiberState *f = UI_shared_state.fiber_states[FiberId()];
|
UI_FiberState *f = UI_shared_state.fiber_states[FiberId()];
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
|
||||||
{
|
{
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
PushAlign(perm, CachelineSize);
|
PushAlign(perm, CachelineSize);
|
||||||
@ -15,34 +14,90 @@ UI_FiberState *UI_GetFiberState(void)
|
|||||||
UI_shared_state.fiber_states[FiberId()] = f;
|
UI_shared_state.fiber_states[FiberId()] = f;
|
||||||
PushAlign(perm, CachelineSize);
|
PushAlign(perm, CachelineSize);
|
||||||
}
|
}
|
||||||
f->build_arena = AcquireArena(Gibi(64));
|
|
||||||
}
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Key helpers
|
//~ Key helpers
|
||||||
|
|
||||||
UI_Key UI_KeyFromString(String str)
|
UI_Key UI_KeyFromString(u64 seed, String str)
|
||||||
{
|
{
|
||||||
UI_Key key = ZI;
|
/* TOIMPL */
|
||||||
key.hash = HashFnv64(Fnv64Basis, str);
|
if (seed == 0)
|
||||||
return key;
|
{
|
||||||
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
seed = RandU64FromSeeds(f->top_parent->box->key.hash, f->top_tag->hash);
|
||||||
|
}
|
||||||
|
UI_Key result = ZI;
|
||||||
|
result.hash = HashFnv64(seed, str);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Stack helpers
|
//~ Stack helpers
|
||||||
|
|
||||||
|
//- Tag
|
||||||
|
|
||||||
|
void UI_PushTagFromHash(u64 hash)
|
||||||
|
{
|
||||||
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
if (f->top_tag)
|
||||||
|
{
|
||||||
|
hash = RandU64FromSeeds(hash, f->top_tag->hash);
|
||||||
|
}
|
||||||
|
UI_Tag *tag = PushStruct(f->build_arena, UI_Tag);
|
||||||
|
StackPush(f->top_tag, tag);
|
||||||
|
tag->hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_PushTagFromString(String str)
|
||||||
|
{
|
||||||
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
u64 hash = Fnv64Basis;
|
||||||
|
if (f->top_tag)
|
||||||
|
{
|
||||||
|
hash = f->top_tag->hash;
|
||||||
|
}
|
||||||
|
hash = HashFnv64(hash, str);
|
||||||
|
UI_Tag *tag = PushStruct(f->build_arena, UI_Tag);
|
||||||
|
StackPush(f->top_tag, tag);
|
||||||
|
tag->hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_PushTagF_(char *fmt_cstr, ...)
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
String str = ZI;
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt_cstr);
|
||||||
|
str = FormatStringV(scratch.arena, StringFromCstrNoLimit(fmt_cstr), va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
UI_PushTagFromString(str);
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_PopTag(void)
|
||||||
|
{
|
||||||
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
StackPop(f->top_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Parent
|
||||||
|
|
||||||
void UI_PushParent(UI_Box *box)
|
void UI_PushParent(UI_Box *box)
|
||||||
{
|
{
|
||||||
UI_FiberState *f = UI_GetFiberState();
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
UI_Parent *parent = PushStruct(f->build_arena, UI_Parent);
|
||||||
|
parent->box = box;
|
||||||
|
StackPush(f->top_parent, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
UI_Box *UI_PopParent(void)
|
void UI_PopParent(void)
|
||||||
{
|
{
|
||||||
UI_FiberState *f = UI_GetFiberState();
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
UI_Box *box = 0;
|
StackPop(f->top_parent);
|
||||||
return box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -50,39 +105,142 @@ UI_Box *UI_PopParent(void)
|
|||||||
|
|
||||||
UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key)
|
UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key)
|
||||||
{
|
{
|
||||||
UI_Box *box = 0;
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
UI_BoxBin *bin = &f->box_bins[key.hash % UI_NumBoxLookupBins];
|
||||||
|
UI_BoxBin *back_bin = &f->back_box_bins[key.hash % UI_NumBoxLookupBins];
|
||||||
|
|
||||||
|
UI_Box *box = PushStruct(f->build_arena, UI_Box);
|
||||||
|
if (key.hash != 0)
|
||||||
|
{
|
||||||
|
DllPushBackNP(bin->first, bin->last, box, next_in_bin, prev_in_bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find previous build's box from hash */
|
||||||
|
UI_Box *back_box = 0;
|
||||||
|
if (key.hash != 0)
|
||||||
|
{
|
||||||
|
for (UI_Box *tmp = back_bin->first; tmp; tmp = tmp->next_in_bin)
|
||||||
|
{
|
||||||
|
if (tmp->key.hash == key.hash)
|
||||||
|
{
|
||||||
|
back_box = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (back_box)
|
||||||
|
{
|
||||||
|
*box = *back_box;
|
||||||
|
}
|
||||||
|
|
||||||
|
box->key = key;
|
||||||
|
box->flags = flags;
|
||||||
|
box->parent = f->top_parent->box;
|
||||||
|
DllPushBack(f->top_parent->box->first, f->top_parent->box->last, box);
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Text
|
//~ Text
|
||||||
|
|
||||||
String UI_DisplayTextFromString(String str)
|
|
||||||
{
|
|
||||||
/* Cap string at non-display pattern (e.g. "Hello##hiddentext" becomes "Hello") */
|
|
||||||
u64 new_len = str.len;
|
|
||||||
if (str.len > 0)
|
|
||||||
{
|
|
||||||
b32 escaped = 0;
|
|
||||||
for (u64 i = 0; i < str.len - 1 && new_len == str.len; ++i)
|
|
||||||
{
|
|
||||||
u8 c = str.text[i];
|
|
||||||
if (c == '\\')
|
|
||||||
{
|
|
||||||
escaped = !escaped;
|
|
||||||
}
|
|
||||||
else if (!escaped && c == '#' && str.text[i + 1] == '#')
|
|
||||||
{
|
|
||||||
new_len = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return STRING(new_len, str.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UI_SetDisplayText(UI_Box *box, String str)
|
void UI_SetDisplayText(UI_Box *box, String str)
|
||||||
{
|
{
|
||||||
UI_FiberState *f = UI_GetFiberState();
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
String text = PushString(f->build_arena, UI_DisplayTextFromString(str));
|
String text = PushString(f->build_arena, str);
|
||||||
box->display_text = text;
|
box->display_text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Image
|
||||||
|
|
||||||
|
void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img)
|
||||||
|
{
|
||||||
|
box->display_image = img;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Begin build
|
||||||
|
|
||||||
|
void UI_BeginBuild(void)
|
||||||
|
{
|
||||||
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
|
||||||
|
/* Swap front & back build states */
|
||||||
|
{
|
||||||
|
Arena *swp = f->build_arena;
|
||||||
|
f->build_arena = f->back_build_arena;
|
||||||
|
f->back_build_arena = swp;
|
||||||
|
}
|
||||||
|
f->back_box_bins = f->box_bins;
|
||||||
|
f->back_root_box = f->root_box;
|
||||||
|
|
||||||
|
/* Reset front build state */
|
||||||
|
if (!f->build_arena)
|
||||||
|
{
|
||||||
|
f->build_arena = AcquireArena(Gibi(64));
|
||||||
|
}
|
||||||
|
ResetArena(f->build_arena);
|
||||||
|
|
||||||
|
/* Init bins */
|
||||||
|
f->box_bins = PushStructs(f->build_arena, UI_BoxBin, UI_NumBoxLookupBins);
|
||||||
|
|
||||||
|
/* Init root box */
|
||||||
|
f->root_box = PushStruct(f->build_arena, UI_Box);
|
||||||
|
f->root_box->key = UI_RootKey;
|
||||||
|
UI_BoxBin *bin = &f->box_bins[f->root_box->key.hash % UI_NumBoxLookupBins];
|
||||||
|
DllPushBackNP(bin->first, bin->last, f->root_box, next_in_bin, prev_in_bin);
|
||||||
|
|
||||||
|
/* Init stacks */
|
||||||
|
UI_PushTagF("root");
|
||||||
|
UI_PushParent(f->root_box);
|
||||||
|
|
||||||
|
if (!f->back_build_arena)
|
||||||
|
{
|
||||||
|
/* Back buffer not initialized, swap again */
|
||||||
|
UI_BeginBuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ End build
|
||||||
|
|
||||||
|
GPU_Resource *UI_EndBuild(void)
|
||||||
|
{
|
||||||
|
UI_FiberState *f = UI_GetFiberState();
|
||||||
|
|
||||||
|
/* TODO: Ensure root is parent */
|
||||||
|
|
||||||
|
GPU_QueueKind render_queue = GPU_QueueKind_Direct;
|
||||||
|
Fence *render_fence = GPU_FenceFromQueue(render_queue);
|
||||||
|
|
||||||
|
/* TODO: Real size */
|
||||||
|
Vec2I32 root_size = VEC2I32(500, 500);
|
||||||
|
|
||||||
|
/* Acquire render target */
|
||||||
|
if (f->render_target && !EqVec2I32(root_size, GPU_GetTextureSize2D(f->render_target)))
|
||||||
|
{
|
||||||
|
YieldOnFence(render_fence, f->render_fence_target);
|
||||||
|
GPU_ReleaseResource(f->render_target, GPU_ReleaseFlag_None);
|
||||||
|
f->render_target = 0;
|
||||||
|
}
|
||||||
|
if (!f->render_target)
|
||||||
|
{
|
||||||
|
GPU_ResourceDesc desc = ZI;
|
||||||
|
desc.kind = GPU_ResourceKind_Texture2D;
|
||||||
|
desc.flags = GPU_ResourceFlag_Renderable;
|
||||||
|
desc.texture.format = GPU_Format_R8G8B8A8_Unorm;
|
||||||
|
desc.texture.size = VEC3I32(root_size.x, root_size.y, 1);
|
||||||
|
f->render_target = GPU_AcquireResource(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build command list */
|
||||||
|
GPU_CommandList *cl = GPU_BeginCommandList(render_queue);
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
f->render_fence_target = GPU_EndCommandList(cl);
|
||||||
|
|
||||||
|
return f->render_target;
|
||||||
|
}
|
||||||
|
|||||||
75
src/ui/ui.h
75
src/ui/ui.h
@ -2,6 +2,7 @@
|
|||||||
//~ Key types
|
//~ Key types
|
||||||
|
|
||||||
#define UI_NilKey ((UI_Key) { 0 })
|
#define UI_NilKey ((UI_Key) { 0 })
|
||||||
|
#define UI_RootKey ((UI_Key) { 0xa3deb3749ef35a7aUll })
|
||||||
|
|
||||||
Struct(UI_Key)
|
Struct(UI_Key)
|
||||||
{
|
{
|
||||||
@ -15,20 +16,63 @@ Enum(UI_Flag)
|
|||||||
{
|
{
|
||||||
UI_Flag_None = 0,
|
UI_Flag_None = 0,
|
||||||
UI_Flag_DrawText = (1 << 0),
|
UI_Flag_DrawText = (1 << 0),
|
||||||
|
UI_Flag_DrawImage = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(UI_Box)
|
Struct(UI_Box)
|
||||||
{
|
{
|
||||||
|
UI_Box *next_in_bin;
|
||||||
|
UI_Box *prev_in_bin;
|
||||||
|
|
||||||
|
UI_Box *parent;
|
||||||
|
UI_Box *first;
|
||||||
|
UI_Box *last;
|
||||||
|
UI_Box *next;
|
||||||
|
UI_Box *prev;
|
||||||
|
|
||||||
|
UI_Key key;
|
||||||
UI_Flag flags;
|
UI_Flag flags;
|
||||||
|
|
||||||
String display_text;
|
String display_text;
|
||||||
|
GPU_Resource *display_image;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(UI_BoxBin)
|
||||||
|
{
|
||||||
|
UI_Box *first;
|
||||||
|
UI_Box *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Stack types
|
||||||
|
|
||||||
|
Struct(UI_Tag) { UI_Tag *next; u64 hash; };
|
||||||
|
Struct(UI_Parent) { UI_Parent *next; UI_Box *box; };
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ State types
|
//~ State types
|
||||||
|
|
||||||
|
#define UI_NumBoxLookupBins 16384
|
||||||
|
|
||||||
Struct(UI_FiberState)
|
Struct(UI_FiberState)
|
||||||
{
|
{
|
||||||
|
//- Build state
|
||||||
Arena *build_arena;
|
Arena *build_arena;
|
||||||
|
Arena *back_build_arena;
|
||||||
|
|
||||||
|
UI_BoxBin *box_bins;
|
||||||
|
UI_BoxBin *back_box_bins;
|
||||||
|
|
||||||
|
UI_Box *root_box;
|
||||||
|
UI_Box *back_root_box;
|
||||||
|
|
||||||
|
//- Stack state
|
||||||
|
UI_Tag *top_tag;
|
||||||
|
UI_Parent *top_parent;
|
||||||
|
|
||||||
|
//- Render state
|
||||||
|
GPU_Resource *render_target;
|
||||||
|
i64 render_fence_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(UI_SharedState)
|
Struct(UI_SharedState)
|
||||||
@ -44,25 +88,44 @@ UI_FiberState *UI_GetFiberState(void);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Key helpers
|
//~ Key helpers
|
||||||
|
|
||||||
UI_Key UI_KeyFromString(String text);
|
UI_Key UI_KeyFromString(u64 seed, String str);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Stack helpers
|
//~ Stack helpers
|
||||||
|
|
||||||
|
//- Tag
|
||||||
|
void UI_PushTagFromHash(u64 hash);
|
||||||
|
void UI_PushTagFromString(String str);
|
||||||
|
#define UI_PushTagF(fmt_cstr, ...) UI_PushTagF_(fmt_cstr, __VA_ARGS__, FmtEnd);
|
||||||
|
void UI_PushTagF_(char *fmt_cstr, ...);
|
||||||
|
void UI_PopTag(void);
|
||||||
|
|
||||||
|
//- Parent
|
||||||
void UI_PushParent(UI_Box *box);
|
void UI_PushParent(UI_Box *box);
|
||||||
UI_Box *UI_PopParent(void);
|
void UI_PopParent(void);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Box
|
//~ Box
|
||||||
|
|
||||||
UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key);
|
UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key);
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Text
|
|
||||||
|
|
||||||
String UI_DisplayTextFromString(String str);
|
|
||||||
void UI_SetDisplayText(UI_Box *box, String str);
|
void UI_SetDisplayText(UI_Box *box, String str);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Image
|
||||||
|
|
||||||
|
void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Begin build
|
||||||
|
|
||||||
|
void UI_BeginBuild(void);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ End build
|
||||||
|
|
||||||
|
GPU_Resource *UI_EndBuild(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,14 @@
|
|||||||
//- Api
|
//- Api
|
||||||
@IncludeC ui.h
|
@IncludeC ui.h
|
||||||
@IncludeC ui_widgets.h
|
@IncludeC ui_widgets.h
|
||||||
|
@IncludeC ui_draw.h
|
||||||
|
@IncludeGpu ui_draw.h
|
||||||
|
|
||||||
//- Impl
|
//- Impl
|
||||||
@IncludeC ui.c
|
@IncludeC ui.c
|
||||||
@IncludeC ui_widgets.c
|
@IncludeC ui_widgets.c
|
||||||
|
@IncludeGpu ui_draw.gpu
|
||||||
|
|
||||||
//- Startup
|
//- Shaders
|
||||||
@startup UI_Startup
|
@VertexShader UI_RectVS
|
||||||
|
@PixelShader UI_RectPS
|
||||||
|
|||||||
49
src/ui/ui_draw.gpu
Normal file
49
src/ui/ui_draw.gpu
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
ConstantBuffer<UI_RectSig> UI_rect_sig : register (b0);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Rect
|
||||||
|
|
||||||
|
Struct(UI_RectPS_Input)
|
||||||
|
{
|
||||||
|
Semantic(Vec4, sv_position);
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(UI_RectPS_Output)
|
||||||
|
{
|
||||||
|
Semantic(Vec4, sv_target0);
|
||||||
|
};
|
||||||
|
|
||||||
|
//- Vertex shader
|
||||||
|
|
||||||
|
UI_RectPS_Input VSDef(UI_RectVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_vertexid))
|
||||||
|
{
|
||||||
|
ConstantBuffer<UI_RectSig> sig = UI_rect_sig;
|
||||||
|
static const Vec2 unit_quad_verts[4] = {
|
||||||
|
Vec2(-0.5f, -0.5f),
|
||||||
|
Vec2(0.5f, -0.5f),
|
||||||
|
Vec2(0.5f, 0.5f),
|
||||||
|
Vec2(-0.5f, 0.5f)
|
||||||
|
};
|
||||||
|
|
||||||
|
StructuredBuffer<UI_RectInstance> instances = UniformResourceFromRid(sig.instances);
|
||||||
|
UI_RectInstance instance = instances[sv_instanceid];
|
||||||
|
Vec2 vert = unit_quad_verts[sv_vertexid];
|
||||||
|
// Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
|
||||||
|
Vec2 world_pos = 0;
|
||||||
|
|
||||||
|
UI_RectPS_Input result;
|
||||||
|
result.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Pixel shader
|
||||||
|
|
||||||
|
UI_RectPS_Output PSDef(UI_RectPS, UI_RectPS_Input input)
|
||||||
|
{
|
||||||
|
ConstantBuffer<UI_RectSig> sig = UI_rect_sig;
|
||||||
|
f32 color = 0;
|
||||||
|
|
||||||
|
UI_RectPS_Output result;
|
||||||
|
result.sv_target0 = color;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
23
src/ui/ui_draw.h
Normal file
23
src/ui/ui_draw.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
////////////////////////////////
|
||||||
|
//~ Rect types
|
||||||
|
|
||||||
|
Struct(UI_RectSig)
|
||||||
|
{
|
||||||
|
/* ----------------------------------------------------- */
|
||||||
|
Mat4x4 projection; /* 16 consts */
|
||||||
|
/* ----------------------------------------------------- */
|
||||||
|
StructuredBufferRid instances; /* 01 consts */
|
||||||
|
u32 _pad0; /* 01 consts (padding) */
|
||||||
|
u32 _pad1; /* 01 consts (padding) */
|
||||||
|
u32 _pad2; /* 01 consts (padding) */
|
||||||
|
/* ----------------------------------------------------- */
|
||||||
|
};
|
||||||
|
AssertRootConst(UI_RectSig, 20);
|
||||||
|
|
||||||
|
Struct(UI_RectInstance)
|
||||||
|
{
|
||||||
|
i32 _;
|
||||||
|
};
|
||||||
|
#define UI_DefaultRectInstance (UI_RectInstance) { \
|
||||||
|
0 \
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
UI_Box *UI_BuildLabel(String text)
|
UI_Box *UI_BuildLabel(String text)
|
||||||
{
|
{
|
||||||
UI_Key key = UI_KeyFromString(text);
|
UI_Key key = UI_KeyFromString(0, text);
|
||||||
UI_Box *box = UI_BuildBox(UI_Flag_DrawText, key);
|
UI_Box *box = UI_BuildBox(UI_Flag_DrawText, key);
|
||||||
UI_SetDisplayText(box, text);
|
UI_SetDisplayText(box, text);
|
||||||
return box;
|
return box;
|
||||||
@ -11,13 +11,15 @@ UI_Box *UI_BuildLabel(String text)
|
|||||||
|
|
||||||
UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...)
|
UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...)
|
||||||
{
|
{
|
||||||
UI_FiberState *f = UI_GetFiberState();
|
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
va_list args;
|
String str = ZI;
|
||||||
va_start(args, fmt_cstr);
|
{
|
||||||
String text = FormatStringV(scratch.arena, StringFromCstrNoLimit(fmt_cstr), args);
|
va_list va;
|
||||||
UI_Box *box = UI_BuildLabel(text);
|
va_start(va, fmt_cstr);
|
||||||
va_end(args);
|
str = FormatStringV(scratch.arena, StringFromCstrNoLimit(fmt_cstr), va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
UI_Box *box = UI_BuildLabel(str);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
//~ Label widget
|
//~ Label widget
|
||||||
|
|
||||||
UI_Box *UI_BuildLabel(String text);
|
UI_Box *UI_BuildLabel(String text);
|
||||||
UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...);
|
|
||||||
#define UI_BuildLabelF(fmt_cstr, ...) UI_BuildLabelF_(fmt_cstr, __VA_ARGS__, FmtEnd)
|
#define UI_BuildLabelF(fmt_cstr, ...) UI_BuildLabelF_(fmt_cstr, __VA_ARGS__, FmtEnd)
|
||||||
|
UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Separator widget
|
//~ Separator widget
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user