mightymandel v16

GPU-based Mandelbrot set explorer

fpxx_step.c
Go to the documentation of this file.
1 // mightymandel -- GPU-based Mandelbrot Set explorer
2 // Copyright (C) 2012,2013,2014,2015 Claude Heiland-Allen
3 // License GPL3+ http://www.gnu.org/licenses/gpl.html
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 
8 #include "fpxx_step.h"
9 #include "shader.h"
10 #include "logging.h"
11 #include "texture.h"
12 
13 extern const char *fpxx_step_vert;
14 const GLchar *fpxx_step_varyings[] = {"cne", "zdz", "err"};
15 
16 void fpxx_step_begin(struct fpxx_step *s) {
17  s->program = compile_program_tf("fpxx_step", fpxx_step_vert, 0, 0, 3, fpxx_step_varyings);
18  s->escaped = glGetUniformLocation(s->program, "escaped");D;
19  s->er2 = glGetUniformLocation(s->program, "er2");D;
20  s->zdz0s = glGetUniformLocation(s->program, "zdz0s");D;
21  s->cne0 = glGetAttribLocation(s->program, "cne0");D;
22  s->zdz0 = glGetAttribLocation(s->program, "zdz0");D;
23  s->err0 = glGetAttribLocation(s->program, "err0");D;
24  glGenTextures(1, &s->zdz0t);D;
25  glActiveTexture(GL_TEXTURE0 + TEX_ORBIT);D;
26  glBindTexture(GL_TEXTURE_2D, s->zdz0t);D;
27  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);D;
28  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);D;
29  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI_EXT, FPXX_STEP_ITERS, DE ? 2 : 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, 0);D;
30  mpfr_inits2(53, s->cx, s->cy, s->zx, s->zy, s->dzx, s->dzy, s->t1, s->t2, s->t3, s->t4, (mpfr_ptr) 0);
31  glGenVertexArrays(1, &s->vao);D;
32  s->orbit = 0;
33  s->current = 0;
34 }
35 
36 void fpxx_step_end(struct fpxx_step *s) {
37  glDeleteProgram(s->program);D;
38  s->program = 0;
39  glDeleteTextures(1, &s->zdz0t);D;
40  s->zdz0t = 0;
41  mpfr_clears(s->cx, s->cy, s->zx, s->zy, s->dzx, s->dzy, s->t1, s->t2, s->t3, s->t4, (mpfr_ptr) 0);
42  glDeleteVertexArrays(1, &s->vao);D;
43  s->vao = 0;
44  // free old orbit
45  struct fpxx_step_orbit *orbit = s->orbit;
46  while (orbit) {
47  struct fpxx_step_orbit *next = orbit->next;
48  free(orbit);
49  orbit = next;
50  }
51  s->orbit = 0;
52  s->current = 0;
53 }
54 
55 void fpxx_step_start(struct fpxx_step *s, GLuint vbo, double escaperadius2, const mpfr_t zx, const mpfr_t zy, const mpfr_t dzx, const mpfr_t dzy, const mpfr_t refx, const mpfr_t refy, bool initial_slice) {
56  if (initial_slice) {
57  // free old orbit
58  struct fpxx_step_orbit *orbit = s->orbit;
59  while (orbit) {
60  struct fpxx_step_orbit *next = orbit->next;
61  free(orbit);
62  orbit = next;
63  }
64  s->orbit = 0;
65  s->current = 0;
66  // update reference parameters
67  mpfr_prec_t p = mpfr_get_prec(refx);
68  mpfr_set_prec(s->cx, p); mpfr_set(s->cx, refx, MPFR_RNDN);
69  mpfr_set_prec(s->cy, p); mpfr_set(s->cy, refy, MPFR_RNDN);
70  mpfr_set_prec(s->zx, p); mpfr_set(s->zx, zx, MPFR_RNDN);
71  mpfr_set_prec(s->zy, p); mpfr_set(s->zy, zy, MPFR_RNDN);
72  mpfr_set_prec(s->dzx, p); mpfr_set(s->dzx, dzx, MPFR_RNDN);
73  mpfr_set_prec(s->dzy, p); mpfr_set(s->dzy, dzy, MPFR_RNDN);
74  mpfr_set_prec(s->t1, p);
75  mpfr_set_prec(s->t2, p);
76  mpfr_set_prec(s->t3, p);
77  mpfr_set_prec(s->t4, p);
78  // set up shader uniforms
79  glUseProgram(s->program);D;
80  glUniform1d(s->er2, escaperadius2);D;
81  glUniform1i(s->zdz0s, TEX_ORBIT);D;
82  glUseProgram(0);D;
83  // set up vertex attributes
84  glBindVertexArray(s->vao);D;
85  glBindBuffer(GL_ARRAY_BUFFER, vbo);D;
86  glEnableVertexAttribArray(s->cne0);D;
87  glEnableVertexAttribArray(s->zdz0);D;
88  glEnableVertexAttribArray(s->err0);D;
89  glVertexAttribLPointer(s->cne0, 4, GL_DOUBLE, (DE ? 9 : 7) * sizeof(GLdouble), 0);D;
90  glVertexAttribLPointer(s->zdz0, DE ? 4 : 2, GL_DOUBLE, (DE ? 9 : 7) * sizeof(GLdouble), ((GLbyte *)0)+(4*sizeof(GLdouble)));D;
91  glVertexAttribLPointer(s->err0, 1, GL_DOUBLE, (DE ? 9 : 7) * sizeof(GLdouble), ((GLbyte *)0)+((DE ? 8 : 6)*sizeof(GLdouble)));D;
92  glBindBuffer(GL_ARRAY_BUFFER, 0);D;
93  glBindVertexArray(0);D;
94  debug_message("VBO step: %d -> ?\n", vbo);
95  }
96  s->current = s->orbit;
97 }
98 
99 typedef union { double d; GLuint u[2]; } doubleint;
100 
101 void fpxx_u2(GLuint *o, mpfr_t i) {
102  doubleint x;
103  x.d = mpfr_get_d(i, MPFR_RNDN);
104  o[0] = x.u[0];
105  o[1] = x.u[1];
106 }
107 
108 void fpxx_step_do(struct fpxx_step *s, GLuint *active_count, GLuint vbo, GLuint query) {
109  if (! s->current) {
110  // allocate a new block
111  s->current = malloc(sizeof(struct fpxx_step_orbit));
112  s->current->next = 0;
113  // compute a reference block
114  for (int i = 0; i < FPXX_STEP_ITERS; ++i) {
115  // buffer <- z, dz
116  fpxx_u2(&s->current->buffer[0][i][0], s->zx);
117  fpxx_u2(&s->current->buffer[0][i][2], s->zy);
118  if (DE) {
119  fpxx_u2(&s->current->buffer[1][i][0], s->dzx);
120  fpxx_u2(&s->current->buffer[1][i][2], s->dzy);
121  // dz <- 2 * z * dz + 1
122  mpfr_mul(s->t1, s->zx, s->dzx, MPFR_RNDN);
123  mpfr_mul(s->t2, s->zy, s->dzy, MPFR_RNDN);
124  mpfr_sub(s->t3, s->t1, s->t2, MPFR_RNDN);
125  mpfr_mul(s->t1, s->zx, s->dzy, MPFR_RNDN);
126  mpfr_mul(s->t2, s->zy, s->dzx, MPFR_RNDN);
127  mpfr_mul_2ui(s->dzx, s->t3, 1, MPFR_RNDN);
128  mpfr_add_ui(s->dzx, s->dzx, 1, MPFR_RNDN);
129  mpfr_add(s->dzy, s->t1, s->t2, MPFR_RNDN);
130  mpfr_mul_2ui(s->dzy, s->dzy, 1, MPFR_RNDN);
131  }
132  // z <- z * z + c
133  mpfr_sqr(s->t1, s->zx, MPFR_RNDN);
134  mpfr_sqr(s->t2, s->zy, MPFR_RNDN);
135  mpfr_mul(s->zy, s->zx, s->zy, MPFR_RNDN);
136  mpfr_mul_2ui(s->zy, s->zy, 1, MPFR_RNDN);
137  mpfr_sub(s->zx, s->t1, s->t2, MPFR_RNDN);
138  mpfr_add(s->zx, s->zx, s->cx, MPFR_RNDN);
139  mpfr_add(s->zy, s->zy, s->cy, MPFR_RNDN);
140  }
141  // append it to the orbit
142  if (! s->orbit) {
143  s->orbit = s->current;
144  } else {
145  struct fpxx_step_orbit *last = s->orbit;
146  while (last->next) {
147  last = last->next;
148  }
149  last->next = s->current;
150  }
151  }
152  // upload block reference
153  glActiveTexture(GL_TEXTURE0 + TEX_ORBIT);D;
154  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FPXX_STEP_ITERS, DE ? 2 : 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &s->current->buffer[0][0][0]);D;
155  // advance block reference for next time
156  s->current = s->current->next;
157  // transform vertices
158  glBindVertexArray(s->vao);D;
159  glUseProgram(s->program);D;
160  glUniform1i(s->escaped, 0);D; // FIXME what about escaping references??
161  glEnable(GL_RASTERIZER_DISCARD);D;
162  glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo);D;
163  glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);D;
164  glBeginTransformFeedback(GL_POINTS);D;
165  glDrawArrays(GL_POINTS, 0, *active_count);D;
166  glEndTransformFeedback();D;
167  glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);D;
168  int before = *active_count;
169  glGetQueryObjectuiv(query, GL_QUERY_RESULT, active_count);D;
170  int after = *active_count;
171  debug_message("step active_count: %d -> %d\n", before, after);
172  glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);D;
173  glDisable(GL_RASTERIZER_DISCARD);D;
174  glUseProgram(0);D;
175  glBindVertexArray(0);D;
176  debug_message("VBO step: ? -> %d\n", vbo);
177 }