File: core.cpp

package info (click to toggle)
halide 21.0.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,752 kB
  • sloc: cpp: 289,334; ansic: 22,751; python: 7,486; makefile: 4,299; sh: 2,508; java: 1,549; javascript: 282; pascal: 207; xml: 127; asm: 9
file content (131 lines) | stat: -rw-r--r-- 4,211 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Adapted from Tim Hutton's MIT-licensed example code at: https://github.com/timhutton/sdl-canvas-wasm

#include <SDL2/SDL.h>
#include <cstdlib>
#include <emscripten.h>
#include <iomanip>
#include <sstream>

#include "HalideBuffer.h"
#include "reaction_diffusion_init.h"
#include "reaction_diffusion_render.h"
#include "reaction_diffusion_update.h"

const int W = 1024, H = 1024;

struct Context {
    SDL_Renderer *renderer = nullptr;
    SDL_Texture *tex = nullptr;
    int iteration = 0;
    int threads = 0;

    double smoothed_runtime = 0;
    double smoothed_fps = 0;
    double smoothed_blit_time = 0;
    double last_frame_time = 0;

    Halide::Runtime::Buffer<float, 3> buf1;
    Halide::Runtime::Buffer<float, 3> buf2;
    Halide::Runtime::Buffer<uint32_t, 2> pixel_buf;
};

void mainloop(void *arg) {
    Context *ctx = static_cast<Context *>(arg);
    SDL_Renderer *renderer = ctx->renderer;

    // Grab mouse position somehow
    int mx = W / 2, my = H / 2;
    SDL_GetMouseState(&mx, &my);

    double t1 = emscripten_get_now();
    reaction_diffusion_update(ctx->buf1, mx, my, ctx->iteration, ctx->buf2);
    reaction_diffusion_render(ctx->buf2, ctx->pixel_buf);
    double t2 = emscripten_get_now();

    std::swap(ctx->buf1, ctx->buf2);

    SDL_UpdateTexture(ctx->tex, NULL, ctx->pixel_buf.data(), ctx->pixel_buf.dim(1).stride() * sizeof(uint32_t));

    SDL_RenderClear(renderer);
    SDL_RenderCopy(renderer, ctx->tex, NULL, NULL);
    SDL_RenderPresent(renderer);

    double t3 = emscripten_get_now();

    double this_runtime = (t2 - t1);
    double this_blit_time = (t3 - t2);
    double this_fps = 1000 / (t3 - ctx->last_frame_time);

    ctx->iteration++;
    if (ctx->iteration < 2) {
        ctx->smoothed_runtime = this_runtime;
        ctx->smoothed_fps = this_fps;
        ctx->smoothed_blit_time = this_blit_time;
    } else {
        ctx->smoothed_runtime = 0.9 * ctx->smoothed_runtime + 0.1 * this_runtime;
        ctx->smoothed_fps = 0.9 * ctx->smoothed_fps + 0.1 * this_fps;
        ctx->smoothed_blit_time = 0.9 * ctx->smoothed_blit_time + 0.1 * this_blit_time;
    }
    ctx->last_frame_time = t3;

    if ((ctx->iteration & 15) == 15) {
        char buf[1024] = {0};
        snprintf(buf, sizeof(buf),
                 "Time for Halide update + render: %0.2f ms<br>"
                 "Time for blit to framebuffer: %0.2f ms<br>"
                 "Frame rate: %2.0f fps",
                 ctx->smoothed_runtime, ctx->smoothed_blit_time, ctx->smoothed_fps);
        // Run some javascript inline to update the web-page
        EM_ASM({ document.getElementById(UTF8ToString($0)).innerHTML = UTF8ToString($1); }, "runtime", buf);

        // Read the threads slider from the UI
        int threads = EM_ASM_INT({
            return parseInt(document.getElementById("threads").value);
        });

        halide_set_num_threads(threads);
        if (threads != ctx->threads) {
            halide_shutdown_thread_pool();
            ctx->threads = threads;
        }
    }
}

int main() {
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window *window;
    SDL_Renderer *renderer;
    SDL_CreateWindowAndRenderer(W, H, 0, &window, &renderer);

    Context ctx;
    ctx.renderer = renderer;
    ctx.buf1 = Halide::Runtime::Buffer<float, 3>(W, H, 3);
    ctx.buf2 = Halide::Runtime::Buffer<float, 3>(W, H, 3);
    ctx.pixel_buf = Halide::Runtime::Buffer<uint32_t, 2>(W, H);

    ctx.tex = SDL_CreateTexture(renderer,
                                SDL_PIXELFORMAT_ARGB8888,
                                SDL_TEXTUREACCESS_STREAMING,
                                W, H);

    // Read the initial thread count from the DOM
    int threads = EM_ASM_INT({
        return parseInt(document.getElementById("threads").value);
    });
    halide_set_num_threads(threads);

    reaction_diffusion_init(ctx.buf1);

    // call the function repeatedly
    const int simulate_infinite_loop = 1;

    // call the function as fast as the browser wants to render (typically 60fps)
    const int fps = -1;
    emscripten_set_main_loop_arg(mainloop, &ctx, fps, simulate_infinite_loop);

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}