MaxImageSplit.c 9.71 KB
Newer Older
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* -*- c -*- *****************************************************************
** Copyright (C) 2011 Sandia Corporation
** Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
** the U.S. Government retains certain rights in this software.
**
** This source code is released under the New BSD License.
**
** This tests the ICET_MAX_IMAGE_SPLIT option.  It sets the max image split to
** less than the total number of processes and makes sure that the image is
** still composited correctly.
*****************************************************************************/

#include <IceT.h>
#include "test_codes.h"
#include "test-util.h"

#include <IceTDevContext.h>
#include <IceTDevMatrix.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define PROC_REGION_WIDTH       10
#define PROC_REGION_HEIGHT      10

static void MaxImageSplitDraw(const IceTDouble *projection_matrix,
                              const IceTDouble *modelview_matrix,
                              const IceTFloat *background_color,
                              const IceTInt *readback_viewport,
                              IceTImage result)
{
    IceTDouble full_transform[16];
    IceTSizeType width;
    IceTSizeType height;
    IceTUInt *colors;
    IceTFloat *depths;

    /* Not using this. */
    (void)background_color;

    width = icetImageGetWidth(result);
    height = icetImageGetHeight(result);

    colors = icetImageGetColorui(result);
    depths = icetImageGetDepthf(result);

    /* Get full transform all the way to window coordinates (pixels). */ {
        IceTDouble scale_transform[16];
        IceTDouble translate_transform[16];
        icetMatrixScale(0.5*width, 0.5*height, 0.5, scale_transform);
        icetMatrixTranslate(1.0, 1.0, 1.0, translate_transform);
        icetMatrixMultiply(full_transform,scale_transform,translate_transform);
        icetMatrixPostMultiply(full_transform, projection_matrix);
        icetMatrixPostMultiply(full_transform, modelview_matrix);
    }

    /* Clear out the image (testing purposes only). */ {
        IceTSizeType pixel;
        memset(colors, 0xFC, width*height*sizeof(IceTUInt));
        for (pixel = 0; pixel < width*height; pixel++) {
            depths[pixel] = 1.0;
        }
    }

    /* Set my pixels. */ {
        IceTInt rank;
        IceTSizeType region_y_start;
        IceTSizeType region_x;
        IceTSizeType region_y;

        icetGetIntegerv(ICET_RANK, &rank);
        region_y_start = rank*PROC_REGION_HEIGHT;

        for (region_y = 0; region_y < PROC_REGION_HEIGHT; region_y++) {
            for (region_x = 0; region_x < PROC_REGION_WIDTH; region_x++) {
                IceTDouble object_coord[4];
                IceTDouble window_coord[4];
                IceTSizeType window_pixel[2];
                IceTSizeType readback_lower[2];
                IceTSizeType readback_upper[2];
                IceTBoolean in_readback;

                object_coord[0] = (IceTDouble)region_x;
                object_coord[1] = (IceTDouble)(region_y + region_y_start);
                object_coord[2] = 0.0;
                object_coord[3] = 1.0;

                icetMatrixVectorMultiply(window_coord,
                                         full_transform,
                                         object_coord);

                window_pixel[0]=(IceTSizeType)(window_coord[0]/window_coord[3]);
                window_pixel[1]=(IceTSizeType)(window_coord[1]/window_coord[3]);

                readback_lower[0] = readback_viewport[0];
                readback_lower[1] = readback_viewport[1];
                readback_upper[0] = readback_viewport[0] + readback_viewport[2];
                readback_upper[1] = readback_viewport[1] + readback_viewport[3];

                in_readback  = (readback_lower[0] <= window_pixel[0]);
                in_readback &= (readback_lower[1] <= window_pixel[1]);
                in_readback &= (window_pixel[0] < readback_upper[0]);
                in_readback &= (window_pixel[1] < readback_upper[1]);
                if (in_readback) {
                    IceTSizeType pixel_idx
                        = window_pixel[0] + window_pixel[1]*PROC_REGION_WIDTH;
                    colors[pixel_idx] = rank;
                    depths[pixel_idx] = 0.0;
                }
            }
        }
    }
}

static void MaxImageSplitSetupRender()
{
    IceTInt num_proc;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

    icetCompositeMode(ICET_COMPOSITE_MODE_Z_BUFFER);
    icetSetColorFormat(ICET_IMAGE_COLOR_RGBA_UBYTE);
    icetSetDepthFormat(ICET_IMAGE_DEPTH_FLOAT);
    icetDisable(ICET_ORDERED_COMPOSITE);

    icetDrawCallback(MaxImageSplitDraw);

    icetResetTiles();
    icetAddTile(0, 0, PROC_REGION_WIDTH, PROC_REGION_HEIGHT*num_proc, 0);
}

static void MaxImageSplitGetMatrices(IceTDouble *projection_matrix,
                                     IceTDouble *modelview_matrix)
{
    IceTDouble scale_matrix[16];
    IceTDouble transform_matrix[16];
    IceTInt num_proc;
    IceTInt rank;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
    icetGetIntegerv(ICET_RANK, &rank);

    /* Make the projection really project pixel positions to normalized clipping
       coordinates. */
    icetMatrixScale(2.0/PROC_REGION_WIDTH,
                    2.0/(PROC_REGION_HEIGHT*num_proc),
                    2.0,
                    scale_matrix);
    icetMatrixTranslate(-1.0, -1.0, -1.0, transform_matrix);
    icetMatrixMultiply(projection_matrix, transform_matrix, scale_matrix);

    /* The modelview just passes pixel positions. */
    icetMatrixIdentity(modelview_matrix);

    /* Based on these matrices, set the region we want the local process to draw
       pixels.  The region is defined in pixels.  The previous matrices
       transform the pixels to screen coordinates, which should then implicitly
       be transformed back to pixel coordinates in the draw function. */
    icetBoundingBoxd(0.0,
                     (IceTDouble)PROC_REGION_WIDTH,
                     (IceTDouble)rank*PROC_REGION_HEIGHT,
                     (IceTDouble)(rank+1)*PROC_REGION_HEIGHT,
                     0.0,
                     1.0);
}

static int MaxImageSplitCheckImage(const IceTImage image)
{
    IceTInt rank;

    icetGetIntegerv(ICET_RANK, &rank);
    if (rank == 0) {
        IceTInt num_proc;
        IceTInt proc;
        const IceTUInt *pixel;

        icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

        pixel = icetImageGetColorcui(image);

        for (proc = 0; proc < num_proc; proc++) {
            IceTInt x, y;
            for (y = 0; y < PROC_REGION_HEIGHT; y++) {
                for (x = 0; x < PROC_REGION_WIDTH; x++) {
                    if (*pixel != proc) {
187
188
189
190
                        printrank("**** Found bad pixel!!!! ****\n");
                        printrank("Region for process %d, x = %d, y = %d\n",
                                  proc, x, y);
                        printrank("Reported %d\n", *pixel);
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
                        return TEST_FAILED;
                    }
                    pixel++;
                }
            }
        }
    }

    return TEST_PASSED;
}

static int MaxImageSplitTryRender()
{
    IceTDouble projection_matrix[16];
    IceTDouble modelview_matrix[16];
    IceTFloat white[4];
    IceTImage image;

    MaxImageSplitSetupRender();
    MaxImageSplitGetMatrices(projection_matrix, modelview_matrix);

    white[0] = white[1] = white[2] = white[3] = 1.0f;

    image = icetDrawFrame(projection_matrix, modelview_matrix, white);

    return MaxImageSplitCheckImage(image);
}

static int MaxImageSplitTryStrategy()
{
    int result = TEST_PASSED;
    int si_strategy_idx;

    icetStrategy(ICET_STRATEGY_SEQUENTIAL);

    for (si_strategy_idx = 0;
         si_strategy_idx < SINGLE_IMAGE_STRATEGY_LIST_SIZE;
         si_strategy_idx++) {
        icetSingleImageStrategy(single_image_strategy_list[si_strategy_idx]);
230
231
        printstat("  Trying single image strategy %s\n",
                  icetGetSingleImageStrategyName());
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
        result += MaxImageSplitTryRender();
    }

    return result;
}

static int MaxImageSplitTryMax()
{
    IceTContext original_context = icetGetContext();
    IceTInt num_proc;
    IceTInt max_image_split;
    IceTInt result = TEST_PASSED;

    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

    for (max_image_split = 1;
         max_image_split/2 < num_proc;
         max_image_split *= 2) {
250
        char image_split_string[64];
251
252
        IceTInt reported_image_split;

253
        printstat("Trying max image split of %d\n", max_image_split);
254

255
256
#ifdef _WIN32
        sprintf(image_split_string, "ICET_MAX_IMAGE_SPLIT=%d", max_image_split);
257
        putenv(image_split_string);
258
#else
259
260
        sprintf(image_split_string, "%d", max_image_split);
        setenv("ICET_MAX_IMAGE_SPLIT", image_split_string, ICET_TRUE);
261
#endif
262
263
264
265
266
267
268
269
270
271
272
273

        /* This is a bit hackish.  The max image split value is set when the
           IceT context is initialized.  Thus, for the environment to take
           effect, we need to make a new context.  To make a new context, we
           need to get the communiator. */
        {
            IceTCommunicator comm = icetGetCommunicator();
            icetCreateContext(comm);
        }

        icetGetIntegerv(ICET_MAX_IMAGE_SPLIT, &reported_image_split);
        if (max_image_split != reported_image_split) {
274
            printrank("**** Max image split not set correctly!!!! ****\n");
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
            return TEST_FAILED;
        }

        result += MaxImageSplitTryStrategy();

        /* We no longer need the context we just created. */
        icetDestroyContext(icetGetContext());
        icetSetContext(original_context);
    }

    return result;
}

static int MaxImageSplitRun(void)
{
    return MaxImageSplitTryMax();
}

int MaxImageSplit(int argc, char *argv[])
{
    /* To remove warning. */
    (void)argc;
    (void)argv;

    return run_test(MaxImageSplitRun);
}