Commit: 60ffc2ebdd32377b74119d1e0cfcbd82109cc542
Parent: 5d25b3e6c3e82a494d8711fcf387fab9fe9e8fb7
Author: Randy Palamar
Date: Fri, 31 Jul 2026 06:09:07 -0700
core: switch arena to a growable implementation
While the fixed size implementation was fine almost everywhere in
the beamformer it is problematic for the UI. Its not that great if
the UI runs out of memory because the user has requested many
panels to be opened even though their system has much more
available RAM.
Diffstat:
| M | beamformer.c | | | 94 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
| M | beamformer.h | | | 26 | +++++++++++++------------- |
| M | beamformer_core.c | | | 94 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
| M | beamformer_internal.h | | | 25 | +++++++++++-------------- |
| M | beamformer_shared_memory.c | | | 24 | ++++++++++++++++-------- |
| M | build.c | | | 868 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
| M | lib/ogl_beamformer_lib.c | | | 44 | ++++++++++++++++++++++---------------------- |
| M | main_linux.c | | | 59 | +++++++++++++++++++++++++++-------------------------------- |
| M | main_w32.c | | | 78 | ++++++++++++++++++++++++++++++++++++------------------------------------------ |
| M | math.c | | | 12 | +++++++----- |
| M | os_linux.c | | | 60 | +++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
| M | os_win32.c | | | 66 | +++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
| M | tests/throughput.c | | | 17 | ++++++++--------- |
| M | ui.c | | | 55 | ++++++++++++++++++++++++++----------------------------- |
| M | util.c | | | 342 | +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
| M | util.h | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++---- |
| M | vulkan.c | | | 102 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
17 files changed, 1167 insertions(+), 847 deletions(-)
diff --git a/beamformer.c b/beamformer.c
@@ -10,7 +10,7 @@ EXPORT i32 AmdPowerXpressRequestHighPerformance = 1;
#include "beamformer_core.c"
#else
-typedef void beamformer_frame_step_fn(BeamformerInput *);
+typedef void beamformer_frame_step_fn(void *, BeamformerInput *);
#define BEAMFORMER_DEBUG_ENTRY_POINTS \
X(beamformer_debug_ui_deinit) \
@@ -23,10 +23,9 @@ BEAMFORMER_DEBUG_ENTRY_POINTS
#undef X
BEAMFORMER_EXPORT void
-beamformer_debug_hot_release(BeamformerInput *input)
+beamformer_debug_hot_release(void *memory, BeamformerInput *input)
{
- BeamformerCtx *ctx = BeamformerContextMemory(input->memory);
-
+ BeamformerCtx *ctx = memory;
// TODO(rnp): this will deadlock if live imaging is active
/* NOTE(rnp): spin until compute thread finishes its work (we will probably
* never reload while compute is in progress but just incase). */
@@ -35,7 +34,7 @@ beamformer_debug_hot_release(BeamformerInput *input)
}
BEAMFORMER_EXPORT void
-beamformer_debug_hot_reload(OSLibrary library, BeamformerInput *input)
+beamformer_debug_hot_reload(OSLibrary library)
{
#define X(name) name = os_lookup_symbol(library, #name);
BEAMFORMER_DEBUG_ENTRY_POINTS
@@ -92,14 +91,14 @@ load_gl(Stream *err)
}
function void
-beamformer_load_cuda_library(BeamformerCtx *ctx, OSLibrary cuda, Arena arena)
+beamformer_load_cuda_library(BeamformerCtx *ctx, OSLibrary cuda, Arena *scratch)
{
/* TODO(rnp): (25.10.30) registering the rf buffer with CUDA is currently
* causing a major performance regression. for now we are disabling its use
* altogether. it will be reenabled once the issue can be fixed */
b32 result = 0 && vk_gpu_info()->vendor == GPUVendor_NVIDIA && ValidHandle(cuda);
if (result) {
- Stream err = arena_stream(arena);
+ Stream err = arena_stream(scratch);
stream_append_str8(&err, beamformer_info("loading CUDA library functions"));
#define X(name, symname) cuda_## name = os_lookup_symbol(cuda, symname);
@@ -140,8 +139,7 @@ function OS_THREAD_ENTRY_POINT_FN(compute_worker_thread_entry_point)
for (;;) {
worker_thread_sleep(ctx, beamformer->shared_memory);
- asan_poison_region(ctx->arena.beg, ctx->arena.end - ctx->arena.beg);
- beamformer_complete_compute(beamformer, &ctx->arena);
+ beamformer_complete_compute(beamformer, ctx->arena);
}
unreachable();
@@ -164,33 +162,25 @@ function OS_THREAD_ENTRY_POINT_FN(beamformer_upload_entry_point)
return 0;
}
-BEAMFORMER_EXPORT void
+BEAMFORMER_EXPORT void *
beamformer_init(BeamformerInput *input)
{
- Arena memory = arena_from_memory(input->memory, input->memory_size);
- Arena compute_arena = sub_arena_end(&memory, MB(2), KB(4));
- Arena upload_arena = sub_arena_end(&memory, KB(4), KB(4));
- Arena ui_arena = sub_arena_end(&memory, MB(2), KB(4));
- Stream error = arena_stream(sub_arena_end(&memory, MB(1), 1));
+ Arena *memory = arena_create(.name = "Beamformer Memory");
+ Stream error = stream_alloc(memory, MB(1));
+ BeamformerCtx *ctx = push_struct(memory, BeamformerCtx);
- BeamformerCtx *ctx = push_struct(&memory, BeamformerCtx);
-
- for EachElement(ctx->frame_arenas, it) {
- ctx->frame_arenas[it] = sub_arena(&memory, KB(64), KB(4));
- ctx->frame_arena_savepoints[it] = begin_temp_arena(ctx->frame_arenas + it);
- }
+ for EachElement(ctx->frame_arenas, it)
+ ctx->frame_arenas[it] = arena_create();
str8 window_title = str8("VK Beamformer");
ctx->main_window = os_window_create(window_title.data, window_title.length, 1280, 840);
ctx->window_size = (iv2){{1280, 840}};
- Arena scratch = {.beg = memory.end - 4096L, .end = memory.end};
- memory.end = scratch.beg;
-
- ctx->error_stream = error;
- ctx->ui_backing_store = ui_arena;
- ctx->compute_worker.arena = compute_arena;
- ctx->upload_worker.arena = upload_arena;
+ ctx->arena = memory;
+ ctx->error_stream = error;
+ ctx->ui_arena = arena_create();
+ ctx->compute_worker.arena = arena_create();
+ ctx->upload_worker.arena = arena_create();
#if BEAMFORMER_RENDERDOC_HOOKS
start_frame_capture = input->renderdoc_start_frame_capture;
@@ -198,7 +188,7 @@ beamformer_init(BeamformerInput *input)
set_capture_path_template = input->renderdoc_set_capture_file_path_template;
#endif
- vk_load(input->vulkan_library_handle, &memory, &ctx->error_stream);
+ vk_load(input->vulkan_library_handle, &ctx->error_stream);
BeamformerComputeContext *cs = &ctx->compute_context;
@@ -248,7 +238,8 @@ beamformer_init(BeamformerInput *input)
vk_bind_shader_resources(shader_resource_infos, countof(shader_resource_infos));
}
- beamformer_load_cuda_library(ctx, input->cuda_library_handle, memory);
+ Arena *scratch = arena_create();
+ beamformer_load_cuda_library(ctx, input->cuda_library_handle, scratch);
load_gl(&ctx->error_stream);
@@ -304,7 +295,7 @@ beamformer_init(BeamformerInput *input)
worker->handle = os_create_thread("[compute]", worker, compute_worker_thread_entry_point);
GLWorkerThreadContext *upload = &ctx->upload_worker;
- BeamformerUploadThreadContext *upctx = push_struct(&memory, typeof(*upctx));
+ BeamformerUploadThreadContext *upctx = push_struct(memory, typeof(*upctx));
upload->user_context = (iptr)upctx;
upctx->rf_buffer = &cs->rf_buffer;
upctx->shared_memory = ctx->shared_memory;
@@ -314,45 +305,46 @@ beamformer_init(BeamformerInput *input)
upload->handle = os_create_thread("[upload]", upload, beamformer_upload_entry_point);
/* NOTE: set up OpenGL debug logging */
- Stream *gl_error_stream = push_struct(&memory, Stream);
- *gl_error_stream = stream_alloc(&memory, 1024);
+ Stream *gl_error_stream = push_struct(memory, Stream);
+ *gl_error_stream = stream_alloc(memory, 1024);
glDebugMessageCallback(gl_debug_logger, gl_error_stream);
-#ifdef _DEBUG
+ #ifdef BEAMFORMER_DEBUG
glEnable(GL_DEBUG_OUTPUT);
-#endif
+ #endif
if (!BakeShaders)
{
for EachElement(beamformer_reloadable_compute_shader_info_indices, it) {
i32 index = beamformer_reloadable_compute_shader_info_indices[it];
- Arena temp = scratch;
- str8 file = push_str8_from_parts(&temp, os_path_separator(), str8("shaders"),
+
+ str8 file = push_str8_from_parts(scratch, os_path_separator(), str8("shaders"),
beamformer_reloadable_shader_files[index][0]);
- BeamformerFileReloadContext *frc = push_struct(&memory, typeof(*frc));
+ BeamformerFileReloadContext *frc = push_struct(memory, typeof(*frc));
frc->kind = BeamformerFileReloadKind_ComputeShader;
frc->shader_reload.shader = beamformer_reloadable_shader_kinds[index];
os_add_file_watch((char *)file.data, file.length, frc);
}
for EachElement(beamformer_reloadable_compute_helpers_shader_info_indices, it) {
- i32 index = beamformer_reloadable_compute_helpers_shader_info_indices[it];
- Arena temp = scratch;
- str8 file = push_str8_from_parts(&temp, os_path_separator(), str8("shaders"),
- beamformer_reloadable_shader_files[index][0]);
- BeamformerFileReloadContext *frc = push_struct(&memory, typeof(*frc));
+ i32 index = beamformer_reloadable_compute_helpers_shader_info_indices[it];
+ str8 file = push_str8_from_parts(scratch, os_path_separator(), str8("shaders"),
+ beamformer_reloadable_shader_files[index][0]);
+ BeamformerFileReloadContext *frc = push_struct(memory, typeof(*frc));
frc->kind = BeamformerFileReloadKind_ComputeShader;
frc->shader_reload.shader = beamformer_reloadable_shader_kinds[index];
os_add_file_watch((char *)file.data, file.length, frc);
}
}
- memory.end = scratch.end;
- ctx->arena = memory;
+ arena_destroy(scratch);
+
ctx->state = BeamformerState_Running;
+
+ return ctx;
}
BEAMFORMER_EXPORT void
-beamformer_terminate(BeamformerInput *input)
+beamformer_terminate(void *memory, BeamformerInput *input)
{
/* NOTE(rnp): work around pebkac when the beamformer is closed while we are doing live
* imaging. if the verasonics is blocked in an external function (calling the library
@@ -361,8 +353,8 @@ beamformer_terminate(BeamformerInput *input)
* into an error state and release dispatch lock so that future calls will error instead
* of blocking.
*/
- BeamformerCtx * ctx = BeamformerContextMemory(input->memory);
- BeamformerSharedMemory * sm = input->shared_memory;
+ BeamformerCtx *ctx = memory;
+ BeamformerSharedMemory *sm = input->shared_memory;
if (ctx->state != BeamformerState_Terminated) {
if (sm) {
BeamformerSharedMemoryLockKind lock = BeamformerSharedMemoryLockKind_DispatchCompute;
@@ -382,10 +374,10 @@ beamformer_terminate(BeamformerInput *input)
}
BEAMFORMER_EXPORT u32
-beamformer_should_close(BeamformerInput *input)
+beamformer_should_close(void *memory, BeamformerInput *input)
{
- BeamformerCtx * ctx = BeamformerContextMemory(input->memory);
+ BeamformerCtx *ctx = memory;
if (ctx->state == BeamformerState_ShouldClose)
- beamformer_terminate(input);
+ beamformer_terminate(memory, input);
return ctx->state == BeamformerState_Terminated;
}
diff --git a/beamformer.h b/beamformer.h
@@ -85,6 +85,12 @@ typedef struct {
BEAMFORMER_IMPORT OSSystemInfo * os_system_info(void);
+BEAMFORMER_IMPORT void * os_memory_reserve(uint64_t size);
+BEAMFORMER_IMPORT void os_memory_release(void *base, uint64_t size);
+BEAMFORMER_IMPORT uint32_t os_memory_commit(void *base, uint64_t size);
+BEAMFORMER_IMPORT void os_memory_uncommit(void *base, uint64_t size);
+BEAMFORMER_IMPORT void os_memory_seal(void *base, uint64_t size);
+
BEAMFORMER_IMPORT OSThread os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn);
BEAMFORMER_IMPORT OSBarrier os_barrier_alloc(uint32_t thread_count);
BEAMFORMER_IMPORT void os_barrier_enter(OSBarrier);
@@ -317,13 +323,6 @@ typedef struct {
} BeamformerInputEvent;
typedef struct {
- /* NOTE(rnp): besides vulkan library code the beamformer will not allocate memory on its
- * own. Recommended minimum size is 16MB. If shared memory is not provided it is recommended
- * to increase this to at least 1GB to help facilitate loading of external data files (not yet
- * implemented). */
- void * memory;
- uint64_t memory_size;
-
/* NOTE(rnp): beamformer will use this to communicate with external processes. While it
* it won't be required in the future it is currently the only way to load data.
* Recommended size is 2-4GB. Currently this size will also limit the size of any data
@@ -355,28 +354,29 @@ typedef struct {
#endif
} BeamformerInput;
-BEAMFORMER_EXPORT void beamformer_init(BeamformerInput *);
+// NOTE(rnp): returns the beamformer's memory, to be passed as part of input.
+BEAMFORMER_EXPORT void *beamformer_init(BeamformerInput *);
/* NOTE(rnp): while the platform can also decide to terminate the beamformer,
* the beamformer itself may indicate that it wants to terminate. If the
* beamformer itself decides to terminate it is unnecessary to call
* `beamformer_terminate()` but it will act as a NOP if you do. */
-BEAMFORMER_EXPORT uint32_t beamformer_should_close(BeamformerInput *);
+BEAMFORMER_EXPORT uint32_t beamformer_should_close(void *memory, BeamformerInput *);
/* IMPORTANT(rnp): since the beamformer may be interacting with external hardware
* it is critical that the platform calls this when it wishes to terminate the
* beamformer. Otherwise the external hardware may be left in a bad state and require
* a reboot. The beamformer will not waste time releasing resources unless it was
* compiled with BEAMFORMER_DEBUG enabled (useful for address sanitizer). */
-BEAMFORMER_EXPORT void beamformer_terminate(BeamformerInput *);
+BEAMFORMER_EXPORT void beamformer_terminate(void *memory, BeamformerInput *);
#if !BEAMFORMER_DEBUG
-BEAMFORMER_EXPORT void beamformer_frame_step(BeamformerInput *);
+BEAMFORMER_EXPORT void beamformer_frame_step(void *memory, BeamformerInput *);
#endif
#if BEAMFORMER_DEBUG
-BEAMFORMER_EXPORT void beamformer_debug_hot_release(BeamformerInput *);
-BEAMFORMER_EXPORT void beamformer_debug_hot_reload(OSLibrary new_library, BeamformerInput *);
+BEAMFORMER_EXPORT void beamformer_debug_hot_release(void *memory, BeamformerInput *);
+BEAMFORMER_EXPORT void beamformer_debug_hot_reload(OSLibrary new_library);
#endif
#endif /*BEAMFORMER_H */
diff --git a/beamformer_core.c b/beamformer_core.c
@@ -75,7 +75,7 @@ global BeamformerCtx *beamformer_context;
global BeamformerInput *beamformer_input;
global f32 dt_for_frame;
-#define beamformer_frame_arena() (beamformer_context->frame_arenas + beamformer_context->frame_index % countof(beamformer_context->frame_arenas))
+#define beamformer_frame_arena() (beamformer_context->frame_arenas[beamformer_context->frame_index % countof(beamformer_context->frame_arenas)])
#define beamformer_registers() (&beamformer_context->registers->v)
#define beamformer_push_registers(...) beamformer_push_registers_(&(BeamformerRegisters){beamformer_registers_init_literal __VA_ARGS__})
#define BeamformerRegistersScope(...) DeferLoop(beamformer_push_registers(__VA_ARGS__), beamformer_pop_registers())
@@ -191,7 +191,7 @@ beamformer_compute_plan_for_block(BeamformerComputeContext *cc, u32 block, Arena
result->ui_voxel_transform = m4_identity();
- Stream label = arena_stream(*arena);
+ Stream label = arena_stream(arena);
stream_append_str8(&label, str8("ComputeParameterArray["));
stream_append_u64(&label, block);
stream_append_str8(&label, str8("]"));
@@ -209,8 +209,9 @@ beamformer_compute_plan_for_block(BeamformerComputeContext *cc, u32 block, Arena
}
function void
-beamformer_filter_update(BeamformerFilter *f, BeamformerFilterParameters fp, u32 block, u32 slot, Arena arena)
+beamformer_filter_update(BeamformerFilter *f, BeamformerFilterParameters fp, u32 block, u32 slot, Arena *arena)
{
+ Temp scratch = temp_begin(arena);
Stream sb = arena_stream(arena);
stream_append_str8s(&sb,
beamformer_filter_kind_strings[fp.kind % countof(beamformer_filter_kind_strings)],
@@ -219,14 +220,14 @@ beamformer_filter_update(BeamformerFilter *f, BeamformerFilterParameters fp, u32
stream_append_str8(&sb, str8("]["));
stream_append_u64(&sb, slot);
stream_append_byte(&sb, ']');
- str8 label = arena_stream_commit(&arena, &sb);
+ str8 label = arena_stream_commit(arena, &sb);
void *filter = 0;
switch (fp.kind) {
case BeamformerFilterKind_Kaiser:{
/* TODO(rnp): this should also support complex */
/* TODO(rnp): implement this as an IFIR filter instead to reduce computation */
- filter = kaiser_low_pass_filter(&arena, fp.kaiser.cutoff_frequency, fp.sampling_frequency,
+ filter = kaiser_low_pass_filter(arena, fp.kaiser.cutoff_frequency, fp.sampling_frequency,
fp.kaiser.beta, (i32)fp.kaiser.length);
f->length = (i32)fp.kaiser.length;
f->time_delay = (f32)f->length / 2.0f / fp.sampling_frequency;
@@ -236,10 +237,10 @@ beamformer_filter_update(BeamformerFilter *f, BeamformerFilterParameters fp, u32
f32 fs = fp.sampling_frequency;
f->length = (i32)(mc->duration * fs);
if (fp.complex) {
- filter = baseband_chirp(&arena, mc->min_frequency, mc->max_frequency, fs, f->length, 1, 0.5f);
+ filter = baseband_chirp(arena, mc->min_frequency, mc->max_frequency, fs, f->length, 1, 0.5f);
f->time_delay = complex_filter_first_moment(filter, f->length, fs);
} else {
- filter = rf_chirp(&arena, mc->min_frequency, mc->max_frequency, fs, f->length, 1);
+ filter = rf_chirp(arena, mc->min_frequency, mc->max_frequency, fs, f->length, 1);
f->time_delay = real_filter_first_moment(filter, f->length, fs);
}
}break;
@@ -258,6 +259,8 @@ beamformer_filter_update(BeamformerFilter *f, BeamformerFilterParameters fp, u32
vk_buffer_allocate(&f->buffer, &allocate_info);
}
vk_buffer_range_upload(&f->buffer, filter, 0, byte_size, 0);
+
+ temp_end(scratch);
}
function iv3
@@ -271,9 +274,9 @@ das_valid_points(iv3 points)
}
function void
-beamformer_update_hadamard(BeamformerComputePlan *cp, i32 order, b32 row_major, Arena arena, b32 das_matrix)
+beamformer_update_hadamard(BeamformerComputePlan *cp, i32 order, b32 row_major, b32 das_matrix, Arena *arena)
{
- f16 *hadamard = make_hadamard_transpose(&arena, order, row_major);
+ f16 *hadamard = make_hadamard_transpose(arena, order, row_major);
if (hadamard) {
u64 offset = das_matrix ? offsetof(BeamformerComputeArrayParameters, DasHadamard)
: offsetof(BeamformerComputeArrayParameters, DecodeHadamard);
@@ -407,7 +410,7 @@ push_compute_graph_node(BeamformerComputeGraph *graph, BeamformerShaderKind kind
}
function void
-plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, Arena scratch)
+plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, Arena *scratch)
{
b32 run_hilbert = 0;
b32 demodulate = 0;
@@ -465,7 +468,7 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A
//////////////////////////////////////
// NOTE(rnp): First Pass: build initial graph and insert hard layout constraints
BeamformerComputeGraph graph = {0};
- BeamformerComputeGraphNode *root_node = push_compute_graph_node(&graph, BeamformerShaderKind_Count, &scratch);
+ BeamformerComputeGraphNode *root_node = push_compute_graph_node(&graph, BeamformerShaderKind_Count, scratch);
root_node->input_data_kind = input_data_kind;
root_node->input_stride.x = 1; // Sample Stride
root_node->input_stride.y = pb->parameters.sample_count * acquisition_count; // Channel Stride
@@ -495,7 +498,7 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A
default:{}break;
}
- BeamformerComputeGraphNode *node = push_compute_graph_node(&graph, pb->pipeline.shaders[it], &scratch);
+ BeamformerComputeGraphNode *node = push_compute_graph_node(&graph, pb->pipeline.shaders[it], scratch);
node->user_pipeline_index = (i32)it;
switch (pb->pipeline.shaders[it]) {
case BeamformerShaderKind_Decode:{
@@ -532,7 +535,7 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A
// NOTE(rnp): insert implicit CoherencyWeighting node
if (pb->parameters.coherency_weighting)
- node = push_compute_graph_node(&graph, BeamformerShaderKind_CoherencyWeighting, &scratch);
+ node = push_compute_graph_node(&graph, BeamformerShaderKind_CoherencyWeighting, scratch);
}break;
default:{}break;
@@ -580,7 +583,7 @@ plan_compute_pipeline(BeamformerComputePlan *cp, BeamformerParameterBlock *pb, A
// NOTE(rnp): insert reshape if needed
if (needs_reshape) {
- BeamformerComputeGraphNode *new = push_compute_graph_node(0, BeamformerShaderKind_Reshape, &scratch);
+ BeamformerComputeGraphNode *new = push_compute_graph_node(0, BeamformerShaderKind_Reshape, scratch);
BeamformerComputeGraphNode *last = node->prev;
DLLInsertLast(0, node, last, new, next, prev);
graph.count++;
@@ -913,7 +916,7 @@ stream_append_shader_header(Stream *s, i32 reloadable_index, BeamformerShaderDes
}
function void
-beamformer_reload_pipeline(VulkanHandle *pipeline, BeamformerShaderReloadInfo *sris, u32 count, Arena arena)
+beamformer_reload_pipeline(VulkanHandle *pipeline, BeamformerShaderReloadInfo *sris, u32 count, Arena *scratch)
{
assume(count <= 2);
str8 paths[2];
@@ -921,12 +924,12 @@ beamformer_reload_pipeline(VulkanHandle *pipeline, BeamformerShaderReloadInfo *s
if (!BakeShaders) {
for (u32 i = 0; i < count; i++)
- paths[i] = push_str8_from_parts(&arena, os_path_separator(), str8("shaders"), sris[i].filename_or_data);
+ paths[i] = push_str8_from_parts(scratch, os_path_separator(), str8("shaders"), sris[i].filename_or_data);
}
u32 push_constants_size = 0;
for (u32 i = 0; i < count; i++) {
- Stream shader_stream = arena_stream(arena);
+ Stream shader_stream = arena_stream(scratch);
i32 reloadable_index = beamformer_shader_reloadable_index_by_shader[sris[i].shader];
if (i == 0) push_constants_size = beamformer_shader_push_constant_sizes[reloadable_index];
else assert(push_constants_size == beamformer_shader_push_constant_sizes[reloadable_index]);
@@ -942,7 +945,7 @@ beamformer_reload_pipeline(VulkanHandle *pipeline, BeamformerShaderReloadInfo *s
}
infos[i].kind = sris[i].shader_kind;
- infos[i].text = arena_stream_commit_zero(&arena, &shader_stream);
+ infos[i].text = arena_stream_commit_zero(scratch, &shader_stream);
infos[i].name = beamformer_shader_names[sris[i].shader];
infos[i].specialization_data = sris[i].shader_descriptor ? &sris[i].shader_descriptor->bake : 0;
infos[i].specialization_struct_id = beamformer_base_shader_to_bake_struct_id[reloadable_index];
@@ -962,7 +965,7 @@ beamformer_reload_pipeline(VulkanHandle *pipeline, BeamformerShaderReloadInfo *s
}
function void
-beamformer_reload_render_pipeline(VulkanHandle *pipeline, BeamformerShaderKind shader, Arena arena)
+beamformer_reload_render_pipeline(VulkanHandle *pipeline, BeamformerShaderKind shader, Arena *scratch)
{
i32 index = beamformer_shader_reloadable_index_by_shader[shader];
BeamformerShaderReloadInfo infos[2] = {
@@ -979,12 +982,12 @@ beamformer_reload_render_pipeline(VulkanHandle *pipeline, BeamformerShaderKind s
: beamformer_reloadable_shader_files[index][1],
},
};
- beamformer_reload_pipeline(pipeline, infos, countof(infos), arena);
+ beamformer_reload_pipeline(pipeline, infos, countof(infos), scratch);
}
function void
beamformer_reload_compute_pipeline(VulkanHandle *pipeline, BeamformerShaderKind shader,
- BeamformerShaderDescriptor *shader_descriptor, Arena arena)
+ BeamformerShaderDescriptor *shader_descriptor, Arena *scratch)
{
i32 index = beamformer_shader_reloadable_index_by_shader[shader];
uv3 layout = shader_descriptor ? shader_descriptor->layout : (uv3){{vk_gpu_info()->subgroup_size, 1, 1}};
@@ -996,11 +999,11 @@ beamformer_reload_compute_pipeline(VulkanHandle *pipeline, BeamformerShaderKind
: beamformer_reloadable_shader_files[index][0],
.layout = layout,
};
- beamformer_reload_pipeline(pipeline, &info, 1, arena);
+ beamformer_reload_pipeline(pipeline, &info, 1, scratch);
}
function void
-beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp, u32 block, Arena arena)
+beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp, u32 block, Arena *scratch)
{
BeamformerParameterBlock *pb;
DeferLoop(pb = beamformer_parameter_block_lock(ctx->shared_memory, block, -1),
@@ -1019,7 +1022,7 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp,
cp->output_points = das_valid_points(pb->parameters.output_points.xyz);
cp->average_frames = pb->parameters.output_points.E[3];
- plan_compute_pipeline(cp, pb, arena);
+ plan_compute_pipeline(cp, pb, scratch);
/* NOTE(rnp): these are both handled by plan_compute_pipeline() */
u32 mask = 1 << BeamformerParameterBlockRegion_ComputePipeline |
@@ -1066,10 +1069,9 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp,
if (pb->parameters.decode_mode != BeamformerDecodeMode_None &&
cp->hadamard_order != (i32)cp->acquisition_count)
{
- beamformer_update_hadamard(cp, (i32)cp->acquisition_count, vk_gpu_info()->cooperative_matrix, arena, false);
-
+ beamformer_update_hadamard(cp, (i32)cp->acquisition_count, vk_gpu_info()->cooperative_matrix, 0, scratch);
if (pb->parameters.readi_group_count > 1)
- beamformer_update_hadamard(cp, (i32)pb->parameters.readi_group_count, false, arena, true);
+ beamformer_update_hadamard(cp, (i32)pb->parameters.readi_group_count, 0, 1, scratch);
}
}break;
@@ -1082,8 +1084,7 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp,
u64 offset = beamformer_compute_array_parameter_offsets[kind];
u64 size = beamformer_compute_array_parameter_sizes[kind];
{
- Arena scratch = arena;
- u16 *u16s = push_array(&scratch, u16, countof(pb->transmit_receive_orientations));
+ u16 *u16s = push_array(scratch, u16, countof(pb->transmit_receive_orientations));
for (u32 i = 0; i < countof(pb->transmit_receive_orientations); i++)
u16s[i] = pb->transmit_receive_orientations[i];
@@ -1117,7 +1118,7 @@ beamformer_commit_parameter_block(BeamformerCtx *ctx, BeamformerComputePlan *cp,
function void
do_compute_shader(BeamformerCtx *ctx, VulkanHandle cmd, BeamformerComputePlan *cp, BeamformerFrame *frame,
- u32 shader_slot, u32 channel_offset, u64 rf_pointer, Arena arena)
+ u32 shader_slot, u32 channel_offset, u64 rf_pointer)
{
BeamformerComputeContext *cc = &ctx->compute_context;
@@ -1435,7 +1436,7 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
BeamformerFrameBacklog *bl = &ctx->compute_context.backlog;
u32 req_count = Clamp(ec->count, 1, bl->counter);
u32 frame_idx = bl->counter - req_count;
- u8 *sm_output = beamformer_shared_memory_scratch_arena(sm, ctx->shared_memory_size).beg;
+ u8 *sm_output = beamformer_shared_memory_data_pointer(sm, ctx->shared_memory_size);
u64 exported_size = 0;
for (u32 export_count = 0; export_count < req_count; export_count++, frame_idx++) {
BeamformerFrame *f = bl->frames + frame_idx % countof(bl->frames);
@@ -1458,7 +1459,7 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
spin_wait(table->write_index != atomic_load_u32(&table->read_index));
ComputeShaderStats *stats = ctx->compute_shader_stats;
if (sizeof(stats->table) <= ec->size)
- memory_copy(beamformer_shared_memory_scratch_arena(sm, ctx->shared_memory_size).beg,
+ memory_copy(beamformer_shared_memory_data_pointer(sm, ctx->shared_memory_size),
&stats->table, sizeof(stats->table));
}break;
InvalidDefaultCase;
@@ -1473,7 +1474,7 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
u32 block = fctx->parameter_block;
u32 slot = fctx->filter_slot;
BeamformerComputePlan *cp = beamformer_compute_plan_for_block(cs, block, arena);
- beamformer_filter_update(cp->filters + slot, fctx->parameters, block, slot, *arena);
+ beamformer_filter_update(cp->filters + slot, fctx->parameters, block, slot, arena);
}break;
case BeamformerWorkKind_ComputeIndirect:
@@ -1485,7 +1486,9 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
BeamformerComputePlan *cp = beamformer_compute_plan_for_block(cs, work->compute_context.parameter_block, arena);
if unlikely(beamformer_parameter_block_dirty(sm, work->compute_context.parameter_block)) {
u32 block = work->compute_context.parameter_block;
- beamformer_commit_parameter_block(ctx, cp, block, *arena);
+ Temp scratch = temp_begin(arena);
+ beamformer_commit_parameter_block(ctx, cp, block, arena);
+ temp_end(scratch);
}
post_sync_barrier(ctx->shared_memory, BeamformerSharedMemoryLockKind_DispatchCompute);
@@ -1495,9 +1498,11 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
if unlikely(dirty_programs) {
for EachBit(dirty_programs, slot) {
assert(slot < BeamformerMaxComputeShaderStages);
+ Temp scratch = temp_begin(arena);
beamformer_reload_compute_pipeline(cp->vulkan_pipelines + slot,
cp->pipeline.shaders[slot],
- cp->shader_descriptors + slot, *arena);
+ cp->shader_descriptors + slot, arena);
+ temp_end(scratch);
}
}
@@ -1573,13 +1578,13 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
u64 rf_pointer = rf->buffer.gpu_pointer + slot * rf->active_rf_size;
rf_pointer += cp->raw_channel_byte_stride * channel_offset;
for (u32 i = 0; i < cp->first_image_shader_index; i++) {
- do_compute_shader(ctx, cmd, cp, frame, i, channel_offset, rf_pointer, *arena);
+ do_compute_shader(ctx, cmd, cp, frame, i, channel_offset, rf_pointer);
vk_command_timestamp(cmd);
}
}
for (u32 i = cp->first_image_shader_index; i < cp->pipeline.shader_count; i++) {
- do_compute_shader(ctx, cmd, cp, frame, i, 0, 0, *arena);
+ do_compute_shader(ctx, cmd, cp, frame, i, 0, 0);
vk_command_timestamp(cmd);
}
@@ -1591,10 +1596,11 @@ complete_queue(BeamformerCtx *ctx, BeamformWorkQueue *q, Arena *arena)
atomic_store_u64(&frame->timeline_valid_value, end_timeline_value);
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(arena), temp_end(scratch))
{
- Arena scratch = *arena;
/* NOTE(rnp): this blocks until work completes */
- u64 *timestamps = vk_command_read_timestamps(VulkanTimeline_Compute, &scratch);
+ u64 *timestamps = vk_command_read_timestamps(VulkanTimeline_Compute, arena);
i32 steps = ((i32)cp->channel_count / BeamformerChunkChannelCount) - 1;
i32 step = 0;
@@ -1746,7 +1752,7 @@ DEBUG_EXPORT BEAMFORMER_RF_UPLOAD_FN(beamformer_rf_upload)
spin_wait(atomic_load_u64(&rf->compute_index) < rf->insertion_index);
vk_host_wait_timeline(VulkanTimeline_Compute, rf->compute_complete_values[slot], -1ULL);
- vk_buffer_range_upload(&rf->buffer, beamformer_shared_memory_scratch_arena(sm, ctx->shared_memory_size).beg,
+ vk_buffer_range_upload(&rf->buffer, beamformer_shared_memory_data_pointer(sm, ctx->shared_memory_size),
slot * rf->active_rf_size, rf->active_rf_size, 1);
store_fence();
@@ -1803,7 +1809,7 @@ beamformer_process_input_events(BeamformerCtx *ctx, BeamformerInput *input,
{}break;
case BeamformerInputEventKind_ExecutableReload:{
- ui_init(ctx, ctx->ui_backing_store);
+ ui_init(ctx, ctx->ui_arena);
}break;
case BeamformerInputEventKind_FileEvent:{
@@ -1869,9 +1875,9 @@ beamformer_panel_group_insert_at(BeamformerUIPanel *group, BeamformerUIPanel *ta
}
BEAMFORMER_EXPORT void
-beamformer_frame_step(BeamformerInput *input)
+beamformer_frame_step(void *memory, BeamformerInput *input)
{
- BeamformerCtx *ctx = beamformer_context = BeamformerContextMemory(input->memory);
+ BeamformerCtx *ctx = beamformer_context = memory;
beamformer_input = input;
u64 current_time = os_timer_count();
@@ -1887,7 +1893,7 @@ beamformer_frame_step(BeamformerInput *input)
swap(ctx->command_queues[0], ctx->command_queues[1]);
zero_struct(ctx->command_queues + 0);
//zero_struct(ctx->registers);
- end_temp_arena(ctx->frame_arena_savepoints[ctx->frame_index % countof(ctx->frame_arenas)]);
+ arena_clear(beamformer_frame_arena());
}
beamformer_process_input_events(ctx, input, input->event_queue, input->event_count);
diff --git a/beamformer_internal.h b/beamformer_internal.h
@@ -144,7 +144,7 @@ typedef struct {
///////////////////////////
// NOTE: vulkan layer API
-DEBUG_IMPORT void vk_load(OSLibrary vulkan, Arena *memory, Stream *error);
+DEBUG_IMPORT void vk_load(OSLibrary vulkan, Stream *error);
DEBUG_IMPORT GPUInfo *vk_gpu_info(void);
@@ -457,12 +457,11 @@ typedef struct {
} BeamformerComputeContext;
typedef struct {
- OSThread handle;
-
- Arena arena;
- iptr user_context;
- i32 sync_variable;
- b32 awake;
+ Arena *arena;
+ iptr user_context;
+ i32 sync_variable;
+ b32 awake;
+ OSThread handle;
} GLWorkerThreadContext;
typedef struct {
@@ -606,15 +605,14 @@ typedef struct {
iv2 window_size;
- Arena arena;
- Arena ui_backing_store;
+ Arena *arena;
+ Arena *ui_arena;
void *ui;
u32 ui_dirty_parameter_blocks;
- u64 frame_timestamp;
- u64 frame_index;
- Arena frame_arenas[2];
- TempArena frame_arena_savepoints[2];
+ u64 frame_timestamp;
+ u64 frame_index;
+ Arena *frame_arenas[2];
BeamformerUIPanel *auto_live_control_panel;
u64 live_imaging_active_frame;
@@ -652,7 +650,6 @@ typedef struct {
// TODO(rnp): this should go to the UI eventually
OSWindow main_window;
} BeamformerCtx;
-#define BeamformerContextMemory(m) (BeamformerCtx *)align_pointer_up((m), alignof(BeamformerCtx));
typedef enum {
BeamformerFileReloadKind_ComputeInternalShader,
diff --git a/beamformer_shared_memory.c b/beamformer_shared_memory.c
@@ -47,11 +47,10 @@ typedef struct {
BeamformerWorkKind kind;
BeamformerSharedMemoryLockKind lock;
union {
- void *generic;
- BeamformerComputeWorkContext compute_context;
- BeamformerCreateFilterContext create_filter_context;
- BeamformerExportContext export_context;
- BeamformerShaderKind reload_shader;
+ BeamformerComputeWorkContext compute_context;
+ BeamformerCreateFilterContext create_filter_context;
+ BeamformerExportContext export_context;
+ BeamformerShaderKind reload_shader;
};
} BeamformWork;
@@ -278,13 +277,22 @@ beamformer_parameter_block_unlock(BeamformerSharedMemory *sm, u32 block)
beamformer_shared_memory_release_lock(sm, BeamformerSharedMemoryLockKind_Count + block);
}
-function Arena
+function Arena *
beamformer_shared_memory_scratch_arena(BeamformerSharedMemory *sm, i64 shared_memory_size)
{
assert(sm->reserved_parameter_blocks > 0);
BeamformerParameterBlock *last = beamformer_parameter_block(sm, sm->reserved_parameter_blocks - 1);
- Arena result = {.beg = (u8 *)(last + 1), .end = (u8 *)sm + shared_memory_size};
- result.beg = arena_aligned_start(result, KB(4));
+ u64 size = (u64)((u8 *)sm + shared_memory_size - (u8 *)(last + 1));
+ Arena *result = arena_create(.optional_backing_store = (last + 1), .reserve_size = size, .commit_size = size, .flags = ArenaFlag_NoChain);
+ arena_pre_align(result, KB(4));
+ return result;
+}
+
+function void *
+beamformer_shared_memory_data_pointer(BeamformerSharedMemory *sm, i64 shared_memory_size)
+{
+ Arena *arena = beamformer_shared_memory_scratch_arena(sm, shared_memory_size);
+ void *result = (u8 *)arena + arena->position;
return result;
}
diff --git a/build.c b/build.c
@@ -8,6 +8,7 @@
* [ ]: seperate dwarf debug info
*/
+#define BEAMFORMER_IMPORT function
#include "util.h"
#include <stdarg.h>
@@ -50,8 +51,6 @@ global char *g_argv0;
#define is_gcc COMPILER_GCC
#define is_msvc COMPILER_MSVC
-#define BEAMFORMER_IMPORT function
-
#if OS_LINUX
#include <dirent.h>
@@ -191,15 +190,6 @@ build_fatal_(char *format, ...)
os_exit(1);
}
-function str8
-read_entire_file(const char *file, Arena *arena)
-{
- str8 result = {0};
- result.length = os_read_entire_file(file, arena->beg, arena_capacity(arena, u8));
- if (result.length > 0) result.data = arena_commit(arena, result.length);
- return result;
-}
-
function b32
str8_contains(str8 s, u8 byte)
{
@@ -297,6 +287,31 @@ os_remove_directory_(i32 base_fd, char *name)
return result;
}
+function str8
+os_read_file_into_arena(const char *name, Arena *arena)
+{
+ str8 result = {0};
+ struct stat sb;
+ i32 fd = open(name, O_RDONLY);
+ if (fd >= 0 && fstat(fd, &sb) >= 0) {
+ result.data = push_array_no_zero(arena, u8, sb.st_size);
+ result.length = sb.st_size;
+ i64 total_read = 0;
+ do {
+ i64 rlen = read(fd, (u8 *)result.data + total_read, (u64)(result.length - total_read));
+ if (rlen > 0) total_read += rlen;
+ } while (total_read != result.length && errno != EINTR);
+
+ if (total_read != result.length) {
+ arena_pop(arena, result.length);
+ result = (str8){0};
+ }
+ }
+ if (fd >= 0) close(fd);
+
+ return result;
+}
+
function u64
os_get_filetime(char *file)
{
@@ -394,6 +409,30 @@ os_make_directory(char *name)
CreateDirectoryA(name, 0);
}
+function str8
+os_read_file_into_arena(const char *name, Arena *arena)
+{
+ str8 result = {0};
+ w32_file_info fileinfo;
+ iptr h = CreateFileA((c8 *)name, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
+ if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) {
+ u64 filesize = (i64)fileinfo.nFileSizeHigh << 32;
+ filesize |= (i64)fileinfo.nFileSizeLow;
+ if (filesize <= S32_MAX) {
+ result.data = push_array_no_zero(arena, u8, filesize);
+ result.length = filesize;
+ i32 rlen = 0;
+ if (!ReadFile(h, result.data, (i32)filesize, &rlen, 0) || rlen != filesize) {
+ arena_pop(arena, filesize);
+ result = (str8){0};
+ }
+ }
+ }
+ if (h >= 0) CloseHandle(h);
+
+ return result;
+}
+
function b32
os_remove_directory(char *name)
{
@@ -506,6 +545,12 @@ os_wait_close_process(iptr handle)
#endif
+function str8
+read_entire_file(const char *file, Arena *arena)
+{
+ return os_read_file_into_arena(file, arena);
+}
+
#define needs_rebuild(b, ...) needs_rebuild_(b, ((char *[]){__VA_ARGS__}), \
(sizeof((char *[]){__VA_ARGS__}) / sizeof(char *)))
function b32
@@ -522,7 +567,7 @@ needs_rebuild_(char *binary, char *deps[], i64 deps_count)
}
function b32
-run_synchronous(Arena a, CommandList *command)
+run_synchronous(Arena *a, CommandList *command)
{
Stream sb = arena_stream(a);
stream_push_command(&sb, command);
@@ -569,24 +614,24 @@ cmd_base(Arena *a, CommandList *c, b32 cpp, b32 debug)
}
function void
-check_rebuild_self(Arena arena, i32 argc, char *argv[])
+check_rebuild_self(Arena *arena, i32 argc, char *argv[])
{
char *binary = shift(argv, argc);
if (needs_rebuild(binary, __FILE__, "meta.h", "os_win32.c", "os_linux.c", "util.c", "util.h")) {
Stream name_buffer = arena_stream(arena);
stream_append_str8s(&name_buffer, str8_from_c_str(binary), str8(".old"));
- char *old_name = (char *)arena_stream_commit_zero(&arena, &name_buffer).data;
+ char *old_name = (char *)arena_stream_commit_zero(arena, &name_buffer).data;
if (!os_rename_file(binary, old_name))
build_fatal("failed to move: %s -> %s", binary, old_name);
CommandList c = {0};
- cmd_base(&arena, &c, 0, 0);
- cmd_append(&arena, &c, EXTRA_FLAGS);
- if (!is_msvc) cmd_append(&arena, &c, "-Wno-unused-function");
- cmd_append(&arena, &c, __FILE__, OUTPUT_EXE(binary));
- if (is_msvc) cmd_append(&arena, &c, "/link", "-incremental:no", "-opt:ref");
- cmd_append(&arena, &c, (void *)0);
+ cmd_base(arena, &c, 0, 0);
+ cmd_append(arena, &c, EXTRA_FLAGS);
+ if (!is_msvc) cmd_append(arena, &c, "-Wno-unused-function");
+ cmd_append(arena, &c, __FILE__, OUTPUT_EXE(binary));
+ if (is_msvc) cmd_append(arena, &c, "/link", "-incremental:no", "-opt:ref");
+ cmd_append(arena, &c, (void *)0);
if (!run_synchronous(arena, &c)) {
os_rename_file(old_name, binary);
build_fatal("failed to rebuild self");
@@ -594,9 +639,9 @@ check_rebuild_self(Arena arena, i32 argc, char *argv[])
os_remove_file(old_name);
c.count = 0;
- cmd_append(&arena, &c, binary);
- cmd_append_count(&arena, &c, argv, argc);
- cmd_append(&arena, &c, (void *)0);
+ cmd_append(arena, &c, binary);
+ cmd_append_count(arena, &c, argv, argc);
+ cmd_append(arena, &c, (void *)0);
if (!run_synchronous(arena, &c))
os_exit(1);
@@ -649,7 +694,7 @@ cmd_pdb(Arena *a, CommandList *cmd, char *name)
if (is_w32 && is_clang) {
cmd_append(a, cmd, "-fuse-ld=lld", "-g", "-gcodeview", "-Wl,--pdb=");
} else if (is_msvc) {
- Stream sb = arena_stream(*a);
+ Stream sb = arena_stream(a);
stream_append_str8s(&sb, str8("-PDB:"), str8_from_c_str(name), str8(".pdb"));
char *pdb = (char *)arena_stream_commit_zero(a, &sb).data;
cmd_append(a, cmd, "/link", "-incremental:no", "-opt:ref", "-DEBUG", pdb);
@@ -657,67 +702,67 @@ cmd_pdb(Arena *a, CommandList *cmd, char *name)
}
function void
-git_submodule_update(Arena a, char *name)
+git_submodule_update(Arena *a, char *name)
{
Stream sb = arena_stream(a);
stream_append_str8s(&sb, str8_from_c_str(name), str8(OS_PATH_SEPARATOR), str8(".git"));
- arena_stream_commit_zero(&a, &sb);
+ arena_stream_commit_zero(a, &sb);
CommandList git = {0};
/* NOTE(rnp): cryptic bs needed to get a simple exit code if name is dirty */
- cmd_append(&a, &git, "git", "diff-index", "--quiet", "HEAD", "--", name, (void *)0);
+ cmd_append(a, &git, "git", "diff-index", "--quiet", "HEAD", "--", name, (void *)0);
if (!os_file_exists((c8 *)sb.data) || !run_synchronous(a, &git)) {
git.count = 1;
- cmd_append(&a, &git, "submodule", "update", "--init", "--depth=1", name, (void *)0);
+ cmd_append(a, &git, "submodule", "update", "--init", "--depth=1", name, (void *)0);
if (!run_synchronous(a, &git))
build_fatal("failed to clone required module: %s", name);
}
}
function b32
-build_shared_library(Arena a, CommandList cc, char *name, char *output, char **libs, i64 libs_count, char **srcs, i64 srcs_count)
+build_shared_library(Arena *a, CommandList cc, char *name, char *output, char **libs, i64 libs_count, char **srcs, i64 srcs_count)
{
- cmd_append_count(&a, &cc, srcs, srcs_count);
- cmd_append(&a, &cc, OUTPUT_DLL(output));
- cmd_pdb(&a, &cc, name);
- cmd_append_count(&a, &cc, libs, libs_count);
- cmd_append(&a, &cc, (void *)0);
+ cmd_append_count(a, &cc, srcs, srcs_count);
+ cmd_append(a, &cc, OUTPUT_DLL(output));
+ cmd_pdb(a, &cc, name);
+ cmd_append_count(a, &cc, libs, libs_count);
+ cmd_append(a, &cc, (void *)0);
b32 result = run_synchronous(a, &cc);
if (!result) build_log_failure("%s", output);
return result;
}
function b32
-cc_single_file(Arena a, CommandList cc, char *exe, char *src, char *dest, char **tail, i64 tail_count)
+cc_single_file(Arena *a, CommandList cc, char *exe, char *src, char *dest, char **tail, i64 tail_count)
{
char *executable[] = {src, is_msvc? "/Fe:" : "-o", dest};
char *object[] = {is_msvc? "/c" : "-c", src, is_msvc? "/Fo:" : "-o", dest};
- cmd_append_count(&a, &cc, exe? executable : object,
+ cmd_append_count(a, &cc, exe? executable : object,
exe? countof(executable) : countof(object));
- if (exe) cmd_pdb(&a, &cc, exe);
- cmd_append_count(&a, &cc, tail, tail_count);
- cmd_append(&a, &cc, (void *)0);
+ if (exe) cmd_pdb(a, &cc, exe);
+ cmd_append_count(a, &cc, tail, tail_count);
+ cmd_append(a, &cc, (void *)0);
b32 result = run_synchronous(a, &cc);
if (!result) build_log_failure("%s", dest);
return result;
}
function b32
-build_static_library_from_objects(Arena a, char *name, char **flags, i64 flags_count, char **objects, i64 count)
+build_static_library_from_objects(Arena *a, char *name, char **flags, i64 flags_count, char **objects, i64 count)
{
CommandList ar = {0};
- cmd_append(&a, &ar, STATIC_LIBRARY_BEGIN(name));
- cmd_append_count(&a, &ar, flags, flags_count);
- cmd_append_count(&a, &ar, objects, count);
- cmd_append(&a, &ar, (void *)0);
+ cmd_append(a, &ar, STATIC_LIBRARY_BEGIN(name));
+ cmd_append_count(a, &ar, flags, flags_count);
+ cmd_append_count(a, &ar, objects, count);
+ cmd_append(a, &ar, (void *)0);
b32 result = run_synchronous(a, &ar);
if (!result) build_log_failure("%s", name);
return result;
}
function b32
-build_static_library(Arena a, CommandList cc, char *name, char **deps, char **outputs, i64 count)
+build_static_library(Arena *a, CommandList cc, char *name, char **deps, char **outputs, i64 count)
{
/* TODO(rnp): refactor to not need outputs */
b32 result = 1;
@@ -728,7 +773,7 @@ build_static_library(Arena a, CommandList cc, char *name, char **deps, char **ou
}
function b32
-build_raylib(Arena a)
+build_raylib(Arena *a)
{
b32 result = 1, shared = config.debug;
char *libraylib = shared ? OS_SHARED_LINK_LIB("raylib") : OUTPUT_LIB(OS_STATIC_LIB("raylib"));
@@ -736,11 +781,11 @@ build_raylib(Arena a)
git_submodule_update(a, "external/raylib");
CommandList cc = {0};
- cmd_base(&a, &cc, 0, config.debug);
- if (is_unix) cmd_append(&a, &cc, "-D_GLFW_X11");
- cmd_append(&a, &cc, "-DPLATFORM_DESKTOP_GLFW");
- if (!is_msvc) cmd_append(&a, &cc, "-Wno-unused-but-set-variable");
- cmd_append(&a, &cc, "-Iexternal/include", "-Iexternal/raylib/src", "-Iexternal/raylib/src/external/glfw/include");
+ cmd_base(a, &cc, 0, config.debug);
+ if (is_unix) cmd_append(a, &cc, "-D_GLFW_X11");
+ cmd_append(a, &cc, "-DPLATFORM_DESKTOP_GLFW");
+ if (!is_msvc) cmd_append(a, &cc, "-Wno-unused-but-set-variable");
+ cmd_append(a, &cc, "-Iexternal/include", "-Iexternal/raylib/src", "-Iexternal/raylib/src/external/glfw/include");
#define RAYLIB_SOURCES \
X(rglfw) \
X(rshapes) \
@@ -757,7 +802,7 @@ build_raylib(Arena a)
if (shared) {
char *libs[] = {LINK_LIB("user32"), LINK_LIB("shell32"), LINK_LIB("gdi32"), LINK_LIB("winmm")};
i64 libs_count = is_w32 ? countof(libs) : 0;
- cmd_append(&a, &cc, "-DBUILD_LIBTYPE_SHARED", "-D_GLFW_BUILD_DLL");
+ cmd_append(a, &cc, "-DBUILD_LIBTYPE_SHARED", "-D_GLFW_BUILD_DLL");
result = build_shared_library(a, cc, "raylib", libraylib, libs, libs_count, srcs, countof(srcs));
} else {
result = build_static_library(a, cc, libraylib, srcs, outs, countof(srcs));
@@ -767,7 +812,7 @@ build_raylib(Arena a)
}
function b32
-build_glslang(Arena a)
+build_glslang(Arena *a)
{
b32 result = 1;
char *lib = OUTPUT_LIB(OS_STATIC_LIB("glslang"));
@@ -776,9 +821,9 @@ build_glslang(Arena a)
// NOTE(rnp): do not build this with debug symbols. The size explodes because c++
CommandList cc = {0};
- cmd_base(&a, &cc, 1, 0);
- cmd_append(&a, &cc, "-std=c++17", "-fno-rtti", "-fno-exceptions", "-Wno-unused-but-set-variable");
- cmd_append(&a, &cc, "-Iexternal/glslang_local", "-Iexternal/glslang");
+ cmd_base(a, &cc, 1, 0);
+ cmd_append(a, &cc, "-std=c++17", "-fno-rtti", "-fno-exceptions", "-Wno-unused-but-set-variable");
+ cmd_append(a, &cc, "-Iexternal/glslang_local", "-Iexternal/glslang");
#if OS_WINDOWS
#define GLSLANG_SOURCES_OS X(ossource, "glslang/glslang/OSDependent/Windows/")
@@ -807,11 +852,11 @@ build_glslang(Arena a)
}
function b32
-build_helper_library(Arena arena)
+build_helper_library(Arena *arena)
{
CommandList cc = {0};
- cmd_base(&arena, &cc, 0, 0);
- cmd_append(&arena, &cc, EXTRA_FLAGS);
+ cmd_base(arena, &cc, 0, 0);
+ cmd_append(arena, &cc, EXTRA_FLAGS);
/////////////
// library
@@ -819,7 +864,7 @@ build_helper_library(Arena arena)
char *libs[] = {LINK_LIB("Synchronization")};
i64 libs_count = is_w32 ? countof(libs) : 0;
- if (!is_msvc) cmd_append(&arena, &cc, "-Wno-unused-function");
+ if (!is_msvc) cmd_append(arena, &cc, "-Wno-unused-function");
b32 result = build_shared_library(arena, cc, "ogl_beamformer_lib", library,
libs, libs_count, (char *[]){"lib/ogl_beamformer_lib.c"}, 1);
return result;
@@ -839,43 +884,43 @@ cmd_beamformer_base(Arena *a, CommandList *c)
}
function b32
-build_beamformer_main(Arena arena)
+build_beamformer_main(Arena *arena)
{
CommandList c = {0};
- cmd_beamformer_base(&arena, &c);
+ cmd_beamformer_base(arena, &c);
- cmd_append(&arena, &c, OS_MAIN, OUTPUT_EXE("ogl"));
- cmd_pdb(&arena, &c, "ogl");
+ cmd_append(arena, &c, OS_MAIN, OUTPUT_EXE("ogl"));
+ cmd_pdb(arena, &c, "ogl");
if (config.debug) {
- if (!is_w32) cmd_append(&arena, &c, "-Wl,--export-dynamic", "-Wl,-rpath,.");
- if (!is_msvc) cmd_append(&arena, &c, "-L.");
- cmd_append(&arena, &c, LINK_LIB("raylib"));
+ if (!is_w32) cmd_append(arena, &c, "-Wl,--export-dynamic", "-Wl,-rpath,.");
+ if (!is_msvc) cmd_append(arena, &c, "-L.");
+ cmd_append(arena, &c, LINK_LIB("raylib"));
} else {
- if (!is_msvc) cmd_append(&arena, &c, "-flto");
- cmd_append(&arena, &c, OUTPUT(OS_STATIC_LIB("raylib")));
+ if (!is_msvc) cmd_append(arena, &c, "-flto");
+ cmd_append(arena, &c, OUTPUT(OS_STATIC_LIB("raylib")));
}
// TODO(rnp): not sure how to do this with msvc. we don't want a runtime dependence on libc++
- cmd_append(&arena, &c, OUTPUT(OS_STATIC_LIB("glslang")), "-Wl,-Bstatic", "-lstdc++", "-Wl,-Bdynamic");
+ cmd_append(arena, &c, OUTPUT(OS_STATIC_LIB("glslang")), "-Wl,-Bstatic", "-lstdc++", "-Wl,-Bdynamic");
- if (!is_msvc) cmd_append(&arena, &c, "-lm");
- if (is_unix) cmd_append(&arena, &c, "-lGL");
+ if (!is_msvc) cmd_append(arena, &c, "-lm");
+ if (is_unix) cmd_append(arena, &c, "-lGL");
if (is_w32) {
- cmd_append(&arena, &c, LINK_LIB("user32"), LINK_LIB("shell32"), LINK_LIB("gdi32"),
+ cmd_append(arena, &c, LINK_LIB("user32"), LINK_LIB("shell32"), LINK_LIB("gdi32"),
LINK_LIB("opengl32"), LINK_LIB("winmm"), LINK_LIB("Synchronization"));
- if (!is_msvc) cmd_append(&arena, &c, "-Wl,--out-implib," OUTPUT(OS_STATIC_LIB("main")));
+ if (!is_msvc) cmd_append(arena, &c, "-Wl,--out-implib," OUTPUT(OS_STATIC_LIB("main")));
}
- cmd_append(&arena, &c, (void *)0);
+ cmd_append(arena, &c, (void *)0);
return run_synchronous(arena, &c);
}
function b32
-build_beamformer_as_library(Arena arena)
+build_beamformer_as_library(Arena *arena)
{
CommandList cc = {0};
- cmd_beamformer_base(&arena, &cc);
+ cmd_beamformer_base(arena, &cc);
if (is_msvc) {
build_static_library_from_objects(arena, OUTPUT_LIB(OS_STATIC_LIB("main")),
@@ -888,26 +933,26 @@ build_beamformer_as_library(Arena arena)
LINK_LIB("shell32"), LINK_LIB("user32"), LINK_LIB("opengl32"),
LINK_LIB("winmm"), LINK_LIB("Synchronization"), OUTPUT("main.lib")};
i64 libs_count = is_w32 ? countof(libs) : 0;
- cmd_append(&arena, &cc, "-D_BEAMFORMER_DLL");
+ cmd_append(arena, &cc, "-D_BEAMFORMER_DLL");
b32 result = build_shared_library(arena, cc, "beamformer", library,
libs, libs_count, arg_list(char *, "beamformer_core.c"));
return result;
}
function b32
-build_tests(Arena arena)
+build_tests(Arena *arena)
{
CommandList cc = {0};
- cmd_base(&arena, &cc, 0, config.debug);
- cmd_append(&arena, &cc, EXTRA_FLAGS);
+ cmd_base(arena, &cc, 0, config.debug);
+ cmd_append(arena, &cc, EXTRA_FLAGS);
#define TEST_PROGRAMS \
X("throughput", LINK_LIB("m"), LINK_LIB("zstd"), W32_DECL(LINK_LIB("Synchronization"))) \
X("decode", LINK_LIB("m"), W32_DECL(LINK_LIB("Synchronization"))) \
os_make_directory(OUTPUT("tests"));
- if (!is_msvc) cmd_append(&arena, &cc, "-Wno-unused-function");
- cmd_append(&arena, &cc, "-I.", "-Ilib");
+ if (!is_msvc) cmd_append(arena, &cc, "-Wno-unused-function");
+ cmd_append(arena, &cc, "-I.", "-Ilib");
b32 result = 1;
i64 cc_count = cc.count;
@@ -961,9 +1006,9 @@ str8_trim(str8 in)
}
typedef struct {
- Stream stream;
- Arena scratch;
- i32 indentation_level;
+ Stream stream;
+ Arena *scratch;
+ i32 indentation_level;
} MetaprogramContext;
function b32
@@ -1421,8 +1466,8 @@ meta_parser_unexpected_token(MetaParser *p, MetaParseToken t)
function void
meta_parser_fill_argument_array(MetaParser *p, MetaEntryArgument *array, Arena *arena)
{
+ str8_list strings = {0};
array->kind = MetaEntryArgumentKind_Array;
- array->strings = arena_aligned_start(*arena, alignof(str8));
array->location = p->p.location;
for (MetaParseToken token = meta_parser_token(p);
token != MetaParseToken_EndArray;
@@ -1432,13 +1477,14 @@ meta_parser_fill_argument_array(MetaParser *p, MetaEntryArgument *array, Arena *
case MetaParseToken_RawString:
case MetaParseToken_String:
{
- assert((u8 *)(array->strings + array->count) == arena->beg);
- *push_struct(arena, str8) = p->u.string;
- array->count++;
+ *da_push(arena, &strings) = p->u.string;
}break;
default:{ meta_parser_unexpected_token(p, token); }break;
}
}
+ array->strings = strings.data;
+ array->count = strings.count;
+ arena_pop(arena, (strings.capacity - strings.count) * sizeof(*strings.data));
}
function void
@@ -1447,13 +1493,17 @@ meta_parser_arguments(MetaParser *p, MetaEntry *e, Arena *arena)
if (meta_parser_peek_token(p) == MetaParseToken_BeginArgs) {
meta_parser_commit(p);
- e->arguments = arena_aligned_start(*arena, alignof(MetaEntryArgument));
+ struct {
+ MetaEntryArgument *data;
+ da_count count;
+ da_count capacity;
+ } arguments = {0};
+
for (MetaParseToken token = meta_parser_token(p);
token != MetaParseToken_EndArgs;
token = meta_parser_token(p))
{
- e->argument_count++;
- MetaEntryArgument *arg = push_struct(arena, MetaEntryArgument);
+ MetaEntryArgument *arg = da_push(arena, &arguments);
switch (token) {
case MetaParseToken_RawString:
case MetaParseToken_String:
@@ -1468,6 +1518,10 @@ meta_parser_arguments(MetaParser *p, MetaEntry *e, Arena *arena)
default:{ meta_parser_unexpected_token(p, token); }break;
}
}
+ e->arguments = arguments.data;
+ e->argument_count = arguments.count;
+ // TODO(rnp): we should count arguments first so that we don't need to leave a hole
+ //arena_pop(arena, (arguments.capacity - arguments.count) * sizeof(*arguments.data));
}
}
@@ -1853,7 +1907,7 @@ typedef struct {
} MetaStruct;
typedef struct {
- Arena *arena, scratch;
+ Arena *arena, *scratch;
str8 filename;
str8 directory;
@@ -2024,9 +2078,9 @@ function MetaEntityID
meta_entity_reference(MetaContext *ctx, str8 name, MetaLocation location)
{
MetaEntityID result = {0};
- Arena scratch;
- DeferLoop(scratch = ctx->scratch, ctx->scratch = scratch) {
- str8 ref_name = push_str8_from_parts(&ctx->scratch, str8(""), str8("R"), name);
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(ctx->scratch), temp_end(scratch)) {
+ str8 ref_name = push_str8_from_parts(ctx->scratch, str8(""), str8("R"), name);
result = meta_intern_entity(ctx, ref_name, MetaEntityKind_Reference,
meta_root_entity_id(ctx), location, 1);
MetaEntity *r = meta_entity(ctx, result);
@@ -2046,9 +2100,9 @@ meta_entity_reference_reference(MetaContext *ctx, str8 name, str8 scope_name, Me
// NOTE(rnp): base reference
MetaEntityID ref_id = meta_entity_reference(ctx, name, location);
- Arena scratch;
- DeferLoop(scratch = ctx->scratch, ctx->scratch = scratch) {
- str8 refref_name = push_str8_from_parts(&ctx->scratch, str8(""), prefix, str8("RR"), name);
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(ctx->scratch), temp_end(scratch)) {
+ str8 refref_name = push_str8_from_parts(ctx->scratch, str8(""), prefix, str8("RR"), name);
result = meta_intern_entity(ctx, refref_name, MetaEntityKind_ReferenceReference,
parent, location, 1);
@@ -2453,7 +2507,7 @@ meta_expand_table_entity_id(MetaContext *ctx, MetaEntry *e)
function str8
meta_expand_parts_to_str8_at_index(MetaContext *ctx, u64 table_index, MetaExpansionPartList parts)
{
- Stream sb = arena_stream(*ctx->arena);
+ Stream sb = arena_stream(ctx->arena);
for EachIndex((u64)parts.count, part) {
MetaExpansionPart *p = parts.data + part;
u32 index = 0;
@@ -2527,9 +2581,10 @@ meta_pack_table_entity(MetaContext *ctx, MetaEntry *e, i64 entry_count, str8 nam
e->kind == MetaEntryKind_Union;
MetaEntryScope scope = meta_entry_extract_scope(e, entry_count);
- if (scope.consumed > 1) {
- Arena scratch = ctx->scratch;
-
+ Temp scratch;
+ if (scope.consumed > 1)
+ DeferLoop(scratch = temp_begin(ctx->scratch), temp_end(scratch))
+ {
// NOTE(rnp): count expands
i64 expand_count = 0;
for (MetaEntry *row = scope.start; row != scope.one_past_last; row++)
@@ -2540,7 +2595,7 @@ meta_pack_table_entity(MetaContext *ctx, MetaEntry *e, i64 entry_count, str8 nam
da_count *table_ids = 0;
i64 table_id_index = 0;
if (expand_count > 0) {
- table_ids = push_array(&ctx->scratch, da_count, expand_count);
+ table_ids = push_array(ctx->scratch, da_count, expand_count);
for (MetaEntry *row = scope.start; row != scope.one_past_last; row++)
if (row->kind == MetaEntryKind_Expand)
table_ids[table_id_index++] = meta_expand_table_entity_id(ctx, row);
@@ -2615,7 +2670,7 @@ meta_pack_table_entity(MetaContext *ctx, MetaEntry *e, i64 entry_count, str8 nam
for EachIndex(argument_count, it) {
working_row_index = row_index;
str8 expand = row->arguments ? row->arguments->strings[it] : row->name;
- MetaExpansionPartList parts = meta_generate_expansion_set(ctx, &ctx->scratch, expand, table, row->location);
+ MetaExpansionPartList parts = meta_generate_expansion_set(ctx, ctx->scratch, expand, table, row->location);
for EachIndex(table->table.entry_count, entry_index)
t->entries[it][working_row_index++] = meta_expand_parts_to_str8_at_index(ctx, entry_index, parts);
}
@@ -2639,8 +2694,6 @@ meta_pack_table_entity(MetaContext *ctx, MetaEntry *e, i64 entry_count, str8 nam
row_index++;
}
}
-
- ctx->scratch = scratch;
}
MetaEntity *entity = meta_entity(ctx, entity_id);
@@ -2822,17 +2875,22 @@ meta_pack_references(MetaContext *ctx, MetaEntry *entries, i64 entry_count, Meta
}
function str8 *
-meta_expand_to_str8_array(MetaContext *ctx, Arena scratch, str8 expand, MetaEntity *table, MetaLocation location)
+meta_expand_to_str8_array(MetaContext *ctx, str8 expand, MetaEntity *table, MetaLocation location)
{
- MetaExpansionPartList parts = meta_generate_expansion_set(ctx, &scratch, expand, table, location);
- str8 *result = push_array(ctx->arena, str8, table->table.entry_count);
- for EachIndex(table->table.entry_count, expansion)
- result[expansion] = meta_expand_parts_to_str8_at_index(ctx, expansion, parts);
+ str8 *result = 0;
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(ctx->scratch), temp_end(scratch))
+ {
+ MetaExpansionPartList parts = meta_generate_expansion_set(ctx, ctx->scratch, expand, table, location);
+ result = push_array(ctx->arena, str8, table->table.entry_count);
+ for EachIndex(table->table.entry_count, expansion)
+ result[expansion] = meta_expand_parts_to_str8_at_index(ctx, expansion, parts);
+ }
return result;
}
function i64
-meta_expand(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count, MetaEmitOperationList *ops)
+meta_expand(MetaContext *ctx, MetaEntry *e, i64 entry_count, MetaEmitOperationList *ops)
{
assert(e->kind == MetaEntryKind_Expand);
@@ -2871,7 +2929,7 @@ meta_expand(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count, Meta
meta_pack_table_begin(&entry, &new->table);
new->table.entries = push_array(ctx->arena, str8 *, new->table.field_count);
new->table.entry_count = table->table.entry_count;
- new->table.entries[0] = meta_expand_to_str8_array(ctx, scratch, expand, table, row->location);
+ new->table.entries[0] = meta_expand_to_str8_array(ctx, expand, table, row->location);
}break;
case MetaEntryKind_Struct:
@@ -2893,12 +2951,12 @@ meta_expand(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count, Meta
meta_pack_table_begin(&entry, &new->table);
new->table.entries = push_array(ctx->arena, str8 *, new->table.field_count);
new->table.entry_count = table->table.entry_count;
- new->table.entries[MetaStructField_Name] = meta_expand_to_str8_array(ctx, scratch, fields.strings[0],
+ new->table.entries[MetaStructField_Name] = meta_expand_to_str8_array(ctx, fields.strings[0],
table, row->location);
- new->table.entries[MetaStructField_Type] = meta_expand_to_str8_array(ctx, scratch, fields.strings[1],
+ new->table.entries[MetaStructField_Type] = meta_expand_to_str8_array(ctx, fields.strings[1],
table, row->location);
if (fields.count == 3) {
- new->table.entries[MetaStructField_Elements] = meta_expand_to_str8_array(ctx, scratch, fields.strings[2],
+ new->table.entries[MetaStructField_Elements] = meta_expand_to_str8_array(ctx, fields.strings[2],
table, row->location);
} else {
new->table.entries[MetaStructField_Elements] = push_array(ctx->arena, str8, table->table.entry_count);
@@ -2918,7 +2976,7 @@ meta_expand(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count, Meta
}
function void
-meta_embed(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count)
+meta_embed(MetaContext *ctx, MetaEntry *e, i64 entry_count)
{
assert(e->kind == MetaEntryKind_Embed);
@@ -3000,7 +3058,7 @@ meta_pack_constant(MetaContext *ctx, MetaEntry *e)
}
function i64
-meta_pack_emit(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count)
+meta_pack_emit(MetaContext *ctx, MetaEntry *e, i64 entry_count)
{
assert(e->kind == MetaEntryKind_Emit);
@@ -3025,7 +3083,7 @@ meta_pack_emit(MetaContext *ctx, Arena scratch, MetaEntry *e, i64 entry_count)
op->location = row->location;
}break;
case MetaEntryKind_Expand:{
- row += meta_expand(ctx, scratch, row, entry_count - (row - e), ops);
+ row += meta_expand(ctx, row, entry_count - (row - e), ops);
}break;
default:{ meta_entry_nesting_error(row, MetaEntryKind_Emit); }break;
}
@@ -3068,30 +3126,33 @@ metagen_push_byte_array(MetaprogramContext *m, str8 bytes)
}
function void
-metagen_push_table(MetaprogramContext *m, Arena scratch, str8 row_start, str8 row_end,
- str8 **column_strings, u64 rows, u64 columns)
+metagen_push_table(MetaprogramContext *m, str8 row_start, str8 row_end, str8 **column_strings, u64 rows, u64 columns)
{
- u32 *column_widths = 0;
- if (columns > 1) {
- column_widths = push_array(&scratch, u32, columns - 1);
- for (u64 column = 0; column < columns - 1; column++) {
- str8 *strings = column_strings[column];
- for (u64 row = 0; row < rows; row++)
- column_widths[column] = Max(column_widths[column], (u32)strings[row].length);
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
+ {
+ u32 *column_widths = 0;
+ if (columns > 1) {
+ column_widths = push_array(m->scratch, u32, columns - 1);
+ for (u64 column = 0; column < columns - 1; column++) {
+ str8 *strings = column_strings[column];
+ for (u64 row = 0; row < rows; row++)
+ column_widths[column] = Max(column_widths[column], (u32)strings[row].length);
+ }
}
- }
- for (u64 row = 0; row < rows; row++) {
- meta_begin_line(m, row_start);
- for (u64 column = 0; column < columns; column++) {
- str8 text = column_strings[column][row];
- meta_push(m, text);
- i32 pad = columns > 1 ? 1 : 0;
- if (column_widths && column < columns - 1)
- pad += (i32)column_widths[column] - (i32)text.length;
- if (column < columns - 1) meta_pad(m, ' ', pad);
+ for (u64 row = 0; row < rows; row++) {
+ meta_begin_line(m, row_start);
+ for (u64 column = 0; column < columns; column++) {
+ str8 text = column_strings[column][row];
+ meta_push(m, text);
+ i32 pad = columns > 1 ? 1 : 0;
+ if (column_widths && column < columns - 1)
+ pad += (i32)column_widths[column] - (i32)text.length;
+ if (column < columns - 1) meta_pad(m, ' ', pad);
+ }
+ meta_end_line(m, row_end);
}
- meta_end_line(m, row_end);
}
}
@@ -3151,88 +3212,93 @@ metagen_run_emit(MetaprogramContext *m, MetaContext *ctx, MetaEmitOperationList
switch (op->kind) {
case MetaEmitOperationKind_String:{ meta_push_line(m, op->string); }break;
case MetaEmitOperationKind_FileBytes:{
- Arena scratch = m->scratch;
- str8 filename = push_str8_from_parts(&scratch, str8(OS_PATH_SEPARATOR), ctx->directory, op->string);
- str8 file = read_entire_file((c8 *)filename.data, &scratch);
- m->indentation_level++;
- metagen_push_byte_array(m, file);
- m->indentation_level--;
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
+ {
+ str8 filename = push_str8_from_parts(m->scratch, str8(OS_PATH_SEPARATOR), ctx->directory, op->string);
+ str8 file = read_entire_file((c8 *)filename.data, m->scratch);
+ m->indentation_level++;
+ metagen_push_byte_array(m, file);
+ m->indentation_level--;
+ }
}break;
case MetaEmitOperationKind_Expand:{
- Arena scratch = m->scratch;
-
- MetaEmitOperationExpansion *eop = &op->expansion_operation;
- MetaTable *t = &ctx->entities.data[eop->table_entity_id].table;
- str8 table_name = ctx->entity_names.data[eop->table_entity_id];
-
- u32 alignment_count = 1;
- u32 evaluation_count = 0;
- for (u32 part = 0; part < eop->part_count; part++) {
- if (eop->parts[part].kind == MetaExpansionPartKind_Alignment)
- alignment_count++;
- if (eop->parts[part].kind == MetaExpansionPartKind_EvalKind ||
- eop->parts[part].kind == MetaExpansionPartKind_EvalKindCount)
- evaluation_count++;
- }
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
+ {
+ MetaEmitOperationExpansion *eop = &op->expansion_operation;
+ MetaTable *t = &ctx->entities.data[eop->table_entity_id].table;
+ str8 table_name = ctx->entity_names.data[eop->table_entity_id];
- MetaKind **evaluation_columns = push_array(&scratch, MetaKind *, evaluation_count);
- for (u32 column = 0; column < evaluation_count; column++)
- evaluation_columns[column] = push_array(&scratch, MetaKind, t->entry_count);
-
- for (u32 part = 0; part < eop->part_count; part++) {
- u32 eval_column = 0;
- MetaExpansionPart *p = eop->parts + part;
- if (p->kind == MetaExpansionPartKind_EvalKind) {
- for (u32 entry = 0; entry < t->entry_count; entry++) {
- evaluation_columns[eval_column][entry] = meta_map_kind(p->strings[entry],
- table_name, op->location);
- }
- eval_column++;
+ u32 alignment_count = 1;
+ u32 evaluation_count = 0;
+ for (u32 part = 0; part < eop->part_count; part++) {
+ if (eop->parts[part].kind == MetaExpansionPartKind_Alignment)
+ alignment_count++;
+ if (eop->parts[part].kind == MetaExpansionPartKind_EvalKind ||
+ eop->parts[part].kind == MetaExpansionPartKind_EvalKindCount)
+ evaluation_count++;
}
- }
- str8 **columns = push_array(&scratch, str8 *, alignment_count);
- for (u32 column = 0; column < alignment_count; column++)
- columns[column] = push_array(&scratch, str8, t->entry_count);
+ MetaKind **evaluation_columns = push_array(m->scratch, MetaKind *, evaluation_count);
+ for (u32 column = 0; column < evaluation_count; column++)
+ evaluation_columns[column] = push_array(m->scratch, MetaKind, t->entry_count);
- Stream sb = arena_stream(scratch);
- for (u32 entry = 0; entry < t->entry_count; entry++) {
- u32 column = 0;
- u32 eval_column = 0;
for (u32 part = 0; part < eop->part_count; part++) {
+ u32 eval_column = 0;
MetaExpansionPart *p = eop->parts + part;
- switch (p->kind) {
- case MetaExpansionPartKind_Alignment:{
- columns[column][entry] = arena_stream_commit_and_reset(&scratch, &sb);
- column++;
- }break;
-
- case MetaExpansionPartKind_Conditional:{
- if (!meta_expansion_part_conditional(p, entry, table_name, op->location))
- part += p->conditional.instruction_skip;
- }break;
-
- case MetaExpansionPartKind_EvalKind:{
- str8 kind = evaluation_table[evaluation_columns[eval_column][entry]];
- stream_append_str8(&sb, kind);
- }break;
+ if (p->kind == MetaExpansionPartKind_EvalKind) {
+ for (u32 entry = 0; entry < t->entry_count; entry++) {
+ evaluation_columns[eval_column][entry] = meta_map_kind(p->strings[entry],
+ table_name, op->location);
+ }
+ eval_column++;
+ }
+ }
- case MetaExpansionPartKind_EvalKindCount:{
- stream_append_u64(&sb, meta_kind_elements[evaluation_columns[eval_column][entry]]);
- }break;
+ str8 **columns = push_array(m->scratch, str8 *, alignment_count);
+ for (u32 column = 0; column < alignment_count; column++)
+ columns[column] = push_array(m->scratch, str8, t->entry_count);
- case MetaExpansionPartKind_Reference:
- case MetaExpansionPartKind_String:
- {
- str8 string = p->kind == MetaExpansionPartKind_Reference ? p->strings[entry] : p->string;
- stream_append_str8(&sb, string);
- }break;
+ Stream sb = arena_stream(m->scratch);
+ for (u32 entry = 0; entry < t->entry_count; entry++) {
+ u32 column = 0;
+ u32 eval_column = 0;
+ for (u32 part = 0; part < eop->part_count; part++) {
+ MetaExpansionPart *p = eop->parts + part;
+ switch (p->kind) {
+ case MetaExpansionPartKind_Alignment:{
+ columns[column][entry] = arena_stream_commit_and_reset(m->scratch, &sb);
+ column++;
+ }break;
+
+ case MetaExpansionPartKind_Conditional:{
+ if (!meta_expansion_part_conditional(p, entry, table_name, op->location))
+ part += p->conditional.instruction_skip;
+ }break;
+
+ case MetaExpansionPartKind_EvalKind:{
+ str8 kind = evaluation_table[evaluation_columns[eval_column][entry]];
+ stream_append_str8(&sb, kind);
+ }break;
+
+ case MetaExpansionPartKind_EvalKindCount:{
+ stream_append_u64(&sb, meta_kind_elements[evaluation_columns[eval_column][entry]]);
+ }break;
+
+ case MetaExpansionPartKind_Reference:
+ case MetaExpansionPartKind_String:
+ {
+ str8 string = p->kind == MetaExpansionPartKind_Reference ? p->strings[entry] : p->string;
+ stream_append_str8(&sb, string);
+ }break;
+ }
}
- }
- columns[column][entry] = arena_stream_commit_and_reset(&scratch, &sb);
+ columns[column][entry] = arena_stream_commit_and_reset(m->scratch, &sb);
+ }
+ metagen_push_table(m, str8(""), str8(""), columns, t->entry_count, alignment_count);
}
- metagen_push_table(m, scratch, str8(""), str8(""), columns, t->entry_count, alignment_count);
}break;
InvalidDefaultCase;
}
@@ -3297,52 +3363,15 @@ metagen_push_counted_enum_body_from_ids(MetaprogramContext *m, str8 kind, str8 p
}
function void
-metagen_push_c_enum(MetaprogramContext *m, Arena scratch, str8 kind, b32 flags, str8 *ids, i64 ids_count)
+metagen_push_c_enum(MetaprogramContext *m, str8 kind, b32 flags, str8 *ids, i64 ids_count)
{
- str8 kind_full = push_str8_from_parts(&scratch, str8(""), kind, str8("_"));
+ str8 kind_full = push_str8_from_parts(m->scratch, str8(""), kind, str8("_"));
meta_begin_scope(m, str8("typedef enum {"));
metagen_push_counted_enum_body(m, kind_full, str8(""), flags ? str8("= 1 << ") : str8("= "), str8(","), ids, ids_count);
if (!flags) meta_push_line(m, kind_full, str8("Count,"));
meta_end_scope(m, str8("} "), kind, str8(";\n"));
}
-function u32
-meta_struct_flattened_member_count(Arena scratch, MetaContext *ctx, MetaStruct *meta_struct)
-{
- struct stack_item {MetaStruct *s; u32 member_offset;} init[16];
- struct {
- struct stack_item *data;
- da_count count;
- da_count capacity;
- } stack = {init, 0, countof(init)};
-
- u32 result = 0;
- *da_push(&scratch, &stack) = (struct stack_item){meta_struct, 0};
- while (stack.count > 0) {
- stack.count--;
- MetaStruct *s = stack.data[stack.count].s;
- u32 member = stack.data[stack.count].member_offset;
- while (member < s->info.member_count) {
- if (s->members[member].length == 0) {
- assert(s->member_flags[member] & MetaStructMemberFlag_ReferenceType);
- MetaStruct *ss = ctx->struct_infos + ctx->entities.data[s->type_ids[member]].table.struct_info_id;
- if (ss->info.flags & MetaStructFlag_Union) {
- member++;
- result++;
- } else {
- *da_push(&scratch, &stack) = (struct stack_item){s, member + 1};
- *da_push(&scratch, &stack) = (struct stack_item){ss, 0};
- break;
- }
- } else {
- member++;
- result++;
- }
- }
- }
- return result;
-}
-
typedef enum {
MetaPushStructStyle_C,
MetaPushStructStyle_MATLAB,
@@ -3364,7 +3393,6 @@ function void
meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struct_entity,
MetaPushStructParameters p)
{
- MetaStruct *meta_struct = ctx->struct_infos + struct_entity->table.struct_info_id;
struct stack_item {MetaEntity *se; u32 member_offset;} init[16];
struct {
struct stack_item *data;
@@ -3372,14 +3400,41 @@ meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struc
da_count capacity;
} stack = {init, 0, countof(init)};
- u32 flattened_member_count = meta_struct_flattened_member_count(m->scratch, ctx, meta_struct);
+ Temp scratch = temp_begin(m->scratch);
+
+ u32 flattened_member_count = 0;
+
+ *da_push(m->scratch, &stack) = (struct stack_item){struct_entity, 0};
+ while (stack.count > 0) {
+ stack.count--;
+ MetaEntity *se = stack.data[stack.count].se;
+ MetaStruct *s = ctx->struct_infos + se->table.struct_info_id;
+ u32 member = stack.data[stack.count].member_offset;
+ while (member < s->info.member_count) {
+ if (s->members[member].length == 0) {
+ assert(s->member_flags[member] & MetaStructMemberFlag_ReferenceType);
+ MetaStruct *ss = ctx->struct_infos + ctx->entities.data[s->type_ids[member]].table.struct_info_id;
+ if (ss->info.flags & MetaStructFlag_Union) {
+ member++;
+ flattened_member_count++;
+ } else {
+ *da_push(ctx->scratch, &stack) = (struct stack_item){se, member + 1};
+ *da_push(ctx->scratch, &stack) = (struct stack_item){ctx->entities.data + s->type_ids[member], 0};
+ break;
+ }
+ } else {
+ member++;
+ flattened_member_count++;
+ }
+ }
+ }
str8 *columns[2];
- columns[0] = push_array(&m->scratch, str8, flattened_member_count);
- columns[1] = push_array(&m->scratch, str8, flattened_member_count);
+ columns[0] = push_array(m->scratch, str8, flattened_member_count);
+ columns[1] = push_array(m->scratch, str8, flattened_member_count);
u32 row = 0, scope = 0;
- *da_push(&m->scratch, &stack) = (struct stack_item){struct_entity, 0};
+ *da_push(m->scratch, &stack) = (struct stack_item){struct_entity, 0};
while (stack.count > 0) {
stack.count--;
MetaEntity *se = stack.data[stack.count].se;
@@ -3396,12 +3451,12 @@ meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struc
if (s->members[member].length == 0 &&
(p.union_style != MetaPushStructStyle_MATLAB || ctx->entities.data[type_id].kind != MetaEntityKind_Union))
{
- *da_push(&m->scratch, &stack) = (struct stack_item){se, member + 1};
- *da_push(&m->scratch, &stack) = (struct stack_item){ctx->entities.data + type_id, 0};
+ *da_push(m->scratch, &stack) = (struct stack_item){se, member + 1};
+ *da_push(m->scratch, &stack) = (struct stack_item){ctx->entities.data + type_id, 0};
MetaStruct *ss = ctx->struct_infos + ctx->entities.data[type_id].table.struct_info_id;
if (p.layout_style == MetaPushStructStyle_C && ss->info.flags & MetaStructFlag_Union) {
- metagen_push_table(m, m->scratch, p.prefix, p.suffix, columns, row, 2);
+ metagen_push_table(m, p.prefix, p.suffix, columns, row, 2);
meta_begin_scope(m, str8("union {"));
row = 0;
scope++;
@@ -3454,7 +3509,7 @@ meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struc
stream_append_u64(&sb, resolved_element_count);
}
stream_append_str8(&sb, elements_count_close[p.layout_style]);
- columns[name_column[p.layout_style]][row] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[name_column[p.layout_style]][row] = arena_stream_commit_and_reset(m->scratch, &sb);
} else {
columns[name_column[p.layout_style]][row] = member_name;
}
@@ -3500,7 +3555,7 @@ meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struc
rs ? rs->info.name : ctx->entity_names.data[type_id]);
}
- columns[type_column[p.layout_style]][row] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[type_column[p.layout_style]][row] = arena_stream_commit_and_reset(m->scratch, &sb);
} else {
columns[type_column[p.layout_style]][row] = p.base_types[type_id];
}
@@ -3512,7 +3567,7 @@ meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struc
}
if (member == s->info.member_count && s->info.flags & MetaStructFlag_Union && p.layout_style == MetaPushStructStyle_C) {
- metagen_push_table(m, m->scratch, p.prefix, p.suffix, columns, row, 2);
+ metagen_push_table(m, p.prefix, p.suffix, columns, row, 2);
while (scope > 0) {
meta_end_scope(m, str8("};"));
scope--;
@@ -3520,7 +3575,9 @@ meta_push_struct_body(MetaContext *ctx, MetaprogramContext *m, MetaEntity *struc
row = 0;
}
}
- metagen_push_table(m, m->scratch, p.prefix, p.suffix, columns, row, 2);
+ metagen_push_table(m, p.prefix, p.suffix, columns, row, 2);
+
+ temp_end(scratch);
}
function void
@@ -3611,7 +3668,11 @@ meta_push_shader_reload_info(MetaprogramContext *m, MetaContext *ctx)
////////////////////////////////////
// NOTE(rnp): shader header strings
- meta_begin_scope(m, str8("read_only global str8 " META_NAMESPACE_LOWER "_shader_global_header_strings[] = {"));
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
+ DeferLoop(meta_begin_scope(m, str8("read_only global str8 " META_NAMESPACE_LOWER
+ "_shader_global_header_strings[] = {")),
+ meta_end_scope(m, str8("};\n")))
{
for (da_count ref = 0; ref < ctx->shader_entity_references.count; ref++) {
da_count entity_id = ctx->shader_entity_references.data[ref];
@@ -3668,7 +3729,7 @@ meta_push_shader_reload_info(MetaprogramContext *m, MetaContext *ctx)
}break;
case MetaEntityKind_Enumeration:{
- str8 kind_name = push_str8_from_parts(&m->scratch, str8(""), entity_name, str8("_"));
+ str8 kind_name = push_str8_from_parts(m->scratch, str8(""), entity_name, str8("_"));
meta_push_line(m, str8("str8_comp(\"\""));
metagen_push_counted_enum_body(m, kind_name, str8("\"#define "), str8(""), str8("\\n\""),
e->table.entries[0], e->table.entry_count);
@@ -3677,10 +3738,8 @@ meta_push_shader_reload_info(MetaprogramContext *m, MetaContext *ctx)
InvalidDefaultCase;
}
-
- m->scratch = ctx->scratch;
}
- } meta_end_scope(m, str8("};\n"));
+ }
meta_begin_scope(m, str8("read_only global b8 " META_NAMESPACE_LOWER "_shader_has_primitive[] = {"));
for (da_count bs = 0; bs < ctx->base_shader_count; bs++) {
@@ -3715,12 +3774,14 @@ meta_push_shader_bake(MetaprogramContext *m, MetaContext *ctx)
if (s->kind == MetaShaderKind_Render)
meta_push(m, it == 0 ? str8("_primitive") : str8("_fragment"));
- meta_begin_scope(m, str8("_bytes[] = {")); {
- Arena scratch = m->scratch;
- str8 filename = push_str8_from_parts(&scratch, str8(OS_PATH_SEPARATOR), str8("shaders"), s->files[it]);
- str8 file = read_entire_file((c8 *)filename.data, &scratch);
+ Temp scratch;
+ DeferLoop(meta_begin_scope(m, str8("_bytes[] = {")), meta_end_scope(m, str8("};\n")))
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
+ {
+ str8 filename = push_str8_from_parts(m->scratch, str8(OS_PATH_SEPARATOR), str8("shaders"), s->files[it]);
+ str8 file = read_entire_file((c8 *)filename.data, m->scratch);
metagen_push_byte_array(m, file);
- } meta_end_scope(m, str8("};\n"));
+ }
}
}
}
@@ -3781,7 +3842,7 @@ metagen_emit_c_str8_list(MetaprogramContext *m, str8 *strs, u32 count)
}
function b32
-metagen_emit_c_code(MetaContext *ctx, Arena arena)
+metagen_emit_c_code(MetaContext *ctx, Arena *arena)
{
b32 result = 1;
char *out, *out_shaders;
@@ -3798,17 +3859,19 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
stream_append_str8s(&sb, str8(OS_PATH_SEPARATOR), basename, str8(".c"));
stream_append_byte(&sb, 0);
- out = (c8 *)arena_stream_commit_and_reset(&arena, &sb).data;
+ out = (c8 *)arena_stream_commit_and_reset(arena, &sb).data;
stream_append_str8s(&sb, ctx->directory, str8(OS_PATH_SEPARATOR), str8("generated"));
stream_append_str8s(&sb, str8(OS_PATH_SEPARATOR), basename, str8("_shader_data.c"));
stream_append_byte(&sb, 0);
- out_shaders = (c8 *)arena_stream_commit_zero(&arena, &sb).data;
+ out_shaders = (c8 *)arena_stream_commit_zero(arena, &sb).data;
}
MetaprogramContext m[1] = {{.stream = arena_stream(arena), .scratch = ctx->scratch}};
+ arena_clear(m->scratch);
+
if (setjmp(compiler_jmp_buf)) {
build_fatal("Failed to generate C Code");
}
@@ -3816,14 +3879,14 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
////////////////////////////
// NOTE(rnp): shader baking
if (ctx->base_shader_count) {
- char **deps = push_array(&m->scratch, char *, 2 * ctx->base_shader_count);
+ char **deps = push_array(m->scratch, char *, 2 * ctx->base_shader_count);
u32 dep_count = 0;
for (da_count bs = 0; bs < ctx->base_shader_count; bs++) {
MetaShader *s = &ctx->entities.data[ctx->base_shader_ids[bs]].shader;
- deps[dep_count++] = (c8 *)push_str8_from_parts(&m->scratch, str8(OS_PATH_SEPARATOR),
+ deps[dep_count++] = (c8 *)push_str8_from_parts(m->scratch, str8(OS_PATH_SEPARATOR),
str8("shaders"), s->files[0]).data;
if (s->files[1].length > 0)
- deps[dep_count++] = (c8 *)push_str8_from_parts(&m->scratch, str8(OS_PATH_SEPARATOR),
+ deps[dep_count++] = (c8 *)push_str8_from_parts(m->scratch, str8(OS_PATH_SEPARATOR),
str8("shaders"), s->files[1]).data;
}
@@ -3833,17 +3896,19 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
meta_push_shader_bake(m, ctx);
result &= meta_write_and_reset(m, out_shaders);
}
- m->scratch = ctx->scratch;
}
+ arena_clear(m->scratch);
+
{
- CommandList deps = meta_extract_emit_file_dependencies(ctx, &m->scratch);
- *da_push(&m->scratch, &deps) = (c8 *)ctx->fullpath.data;
+ CommandList deps = meta_extract_emit_file_dependencies(ctx, m->scratch);
+ *da_push(m->scratch, &deps) = (c8 *)ctx->fullpath.data;
if (!needs_rebuild_(out, deps.data, deps.count))
return result;
- m->scratch = ctx->scratch;
}
+ arena_clear(m->scratch);
+
build_log_generate("%.*s: C Code", (i32)ctx->filename.length, ctx->filename.data);
meta_push(m, c_file_header);
@@ -3863,8 +3928,8 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
u32 row_alloc_count = Max(integers, floats);
str8 *columns[2];
- columns[0] = push_array(&m->scratch, str8, row_alloc_count);
- columns[1] = push_array(&m->scratch, str8, row_alloc_count);
+ columns[0] = push_array(m->scratch, str8, row_alloc_count);
+ columns[1] = push_array(m->scratch, str8, row_alloc_count);
u32 row_count;
@@ -3878,11 +3943,11 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
stream_append_str8(&sb, str8("("));
stream_append_u64(&sb, e->constant.U64);
columns[0][row_count] = ctx->entity_names.data[id];
- columns[1][row_count] = arena_stream_commit(&m->scratch, &sb);
+ columns[1][row_count] = arena_stream_commit(m->scratch, &sb);
row_count++;
}
}
- metagen_push_table(m, m->scratch, str8("#define " META_NAMESPACE_UPPER), str8(")"), columns, row_count, 2);
+ metagen_push_table(m, str8("#define " META_NAMESPACE_UPPER), str8(")"), columns, row_count, 2);
row_count = 0;
if (floats) meta_push_line(m, str8("\n// NOTE: Constants (Float)"));
@@ -3894,17 +3959,17 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
stream_append_str8(&sb, str8("("));
stream_append_f64(&sb, e->constant.F64, 1000000);
columns[0][row_count] = ctx->entity_names.data[id];
- columns[1][row_count] = arena_stream_commit(&m->scratch, &sb);
+ columns[1][row_count] = arena_stream_commit(m->scratch, &sb);
row_count++;
}
}
- metagen_push_table(m, m->scratch, str8("#define " META_NAMESPACE_UPPER), str8(")"), columns, row_count, 2);
-
- m->scratch = ctx->scratch;
+ metagen_push_table(m, str8("#define " META_NAMESPACE_UPPER), str8(")"), columns, row_count, 2);
if (integers || floats) meta_push(m, str8("\n"));
}
+ arena_clear(m->scratch);
+
/////////////////////////
// NOTE(rnp): enumerants
struct {MetaEntityKind kind; b32 flags;} enums[] = {
@@ -3916,13 +3981,14 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
da_count id = ctx->entity_kind_ids[enums[it].kind][kind];
MetaEntity *e = ctx->entities.data + id;
- str8 enum_name = push_str8_from_parts(&m->scratch, str8(""), str8(META_NAMESPACE_UPPER),
+ str8 enum_name = push_str8_from_parts(m->scratch, str8(""), str8(META_NAMESPACE_UPPER),
ctx->entity_names.data[id]);
- metagen_push_c_enum(m, m->scratch, enum_name, enums[it].flags, e->table.entries[0], e->table.entry_count);
- m->scratch = ctx->scratch;
+ metagen_push_c_enum(m, enum_name, enums[it].flags, e->table.entries[0], e->table.entry_count);
}
}
+ arena_clear(m->scratch);
+
// TODO(rnp): technically this needs to be namespaced to the file they are coming from
if (ctx->entity_kind_counts[MetaEntityKind_Shader]) {
str8 kind = str8(META_NAMESPACE_UPPER "ShaderKind");
@@ -3934,8 +4000,8 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
meta_push_line(m, kind_full, str8("Count,\n"));
str8 *columns[2];
- columns[0] = push_array(&m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_ShaderGroup] * 3);
- columns[1] = push_array(&m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_ShaderGroup] * 3);
+ columns[0] = push_array(m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_ShaderGroup] * 3);
+ columns[1] = push_array(m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_ShaderGroup] * 3);
u32 rows = 0;
for (da_count group = 0; group < ctx->entity_kind_counts[MetaEntityKind_ShaderGroup]; group++) {
@@ -3950,27 +4016,28 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
str8 first_name = ctx->entity_names.data[ctx->entities.data[child.value].previous_sibling.value];
str8 last_name = ctx->entity_names.data[child.value];
- columns[0][3 * group + 0] = push_str8_from_parts(&m->scratch, str8(""), kind, str8("_"), name, str8("First"));
- columns[1][3 * group + 0] = push_str8_from_parts(&m->scratch, str8(""), str8("= "), kind, str8("_"), first_name);
+ columns[0][3 * group + 0] = push_str8_from_parts(m->scratch, str8(""), kind, str8("_"), name, str8("First"));
+ columns[1][3 * group + 0] = push_str8_from_parts(m->scratch, str8(""), str8("= "), kind, str8("_"), first_name);
- columns[0][3 * group + 1] = push_str8_from_parts(&m->scratch, str8(""), kind, str8("_"), name, str8("Last"));
- columns[1][3 * group + 1] = push_str8_from_parts(&m->scratch, str8(""),str8("= "), kind, str8("_"), last_name);
+ columns[0][3 * group + 1] = push_str8_from_parts(m->scratch, str8(""), kind, str8("_"), name, str8("Last"));
+ columns[1][3 * group + 1] = push_str8_from_parts(m->scratch, str8(""),str8("= "), kind, str8("_"), last_name);
- columns[0][3 * group + 2] = push_str8_from_parts(&m->scratch, str8(""), kind, str8("_"), name, str8("Count"));
+ columns[0][3 * group + 2] = push_str8_from_parts(m->scratch, str8(""), kind, str8("_"), name, str8("Count"));
Stream sb = arena_stream(m->scratch);
stream_append_str8(&sb, str8("= "));
stream_append_i64(&sb, shader_count);
- columns[1][3 * group + 2] = arena_stream_commit(&m->scratch, &sb);
+ columns[1][3 * group + 2] = arena_stream_commit(m->scratch, &sb);
rows += 3;
}
}
- metagen_push_table(m, m->scratch, str8(""), str8(","), columns, rows, 2);
+ metagen_push_table(m, str8(""), str8(","), columns, rows, 2);
meta_end_scope(m, str8("} "), kind, str8(";\n"));
- m->scratch = ctx->scratch;
}
+ arena_clear(m->scratch);
+
//////////////////////
// NOTE(rnp): structs
{
@@ -4000,25 +4067,23 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
DeferLoop(meta_begin_scope(m, str8("typedef union {")),
meta_end_scope(m, str8("} " META_NAMESPACE_UPPER "ShaderBakeParameters;\n")))
{
- Arena scratch;
- DeferLoop(scratch = m->scratch, m->scratch = scratch)
- {
- str8 *columns[2];
- columns[0] = push_array(&m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
- columns[1] = push_array(&m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
+ str8 *columns[2];
+ columns[0] = push_array(m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
+ columns[1] = push_array(m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
- for (da_count bake = 0; bake < ctx->entity_kind_counts[MetaEntityKind_BakeParameters]; bake++) {
- da_count id = ctx->entity_kind_ids[MetaEntityKind_BakeParameters][bake];
+ for (da_count bake = 0; bake < ctx->entity_kind_counts[MetaEntityKind_BakeParameters]; bake++) {
+ da_count id = ctx->entity_kind_ids[MetaEntityKind_BakeParameters][bake];
- str8 bake_name = ctx->entity_names.data[id];
- str8 shader_name = {.data = bake_name.data, .length = bake_name.length - str8("BakeParameters").length};
+ str8 bake_name = ctx->entity_names.data[id];
+ str8 shader_name = {.data = bake_name.data, .length = bake_name.length - str8("BakeParameters").length};
- columns[0][bake] = push_str8_from_parts(&m->scratch, str8(""), str8(META_NAMESPACE_UPPER), bake_name);
- columns[1][bake] = shader_name;
- }
- metagen_push_table(m, m->scratch, str8(""), str8(";"), columns,
- ctx->entity_kind_counts[MetaEntityKind_BakeParameters], 2);
+ columns[0][bake] = push_str8_from_parts(m->scratch, str8(""), str8(META_NAMESPACE_UPPER), bake_name);
+ columns[1][bake] = shader_name;
}
+ metagen_push_table(m, str8(""), str8(";"), columns,
+ ctx->entity_kind_counts[MetaEntityKind_BakeParameters], 2);
+
+ arena_clear(m->scratch);
}
metagen_run_emit_set(m, ctx, ctx->emit_sets + MetaEmitLang_C, meta_kind_c_types);
@@ -4035,7 +4100,6 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
meta_push_line(m, kind_full, str8("Count,"));
}
- m->scratch = ctx->scratch;
// TODO(rnp): we may want this to include more than just the bake structs
if (ctx->base_shader_count)
@@ -4048,7 +4112,7 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
str8 *columns[4];
for EachElement(columns, it)
- columns[it] = push_array(&m->scratch, str8, s->info.member_count);
+ columns[it] = push_array(m->scratch, str8, s->info.member_count);
u32 offset = 0;
for EachIndex((u64)s->info.member_count, member) {
@@ -4057,13 +4121,13 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
Stream sb = arena_stream(m->scratch);
stream_append_u64(&sb, s->type_ids[member]); stream_append_byte(&sb, ',');
- columns[0][member] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[0][member] = arena_stream_commit_and_reset(m->scratch, &sb);
stream_append_u64(&sb, offset); stream_append_byte(&sb, ',');
- columns[1][member] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[1][member] = arena_stream_commit_and_reset(m->scratch, &sb);
stream_append_u64(&sb, s->elements[member]); stream_append_byte(&sb, ',');
- columns[2][member] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[2][member] = arena_stream_commit_and_reset(m->scratch, &sb);
columns[3][member] = str8("0"); // TODO(rnp): reference type flag
@@ -4071,8 +4135,9 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
}
DeferLoop(meta_begin_scope(m, str8("(MetaStructMember []){")), meta_end_scope(m, str8("},")))
- metagen_push_table(m, m->scratch, str8("{"), str8("},"), columns, s->info.member_count, countof(columns));
- m->scratch = ctx->scratch;
+ metagen_push_table(m, str8("{"), str8("},"), columns, s->info.member_count, countof(columns));
+
+ arena_clear(m->scratch);
}
}
@@ -4096,28 +4161,29 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
{
str8 *columns[4];
for EachElement(columns, it)
- columns[it] = push_array(&m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
+ columns[it] = push_array(m->scratch, str8, ctx->entity_kind_counts[MetaEntityKind_BakeParameters]);
for EachIndex((u64)ctx->entity_kind_counts[MetaEntityKind_BakeParameters], id) {
da_count entity = ctx->entity_kind_ids[MetaEntityKind_BakeParameters][id];
MetaTable *t = &ctx->entities.data[entity].table;
MetaStruct *s = ctx->struct_infos + t->struct_info_id;
- columns[0][id] = push_str8_from_parts(&m->scratch, str8(""), ctx->entity_names.data[entity], str8("\"),"));
+ columns[0][id] = push_str8_from_parts(m->scratch, str8(""), ctx->entity_names.data[entity], str8("\"),"));
Stream sb = arena_stream(m->scratch);
stream_append_u64(&sb, s->info.member_count); stream_append_byte(&sb, ',');
- columns[1][id] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[1][id] = arena_stream_commit_and_reset(m->scratch, &sb);
stream_append_u64(&sb, s->info.size); stream_append_byte(&sb, ',');
- columns[2][id] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[2][id] = arena_stream_commit_and_reset(m->scratch, &sb);
columns[3][id] = str8("0"); // TODO(rnp): union flags
}
- metagen_push_table(m, m->scratch, str8("{str8_comp(\""), str8("},"), columns,
+ metagen_push_table(m, str8("{str8_comp(\""), str8("},"), columns,
ctx->entity_kind_counts[MetaEntityKind_BakeParameters], countof(columns));
- m->scratch = ctx->scratch;
+
+ arena_clear(m->scratch);
}
/////////////////////////////////
@@ -4235,6 +4301,8 @@ metagen_emit_c_code(MetaContext *ctx, Arena arena)
result = meta_write_and_reset(m, out);
+ arena_clear(m->scratch);
+
return result;
}
@@ -4243,10 +4311,10 @@ metagen_matlab_union(MetaprogramContext *m, MetaContext *ctx, MetaStruct *u, str
{
b32 result = 1;
- Arena scratch;
- DeferLoop(scratch = m->scratch, m->scratch = scratch)
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
{
- str8 outfile = push_str8_from_parts(&m->scratch, str8(OS_PATH_SEPARATOR), outdir, str8("Base.m"));
+ str8 outfile = push_str8_from_parts(m->scratch, str8(OS_PATH_SEPARATOR), outdir, str8("Base.m"));
meta_begin_scope(m, str8("classdef Base"));
{
meta_begin_scope(m, str8("properties (Constant)"));
@@ -4272,11 +4340,11 @@ metagen_matlab_union(MetaprogramContext *m, MetaContext *ctx, MetaStruct *u, str
break;
}
- DeferLoop(scratch = m->scratch, m->scratch = scratch)
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
{
MetaStruct *s = ctx->struct_infos + ctx->entities.data[u->type_ids[union_member]].table.struct_info_id;
str8 sub_name = u->members[union_member];
- str8 outfile = push_str8_from_parts(&m->scratch, str8(""), outdir, str8(OS_PATH_SEPARATOR), sub_name, str8(".m"));
+ str8 outfile = push_str8_from_parts(m->scratch, str8(""), outdir, str8(OS_PATH_SEPARATOR), sub_name, str8(".m"));
DeferLoop(meta_begin_scope(m, str8("classdef "), sub_name, str8(" < " MATLAB_NAMESPACE META_NAMESPACE_UPPER),
namespace, str8(".Base")),
meta_end_scope(m, str8("end")))
@@ -4297,9 +4365,9 @@ metagen_matlab_union(MetaprogramContext *m, MetaContext *ctx, MetaStruct *u, str
meta_push_line(m, str8("bytes = zeros(1, obj.byteSize, 'uint8');"));
str8 *columns[3];
- columns[0] = push_array(&m->scratch, str8, s->info.member_count);
- columns[1] = push_array(&m->scratch, str8, s->info.member_count);
- columns[2] = push_array(&m->scratch, str8, s->info.member_count);
+ columns[0] = push_array(m->scratch, str8, s->info.member_count);
+ columns[1] = push_array(m->scratch, str8, s->info.member_count);
+ columns[2] = push_array(m->scratch, str8, s->info.member_count);
u32 offset = 1;
for EachIndex(s->info.member_count, member) {
@@ -4332,7 +4400,7 @@ metagen_matlab_union(MetaprogramContext *m, MetaContext *ctx, MetaStruct *u, str
stream_append_byte(&sb, ')');
offset += member_size;
- columns[0][member] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[0][member] = arena_stream_commit_and_reset(m->scratch, &sb);
stream_append_str8s(&sb, str8("= typecast(obj."), s->members[member]);
if (s->member_flags[member] & MetaStructMemberFlag_ReferenceType) {
@@ -4349,11 +4417,11 @@ metagen_matlab_union(MetaprogramContext *m, MetaContext *ctx, MetaStruct *u, str
}
stream_append_byte(&sb, ',');
- columns[1][member] = arena_stream_commit_and_reset(&m->scratch, &sb);
+ columns[1][member] = arena_stream_commit_and_reset(m->scratch, &sb);
columns[2][member] = str8("'uint8');");
}
- metagen_push_table(m, m->scratch, str8("bytes("), str8(""), columns, s->info.member_count, 3);
+ metagen_push_table(m, str8("bytes("), str8(""), columns, s->info.member_count, 3);
}
}
}
@@ -4365,7 +4433,7 @@ metagen_matlab_union(MetaprogramContext *m, MetaContext *ctx, MetaStruct *u, str
}
function b32
-metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
+metagen_emit_matlab_code(MetaContext *ctx, Arena *arena)
{
b32 result = 1;
if (!needs_rebuild(OUTPUT("matlab/OGLBeamformerShaderStage.m"), "beamformer.meta"))
@@ -4386,6 +4454,8 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
MetaprogramContext m[1] = {{.stream = arena_stream(arena), .scratch = ctx->scratch}};
+ arena_clear(m->scratch);
+
meta_begin_matlab_class(m, "OGLBeamformerShaderStage", "int32");
meta_begin_scope(m, str8("enumeration"));
{
@@ -4401,12 +4471,12 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
if (group_id != -1) {
da_count children;
da_count *ids = meta_entity_extract_children(ctx, (MetaEntityID){.value = group_id},
- &children, &m->scratch);
+ &children, m->scratch);
if (children > 0) {
metagen_push_counted_enum_body_from_ids(m, str8(""), str8(""), str8("("), str8(")"), ids,
ctx->entity_names.data, children);
}
- m->scratch = ctx->scratch;
+ arena_clear(m->scratch);
} else {
build_log_failure("failed to find Compute shader group in meta info\n");
}
@@ -4415,10 +4485,9 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
result &= meta_end_and_write_matlab(m, OUTPUT("matlab/OGLBeamformerShaderStage.m"));
for (da_count kind = 0; kind < ctx->entity_kind_counts[MetaEntityKind_Enumeration]; kind++) {
- Arena scratch = ctx->scratch;
da_count id = ctx->entity_kind_ids[MetaEntityKind_Enumeration][kind];
str8 name = ctx->entity_names.data[id];
- str8 output = push_str8_from_parts(&scratch, str8(""), str8(OUTPUT("matlab/OGLBeamformer")), name, str8(".m"));
+ str8 output = push_str8_from_parts(m->scratch, str8(""), str8(OUTPUT("matlab/OGLBeamformer")), name, str8(".m"));
MetaTable *etable = &ctx->entities.data[id].table;
str8 *kinds = etable->entries[0];
@@ -4428,6 +4497,8 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
if (etable->entry_count > 0 && IsDigit(kinds[0].data[0])) prefix = str8("m");
metagen_push_counted_enum_body(m, str8(""), prefix, str8("("), str8(")"), kinds, etable->entry_count);
result &= meta_end_and_write_matlab(m, (c8 *)output.data);
+
+ arena_clear(m->scratch);
}
////////////////////
@@ -4436,14 +4507,14 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
MetaEmitOperationListSet *emit_set = ctx->emit_sets + MetaEmitLang_MATLAB;
for (da_count list = 0; list < emit_set->count; list++) {
MetaEmitOperationList *ops = emit_set->data + list;
- Arena scratch = m->scratch;
- str8 output = push_str8_from_parts(&m->scratch, str8(""),
+ str8 output = push_str8_from_parts(m->scratch, str8(""),
str8(OUTPUT("matlab") OS_PATH_SEPARATOR "OGLBeamformer"),
ops->filename, str8(".m"));
meta_push_line(m, str8("% GENERATED CODE"));
metagen_run_emit(m, ctx, ops, meta_kind_matlab_types);
result &= meta_write_and_reset(m, (c8 *)output.data);
- m->scratch = scratch;
+
+ arena_clear(m->scratch);
}
}
@@ -4451,7 +4522,7 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
// NOTE(rnp): entities marked @MATLAB
{
da_count children;
- da_count *ids = meta_entity_extract_children(ctx, ctx->matlab_entity, &children, &m->scratch);
+ da_count *ids = meta_entity_extract_children(ctx, ctx->matlab_entity, &children, m->scratch);
for EachIndex((u64)children, it) {
MetaEntity *rr = ctx->entities.data + ids[it];
@@ -4461,11 +4532,12 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
switch (re->kind) {
InvalidDefaultCase;
case MetaEntityKind_Union:{
- Arena scratch;
- DeferLoop(scratch = m->scratch, m->scratch = scratch) {
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(m->scratch), temp_end(scratch))
+ {
MetaStruct *s = ctx->struct_infos + re->table.struct_info_id;
str8 name = (rr->reference.scope_name.length > 0) ? rr->reference.scope_name : s->info.name;
- str8 outdir = push_str8_from_parts(&m->scratch, str8(""), str8(OUTPUT("matlab") OS_PATH_SEPARATOR),
+ str8 outdir = push_str8_from_parts(m->scratch, str8(""), str8(OUTPUT("matlab") OS_PATH_SEPARATOR),
str8("+" MATLAB_NAMESPACE META_NAMESPACE_UPPER), name);
os_make_directory((c8 *)outdir.data);
result &= metagen_matlab_union(m, ctx, s, outdir, name);
@@ -4475,7 +4547,7 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
case MetaEntityKind_Struct:{
MetaStruct *s = ctx->struct_infos + re->table.struct_info_id;
str8 name = (rr->reference.scope_name.length > 0) ? rr->reference.scope_name : s->info.name;
- str8 outfile = push_str8_from_parts(&m->scratch, str8(""), str8(OUTPUT("matlab") OS_PATH_SEPARATOR),
+ str8 outfile = push_str8_from_parts(m->scratch, str8(""), str8(OUTPUT("matlab") OS_PATH_SEPARATOR),
str8(MATLAB_NAMESPACE META_NAMESPACE_UPPER), name, str8(".m"));
meta_begin_scope(m, str8("classdef " MATLAB_NAMESPACE META_NAMESPACE_UPPER), name);
{
@@ -4486,9 +4558,10 @@ metagen_emit_matlab_code(MetaContext *ctx, Arena arena)
}
}
- m->scratch = ctx->scratch;
}
+ arena_clear(m->scratch);
+
return result;
}
@@ -4509,8 +4582,8 @@ meta_push_helper_library_header_base(MetaprogramContext *m, MetaContext *ctx)
}
str8 *columns[2];
- columns[0] = push_array(&m->scratch, str8, integers);
- columns[1] = push_array(&m->scratch, str8, integers);
+ columns[0] = push_array(m->scratch, str8, integers);
+ columns[1] = push_array(m->scratch, str8, integers);
u32 row_count = 0;
meta_push_line(m, str8("// NOTE: Constants (Integer)"));
@@ -4522,24 +4595,27 @@ meta_push_helper_library_header_base(MetaprogramContext *m, MetaContext *ctx)
stream_append_str8(&sb, str8("("));
stream_append_u64(&sb, e->constant.U64);
columns[0][row_count] = ctx->entity_names.data[id];
- columns[1][row_count] = arena_stream_commit(&m->scratch, &sb);
+ columns[1][row_count] = arena_stream_commit(m->scratch, &sb);
row_count++;
}
}
- metagen_push_table(m, m->scratch, str8("#define " META_NAMESPACE_UPPER), str8(")"), columns, row_count, 2);
+ metagen_push_table(m, str8("#define " META_NAMESPACE_UPPER), str8(")"), columns, row_count, 2);
meta_push(m, str8("\n"));
}
+ arena_clear(m->scratch);
+
/////////////////////////
// NOTE(rnp): enumerants
for (da_count kind = 0; kind < ctx->entity_kind_counts[MetaEntityKind_Enumeration]; kind++) {
da_count id = ctx->entity_kind_ids[MetaEntityKind_Enumeration][kind];
MetaEntity *e = ctx->entities.data + id;
- str8 enum_name = push_str8_from_parts(&m->scratch, str8(""), str8(META_NAMESPACE_UPPER),
+ str8 enum_name = push_str8_from_parts(m->scratch, str8(""), str8(META_NAMESPACE_UPPER),
ctx->entity_names.data[id]);
- metagen_push_c_enum(m, m->scratch, enum_name, 0, e->table.entries[0], e->table.entry_count);
- m->scratch = ctx->scratch;
+ metagen_push_c_enum(m, enum_name, 0, e->table.entries[0], e->table.entry_count);
+
+ arena_clear(m->scratch);
}
{
@@ -4556,7 +4632,7 @@ meta_push_helper_library_header_base(MetaprogramContext *m, MetaContext *ctx)
if (group_id != -1) {
da_count children;
da_count *ids = meta_entity_extract_children(ctx, (MetaEntityID){.value = group_id},
- &children, &m->scratch);
+ &children, m->scratch);
if (children > 0) {
str8 kind = str8(META_NAMESPACE_UPPER "ShaderKind");
str8 kind_full = str8(META_NAMESPACE_UPPER "ShaderKind_");
@@ -4567,13 +4643,12 @@ meta_push_helper_library_header_base(MetaprogramContext *m, MetaContext *ctx)
meta_push_line(m, kind_full, str8("Count,"));
} meta_end_scope(m, str8("} "), kind, str8(";\n"));
- m->scratch = ctx->scratch;
-
meta_begin_line(m, str8("#define "), kind_full, str8("ComputeCount ("));
meta_push_i64(m, children);
meta_end_line(m, str8(")\n"));
}
- m->scratch = ctx->scratch;
+
+ arena_clear(m->scratch);
} else {
build_log_failure("failed to find Compute shader group in meta info\n");
}
@@ -4596,7 +4671,7 @@ meta_entity_resolve_references(MetaContext *ctx, da_count *ids, u64 id_count)
}
function b32
-metagen_emit_helper_library_header(MetaContext *ctx, Arena arena)
+metagen_emit_helper_library_header(MetaContext *ctx, Arena *arena)
{
b32 result = 1;
char *out = OUTPUT("ogl_beamformer_lib.h");
@@ -4605,16 +4680,18 @@ metagen_emit_helper_library_header(MetaContext *ctx, Arena arena)
build_log_generate("Library Header");
- str8 base_header = read_entire_file("lib/ogl_beamformer_lib_base.h", &arena);
+ str8 base_header = read_entire_file("lib/ogl_beamformer_lib_base.h", arena);
MetaprogramContext m[1] = {{.stream = arena_stream(arena), .scratch = ctx->scratch}};
meta_push_helper_library_header_base(m, ctx);
+
+ arena_clear(m->scratch);
/////////////////////////
// NOTE(rnp): entities marked @Library
{
da_count children;
- da_count *ids = meta_entity_extract_children(ctx, ctx->library_entity, &children, &m->scratch);
+ da_count *ids = meta_entity_extract_children(ctx, ctx->library_entity, &children, m->scratch);
meta_entity_resolve_references(ctx, ids, children);
@@ -4642,7 +4719,8 @@ metagen_emit_helper_library_header(MetaContext *ctx, Arena arena)
}
}
- m->scratch = ctx->scratch;
+
+ arena_clear(m->scratch);
}
metagen_run_emit_set(m, ctx, ctx->emit_sets + MetaEmitLang_CLibrary, meta_kind_base_c_types);
@@ -4659,7 +4737,7 @@ metagen_emit_helper_library_header(MetaContext *ctx, Arena arena)
// NOTE(rnp): entities marked @Library
{
da_count children;
- da_count *ids = meta_entity_extract_children(ctx, ctx->library_entity, &children, &m->scratch);
+ da_count *ids = meta_entity_extract_children(ctx, ctx->library_entity, &children, m->scratch);
meta_entity_resolve_references(ctx, ids, children);
@@ -4684,9 +4762,10 @@ metagen_emit_helper_library_header(MetaContext *ctx, Arena arena)
case MetaEntityKind_Union:{}break;
}
}
- m->scratch = ctx->scratch;
}
+ arena_clear(m->scratch);
+
metagen_run_emit_set(m, ctx, ctx->emit_sets + MetaEmitLang_CLibrary, meta_kind_base_c_types);
meta_push_line(m, str8("// END GENERATED CODE\n"));
@@ -4695,11 +4774,11 @@ metagen_emit_helper_library_header(MetaContext *ctx, Arena arena)
result &= meta_write_and_reset(m, OUTPUT("ogl_beamformer_lib_matlab.h"));
}
- {
- CommandList cpp = {0};
- cmd_append(&arena, &cpp, PREPROCESSOR, out, COMPILER_OUTPUT, OUTPUT("ogl_beamformer_lib_python_ffi.h"));
- result &= run_synchronous(arena, &cpp);
- }
+ CommandList cpp = {0};
+ cmd_append(m->scratch, &cpp, PREPROCESSOR, out, COMPILER_OUTPUT, OUTPUT("ogl_beamformer_lib_python_ffi.h"));
+ result &= run_synchronous(m->scratch, &cpp);
+
+ arena_clear(m->scratch);
return result;
}
@@ -4713,7 +4792,7 @@ metagen_load_context(Arena *arena, char *filename)
}
MetaContext *ctx = push_struct(arena, MetaContext);
- ctx->scratch = sub_arena(arena, MB(1), 16);
+ ctx->scratch = arena_create(.commit_size = MB(1));
ctx->arena = arena;
// NOTE(rnp): nil entity
@@ -4732,7 +4811,6 @@ metagen_load_context(Arena *arena, char *filename)
str8(OS_PATH_SEPARATOR), ctx->filename);
}
- Arena scratch = ctx->scratch;
MetaEntryStack entries = meta_entry_stack_from_file(ctx->arena, filename);
for (i64 i = 0; i < entries.count; i++) {
@@ -4744,15 +4822,15 @@ metagen_load_context(Arena *arena, char *filename)
}break;
case MetaEntryKind_Emit:{
- i += meta_pack_emit(ctx, scratch, e, entries.count - i);
+ i += meta_pack_emit(ctx, e, entries.count - i);
}break;
case MetaEntryKind_Embed:{
- meta_embed(ctx, scratch, e, entries.count - i);
+ meta_embed(ctx, e, entries.count - i);
}break;
case MetaEntryKind_Expand:{
- i += meta_expand(ctx, scratch, e, entries.count - i, 0);
+ i += meta_expand(ctx, e, entries.count - i, 0);
}break;
case MetaEntryKind_Library:
@@ -5063,14 +5141,15 @@ metagen_load_context(Arena *arena, char *filename)
}
}
+ arena_clear(ctx->scratch);
result->arena = 0;
return result;
}
function b32
-metagen_file_direct(Arena arena, char *filename)
+metagen_file_direct(Arena *arena, char *filename)
{
- MetaContext *ctx = metagen_load_context(&arena, filename);
+ MetaContext *ctx = metagen_load_context(arena, filename);
b32 result = ctx && metagen_emit_c_code(ctx, arena);
return result;
}
@@ -5082,20 +5161,31 @@ main(i32 argc, char *argv[])
g_argv0 = argv[0];
b32 result = 1;
- Arena arena = os_alloc_arena(MB(8));
+ Arena *arena = arena_create(.commit_size = MB(8));
+
check_rebuild_self(arena, argc, argv);
+ arena_clear(arena);
os_make_directory(OUTDIR);
result &= metagen_file_direct(arena, "assets" OS_PATH_SEPARATOR "assets.meta");
+ arena_clear(arena);
+
result &= metagen_file_direct(arena, "beamformer_core.meta");
+ arena_clear(arena);
- MetaContext *meta = metagen_load_context(&arena, "beamformer.meta");
+ MetaContext *meta = metagen_load_context(arena, "beamformer.meta");
if (!meta) return 1;
- result &= metagen_emit_c_code(meta, arena);
- result &= metagen_emit_helper_library_header(meta, arena);
- result &= metagen_emit_matlab_code(meta, arena);
+ Temp scratch;
+ DeferLoop(scratch = temp_begin(arena), temp_end(scratch))
+ result &= metagen_emit_c_code(meta, arena);
+ DeferLoop(scratch = temp_begin(arena), temp_end(scratch))
+ result &= metagen_emit_helper_library_header(meta, arena);
+ DeferLoop(scratch = temp_begin(arena), temp_end(scratch))
+ result &= metagen_emit_matlab_code(meta, arena);
+
+ arena_clear(arena);
parse_config(argc, argv);
diff --git a/lib/ogl_beamformer_lib.c b/lib/ogl_beamformer_lib.c
@@ -3,8 +3,6 @@
#define BEAMFORMER_IMPORT static
-#include "../beamformer.h"
-
#include "../util.h"
#include "../generated/beamformer.c"
@@ -314,9 +312,9 @@ beamformer_maximum_rf_data_size(void)
{
u64 result = U64_MAX;
if (check_shared_memory()) {
- Arena sm = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
- g_beamformer_library_context.shared_memory_size);
- result = Min((u64)arena_capacity(&sm, u8), g_beamformer_library_context.bp->capabilities.max_rf_data_size);
+ Arena *sm = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
+ g_beamformer_library_context.shared_memory_size);
+ result = Min(sm->reserved - sm->position, g_beamformer_library_context.bp->capabilities.max_rf_data_size);
}
return result;
}
@@ -491,20 +489,21 @@ function b32
beamformer_push_data_base(void *data, u32 data_size, i32 timeout_ms, u32 block)
{
b32 result = 0;
- Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
- g_beamformer_library_context.shared_memory_size);
+ Arena *scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
+ g_beamformer_library_context.shared_memory_size);
BeamformerParameterBlock *b = beamformer_parameter_block(g_beamformer_library_context.bp, block);
BeamformerParameters *bp = &b->parameters;
BeamformerDataKind data_kind = b->pipeline.data_kind;
BeamformerContrastMode contrast_mode = bp->contrast_mode;
+ u64 arena_size = scratch->reserved - scratch->position;
u64 max_rf_size = g_beamformer_library_context.bp->capabilities.max_rf_data_size;
u32 rf_size = bp->acquisition_count * bp->sample_count * bp->channel_count * beamformer_data_kind_byte_size[data_kind];
u32 raw_size = bp->raw_data_dimensions.x * bp->raw_data_dimensions.y * beamformer_data_kind_byte_size[data_kind];
// TODO(rnp): support multi push upload so that max_rf_size is actual limit
- if (lib_error_check(rf_size <= arena_capacity(&scratch, u8), BufferOverflow) &&
+ if (lib_error_check(rf_size <= arena_size, BufferOverflow) &&
lib_error_check(rf_size <= max_rf_size, RFDataSizeOverflow) &&
lib_error_check(rf_size <= data_size && data_size == raw_size, DataSizeMismatch))
{
@@ -518,11 +517,12 @@ beamformer_push_data_base(void *data, u32 data_size, i32 timeout_ms, u32 block)
u16 data_channel = (u16)b->channel_mapping[channel];
u32 out_off = out_channel_stride * channel;
u32 in_off = in_channel_stride * data_channel;
+ u8 *memory = (u8 *)scratch + scratch->position + out_off;
switch (contrast_mode) {
default:{
/* NOTE(rnp): non temporal copy would be better, but we can't ensure
* 64 byte boundaries. */
- memory_copy(scratch.beg + out_off, (u8 *)data + in_off, out_channel_stride);
+ memory_copy(memory, (u8 *)data + in_off, out_channel_stride);
}break;
case BeamformerContrastMode_A1S2:{
@@ -547,12 +547,10 @@ beamformer_push_data_base(void *data, u32 data_size, i32 timeout_ms, u32 block)
// like mix of the old and new dataset). Putting this here fixes the issue.
// Counter-intuitively this improves throughput on my zen4 test computer,
// however it obviously should not be needed.
- memory_clear(scratch.beg + out_off, 0, out_channel_stride);
+ memory_clear(memory, 0, out_channel_stride);
u32 sample_count = bp->sample_count * beamformer_data_kind_element_count[data_kind];
- reduce_a1s2_fn_table[reduce_a1s2_index_map[data_kind]](scratch.beg + out_off,
- (u8 *)data + in_off,
- sample_count);
+ reduce_a1s2_fn_table[reduce_a1s2_index_map[data_kind]](memory, (u8 *)data + in_off, sample_count);
}break;
}
}
@@ -677,9 +675,9 @@ beamformer_export(BeamformerExportContext export, void *out, i32 timeout_ms)
if (lib_try_lock(BeamformerSharedMemoryLockKind_ExportSync, timeout_ms)) {
if (lib_try_lock(BeamformerSharedMemoryLockKind_ScratchSpace, 0)) {
- Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
- g_beamformer_library_context.shared_memory_size);
- memory_copy(out, scratch.beg, export.size);
+ void *sm = beamformer_shared_memory_data_pointer(g_beamformer_library_context.bp,
+ g_beamformer_library_context.shared_memory_size);
+ memory_copy(out, sm, export.size);
lib_release_lock(BeamformerSharedMemoryLockKind_ScratchSpace);
result = 1;
}
@@ -720,9 +718,10 @@ beamformer_beamform_data(BeamformerSimpleParameters *bp, void *data, uint32_t da
u64 output_size = output_points.x * output_points.y * output_points.z * sizeof(f32);
if (complex) output_size *= 2;
- Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
- g_beamformer_library_context.shared_memory_size);
- if (result && out_data) result &= lib_error_check((i64)output_size <= arena_capacity(&scratch, u8), ExportSpaceOverflow);
+ Arena *scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
+ g_beamformer_library_context.shared_memory_size);
+ u64 scratch_size = scratch->reserved - scratch->position;
+ if (result && out_data) result &= lib_error_check(output_size <= scratch_size, ExportSpaceOverflow);
if (result) {
result = beamformer_push_data_with_compute(data, data_size, 0, 0);
@@ -738,9 +737,10 @@ beamformer_compute_timings(BeamformerComputeStatsTable *output, i32 timeout_ms)
{
b32 result = 0;
if (check_shared_memory()) {
- Arena scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
- g_beamformer_library_context.shared_memory_size);
- if (lib_error_check((i64)sizeof(*output) <= arena_capacity(&scratch, u8), ExportSpaceOverflow)) {
+ Arena *scratch = beamformer_shared_memory_scratch_arena(g_beamformer_library_context.bp,
+ g_beamformer_library_context.shared_memory_size);
+ u64 scratch_size = scratch->reserved - scratch->position;
+ if (lib_error_check(sizeof(*output) <= scratch_size, ExportSpaceOverflow)) {
BeamformerExportContext export = {0};
export.kind = BeamformerExportKind_Stats;
export.size = sizeof(*output);
diff --git a/main_linux.c b/main_linux.c
@@ -79,7 +79,7 @@ struct OSLinuxEntity {
};
typedef struct {
- Arena arena;
+ Arena *arena;
i32 arena_lock;
i32 inotify_handle;
@@ -109,7 +109,7 @@ os_entity_allocate(OSLinuxEntityKind kind)
DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
{
result = SLLPopFreelist(os_linux_context.entity_freelist);
- if (!result) result = push_struct_no_zero(&os_linux_context.arena, OSLinuxEntity);
+ if (!result) result = push_struct_no_zero(os_linux_context.arena, OSLinuxEntity);
}
zero_struct(result);
@@ -148,7 +148,7 @@ os_barrier_alloc(u32 count)
OSBarrier result = {0};
DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
{
- pthread_barrier_t *barrier = push_struct(&os_linux_context.arena, pthread_barrier_t);
+ pthread_barrier_t *barrier = push_struct(os_linux_context.arena, pthread_barrier_t);
pthread_barrier_init(barrier, 0, count);
result.value[0] = (u64)barrier;
}
@@ -231,7 +231,7 @@ os_linux_add_file_watch(str8 path, void *user_context, OSLinuxFileWatchKind kind
os_linux_context.file_watch_directories.last, dir, next, prev);
dir->hash = hash;
- dir->name = push_str8(&os_linux_context.arena, directory);
+ dir->name = push_str8(os_linux_context.arena, directory);
u32 mask = IN_MOVED_TO|IN_CLOSE_WRITE;
dir->handle = inotify_add_watch(os_linux_context.inotify_handle, (c8 *)dir->name.data, mask);
}
@@ -284,11 +284,11 @@ os_window_create(u8 *title, i64 title_length, i32 width, i32 height)
SetConfigFlags(FLAG_VSYNC_HINT|FLAG_WINDOW_ALWAYS_RUN);
str8 name = {.data = title, .length = title_length};
+ Temp scratch;
DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_linux_context.arena), temp_end(scratch))
{
- Arena scratch = os_linux_context.arena;
- name.length = Min(name.length, arena_capacity(&scratch, u8) - 1);
- str8 title_string = push_str8(&scratch, name);
+ str8 title_string = push_str8(scratch.arena, name);
InitWindow(width, height, (char *)title_string.data);
}
@@ -314,12 +314,12 @@ os_get_clipboard_text(i64 *length)
BEAMFORMER_IMPORT void
os_set_clipboard_text(u8 *data, i64 length)
{
+ Temp scratch;
DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_linux_context.arena), temp_end(scratch))
{
- Arena scratch = os_linux_context.arena;
- str8 string = {.data = data, .length = Min(length, arena_capacity(&scratch, u8) - 1)};
- str8 safe_string = push_str8(&scratch, string);
- SetClipboardText((char *)safe_string.data);
+ str8 string = push_str8(scratch.arena, (str8){.data = data, .length = length});
+ SetClipboardText((char *)string.data);
}
}
@@ -339,12 +339,12 @@ load_library(char *name, char *temp_name, u32 flags)
#if BEAMFORMER_DEBUG
function void
-debug_library_reload(BeamformerInput *input)
+debug_library_reload(void *beamformer, BeamformerInput *input)
{
local_persist OSLibrary beamformer_library_handle = {OSInvalidHandleValue};
if ValidHandle(beamformer_library_handle) {
- beamformer_debug_hot_release(input);
+ beamformer_debug_hot_release(beamformer, input);
dlclose((void *)beamformer_library_handle.value[0]);
beamformer_library_handle = (OSLibrary){OSInvalidHandleValue};
}
@@ -354,19 +354,19 @@ debug_library_reload(BeamformerInput *input)
fatal(str8("[os] failed to load: " OS_DEBUG_LIB_NAME "\n"));
if ValidHandle(new_handle) {
- beamformer_debug_hot_reload(new_handle, input);
+ beamformer_debug_hot_reload(new_handle);
beamformer_library_handle = new_handle;
}
}
#else
-#define debug_library_reload(a) (void)(a)
+#define debug_library_reload(a, b) (void)(a), (void)(b)
#endif /* BEAMFORMER_DEBUG */
function void
load_platform_libraries(BeamformerInput *input)
{
#if BEAMFORMER_DEBUG
- debug_library_reload(input);
+ debug_library_reload(0, input);
os_linux_add_file_watch(str8(OS_DEBUG_LIB_NAME), (void *)BeamformerInputEventKind_ExecutableReload,
OSLinuxFileWatchKind_Platform);
#endif
@@ -391,16 +391,15 @@ load_platform_libraries(BeamformerInput *input)
}
function void
-dispatch_file_watch_events(BeamformerInput *input)
+dispatch_file_watch_events(void *beamformer, BeamformerInput *input)
{
- Arena arena = os_linux_context.arena;
- u8 *mem = arena_alloc(&arena, .size = 4096, .align = 16);
+ local_persist alignas(16) u8 mem[KB(4)];
struct inotify_event *event;
u64 current_time = os_timer_count();
i64 rlen;
- while ((rlen = read(os_linux_context.inotify_handle, mem, 4096)) > 0) {
+ while ((rlen = read(os_linux_context.inotify_handle, mem, countof(mem))) > 0) {
for (u8 *data = mem; data < mem + rlen; data += sizeof(*event) + event->len) {
event = (struct inotify_event *)data;
for (OSLinuxFileWatchDirectory *dir = os_linux_context.file_watch_directories.first; dir; dir = dir->next) {
@@ -416,7 +415,7 @@ dispatch_file_watch_events(BeamformerInput *input)
if (fw->kind == OSLinuxFileWatchKind_Platform) {
assert((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload);
if ((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload)
- debug_library_reload(input);
+ debug_library_reload(beamformer, input);
input_event.kind = (u64)fw->user_context;
} else {
input_event.kind = BeamformerInputEventKind_FileEvent;
@@ -440,15 +439,11 @@ main(void)
os_linux_context.system_info.page_size = ARCH_X64? KB(4) : getauxval(AT_PAGESZ);
os_linux_context.system_info.path_separator_byte = '/';
- Arena program_memory = os_alloc_arena(MB(16) + MB(1));
-
- os_linux_context.arena = sub_arena(&program_memory, MB(1), KB(4));
+ os_linux_context.arena = arena_create(.name = "Platform Arena");
os_linux_context.inotify_handle = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
- BeamformerInput *input = push_struct(&program_memory, BeamformerInput);
+ BeamformerInput *input = push_struct(os_linux_context.arena, BeamformerInput);
os_linux_context.input = input;
- input->memory = program_memory.beg;
- input->memory_size = program_memory.end - program_memory.beg;
input->shared_memory = allocate_shared_memory(OS_SHARED_MEMORY_NAME, OS_SHARED_MEMORY_SIZE,
&input->shared_memory_size);
if (input->shared_memory) {
@@ -462,20 +457,20 @@ main(void)
load_platform_libraries(input);
- beamformer_init(input);
+ void *beamformer = beamformer_init(input);
struct pollfd fds[1] = {{0}};
fds[0].fd = os_linux_context.inotify_handle;
fds[0].events = POLLIN;
- while (!WindowShouldClose() && !beamformer_should_close(input)) {
+ while (!WindowShouldClose() && !beamformer_should_close(beamformer, input)) {
os_build_frame_input(input);
poll(fds, countof(fds), 0);
if (fds[0].revents & POLLIN)
- dispatch_file_watch_events(input);
+ dispatch_file_watch_events(beamformer, input);
- beamformer_frame_step(input);
+ beamformer_frame_step(beamformer, input);
// NOTE(rnp): this must happen at the end of frame to allow the pre loop events through
// TODO(rnp): hack: until raylib is removed this happens in ui since raylib will cause
@@ -483,7 +478,7 @@ main(void)
//input->event_count = 0;
}
- beamformer_terminate(input);
+ beamformer_terminate(beamformer, input);
/* NOTE: make sure this will get cleaned up after external
* programs release their references */
diff --git a/main_w32.c b/main_w32.c
@@ -115,7 +115,7 @@ struct OSW32Entity {
};
typedef struct {
- Arena arena;
+ Arena *arena;
i32 arena_lock;
i64 error_handle;
i64 io_completion_handle;
@@ -145,7 +145,7 @@ os_entity_allocate(OSW32EntityKind kind)
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
{
result = SLLPopFreelist(os_w32_context.entity_freelist);
- if (!result) result = push_struct_no_zero(&os_w32_context.arena, OSW32Entity);
+ if (!result) result = push_struct_no_zero(os_w32_context.arena, OSW32Entity);
}
zero_struct(result);
@@ -164,10 +164,11 @@ os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn
{
OSThread result = {(u64)CreateThread(0, 0, (iptr)fn, (iptr)user_context, 0, 0)};
if (result.value[0]) {
+ Temp scratch;
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
{
- Arena arena = os_w32_context.arena;
- SetThreadDescription(result.value[0], str16_from_str8(&arena, str8_from_c_str((c8 *)name)).data);
+ SetThreadDescription(result.value[0], str16_from_str8(scratch.arena, str8_from_c_str((c8 *)name)).data);
}
} else {
result.value[0] = OSInvalidHandleValue;
@@ -181,7 +182,7 @@ os_barrier_alloc(u32 count)
OSBarrier result = {0};
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
{
- w32_synchronization_barrier *barrier = push_struct(&os_w32_context.arena, w32_synchronization_barrier);
+ w32_synchronization_barrier *barrier = push_struct(os_w32_context.arena, w32_synchronization_barrier);
InitializeSynchronizationBarrier(barrier, (i32)count, -1);
result.value[0] = (u64)barrier;
}
@@ -262,7 +263,7 @@ os_w32_add_file_watch(str8 path, void *user_context, OSW32FileWatchKind kind)
os_w32_context.file_watch_directories.last, dir, next, prev);
dir->hash = hash;
- dir->name = push_str8(&os_w32_context.arena, directory);
+ dir->name = push_str8(os_w32_context.arena, directory);
dir->handle = CreateFileA((c8 *)dir->name.data, GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 0);
@@ -271,7 +272,7 @@ os_w32_add_file_watch(str8 path, void *user_context, OSW32FileWatchKind kind)
dir->event.context = (iptr)dir;
CreateIoCompletionPort(dir->handle, os_w32_context.io_completion_handle, (uptr)&dir->event, 0);
- dir->buffer = arena_alloc(&os_w32_context.arena, .size = OSW32_FileWatchDirectoryBufferSize);
+ dir->buffer = arena_alloc(os_w32_context.arena, .size = OSW32_FileWatchDirectoryBufferSize);
ReadDirectoryChangesW(dir->handle, dir->buffer, OSW32_FileWatchDirectoryBufferSize, 0,
FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &dir->overlapped, 0);
}
@@ -324,11 +325,11 @@ os_window_create(u8 *title, i64 title_length, i32 width, i32 height)
SetConfigFlags(FLAG_VSYNC_HINT|FLAG_WINDOW_ALWAYS_RUN);
str8 name = {.data = title, .length = title_length};
+ Temp scratch;
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
{
- Arena scratch = os_w32_context.arena;
- name.length = Min(name.length, arena_capacity(&scratch, u8) - 1);
- str8 title_string = push_str8(&scratch, name);
+ str8 title_string = push_str8(scratch.arena, name);
InitWindow(width, height, (char *)title_string.data);
}
@@ -354,12 +355,12 @@ os_get_clipboard_text(i64 *length)
BEAMFORMER_IMPORT void
os_set_clipboard_text(u8 *data, i64 length)
{
+ Temp scratch;
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
{
- Arena scratch = os_w32_context.arena;
- str8 string = {.data = data, .length = Min(length, arena_capacity(&scratch, u8) - 1)};
- str8 safe_string = push_str8(&scratch, string);
- SetClipboardText((char *)safe_string.data);
+ str8 string = push_str8(scratch.arena, (str8){.data = data, .length = length});
+ SetClipboardText((char *)string.data);
}
}
@@ -389,12 +390,12 @@ load_library(char *name, char *temp_name)
#if BEAMFORMER_DEBUG
function void
-debug_library_reload(BeamformerInput *input)
+debug_library_reload(void *beamformer, BeamformerInput *input)
{
local_persist OSLibrary beamformer_library_handle = {OSInvalidHandleValue};
if ValidHandle(beamformer_library_handle) {
- beamformer_debug_hot_release(input);
+ beamformer_debug_hot_release(beamformer, input);
FreeLibrary(beamformer_library_handle.value[0]);
beamformer_library_handle = (OSLibrary){OSInvalidHandleValue};
}
@@ -404,19 +405,19 @@ debug_library_reload(BeamformerInput *input)
fatal(str8("[os] failed to load: " OS_DEBUG_LIB_NAME "\n"));
if ValidHandle(new_handle) {
- beamformer_debug_hot_reload(new_handle, input);
+ beamformer_debug_hot_reload(new_handle);
beamformer_library_handle = new_handle;
}
}
#else
-#define debug_library_reload(a) (void)(a)
+#define debug_library_reload(a, b) (void)(a), (void)(b)
#endif /* BEAMFORMER_DEBUG */
function void
load_platform_libraries(BeamformerInput *input)
{
#if BEAMFORMER_DEBUG
- debug_library_reload(input);
+ debug_library_reload(0, input);
os_w32_add_file_watch(str8(OS_DEBUG_LIB_NAME), (void *)BeamformerInputEventKind_ExecutableReload,
OSW32FileWatchKind_Platform);
#endif
@@ -441,18 +442,12 @@ load_platform_libraries(BeamformerInput *input)
}
function void
-dispatch_file_watch(BeamformerInput *input, Arena arena, u64 current_time, OSW32FileWatchDirectory *fw_dir)
+dispatch_file_watch(void *beamformer, BeamformerInput *input, u64 current_time, OSW32FileWatchDirectory *fw_dir, Arena *scratch)
{
- TempArena save_point = {0};
- i64 offset = 0;
-
+ i64 offset = 0;
w32_file_notify_info *fni = (w32_file_notify_info *)fw_dir->buffer;
+ Stream e = stream_alloc(scratch, KB(1));
do {
- end_temp_arena(save_point);
- save_point = begin_temp_arena(&arena);
-
- Stream e = {.data = arena_commit(&arena, KB(1)), .cap = KB(1)};
-
if (fni->action != FILE_ACTION_MODIFIED) {
stream_append_str8(&e, str8("[os] unknown file watch event: "));
stream_append_u64(&e, fni->action);
@@ -461,7 +456,7 @@ dispatch_file_watch(BeamformerInput *input, Arena arena, u64 current_time, OSW32
stream_reset(&e, 0);
}
- str8 file_name = str8_from_str16(&arena, (str16){.data = fni->filename, .length = fni->filename_size / 2});
+ str8 file_name = str8_from_str16(scratch, (str16){.data = fni->filename, .length = fni->filename_size / 2});
u64 hash = u64_hash_from_str8(file_name);
for (OSW32FileWatch *fw = fw_dir->first_child; fw; fw = fw->next) if (fw->hash == hash) {
// NOTE(rnp): avoid multiple updates in a single frame
@@ -470,7 +465,7 @@ dispatch_file_watch(BeamformerInput *input, Arena arena, u64 current_time, OSW32
if (fw->kind == OSW32FileWatchKind_Platform) {
assert((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload);
if ((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload)
- debug_library_reload(input);
+ debug_library_reload(beamformer, input);
input_event.kind = (u64)fw->user_context;
} else {
input_event.kind = BeamformerInputEventKind_FileEvent;
@@ -488,7 +483,7 @@ dispatch_file_watch(BeamformerInput *input, Arena arena, u64 current_time, OSW32
}
function void
-clear_io_queue(BeamformerInput *input, Arena arena)
+clear_io_queue(void *beamformer, BeamformerInput *input, Arena *scratch)
{
iptr handle = os_w32_context.io_completion_handle;
w32_overlapped *overlapped;
@@ -502,7 +497,7 @@ clear_io_queue(BeamformerInput *input, Arena arena)
switch (event->tag) {
case W32IOEvent_FileWatch:{
OSW32FileWatchDirectory *dir = (OSW32FileWatchDirectory *)event->context;
- dispatch_file_watch(input, arena, current_time, dir);
+ dispatch_file_watch(beamformer, input, current_time, dir, scratch);
zero_struct(&dir->overlapped);
ReadDirectoryChangesW(dir->handle, dir->buffer, OSW32_FileWatchDirectoryBufferSize, 0,
FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &dir->overlapped, 0);
@@ -526,13 +521,10 @@ main(void)
os_w32_context.system_info.logical_processor_count = info.number_of_processors;
}
- Arena program_memory = os_alloc_arena(MB(16) + MB(2));
- os_w32_context.arena = sub_arena(&program_memory, MB(2), os_w32_context.system_info.page_size);
+ os_w32_context.arena = arena_create(.name = "Platform Arena");
- BeamformerInput *input = push_struct(&program_memory, BeamformerInput);
+ BeamformerInput *input = push_struct(os_w32_context.arena, BeamformerInput);
os_w32_context.input = input;
- input->memory = program_memory.beg;
- input->memory_size = program_memory.end - program_memory.beg;
input->shared_memory = allocate_shared_memory(OS_SHARED_MEMORY_NAME, OS_SHARED_MEMORY_SIZE,
&input->shared_memory_size);
if (input->shared_memory) {
@@ -546,17 +538,19 @@ main(void)
load_platform_libraries(input);
- beamformer_init(input);
+ void *beamformer = beamformer_init(input);
- while (!WindowShouldClose() && !beamformer_should_close(input)) {
+ while (!WindowShouldClose() && !beamformer_should_close(beamformer, input)) {
os_build_frame_input(input);
+ Temp scratch;
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
{
- clear_io_queue(input, os_w32_context.arena);
+ clear_io_queue(beamformer, input, scratch.arena);
}
- beamformer_frame_step(input);
+ beamformer_frame_step(beamformer, input);
// NOTE(rnp): this must happen at the end of frame to allow the pre loop events through
// TODO(rnp): hack: until raylib is removed this happens in ui since raylib will cause
@@ -564,5 +558,5 @@ main(void)
//input->event_count = 0;
}
- beamformer_terminate(input);
+ beamformer_terminate(beamformer, input);
}
diff --git a/math.c b/math.c
@@ -33,7 +33,7 @@ kronecker_product_f16(f16 *out, f16 *a, iv2 a_dim, f16 *b, iv2 b_dim)
/* NOTE/TODO: to support even more hadamard sizes use the Paley construction */
function f16 *
-make_hadamard_transpose(Arena *a, i32 dim, b32 row_major)
+make_hadamard_transpose(Arena *arena, i32 dim, b32 row_major)
{
read_only local_persist f16 hadamard_12_12_transpose[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -93,11 +93,11 @@ make_hadamard_transpose(Arena *a, i32 dim, b32 row_major)
dim /= 12;
}
- if (power_of_2 && base_dim && arena_capacity(a, f16) >= elements * (1 + (dim != base_dim))) {
- result = push_array(a, f16, elements);
+ if (power_of_2 && base_dim) {
+ result = push_array(arena, f16, elements);
- Arena tmp = *a;
- f16 *m = dim == base_dim ? result : push_array(&tmp, f16, elements);
+ Temp scratch = temp_begin(arena);
+ f16 *m = dim == base_dim ? result : push_array(arena, f16, elements);
#define IND(i, j) ((i) * dim + (j))
m[0] = 1;
@@ -120,6 +120,8 @@ make_hadamard_transpose(Arena *a, i32 dim, b32 row_major)
case 20:{ m2 = hadamard_20_20_transpose; m2_dim = (iv2){{20, 20}}; }break;
}
if (m2) kronecker_product_f16(result, m, (iv2){{dim, dim}}, m2, m2_dim);
+
+ temp_end(scratch);
}
if (row_major) {
diff --git a/os_linux.c b/os_linux.c
@@ -69,19 +69,61 @@ os_number_of_processors(void)
return result > 0 ? result : 1;
}
-function OS_ALLOC_ARENA_FN(os_alloc_arena)
-{
- Arena result = {0};
- capacity = round_up_to(capacity, ARCH_X64? (i64)KB(4) : (i64)getauxval(AT_PAGESZ));
- void *memory = mmap(0, (u64)capacity, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- if (memory != MAP_FAILED) {
- result.beg = memory;
- result.end = result.beg + capacity;
- asan_poison_region(result.beg, result.end - result.beg);
+#ifndef BEAMFORMER_H
+// TODO(rnp): fix main and platform code split
+
+function OSSystemInfo *
+os_system_info(void)
+{
+ local_persist b32 ready = 0;
+ local_persist OSSystemInfo linux_system_info = {0};
+ if unlikely(!ready) {
+ linux_system_info.timer_frequency = os_timer_frequency();
+ linux_system_info.logical_processor_count = os_number_of_processors();
+ linux_system_info.page_size = ARCH_X64? KB(4) : getauxval(AT_PAGESZ);
+ linux_system_info.path_separator_byte = '/';
+ ready = 1;
}
+ return &linux_system_info;
+}
+
+#endif
+
+BEAMFORMER_IMPORT void *
+os_memory_reserve(u64 size)
+{
+ void *result = mmap(0, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ if (result == MAP_FAILED)
+ result = 0;
return result;
}
+BEAMFORMER_IMPORT void
+os_memory_release(void *base, u64 size)
+{
+ munmap(base, size);
+}
+
+BEAMFORMER_IMPORT b32
+os_memory_commit(void *base, u64 size)
+{
+ mprotect(base, size, PROT_READ|PROT_WRITE);
+ return 1;
+}
+
+BEAMFORMER_IMPORT void
+os_memory_uncommit(void *base, u64 size)
+{
+ madvise(base, size, MADV_DONTNEED);
+ mprotect(base, size, PROT_NONE);
+}
+
+BEAMFORMER_IMPORT void
+os_memory_seal(void *base, u64 size)
+{
+ mprotect(base, size, PROT_READ);
+}
+
BEAMFORMER_IMPORT OS_READ_ENTIRE_FILE_FN(os_read_entire_file)
{
i64 result = 0;
diff --git a/os_win32.c b/os_win32.c
@@ -11,9 +11,12 @@
#define STD_OUTPUT_HANDLE -11
#define STD_ERROR_HANDLE -12
+#define PAGE_READONLY 0x02
#define PAGE_READWRITE 0x04
#define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000
+#define MEM_DECOMMIT 0x4000
+#define MEM_RELEASE 0x8000
#define GENERIC_WRITE 0x40000000
#define GENERIC_READ 0x80000000
@@ -120,6 +123,8 @@ W32(b32) WaitOnAddress(void *, void *, u64, u32);
W32(i32) WakeByAddressAll(void *);
W32(b32) WriteFile(iptr, u8 *, i32, i32 *, void *);
W32(void *) VirtualAlloc(u8 *, i64, u32, u32);
+W32(b32) VirtualFree(void *, u64, u32);
+W32(b32) VirtualProtect(void *, u64, u32, u32 *);
function b32
os_write_file(iptr file, void *data, i64 length)
@@ -152,27 +157,62 @@ os_timer_count(void)
return result;
}
-function u32
-os_get_page_size(void)
+#ifndef BEAMFORMER_H
+// TODO(rnp): fix main and platform code split
+
+function OSSystemInfo *
+os_system_info(void)
+{
+ local_persist b32 ready = 0;
+ local_persist OSSystemInfo w32_platform_info = {0};
+ if unlikely(!ready) {
+ w32_system_info info = {0};
+ GetSystemInfo(&info);
+ w32_platform_info.timer_frequency = os_timer_frequency();
+ w32_platform_info.path_separator_byte = '\\';
+ w32_platform_info.page_size = info.page_size;
+ w32_platform_info.logical_processor_count = info.number_of_processors;
+ ready = 1;
+ }
+ return &w32_platform_info;
+}
+
+#endif
+
+BEAMFORMER_IMPORT void *
+os_memory_reserve(u64 size)
{
- w32_system_info info = {0};
- GetSystemInfo(&info);
- u32 result = info.page_size;
+ void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
return result;
}
-function OS_ALLOC_ARENA_FN(os_alloc_arena)
+BEAMFORMER_IMPORT void
+os_memory_release(void *base, u64 size)
{
- Arena result = {0};
- capacity = round_up_to(capacity, os_get_page_size());
- result.beg = VirtualAlloc(0, capacity, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
- if (result.beg) {
- result.end = result.beg + capacity;
- asan_poison_region(result.beg, result.end - result.beg);
- }
+ // NOTE(rnp): size must be 0 on w32, no partial releasing
+ VirtualFree(base, 0, MEM_RELEASE);
+}
+
+BEAMFORMER_IMPORT b32
+os_memory_commit(void *base, u64 size)
+{
+ b32 result = VirtualAlloc(base, size, MEM_COMMIT, PAGE_READWRITE) != 0;
return result;
}
+BEAMFORMER_IMPORT void
+os_memory_uncommit(void *base, u64 size)
+{
+ VirtualFree(base, size, MEM_DECOMMIT);
+}
+
+BEAMFORMER_IMPORT void
+os_memory_seal(void *base, u64 size)
+{
+ u32 w32_dummy;
+ VirtualProtect(base, size, PAGE_READONLY, &w32_dummy);
+}
+
BEAMFORMER_IMPORT OS_READ_ENTIRE_FILE_FN(os_read_entire_file)
{
i64 result = 0;
diff --git a/tests/throughput.c b/tests/throughput.c
@@ -416,18 +416,18 @@ parse_argv(i32 argc, char *argv[])
}
function b32
-send_frame(void *restrict data, BeamformerSimpleParameters *restrict bp)
+send_frame(void *restrict data, BeamformerSimpleParameters *restrict bp, BeamformerViewPlaneTag tag, u32 slot)
{
u32 data_size = bp->raw_data_dimensions.E[0] * bp->raw_data_dimensions.E[1]
* beamformer_data_kind_byte_size[bp->data_kind];
- b32 result = beamformer_push_data_with_compute(data, data_size, BeamformerViewPlaneTag_XZ, 0);
+ b32 result = beamformer_push_data_with_compute(data, data_size, tag, slot);
if (!result && !g_should_exit) printf("lib error: %s\n", beamformer_get_last_error_string());
return result;
}
function void
-execute_study(Arena arena, Stream path, Options *options)
+execute_study(Arena *arena, Stream path, Options *options)
{
i32 path_work_index = path.widx;
stream_ensure_termination(&path, 0);
@@ -457,9 +457,8 @@ execute_study(Arena arena, Stream path, Options *options)
bp.compute_stages[bp.compute_stages_count++] = BeamformerShaderKind_Decode;
bp.compute_stages[bp.compute_stages_count++] = BeamformerShaderKind_DAS;
+ BeamformerFilterParameters filter = {.sampling_frequency = bp.sampling_frequency / 2};
{
- BeamformerFilterParameters filter = {.sampling_frequency = bp.sampling_frequency / 2};
-
BeamformerEmissionParameters *ep = &bp.emission_parameters;
switch (bp.emission_parameters.kind) {
@@ -537,7 +536,7 @@ execute_study(Arena arena, Stream path, Options *options)
u64 start = os_timer_count();
f64 frequency = os_timer_frequency();
for (;!g_should_exit;) {
- if (send_frame(data, &bp)) {
+ if (send_frame(data, &bp, BeamformerViewPlaneTag_XZ, 0)) {
u64 now = os_timer_count();
f64 delta = (now - start) / frequency;
start = now;
@@ -561,7 +560,7 @@ execute_study(Arena arena, Stream path, Options *options)
lip.active = 0;
beamformer_set_live_parameters(&lip);
} else {
- send_frame(data, &bp);
+ send_frame(data, &bp, BeamformerViewPlaneTag_XZ, 0);
}
}
@@ -581,8 +580,8 @@ main(i32 argc, char *argv[])
signal(SIGINT, sigint);
- Arena arena = os_alloc_arena(KB(8));
- Stream path = stream_alloc(&arena, KB(4));
+ Arena *arena = arena_create();
+ Stream path = stream_alloc(arena, KB(4));
stream_append_str8(&path, str8_from_c_str(options.remaining[0]));
execute_study(arena, path, &options);
diff --git a/ui.c b/ui.c
@@ -348,8 +348,8 @@ struct V4Node {V4Node *next; v4 v;};
typedef struct {
- u64 current_frame_index;
- Arena arena;
+ u64 current_frame_index;
+ Arena *arena;
v2 current_mouse;
v2 last_mouse;
@@ -414,8 +414,7 @@ typedef struct {
// NOTE(rnp): Builder State
UINode *node_freelist;
UINode *root_node;
- Arena build_arenas[2];
- TempArena build_arena_savepoints[2];
+ Arena *build_arenas[2];
// NOTE(rnp): Builder Stacks
#define X(type, name, ...) struct {type *top; type *free; u64 count;} name##_node_stack;
UI_STACK_LIST
@@ -466,7 +465,7 @@ UI_STACK_LIST
#undef X
#define ui_node_is_nil(n) ((n) == 0 || (n) == &ui_node_nil)
-#define ui_build_arena() (ui_context->build_arenas + (ui_context->current_frame_index % countof(ui_context->build_arenas)))
+#define ui_build_arena() (ui_context->build_arenas[(ui_context->current_frame_index % countof(ui_context->build_arenas))])
#define UIStackPushBody(name_upper, name_lower, type, new_value) \
name_upper *node = SLLPop(ui_context->name_lower##_node_stack.free, next); \
@@ -772,7 +771,7 @@ push_acquisition_kind(Arena *arena, BeamformerAcquisitionKind kind, u32 transmit
fixed_transmits = beamformer_acquisition_kind_has_fixed_transmits[kind];
}
- Stream sb = arena_stream(*arena);
+ Stream sb = arena_stream(arena);
stream_append_str8(&sb, name);
if (!fixed_transmits) {
stream_append_byte(&sb, '-');
@@ -871,7 +870,7 @@ beamformer_ui_frame_view_new(BeamformerFrameViewKind kind)
{
BeamformerFrameView *old = (BeamformerFrameView *)beamformer_registers()->frame_view;
BeamformerFrameView *result = SLLPopFreelist(ui_context->view_freelist);
- if (!result) result = push_struct_no_zero(&ui_context->arena, typeof(*result));
+ if (!result) result = push_struct_no_zero(ui_context->arena, typeof(*result));
zero_struct(result);
DLLInsertLast(0, ui_context->view_first, ui_context->view_last, result, next, prev);
@@ -1309,7 +1308,7 @@ world_point_to_screen_2d(v2 p, v2 world_min, v2 world_max, v2 screen_min, v2 scr
}
function void
-draw_view_ruler(BeamformerFrameView *view, Arena a, Rect view_rect, TextSpec ts)
+draw_view_ruler(BeamformerFrameView *view, Rect view_rect, TextSpec ts)
{
// TODO(rnp): merge this into draw function, tons of duplicate code
v2 vr_max_p = v2_add(view_rect.pos, view_rect.size);
@@ -1340,7 +1339,7 @@ draw_view_ruler(BeamformerFrameView *view, Arena a, Rect view_rect, TextSpec ts)
if (start_in_bounds) DrawCircleV(rl_v2(start_p), 3, rl_colour);
if (end_in_bounds) DrawCircleV(rl_v2(end_p), 3, rl_colour);
- Stream buf = arena_stream(a);
+ Stream buf = arena_stream(ui_build_arena());
stream_append_f64(&buf, 1e3 * v3_magnitude(v3_sub(end, view->ruler.start)), 100);
stream_append_str8(&buf, str8(" mm"));
@@ -1569,8 +1568,7 @@ ui_text_input_update(BeamformerInput *input)
{
UITextInputState *tis = &ui_context->text_input_state;
- Arena scratch = *ui_build_arena();
- Stream sb = arena_stream(scratch);
+ Stream sb = arena_stream(ui_build_arena());
enum {
DeltaPicksSide = (1 << 0),
@@ -1971,7 +1969,7 @@ ui_build_node_from_key(UINodeFlags flags, UINodeKey key)
if (!ui_node_is_nil(result)) {
SLLStackPop(ui_context->node_freelist, next_sibling);
} else {
- result = push_struct_no_zero(transient ? ui_build_arena() : &ui_context->arena, UINode);
+ result = push_struct_no_zero(transient ? ui_build_arena() : ui_context->arena, UINode);
}
zero_struct(result);
}
@@ -2268,7 +2266,7 @@ function UI_CUSTOM_DRAW_FUNCTION(beamformer_custom_draw_frame_view)
.colour = RULER_COLOUR, .outline_thick = 1, .outline_colour.a = 1,
.limits.size.x = node_rect.size.w};
if (view->kind != BeamformerFrameViewKind_3DXPlane && view->ruler.state != RulerState_None)
- draw_view_ruler(view, *ui_build_arena(), node_rect, text_spec);
+ draw_view_ruler(view, node_rect, text_spec);
}
function b32
@@ -2504,7 +2502,7 @@ function UI_CUSTOM_DRAW_FUNCTION(ui_custom_draw_scale_bar)
rlTranslatef(start_point.x, start_point.y, 0);
rlRotatef(atan2_f32(end_point.y, end_point.x) * 180 / PI, 0, 0, 1);
- Stream buf = arena_stream(*ui_build_arena());
+ Stream buf = arena_stream(ui_build_arena());
f32 inc = v2_magnitude(end_point) / (f32)info->segments;
f32 value_inc = (info->end_value - info->start_value) / (f32)info->segments;
f32 value = info->start_value;
@@ -3188,7 +3186,7 @@ function UI_CUSTOM_DRAW_FUNCTION(beamformer_ui_custom_draw_compute_bar_graph)
if (point_in_rect(ui_context->last_mouse, rect)) {
// TODO(rnp): tooltips
text_pos = v2_add(rect.pos, (v2){{UI_NODE_PAD, 3.f}});
- Stream sb = arena_stream(*ui_build_arena());
+ Stream sb = arena_stream(ui_build_arena());
stream_append_str8s(&sb, beamformer_shader_names[stats->table.shader_ids[i]], str8(": "));
stream_append_f64_e(&sb, stats->table.times[frame_index][i]);
mouse_text = arena_stream_commit(ui_build_arena(), &sb);
@@ -3323,7 +3321,7 @@ ui_build_compute_stats(BeamformerComputePlan *cp, f32 broken_shader_t, Beamforme
MetaStructInfo *si = meta_struct_info_by_id + struct_id;
MetaStructMember *sm = meta_struct_members_by_id[struct_id];
for EachIndex(si->member_count, member) {
- Stream sb = arena_stream(*ui_build_arena());
+ Stream sb = arena_stream(ui_build_arena());
stream_append_struct_member(&sb, sm + member, &sd->bake);
stream_append_str8s(&sb, str8("##"), names[member]);
UIParent(left) ui_label(names[member]);
@@ -3799,7 +3797,7 @@ ui_build_live_imaging_controls(BeamformerUIPanel *panel)
function UISignal
ui_panel_label(BeamformerUIPanel *panel)
{
- Stream sb = arena_stream(*ui_build_arena());
+ Stream sb = arena_stream(ui_build_arena());
switch (panel->kind) {
InvalidDefaultCase;
case BeamformerPanelKind_ComputeBarGraph:{stream_append_str8(&sb, str8("Compute Bar Graph"));}break;
@@ -4477,7 +4475,7 @@ ui_build_drag_overlay(Rect window_rect)
UIParent(ui_spacer(0))
{
// TODO(rnp): cleanup
- Stream sb = arena_stream(*ui_build_arena());
+ Stream sb = arena_stream(ui_build_arena());
stream_appendf(&sb, "###%p_split", panel);
str8 tag = arena_stream_commit(ui_build_arena(), &sb);
@@ -4986,7 +4984,7 @@ beamformer_ui_push_panel_node(BeamformerUIPanel *parent)
BeamformerUI *ui = ui_context;
BeamformerUIPanel *result = ui->tree_node_freelist;
if (result) SLLStackPop(ui->tree_node_freelist, next_sibling);
- else result = push_struct_no_zero(&ui->arena, BeamformerUIPanel);
+ else result = push_struct_no_zero(ui->arena, BeamformerUIPanel);
zero_struct(result);
result->parent = parent;
@@ -5034,17 +5032,15 @@ DEBUG_EXPORT BEAMFORMER_DEBUG_UI_DEINIT_FN(beamformer_debug_ui_deinit)
}
function void
-ui_init(BeamformerCtx *ctx, Arena store)
+ui_init(BeamformerCtx *ctx, Arena *store)
{
BeamformerUI *ui = ui_context = ctx->ui;
if (!ui) {
- ui = ui_context = ctx->ui = push_struct(&store, typeof(*ui));
+ ui = ui_context = ctx->ui = push_struct(store, typeof(*ui));
ui->arena = store;
- for EachElement(ui->build_arenas, it) {
- ui->build_arenas[it] = sub_arena(&ui->arena, KB(128), KB(4));
- ui->build_arena_savepoints[it] = begin_temp_arena(ui->build_arenas + it);
- }
+ for EachElement(ui->build_arenas, it)
+ ui->build_arenas[it] = arena_create();
ui->node_freelist = &ui_node_nil;
/* TODO(rnp): better font, this one is jank at small sizes */
@@ -5099,16 +5095,17 @@ ui_init(BeamformerCtx *ctx, Arena store)
for EachElement(beamformer_reloadable_render_shader_info_indices, it) {
i32 index = beamformer_reloadable_render_shader_info_indices[it];
for (u32 i = 0; i < 2; i++) {
- BeamformerFileReloadContext *frc = push_struct(&ui->arena, typeof(*frc));
+ BeamformerFileReloadContext *frc = push_struct(ui->arena, typeof(*frc));
frc->kind = BeamformerFileReloadKind_RenderShader;
frc->shader_reload.shader = beamformer_reloadable_shader_kinds[index];
frc->shader_reload.pipeline = ui->pipelines + it;
- Arena scratch = ui->arena;
- str8 file = push_str8_from_parts(&scratch, os_path_separator(), str8("shaders"),
+ Temp scratch = temp_begin(ui->arena);
+ str8 file = push_str8_from_parts(ui->arena, os_path_separator(), str8("shaders"),
beamformer_reloadable_shader_files[index][i]);
os_add_file_watch((char *)file.data, file.length, frc);
+ temp_end(scratch);
}
}
}
@@ -5335,7 +5332,7 @@ beamformer_ui_frame(void)
{
////////////////////////////
// NOTE(rnp): Build Pass
- end_temp_arena(ui->build_arena_savepoints[ui->current_frame_index % countof(ui->build_arenas)]);
+ arena_clear(ui_build_arena());
// NOTE(rnp): reset last frame's build stacks
{
#define X(type, name, ...) \
diff --git a/util.c b/util.c
@@ -96,53 +96,40 @@ memory_scan_backwards(void *memory, u8 byte, i64 n)
return result;
}
-function Arena
-arena_from_memory(void *memory, u64 size)
+/* NOTE(rnp): from Hacker's Delight */
+function force_inline u64
+round_down_power_of_two(u64 a)
{
- Arena result;
- result.beg = memory;
- result.end = result.beg + size;
+ u64 result = 0x8000000000000000ULL >> clz_u64(a);
return result;
}
-function void *
-align_pointer_up(void *p, u64 alignment)
+function force_inline u64
+round_up_power_of_two(u64 a)
{
- u64 padding = -(u64)p & (alignment - 1);
- void *result = (u8 *)p + padding;
+ u64 result = 0x8000000000000000ULL >> (clz_u64(a - 1) - 1);
return result;
}
-function void *
-arena_aligned_start(Arena a, u64 alignment)
-{
- return align_pointer_up(a.beg, alignment);
-}
-
-#define arena_capacity(a, t) arena_capacity_(a, sizeof(t), alignof(t))
-function i64
-arena_capacity_(Arena *a, i64 size, u64 alignment)
+function force_inline i64
+round_up_to(i64 value, i64 multiple)
{
- i64 available = a->end - (u8 *)arena_aligned_start(*a, alignment);
- i64 result = available / size;
+ i64 result = value;
+ if (value % multiple != 0)
+ result += multiple - value % multiple;
return result;
}
function u8 *
arena_commit(Arena *a, i64 size)
{
- assert(a->end - a->beg >= size);
- u8 *result = a->beg;
- a->beg += size;
+ Arena *current = a->current;
+ assert(current->committed - current->position >= (u64)size);
+ u8 *result = (u8 *)current + current->position;
+ current->position += size;
return result;
}
-function void
-arena_pop(Arena *a, i64 length)
-{
- a->beg -= length;
-}
-
typedef enum {
ArenaAllocateFlags_NoZero = 1 << 0,
} ArenaAllocateFlags;
@@ -160,61 +147,205 @@ typedef struct {
#define push_struct(a, t) push_array(a, t, 1)
#define push_struct_no_zero(a, t) push_array_no_zero(a, t, 1)
-function void *
-arena_alloc_(Arena *a, ArenaAllocateInfo info)
+#ifndef BEAMFORMER_H
+// TODO(rnp): fix main and platform code split
+typedef struct {
+ u64 timer_frequency;
+ u32 logical_processor_count;
+ u32 page_size;
+ u8 path_separator_byte;
+} OSSystemInfo;
+
+BEAMFORMER_IMPORT OSSystemInfo *os_system_info(void);
+
+BEAMFORMER_IMPORT void *os_memory_reserve(u64 size);
+BEAMFORMER_IMPORT void os_memory_release(void *base, u64 size);
+BEAMFORMER_IMPORT b32 os_memory_commit(void *base, u64 size);
+BEAMFORMER_IMPORT void os_memory_uncommit(void *base, u64 size);
+BEAMFORMER_IMPORT void os_memory_seal(void *base, u64 size);
+#endif
+
+#define arena_create(...) arena_create_((ArenaParameters){\
+ .reserve_size = MB(64),\
+ .commit_size = KB(64),\
+ .flags = 0,\
+ .allocation_site_file = __FILE__,\
+ .allocation_site_line = __LINE__,\
+ __VA_ARGS__})
+
+function Arena *
+arena_create_(ArenaParameters ap)
{
- void *result = 0;
- if (a->beg) {
- u8 *start = arena_aligned_start(*a, info.align);
- i64 available = a->end - start;
- assert((available >= 0 && info.count <= available / info.size));
- asan_unpoison_region(start, info.count * info.size);
- a->beg = start + info.count * info.size;
- result = start;
- if ((info.flags & ArenaAllocateFlags_NoZero) == 0)
- result = memory_clear(start, 0, info.count * info.size);
+ void *base = ap.optional_backing_store;
+ if (base == 0) {
+ ap.commit_size = round_up_to(ap.commit_size, os_system_info()->page_size);
+ ap.reserve_size = round_up_to(ap.reserve_size, os_system_info()->page_size);
+
+ base = os_memory_reserve(ap.reserve_size);
+ os_memory_commit(base, ap.commit_size);
}
+
+ Arena *result = base;
+ result->current = result;
+ result->position = sizeof(*result);
+ result->reserved = ap.reserve_size;
+ result->committed = ap.commit_size;
+ result->flags = ap.flags;
+
+ result->reserve_size = ap.reserve_size;
+ result->commit_size = ap.commit_size;
+
+ result->name = ap.name;
+ result->allocation_site_file = ap.allocation_site_file;
+ result->allocation_site_line = ap.allocation_site_line;
+
return result;
}
-function Arena
-sub_arena(Arena *a, i64 size, u64 align)
+function void
+arena_destroy(Arena *arena)
{
- Arena result = {.beg = arena_alloc(a, .size = size, .align = align, .flags = ArenaAllocateFlags_NoZero)};
- result.end = result.beg + size;
- return result;
+ for (Arena *a = arena->current, *prev = 0; a; a = prev) {
+ prev = a->prev;
+ os_memory_release(a, a->reserved);
+ }
}
-function Arena
-sub_arena_end(Arena *a, i64 len, u64 align)
+function void
+arena_seal(Arena *arena)
{
- Arena result;
- result.beg = (u8 *)((u64)(a->end - len) & ~(align - 1)),
- result.end = a->end,
+ assert(arena == arena->current);
+ u64 position = round_up_to(arena->position, os_system_info()->page_size);
+ if (arena->committed > position) {
+ os_memory_uncommit((u8 *)arena + position, arena->committed - position);
+ arena->committed = position;
+ }
+ if (arena->reserved > arena->committed) {
+ os_memory_release((u8 *)arena + arena->committed, arena->reserved - arena->committed);
+ arena->reserved = arena->committed;
+ }
+ os_memory_seal(arena, arena->reserved);
+}
- a->end = result.beg;
- assert(a->end >= a->beg);
+#define arena_alloc(a, ...) arena_alloc_(a, (ArenaAllocateInfo){.align = 8, .count = 1, ##__VA_ARGS__})
+#define push_array(a, t, n) (t *)arena_alloc(a, .size = sizeof(t), .align = alignof(t), .count = n)
+#define push_array_no_zero(a, t, n) (t *)arena_alloc(a, .size = sizeof(t), .align = alignof(t), .count = n, .flags = ArenaAllocateFlags_NoZero)
+#define push_struct(a, t) push_array(a, t, 1)
+#define push_struct_no_zero(a, t) push_array_no_zero(a, t, 1)
+
+function void *
+arena_alloc_(Arena *arena, ArenaAllocateInfo info)
+{
+ Arena *current = arena->current;
+ u64 size = info.count * info.size;
+ u64 pre_position = AlignUpPowerOfTwo(current->position, info.align);
+ u64 post_position = pre_position + size;
+ u64 zero_size = Min(current->committed, post_position) - pre_position;
+
+ if (current->reserved < post_position && (current->flags & ArenaFlag_NoChain) == 0) {
+ u64 reserve_size = current->reserve_size;
+ u64 commit_size = current->commit_size;
+ if (size + AlignUpPowerOfTwo(sizeof(*arena), info.align) > reserve_size) {
+ reserve_size = size + AlignUpPowerOfTwo(sizeof(*arena), info.align);
+ commit_size = size + AlignUpPowerOfTwo(sizeof(*arena), info.align);
+ }
+ Arena *new_arena = arena_create(.reserve_size = reserve_size,
+ .commit_size = commit_size,
+ .flags = current->flags,
+ .allocation_site_file = current->allocation_site_file,
+ .allocation_site_line = current->allocation_site_line,
+ .name = current->name);
+ zero_size = 0;
+
+ new_arena->base_position = current->base_position + current->reserved;
+ SLLStackPush(arena->current, new_arena, prev);
+ current = new_arena;
+ pre_position = AlignUpPowerOfTwo(current->position, info.align);
+ post_position = pre_position + size;
+ }
+
+ if (current->committed < post_position) {
+ u64 commit_post = post_position + current->commit_size - 1;
+ commit_post -= commit_post % current->commit_size;
+ commit_post = Min(commit_post, current->reserved);
+ os_memory_commit((u8 *)current + current->committed, commit_post - current->committed);
+ current->committed = commit_post;
+ }
+
+ void *result = 0;
+ if (current->committed >= post_position) {
+ result = (u8 *)current + pre_position;
+ current->position = post_position;
+ if ((info.flags & ArenaAllocateFlags_NoZero) == 0)
+ result = memory_clear(result, 0, zero_size);
+ }
+
+ assert(result);
return result;
}
-function TempArena
-begin_temp_arena(Arena *a)
+function u64
+arena_position(Arena *arena)
{
- TempArena result = {.arena = a, .original_arena = *a};
+ Arena *current = arena->current;
+ u64 result = current->base_position + current->position;
return result;
}
function void
-end_temp_arena(TempArena ta)
+arena_pop_to(Arena *arena, u64 position)
{
- Arena *a = ta.arena;
- if (a) {
- assert(a->beg >= ta.original_arena.beg);
- *a = ta.original_arena;
+ position = Max(position, sizeof(*arena));
+ Arena *current = arena->current;
+ for (Arena *prev = 0; current->base_position >= position; current = prev) {
+ prev = current->prev;
+ os_memory_release(current, current->reserved);
}
+ arena->current = current;
+ u64 new_position = position - current->base_position;
+ assert(new_position <= current->position);
+ current->position = new_position;
}
+function void
+arena_pop(Arena *arena, u64 size)
+{
+ u64 old_position = arena_position(arena);
+ u64 new_position = old_position;
+ if (size < old_position)
+ new_position = old_position - size;
+ arena_pop_to(arena, new_position);
+}
+
+function void
+arena_clear(Arena *arena)
+{
+ arena_pop_to(arena, 0);
+}
+
+function void
+arena_pre_align(Arena *arena, u64 align)
+{
+ assert(IsPowerOfTwo(align));
+ Arena *current = arena->current;
+ u8 *start = (u8 *)current + current->position;
+ u8 *desired_start = (u8 *)AlignUpPowerOfTwo((u64)start, align);
+ current->position += (u64)(desired_start - start);
+}
+
+function Temp
+temp_begin(Arena *arena)
+{
+ Temp result = {.arena = arena, .position = arena_position(arena)};
+ return result;
+}
+
+function void
+temp_end(Temp t)
+{
+ arena_pop_to(t.arena, t.position);
+}
enum { DA_INITIAL_CAP = 16 };
@@ -235,23 +366,36 @@ enum { DA_INITIAL_CAP = 16 };
(s)->data + (s)->count++ \
: (s)->data + (s)->count++, 0, sizeof(*(s)->data)))
+
+/* NOTE(rnp): handles both 0 initialized DAs and DAs that need to be moved (they started
+ * on the stack or someone allocated something in the middle of the arena during usage) */
function void *
da_reserve_(Arena *a, void *data, da_count *capacity, da_count needed, u64 align, i64 size)
{
da_count cap = *capacity;
-
- /* NOTE(rnp): handle both 0 initialized DAs and DAs that need to be moved (they started
- * on the stack or someone allocated something in the middle of the arena during usage) */
- if (!data || a->beg != (u8 *)data + cap * size) {
- void *copy = arena_alloc(a, .size = size, .align = align, .count = cap);
- if (data) memory_copy(copy, data, (u64)(cap * size));
- data = copy;
- }
-
if (!cap) cap = DA_INITIAL_CAP;
while (cap < needed) cap *= 2;
- arena_alloc(a, .size = size, .align = align, .count = cap - *capacity);
+
+ Arena *current = a->current;
+ u64 needed_size = cap * size;
+ u64 old_size = *capacity * size;
+ b32 can_extend = data && (u8 *)current + current->position == (u8 *)data + old_size &&
+ (current->reserved - current->position) >= (needed_size - old_size);
+ b32 needs_copy = data && !can_extend;
+
+ u64 alloc_cap = cap;
+ if (can_extend) alloc_cap -= *capacity;
+
+ void *new = arena_alloc(a, .size = size, .align = align, .count = alloc_cap);
+
+ if (needs_copy)
+ memory_copy(new, data, (u64)(*capacity * size));
+
+ if (!can_extend)
+ data = new;
+
*capacity = cap;
+
return data;
}
@@ -326,7 +470,7 @@ stream_from_buffer(u8 *buffer, u32 capacity)
function Stream
stream_alloc(Arena *a, i32 cap)
{
- Stream result = stream_from_buffer(arena_commit(a, cap), (u32)cap);
+ Stream result = stream_from_buffer(push_array_no_zero(a, u8, cap), (u32)cap);
return result;
}
@@ -347,14 +491,6 @@ stream_reset(Stream *s, i32 index)
}
function void
-stream_commit(Stream *s, i32 count)
-{
- s->errors |= !Between(s->widx + count, 0, s->cap);
- if (!s->errors)
- s->widx += count;
-}
-
-function void
stream_append(Stream *s, void *data, i64 count)
{
s->errors |= (s->cap - s->widx) < count;
@@ -565,11 +701,12 @@ stream_append_struct_member(Stream *s, MetaStructMember *m, void *struct_base)
}
function Stream
-arena_stream(Arena a)
+arena_stream(Arena *a)
{
+ Arena *current = a->current;
Stream result = {0};
- result.data = a.beg;
- result.cap = (i32)(a.end - a.beg);
+ result.data = (u8 *)current + current->position;
+ result.cap = (i32)(current->committed - current->position);
/* TODO(rnp): no idea what to do here if we want to maintain the ergonomics */
asan_unpoison_region(result.data, result.cap);
@@ -580,7 +717,8 @@ arena_stream(Arena a)
function str8
arena_stream_commit(Arena *a, Stream *s)
{
- assert(s->data == a->beg);
+ Arena *current = a->current;
+ assert(s->data == (u8 *)current + current->position);
str8 result = stream_to_str8(s);
arena_commit(a, result.length);
return result;
@@ -601,7 +739,7 @@ function str8
arena_stream_commit_and_reset(Arena *arena, Stream *s)
{
str8 result = arena_stream_commit_zero(arena, s);
- *s = arena_stream(*arena);
+ *s = arena_stream(arena);
return result;
}
@@ -759,9 +897,9 @@ str8_from_str16(Arena *a, str16 in)
if (in.length) {
i64 commit = in.length * 4;
i64 length = 0;
- u8 *data = arena_commit(a, commit + 1);
- u16 *beg = in.data;
- u16 *end = in.data + in.length;
+ u8 *data = push_array_no_zero(a, u8, commit + 1);
+ u16 *beg = in.data;
+ u16 *end = in.data + in.length;
while (beg < end) {
UnicodeDecode decode = utf16_decode(beg, end - beg);
length += utf8_encode(data + length, decode.cp);
@@ -801,7 +939,7 @@ push_str8_from_parts_(Arena *arena, str8 joiner, str8 *parts, i64 count)
for (i64 i = 0; i < count; i++)
length += parts[i].length;
- str8 result = {.length = length, .data = arena_commit(arena, length + 1)};
+ str8 result = {.length = length, .data = push_array_no_zero(arena, u8, length + 1)};
i64 offset = 0;
for (i64 i = 0; i < count; i++) {
@@ -830,36 +968,12 @@ push_str8(Arena *a, str8 str)
function str8
push_str8_fv(Arena *arena, const char *format, va_list args)
{
- Stream sb = arena_stream(*arena);
+ Stream sb = arena_stream(arena);
stream_appendfv(&sb, format, args);
str8 result = arena_stream_commit(arena, &sb);
return result;
}
-/* NOTE(rnp): from Hacker's Delight */
-function force_inline u64
-round_down_power_of_two(u64 a)
-{
- u64 result = 0x8000000000000000ULL >> clz_u64(a);
- return result;
-}
-
-function force_inline u64
-round_up_power_of_two(u64 a)
-{
- u64 result = 0x8000000000000000ULL >> (clz_u64(a - 1) - 1);
- return result;
-}
-
-function force_inline i64
-round_up_to(i64 value, i64 multiple)
-{
- i64 result = value;
- if (value % multiple != 0)
- result += multiple - value % multiple;
- return result;
-}
-
function NumberConversion
integer_from_str8(str8 raw)
{
diff --git a/util.h b/util.h
@@ -113,7 +113,9 @@ typedef u64 uptr;
#define Clamp01(x) Clamp(x, 0, 1)
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
-#define IsPowerOfTwo(a) (((a) & ((a) - 1)) == 0)
+
+#define IsPowerOfTwo(a) (((a) & ((a) - 1)) == 0)
+#define AlignUpPowerOfTwo(v, a) (((v) + (a) - 1) & (~((a) - 1)))
#define IsDigit(c) (Between((c), '0', '9'))
#define IsUpper(c) (((c) & 0x20u) == 0)
@@ -181,6 +183,7 @@ typedef u64 uptr;
#define I8_MAX (0x0000007FL)
#define I32_MAX (0x7FFFFFFFL)
+#define S32_MAX (0x7FFFFFFFL)
#define U8_MAX (0x000000FFUL)
#define U16_MAX (0x0000FFFFUL)
#define U32_MAX (0xFFFFFFFFUL)
@@ -207,8 +210,46 @@ typedef alignas(16) union {
u32x4 U32x4;
} u128;
-typedef struct { u8 *beg, *end; } Arena;
-typedef struct { Arena *arena, original_arena; } TempArena;
+typedef enum {
+ ArenaFlag_NoChain = 1 << 0,
+
+ ArenaFlag_CreationMask = ArenaFlag_NoChain,
+
+ ArenaFlag_Sealed = 1 << 31,
+} ArenaFlags;
+
+typedef struct {
+ u64 reserve_size;
+ u64 commit_size;
+ ArenaFlags flags;
+
+ void *optional_backing_store;
+
+ char *name;
+ char *allocation_site_file;
+ i32 allocation_site_line;
+} ArenaParameters;
+
+typedef struct Arena Arena;
+struct Arena {
+ u64 position;
+ u64 committed;
+ u64 reserved;
+
+ // NOTE(rnp): arena chain
+ u64 base_position; // position relative to first arena in chain
+ Arena *prev;
+ Arena *current;
+
+ u64 reserve_size;
+ u64 commit_size;
+ ArenaFlags flags;
+
+ char *name;
+ char *allocation_site_file;
+ i32 allocation_site_line;
+};
+typedef struct { Arena *arena; u64 position; } Temp;
typedef struct { i64 length; u8 *data; } str8;
#define str8(s) (str8){.length = countof(s) - 1, .data = (u8 *)s}
@@ -369,7 +410,6 @@ typedef struct {
LaneContext lane_context;
} ThreadContext;
-#define OS_ALLOC_ARENA_FN(name) Arena name(i64 capacity)
#define OS_READ_ENTIRE_FILE_FN(name) i64 name(const char *file, void *buffer, i64 buffer_capacity)
#define OS_WAIT_ON_ADDRESS_FN(name) b32 name(i32 *value, i32 current, u32 timeout_ms)
#define OS_WAKE_ALL_WAITERS_FN(name) void name(i32 *sync)
diff --git a/vulkan.c b/vulkan.c
@@ -121,7 +121,7 @@ typedef alignas(64) struct {
} VulkanCommandPool;
typedef struct {
- Arena arena;
+ Arena *arena;
i32 arena_lock;
VkInstance handle;
@@ -161,8 +161,8 @@ typedef struct {
VkFormat swap_chain_image_format;
VkFormat depth_stencil_format;
- VulkanEntity * entity_freelist;
- Arena entity_arena;
+ VulkanEntity *entity_freelist;
+ Arena *entity_arena;
i32 entity_lock;
} VulkanContext;
@@ -406,7 +406,7 @@ function void
vk_label_object_(VkObjectType kind, u64 handle, str8 label, str8 extra)
{
local_persist u8 buffer[1024];
- Stream sb = arena_stream(arena_from_memory(buffer, sizeof(buffer)));
+ Stream sb = stream_from_buffer(buffer, countof(buffer));
if (vulkan_config.instance.debug_utils && label.length > 0) {
stream_append_str8s(&sb, label, str8(" ("), extra, str8(")"));
stream_append_byte(&sb, 0);
@@ -433,7 +433,7 @@ vk_entity_allocate(VulkanEntityKind kind)
DeferLoop(take_lock(&vulkan_context->entity_lock, -1), release_lock(&vulkan_context->entity_lock))
{
result = SLLPopFreelist(vulkan_context->entity_freelist);
- if (!result) result = push_array_no_zero(&vulkan_context->entity_arena, VulkanEntity, 1);
+ if (!result) result = push_struct_no_zero(vulkan_context->entity_arena, VulkanEntity);
}
zero_struct(result);
@@ -469,7 +469,7 @@ vk_command_buffer(VulkanHandle h)
#define glslang_log(a, ...) glslang_log_(a, arg_list(str8, __VA_ARGS__))
function void
-glslang_log_(Arena arena, str8 *items, u64 count)
+glslang_log_(Arena *arena, str8 *items, u64 count)
{
Stream sb = arena_stream(arena);
stream_append_str8(&sb, glslang_info(""));
@@ -510,7 +510,7 @@ glsl_to_spirv(Arena *arena, u32 kind, str8 shader_text, str8 name)
}
if (error.length) {
- glslang_log(*arena, name, str8(": "), error, str8("\n"),
+ glslang_log(arena, name, str8(": "), error, str8("\n"),
str8_from_c_str((c8 *)glslang_shader_get_info_log(shader)),
str8_from_c_str((c8 *)glslang_shader_get_info_debug_log(shader)));
glslang_shader_delete(shader);
@@ -542,9 +542,9 @@ glsl_to_spirv(Arena *arena, u32 kind, str8 shader_text, str8 name)
glslang_program_SPIRV_get(program, (u32 *)result.data);
str8 spirv_msg = str8_from_c_str((c8 *)glslang_program_SPIRV_get_messages(program));
- if (spirv_msg.length) glslang_log(*arena, name, str8(": spirv info: "), spirv_msg);
+ if (spirv_msg.length) glslang_log(arena, name, str8(": spirv info: "), spirv_msg);
} else {
- glslang_log(*arena, name, str8(": shader linking failed\n"),
+ glslang_log(arena, name, str8(": shader linking failed\n"),
str8_from_c_str((c8 *)glslang_program_get_info_log(program)),
str8_from_c_str((c8 *)glslang_program_get_info_debug_log(program)));
}
@@ -563,10 +563,10 @@ vk_shader_kind_to_glslang_shader_kind(u32 kind)
}
function VkShaderModule
-vk_compile_shader_module(Arena arena, u32 kind, str8 text, str8 name)
+vk_compile_shader_module(Arena *arena, u32 kind, str8 text, str8 name)
{
VkShaderModule result = {0};
- str8 spirv = glsl_to_spirv(&arena, vk_shader_kind_to_glslang_shader_kind(kind), text, name);
+ str8 spirv = glsl_to_spirv(arena, vk_shader_kind_to_glslang_shader_kind(kind), text, name);
VkShaderModuleCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = (u64)spirv.length,
@@ -607,7 +607,7 @@ vk_specialization_map_from_struct_id(Arena *arena, i32 struct_id)
}
function VulkanPipeline
-vk_compute_pipeline_from_info(Arena arena, VulkanPipelineCreateInfo *info, u32 push_constants_size)
+vk_compute_pipeline_from_info(Arena *arena, VulkanPipelineCreateInfo *info, u32 push_constants_size)
{
VulkanPipeline result = {.stage_flags = VK_SHADER_STAGE_COMPUTE_BIT};
VkShaderModule module = vk_compile_shader_module(arena, VK_SHADER_STAGE_COMPUTE_BIT, info->text, info->name);
@@ -643,7 +643,7 @@ vk_compute_pipeline_from_info(Arena arena, VulkanPipelineCreateInfo *info, u32 p
if (info->specialization_data && info->specialization_struct_id >= 0) {
MetaStructInfo *si = meta_struct_info_by_id + info->specialization_struct_id;
pipeline_create_info.stage.pSpecializationInfo = &specialization_info;
- specialization_info.pMapEntries = vk_specialization_map_from_struct_id(&arena, info->specialization_struct_id);
+ specialization_info.pMapEntries = vk_specialization_map_from_struct_id(arena, info->specialization_struct_id);
specialization_info.mapEntryCount = si->member_count;
specialization_info.dataSize = si->size;
specialization_info.pData = info->specialization_data;
@@ -663,7 +663,7 @@ vk_compute_pipeline_from_info(Arena arena, VulkanPipelineCreateInfo *info, u32 p
}
function VulkanPipeline
-vk_graphics_pipeline_from_infos(Arena arena, VulkanPipelineCreateInfo *infos, u32 count, u32 push_constants_size)
+vk_graphics_pipeline_from_infos(Arena *arena, VulkanPipelineCreateInfo *infos, u32 count, u32 push_constants_size)
{
assume(count == 2);
@@ -1062,8 +1062,9 @@ vk_buffer_allocate_common(VulkanBuffer *vb, VulkanBufferAllocateInfo *ai)
}
function void
-vk_load_instance(Arena arena, Stream *err)
+vk_load_instance(Arena *arena, Stream *err)
{
+ Temp scratch = temp_begin(arena);
#define X(name, ...) name = (name##_fn *)vkGetInstanceProcAddr(0, #name);
VkBaseProcedureList
#undef X
@@ -1083,8 +1084,8 @@ vk_load_instance(Arena arena, Stream *err)
u32 layer_count = 0;
vkEnumerateInstanceLayerProperties(&layer_count, 0);
- VkLayerProperties *layers = push_array(&arena, VkLayerProperties, layer_count);
- str8 *layer_str8s = push_array(&arena, str8, layer_count);
+ VkLayerProperties *layers = push_array(arena, VkLayerProperties, layer_count);
+ str8 *layer_str8s = push_array(arena, str8, layer_count);
vkEnumerateInstanceLayerProperties(&layer_count, layers);
for (u32 i = 0; i < layer_count; i++)
@@ -1115,8 +1116,8 @@ vk_load_instance(Arena arena, Stream *err)
u32 instance_extension_count = 0;
vkEnumerateInstanceExtensionProperties(0, &instance_extension_count, 0);
- VkExtensionProperties *instance_extensions = push_array(&arena, VkExtensionProperties, instance_extension_count);
- str8 *instance_ext_str8s = push_array(&arena, str8, instance_extension_count);
+ VkExtensionProperties *instance_extensions = push_array(arena, VkExtensionProperties, instance_extension_count);
+ str8 *instance_ext_str8s = push_array(arena, str8, instance_extension_count);
vkEnumerateInstanceExtensionProperties(0, &instance_extension_count, instance_extensions);
for EachIndex(instance_extension_count, it)
instance_ext_str8s[it] = str8_from_c_str(instance_extensions[it].extensionName);
@@ -1174,23 +1175,24 @@ vk_load_instance(Arena arena, Stream *err)
#define X(name, ...) name = (name##_fn *)vkGetInstanceProcAddr(vulkan_context->handle, #name);
VkInstanceProcedureList
#undef X
+ temp_end(scratch);
}
function void
-vk_load_physical_device(Arena arena, Stream *err)
+vk_load_physical_device(Arena *arena, Stream *err)
{
+ Temp scratch = temp_begin(arena);
VulkanContext *vk = vulkan_context;
u32 device_count;
vkEnumeratePhysicalDevices(vk->handle, &device_count, 0);
- VkPhysicalDevice *devices = push_array(&arena, typeof(*devices), device_count);
+ VkPhysicalDevice *devices = push_array(arena, typeof(*devices), device_count);
vkEnumeratePhysicalDevices(vk->handle, &device_count, devices);
i32 best_index = -1, best_score = -1;
for (u32 i = 0; i < device_count; i++) {
- Arena scratch = arena;
- VkPhysicalDeviceProperties2 *dp = push_struct(&scratch, typeof(*dp));
+ VkPhysicalDeviceProperties2 *dp = push_struct(arena, typeof(*dp));
dp->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
vkGetPhysicalDeviceProperties2(devices[i], dp);
@@ -1222,17 +1224,16 @@ vk_load_physical_device(Arena arena, Stream *err)
}
{
- Arena scratch = arena;
u32 extension_count = 0;
vkEnumerateDeviceExtensionProperties(vk->physical_device, 0, &extension_count, 0);
- VkExtensionProperties *extensions = push_array(&scratch, VkExtensionProperties, extension_count);
+ VkExtensionProperties *extensions = push_array(arena, VkExtensionProperties, extension_count);
vkEnumerateDeviceExtensionProperties(vk->physical_device, 0, &extension_count, extensions);
- str8 *ext_str8s = push_array(&scratch, str8, extension_count);
+ str8 *ext_str8s = push_array(arena, str8, extension_count);
for (u32 index = 0; index < extension_count; index++)
ext_str8s[index] = str8_from_c_str(extensions[index].extensionName);
- b8 *supported = push_array(&scratch, b8, countof(vk_required_device_extensions));
+ b8 *supported = push_array(arena, b8, countof(vk_required_device_extensions));
for EachIndex(extension_count, index)
for EachElement(vk_required_device_extensions, it)
supported[it] |= str8_equal(vk_required_device_extensions[it], ext_str8s[index]);
@@ -1336,11 +1337,10 @@ vk_load_physical_device(Arena arena, Stream *err)
}
if (vulkan_config.optional.cooperative_matrix) {
- Arena scratch = arena;
u32 property_count = 0;
vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR(vk->physical_device, &property_count, 0);
- VkCooperativeMatrixPropertiesKHR *mat = push_array(&scratch, VkCooperativeMatrixPropertiesKHR, property_count);
+ VkCooperativeMatrixPropertiesKHR *mat = push_array(arena, VkCooperativeMatrixPropertiesKHR, property_count);
// NOTE(rnp): validation layer stupidity
for EachIndex(property_count, it)
@@ -1445,8 +1445,9 @@ vk_load_physical_device(Arena arena, Stream *err)
vk->gpu_info.subgroup_size = v11p.subgroupSize;
vk->gpu_info.max_compute_shared_memory_size = dp.properties.limits.maxComputeSharedMemorySize;
+ temp_end(scratch);
// IMPORTANT(rnp): memory must only be pushed at the end of the function
- vk->gpu_info.name = push_str8(&vk->arena, str8_from_c_str(dp.properties.deviceName));
+ vk->gpu_info.name = push_str8(vk->arena, str8_from_c_str(dp.properties.deviceName));
#if BEAMFORMER_DEBUG
{
@@ -1471,7 +1472,7 @@ vk_load_physical_device(Arena arena, Stream *err)
}
function void
-vk_load_queues(Arena *memory, Stream *err)
+vk_load_queues(Arena *arena, Stream *err)
{
///////////////////////////////////////////////////////
// NOTE(rnp): try to allocate an appropriate queue for
@@ -1486,8 +1487,8 @@ vk_load_queues(Arena *memory, Stream *err)
u32 queue_family_count;
vkGetPhysicalDeviceQueueFamilyProperties(vk->physical_device, &queue_family_count, 0);
- TempArena arena_save = begin_temp_arena(memory);
- VkQueueFamilyProperties *queues = push_array(memory, typeof(*queues), queue_family_count);
+ Temp scratch = temp_begin(arena);
+ VkQueueFamilyProperties *queues = push_array(arena, typeof(*queues), queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(vk->physical_device, &queue_family_count, queues);
i32 queue_indices[VulkanQueueKind_Count];
@@ -1589,7 +1590,7 @@ vk_load_queues(Arena *memory, Stream *err)
for EachElement(assigned_subindices, it)
vk->unique_queues += assigned_subindices[it];
- end_temp_arena(arena_save);
+ temp_end(scratch);
/////////////////////////////////////////////
// NOTE(rnp): fill in info and create device
@@ -1602,7 +1603,7 @@ vk_load_queues(Arena *memory, Stream *err)
for EachElement(vk->queues, it) {
if (vk->queues[vk->queue_indices[it]] == 0) {
- vk->queues[vk->queue_indices[it]] = push_struct(memory, VulkanQueue);
+ vk->queues[vk->queue_indices[it]] = push_struct(vk->arena, VulkanQueue);
vk->queues[vk->queue_indices[it]]->queue_family = queue_indices[it];
vk->queues[vk->queue_indices[it]]->queue_index = queue_subindices[it];
}
@@ -1610,7 +1611,7 @@ vk_load_queues(Arena *memory, Stream *err)
}
for EachElement(vk->command_pools, it)
- vk->command_pools[it] = push_struct(memory, VulkanCommandPool);
+ vk->command_pools[it] = push_struct(vk->arena, VulkanCommandPool);
VkDeviceQueueCreateInfo queue_create_infos[VulkanQueueKind_Count];
@@ -1860,10 +1861,12 @@ vk_load_descriptor_block(void)
vk_label_object(DESCRIPTOR_POOL, vk->descriptor_pool, str8("Beamformer Resources"), str8("Pool"));
- DeferLoop(take_lock(&vk->arena_lock, -1), release_lock(&vk->arena_lock)) {
- Arena scratch = vk->arena;
+ Temp scratch;
+ DeferLoop(take_lock(&vk->arena_lock, -1), release_lock(&vk->arena_lock))
+ DeferLoop(scratch = temp_begin(vk->arena), temp_end(scratch))
+ {
for EachElement(vk->descriptor_sets, it) {
- Stream sb = arena_stream(scratch);
+ Stream sb = arena_stream(vk->arena);
stream_append_str8s(&sb, str8("Beamformer "), beamformer_shader_resource_kind_strings[it], str8("s"));
vk_label_object(DESCRIPTOR_SET, vk->descriptor_sets[it], stream_to_str8(&sb), str8("Set"));
vk_label_object(DESCRIPTOR_SET_LAYOUT, vk->descriptor_set_layouts[it], stream_to_str8(&sb), str8("Set Layout"));
@@ -1879,7 +1882,7 @@ vk_load_descriptor_block(void)
// NOTE(rnp): User API
DEBUG_IMPORT void
-vk_load(OSLibrary vulkan_library_handle, Arena *memory, Stream *err)
+vk_load(OSLibrary vulkan_library_handle, Stream *err)
{
#define X(name, ...) name = (name##_fn *)os_lookup_symbol(vulkan_library_handle, #name);
VkLoaderProcedureList
@@ -1891,12 +1894,12 @@ vk_load(OSLibrary vulkan_library_handle, Arena *memory, Stream *err)
}
VulkanContext *vk = vulkan_context;
- vk->entity_arena = sub_arena_end(memory, KB(64), KB(4));
- vk->arena = sub_arena_end(memory, KB(96), KB(4));
+ vk->arena = arena_create(.name = "Vulkan Arena");
+ vk->entity_arena = arena_create(.name = "Vulkan Entity Arena");
vk_load_instance(vk->arena, err);
vk_load_physical_device(vk->arena, err);
- vk_load_queues(&vk->arena, err);
+ vk_load_queues(vk->arena, err);
vk_load_graphics();
vk_load_descriptor_block();
@@ -2372,15 +2375,15 @@ vk_pipeline(VulkanPipelineCreateInfo *infos, u32 count, u32 push_constants_size)
assert(count == 2 || infos[0].kind == VulkanShaderKind_Compute);
VulkanHandle result = {0};
+ Temp scratch;
DeferLoop(take_lock(&vulkan_context->arena_lock, -1), release_lock(&vulkan_context->arena_lock))
+ DeferLoop(scratch = temp_begin(vulkan_context->arena), temp_end(scratch))
{
- Arena arena = vulkan_context->arena;
-
VulkanEntity *e = vk_entity_allocate(VulkanEntityKind_Pipeline);
result = (VulkanHandle){(u64)e};
- if (count == 2) e->as.pipeline = vk_graphics_pipeline_from_infos(arena, infos, count, push_constants_size);
- else e->as.pipeline = vk_compute_pipeline_from_info(arena, infos, push_constants_size);
+ if (count == 2) e->as.pipeline = vk_graphics_pipeline_from_infos(scratch.arena, infos, count, push_constants_size);
+ else e->as.pipeline = vk_compute_pipeline_from_info(scratch.arena, infos, push_constants_size);
}
return result;
}
@@ -2533,11 +2536,12 @@ vk_command_buffer_memory_barriers(VulkanHandle command, GPUMemoryBarrierInfo *ba
VulkanCommandPool *vcp = vk->command_pools[vcb->timeline];
VulkanQueue *vq = vk->queues[vcb->timeline];
+ Temp scratch;
DeferLoop(take_lock(&vk->arena_lock, -1), release_lock(&vk->arena_lock))
+ DeferLoop(scratch = temp_begin(vk->arena), temp_end(scratch))
{
- Arena arena = vk->arena;
u32 valid_count = 0;
- VkBufferMemoryBarrier2 *memory_barriers = push_array(&arena, VkBufferMemoryBarrier2, count);
+ VkBufferMemoryBarrier2 *memory_barriers = push_array(vk->arena, VkBufferMemoryBarrier2, count);
for (u64 it = 0; it < count; it++) {
if ValidVulkanHandle(barriers[it].gpu_buffer->handle) {
u32 index = valid_count++;