Add CTS_ARB_gl_spirv test implementation
[platform/upstream/VK-GL-CTS.git] / framework / referencerenderer / rrPrimitiveAssembler.hpp
1 #ifndef _RRPRIMITIVEASSEMBLER_HPP
2 #define _RRPRIMITIVEASSEMBLER_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Reference Renderer
5  * -----------------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Primitive assembler
24  *//*--------------------------------------------------------------------*/
25
26 #include "rrDefs.hpp"
27 #include "rrVertexPacket.hpp"
28
29 namespace rr
30 {
31 namespace pa
32 {
33
34 struct Triangle
35 {
36         enum
37         {
38                 NUM_VERTICES = 3
39         };
40
41         Triangle (void)
42                 : v0                            (DE_NULL)
43                 , v1                            (DE_NULL)
44                 , v2                            (DE_NULL)
45                 , provokingIndex        (-1)
46         {
47         }
48
49         Triangle (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, int provokingIndex_)
50                 : v0                            (v0_)
51                 , v1                            (v1_)
52                 , v2                            (v2_)
53                 , provokingIndex        (provokingIndex_)
54         {
55         }
56
57         VertexPacket* getProvokingVertex (void)
58         {
59                 switch (provokingIndex)
60                 {
61                         case 0: return v0;
62                         case 1: return v1;
63                         case 2: return v2;
64                         default:
65                                 DE_ASSERT(false);
66                                 return DE_NULL;
67                 }
68         }
69
70         VertexPacket*   v0;
71         VertexPacket*   v1;
72         VertexPacket*   v2;
73
74         int                             provokingIndex;
75 } DE_WARN_UNUSED_TYPE;
76
77 struct Triangles
78 {
79         template <typename Iterator>
80         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
81         {
82                 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2);
83
84                 for (size_t ndx = 0; ndx + 2 < numVertices; ndx += 3)
85                         *(outputIterator++) = Triangle(vertices[ndx], vertices[ndx+1], vertices[ndx+2], provokingOffset);
86         }
87
88         static size_t getPrimitiveCount (size_t vertices)
89         {
90                 return vertices / 3;
91         }
92 } DE_WARN_UNUSED_TYPE;
93
94 struct TriangleStrip
95 {
96         template <typename Iterator>
97         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
98         {
99                 if (numVertices < 3)
100                 {
101                 }
102                 else
103                 {
104                         VertexPacket* vert0 = vertices[0];
105                         VertexPacket* vert1 = vertices[1];
106                         size_t ndx = 2;
107
108                         for (;;)
109                         {
110                                 {
111                                         if (ndx >= numVertices)
112                                                 break;
113
114                                         *(outputIterator++) = Triangle(vert0, vert1, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (2));
115                                         vert0 = vertices[ndx];
116
117                                         ndx++;
118                                 }
119
120                                 {
121                                         if (ndx >= numVertices)
122                                                 break;
123
124                                         *(outputIterator++) = Triangle(vert0, vert1, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2));
125                                         vert1 = vertices[ndx];
126
127                                         ndx++;
128                                 }
129                         }
130                 }
131         }
132
133         static size_t getPrimitiveCount (size_t vertices)
134         {
135                 return (vertices < 3) ? (0) : (vertices - 2);
136         }
137 } DE_WARN_UNUSED_TYPE;
138
139 struct TriangleFan
140 {
141         template <typename Iterator>
142         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
143         {
144                 if (numVertices == 0)
145                 {
146                 }
147                 else
148                 {
149                         const int                       provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
150                         VertexPacket* const     first                   = vertices[0];
151
152                         for (size_t ndx = 1; ndx + 1 < numVertices; ++ndx)
153                                 *(outputIterator++) = Triangle(first, vertices[ndx], vertices[ndx+1], provokingOffset);
154                 }
155         }
156
157         static size_t getPrimitiveCount (size_t vertices)
158         {
159                 return (vertices < 3) ? (0) : (vertices - 2);
160         }
161 } DE_WARN_UNUSED_TYPE;
162
163 struct Line
164 {
165         enum
166         {
167                 NUM_VERTICES = 2
168         };
169
170         Line (void)
171                 : v0                            (DE_NULL)
172                 , v1                            (DE_NULL)
173                 , provokingIndex        (-1)
174         {
175         }
176
177         Line (VertexPacket* v0_, VertexPacket* v1_, int provokingIndex_)
178                 : v0                            (v0_)
179                 , v1                            (v1_)
180                 , provokingIndex        (provokingIndex_)
181         {
182         }
183
184         VertexPacket* getProvokingVertex (void)
185         {
186                 switch (provokingIndex)
187                 {
188                         case 0: return v0;
189                         case 1: return v1;
190                         default:
191                                 DE_ASSERT(false);
192                                 return DE_NULL;
193                 }
194         }
195
196         VertexPacket*   v0;
197         VertexPacket*   v1;
198
199         int                             provokingIndex;
200 } DE_WARN_UNUSED_TYPE;
201
202 struct Lines
203 {
204         template <typename Iterator>
205         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
206         {
207                 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1);
208
209                 for (size_t ndx = 0; ndx + 1 < numVertices; ndx += 2)
210                         *(outputIterator++) = Line(vertices[ndx], vertices[ndx+1], provokingOffset);
211         }
212
213         static size_t getPrimitiveCount (size_t vertices)
214         {
215                 return vertices / 2;
216         }
217 } DE_WARN_UNUSED_TYPE;
218
219 struct LineStrip
220 {
221         template <typename Iterator>
222         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
223         {
224                 if (numVertices == 0)
225                 {
226                 }
227                 else
228                 {
229                         VertexPacket* prev = vertices[0];
230
231                         for (size_t ndx = 1; ndx < numVertices; ++ndx)
232                         {
233                                 *(outputIterator++) = Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
234                                 prev = vertices[ndx];
235                         }
236                 }
237         }
238
239         static size_t getPrimitiveCount (size_t vertices)
240         {
241                 return (vertices < 2) ? (0) : (vertices - 1);
242         }
243 } DE_WARN_UNUSED_TYPE;
244
245 struct LineLoop
246 {
247         template <typename Iterator>
248         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
249         {
250                 if (numVertices < 2)
251                 {
252                 }
253                 else
254                 {
255                         VertexPacket* prev = vertices[0];
256
257                         for (size_t ndx = 1; ndx < numVertices; ++ndx)
258                         {
259                                 *(outputIterator++) = Line(prev, vertices[ndx], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
260                                 prev = vertices[ndx];
261                         }
262
263                         *(outputIterator++) = Line(prev, vertices[0], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (1));
264                 }
265         }
266
267         static size_t getPrimitiveCount (size_t vertices)
268         {
269                 return (vertices < 2) ? (0) : (vertices);
270         }
271 } DE_WARN_UNUSED_TYPE;
272
273 struct Point
274 {
275         enum
276         {
277                 NUM_VERTICES = 1
278         };
279
280         Point (void)
281                 : v0(DE_NULL)
282         {
283         }
284
285         Point (VertexPacket* v0_)
286                 : v0(v0_)
287         {
288         }
289
290         VertexPacket* v0;
291 } DE_WARN_UNUSED_TYPE;
292
293 struct Points
294 {
295         template <typename Iterator>
296         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
297         {
298                 DE_UNREF(provokingConvention);
299
300                 for (size_t ndx = 0; ndx < numVertices; ++ndx)
301                         *(outputIterator++) = Point(vertices[ndx]);
302         }
303
304         static size_t getPrimitiveCount (size_t vertices)
305         {
306                 return (vertices);
307         }
308 } DE_WARN_UNUSED_TYPE;
309
310 struct LineAdjacency
311 {
312         enum
313         {
314                 NUM_VERTICES = 4
315         };
316
317         LineAdjacency (void)
318                 : v0                            (DE_NULL)
319                 , v1                            (DE_NULL)
320                 , v2                            (DE_NULL)
321                 , v3                            (DE_NULL)
322                 , provokingIndex        (-1)
323         {
324         }
325
326         LineAdjacency (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, VertexPacket* v3_, int provokingIndex_)
327                 : v0                            (v0_)
328                 , v1                            (v1_)
329                 , v2                            (v2_)
330                 , v3                            (v3_)
331                 , provokingIndex        (provokingIndex_)
332         {
333         }
334
335         VertexPacket* getProvokingVertex (void)
336         {
337                 switch (provokingIndex)
338                 {
339                         case 1: return v1;
340                         case 2: return v2;
341                         default:
342                                 DE_ASSERT(false);
343                                 return DE_NULL;
344                 }
345         }
346
347         VertexPacket*   v0;
348         VertexPacket*   v1;
349         VertexPacket*   v2;
350         VertexPacket*   v3;
351
352         int                             provokingIndex;
353 } DE_WARN_UNUSED_TYPE;
354
355 struct LinesAdjacency
356 {
357         template <typename Iterator>
358         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
359         {
360                 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
361
362                 for (size_t ndx = 0; ndx + 3 < numVertices; ndx += 4)
363                         *(outputIterator++) = LineAdjacency(vertices[ndx], vertices[ndx+1], vertices[ndx+2], vertices[ndx+3], provokingOffset);
364         }
365
366         static size_t getPrimitiveCount (size_t vertices)
367         {
368                 return vertices / 4;
369         }
370 } DE_WARN_UNUSED_TYPE;
371
372 struct LineStripAdjacency
373 {
374         template <typename Iterator>
375         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
376         {
377                 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (1) : (2);
378
379                 for (size_t ndx = 0; ndx + 3 < numVertices; ++ndx)
380                         *(outputIterator++) = LineAdjacency(vertices[ndx], vertices[ndx+1], vertices[ndx+2], vertices[ndx+3], provokingOffset);
381         }
382
383         static size_t getPrimitiveCount (size_t vertices)
384         {
385                 return (vertices < 4) ? (0) : (vertices - 3);
386         }
387 } DE_WARN_UNUSED_TYPE;
388
389 struct TriangleAdjacency
390 {
391         enum
392         {
393                 NUM_VERTICES = 6
394         };
395
396         TriangleAdjacency (void)
397                 : v0                            (DE_NULL)
398                 , v1                            (DE_NULL)
399                 , v2                            (DE_NULL)
400                 , v3                            (DE_NULL)
401                 , v4                            (DE_NULL)
402                 , v5                            (DE_NULL)
403                 , provokingIndex        (-1)
404         {
405         }
406
407         TriangleAdjacency (VertexPacket* v0_, VertexPacket* v1_, VertexPacket* v2_, VertexPacket* v3_, VertexPacket* v4_, VertexPacket* v5_, int provokingIndex_)
408                 : v0                            (v0_)
409                 , v1                            (v1_)
410                 , v2                            (v2_)
411                 , v3                            (v3_)
412                 , v4                            (v4_)
413                 , v5                            (v5_)
414                 , provokingIndex        (provokingIndex_)
415         {
416         }
417
418         VertexPacket* getProvokingVertex (void)
419         {
420                 switch (provokingIndex)
421                 {
422                         case 0: return v0;
423                         case 2: return v2;
424                         case 4: return v4;
425                         default:
426                                 DE_ASSERT(false);
427                                 return DE_NULL;
428                 }
429         }
430
431         VertexPacket*   v0;
432         VertexPacket*   v1;     //!< adjacent
433         VertexPacket*   v2;
434         VertexPacket*   v3;     //!< adjacent
435         VertexPacket*   v4;
436         VertexPacket*   v5;     //!< adjacent
437
438         int                             provokingIndex;
439 } DE_WARN_UNUSED_TYPE;
440
441 struct TrianglesAdjacency
442 {
443         template <typename Iterator>
444         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
445         {
446                 const int provokingOffset = (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4);
447
448                 for (size_t ndx = 0; ndx + 5 < numVertices; ndx += 6)
449                         *(outputIterator++) = TriangleAdjacency(vertices[ndx], vertices[ndx+1], vertices[ndx+2], vertices[ndx+3], vertices[ndx+4], vertices[ndx+5], provokingOffset);
450         }
451
452         static size_t getPrimitiveCount (size_t vertices)
453         {
454                 return vertices / 6;
455         }
456 } DE_WARN_UNUSED_TYPE;
457
458 struct TriangleStripAdjacency
459 {
460         template <typename Iterator>
461         static void exec (Iterator outputIterator, VertexPacket* const* vertices, size_t numVertices, rr::ProvokingVertex provokingConvention)
462         {
463                 if (numVertices < 6)
464                 {
465                 }
466                 else if (numVertices < 8)
467                 {
468                         *(outputIterator++) = TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[5], vertices[4], vertices[3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
469                 }
470                 else
471                 {
472                         const size_t primitiveCount = getPrimitiveCount(numVertices);
473                         size_t i;
474
475                         // first
476                         *(outputIterator++) = TriangleAdjacency(vertices[0], vertices[1], vertices[2], vertices[6], vertices[4], vertices[3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
477
478                         // middle
479                         for (i = 1; i + 1 < primitiveCount; ++i)
480                         {
481                                 // odd
482                                 if (i % 2 == 1)
483                                 {
484                                         *(outputIterator++) = TriangleAdjacency(vertices[2*i+2], vertices[2*i-2], vertices[2*i+0], vertices[2*i+3], vertices[2*i+4], vertices[2*i+6], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (2) : (4));
485                                 }
486                                 // even
487                                 else
488                                 {
489                                         *(outputIterator++) = TriangleAdjacency(vertices[2*i+0], vertices[2*i-2], vertices[2*i+2], vertices[2*i+6], vertices[2*i+4], vertices[2*i+3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
490                                 }
491                         }
492
493                         // last
494
495                         // odd
496                         if (i % 2 == 1)
497                                 *(outputIterator++) = TriangleAdjacency(vertices[2*i+2], vertices[2*i-2], vertices[2*i+0], vertices[2*i+3], vertices[2*i+4], vertices[2*i+5], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (2) : (4));
498                         // even
499                         else
500                                 *(outputIterator++) = TriangleAdjacency(vertices[2*i+0], vertices[2*i-2], vertices[2*i+2], vertices[2*i+5], vertices[2*i+4], vertices[2*i+3], (provokingConvention == rr::PROVOKINGVERTEX_FIRST) ? (0) : (4));
501                 }
502         }
503
504         static size_t getPrimitiveCount (size_t vertices)
505         {
506                 return (vertices < 6) ? 0 : ((vertices - 4) / 2);
507         }
508 } DE_WARN_UNUSED_TYPE;
509
510 } // pa
511 } // rr
512
513 #endif // _RRPRIMITIVEASSEMBLER_HPP