~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mesa/math/m_debug_clip.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Mesa 3-D graphics library
3
 
 *
4
 
 * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
5
 
 *
6
 
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 
 * copy of this software and associated documentation files (the "Software"),
8
 
 * to deal in the Software without restriction, including without limitation
9
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 
 * and/or sell copies of the Software, and to permit persons to whom the
11
 
 * Software is furnished to do so, subject to the following conditions:
12
 
 *
13
 
 * The above copyright notice and this permission notice shall be included
14
 
 * in all copies or substantial portions of the Software.
15
 
 *
16
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 
 * OTHER DEALINGS IN THE SOFTWARE.
23
 
 *
24
 
 * Authors:
25
 
 *    Gareth Hughes
26
 
 */
27
 
 
28
 
#include "main/glheader.h"
29
 
#include "main/context.h"
30
 
#include "main/macros.h"
31
 
 
32
 
 
33
 
#include "m_matrix.h"
34
 
#include "m_xform.h"
35
 
 
36
 
#include "m_debug.h"
37
 
#include "m_debug_util.h"
38
 
 
39
 
#ifdef __UNIXOS2__
40
 
/* The linker doesn't like empty files */
41
 
static char dummy;
42
 
#endif
43
 
 
44
 
#ifdef DEBUG_MATH  /* This code only used for debugging */
45
 
 
46
 
static clip_func *clip_tab[2] = {
47
 
   _mesa_clip_tab,
48
 
   _mesa_clip_np_tab
49
 
};
50
 
static char *cnames[2] = {
51
 
   "_mesa_clip_tab",
52
 
   "_mesa_clip_np_tab"
53
 
};
54
 
#ifdef RUN_DEBUG_BENCHMARK
55
 
static char *cstrings[2] = {
56
 
   "clip, perspective divide",
57
 
   "clip, no divide"
58
 
};
59
 
#endif
60
 
 
61
 
 
62
 
/* =============================================================
63
 
 * Reference cliptests
64
 
 */
65
 
 
66
 
static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec,
67
 
                                         GLvector4f *proj_vec,
68
 
                                         GLubyte clipMask[],
69
 
                                         GLubyte *orMask,
70
 
                                         GLubyte *andMask,
71
 
                                         GLboolean viewport_z_clip )
72
 
{
73
 
   const GLuint stride = clip_vec->stride;
74
 
   const GLuint count = clip_vec->count;
75
 
   const GLfloat *from = (GLfloat *)clip_vec->start;
76
 
   GLuint c = 0;
77
 
   GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
78
 
   GLubyte tmpAndMask = *andMask;
79
 
   GLubyte tmpOrMask = *orMask;
80
 
   GLuint i;
81
 
   for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
82
 
      const GLfloat cx = from[0];
83
 
      const GLfloat cy = from[1];
84
 
      const GLfloat cz = from[2];
85
 
      const GLfloat cw = from[3];
86
 
      GLubyte mask = 0;
87
 
      if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT;
88
 
      if (  cx + cw < 0 ) mask |= CLIP_LEFT_BIT;
89
 
      if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT;
90
 
      if (  cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT;
91
 
      if (viewport_z_clip) {
92
 
         if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT;
93
 
         if (  cz + cw < 0 ) mask |= CLIP_NEAR_BIT;
94
 
      }
95
 
      clipMask[i] = mask;
96
 
      if ( mask ) {
97
 
         c++;
98
 
         tmpAndMask &= mask;
99
 
         tmpOrMask |= mask;
100
 
         vProj[i][0] = 0;
101
 
         vProj[i][1] = 0;
102
 
         vProj[i][2] = 0;
103
 
         vProj[i][3] = 1;
104
 
      } else {
105
 
         GLfloat oow = 1.0F / cw;
106
 
         vProj[i][0] = cx * oow;
107
 
         vProj[i][1] = cy * oow;
108
 
         vProj[i][2] = cz * oow;
109
 
         vProj[i][3] = oow;
110
 
      }
111
 
   }
112
 
 
113
 
   *orMask = tmpOrMask;
114
 
   *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
115
 
 
116
 
   proj_vec->flags |= VEC_SIZE_4;
117
 
   proj_vec->size = 4;
118
 
   proj_vec->count = clip_vec->count;
119
 
   return proj_vec;
120
 
}
121
 
 
122
 
/* Keep these here for now, even though we don't use them...
123
 
 */
124
 
static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec,
125
 
                                         GLvector4f *proj_vec,
126
 
                                         GLubyte clipMask[],
127
 
                                         GLubyte *orMask,
128
 
                                         GLubyte *andMask,
129
 
                                         GLboolean viewport_z_clip )
130
 
{
131
 
   const GLuint stride = clip_vec->stride;
132
 
   const GLuint count = clip_vec->count;
133
 
   const GLfloat *from = (GLfloat *)clip_vec->start;
134
 
 
135
 
   GLubyte tmpOrMask = *orMask;
136
 
   GLubyte tmpAndMask = *andMask;
137
 
   GLuint i;
138
 
   for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
139
 
      const GLfloat cx = from[0], cy = from[1], cz = from[2];
140
 
      GLubyte mask = 0;
141
 
      if ( cx >  1.0 )          mask |= CLIP_RIGHT_BIT;
142
 
      else if ( cx < -1.0 )     mask |= CLIP_LEFT_BIT;
143
 
      if ( cy >  1.0 )          mask |= CLIP_TOP_BIT;
144
 
      else if ( cy < -1.0 )     mask |= CLIP_BOTTOM_BIT;
145
 
      if (viewport_z_clip) {
146
 
         if ( cz >  1.0 )               mask |= CLIP_FAR_BIT;
147
 
         else if ( cz < -1.0 )  mask |= CLIP_NEAR_BIT;
148
 
      }
149
 
      clipMask[i] = mask;
150
 
      tmpOrMask |= mask;
151
 
      tmpAndMask &= mask;
152
 
   }
153
 
 
154
 
   *orMask = tmpOrMask;
155
 
   *andMask = tmpAndMask;
156
 
   return clip_vec;
157
 
}
158
 
 
159
 
static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec,
160
 
                                          GLvector4f *proj_vec,
161
 
                                          GLubyte clipMask[],
162
 
                                          GLubyte *orMask,
163
 
                                          GLubyte *andMask,
164
 
                                          GLboolean viewport_z_clip )
165
 
{
166
 
   const GLuint stride = clip_vec->stride;
167
 
   const GLuint count = clip_vec->count;
168
 
   const GLfloat *from = (GLfloat *)clip_vec->start;
169
 
 
170
 
   GLubyte tmpOrMask = *orMask;
171
 
   GLubyte tmpAndMask = *andMask;
172
 
   GLuint i;
173
 
 
174
 
   (void) viewport_z_clip;
175
 
 
176
 
   for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
177
 
      const GLfloat cx = from[0], cy = from[1];
178
 
      GLubyte mask = 0;
179
 
      if ( cx >  1.0 )          mask |= CLIP_RIGHT_BIT;
180
 
      else if ( cx < -1.0 )     mask |= CLIP_LEFT_BIT;
181
 
      if ( cy >  1.0 )          mask |= CLIP_TOP_BIT;
182
 
      else if ( cy < -1.0 )     mask |= CLIP_BOTTOM_BIT;
183
 
      clipMask[i] = mask;
184
 
      tmpOrMask |= mask;
185
 
      tmpAndMask &= mask;
186
 
   }
187
 
 
188
 
   *orMask = tmpOrMask;
189
 
   *andMask = tmpAndMask;
190
 
   return clip_vec;
191
 
}
192
 
 
193
 
static clip_func ref_cliptest[5] = {
194
 
   0,
195
 
   0,
196
 
   ref_cliptest_points2,
197
 
   ref_cliptest_points3,
198
 
   ref_cliptest_points4
199
 
};
200
 
 
201
 
 
202
 
/* =============================================================
203
 
 * Cliptest tests
204
 
 */
205
 
 
206
 
ALIGN16 static GLfloat s[TEST_COUNT][4];
207
 
ALIGN16 static GLfloat d[TEST_COUNT][4];
208
 
ALIGN16 static GLfloat r[TEST_COUNT][4];
209
 
 
210
 
 
211
 
/**
212
 
 * Check if X, Y or Z component of the coordinate is close to W, in terms
213
 
 * of the clip test.
214
 
 */
215
 
static GLboolean
216
 
xyz_close_to_w(const GLfloat c[4])
217
 
{
218
 
   float k = 0.0001;
219
 
   return (fabs(c[0] - c[3]) < k ||
220
 
           fabs(c[1] - c[3]) < k ||
221
 
           fabs(c[2] - c[3]) < k ||
222
 
           fabs(-c[0] - c[3]) < k ||
223
 
           fabs(-c[1] - c[3]) < k ||
224
 
           fabs(-c[2] - c[3]) < k);
225
 
}
226
 
 
227
 
 
228
 
 
229
 
static int test_cliptest_function( clip_func func, int np,
230
 
                                   int psize, long *cycles )
231
 
{
232
 
   GLvector4f source[1], dest[1], ref[1];
233
 
   GLubyte dm[TEST_COUNT], dco, dca;
234
 
   GLubyte rm[TEST_COUNT], rco, rca;
235
 
   int i, j;
236
 
#ifdef  RUN_DEBUG_BENCHMARK
237
 
   int cycle_i;                /* the counter for the benchmarks we run */
238
 
#endif
239
 
   GLboolean viewport_z_clip = GL_TRUE;
240
 
 
241
 
   (void) cycles;
242
 
 
243
 
   if ( psize > 4 ) {
244
 
      _mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" );
245
 
      return 0;
246
 
   }
247
 
 
248
 
   for ( i = 0 ; i < TEST_COUNT ; i++) {
249
 
      ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 );
250
 
      ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 );
251
 
      for ( j = 0 ; j < psize ; j++ )
252
 
         s[i][j] = rnd();
253
 
   }
254
 
 
255
 
   source->data = (GLfloat(*)[4])s;
256
 
   source->start = (GLfloat *)s;
257
 
   source->count = TEST_COUNT;
258
 
   source->stride = sizeof(s[0]);
259
 
   source->size = 4;
260
 
   source->flags = 0;
261
 
 
262
 
   dest->data = (GLfloat(*)[4])d;
263
 
   dest->start = (GLfloat *)d;
264
 
   dest->count = TEST_COUNT;
265
 
   dest->stride = sizeof(float[4]);
266
 
   dest->size = 0;
267
 
   dest->flags = 0;
268
 
 
269
 
   ref->data = (GLfloat(*)[4])r;
270
 
   ref->start = (GLfloat *)r;
271
 
   ref->count = TEST_COUNT;
272
 
   ref->stride = sizeof(float[4]);
273
 
   ref->size = 0;
274
 
   ref->flags = 0;
275
 
 
276
 
   dco = rco = 0;
277
 
   dca = rca = CLIP_FRUSTUM_BITS;
278
 
 
279
 
   ref_cliptest[psize]( source, ref, rm, &rco, &rca, viewport_z_clip );
280
 
 
281
 
   if ( mesa_profile ) {
282
 
      BEGIN_RACE( *cycles );
283
 
      func( source, dest, dm, &dco, &dca, viewport_z_clip );
284
 
      END_RACE( *cycles );
285
 
   }
286
 
   else {
287
 
      func( source, dest, dm, &dco, &dca, viewport_z_clip );
288
 
   }
289
 
 
290
 
   if ( dco != rco ) {
291
 
      printf( "\n-----------------------------\n" );
292
 
      printf( "dco = 0x%02x   rco = 0x%02x\n", dco, rco );
293
 
      return 0;
294
 
   }
295
 
   if ( dca != rca ) {
296
 
      printf( "\n-----------------------------\n" );
297
 
      printf( "dca = 0x%02x   rca = 0x%02x\n", dca, rca );
298
 
      return 0;
299
 
   }
300
 
   for ( i = 0 ; i < TEST_COUNT ; i++ ) {
301
 
      if ( dm[i] != rm[i] ) {
302
 
         GLfloat *c = source->start;
303
 
         STRIDE_F(c, source->stride * i);
304
 
         if (psize == 4 && xyz_close_to_w(c)) {
305
 
            /* The coordinate is very close to the clip plane.  The clipmask
306
 
             * may vary depending on code path, but that's OK.
307
 
             */
308
 
            continue;
309
 
         }
310
 
         printf( "\n-----------------------------\n" );
311
 
         printf( "mask[%d] = 0x%02x   ref mask[%d] = 0x%02x\n", i, dm[i], i,rm[i] );
312
 
         printf(" coord = %f, %f, %f, %f\n",
313
 
                c[0], c[1], c[2], c[3]);
314
 
         return 0;
315
 
      }
316
 
   }
317
 
 
318
 
   /* Only verify output on projected points4 case.  FIXME: Do we need
319
 
    * to test other cases?
320
 
    */
321
 
   if ( np || psize < 4 )
322
 
      return 1;
323
 
 
324
 
   for ( i = 0 ; i < TEST_COUNT ; i++ ) {
325
 
      for ( j = 0 ; j < 4 ; j++ ) {
326
 
         if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
327
 
            printf( "\n-----------------------------\n" );
328
 
            printf( "(i = %i, j = %i)  dm = 0x%02x   rm = 0x%02x\n",
329
 
                    i, j, dm[i], rm[i] );
330
 
            printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
331
 
                    d[i][0], r[i][0], r[i][0]-d[i][0],
332
 
                    MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
333
 
            printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
334
 
                    d[i][1], r[i][1], r[i][1]-d[i][1],
335
 
                    MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
336
 
            printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
337
 
                    d[i][2], r[i][2], r[i][2]-d[i][2],
338
 
                    MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
339
 
            printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
340
 
                    d[i][3], r[i][3], r[i][3]-d[i][3],
341
 
                    MAX_PRECISION - significand_match( d[i][3], r[i][3] ) );
342
 
            return 0;
343
 
         }
344
 
      }
345
 
   }
346
 
 
347
 
   return 1;
348
 
}
349
 
 
350
 
void _math_test_all_cliptest_functions( char *description )
351
 
{
352
 
   int np, psize;
353
 
   long benchmark_tab[2][4];
354
 
   static int first_time = 1;
355
 
 
356
 
   if ( first_time ) {
357
 
      first_time = 0;
358
 
      mesa_profile = getenv( "MESA_PROFILE" );
359
 
   }
360
 
 
361
 
#ifdef RUN_DEBUG_BENCHMARK
362
 
   if ( mesa_profile ) {
363
 
      if ( !counter_overhead ) {
364
 
         INIT_COUNTER();
365
 
         printf( "counter overhead: %ld cycles\n\n", counter_overhead );
366
 
      }
367
 
      printf( "cliptest results after hooking in %s functions:\n", description );
368
 
   }
369
 
#endif
370
 
 
371
 
#ifdef RUN_DEBUG_BENCHMARK
372
 
   if ( mesa_profile ) {
373
 
      printf( "\n\t" );
374
 
      for ( psize = 2 ; psize <= 4 ; psize++ ) {
375
 
         printf( " p%d\t", psize );
376
 
      }
377
 
      printf( "\n--------------------------------------------------------\n\t" );
378
 
   }
379
 
#endif
380
 
 
381
 
   for ( np = 0 ; np < 2 ; np++ ) {
382
 
      for ( psize = 2 ; psize <= 4 ; psize++ ) {
383
 
         clip_func func = clip_tab[np][psize];
384
 
         long *cycles = &(benchmark_tab[np][psize-1]);
385
 
 
386
 
         if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) {
387
 
            char buf[100];
388
 
            sprintf( buf, "%s[%d] failed test (%s)",
389
 
                     cnames[np], psize, description );
390
 
            _mesa_problem( NULL, "%s", buf );
391
 
         }
392
 
#ifdef RUN_DEBUG_BENCHMARK
393
 
         if ( mesa_profile )
394
 
            printf( " %li\t", benchmark_tab[np][psize-1] );
395
 
#endif
396
 
      }
397
 
#ifdef RUN_DEBUG_BENCHMARK
398
 
      if ( mesa_profile )
399
 
         printf( " | [%s]\n\t", cstrings[np] );
400
 
#endif
401
 
   }
402
 
#ifdef RUN_DEBUG_BENCHMARK
403
 
   if ( mesa_profile )
404
 
      printf( "\n" );
405
 
#endif
406
 
}
407
 
 
408
 
 
409
 
#endif /* DEBUG_MATH */