From 77a8caa3ee2399e9750b23f059e7db4eae15ed09 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sun, 14 May 2017 11:29:54 -0400 Subject: lower memory use for particle data --- main.c | 119 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/main.c b/main.c index e4bd106..5c8b5d9 100644 --- a/main.c +++ b/main.c @@ -38,10 +38,10 @@ #define USE_GL_DEBUG false // number of particles -#define NUM_PARTICLES 1024 +#define NUM_PARTICLES 2048 // size of compute shader workgroups -#define WORKGROUP_SIZE 128 +#define WORKGROUP_SIZE 1024 typedef struct { const GLuint type; @@ -72,17 +72,25 @@ verts[] = { }; typedef struct { - float positions[4 * NUM_PARTICLES], - velocities[4 * NUM_PARTICLES], - colors[4 * NUM_PARTICLES]; + float x, y; +} vec2_t; + +typedef struct { + vec2_t positions[NUM_PARTICLES], + velocities[NUM_PARTICLES]; + uint32_t colors[NUM_PARTICLES]; + struct { + float r, g, b, a; + } palette[256]; } particles_t; // shared particle shader storage buffer definition #define PARTICLE_BUFFER \ "layout (std430, binding = 1) buffer particles {\n" \ - " mediump vec4 positions[" S(NUM_PARTICLES) "];\n" \ - " mediump vec4 velocities[" S(NUM_PARTICLES) "];\n" \ - " mediump vec4 colors[" S(NUM_PARTICLES) "];\n" \ + " mediump vec2 positions[" S(NUM_PARTICLES) "];\n" \ + " mediump vec2 velocities[" S(NUM_PARTICLES) "];\n" \ + " mediump uint colors[" S(NUM_PARTICLES) "];\n" \ + " mediump vec4 palette[256];\n" \ "};\n" // real compute shader @@ -101,7 +109,7 @@ cs_src[] = "\n" "void main() {\n" " mediump uint i = gl_GlobalInvocationID.x;\n" - " positions[i].xy += delta * velocities[i].xy;\n" + " positions[i] += delta * velocities[i];\n" "\n" " if (positions[i].x > 1.1) {\n" " positions[i].x -= 2.2;\n" @@ -127,7 +135,7 @@ vs_src[] = "out mediump flat int instance_id;\n" "\n" "void main() {\n" - " gl_Position = positions[gl_InstanceID] + 0.025 * vec4(pos, 1);\n" + " gl_Position = vec4(positions[gl_InstanceID], 0, 1) + 0.025 * vec4(pos, 1);\n" " instance_id = gl_InstanceID;\n" "}\n"; @@ -145,7 +153,7 @@ fs_src[] = "\n" "void main() {\n" " mediump float alpha = 0.5f + 0.5f * (0.5f + 0.5 * sin(time * 3.141));\n" - " color = vec4(colors[instance_id].rgb, 1) * alpha;\n" + " color = palette[colors[instance_id]] * alpha;\n" "}\n"; static const shader_t @@ -267,12 +275,32 @@ color_map(uint8_t bits) { } } +static void +init_palette( + particles_t * const data +) { + // generate palette seed data + uint8_t seeds[256]; + if (!RAND_bytes(seeds, 256)) { + LOG_C("RAND_bytes() failed"); + exit(EXIT_FAILURE); + } + + #pragma omp parallel for + for (int i = 0; i < 256; i++) { + // get seed + const uint8_t cs = seeds[i]; + + // set color + data->palette[i].r = color_map(cs & 0x3); + data->palette[i].g = color_map((cs >> 2) & 0x3); + data->palette[i].b = color_map((cs >> 4) & 0x3); + data->palette[i].a = 1.0; + } +} + static GLuint init_particles(void) { - // create shader storage buffer - GLuint ssbo; - glGenBuffers(1, &ssbo); - // generate seed data uint8_t seeds[5 * NUM_PARTICLES]; if (!RAND_bytes(seeds, 5 * NUM_PARTICLES)) { @@ -282,44 +310,27 @@ init_particles(void) { // populate particle data particles_t data; - #pragma omp parallel for for (int i = 0; i < NUM_PARTICLES; i++) { - // calculate position - const float px = 2.0 * seeds[5 * i + 0] / 0xFF - 1.0, - py = 2.0 * seeds[5 * i + 1] / 0xFF - 1.0; - - // LOG_D("%f,%f", px, py); - // set position - data.positions[4 * i + 0] = px; - data.positions[4 * i + 1] = py; - data.positions[4 * i + 2] = 0.0; - data.positions[4 * i + 3] = 1.0; - - // calculate velocity - const float vx = 2.0 * seeds[5 * i + 2] / 0xFF - 1.0, - vy = 2.0 * seeds[5 * i + 3] / 0xFF - 1.0; + data.positions[i].x = 2.0 * seeds[5 * i + 0] / 0xFF - 1.0; + data.positions[i].y = 2.0 * seeds[5 * i + 1] / 0xFF - 1.0; // set velocity - data.velocities[4 * i + 0] = vx; - data.velocities[4 * i + 1] = vy; - data.velocities[4 * i + 2] = 0; - data.velocities[4 * i + 3] = 0; - - // calculate color - const uint8_t cs = seeds[5 * i + 4]; - const float r = color_map(cs & 0x3), - g = color_map((cs >> 2) & 0x3), - b = color_map((cs >> 4) & 0x3); + data.velocities[i].x = 2.0 * seeds[5 * i + 2] / 0xFF - 1.0; + data.velocities[i].y = 2.0 * seeds[5 * i + 3] / 0xFF - 1.0; // set color - data.colors[4 * i + 0] = r; - data.colors[4 * i + 1] = g; - data.colors[4 * i + 2] = b; - data.colors[4 * i + 3] = 1.0; + data.colors[i] = seeds[5 * i + 4] & 0x3f; } + // generate palette + init_palette(&data); + + // create shader storage buffer + GLuint ssbo; + glGenBuffers(1, &ssbo); + // populate buffer glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(particles_t), &data, GL_DYNAMIC_DRAW); @@ -391,19 +402,19 @@ update_particles( #pragma omp parallel for for (int i = 0; i < NUM_PARTICLES; i++) { // update x coordinate - data->positions[4 * i + 0] += delta * data->velocities[4 * i + 0]; - if (data->positions[4 * i + 0] < -1.1) { - data->positions[4 * i + 0] += 2.2; - } else if (data->positions[4 * i + 0] > 1.1) { - data->positions[4 * i + 0] -= 2.2; + data->positions[i].x += delta * data->velocities[i].x; + if (data->positions[i].x < -1.1) { + data->positions[i].x += 2.2; + } else if (data->positions[i].x > 1.1) { + data->positions[i].x -= 2.2; } // update y coordinate - data->positions[4 * i + 1] += delta * data->velocities[4 * i + 1]; - if (data->positions[4 * i + 1] < -1.1) { - data->positions[4 * i + 1] += 2.2; - } else if (data->positions[4 * i + 1] > 1.1) { - data->positions[4 * i + 1] -= 2.2; + data->positions[i].y += delta * data->velocities[i].y; + if (data->positions[i].y < -1.1) { + data->positions[i].y += 2.2; + } else if (data->positions[i].y > 1.1) { + data->positions[i].y -= 2.2; } } -- cgit v1.2.3