aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
blob: 6526f82435b1daa68d71904c256b89900e2e36b3 (plain)
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
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

#include "pipeline.h"
#include <hip/hip_runtime.h>
#include <cstdio>
#include <string>
#include <vector>

static float4* upload_image(const char* path, int& out_width, int& out_height) {
    int w, h, channels;
    unsigned char* data = stbi_load(path, &w, &h, &channels, 4);
    if (!data) throw std::runtime_error(std::string("Failed to load: ") + path);

    out_width = w; out_height = h;
    const int n = w * h;

    std::vector<float4> host(n);
    for (int i = 0; i < n; ++i) {
        host[i] = make_float4(
            data[4*i + 0] / 255.0f,
            data[4*i + 1] / 255.0f,
            data[4*i + 2] / 255.0f,
            0.0f);
    }
    stbi_image_free(data);

    float4* dev;
    hip_check(hipMalloc(&dev, sizeof(float4) * n));
    hip_check(hipMemcpy(dev, host.data(), sizeof(float4) * n, hipMemcpyHostToDevice));
    return dev;
}

static void dump_level(const PyramidLevel& lvl, const char* path) {
    const int n = lvl.width * lvl.height;
    std::vector<float4> host(n);
    hip_check(hipMemcpy(host.data(), lvl.color_smax,
                        sizeof(float4) * n, hipMemcpyDeviceToHost));

    std::vector<unsigned char> bytes(n * 3);
    for (int i = 0; i < n; ++i) {
        bytes[3*i + 0] = static_cast<unsigned char>(
            std::min(host[i].x, 1.0f) * 255.0f);
        bytes[3*i + 1] = static_cast<unsigned char>(
            std::min(host[i].y, 1.0f) * 255.0f);
        bytes[3*i + 2] = static_cast<unsigned char>(
            std::min(host[i].z, 1.0f) * 255.0f);
    }
    stbi_write_png(path, lvl.width, lvl.height, 3, bytes.data(), lvl.width * 3);
    printf("Wrote %s (%dx%d)\n", path, lvl.width, lvl.height);
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <image>\n", argv[0]);
        return 1;
    }

    try {
        int w, h;
        float4* src = upload_image(argv[1], w, h);

        const int num_levels = 5;
        Pyramid pyr = make_pyramid(w, h, num_levels);

        hip_check(hipMemcpy(pyr.levels[0].color_smax, src,
                            sizeof(float4) * w * h, hipMemcpyDeviceToDevice));
        hipFree(src);

        build_pyramid(pyr);

        for (int i = 0; i < static_cast<int>(pyr.levels.size()); ++i) {
            std::string path = "level_" + std::to_string(i) + ".png";
            dump_level(pyr.levels[i], path.c_str());
        }

        destroy_pyramid(pyr);

    } catch (const std::exception& e) {
        fprintf(stderr, "Error: %s\n", e.what());
        return 1;
    }

    return 0;
}