root/trunk/qd/test30.d

Revision 701, 5.9 kB (checked in by FeepingCreature, 2 years ago)

VM-based renderer

Line 
1 module test30;
2
3 import qd, SDL_image, tools.base, SDL_ttf, tools.log;
4
5 class VM {
6   float[16] regs;
7   ubyte[] program;
8   int pc;
9   this() {
10     program.length = 1024;
11   }
12   void reset() {
13     regs[] = 0f;
14     pc = 0;
15   }
16   void run(int cycles, lazy float randf) {
17     while (cycles--) {
18       auto inst = program[pc];
19       int cmd = inst & 15, param = inst >> 4;
20       cmd &= 7; // ignore high bit
21       switch (cmd) {
22         case 0:
23           version(LOG) logln("branch to ", pc, "+", param + 1);
24           pc = (pc + param) % program.length;
25           break;
26         case 1:
27           version(LOG) logln("store 0(", regs[0], ") to ", param);
28           regs[param] = regs[0];
29           break;
30         case 2:
31           version(log) logln("skip cond on ", regs[0], " => ", atan2(regs[0]) / (PI/4) + 0.5);
32           if (atan(regs[0]) / (PI/4) + 0.5 > randf()) pc++;
33           break;
34           /*version(LOG) logln("skip if ", regs[0], " > 0");
35           if (regs[0] > 0) pc++;
36           break;*/
37         case 3:
38           version(LOG) logln("load ", (param - 8) / 6f);
39           regs[0] = (param - 8) / 6f;
40           break;
41         case 4:
42           version(LOG) logln("swap 0(", regs[0], ") and ", param, "(", regs[param], ")");
43           swap(regs[0], regs[param]);
44           break;
45         case 5:
46           version(LOG) logln("add 0(", regs[0], ") + ", param, "(", regs[param], ")");
47           regs[0] += regs[param];
48           break;
49         case 6:
50           version(LOG) logln("mul 0(", regs[0], ") + ", param, "(", regs[param], ")");
51           regs[0] *= regs[param];
52           break;
53         case 7:
54           version(LOG) logln("div 0(", regs[0], ") / (1 + ", param, "(", regs[param], ") )");
55           regs[0] /= regs[param] + 1;
56           break;
57       }
58       pc++;
59       if (pc == program.length) pc = 0;
60     }
61   }
62   void generate(uint delegate() dg) {
63     foreach (ref val; program) {
64       val = dg() % 256;
65     }
66   }
67 }
68
69 long atol(string s) {
70   long res;
71   s = s.strip();
72   while (s.length) {
73     auto ch = s.take();
74     assert(ch >= '0' && ch <= '9');
75     res = res * 10L + (ch - '0');
76   }
77   return res;
78 }
79
80 // Thank you George Marsaglia .. you're a lifesaver
81
82 class KISS {
83   uint z, w, jcong, jsr;
84   void reset() {
85     z = 362436069;
86     w = 521288629;
87     jcong = 380116160;
88     jsr = 123456789;
89   }
90   this() { reset; }
91   uint znew() { return z = 36969 * (z & 65535) + (z >> 16); }
92   uint wnew() { return w = 18000 * (w & 65535) + (w >> 16); }
93   uint mwc() { return (znew << 16) + wnew; }
94   uint cong() { return jcong = 69069 * jcong + 1234567; }
95   uint shr3() {
96     jsr ^= jsr << 17;
97     jsr ^= jsr >> 13;
98     jsr ^= jsr << 5;
99     return jsr;
100   }
101   uint kiss() { return (mwc() ^ cong()) + shr3; }
102   alias kiss rand;
103   float randf() { return rand() * 1f / typeof(rand()).max; }
104 }
105
106 import tools.mersenne, tools.time;
107 void main(string[] args) {
108   auto exec = args.take();
109   auto a2 = args;
110   int steps = 1024;
111   ulong seed;
112   bool filter = true, show = true, quiet = false;
113   int aa;
114   string output;
115   int w = 640, h = 480;
116   while (args.length) {
117     auto flag = args.take();
118     switch (flag) {
119       case "-steps": steps = args.take().atoi(); break;
120       case "-seed": seed = args.take().atol(); filter = false; break;
121       case "-o": output = args.take(); break;
122       case "-nofilter": filter = false; break;
123       case "-filter": filter = true; break;
124       case "-noshow": show = false; break;
125       case "-aa": aa = args.take().atoi(); break;
126       case "-w": w = args.take().atoi(); break;
127       case "-h": h = args.take().atoi(); break;
128       case "-q": quiet = true; break;
129     }
130   }
131   auto test = new VM;
132   screen(w, h, 0, !show);
133   auto last = sec();
134   while (true) {continue_outer:
135     auto sv = µsec();
136     if (seed) sv = seed;
137     void update() {
138       if (sec() - last > 0.2) {
139         if (!quiet)
140           print(10, 10, Bottom|Right, Back = Black, Format("::", sv));
141         flip;
142         events;
143         last = sec();
144       }
145     }
146     auto rng = new Mersenne(sv);
147     test.generate(&rng.rand);
148     const STEP = 1;
149     bool testmode = filter;
150     rerun:
151     int fail;
152     rgb prev;
153     auto rung = new KISS;
154     rgb eval(float x, float y) {
155       test.reset;
156       if (testmode) rung.reset();
157       test.regs[4] = (x - 0.5) * 4f;
158       test.regs[5] = (y - 0.5) * 4f;
159       test.run(steps, rung.randf);
160       // logln("post-register file ", test.regs);
161       rgb col;
162       foreach (i, ref val; test.regs[1..4]) {
163         auto ub = cast(ubyte) (val * 255);
164         if (ub > 0) {
165           if (ub < 128) col.values[i] = ub * 2;
166           else if (ub < 256) col.values[i] = (255 - ub) * 2;
167         }
168       }
169       return col;
170     }
171     for (int y = 0; y < screen.h; y += STEP) {
172       for (int x = 0; x < screen.w; x += STEP) {
173         rgb col;
174         if (aa) {
175           int[3] sums;
176           for (int y2 = 0; y2 < aa; ++y2) {
177             for (int x2 = 0; x2 < aa; ++x2) {
178               auto lc = eval((x * 1f + x2 * 1f / aa) / screen.w, (y * 1f + y2 * 1f / aa) / screen.h);
179               foreach (i, v; lc.values)
180                 sums[i] += v;
181             }
182           }
183           foreach (k, ref v; col.values)
184             v = sums[k] / (aa*aa);
185         } else {
186           col = eval(x * 1f / screen.w, y * 1f / screen.h);
187         }
188         if (col == prev) fail++;
189         else fail = 0;
190         prev = col;
191         if (testmode) {
192           if (filter && y < 16 && fail > 4096) {
193             // logln("Giving up. ");
194             goto continue_outer;
195           }
196           if (y !< 16) {
197             testmode = false;
198             goto rerun; // redo
199           }
200         }
201         putpixel32(x, y, col);
202       }
203       update;
204     }
205     auto bmpname = Format("temp_", sv, ".bmp");
206     SaveBMP(display, bmpname);
207     auto dest = output;
208     if (!dest.length) dest = Format("images/", sv, ".png");
209     string num = Format(steps);
210     while (num.length < 6) num = "0" ~ num;
211     dest = dest.replace("%NUM%", num);
212     system(Format("convert ", bmpname, " ", dest, " && rm ", bmpname).toStringz());
213     logln("Saved to ", dest);
214     if (seed) break;
215   }
216 }
Note: See TracBrowser for help on using the browser.