Introduce memory arenas
This commit is contained in:
parent
c97d9664e0
commit
67cf29b684
52
arena.c
Normal file
52
arena.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "arena.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static bool is_power_of_two(uintptr_t x) { return (x & (x - 1)) == 0; }
|
||||||
|
|
||||||
|
static uintptr_t align_forward(uintptr_t ptr, size_t alignment) {
|
||||||
|
assert(is_power_of_two(alignment));
|
||||||
|
|
||||||
|
uintptr_t modulo = ptr & (alignment - 1); /* = ptr % alignment */
|
||||||
|
if (modulo != 0)
|
||||||
|
ptr += alignment - modulo;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arena_init(Arena *arena, void *buffer, size_t buffer_length) {
|
||||||
|
arena->buffer = buffer;
|
||||||
|
arena->buffer_length = buffer_length;
|
||||||
|
arena->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DEFAULT_ALIGNMENT
|
||||||
|
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *arena_alloc(Arena *arena, size_t size) {
|
||||||
|
return arena_alloc_align(arena, size, DEFAULT_ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *arena_alloc_align(Arena *arena, size_t size, size_t alignment) {
|
||||||
|
/* Align the current offset to the specified alignment */
|
||||||
|
uintptr_t curr_ptr = (uintptr_t)arena->buffer + arena->offset;
|
||||||
|
uintptr_t offset = align_forward(curr_ptr, alignment);
|
||||||
|
offset -= (uintptr_t)arena->buffer;
|
||||||
|
|
||||||
|
/* Check to see if there is some memory left */
|
||||||
|
if (offset <= arena->buffer_length - size) {
|
||||||
|
void *ptr = &arena->buffer[offset];
|
||||||
|
arena->offset = offset + size;
|
||||||
|
|
||||||
|
/* Zero out newly allocated memory */
|
||||||
|
memset(ptr, 0, size);
|
||||||
|
assert(ptr != 0);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arena_clear(Arena *arena) { arena->offset = 0; }
|
||||||
20
arena.h
Normal file
20
arena.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef INCLUDED_ARENA_H
|
||||||
|
#define INCLUDED_ARENA_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct Arena {
|
||||||
|
unsigned char *buffer;
|
||||||
|
size_t buffer_length;
|
||||||
|
size_t offset;
|
||||||
|
} Arena;
|
||||||
|
|
||||||
|
void arena_init(Arena *arena, void *buffer, size_t buffer_length);
|
||||||
|
|
||||||
|
void *arena_alloc(Arena *arena, size_t size);
|
||||||
|
void *arena_alloc_align(Arena *arena, size_t size, size_t alignment);
|
||||||
|
void arena_clear(Arena *arena);
|
||||||
|
|
||||||
|
#endif /* INCLUDED_ARENA_H */
|
||||||
26
hittable.c
26
hittable.c
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void hit_record_set_face_normal(HitRecord *record, Ray r, Vec3 outward_normal) {
|
void hit_record_set_face_normal(HitRecord *record, Ray r, Vec3 outward_normal) {
|
||||||
record->front_face = vec3_dot(r.direction, outward_normal) < 0;
|
record->front_face = vec3_dot(r.direction, outward_normal) < 0;
|
||||||
@ -23,24 +24,24 @@ bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hittable_list_grow(HittableList *list, size_t n) {
|
static void hittable_list_grow(HittableList *list, size_t n, Arena *arena) {
|
||||||
if (list->objects) {
|
if (list->objects) {
|
||||||
list->objects = realloc(list->objects, n * sizeof(Hittable *));
|
const Hittable **new_objects =
|
||||||
if (!list->objects)
|
arena_alloc(arena, (list->capacity + n) * sizeof(Hittable *));
|
||||||
abort();
|
memcpy(new_objects, list->objects, list->size * sizeof(Hittable *));
|
||||||
list->capacity = n;
|
list->objects = new_objects;
|
||||||
|
list->capacity += n;
|
||||||
} else {
|
} else {
|
||||||
list->objects = malloc(n * sizeof(Hittable *));
|
list->objects = arena_alloc(arena, n * sizeof(Hittable *));
|
||||||
if (!list->objects)
|
|
||||||
abort();
|
|
||||||
list->capacity = n;
|
list->capacity = n;
|
||||||
list->size = 0;
|
list->size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hittable_list_add(HittableList *list, const Hittable *hittable) {
|
void hittable_list_add(HittableList *list, const Hittable *hittable,
|
||||||
|
Arena *arena) {
|
||||||
if (list->capacity == list->size)
|
if (list->capacity == list->size)
|
||||||
hittable_list_grow(list, list->capacity == 0 ? 16 : list->capacity);
|
hittable_list_grow(list, list->capacity == 0 ? 16 : list->capacity, arena);
|
||||||
list->objects[list->size++] = hittable;
|
list->objects[list->size++] = hittable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +60,6 @@ bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
|||||||
return hit_anything;
|
return hit_anything;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hittable_list_free(HittableList *list) {
|
|
||||||
free(list->objects);
|
|
||||||
list->objects = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sphere_hit(const Sphere *sphere, Ray r, double t_min, double t_max,
|
bool sphere_hit(const Sphere *sphere, Ray r, double t_min, double t_max,
|
||||||
HitRecord *record) {
|
HitRecord *record) {
|
||||||
Vec3 oc = point3_sub(r.origin, sphere->center);
|
Vec3 oc = point3_sub(r.origin, sphere->center);
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
#ifndef INCLUDED_HITTABLE_H
|
#ifndef INCLUDED_HITTABLE_H
|
||||||
#define INCLUDED_HITTABLE_H
|
#define INCLUDED_HITTABLE_H
|
||||||
|
|
||||||
|
#include "arena.h"
|
||||||
|
#include "material.h"
|
||||||
#include "point3.h"
|
#include "point3.h"
|
||||||
#include "ray.h"
|
#include "ray.h"
|
||||||
#include "vec3.h"
|
#include "vec3.h"
|
||||||
#include "material.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -38,10 +39,10 @@ typedef struct HittableList {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} HittableList;
|
} HittableList;
|
||||||
|
|
||||||
void hittable_list_add(HittableList *list, const Hittable *hittable);
|
void hittable_list_add(HittableList *list, const Hittable *hittable,
|
||||||
|
Arena *arena);
|
||||||
bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
||||||
double t_max, HitRecord *record);
|
double t_max, HitRecord *record);
|
||||||
void hittable_list_free(HittableList *list);
|
|
||||||
|
|
||||||
typedef struct Sphere {
|
typedef struct Sphere {
|
||||||
HittableType type;
|
HittableType type;
|
||||||
|
|||||||
52
main.c
52
main.c
@ -4,6 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "arena.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "hittable.h"
|
#include "hittable.h"
|
||||||
@ -33,19 +34,17 @@ static Color ray_color(Ray r, const Hittable *world, int depth) {
|
|||||||
return color_lerp(gradient1, gradient2, t);
|
return color_lerp(gradient1, gradient2, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Hittable *generate_random_scene(void) {
|
static const Hittable *generate_random_scene(Arena *arena) {
|
||||||
static HittableList world = {.type = HITTABLE_LIST};
|
static HittableList world = {.type = HITTABLE_LIST};
|
||||||
|
|
||||||
/* FIXME: Use arena allocators to be able to free memory */
|
|
||||||
|
|
||||||
static Lambertian ground_material = {.type = MATERIAL_LAMBERTIAN,
|
static Lambertian ground_material = {.type = MATERIAL_LAMBERTIAN,
|
||||||
.albedo = (Color){0.5, 0.5, 0.5}};
|
.albedo = (Color){0.5, 0.5, 0.5}};
|
||||||
Sphere *ground_sphere = malloc(sizeof(Sphere));
|
Sphere *ground_sphere = arena_alloc(arena, sizeof(Sphere));
|
||||||
ground_sphere->type = HITTABLE_SPHERE;
|
ground_sphere->type = HITTABLE_SPHERE;
|
||||||
ground_sphere->center = (Point3){0.0, -1000.0, 0.0};
|
ground_sphere->center = (Point3){0.0, -1000.0, 0.0};
|
||||||
ground_sphere->radius = 1000.0;
|
ground_sphere->radius = 1000.0;
|
||||||
ground_sphere->material = (const Material *)&ground_material;
|
ground_sphere->material = (const Material *)&ground_material;
|
||||||
hittable_list_add(&world, (const Hittable *)ground_sphere);
|
hittable_list_add(&world, (const Hittable *)ground_sphere, arena);
|
||||||
|
|
||||||
static Lambertian lambertian = {.type = MATERIAL_LAMBERTIAN,
|
static Lambertian lambertian = {.type = MATERIAL_LAMBERTIAN,
|
||||||
.albedo = {0.4, 0.2, 0.1}};
|
.albedo = {0.4, 0.2, 0.1}};
|
||||||
@ -62,66 +61,76 @@ static const Hittable *generate_random_scene(void) {
|
|||||||
if (vec3_length(point3_sub(center, (Point3){4.0, 0.2, 0.0})) > 0.9) {
|
if (vec3_length(point3_sub(center, (Point3){4.0, 0.2, 0.0})) > 0.9) {
|
||||||
if (choose_material < 0.8) {
|
if (choose_material < 0.8) {
|
||||||
Color albedo = color_mul(color_random(), color_random());
|
Color albedo = color_mul(color_random(), color_random());
|
||||||
Lambertian *material = malloc(sizeof(Lambertian));
|
Lambertian *material = arena_alloc(arena, sizeof(Lambertian));
|
||||||
material->type = MATERIAL_LAMBERTIAN;
|
material->type = MATERIAL_LAMBERTIAN;
|
||||||
material->albedo = albedo;
|
material->albedo = albedo;
|
||||||
|
|
||||||
Sphere *sphere = malloc(sizeof(Sphere));
|
Sphere *sphere = arena_alloc(arena, sizeof(Sphere));
|
||||||
sphere->type = HITTABLE_SPHERE;
|
sphere->type = HITTABLE_SPHERE;
|
||||||
sphere->center = center;
|
sphere->center = center;
|
||||||
sphere->radius = 0.2;
|
sphere->radius = 0.2;
|
||||||
sphere->material = (const Material *)material;
|
sphere->material = (const Material *)material;
|
||||||
hittable_list_add(&world, (const Hittable *)sphere);
|
hittable_list_add(&world, (const Hittable *)sphere, arena);
|
||||||
} else if (choose_material < 0.95) {
|
} else if (choose_material < 0.95) {
|
||||||
Color albedo = color_random_in_range(0.5, 1);
|
Color albedo = color_random_in_range(0.5, 1);
|
||||||
double fuzziness = random_double_in_range(0.5, 1.0);
|
double fuzziness = random_double_in_range(0.5, 1.0);
|
||||||
Metal *material = malloc(sizeof(Metal));
|
Metal *material = arena_alloc(arena, sizeof(Metal));
|
||||||
material->type = MATERIAL_METAL;
|
material->type = MATERIAL_METAL;
|
||||||
material->albedo = albedo;
|
material->albedo = albedo;
|
||||||
material->fuzziness = fuzziness;
|
material->fuzziness = fuzziness;
|
||||||
|
|
||||||
Sphere *sphere = malloc(sizeof(Sphere));
|
Sphere *sphere = arena_alloc(arena, sizeof(Sphere));
|
||||||
sphere->type = HITTABLE_SPHERE;
|
sphere->type = HITTABLE_SPHERE;
|
||||||
sphere->center = center;
|
sphere->center = center;
|
||||||
sphere->radius = 0.2;
|
sphere->radius = 0.2;
|
||||||
sphere->material = (const Material *)material;
|
sphere->material = (const Material *)material;
|
||||||
hittable_list_add(&world, (const Hittable *)sphere);
|
hittable_list_add(&world, (const Hittable *)sphere, arena);
|
||||||
} else {
|
} else {
|
||||||
Sphere *sphere = malloc(sizeof(Sphere));
|
Sphere *sphere = arena_alloc(arena, sizeof(Sphere));
|
||||||
sphere->type = HITTABLE_SPHERE;
|
sphere->type = HITTABLE_SPHERE;
|
||||||
sphere->center = center;
|
sphere->center = center;
|
||||||
sphere->radius = 0.2;
|
sphere->radius = 0.2;
|
||||||
sphere->material = (const Material *)&glass;
|
sphere->material = (const Material *)&glass;
|
||||||
hittable_list_add(&world, (const Hittable *)sphere);
|
hittable_list_add(&world, (const Hittable *)sphere, arena);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sphere *sphere1 = malloc(sizeof(Sphere));
|
Sphere *sphere1 = arena_alloc(arena, sizeof(Sphere));
|
||||||
sphere1->type = HITTABLE_SPHERE;
|
sphere1->type = HITTABLE_SPHERE;
|
||||||
sphere1->center = (Point3){0.0, 1.0, 0.0};
|
sphere1->center = (Point3){0.0, 1.0, 0.0};
|
||||||
sphere1->radius = 1.0;
|
sphere1->radius = 1.0;
|
||||||
sphere1->material = (const Material *)&glass;
|
sphere1->material = (const Material *)&glass;
|
||||||
hittable_list_add(&world, (const Hittable *)sphere1);
|
hittable_list_add(&world, (const Hittable *)sphere1, arena);
|
||||||
Sphere *sphere2 = malloc(sizeof(Sphere));
|
Sphere *sphere2 = arena_alloc(arena, sizeof(Sphere));
|
||||||
sphere2->type = HITTABLE_SPHERE;
|
sphere2->type = HITTABLE_SPHERE;
|
||||||
sphere2->center = (Point3){-4.0, 1.0, 0.0};
|
sphere2->center = (Point3){-4.0, 1.0, 0.0};
|
||||||
sphere2->radius = 1.0;
|
sphere2->radius = 1.0;
|
||||||
sphere2->material = (const Material *)&lambertian;
|
sphere2->material = (const Material *)&lambertian;
|
||||||
hittable_list_add(&world, (const Hittable *)sphere2);
|
hittable_list_add(&world, (const Hittable *)sphere2, arena);
|
||||||
Sphere *sphere3 = malloc(sizeof(Sphere));
|
Sphere *sphere3 = arena_alloc(arena, sizeof(Sphere));
|
||||||
sphere3->type = HITTABLE_SPHERE;
|
sphere3->type = HITTABLE_SPHERE;
|
||||||
sphere3->center = (Point3){4.0, 1.0, 0.0};
|
sphere3->center = (Point3){4.0, 1.0, 0.0};
|
||||||
sphere3->radius = 1.0;
|
sphere3->radius = 1.0;
|
||||||
sphere3->material = (const Material *)&metal;
|
sphere3->material = (const Material *)&metal;
|
||||||
hittable_list_add(&world, (const Hittable *)sphere3);
|
hittable_list_add(&world, (const Hittable *)sphere3, arena);
|
||||||
|
|
||||||
return (const Hittable *)&world;
|
return (const Hittable *)&world;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
/* Memory management */
|
||||||
|
|
||||||
|
const unsigned int buffer_size = 1 * 1024 * 1024;
|
||||||
|
void *buffer = malloc(buffer_size);
|
||||||
|
if (!buffer)
|
||||||
|
abort();
|
||||||
|
Arena arena = {0};
|
||||||
|
arena_init(&arena, buffer, buffer_size);
|
||||||
|
|
||||||
/* Image parameters */
|
/* Image parameters */
|
||||||
|
|
||||||
const double aspect_ratio = 3.0 / 2.0;
|
const double aspect_ratio = 3.0 / 2.0;
|
||||||
const int image_width = 1200;
|
const int image_width = 1200;
|
||||||
const int image_height = (int)(image_width / aspect_ratio);
|
const int image_height = (int)(image_width / aspect_ratio);
|
||||||
@ -130,7 +139,7 @@ int main(void) {
|
|||||||
|
|
||||||
/* World */
|
/* World */
|
||||||
|
|
||||||
const Hittable *world = generate_random_scene();
|
const Hittable *world = generate_random_scene(&arena);
|
||||||
|
|
||||||
/* Camera */
|
/* Camera */
|
||||||
|
|
||||||
@ -162,9 +171,12 @@ int main(void) {
|
|||||||
|
|
||||||
fprintf(stderr, "\nDone.\n");
|
fprintf(stderr, "\nDone.\n");
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "arena.c"
|
||||||
#include "camera.c"
|
#include "camera.c"
|
||||||
#include "color.c"
|
#include "color.c"
|
||||||
#include "hittable.c"
|
#include "hittable.c"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user