xref: /aosp_15_r20/external/deqp/framework/referencerenderer/rrRenderer.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Reference Renderer
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Reference renderer interface.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "rrRenderer.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuFloat.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "rrPrimitiveAssembler.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "rrFragmentOperations.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "rrRasterizer.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker #include <set>
34*35238bceSAndroid Build Coastguard Worker #include <limits>
35*35238bceSAndroid Build Coastguard Worker 
36*35238bceSAndroid Build Coastguard Worker namespace rr
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker namespace
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker typedef double ClipFloat; // floating point type used in clipping
42*35238bceSAndroid Build Coastguard Worker 
43*35238bceSAndroid Build Coastguard Worker typedef tcu::Vector<ClipFloat, 4> ClipVec4;
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker struct RasterizationInternalBuffers
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker     std::vector<FragmentPacket> fragmentPackets;
48*35238bceSAndroid Build Coastguard Worker     std::vector<GenericVec4> shaderOutputs;
49*35238bceSAndroid Build Coastguard Worker     std::vector<GenericVec4> shaderOutputsSrc1;
50*35238bceSAndroid Build Coastguard Worker     std::vector<Fragment> shadedFragments;
51*35238bceSAndroid Build Coastguard Worker     float *fragmentDepthBuffer;
52*35238bceSAndroid Build Coastguard Worker };
53*35238bceSAndroid Build Coastguard Worker 
readIndexArray(const IndexType type,const void * ptr,size_t ndx)54*35238bceSAndroid Build Coastguard Worker uint32_t readIndexArray(const IndexType type, const void *ptr, size_t ndx)
55*35238bceSAndroid Build Coastguard Worker {
56*35238bceSAndroid Build Coastguard Worker     switch (type)
57*35238bceSAndroid Build Coastguard Worker     {
58*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT8:
59*35238bceSAndroid Build Coastguard Worker         return ((const uint8_t *)ptr)[ndx];
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT16:
62*35238bceSAndroid Build Coastguard Worker     {
63*35238bceSAndroid Build Coastguard Worker         uint16_t retVal;
64*35238bceSAndroid Build Coastguard Worker         deMemcpy(&retVal, (const uint8_t *)ptr + ndx * sizeof(uint16_t), sizeof(uint16_t));
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker         return retVal;
67*35238bceSAndroid Build Coastguard Worker     }
68*35238bceSAndroid Build Coastguard Worker 
69*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT32:
70*35238bceSAndroid Build Coastguard Worker     {
71*35238bceSAndroid Build Coastguard Worker         uint32_t retVal;
72*35238bceSAndroid Build Coastguard Worker         deMemcpy(&retVal, (const uint8_t *)ptr + ndx * sizeof(uint32_t), sizeof(uint32_t));
73*35238bceSAndroid Build Coastguard Worker 
74*35238bceSAndroid Build Coastguard Worker         return retVal;
75*35238bceSAndroid Build Coastguard Worker     }
76*35238bceSAndroid Build Coastguard Worker 
77*35238bceSAndroid Build Coastguard Worker     default:
78*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
79*35238bceSAndroid Build Coastguard Worker         return 0;
80*35238bceSAndroid Build Coastguard Worker     }
81*35238bceSAndroid Build Coastguard Worker }
82*35238bceSAndroid Build Coastguard Worker 
getBufferSize(const rr::MultisampleConstPixelBufferAccess & multisampleBuffer)83*35238bceSAndroid Build Coastguard Worker tcu::IVec4 getBufferSize(const rr::MultisampleConstPixelBufferAccess &multisampleBuffer)
84*35238bceSAndroid Build Coastguard Worker {
85*35238bceSAndroid Build Coastguard Worker     return tcu::IVec4(0, 0, multisampleBuffer.raw().getHeight(), multisampleBuffer.raw().getDepth());
86*35238bceSAndroid Build Coastguard Worker }
87*35238bceSAndroid Build Coastguard Worker 
isEmpty(const rr::MultisampleConstPixelBufferAccess & access)88*35238bceSAndroid Build Coastguard Worker bool isEmpty(const rr::MultisampleConstPixelBufferAccess &access)
89*35238bceSAndroid Build Coastguard Worker {
90*35238bceSAndroid Build Coastguard Worker     return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
91*35238bceSAndroid Build Coastguard Worker }
92*35238bceSAndroid Build Coastguard Worker 
93*35238bceSAndroid Build Coastguard Worker struct DrawContext
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker     int primitiveID;
96*35238bceSAndroid Build Coastguard Worker 
DrawContextrr::__anon5c33bade0111::DrawContext97*35238bceSAndroid Build Coastguard Worker     DrawContext(void) : primitiveID(0)
98*35238bceSAndroid Build Coastguard Worker     {
99*35238bceSAndroid Build Coastguard Worker     }
100*35238bceSAndroid Build Coastguard Worker };
101*35238bceSAndroid Build Coastguard Worker 
102*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
103*35238bceSAndroid Build Coastguard Worker  * \brief Calculates intersection of two rects given as (left, bottom, width, height)
104*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
rectIntersection(const tcu::IVec4 & a,const tcu::IVec4 & b)105*35238bceSAndroid Build Coastguard Worker tcu::IVec4 rectIntersection(const tcu::IVec4 &a, const tcu::IVec4 &b)
106*35238bceSAndroid Build Coastguard Worker {
107*35238bceSAndroid Build Coastguard Worker     const tcu::IVec2 pos    = tcu::IVec2(de::max(a.x(), b.x()), de::max(a.y(), b.y()));
108*35238bceSAndroid Build Coastguard Worker     const tcu::IVec2 endPos = tcu::IVec2(de::min(a.x() + a.z(), b.x() + b.z()), de::min(a.y() + a.w(), b.y() + b.w()));
109*35238bceSAndroid Build Coastguard Worker 
110*35238bceSAndroid Build Coastguard Worker     return tcu::IVec4(pos.x(), pos.y(), endPos.x() - pos.x(), endPos.y() - pos.y());
111*35238bceSAndroid Build Coastguard Worker }
112*35238bceSAndroid Build Coastguard Worker 
convertPrimitiveToBaseType(std::vector<pa::Triangle> & output,std::vector<pa::Triangle> & input)113*35238bceSAndroid Build Coastguard Worker void convertPrimitiveToBaseType(std::vector<pa::Triangle> &output, std::vector<pa::Triangle> &input)
114*35238bceSAndroid Build Coastguard Worker {
115*35238bceSAndroid Build Coastguard Worker     std::swap(output, input);
116*35238bceSAndroid Build Coastguard Worker }
117*35238bceSAndroid Build Coastguard Worker 
convertPrimitiveToBaseType(std::vector<pa::Line> & output,std::vector<pa::Line> & input)118*35238bceSAndroid Build Coastguard Worker void convertPrimitiveToBaseType(std::vector<pa::Line> &output, std::vector<pa::Line> &input)
119*35238bceSAndroid Build Coastguard Worker {
120*35238bceSAndroid Build Coastguard Worker     std::swap(output, input);
121*35238bceSAndroid Build Coastguard Worker }
122*35238bceSAndroid Build Coastguard Worker 
convertPrimitiveToBaseType(std::vector<pa::Point> & output,std::vector<pa::Point> & input)123*35238bceSAndroid Build Coastguard Worker void convertPrimitiveToBaseType(std::vector<pa::Point> &output, std::vector<pa::Point> &input)
124*35238bceSAndroid Build Coastguard Worker {
125*35238bceSAndroid Build Coastguard Worker     std::swap(output, input);
126*35238bceSAndroid Build Coastguard Worker }
127*35238bceSAndroid Build Coastguard Worker 
convertPrimitiveToBaseType(std::vector<pa::Line> & output,std::vector<pa::LineAdjacency> & input)128*35238bceSAndroid Build Coastguard Worker void convertPrimitiveToBaseType(std::vector<pa::Line> &output, std::vector<pa::LineAdjacency> &input)
129*35238bceSAndroid Build Coastguard Worker {
130*35238bceSAndroid Build Coastguard Worker     output.resize(input.size());
131*35238bceSAndroid Build Coastguard Worker     for (size_t i = 0; i < input.size(); ++i)
132*35238bceSAndroid Build Coastguard Worker     {
133*35238bceSAndroid Build Coastguard Worker         const int adjacentProvokingVertex  = input[i].provokingIndex;
134*35238bceSAndroid Build Coastguard Worker         const int baseProvokingVertexIndex = adjacentProvokingVertex - 1;
135*35238bceSAndroid Build Coastguard Worker         output[i]                          = pa::Line(input[i].v1, input[i].v2, baseProvokingVertexIndex);
136*35238bceSAndroid Build Coastguard Worker     }
137*35238bceSAndroid Build Coastguard Worker }
138*35238bceSAndroid Build Coastguard Worker 
convertPrimitiveToBaseType(std::vector<pa::Triangle> & output,std::vector<pa::TriangleAdjacency> & input)139*35238bceSAndroid Build Coastguard Worker void convertPrimitiveToBaseType(std::vector<pa::Triangle> &output, std::vector<pa::TriangleAdjacency> &input)
140*35238bceSAndroid Build Coastguard Worker {
141*35238bceSAndroid Build Coastguard Worker     output.resize(input.size());
142*35238bceSAndroid Build Coastguard Worker     for (size_t i = 0; i < input.size(); ++i)
143*35238bceSAndroid Build Coastguard Worker     {
144*35238bceSAndroid Build Coastguard Worker         const int adjacentProvokingVertex  = input[i].provokingIndex;
145*35238bceSAndroid Build Coastguard Worker         const int baseProvokingVertexIndex = adjacentProvokingVertex / 2;
146*35238bceSAndroid Build Coastguard Worker         output[i] = pa::Triangle(input[i].v0, input[i].v2, input[i].v4, baseProvokingVertexIndex);
147*35238bceSAndroid Build Coastguard Worker     }
148*35238bceSAndroid Build Coastguard Worker }
149*35238bceSAndroid Build Coastguard Worker 
150*35238bceSAndroid Build Coastguard Worker namespace cliputil
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
154*35238bceSAndroid Build Coastguard Worker  * \brief Get clipped portion of the second endpoint
155*35238bceSAndroid Build Coastguard Worker  *
156*35238bceSAndroid Build Coastguard Worker  * Calculate the intersection of line segment v0-v1 and a given plane. Line
157*35238bceSAndroid Build Coastguard Worker  * segment is defined by a pair of one-dimensional homogeneous coordinates.
158*35238bceSAndroid Build Coastguard Worker  *
159*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
getSegmentVolumeEdgeClip(const ClipFloat v0,const ClipFloat w0,const ClipFloat v1,const ClipFloat w1,const ClipFloat plane)160*35238bceSAndroid Build Coastguard Worker ClipFloat getSegmentVolumeEdgeClip(const ClipFloat v0, const ClipFloat w0, const ClipFloat v1, const ClipFloat w1,
161*35238bceSAndroid Build Coastguard Worker                                    const ClipFloat plane)
162*35238bceSAndroid Build Coastguard Worker {
163*35238bceSAndroid Build Coastguard Worker     // The +epsilon avoids division by zero without causing a meaningful change in the calculation.
164*35238bceSAndroid Build Coastguard Worker     // Fixes divide by zero in builds when using the gcc toolset.
165*35238bceSAndroid Build Coastguard Worker     return (plane * w0 - v0) / ((v1 - v0) - plane * (w1 - w0) + std::numeric_limits<ClipFloat>::epsilon());
166*35238bceSAndroid Build Coastguard Worker }
167*35238bceSAndroid Build Coastguard Worker 
168*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
169*35238bceSAndroid Build Coastguard Worker  * \brief Get clipped portion of the endpoint
170*35238bceSAndroid Build Coastguard Worker  *
171*35238bceSAndroid Build Coastguard Worker  * How much (in [0-1] range) of a line segment v0-v1 would be clipped
172*35238bceSAndroid Build Coastguard Worker  * of the v0 end of the line segment by clipping.
173*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
getLineEndpointClipping(const ClipVec4 & v0,const ClipVec4 & v1)174*35238bceSAndroid Build Coastguard Worker ClipFloat getLineEndpointClipping(const ClipVec4 &v0, const ClipVec4 &v1)
175*35238bceSAndroid Build Coastguard Worker {
176*35238bceSAndroid Build Coastguard Worker     const ClipFloat clipVolumeSize = (ClipFloat)1.0;
177*35238bceSAndroid Build Coastguard Worker 
178*35238bceSAndroid Build Coastguard Worker     if (v0.z() > v0.w())
179*35238bceSAndroid Build Coastguard Worker     {
180*35238bceSAndroid Build Coastguard Worker         // Clip +Z
181*35238bceSAndroid Build Coastguard Worker         return getSegmentVolumeEdgeClip(v0.z(), v0.w(), v1.z(), v1.w(), clipVolumeSize);
182*35238bceSAndroid Build Coastguard Worker     }
183*35238bceSAndroid Build Coastguard Worker     else if (v0.z() < -v0.w())
184*35238bceSAndroid Build Coastguard Worker     {
185*35238bceSAndroid Build Coastguard Worker         // Clip -Z
186*35238bceSAndroid Build Coastguard Worker         return getSegmentVolumeEdgeClip(v0.z(), v0.w(), v1.z(), v1.w(), -clipVolumeSize);
187*35238bceSAndroid Build Coastguard Worker     }
188*35238bceSAndroid Build Coastguard Worker     else
189*35238bceSAndroid Build Coastguard Worker     {
190*35238bceSAndroid Build Coastguard Worker         // no clipping
191*35238bceSAndroid Build Coastguard Worker         return (ClipFloat)0.0;
192*35238bceSAndroid Build Coastguard Worker     }
193*35238bceSAndroid Build Coastguard Worker }
194*35238bceSAndroid Build Coastguard Worker 
vec4ToClipVec4(const tcu::Vec4 & v)195*35238bceSAndroid Build Coastguard Worker ClipVec4 vec4ToClipVec4(const tcu::Vec4 &v)
196*35238bceSAndroid Build Coastguard Worker {
197*35238bceSAndroid Build Coastguard Worker     return ClipVec4((ClipFloat)v.x(), (ClipFloat)v.y(), (ClipFloat)v.z(), (ClipFloat)v.w());
198*35238bceSAndroid Build Coastguard Worker }
199*35238bceSAndroid Build Coastguard Worker 
clipVec4ToVec4(const ClipVec4 & v)200*35238bceSAndroid Build Coastguard Worker tcu::Vec4 clipVec4ToVec4(const ClipVec4 &v)
201*35238bceSAndroid Build Coastguard Worker {
202*35238bceSAndroid Build Coastguard Worker     return tcu::Vec4((float)v.x(), (float)v.y(), (float)v.z(), (float)v.w());
203*35238bceSAndroid Build Coastguard Worker }
204*35238bceSAndroid Build Coastguard Worker 
205*35238bceSAndroid Build Coastguard Worker class ClipVolumePlane
206*35238bceSAndroid Build Coastguard Worker {
207*35238bceSAndroid Build Coastguard Worker public:
~ClipVolumePlane()208*35238bceSAndroid Build Coastguard Worker     virtual ~ClipVolumePlane()
209*35238bceSAndroid Build Coastguard Worker     {
210*35238bceSAndroid Build Coastguard Worker     }
211*35238bceSAndroid Build Coastguard Worker     virtual bool pointInClipVolume(const ClipVec4 &p) const                                 = 0;
212*35238bceSAndroid Build Coastguard Worker     virtual ClipFloat clipLineSegmentEnd(const ClipVec4 &v0, const ClipVec4 &v1) const      = 0;
213*35238bceSAndroid Build Coastguard Worker     virtual ClipVec4 getLineIntersectionPoint(const ClipVec4 &v0, const ClipVec4 &v1) const = 0;
214*35238bceSAndroid Build Coastguard Worker };
215*35238bceSAndroid Build Coastguard Worker 
216*35238bceSAndroid Build Coastguard Worker template <int Sign, int CompNdx>
217*35238bceSAndroid Build Coastguard Worker class ComponentPlane : public ClipVolumePlane
218*35238bceSAndroid Build Coastguard Worker {
219*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(Sign == +1 || Sign == -1);
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker public:
222*35238bceSAndroid Build Coastguard Worker     bool pointInClipVolume(const ClipVec4 &p) const;
223*35238bceSAndroid Build Coastguard Worker     ClipFloat clipLineSegmentEnd(const ClipVec4 &v0, const ClipVec4 &v1) const;
224*35238bceSAndroid Build Coastguard Worker     ClipVec4 getLineIntersectionPoint(const ClipVec4 &v0, const ClipVec4 &v1) const;
225*35238bceSAndroid Build Coastguard Worker };
226*35238bceSAndroid Build Coastguard Worker 
227*35238bceSAndroid Build Coastguard Worker template <int Sign, int CompNdx>
pointInClipVolume(const ClipVec4 & p) const228*35238bceSAndroid Build Coastguard Worker bool ComponentPlane<Sign, CompNdx>::pointInClipVolume(const ClipVec4 &p) const
229*35238bceSAndroid Build Coastguard Worker {
230*35238bceSAndroid Build Coastguard Worker     const ClipFloat clipVolumeSize = (ClipFloat)1.0;
231*35238bceSAndroid Build Coastguard Worker 
232*35238bceSAndroid Build Coastguard Worker     return (ClipFloat)(Sign * p[CompNdx]) <= clipVolumeSize * p.w();
233*35238bceSAndroid Build Coastguard Worker }
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker template <int Sign, int CompNdx>
clipLineSegmentEnd(const ClipVec4 & v0,const ClipVec4 & v1) const236*35238bceSAndroid Build Coastguard Worker ClipFloat ComponentPlane<Sign, CompNdx>::clipLineSegmentEnd(const ClipVec4 &v0, const ClipVec4 &v1) const
237*35238bceSAndroid Build Coastguard Worker {
238*35238bceSAndroid Build Coastguard Worker     const ClipFloat clipVolumeSize = (ClipFloat)1.0;
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker     return getSegmentVolumeEdgeClip(v0[CompNdx], v0.w(), v1[CompNdx], v1.w(), (ClipFloat)Sign * clipVolumeSize);
241*35238bceSAndroid Build Coastguard Worker }
242*35238bceSAndroid Build Coastguard Worker 
243*35238bceSAndroid Build Coastguard Worker template <int Sign, int CompNdx>
getLineIntersectionPoint(const ClipVec4 & v0,const ClipVec4 & v1) const244*35238bceSAndroid Build Coastguard Worker ClipVec4 ComponentPlane<Sign, CompNdx>::getLineIntersectionPoint(const ClipVec4 &v0, const ClipVec4 &v1) const
245*35238bceSAndroid Build Coastguard Worker {
246*35238bceSAndroid Build Coastguard Worker     // A point on line might be far away, causing clipping ratio (clipLineSegmentEnd) to become extremely close to 1.0
247*35238bceSAndroid Build Coastguard Worker     // even if the another point is not on the plane. Prevent clipping ratio from saturating by using points on line
248*35238bceSAndroid Build Coastguard Worker     // that are (nearly) on this and (nearly) on the opposite plane.
249*35238bceSAndroid Build Coastguard Worker 
250*35238bceSAndroid Build Coastguard Worker     const ClipVec4 clippedV0  = tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
251*35238bceSAndroid Build Coastguard Worker     const ClipVec4 clippedV1  = tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
252*35238bceSAndroid Build Coastguard Worker     const ClipFloat clipRatio = clipLineSegmentEnd(clippedV0, clippedV1);
253*35238bceSAndroid Build Coastguard Worker 
254*35238bceSAndroid Build Coastguard Worker     // Find intersection point of line from v0 to v1 and the current plane. Avoid ratios near 1.0
255*35238bceSAndroid Build Coastguard Worker     if (clipRatio <= (ClipFloat)0.5)
256*35238bceSAndroid Build Coastguard Worker         return tcu::mix(clippedV0, clippedV1, clipRatio);
257*35238bceSAndroid Build Coastguard Worker     else
258*35238bceSAndroid Build Coastguard Worker     {
259*35238bceSAndroid Build Coastguard Worker         const ClipFloat complementClipRatio = clipLineSegmentEnd(clippedV1, clippedV0);
260*35238bceSAndroid Build Coastguard Worker         return tcu::mix(clippedV1, clippedV0, complementClipRatio);
261*35238bceSAndroid Build Coastguard Worker     }
262*35238bceSAndroid Build Coastguard Worker }
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker struct TriangleVertex
265*35238bceSAndroid Build Coastguard Worker {
266*35238bceSAndroid Build Coastguard Worker     ClipVec4 position;
267*35238bceSAndroid Build Coastguard Worker     ClipFloat weight[3]; //!< barycentrics
268*35238bceSAndroid Build Coastguard Worker };
269*35238bceSAndroid Build Coastguard Worker 
270*35238bceSAndroid Build Coastguard Worker struct SubTriangle
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker     TriangleVertex vertices[3];
273*35238bceSAndroid Build Coastguard Worker };
274*35238bceSAndroid Build Coastguard Worker 
clipTriangleOneVertex(std::vector<TriangleVertex> & clippedEdges,const ClipVolumePlane & plane,const TriangleVertex & clipped,const TriangleVertex & v1,const TriangleVertex & v2)275*35238bceSAndroid Build Coastguard Worker void clipTriangleOneVertex(std::vector<TriangleVertex> &clippedEdges, const ClipVolumePlane &plane,
276*35238bceSAndroid Build Coastguard Worker                            const TriangleVertex &clipped, const TriangleVertex &v1, const TriangleVertex &v2)
277*35238bceSAndroid Build Coastguard Worker {
278*35238bceSAndroid Build Coastguard Worker     const ClipFloat degenerateLimit = (ClipFloat)1.0;
279*35238bceSAndroid Build Coastguard Worker 
280*35238bceSAndroid Build Coastguard Worker     // calc clip pos
281*35238bceSAndroid Build Coastguard Worker     TriangleVertex mid1;
282*35238bceSAndroid Build Coastguard Worker     TriangleVertex mid2;
283*35238bceSAndroid Build Coastguard Worker     bool outputDegenerate = false;
284*35238bceSAndroid Build Coastguard Worker 
285*35238bceSAndroid Build Coastguard Worker     {
286*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &inside  = v1;
287*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &outside = clipped;
288*35238bceSAndroid Build Coastguard Worker         TriangleVertex &middle        = mid1;
289*35238bceSAndroid Build Coastguard Worker 
290*35238bceSAndroid Build Coastguard Worker         const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
291*35238bceSAndroid Build Coastguard Worker 
292*35238bceSAndroid Build Coastguard Worker         if (hitDist >= degenerateLimit)
293*35238bceSAndroid Build Coastguard Worker         {
294*35238bceSAndroid Build Coastguard Worker             // do not generate degenerate triangles
295*35238bceSAndroid Build Coastguard Worker             outputDegenerate = true;
296*35238bceSAndroid Build Coastguard Worker         }
297*35238bceSAndroid Build Coastguard Worker         else
298*35238bceSAndroid Build Coastguard Worker         {
299*35238bceSAndroid Build Coastguard Worker             const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
300*35238bceSAndroid Build Coastguard Worker             const ClipVec4 anotherPointOnLine    = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker             middle.position  = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
303*35238bceSAndroid Build Coastguard Worker             middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
304*35238bceSAndroid Build Coastguard Worker             middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
305*35238bceSAndroid Build Coastguard Worker             middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
306*35238bceSAndroid Build Coastguard Worker         }
307*35238bceSAndroid Build Coastguard Worker     }
308*35238bceSAndroid Build Coastguard Worker 
309*35238bceSAndroid Build Coastguard Worker     {
310*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &inside  = v2;
311*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &outside = clipped;
312*35238bceSAndroid Build Coastguard Worker         TriangleVertex &middle        = mid2;
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker         const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
315*35238bceSAndroid Build Coastguard Worker 
316*35238bceSAndroid Build Coastguard Worker         if (hitDist >= degenerateLimit)
317*35238bceSAndroid Build Coastguard Worker         {
318*35238bceSAndroid Build Coastguard Worker             // do not generate degenerate triangles
319*35238bceSAndroid Build Coastguard Worker             outputDegenerate = true;
320*35238bceSAndroid Build Coastguard Worker         }
321*35238bceSAndroid Build Coastguard Worker         else
322*35238bceSAndroid Build Coastguard Worker         {
323*35238bceSAndroid Build Coastguard Worker             const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
324*35238bceSAndroid Build Coastguard Worker             const ClipVec4 anotherPointOnLine    = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
325*35238bceSAndroid Build Coastguard Worker 
326*35238bceSAndroid Build Coastguard Worker             middle.position  = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
327*35238bceSAndroid Build Coastguard Worker             middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
328*35238bceSAndroid Build Coastguard Worker             middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
329*35238bceSAndroid Build Coastguard Worker             middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
330*35238bceSAndroid Build Coastguard Worker         }
331*35238bceSAndroid Build Coastguard Worker     }
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker     if (!outputDegenerate)
334*35238bceSAndroid Build Coastguard Worker     {
335*35238bceSAndroid Build Coastguard Worker         // gen quad (v1) -> mid1 -> mid2 -> (v2)
336*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v1);
337*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(mid1);
338*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(mid2);
339*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v2);
340*35238bceSAndroid Build Coastguard Worker     }
341*35238bceSAndroid Build Coastguard Worker     else
342*35238bceSAndroid Build Coastguard Worker     {
343*35238bceSAndroid Build Coastguard Worker         // don't modify
344*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v1);
345*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(clipped);
346*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v2);
347*35238bceSAndroid Build Coastguard Worker     }
348*35238bceSAndroid Build Coastguard Worker }
349*35238bceSAndroid Build Coastguard Worker 
clipTriangleTwoVertices(std::vector<TriangleVertex> & clippedEdges,const ClipVolumePlane & plane,const TriangleVertex & v0,const TriangleVertex & clipped1,const TriangleVertex & clipped2)350*35238bceSAndroid Build Coastguard Worker void clipTriangleTwoVertices(std::vector<TriangleVertex> &clippedEdges, const ClipVolumePlane &plane,
351*35238bceSAndroid Build Coastguard Worker                              const TriangleVertex &v0, const TriangleVertex &clipped1, const TriangleVertex &clipped2)
352*35238bceSAndroid Build Coastguard Worker {
353*35238bceSAndroid Build Coastguard Worker     const ClipFloat unclippableLimit = (ClipFloat)1.0;
354*35238bceSAndroid Build Coastguard Worker 
355*35238bceSAndroid Build Coastguard Worker     // calc clip pos
356*35238bceSAndroid Build Coastguard Worker     TriangleVertex mid1;
357*35238bceSAndroid Build Coastguard Worker     TriangleVertex mid2;
358*35238bceSAndroid Build Coastguard Worker     bool unclippableVertex1 = false;
359*35238bceSAndroid Build Coastguard Worker     bool unclippableVertex2 = false;
360*35238bceSAndroid Build Coastguard Worker 
361*35238bceSAndroid Build Coastguard Worker     {
362*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &inside  = v0;
363*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &outside = clipped1;
364*35238bceSAndroid Build Coastguard Worker         TriangleVertex &middle        = mid1;
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker         const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker         if (hitDist >= unclippableLimit)
369*35238bceSAndroid Build Coastguard Worker         {
370*35238bceSAndroid Build Coastguard Worker             // this edge cannot be clipped because the edge is really close to the volume boundary
371*35238bceSAndroid Build Coastguard Worker             unclippableVertex1 = true;
372*35238bceSAndroid Build Coastguard Worker         }
373*35238bceSAndroid Build Coastguard Worker         else
374*35238bceSAndroid Build Coastguard Worker         {
375*35238bceSAndroid Build Coastguard Worker             const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
376*35238bceSAndroid Build Coastguard Worker             const ClipVec4 anotherPointOnLine    = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
377*35238bceSAndroid Build Coastguard Worker 
378*35238bceSAndroid Build Coastguard Worker             middle.position  = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
379*35238bceSAndroid Build Coastguard Worker             middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
380*35238bceSAndroid Build Coastguard Worker             middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
381*35238bceSAndroid Build Coastguard Worker             middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
382*35238bceSAndroid Build Coastguard Worker         }
383*35238bceSAndroid Build Coastguard Worker     }
384*35238bceSAndroid Build Coastguard Worker 
385*35238bceSAndroid Build Coastguard Worker     {
386*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &inside  = v0;
387*35238bceSAndroid Build Coastguard Worker         const TriangleVertex &outside = clipped2;
388*35238bceSAndroid Build Coastguard Worker         TriangleVertex &middle        = mid2;
389*35238bceSAndroid Build Coastguard Worker 
390*35238bceSAndroid Build Coastguard Worker         const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
391*35238bceSAndroid Build Coastguard Worker 
392*35238bceSAndroid Build Coastguard Worker         if (hitDist >= unclippableLimit)
393*35238bceSAndroid Build Coastguard Worker         {
394*35238bceSAndroid Build Coastguard Worker             // this edge cannot be clipped because the edge is really close to the volume boundary
395*35238bceSAndroid Build Coastguard Worker             unclippableVertex2 = true;
396*35238bceSAndroid Build Coastguard Worker         }
397*35238bceSAndroid Build Coastguard Worker         else
398*35238bceSAndroid Build Coastguard Worker         {
399*35238bceSAndroid Build Coastguard Worker             const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
400*35238bceSAndroid Build Coastguard Worker             const ClipVec4 anotherPointOnLine    = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
401*35238bceSAndroid Build Coastguard Worker 
402*35238bceSAndroid Build Coastguard Worker             middle.position  = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
403*35238bceSAndroid Build Coastguard Worker             middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
404*35238bceSAndroid Build Coastguard Worker             middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
405*35238bceSAndroid Build Coastguard Worker             middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
406*35238bceSAndroid Build Coastguard Worker         }
407*35238bceSAndroid Build Coastguard Worker     }
408*35238bceSAndroid Build Coastguard Worker 
409*35238bceSAndroid Build Coastguard Worker     if (!unclippableVertex1 && !unclippableVertex2)
410*35238bceSAndroid Build Coastguard Worker     {
411*35238bceSAndroid Build Coastguard Worker         // gen triangle (v0) -> mid1 -> mid2
412*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v0);
413*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(mid1);
414*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(mid2);
415*35238bceSAndroid Build Coastguard Worker     }
416*35238bceSAndroid Build Coastguard Worker     else if (!unclippableVertex1 && unclippableVertex2)
417*35238bceSAndroid Build Coastguard Worker     {
418*35238bceSAndroid Build Coastguard Worker         // clip just vertex 1
419*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v0);
420*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(mid1);
421*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(clipped2);
422*35238bceSAndroid Build Coastguard Worker     }
423*35238bceSAndroid Build Coastguard Worker     else if (unclippableVertex1 && !unclippableVertex2)
424*35238bceSAndroid Build Coastguard Worker     {
425*35238bceSAndroid Build Coastguard Worker         // clip just vertex 2
426*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v0);
427*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(clipped1);
428*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(mid2);
429*35238bceSAndroid Build Coastguard Worker     }
430*35238bceSAndroid Build Coastguard Worker     else
431*35238bceSAndroid Build Coastguard Worker     {
432*35238bceSAndroid Build Coastguard Worker         // don't modify
433*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(v0);
434*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(clipped1);
435*35238bceSAndroid Build Coastguard Worker         clippedEdges.push_back(clipped2);
436*35238bceSAndroid Build Coastguard Worker     }
437*35238bceSAndroid Build Coastguard Worker }
438*35238bceSAndroid Build Coastguard Worker 
clipTriangleToPlane(std::vector<TriangleVertex> & clippedEdges,const TriangleVertex * vertices,const ClipVolumePlane & plane)439*35238bceSAndroid Build Coastguard Worker void clipTriangleToPlane(std::vector<TriangleVertex> &clippedEdges, const TriangleVertex *vertices,
440*35238bceSAndroid Build Coastguard Worker                          const ClipVolumePlane &plane)
441*35238bceSAndroid Build Coastguard Worker {
442*35238bceSAndroid Build Coastguard Worker     const bool v0Clipped = !plane.pointInClipVolume(vertices[0].position);
443*35238bceSAndroid Build Coastguard Worker     const bool v1Clipped = !plane.pointInClipVolume(vertices[1].position);
444*35238bceSAndroid Build Coastguard Worker     const bool v2Clipped = !plane.pointInClipVolume(vertices[2].position);
445*35238bceSAndroid Build Coastguard Worker     const int clipCount  = ((v0Clipped) ? (1) : (0)) + ((v1Clipped) ? (1) : (0)) + ((v2Clipped) ? (1) : (0));
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker     if (clipCount == 0)
448*35238bceSAndroid Build Coastguard Worker     {
449*35238bceSAndroid Build Coastguard Worker         // pass
450*35238bceSAndroid Build Coastguard Worker         clippedEdges.insert(clippedEdges.begin(), vertices, vertices + 3);
451*35238bceSAndroid Build Coastguard Worker     }
452*35238bceSAndroid Build Coastguard Worker     else if (clipCount == 1)
453*35238bceSAndroid Build Coastguard Worker     {
454*35238bceSAndroid Build Coastguard Worker         // clip one vertex
455*35238bceSAndroid Build Coastguard Worker         if (v0Clipped)
456*35238bceSAndroid Build Coastguard Worker             clipTriangleOneVertex(clippedEdges, plane, vertices[0], vertices[1], vertices[2]);
457*35238bceSAndroid Build Coastguard Worker         else if (v1Clipped)
458*35238bceSAndroid Build Coastguard Worker             clipTriangleOneVertex(clippedEdges, plane, vertices[1], vertices[2], vertices[0]);
459*35238bceSAndroid Build Coastguard Worker         else
460*35238bceSAndroid Build Coastguard Worker             clipTriangleOneVertex(clippedEdges, plane, vertices[2], vertices[0], vertices[1]);
461*35238bceSAndroid Build Coastguard Worker     }
462*35238bceSAndroid Build Coastguard Worker     else if (clipCount == 2)
463*35238bceSAndroid Build Coastguard Worker     {
464*35238bceSAndroid Build Coastguard Worker         // clip two vertices
465*35238bceSAndroid Build Coastguard Worker         if (!v0Clipped)
466*35238bceSAndroid Build Coastguard Worker             clipTriangleTwoVertices(clippedEdges, plane, vertices[0], vertices[1], vertices[2]);
467*35238bceSAndroid Build Coastguard Worker         else if (!v1Clipped)
468*35238bceSAndroid Build Coastguard Worker             clipTriangleTwoVertices(clippedEdges, plane, vertices[1], vertices[2], vertices[0]);
469*35238bceSAndroid Build Coastguard Worker         else
470*35238bceSAndroid Build Coastguard Worker             clipTriangleTwoVertices(clippedEdges, plane, vertices[2], vertices[0], vertices[1]);
471*35238bceSAndroid Build Coastguard Worker     }
472*35238bceSAndroid Build Coastguard Worker     else if (clipCount == 3)
473*35238bceSAndroid Build Coastguard Worker     {
474*35238bceSAndroid Build Coastguard Worker         // discard
475*35238bceSAndroid Build Coastguard Worker     }
476*35238bceSAndroid Build Coastguard Worker     else
477*35238bceSAndroid Build Coastguard Worker     {
478*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
479*35238bceSAndroid Build Coastguard Worker     }
480*35238bceSAndroid Build Coastguard Worker }
481*35238bceSAndroid Build Coastguard Worker 
482*35238bceSAndroid Build Coastguard Worker } // namespace cliputil
483*35238bceSAndroid Build Coastguard Worker 
to2DCartesian(const tcu::Vec4 & p)484*35238bceSAndroid Build Coastguard Worker tcu::Vec2 to2DCartesian(const tcu::Vec4 &p)
485*35238bceSAndroid Build Coastguard Worker {
486*35238bceSAndroid Build Coastguard Worker     return tcu::Vec2(p.x(), p.y()) / p.w();
487*35238bceSAndroid Build Coastguard Worker }
488*35238bceSAndroid Build Coastguard Worker 
cross2D(const tcu::Vec2 & a,const tcu::Vec2 & b)489*35238bceSAndroid Build Coastguard Worker float cross2D(const tcu::Vec2 &a, const tcu::Vec2 &b)
490*35238bceSAndroid Build Coastguard Worker {
491*35238bceSAndroid Build Coastguard Worker     return tcu::cross(tcu::Vec3(a.x(), a.y(), 0.0f), tcu::Vec3(b.x(), b.y(), 0.0f)).z();
492*35238bceSAndroid Build Coastguard Worker }
493*35238bceSAndroid Build Coastguard Worker 
flatshadePrimitiveVertices(pa::Triangle & target,size_t outputNdx)494*35238bceSAndroid Build Coastguard Worker void flatshadePrimitiveVertices(pa::Triangle &target, size_t outputNdx)
495*35238bceSAndroid Build Coastguard Worker {
496*35238bceSAndroid Build Coastguard Worker     const rr::GenericVec4 flatValue = target.getProvokingVertex()->outputs[outputNdx];
497*35238bceSAndroid Build Coastguard Worker     target.v0->outputs[outputNdx]   = flatValue;
498*35238bceSAndroid Build Coastguard Worker     target.v1->outputs[outputNdx]   = flatValue;
499*35238bceSAndroid Build Coastguard Worker     target.v2->outputs[outputNdx]   = flatValue;
500*35238bceSAndroid Build Coastguard Worker }
501*35238bceSAndroid Build Coastguard Worker 
flatshadePrimitiveVertices(pa::Line & target,size_t outputNdx)502*35238bceSAndroid Build Coastguard Worker void flatshadePrimitiveVertices(pa::Line &target, size_t outputNdx)
503*35238bceSAndroid Build Coastguard Worker {
504*35238bceSAndroid Build Coastguard Worker     const rr::GenericVec4 flatValue = target.getProvokingVertex()->outputs[outputNdx];
505*35238bceSAndroid Build Coastguard Worker     target.v0->outputs[outputNdx]   = flatValue;
506*35238bceSAndroid Build Coastguard Worker     target.v1->outputs[outputNdx]   = flatValue;
507*35238bceSAndroid Build Coastguard Worker }
508*35238bceSAndroid Build Coastguard Worker 
flatshadePrimitiveVertices(pa::Point & target,size_t outputNdx)509*35238bceSAndroid Build Coastguard Worker void flatshadePrimitiveVertices(pa::Point &target, size_t outputNdx)
510*35238bceSAndroid Build Coastguard Worker {
511*35238bceSAndroid Build Coastguard Worker     DE_UNREF(target);
512*35238bceSAndroid Build Coastguard Worker     DE_UNREF(outputNdx);
513*35238bceSAndroid Build Coastguard Worker }
514*35238bceSAndroid Build Coastguard Worker 
515*35238bceSAndroid Build Coastguard Worker template <typename ContainerType>
flatshadeVertices(const Program & program,ContainerType & list)516*35238bceSAndroid Build Coastguard Worker void flatshadeVertices(const Program &program, ContainerType &list)
517*35238bceSAndroid Build Coastguard Worker {
518*35238bceSAndroid Build Coastguard Worker     // flatshade
519*35238bceSAndroid Build Coastguard Worker     const std::vector<rr::VertexVaryingInfo> &fragInputs =
520*35238bceSAndroid Build Coastguard Worker         (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
521*35238bceSAndroid Build Coastguard Worker 
522*35238bceSAndroid Build Coastguard Worker     for (size_t inputNdx = 0; inputNdx < fragInputs.size(); ++inputNdx)
523*35238bceSAndroid Build Coastguard Worker         if (fragInputs[inputNdx].flatshade)
524*35238bceSAndroid Build Coastguard Worker             for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
525*35238bceSAndroid Build Coastguard Worker                 flatshadePrimitiveVertices(*it, inputNdx);
526*35238bceSAndroid Build Coastguard Worker }
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
529*35238bceSAndroid Build Coastguard Worker  * Clip triangles to the clip volume.
530*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
clipPrimitives(std::vector<pa::Triangle> & list,const Program & program,bool clipWithZPlanes,VertexPacketAllocator & vpalloc)531*35238bceSAndroid Build Coastguard Worker void clipPrimitives(std::vector<pa::Triangle> &list, const Program &program, bool clipWithZPlanes,
532*35238bceSAndroid Build Coastguard Worker                     VertexPacketAllocator &vpalloc)
533*35238bceSAndroid Build Coastguard Worker {
534*35238bceSAndroid Build Coastguard Worker     using namespace cliputil;
535*35238bceSAndroid Build Coastguard Worker 
536*35238bceSAndroid Build Coastguard Worker     cliputil::ComponentPlane<+1, 0> clipPosX;
537*35238bceSAndroid Build Coastguard Worker     cliputil::ComponentPlane<-1, 0> clipNegX;
538*35238bceSAndroid Build Coastguard Worker     cliputil::ComponentPlane<+1, 1> clipPosY;
539*35238bceSAndroid Build Coastguard Worker     cliputil::ComponentPlane<-1, 1> clipNegY;
540*35238bceSAndroid Build Coastguard Worker     cliputil::ComponentPlane<+1, 2> clipPosZ;
541*35238bceSAndroid Build Coastguard Worker     cliputil::ComponentPlane<-1, 2> clipNegZ;
542*35238bceSAndroid Build Coastguard Worker 
543*35238bceSAndroid Build Coastguard Worker     const std::vector<rr::VertexVaryingInfo> &fragInputs =
544*35238bceSAndroid Build Coastguard Worker         (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
545*35238bceSAndroid Build Coastguard Worker     const ClipVolumePlane *planes[] = {&clipPosX, &clipNegX, &clipPosY, &clipNegY, &clipPosZ, &clipNegZ};
546*35238bceSAndroid Build Coastguard Worker     const int numPlanes             = (clipWithZPlanes) ? (6) : (4);
547*35238bceSAndroid Build Coastguard Worker 
548*35238bceSAndroid Build Coastguard Worker     std::vector<pa::Triangle> outputTriangles;
549*35238bceSAndroid Build Coastguard Worker 
550*35238bceSAndroid Build Coastguard Worker     for (int inputTriangleNdx = 0; inputTriangleNdx < (int)list.size(); ++inputTriangleNdx)
551*35238bceSAndroid Build Coastguard Worker     {
552*35238bceSAndroid Build Coastguard Worker         bool clippedByPlane[6];
553*35238bceSAndroid Build Coastguard Worker 
554*35238bceSAndroid Build Coastguard Worker         // Needs clipping?
555*35238bceSAndroid Build Coastguard Worker         {
556*35238bceSAndroid Build Coastguard Worker             bool discardPrimitive  = false;
557*35238bceSAndroid Build Coastguard Worker             bool fullyInClipVolume = true;
558*35238bceSAndroid Build Coastguard Worker 
559*35238bceSAndroid Build Coastguard Worker             for (int planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
560*35238bceSAndroid Build Coastguard Worker             {
561*35238bceSAndroid Build Coastguard Worker                 const ClipVolumePlane *plane = planes[planeNdx];
562*35238bceSAndroid Build Coastguard Worker                 const bool v0InsidePlane =
563*35238bceSAndroid Build Coastguard Worker                     plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v0->position));
564*35238bceSAndroid Build Coastguard Worker                 const bool v1InsidePlane =
565*35238bceSAndroid Build Coastguard Worker                     plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v1->position));
566*35238bceSAndroid Build Coastguard Worker                 const bool v2InsidePlane =
567*35238bceSAndroid Build Coastguard Worker                     plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v2->position));
568*35238bceSAndroid Build Coastguard Worker 
569*35238bceSAndroid Build Coastguard Worker                 // Fully outside
570*35238bceSAndroid Build Coastguard Worker                 if (!v0InsidePlane && !v1InsidePlane && !v2InsidePlane)
571*35238bceSAndroid Build Coastguard Worker                 {
572*35238bceSAndroid Build Coastguard Worker                     discardPrimitive = true;
573*35238bceSAndroid Build Coastguard Worker                     break;
574*35238bceSAndroid Build Coastguard Worker                 }
575*35238bceSAndroid Build Coastguard Worker                 // Partially outside
576*35238bceSAndroid Build Coastguard Worker                 else if (!v0InsidePlane || !v1InsidePlane || !v2InsidePlane)
577*35238bceSAndroid Build Coastguard Worker                 {
578*35238bceSAndroid Build Coastguard Worker                     clippedByPlane[planeNdx] = true;
579*35238bceSAndroid Build Coastguard Worker                     fullyInClipVolume        = false;
580*35238bceSAndroid Build Coastguard Worker                 }
581*35238bceSAndroid Build Coastguard Worker                 // Fully inside
582*35238bceSAndroid Build Coastguard Worker                 else
583*35238bceSAndroid Build Coastguard Worker                     clippedByPlane[planeNdx] = false;
584*35238bceSAndroid Build Coastguard Worker             }
585*35238bceSAndroid Build Coastguard Worker 
586*35238bceSAndroid Build Coastguard Worker             if (discardPrimitive)
587*35238bceSAndroid Build Coastguard Worker                 continue;
588*35238bceSAndroid Build Coastguard Worker 
589*35238bceSAndroid Build Coastguard Worker             if (fullyInClipVolume)
590*35238bceSAndroid Build Coastguard Worker             {
591*35238bceSAndroid Build Coastguard Worker                 outputTriangles.push_back(list[inputTriangleNdx]);
592*35238bceSAndroid Build Coastguard Worker                 continue;
593*35238bceSAndroid Build Coastguard Worker             }
594*35238bceSAndroid Build Coastguard Worker         }
595*35238bceSAndroid Build Coastguard Worker 
596*35238bceSAndroid Build Coastguard Worker         // Clip
597*35238bceSAndroid Build Coastguard Worker         {
598*35238bceSAndroid Build Coastguard Worker             std::vector<SubTriangle> subTriangles(1);
599*35238bceSAndroid Build Coastguard Worker             SubTriangle &initialTri = subTriangles[0];
600*35238bceSAndroid Build Coastguard Worker 
601*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[0].position  = vec4ToClipVec4(list[inputTriangleNdx].v0->position);
602*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[0].weight[0] = (ClipFloat)1.0;
603*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[0].weight[1] = (ClipFloat)0.0;
604*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[0].weight[2] = (ClipFloat)0.0;
605*35238bceSAndroid Build Coastguard Worker 
606*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[1].position  = vec4ToClipVec4(list[inputTriangleNdx].v1->position);
607*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[1].weight[0] = (ClipFloat)0.0;
608*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[1].weight[1] = (ClipFloat)1.0;
609*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[1].weight[2] = (ClipFloat)0.0;
610*35238bceSAndroid Build Coastguard Worker 
611*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[2].position  = vec4ToClipVec4(list[inputTriangleNdx].v2->position);
612*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[2].weight[0] = (ClipFloat)0.0;
613*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[2].weight[1] = (ClipFloat)0.0;
614*35238bceSAndroid Build Coastguard Worker             initialTri.vertices[2].weight[2] = (ClipFloat)1.0;
615*35238bceSAndroid Build Coastguard Worker 
616*35238bceSAndroid Build Coastguard Worker             // Clip all subtriangles to all relevant planes
617*35238bceSAndroid Build Coastguard Worker             for (int planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
618*35238bceSAndroid Build Coastguard Worker             {
619*35238bceSAndroid Build Coastguard Worker                 std::vector<SubTriangle> nextPhaseSubTriangles;
620*35238bceSAndroid Build Coastguard Worker 
621*35238bceSAndroid Build Coastguard Worker                 if (!clippedByPlane[planeNdx])
622*35238bceSAndroid Build Coastguard Worker                     continue;
623*35238bceSAndroid Build Coastguard Worker 
624*35238bceSAndroid Build Coastguard Worker                 for (int subTriangleNdx = 0; subTriangleNdx < (int)subTriangles.size(); ++subTriangleNdx)
625*35238bceSAndroid Build Coastguard Worker                 {
626*35238bceSAndroid Build Coastguard Worker                     std::vector<TriangleVertex> convexPrimitive;
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker                     // Clip triangle and form a convex n-gon ( n c {3, 4} )
629*35238bceSAndroid Build Coastguard Worker                     clipTriangleToPlane(convexPrimitive, subTriangles[subTriangleNdx].vertices, *planes[planeNdx]);
630*35238bceSAndroid Build Coastguard Worker 
631*35238bceSAndroid Build Coastguard Worker                     // Subtriangle completely discarded
632*35238bceSAndroid Build Coastguard Worker                     if (convexPrimitive.empty())
633*35238bceSAndroid Build Coastguard Worker                         continue;
634*35238bceSAndroid Build Coastguard Worker 
635*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(convexPrimitive.size() == 3 || convexPrimitive.size() == 4);
636*35238bceSAndroid Build Coastguard Worker 
637*35238bceSAndroid Build Coastguard Worker                     //Triangulate planar convex n-gon
638*35238bceSAndroid Build Coastguard Worker                     {
639*35238bceSAndroid Build Coastguard Worker                         TriangleVertex &v0 = convexPrimitive[0];
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker                         for (int subsubTriangleNdx = 1; subsubTriangleNdx + 1 < (int)convexPrimitive.size();
642*35238bceSAndroid Build Coastguard Worker                              ++subsubTriangleNdx)
643*35238bceSAndroid Build Coastguard Worker                         {
644*35238bceSAndroid Build Coastguard Worker                             const float degenerateEpsilon = 1.0e-6f;
645*35238bceSAndroid Build Coastguard Worker                             const TriangleVertex &v1      = convexPrimitive[subsubTriangleNdx];
646*35238bceSAndroid Build Coastguard Worker                             const TriangleVertex &v2      = convexPrimitive[subsubTriangleNdx + 1];
647*35238bceSAndroid Build Coastguard Worker                             const float visibleArea       = de::abs(cross2D(to2DCartesian(clipVec4ToVec4(v1.position)) -
648*35238bceSAndroid Build Coastguard Worker                                                                                 to2DCartesian(clipVec4ToVec4(v0.position)),
649*35238bceSAndroid Build Coastguard Worker                                                                             to2DCartesian(clipVec4ToVec4(v2.position)) -
650*35238bceSAndroid Build Coastguard Worker                                                                                 to2DCartesian(clipVec4ToVec4(v0.position))));
651*35238bceSAndroid Build Coastguard Worker 
652*35238bceSAndroid Build Coastguard Worker                             // has surface area (is not a degenerate)
653*35238bceSAndroid Build Coastguard Worker                             if (visibleArea >= degenerateEpsilon)
654*35238bceSAndroid Build Coastguard Worker                             {
655*35238bceSAndroid Build Coastguard Worker                                 SubTriangle subsubTriangle;
656*35238bceSAndroid Build Coastguard Worker 
657*35238bceSAndroid Build Coastguard Worker                                 subsubTriangle.vertices[0] = v0;
658*35238bceSAndroid Build Coastguard Worker                                 subsubTriangle.vertices[1] = v1;
659*35238bceSAndroid Build Coastguard Worker                                 subsubTriangle.vertices[2] = v2;
660*35238bceSAndroid Build Coastguard Worker 
661*35238bceSAndroid Build Coastguard Worker                                 nextPhaseSubTriangles.push_back(subsubTriangle);
662*35238bceSAndroid Build Coastguard Worker                             }
663*35238bceSAndroid Build Coastguard Worker                         }
664*35238bceSAndroid Build Coastguard Worker                     }
665*35238bceSAndroid Build Coastguard Worker                 }
666*35238bceSAndroid Build Coastguard Worker 
667*35238bceSAndroid Build Coastguard Worker                 subTriangles.swap(nextPhaseSubTriangles);
668*35238bceSAndroid Build Coastguard Worker             }
669*35238bceSAndroid Build Coastguard Worker 
670*35238bceSAndroid Build Coastguard Worker             // Rebuild pa::Triangles from subtriangles
671*35238bceSAndroid Build Coastguard Worker             for (int subTriangleNdx = 0; subTriangleNdx < (int)subTriangles.size(); ++subTriangleNdx)
672*35238bceSAndroid Build Coastguard Worker             {
673*35238bceSAndroid Build Coastguard Worker                 VertexPacket *p0 = vpalloc.alloc();
674*35238bceSAndroid Build Coastguard Worker                 VertexPacket *p1 = vpalloc.alloc();
675*35238bceSAndroid Build Coastguard Worker                 VertexPacket *p2 = vpalloc.alloc();
676*35238bceSAndroid Build Coastguard Worker                 pa::Triangle ngonFragment(p0, p1, p2, -1);
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker                 p0->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[0].position);
679*35238bceSAndroid Build Coastguard Worker                 p1->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[1].position);
680*35238bceSAndroid Build Coastguard Worker                 p2->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[2].position);
681*35238bceSAndroid Build Coastguard Worker 
682*35238bceSAndroid Build Coastguard Worker                 for (size_t outputNdx = 0; outputNdx < fragInputs.size(); ++outputNdx)
683*35238bceSAndroid Build Coastguard Worker                 {
684*35238bceSAndroid Build Coastguard Worker                     if (fragInputs[outputNdx].type == GENERICVECTYPE_FLOAT)
685*35238bceSAndroid Build Coastguard Worker                     {
686*35238bceSAndroid Build Coastguard Worker                         const tcu::Vec4 out0 = list[inputTriangleNdx].v0->outputs[outputNdx].get<float>();
687*35238bceSAndroid Build Coastguard Worker                         const tcu::Vec4 out1 = list[inputTriangleNdx].v1->outputs[outputNdx].get<float>();
688*35238bceSAndroid Build Coastguard Worker                         const tcu::Vec4 out2 = list[inputTriangleNdx].v2->outputs[outputNdx].get<float>();
689*35238bceSAndroid Build Coastguard Worker 
690*35238bceSAndroid Build Coastguard Worker                         p0->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[0].weight[0] * out0 +
691*35238bceSAndroid Build Coastguard Worker                                                  (float)subTriangles[subTriangleNdx].vertices[0].weight[1] * out1 +
692*35238bceSAndroid Build Coastguard Worker                                                  (float)subTriangles[subTriangleNdx].vertices[0].weight[2] * out2;
693*35238bceSAndroid Build Coastguard Worker 
694*35238bceSAndroid Build Coastguard Worker                         p1->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[1].weight[0] * out0 +
695*35238bceSAndroid Build Coastguard Worker                                                  (float)subTriangles[subTriangleNdx].vertices[1].weight[1] * out1 +
696*35238bceSAndroid Build Coastguard Worker                                                  (float)subTriangles[subTriangleNdx].vertices[1].weight[2] * out2;
697*35238bceSAndroid Build Coastguard Worker 
698*35238bceSAndroid Build Coastguard Worker                         p2->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[2].weight[0] * out0 +
699*35238bceSAndroid Build Coastguard Worker                                                  (float)subTriangles[subTriangleNdx].vertices[2].weight[1] * out1 +
700*35238bceSAndroid Build Coastguard Worker                                                  (float)subTriangles[subTriangleNdx].vertices[2].weight[2] * out2;
701*35238bceSAndroid Build Coastguard Worker                     }
702*35238bceSAndroid Build Coastguard Worker                     else
703*35238bceSAndroid Build Coastguard Worker                     {
704*35238bceSAndroid Build Coastguard Worker                         // only floats are interpolated, all others must be flatshaded then
705*35238bceSAndroid Build Coastguard Worker                         p0->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
706*35238bceSAndroid Build Coastguard Worker                         p1->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
707*35238bceSAndroid Build Coastguard Worker                         p2->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
708*35238bceSAndroid Build Coastguard Worker                     }
709*35238bceSAndroid Build Coastguard Worker                 }
710*35238bceSAndroid Build Coastguard Worker 
711*35238bceSAndroid Build Coastguard Worker                 outputTriangles.push_back(ngonFragment);
712*35238bceSAndroid Build Coastguard Worker             }
713*35238bceSAndroid Build Coastguard Worker         }
714*35238bceSAndroid Build Coastguard Worker     }
715*35238bceSAndroid Build Coastguard Worker 
716*35238bceSAndroid Build Coastguard Worker     // output result
717*35238bceSAndroid Build Coastguard Worker     list.swap(outputTriangles);
718*35238bceSAndroid Build Coastguard Worker }
719*35238bceSAndroid Build Coastguard Worker 
720*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
721*35238bceSAndroid Build Coastguard Worker  * Clip lines to the near and far clip planes.
722*35238bceSAndroid Build Coastguard Worker  *
723*35238bceSAndroid Build Coastguard Worker  * Clipping to other planes is a by-product of the viewport test  (i.e.
724*35238bceSAndroid Build Coastguard Worker  * rasterization area selection).
725*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
clipPrimitives(std::vector<pa::Line> & list,const Program & program,bool clipWithZPlanes,VertexPacketAllocator & vpalloc)726*35238bceSAndroid Build Coastguard Worker void clipPrimitives(std::vector<pa::Line> &list, const Program &program, bool clipWithZPlanes,
727*35238bceSAndroid Build Coastguard Worker                     VertexPacketAllocator &vpalloc)
728*35238bceSAndroid Build Coastguard Worker {
729*35238bceSAndroid Build Coastguard Worker     DE_UNREF(vpalloc);
730*35238bceSAndroid Build Coastguard Worker 
731*35238bceSAndroid Build Coastguard Worker     using namespace cliputil;
732*35238bceSAndroid Build Coastguard Worker 
733*35238bceSAndroid Build Coastguard Worker     // Lines are clipped only by the far and the near planes here. Line clipping by other planes done in the rasterization phase
734*35238bceSAndroid Build Coastguard Worker 
735*35238bceSAndroid Build Coastguard Worker     const std::vector<rr::VertexVaryingInfo> &fragInputs =
736*35238bceSAndroid Build Coastguard Worker         (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
737*35238bceSAndroid Build Coastguard Worker     std::vector<pa::Line> visibleLines;
738*35238bceSAndroid Build Coastguard Worker 
739*35238bceSAndroid Build Coastguard Worker     // Z-clipping disabled, don't do anything
740*35238bceSAndroid Build Coastguard Worker     if (!clipWithZPlanes)
741*35238bceSAndroid Build Coastguard Worker         return;
742*35238bceSAndroid Build Coastguard Worker 
743*35238bceSAndroid Build Coastguard Worker     for (size_t ndx = 0; ndx < list.size(); ++ndx)
744*35238bceSAndroid Build Coastguard Worker     {
745*35238bceSAndroid Build Coastguard Worker         pa::Line &l = list[ndx];
746*35238bceSAndroid Build Coastguard Worker 
747*35238bceSAndroid Build Coastguard Worker         // Totally discarded?
748*35238bceSAndroid Build Coastguard Worker         if ((l.v0->position.z() < -l.v0->position.w() && l.v1->position.z() < -l.v1->position.w()) ||
749*35238bceSAndroid Build Coastguard Worker             (l.v0->position.z() > l.v0->position.w() && l.v1->position.z() > l.v1->position.w()))
750*35238bceSAndroid Build Coastguard Worker             continue; // discard
751*35238bceSAndroid Build Coastguard Worker 
752*35238bceSAndroid Build Coastguard Worker         // Something is visible
753*35238bceSAndroid Build Coastguard Worker 
754*35238bceSAndroid Build Coastguard Worker         const ClipVec4 p0  = vec4ToClipVec4(l.v0->position);
755*35238bceSAndroid Build Coastguard Worker         const ClipVec4 p1  = vec4ToClipVec4(l.v1->position);
756*35238bceSAndroid Build Coastguard Worker         const ClipFloat t0 = getLineEndpointClipping(p0, p1);
757*35238bceSAndroid Build Coastguard Worker         const ClipFloat t1 = getLineEndpointClipping(p1, p0);
758*35238bceSAndroid Build Coastguard Worker 
759*35238bceSAndroid Build Coastguard Worker         // Not clipped at all?
760*35238bceSAndroid Build Coastguard Worker         if (t0 == (ClipFloat)0.0 && t1 == (ClipFloat)0.0)
761*35238bceSAndroid Build Coastguard Worker         {
762*35238bceSAndroid Build Coastguard Worker             visibleLines.push_back(pa::Line(l.v0, l.v1, -1));
763*35238bceSAndroid Build Coastguard Worker         }
764*35238bceSAndroid Build Coastguard Worker         else
765*35238bceSAndroid Build Coastguard Worker         {
766*35238bceSAndroid Build Coastguard Worker             // Clip position
767*35238bceSAndroid Build Coastguard Worker             l.v0->position = clipVec4ToVec4(tcu::mix(p0, p1, t0));
768*35238bceSAndroid Build Coastguard Worker             l.v1->position = clipVec4ToVec4(tcu::mix(p1, p0, t1));
769*35238bceSAndroid Build Coastguard Worker 
770*35238bceSAndroid Build Coastguard Worker             // Clip attributes
771*35238bceSAndroid Build Coastguard Worker             for (size_t outputNdx = 0; outputNdx < fragInputs.size(); ++outputNdx)
772*35238bceSAndroid Build Coastguard Worker             {
773*35238bceSAndroid Build Coastguard Worker                 // only floats are clipped, other types are flatshaded
774*35238bceSAndroid Build Coastguard Worker                 if (fragInputs[outputNdx].type == GENERICVECTYPE_FLOAT)
775*35238bceSAndroid Build Coastguard Worker                 {
776*35238bceSAndroid Build Coastguard Worker                     const tcu::Vec4 a0 = l.v0->outputs[outputNdx].get<float>();
777*35238bceSAndroid Build Coastguard Worker                     const tcu::Vec4 a1 = l.v1->outputs[outputNdx].get<float>();
778*35238bceSAndroid Build Coastguard Worker 
779*35238bceSAndroid Build Coastguard Worker                     l.v0->outputs[outputNdx] = tcu::mix(a0, a1, (float)t0);
780*35238bceSAndroid Build Coastguard Worker                     l.v1->outputs[outputNdx] = tcu::mix(a1, a0, (float)t1);
781*35238bceSAndroid Build Coastguard Worker                 }
782*35238bceSAndroid Build Coastguard Worker             }
783*35238bceSAndroid Build Coastguard Worker 
784*35238bceSAndroid Build Coastguard Worker             visibleLines.push_back(pa::Line(l.v0, l.v1, -1));
785*35238bceSAndroid Build Coastguard Worker         }
786*35238bceSAndroid Build Coastguard Worker     }
787*35238bceSAndroid Build Coastguard Worker 
788*35238bceSAndroid Build Coastguard Worker     // return visible in list
789*35238bceSAndroid Build Coastguard Worker     std::swap(visibleLines, list);
790*35238bceSAndroid Build Coastguard Worker }
791*35238bceSAndroid Build Coastguard Worker 
792*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
793*35238bceSAndroid Build Coastguard Worker  * Discard points not within clip volume. Clipping is a by-product
794*35238bceSAndroid Build Coastguard Worker  * of the viewport test.
795*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
clipPrimitives(std::vector<pa::Point> & list,const Program & program,bool clipWithZPlanes,VertexPacketAllocator & vpalloc)796*35238bceSAndroid Build Coastguard Worker void clipPrimitives(std::vector<pa::Point> &list, const Program &program, bool clipWithZPlanes,
797*35238bceSAndroid Build Coastguard Worker                     VertexPacketAllocator &vpalloc)
798*35238bceSAndroid Build Coastguard Worker {
799*35238bceSAndroid Build Coastguard Worker     DE_UNREF(vpalloc);
800*35238bceSAndroid Build Coastguard Worker     DE_UNREF(program);
801*35238bceSAndroid Build Coastguard Worker 
802*35238bceSAndroid Build Coastguard Worker     std::vector<pa::Point> visiblePoints;
803*35238bceSAndroid Build Coastguard Worker 
804*35238bceSAndroid Build Coastguard Worker     // Z-clipping disabled, don't do anything
805*35238bceSAndroid Build Coastguard Worker     if (!clipWithZPlanes)
806*35238bceSAndroid Build Coastguard Worker         return;
807*35238bceSAndroid Build Coastguard Worker 
808*35238bceSAndroid Build Coastguard Worker     for (size_t ndx = 0; ndx < list.size(); ++ndx)
809*35238bceSAndroid Build Coastguard Worker     {
810*35238bceSAndroid Build Coastguard Worker         pa::Point &p = list[ndx];
811*35238bceSAndroid Build Coastguard Worker 
812*35238bceSAndroid Build Coastguard Worker         // points are discarded if Z is not in range. (Wide) point clipping is done in the rasterization phase
813*35238bceSAndroid Build Coastguard Worker         if (de::inRange(p.v0->position.z(), -p.v0->position.w(), p.v0->position.w()))
814*35238bceSAndroid Build Coastguard Worker             visiblePoints.push_back(pa::Point(p.v0));
815*35238bceSAndroid Build Coastguard Worker     }
816*35238bceSAndroid Build Coastguard Worker 
817*35238bceSAndroid Build Coastguard Worker     // return visible in list
818*35238bceSAndroid Build Coastguard Worker     std::swap(visiblePoints, list);
819*35238bceSAndroid Build Coastguard Worker }
820*35238bceSAndroid Build Coastguard Worker 
transformVertexClipCoordsToWindowCoords(const RenderState & state,VertexPacket & packet)821*35238bceSAndroid Build Coastguard Worker void transformVertexClipCoordsToWindowCoords(const RenderState &state, VertexPacket &packet)
822*35238bceSAndroid Build Coastguard Worker {
823*35238bceSAndroid Build Coastguard Worker     // To normalized device coords
824*35238bceSAndroid Build Coastguard Worker     {
825*35238bceSAndroid Build Coastguard Worker         packet.position =
826*35238bceSAndroid Build Coastguard Worker             tcu::Vec4(packet.position.x() / packet.position.w(), packet.position.y() / packet.position.w(),
827*35238bceSAndroid Build Coastguard Worker                       packet.position.z() / packet.position.w(), 1.0f / packet.position.w());
828*35238bceSAndroid Build Coastguard Worker     }
829*35238bceSAndroid Build Coastguard Worker 
830*35238bceSAndroid Build Coastguard Worker     // To window coords
831*35238bceSAndroid Build Coastguard Worker     {
832*35238bceSAndroid Build Coastguard Worker         const WindowRectangle &viewport = state.viewport.rect;
833*35238bceSAndroid Build Coastguard Worker         const float halfW               = (float)(viewport.width) / 2.0f;
834*35238bceSAndroid Build Coastguard Worker         const float halfH               = (float)(viewport.height) / 2.0f;
835*35238bceSAndroid Build Coastguard Worker         const float oX                  = (float)viewport.left + halfW;
836*35238bceSAndroid Build Coastguard Worker         const float oY                  = (float)viewport.bottom + halfH;
837*35238bceSAndroid Build Coastguard Worker         const float zn                  = state.viewport.zn;
838*35238bceSAndroid Build Coastguard Worker         const float zf                  = state.viewport.zf;
839*35238bceSAndroid Build Coastguard Worker 
840*35238bceSAndroid Build Coastguard Worker         packet.position = tcu::Vec4(packet.position.x() * halfW + oX, packet.position.y() * halfH + oY,
841*35238bceSAndroid Build Coastguard Worker                                     packet.position.z() * (zf - zn) / 2.0f + (zn + zf) / 2.0f, packet.position.w());
842*35238bceSAndroid Build Coastguard Worker     }
843*35238bceSAndroid Build Coastguard Worker }
844*35238bceSAndroid Build Coastguard Worker 
transformPrimitiveClipCoordsToWindowCoords(const RenderState & state,pa::Triangle & target)845*35238bceSAndroid Build Coastguard Worker void transformPrimitiveClipCoordsToWindowCoords(const RenderState &state, pa::Triangle &target)
846*35238bceSAndroid Build Coastguard Worker {
847*35238bceSAndroid Build Coastguard Worker     transformVertexClipCoordsToWindowCoords(state, *target.v0);
848*35238bceSAndroid Build Coastguard Worker     transformVertexClipCoordsToWindowCoords(state, *target.v1);
849*35238bceSAndroid Build Coastguard Worker     transformVertexClipCoordsToWindowCoords(state, *target.v2);
850*35238bceSAndroid Build Coastguard Worker }
851*35238bceSAndroid Build Coastguard Worker 
transformPrimitiveClipCoordsToWindowCoords(const RenderState & state,pa::Line & target)852*35238bceSAndroid Build Coastguard Worker void transformPrimitiveClipCoordsToWindowCoords(const RenderState &state, pa::Line &target)
853*35238bceSAndroid Build Coastguard Worker {
854*35238bceSAndroid Build Coastguard Worker     transformVertexClipCoordsToWindowCoords(state, *target.v0);
855*35238bceSAndroid Build Coastguard Worker     transformVertexClipCoordsToWindowCoords(state, *target.v1);
856*35238bceSAndroid Build Coastguard Worker }
857*35238bceSAndroid Build Coastguard Worker 
transformPrimitiveClipCoordsToWindowCoords(const RenderState & state,pa::Point & target)858*35238bceSAndroid Build Coastguard Worker void transformPrimitiveClipCoordsToWindowCoords(const RenderState &state, pa::Point &target)
859*35238bceSAndroid Build Coastguard Worker {
860*35238bceSAndroid Build Coastguard Worker     transformVertexClipCoordsToWindowCoords(state, *target.v0);
861*35238bceSAndroid Build Coastguard Worker }
862*35238bceSAndroid Build Coastguard Worker 
863*35238bceSAndroid Build Coastguard Worker template <typename ContainerType>
transformClipCoordsToWindowCoords(const RenderState & state,ContainerType & list)864*35238bceSAndroid Build Coastguard Worker void transformClipCoordsToWindowCoords(const RenderState &state, ContainerType &list)
865*35238bceSAndroid Build Coastguard Worker {
866*35238bceSAndroid Build Coastguard Worker     for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
867*35238bceSAndroid Build Coastguard Worker         transformPrimitiveClipCoordsToWindowCoords(state, *it);
868*35238bceSAndroid Build Coastguard Worker }
869*35238bceSAndroid Build Coastguard Worker 
makeSharedVerticeDistinct(VertexPacket * & packet,std::set<VertexPacket *,std::less<void * >> & vertices,VertexPacketAllocator & vpalloc)870*35238bceSAndroid Build Coastguard Worker void makeSharedVerticeDistinct(VertexPacket *&packet, std::set<VertexPacket *, std::less<void *>> &vertices,
871*35238bceSAndroid Build Coastguard Worker                                VertexPacketAllocator &vpalloc)
872*35238bceSAndroid Build Coastguard Worker {
873*35238bceSAndroid Build Coastguard Worker     // distinct
874*35238bceSAndroid Build Coastguard Worker     if (vertices.find(packet) == vertices.end())
875*35238bceSAndroid Build Coastguard Worker     {
876*35238bceSAndroid Build Coastguard Worker         vertices.insert(packet);
877*35238bceSAndroid Build Coastguard Worker     }
878*35238bceSAndroid Build Coastguard Worker     else
879*35238bceSAndroid Build Coastguard Worker     {
880*35238bceSAndroid Build Coastguard Worker         VertexPacket *newPacket = vpalloc.alloc();
881*35238bceSAndroid Build Coastguard Worker 
882*35238bceSAndroid Build Coastguard Worker         // copy packet output values
883*35238bceSAndroid Build Coastguard Worker         newPacket->position    = packet->position;
884*35238bceSAndroid Build Coastguard Worker         newPacket->pointSize   = packet->pointSize;
885*35238bceSAndroid Build Coastguard Worker         newPacket->primitiveID = packet->primitiveID;
886*35238bceSAndroid Build Coastguard Worker 
887*35238bceSAndroid Build Coastguard Worker         for (size_t outputNdx = 0; outputNdx < vpalloc.getNumVertexOutputs(); ++outputNdx)
888*35238bceSAndroid Build Coastguard Worker             newPacket->outputs[outputNdx] = packet->outputs[outputNdx];
889*35238bceSAndroid Build Coastguard Worker 
890*35238bceSAndroid Build Coastguard Worker         // no need to insert new packet to "vertices" as newPacket is unique
891*35238bceSAndroid Build Coastguard Worker         packet = newPacket;
892*35238bceSAndroid Build Coastguard Worker     }
893*35238bceSAndroid Build Coastguard Worker }
894*35238bceSAndroid Build Coastguard Worker 
makeSharedVerticesDistinct(pa::Triangle & target,std::set<VertexPacket *,std::less<void * >> & vertices,VertexPacketAllocator & vpalloc)895*35238bceSAndroid Build Coastguard Worker void makeSharedVerticesDistinct(pa::Triangle &target, std::set<VertexPacket *, std::less<void *>> &vertices,
896*35238bceSAndroid Build Coastguard Worker                                 VertexPacketAllocator &vpalloc)
897*35238bceSAndroid Build Coastguard Worker {
898*35238bceSAndroid Build Coastguard Worker     makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
899*35238bceSAndroid Build Coastguard Worker     makeSharedVerticeDistinct(target.v1, vertices, vpalloc);
900*35238bceSAndroid Build Coastguard Worker     makeSharedVerticeDistinct(target.v2, vertices, vpalloc);
901*35238bceSAndroid Build Coastguard Worker }
902*35238bceSAndroid Build Coastguard Worker 
makeSharedVerticesDistinct(pa::Line & target,std::set<VertexPacket *,std::less<void * >> & vertices,VertexPacketAllocator & vpalloc)903*35238bceSAndroid Build Coastguard Worker void makeSharedVerticesDistinct(pa::Line &target, std::set<VertexPacket *, std::less<void *>> &vertices,
904*35238bceSAndroid Build Coastguard Worker                                 VertexPacketAllocator &vpalloc)
905*35238bceSAndroid Build Coastguard Worker {
906*35238bceSAndroid Build Coastguard Worker     makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
907*35238bceSAndroid Build Coastguard Worker     makeSharedVerticeDistinct(target.v1, vertices, vpalloc);
908*35238bceSAndroid Build Coastguard Worker }
909*35238bceSAndroid Build Coastguard Worker 
makeSharedVerticesDistinct(pa::Point & target,std::set<VertexPacket *,std::less<void * >> & vertices,VertexPacketAllocator & vpalloc)910*35238bceSAndroid Build Coastguard Worker void makeSharedVerticesDistinct(pa::Point &target, std::set<VertexPacket *, std::less<void *>> &vertices,
911*35238bceSAndroid Build Coastguard Worker                                 VertexPacketAllocator &vpalloc)
912*35238bceSAndroid Build Coastguard Worker {
913*35238bceSAndroid Build Coastguard Worker     makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
914*35238bceSAndroid Build Coastguard Worker }
915*35238bceSAndroid Build Coastguard Worker 
916*35238bceSAndroid Build Coastguard Worker template <typename ContainerType>
makeSharedVerticesDistinct(ContainerType & list,VertexPacketAllocator & vpalloc)917*35238bceSAndroid Build Coastguard Worker void makeSharedVerticesDistinct(ContainerType &list, VertexPacketAllocator &vpalloc)
918*35238bceSAndroid Build Coastguard Worker {
919*35238bceSAndroid Build Coastguard Worker     std::set<VertexPacket *, std::less<void *>> vertices;
920*35238bceSAndroid Build Coastguard Worker 
921*35238bceSAndroid Build Coastguard Worker     for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
922*35238bceSAndroid Build Coastguard Worker         makeSharedVerticesDistinct(*it, vertices, vpalloc);
923*35238bceSAndroid Build Coastguard Worker }
924*35238bceSAndroid Build Coastguard Worker 
generatePrimitiveIDs(pa::Triangle & target,int id)925*35238bceSAndroid Build Coastguard Worker void generatePrimitiveIDs(pa::Triangle &target, int id)
926*35238bceSAndroid Build Coastguard Worker {
927*35238bceSAndroid Build Coastguard Worker     target.v0->primitiveID = id;
928*35238bceSAndroid Build Coastguard Worker     target.v1->primitiveID = id;
929*35238bceSAndroid Build Coastguard Worker     target.v2->primitiveID = id;
930*35238bceSAndroid Build Coastguard Worker }
931*35238bceSAndroid Build Coastguard Worker 
generatePrimitiveIDs(pa::Line & target,int id)932*35238bceSAndroid Build Coastguard Worker void generatePrimitiveIDs(pa::Line &target, int id)
933*35238bceSAndroid Build Coastguard Worker {
934*35238bceSAndroid Build Coastguard Worker     target.v0->primitiveID = id;
935*35238bceSAndroid Build Coastguard Worker     target.v1->primitiveID = id;
936*35238bceSAndroid Build Coastguard Worker }
937*35238bceSAndroid Build Coastguard Worker 
generatePrimitiveIDs(pa::Point & target,int id)938*35238bceSAndroid Build Coastguard Worker void generatePrimitiveIDs(pa::Point &target, int id)
939*35238bceSAndroid Build Coastguard Worker {
940*35238bceSAndroid Build Coastguard Worker     target.v0->primitiveID = id;
941*35238bceSAndroid Build Coastguard Worker }
942*35238bceSAndroid Build Coastguard Worker 
943*35238bceSAndroid Build Coastguard Worker template <typename ContainerType>
generatePrimitiveIDs(ContainerType & list,DrawContext & drawContext)944*35238bceSAndroid Build Coastguard Worker void generatePrimitiveIDs(ContainerType &list, DrawContext &drawContext)
945*35238bceSAndroid Build Coastguard Worker {
946*35238bceSAndroid Build Coastguard Worker     for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
947*35238bceSAndroid Build Coastguard Worker         generatePrimitiveIDs(*it, drawContext.primitiveID++);
948*35238bceSAndroid Build Coastguard Worker }
949*35238bceSAndroid Build Coastguard Worker 
findTriangleVertexDepthSlope(const tcu::Vec4 & p,const tcu::Vec4 & v0,const tcu::Vec4 & v1)950*35238bceSAndroid Build Coastguard Worker static float findTriangleVertexDepthSlope(const tcu::Vec4 &p, const tcu::Vec4 &v0, const tcu::Vec4 &v1)
951*35238bceSAndroid Build Coastguard Worker {
952*35238bceSAndroid Build Coastguard Worker     // screen space
953*35238bceSAndroid Build Coastguard Worker     const tcu::Vec3 ssp  = p.swizzle(0, 1, 2);
954*35238bceSAndroid Build Coastguard Worker     const tcu::Vec3 ssv0 = v0.swizzle(0, 1, 2);
955*35238bceSAndroid Build Coastguard Worker     const tcu::Vec3 ssv1 = v1.swizzle(0, 1, 2);
956*35238bceSAndroid Build Coastguard Worker 
957*35238bceSAndroid Build Coastguard Worker     // dx & dy
958*35238bceSAndroid Build Coastguard Worker 
959*35238bceSAndroid Build Coastguard Worker     const tcu::Vec3 a   = ssv0.swizzle(0, 1, 2) - ssp.swizzle(0, 1, 2);
960*35238bceSAndroid Build Coastguard Worker     const tcu::Vec3 b   = ssv1.swizzle(0, 1, 2) - ssp.swizzle(0, 1, 2);
961*35238bceSAndroid Build Coastguard Worker     const float epsilon = 0.0001f;
962*35238bceSAndroid Build Coastguard Worker     const float det     = (a.x() * b.y() - b.x() * a.y());
963*35238bceSAndroid Build Coastguard Worker 
964*35238bceSAndroid Build Coastguard Worker     // degenerate triangle, it won't generate any fragments anyway. Return value doesn't matter
965*35238bceSAndroid Build Coastguard Worker     if (de::abs(det) < epsilon)
966*35238bceSAndroid Build Coastguard Worker         return 0.0f;
967*35238bceSAndroid Build Coastguard Worker 
968*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 dxDir = tcu::Vec2(b.y(), -a.y()) / det;
969*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 dyDir = tcu::Vec2(-b.x(), a.x()) / det;
970*35238bceSAndroid Build Coastguard Worker 
971*35238bceSAndroid Build Coastguard Worker     const float dzdx = dxDir.x() * a.z() + dxDir.y() * b.z();
972*35238bceSAndroid Build Coastguard Worker     const float dzdy = dyDir.x() * a.z() + dyDir.y() * b.z();
973*35238bceSAndroid Build Coastguard Worker 
974*35238bceSAndroid Build Coastguard Worker     // approximate using max(|dz/dx|, |dz/dy|)
975*35238bceSAndroid Build Coastguard Worker     return de::max(de::abs(dzdx), de::abs(dzdy));
976*35238bceSAndroid Build Coastguard Worker }
977*35238bceSAndroid Build Coastguard Worker 
findPrimitiveMaximumDepthSlope(const pa::Triangle & triangle)978*35238bceSAndroid Build Coastguard Worker static float findPrimitiveMaximumDepthSlope(const pa::Triangle &triangle)
979*35238bceSAndroid Build Coastguard Worker {
980*35238bceSAndroid Build Coastguard Worker     const float d1 = findTriangleVertexDepthSlope(triangle.v0->position, triangle.v1->position, triangle.v2->position);
981*35238bceSAndroid Build Coastguard Worker     const float d2 = findTriangleVertexDepthSlope(triangle.v1->position, triangle.v2->position, triangle.v0->position);
982*35238bceSAndroid Build Coastguard Worker     const float d3 = findTriangleVertexDepthSlope(triangle.v2->position, triangle.v0->position, triangle.v1->position);
983*35238bceSAndroid Build Coastguard Worker 
984*35238bceSAndroid Build Coastguard Worker     return de::max(d1, de::max(d2, d3));
985*35238bceSAndroid Build Coastguard Worker }
986*35238bceSAndroid Build Coastguard Worker 
getFloatingPointMinimumResolvableDifference(float maxZValue,tcu::TextureFormat::ChannelType type)987*35238bceSAndroid Build Coastguard Worker static float getFloatingPointMinimumResolvableDifference(float maxZValue, tcu::TextureFormat::ChannelType type)
988*35238bceSAndroid Build Coastguard Worker {
989*35238bceSAndroid Build Coastguard Worker     if (type == tcu::TextureFormat::FLOAT)
990*35238bceSAndroid Build Coastguard Worker     {
991*35238bceSAndroid Build Coastguard Worker         // 32f
992*35238bceSAndroid Build Coastguard Worker         const int maxExponent = tcu::Float32(maxZValue).exponent();
993*35238bceSAndroid Build Coastguard Worker         return tcu::Float32::construct(+1, maxExponent - 23, 1 << 23).asFloat();
994*35238bceSAndroid Build Coastguard Worker     }
995*35238bceSAndroid Build Coastguard Worker 
996*35238bceSAndroid Build Coastguard Worker     // unexpected format
997*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
998*35238bceSAndroid Build Coastguard Worker     return 0.0f;
999*35238bceSAndroid Build Coastguard Worker }
1000*35238bceSAndroid Build Coastguard Worker 
getFixedPointMinimumResolvableDifference(int numBits)1001*35238bceSAndroid Build Coastguard Worker static float getFixedPointMinimumResolvableDifference(int numBits)
1002*35238bceSAndroid Build Coastguard Worker {
1003*35238bceSAndroid Build Coastguard Worker     return tcu::Float32::construct(+1, -numBits, 1 << 23).asFloat();
1004*35238bceSAndroid Build Coastguard Worker }
1005*35238bceSAndroid Build Coastguard Worker 
findPrimitiveMinimumResolvableDifference(const pa::Triangle & triangle,const rr::MultisampleConstPixelBufferAccess & depthAccess)1006*35238bceSAndroid Build Coastguard Worker static float findPrimitiveMinimumResolvableDifference(const pa::Triangle &triangle,
1007*35238bceSAndroid Build Coastguard Worker                                                       const rr::MultisampleConstPixelBufferAccess &depthAccess)
1008*35238bceSAndroid Build Coastguard Worker {
1009*35238bceSAndroid Build Coastguard Worker     const float maxZvalue =
1010*35238bceSAndroid Build Coastguard Worker         de::max(de::max(triangle.v0->position.z(), triangle.v1->position.z()), triangle.v2->position.z());
1011*35238bceSAndroid Build Coastguard Worker     const tcu::TextureFormat format              = depthAccess.raw().getFormat();
1012*35238bceSAndroid Build Coastguard Worker     const tcu::TextureFormat::ChannelOrder order = format.order;
1013*35238bceSAndroid Build Coastguard Worker 
1014*35238bceSAndroid Build Coastguard Worker     if (order == tcu::TextureFormat::D)
1015*35238bceSAndroid Build Coastguard Worker     {
1016*35238bceSAndroid Build Coastguard Worker         // depth only
1017*35238bceSAndroid Build Coastguard Worker         const tcu::TextureFormat::ChannelType channelType = format.type;
1018*35238bceSAndroid Build Coastguard Worker         const tcu::TextureChannelClass channelClass       = tcu::getTextureChannelClass(channelType);
1019*35238bceSAndroid Build Coastguard Worker         const int numBits                                 = tcu::getTextureFormatBitDepth(format).x();
1020*35238bceSAndroid Build Coastguard Worker 
1021*35238bceSAndroid Build Coastguard Worker         if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1022*35238bceSAndroid Build Coastguard Worker             return getFloatingPointMinimumResolvableDifference(maxZvalue, channelType);
1023*35238bceSAndroid Build Coastguard Worker         else
1024*35238bceSAndroid Build Coastguard Worker             // \note channelClass might be CLASS_LAST but that's ok
1025*35238bceSAndroid Build Coastguard Worker             return getFixedPointMinimumResolvableDifference(numBits);
1026*35238bceSAndroid Build Coastguard Worker     }
1027*35238bceSAndroid Build Coastguard Worker     else if (order == tcu::TextureFormat::DS)
1028*35238bceSAndroid Build Coastguard Worker     {
1029*35238bceSAndroid Build Coastguard Worker         // depth stencil, special cases for possible combined formats
1030*35238bceSAndroid Build Coastguard Worker         if (format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
1031*35238bceSAndroid Build Coastguard Worker             return getFloatingPointMinimumResolvableDifference(maxZvalue, tcu::TextureFormat::FLOAT);
1032*35238bceSAndroid Build Coastguard Worker         else if (format.type == tcu::TextureFormat::UNSIGNED_INT_24_8)
1033*35238bceSAndroid Build Coastguard Worker             return getFixedPointMinimumResolvableDifference(24);
1034*35238bceSAndroid Build Coastguard Worker     }
1035*35238bceSAndroid Build Coastguard Worker 
1036*35238bceSAndroid Build Coastguard Worker     // unexpected format
1037*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(false);
1038*35238bceSAndroid Build Coastguard Worker     return 0.0f;
1039*35238bceSAndroid Build Coastguard Worker }
1040*35238bceSAndroid Build Coastguard Worker 
writeFragmentPackets(const RenderState & state,const RenderTarget & renderTarget,const Program & program,const FragmentPacket * fragmentPackets,int numRasterizedPackets,rr::FaceType facetype,const std::vector<rr::GenericVec4> & fragmentOutputArray,const std::vector<rr::GenericVec4> & fragmentOutputArraySrc1,const float * depthValues,std::vector<Fragment> & fragmentBuffer)1041*35238bceSAndroid Build Coastguard Worker void writeFragmentPackets(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1042*35238bceSAndroid Build Coastguard Worker                           const FragmentPacket *fragmentPackets, int numRasterizedPackets, rr::FaceType facetype,
1043*35238bceSAndroid Build Coastguard Worker                           const std::vector<rr::GenericVec4> &fragmentOutputArray,
1044*35238bceSAndroid Build Coastguard Worker                           const std::vector<rr::GenericVec4> &fragmentOutputArraySrc1, const float *depthValues,
1045*35238bceSAndroid Build Coastguard Worker                           std::vector<Fragment> &fragmentBuffer)
1046*35238bceSAndroid Build Coastguard Worker {
1047*35238bceSAndroid Build Coastguard Worker     const int numSamples    = renderTarget.getNumSamples();
1048*35238bceSAndroid Build Coastguard Worker     const size_t numOutputs = program.fragmentShader->getOutputs().size();
1049*35238bceSAndroid Build Coastguard Worker     FragmentProcessor fragProcessor;
1050*35238bceSAndroid Build Coastguard Worker 
1051*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fragmentOutputArray.size() >= (size_t)numRasterizedPackets * 4 * numOutputs);
1052*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fragmentBuffer.size() >= (size_t)numRasterizedPackets * 4);
1053*35238bceSAndroid Build Coastguard Worker 
1054*35238bceSAndroid Build Coastguard Worker     // Translate fragments but do not set the value yet
1055*35238bceSAndroid Build Coastguard Worker     {
1056*35238bceSAndroid Build Coastguard Worker         int fragCount = 0;
1057*35238bceSAndroid Build Coastguard Worker         for (int packetNdx = 0; packetNdx < numRasterizedPackets; ++packetNdx)
1058*35238bceSAndroid Build Coastguard Worker             for (int fragNdx = 0; fragNdx < 4; fragNdx++)
1059*35238bceSAndroid Build Coastguard Worker             {
1060*35238bceSAndroid Build Coastguard Worker                 const FragmentPacket &packet = fragmentPackets[packetNdx];
1061*35238bceSAndroid Build Coastguard Worker                 const int xo                 = fragNdx % 2;
1062*35238bceSAndroid Build Coastguard Worker                 const int yo                 = fragNdx / 2;
1063*35238bceSAndroid Build Coastguard Worker 
1064*35238bceSAndroid Build Coastguard Worker                 if (getCoverageAnyFragmentSampleLive(packet.coverage, numSamples, xo, yo))
1065*35238bceSAndroid Build Coastguard Worker                 {
1066*35238bceSAndroid Build Coastguard Worker                     Fragment &fragment = fragmentBuffer[fragCount++];
1067*35238bceSAndroid Build Coastguard Worker 
1068*35238bceSAndroid Build Coastguard Worker                     fragment.pixelCoord = packet.position + tcu::IVec2(xo, yo);
1069*35238bceSAndroid Build Coastguard Worker                     fragment.coverage =
1070*35238bceSAndroid Build Coastguard Worker                         (uint32_t)((packet.coverage & getCoverageFragmentSampleBits(numSamples, xo, yo)) >>
1071*35238bceSAndroid Build Coastguard Worker                                    getCoverageOffset(numSamples, xo, yo));
1072*35238bceSAndroid Build Coastguard Worker                     fragment.sampleDepths =
1073*35238bceSAndroid Build Coastguard Worker                         (depthValues) ? (&depthValues[(packetNdx * 4 + yo * 2 + xo) * numSamples]) : (DE_NULL);
1074*35238bceSAndroid Build Coastguard Worker                 }
1075*35238bceSAndroid Build Coastguard Worker             }
1076*35238bceSAndroid Build Coastguard Worker     }
1077*35238bceSAndroid Build Coastguard Worker 
1078*35238bceSAndroid Build Coastguard Worker     // Set per output output values
1079*35238bceSAndroid Build Coastguard Worker     {
1080*35238bceSAndroid Build Coastguard Worker         rr::FragmentOperationState noStencilDepthWriteState(state.fragOps);
1081*35238bceSAndroid Build Coastguard Worker         noStencilDepthWriteState.depthMask                      = false;
1082*35238bceSAndroid Build Coastguard Worker         noStencilDepthWriteState.stencilStates[facetype].sFail  = STENCILOP_KEEP;
1083*35238bceSAndroid Build Coastguard Worker         noStencilDepthWriteState.stencilStates[facetype].dpFail = STENCILOP_KEEP;
1084*35238bceSAndroid Build Coastguard Worker         noStencilDepthWriteState.stencilStates[facetype].dpPass = STENCILOP_KEEP;
1085*35238bceSAndroid Build Coastguard Worker 
1086*35238bceSAndroid Build Coastguard Worker         int fragCount = 0;
1087*35238bceSAndroid Build Coastguard Worker         for (size_t outputNdx = 0; outputNdx < numOutputs; ++outputNdx)
1088*35238bceSAndroid Build Coastguard Worker         {
1089*35238bceSAndroid Build Coastguard Worker             // Only the last output-pass has default state, other passes have stencil & depth writemask=0
1090*35238bceSAndroid Build Coastguard Worker             const rr::FragmentOperationState &fragOpsState =
1091*35238bceSAndroid Build Coastguard Worker                 (outputNdx == numOutputs - 1) ? (state.fragOps) : (noStencilDepthWriteState);
1092*35238bceSAndroid Build Coastguard Worker 
1093*35238bceSAndroid Build Coastguard Worker             for (int packetNdx = 0; packetNdx < numRasterizedPackets; ++packetNdx)
1094*35238bceSAndroid Build Coastguard Worker                 for (int fragNdx = 0; fragNdx < 4; fragNdx++)
1095*35238bceSAndroid Build Coastguard Worker                 {
1096*35238bceSAndroid Build Coastguard Worker                     const FragmentPacket &packet = fragmentPackets[packetNdx];
1097*35238bceSAndroid Build Coastguard Worker                     const int xo                 = fragNdx % 2;
1098*35238bceSAndroid Build Coastguard Worker                     const int yo                 = fragNdx / 2;
1099*35238bceSAndroid Build Coastguard Worker 
1100*35238bceSAndroid Build Coastguard Worker                     // Add only fragments that have live samples to shaded fragments queue.
1101*35238bceSAndroid Build Coastguard Worker                     if (getCoverageAnyFragmentSampleLive(packet.coverage, numSamples, xo, yo))
1102*35238bceSAndroid Build Coastguard Worker                     {
1103*35238bceSAndroid Build Coastguard Worker                         Fragment &fragment = fragmentBuffer[fragCount++];
1104*35238bceSAndroid Build Coastguard Worker                         fragment.value     = fragmentOutputArray[(packetNdx * 4 + fragNdx) * numOutputs + outputNdx];
1105*35238bceSAndroid Build Coastguard Worker                         fragment.value1 = fragmentOutputArraySrc1[(packetNdx * 4 + fragNdx) * numOutputs + outputNdx];
1106*35238bceSAndroid Build Coastguard Worker                     }
1107*35238bceSAndroid Build Coastguard Worker                 }
1108*35238bceSAndroid Build Coastguard Worker 
1109*35238bceSAndroid Build Coastguard Worker             // Execute per-fragment ops and write
1110*35238bceSAndroid Build Coastguard Worker             fragProcessor.render(renderTarget.getColorBuffer((int)outputNdx), renderTarget.getDepthBuffer(),
1111*35238bceSAndroid Build Coastguard Worker                                  renderTarget.getStencilBuffer(), &fragmentBuffer[0], fragCount, facetype,
1112*35238bceSAndroid Build Coastguard Worker                                  fragOpsState);
1113*35238bceSAndroid Build Coastguard Worker         }
1114*35238bceSAndroid Build Coastguard Worker     }
1115*35238bceSAndroid Build Coastguard Worker }
1116*35238bceSAndroid Build Coastguard Worker 
rasterizePrimitive(const RenderState & state,const RenderTarget & renderTarget,const Program & program,const pa::Triangle & triangle,const tcu::IVec4 & renderTargetRect,RasterizationInternalBuffers & buffers)1117*35238bceSAndroid Build Coastguard Worker void rasterizePrimitive(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1118*35238bceSAndroid Build Coastguard Worker                         const pa::Triangle &triangle, const tcu::IVec4 &renderTargetRect,
1119*35238bceSAndroid Build Coastguard Worker                         RasterizationInternalBuffers &buffers)
1120*35238bceSAndroid Build Coastguard Worker {
1121*35238bceSAndroid Build Coastguard Worker     const int numSamples      = renderTarget.getNumSamples();
1122*35238bceSAndroid Build Coastguard Worker     const float depthClampMin = de::min(state.viewport.zn, state.viewport.zf);
1123*35238bceSAndroid Build Coastguard Worker     const float depthClampMax = de::max(state.viewport.zn, state.viewport.zf);
1124*35238bceSAndroid Build Coastguard Worker     TriangleRasterizer rasterizer(renderTargetRect, numSamples, state.rasterization, state.subpixelBits);
1125*35238bceSAndroid Build Coastguard Worker     float depthOffset = 0.0f;
1126*35238bceSAndroid Build Coastguard Worker 
1127*35238bceSAndroid Build Coastguard Worker     rasterizer.init(triangle.v0->position, triangle.v1->position, triangle.v2->position);
1128*35238bceSAndroid Build Coastguard Worker 
1129*35238bceSAndroid Build Coastguard Worker     // Culling
1130*35238bceSAndroid Build Coastguard Worker     const FaceType visibleFace = rasterizer.getVisibleFace();
1131*35238bceSAndroid Build Coastguard Worker     if ((state.cullMode == CULLMODE_FRONT && visibleFace == FACETYPE_FRONT) ||
1132*35238bceSAndroid Build Coastguard Worker         (state.cullMode == CULLMODE_BACK && visibleFace == FACETYPE_BACK))
1133*35238bceSAndroid Build Coastguard Worker         return;
1134*35238bceSAndroid Build Coastguard Worker 
1135*35238bceSAndroid Build Coastguard Worker     // Shading context
1136*35238bceSAndroid Build Coastguard Worker     FragmentShadingContext shadingContext(
1137*35238bceSAndroid Build Coastguard Worker         triangle.v0->outputs, triangle.v1->outputs, triangle.v2->outputs, &buffers.shaderOutputs[0],
1138*35238bceSAndroid Build Coastguard Worker         &buffers.shaderOutputsSrc1[0], buffers.fragmentDepthBuffer, triangle.v2->primitiveID,
1139*35238bceSAndroid Build Coastguard Worker         (int)program.fragmentShader->getOutputs().size(), numSamples, rasterizer.getVisibleFace());
1140*35238bceSAndroid Build Coastguard Worker 
1141*35238bceSAndroid Build Coastguard Worker     // Polygon offset
1142*35238bceSAndroid Build Coastguard Worker     if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
1143*35238bceSAndroid Build Coastguard Worker     {
1144*35238bceSAndroid Build Coastguard Worker         const float maximumDepthSlope = findPrimitiveMaximumDepthSlope(triangle);
1145*35238bceSAndroid Build Coastguard Worker         const float minimumResolvableDifference =
1146*35238bceSAndroid Build Coastguard Worker             findPrimitiveMinimumResolvableDifference(triangle, renderTarget.getDepthBuffer());
1147*35238bceSAndroid Build Coastguard Worker 
1148*35238bceSAndroid Build Coastguard Worker         depthOffset = maximumDepthSlope * state.fragOps.polygonOffsetFactor +
1149*35238bceSAndroid Build Coastguard Worker                       minimumResolvableDifference * state.fragOps.polygonOffsetUnits;
1150*35238bceSAndroid Build Coastguard Worker     }
1151*35238bceSAndroid Build Coastguard Worker 
1152*35238bceSAndroid Build Coastguard Worker     // Execute rasterize - shade - write loop
1153*35238bceSAndroid Build Coastguard Worker     for (;;)
1154*35238bceSAndroid Build Coastguard Worker     {
1155*35238bceSAndroid Build Coastguard Worker         const int maxFragmentPackets = (int)buffers.fragmentPackets.size();
1156*35238bceSAndroid Build Coastguard Worker         int numRasterizedPackets     = 0;
1157*35238bceSAndroid Build Coastguard Worker 
1158*35238bceSAndroid Build Coastguard Worker         // Rasterize
1159*35238bceSAndroid Build Coastguard Worker 
1160*35238bceSAndroid Build Coastguard Worker         rasterizer.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets,
1161*35238bceSAndroid Build Coastguard Worker                              numRasterizedPackets);
1162*35238bceSAndroid Build Coastguard Worker 
1163*35238bceSAndroid Build Coastguard Worker         // numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
1164*35238bceSAndroid Build Coastguard Worker 
1165*35238bceSAndroid Build Coastguard Worker         if (!numRasterizedPackets)
1166*35238bceSAndroid Build Coastguard Worker             break; // Rasterization finished.
1167*35238bceSAndroid Build Coastguard Worker 
1168*35238bceSAndroid Build Coastguard Worker         // Polygon offset
1169*35238bceSAndroid Build Coastguard Worker         if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
1170*35238bceSAndroid Build Coastguard Worker             for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1171*35238bceSAndroid Build Coastguard Worker                 buffers.fragmentDepthBuffer[sampleNdx] =
1172*35238bceSAndroid Build Coastguard Worker                     de::clamp(buffers.fragmentDepthBuffer[sampleNdx] + depthOffset, 0.0f, 1.0f);
1173*35238bceSAndroid Build Coastguard Worker 
1174*35238bceSAndroid Build Coastguard Worker         // Shade
1175*35238bceSAndroid Build Coastguard Worker 
1176*35238bceSAndroid Build Coastguard Worker         program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
1177*35238bceSAndroid Build Coastguard Worker 
1178*35238bceSAndroid Build Coastguard Worker         // Depth clamp
1179*35238bceSAndroid Build Coastguard Worker         if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
1180*35238bceSAndroid Build Coastguard Worker             for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1181*35238bceSAndroid Build Coastguard Worker                 buffers.fragmentDepthBuffer[sampleNdx] =
1182*35238bceSAndroid Build Coastguard Worker                     de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
1183*35238bceSAndroid Build Coastguard Worker 
1184*35238bceSAndroid Build Coastguard Worker         // Handle fragment shader outputs
1185*35238bceSAndroid Build Coastguard Worker 
1186*35238bceSAndroid Build Coastguard Worker         writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets,
1187*35238bceSAndroid Build Coastguard Worker                              visibleFace, buffers.shaderOutputs, buffers.shaderOutputsSrc1, buffers.fragmentDepthBuffer,
1188*35238bceSAndroid Build Coastguard Worker                              buffers.shadedFragments);
1189*35238bceSAndroid Build Coastguard Worker     }
1190*35238bceSAndroid Build Coastguard Worker }
1191*35238bceSAndroid Build Coastguard Worker 
rasterizePrimitive(const RenderState & state,const RenderTarget & renderTarget,const Program & program,const pa::Line & line,const tcu::IVec4 & renderTargetRect,RasterizationInternalBuffers & buffers)1192*35238bceSAndroid Build Coastguard Worker void rasterizePrimitive(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1193*35238bceSAndroid Build Coastguard Worker                         const pa::Line &line, const tcu::IVec4 &renderTargetRect, RasterizationInternalBuffers &buffers)
1194*35238bceSAndroid Build Coastguard Worker {
1195*35238bceSAndroid Build Coastguard Worker     const int numSamples      = renderTarget.getNumSamples();
1196*35238bceSAndroid Build Coastguard Worker     const float depthClampMin = de::min(state.viewport.zn, state.viewport.zf);
1197*35238bceSAndroid Build Coastguard Worker     const float depthClampMax = de::max(state.viewport.zn, state.viewport.zf);
1198*35238bceSAndroid Build Coastguard Worker     const bool msaa           = numSamples > 1;
1199*35238bceSAndroid Build Coastguard Worker     FragmentShadingContext shadingContext(line.v0->outputs, line.v1->outputs, DE_NULL, &buffers.shaderOutputs[0],
1200*35238bceSAndroid Build Coastguard Worker                                           &buffers.shaderOutputsSrc1[0], buffers.fragmentDepthBuffer,
1201*35238bceSAndroid Build Coastguard Worker                                           line.v1->primitiveID, (int)program.fragmentShader->getOutputs().size(),
1202*35238bceSAndroid Build Coastguard Worker                                           numSamples, FACETYPE_FRONT);
1203*35238bceSAndroid Build Coastguard Worker     SingleSampleLineRasterizer aliasedRasterizer(renderTargetRect, state.subpixelBits);
1204*35238bceSAndroid Build Coastguard Worker     MultiSampleLineRasterizer msaaRasterizer(numSamples, renderTargetRect, state.subpixelBits);
1205*35238bceSAndroid Build Coastguard Worker 
1206*35238bceSAndroid Build Coastguard Worker     // Initialize rasterization.
1207*35238bceSAndroid Build Coastguard Worker     if (msaa)
1208*35238bceSAndroid Build Coastguard Worker         msaaRasterizer.init(line.v0->position, line.v1->position, state.line.lineWidth);
1209*35238bceSAndroid Build Coastguard Worker     else
1210*35238bceSAndroid Build Coastguard Worker         aliasedRasterizer.init(line.v0->position, line.v1->position, state.line.lineWidth, 1, 0xFFFF);
1211*35238bceSAndroid Build Coastguard Worker 
1212*35238bceSAndroid Build Coastguard Worker     for (;;)
1213*35238bceSAndroid Build Coastguard Worker     {
1214*35238bceSAndroid Build Coastguard Worker         const int maxFragmentPackets = (int)buffers.fragmentPackets.size();
1215*35238bceSAndroid Build Coastguard Worker         int numRasterizedPackets     = 0;
1216*35238bceSAndroid Build Coastguard Worker 
1217*35238bceSAndroid Build Coastguard Worker         // Rasterize
1218*35238bceSAndroid Build Coastguard Worker 
1219*35238bceSAndroid Build Coastguard Worker         if (msaa)
1220*35238bceSAndroid Build Coastguard Worker             msaaRasterizer.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets,
1221*35238bceSAndroid Build Coastguard Worker                                      numRasterizedPackets);
1222*35238bceSAndroid Build Coastguard Worker         else
1223*35238bceSAndroid Build Coastguard Worker             aliasedRasterizer.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets,
1224*35238bceSAndroid Build Coastguard Worker                                         numRasterizedPackets);
1225*35238bceSAndroid Build Coastguard Worker 
1226*35238bceSAndroid Build Coastguard Worker         // numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
1227*35238bceSAndroid Build Coastguard Worker 
1228*35238bceSAndroid Build Coastguard Worker         if (!numRasterizedPackets)
1229*35238bceSAndroid Build Coastguard Worker             break; // Rasterization finished.
1230*35238bceSAndroid Build Coastguard Worker 
1231*35238bceSAndroid Build Coastguard Worker         // Shade
1232*35238bceSAndroid Build Coastguard Worker 
1233*35238bceSAndroid Build Coastguard Worker         program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
1234*35238bceSAndroid Build Coastguard Worker 
1235*35238bceSAndroid Build Coastguard Worker         // Depth clamp
1236*35238bceSAndroid Build Coastguard Worker         if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
1237*35238bceSAndroid Build Coastguard Worker             for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1238*35238bceSAndroid Build Coastguard Worker                 buffers.fragmentDepthBuffer[sampleNdx] =
1239*35238bceSAndroid Build Coastguard Worker                     de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
1240*35238bceSAndroid Build Coastguard Worker 
1241*35238bceSAndroid Build Coastguard Worker         // Handle fragment shader outputs
1242*35238bceSAndroid Build Coastguard Worker 
1243*35238bceSAndroid Build Coastguard Worker         writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets,
1244*35238bceSAndroid Build Coastguard Worker                              rr::FACETYPE_FRONT, buffers.shaderOutputs, buffers.shaderOutputsSrc1,
1245*35238bceSAndroid Build Coastguard Worker                              buffers.fragmentDepthBuffer, buffers.shadedFragments);
1246*35238bceSAndroid Build Coastguard Worker     }
1247*35238bceSAndroid Build Coastguard Worker }
1248*35238bceSAndroid Build Coastguard Worker 
rasterizePrimitive(const RenderState & state,const RenderTarget & renderTarget,const Program & program,const pa::Point & point,const tcu::IVec4 & renderTargetRect,RasterizationInternalBuffers & buffers)1249*35238bceSAndroid Build Coastguard Worker void rasterizePrimitive(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1250*35238bceSAndroid Build Coastguard Worker                         const pa::Point &point, const tcu::IVec4 &renderTargetRect,
1251*35238bceSAndroid Build Coastguard Worker                         RasterizationInternalBuffers &buffers)
1252*35238bceSAndroid Build Coastguard Worker {
1253*35238bceSAndroid Build Coastguard Worker     const int numSamples      = renderTarget.getNumSamples();
1254*35238bceSAndroid Build Coastguard Worker     const float depthClampMin = de::min(state.viewport.zn, state.viewport.zf);
1255*35238bceSAndroid Build Coastguard Worker     const float depthClampMax = de::max(state.viewport.zn, state.viewport.zf);
1256*35238bceSAndroid Build Coastguard Worker     TriangleRasterizer rasterizer1(renderTargetRect, numSamples, state.rasterization, state.subpixelBits);
1257*35238bceSAndroid Build Coastguard Worker     TriangleRasterizer rasterizer2(renderTargetRect, numSamples, state.rasterization, state.subpixelBits);
1258*35238bceSAndroid Build Coastguard Worker 
1259*35238bceSAndroid Build Coastguard Worker     // draw point as two triangles
1260*35238bceSAndroid Build Coastguard Worker     const float offset = point.v0->pointSize / 2.0f;
1261*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 w0 = tcu::Vec4(point.v0->position.x() + offset, point.v0->position.y() + offset,
1262*35238bceSAndroid Build Coastguard Worker                                    point.v0->position.z(), point.v0->position.w());
1263*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 w1 = tcu::Vec4(point.v0->position.x() - offset, point.v0->position.y() + offset,
1264*35238bceSAndroid Build Coastguard Worker                                    point.v0->position.z(), point.v0->position.w());
1265*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 w2 = tcu::Vec4(point.v0->position.x() - offset, point.v0->position.y() - offset,
1266*35238bceSAndroid Build Coastguard Worker                                    point.v0->position.z(), point.v0->position.w());
1267*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 w3 = tcu::Vec4(point.v0->position.x() + offset, point.v0->position.y() - offset,
1268*35238bceSAndroid Build Coastguard Worker                                    point.v0->position.z(), point.v0->position.w());
1269*35238bceSAndroid Build Coastguard Worker 
1270*35238bceSAndroid Build Coastguard Worker     rasterizer1.init(w0, w1, w2);
1271*35238bceSAndroid Build Coastguard Worker     rasterizer2.init(w0, w2, w3);
1272*35238bceSAndroid Build Coastguard Worker 
1273*35238bceSAndroid Build Coastguard Worker     // Shading context
1274*35238bceSAndroid Build Coastguard Worker     FragmentShadingContext shadingContext(point.v0->outputs, DE_NULL, DE_NULL, &buffers.shaderOutputs[0],
1275*35238bceSAndroid Build Coastguard Worker                                           &buffers.shaderOutputsSrc1[0], buffers.fragmentDepthBuffer,
1276*35238bceSAndroid Build Coastguard Worker                                           point.v0->primitiveID, (int)program.fragmentShader->getOutputs().size(),
1277*35238bceSAndroid Build Coastguard Worker                                           numSamples, FACETYPE_FRONT);
1278*35238bceSAndroid Build Coastguard Worker 
1279*35238bceSAndroid Build Coastguard Worker     // Execute rasterize - shade - write loop
1280*35238bceSAndroid Build Coastguard Worker     for (;;)
1281*35238bceSAndroid Build Coastguard Worker     {
1282*35238bceSAndroid Build Coastguard Worker         const int maxFragmentPackets = (int)buffers.fragmentPackets.size();
1283*35238bceSAndroid Build Coastguard Worker         int numRasterizedPackets     = 0;
1284*35238bceSAndroid Build Coastguard Worker 
1285*35238bceSAndroid Build Coastguard Worker         // Rasterize both triangles
1286*35238bceSAndroid Build Coastguard Worker 
1287*35238bceSAndroid Build Coastguard Worker         rasterizer1.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets,
1288*35238bceSAndroid Build Coastguard Worker                               numRasterizedPackets);
1289*35238bceSAndroid Build Coastguard Worker         if (numRasterizedPackets != maxFragmentPackets)
1290*35238bceSAndroid Build Coastguard Worker         {
1291*35238bceSAndroid Build Coastguard Worker             float *const depthBufferAppendPointer =
1292*35238bceSAndroid Build Coastguard Worker                 (buffers.fragmentDepthBuffer) ? (buffers.fragmentDepthBuffer + numRasterizedPackets * numSamples * 4) :
1293*35238bceSAndroid Build Coastguard Worker                                                 (DE_NULL);
1294*35238bceSAndroid Build Coastguard Worker             int numRasterizedPackets2 = 0;
1295*35238bceSAndroid Build Coastguard Worker 
1296*35238bceSAndroid Build Coastguard Worker             rasterizer2.rasterize(&buffers.fragmentPackets[numRasterizedPackets], depthBufferAppendPointer,
1297*35238bceSAndroid Build Coastguard Worker                                   maxFragmentPackets - numRasterizedPackets, numRasterizedPackets2);
1298*35238bceSAndroid Build Coastguard Worker 
1299*35238bceSAndroid Build Coastguard Worker             numRasterizedPackets += numRasterizedPackets2;
1300*35238bceSAndroid Build Coastguard Worker         }
1301*35238bceSAndroid Build Coastguard Worker 
1302*35238bceSAndroid Build Coastguard Worker         // numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
1303*35238bceSAndroid Build Coastguard Worker 
1304*35238bceSAndroid Build Coastguard Worker         if (!numRasterizedPackets)
1305*35238bceSAndroid Build Coastguard Worker             break; // Rasterization finished.
1306*35238bceSAndroid Build Coastguard Worker 
1307*35238bceSAndroid Build Coastguard Worker         // Shade
1308*35238bceSAndroid Build Coastguard Worker 
1309*35238bceSAndroid Build Coastguard Worker         program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
1310*35238bceSAndroid Build Coastguard Worker 
1311*35238bceSAndroid Build Coastguard Worker         // Depth clamp
1312*35238bceSAndroid Build Coastguard Worker         if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
1313*35238bceSAndroid Build Coastguard Worker             for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1314*35238bceSAndroid Build Coastguard Worker                 buffers.fragmentDepthBuffer[sampleNdx] =
1315*35238bceSAndroid Build Coastguard Worker                     de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
1316*35238bceSAndroid Build Coastguard Worker 
1317*35238bceSAndroid Build Coastguard Worker         // Handle fragment shader outputs
1318*35238bceSAndroid Build Coastguard Worker 
1319*35238bceSAndroid Build Coastguard Worker         writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets,
1320*35238bceSAndroid Build Coastguard Worker                              rr::FACETYPE_FRONT, buffers.shaderOutputs, buffers.shaderOutputsSrc1,
1321*35238bceSAndroid Build Coastguard Worker                              buffers.fragmentDepthBuffer, buffers.shadedFragments);
1322*35238bceSAndroid Build Coastguard Worker     }
1323*35238bceSAndroid Build Coastguard Worker }
1324*35238bceSAndroid Build Coastguard Worker 
1325*35238bceSAndroid Build Coastguard Worker template <typename ContainerType>
rasterize(const RenderState & state,const RenderTarget & renderTarget,const Program & program,const ContainerType & list)1326*35238bceSAndroid Build Coastguard Worker void rasterize(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1327*35238bceSAndroid Build Coastguard Worker                const ContainerType &list)
1328*35238bceSAndroid Build Coastguard Worker {
1329*35238bceSAndroid Build Coastguard Worker     const int numSamples            = renderTarget.getNumSamples();
1330*35238bceSAndroid Build Coastguard Worker     const int numFragmentOutputs    = (int)program.fragmentShader->getOutputs().size();
1331*35238bceSAndroid Build Coastguard Worker     const size_t maxFragmentPackets = 128;
1332*35238bceSAndroid Build Coastguard Worker 
1333*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 viewportRect     = tcu::IVec4(state.viewport.rect.left, state.viewport.rect.bottom,
1334*35238bceSAndroid Build Coastguard Worker                                                    state.viewport.rect.width, state.viewport.rect.height);
1335*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 bufferRect       = getBufferSize(renderTarget.getColorBuffer(0));
1336*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 renderTargetRect = rectIntersection(viewportRect, bufferRect);
1337*35238bceSAndroid Build Coastguard Worker 
1338*35238bceSAndroid Build Coastguard Worker     // shared buffers for all primitives
1339*35238bceSAndroid Build Coastguard Worker     std::vector<FragmentPacket> fragmentPackets(maxFragmentPackets);
1340*35238bceSAndroid Build Coastguard Worker     std::vector<GenericVec4> shaderOutputs(maxFragmentPackets * 4 * numFragmentOutputs);
1341*35238bceSAndroid Build Coastguard Worker     std::vector<GenericVec4> shaderOutputsSrc1(maxFragmentPackets * 4 * numFragmentOutputs);
1342*35238bceSAndroid Build Coastguard Worker     std::vector<Fragment> shadedFragments(maxFragmentPackets * 4);
1343*35238bceSAndroid Build Coastguard Worker     std::vector<float> depthValues(0);
1344*35238bceSAndroid Build Coastguard Worker     float *depthBufferPointer = DE_NULL;
1345*35238bceSAndroid Build Coastguard Worker 
1346*35238bceSAndroid Build Coastguard Worker     RasterizationInternalBuffers buffers;
1347*35238bceSAndroid Build Coastguard Worker 
1348*35238bceSAndroid Build Coastguard Worker     // calculate depth only if we have a depth buffer
1349*35238bceSAndroid Build Coastguard Worker     if (!isEmpty(renderTarget.getDepthBuffer()))
1350*35238bceSAndroid Build Coastguard Worker     {
1351*35238bceSAndroid Build Coastguard Worker         depthValues.resize(maxFragmentPackets * 4 * numSamples);
1352*35238bceSAndroid Build Coastguard Worker         depthBufferPointer = &depthValues[0];
1353*35238bceSAndroid Build Coastguard Worker     }
1354*35238bceSAndroid Build Coastguard Worker 
1355*35238bceSAndroid Build Coastguard Worker     // set buffers
1356*35238bceSAndroid Build Coastguard Worker     buffers.fragmentPackets.swap(fragmentPackets);
1357*35238bceSAndroid Build Coastguard Worker     buffers.shaderOutputs.swap(shaderOutputs);
1358*35238bceSAndroid Build Coastguard Worker     buffers.shaderOutputsSrc1.swap(shaderOutputsSrc1);
1359*35238bceSAndroid Build Coastguard Worker     buffers.shadedFragments.swap(shadedFragments);
1360*35238bceSAndroid Build Coastguard Worker     buffers.fragmentDepthBuffer = depthBufferPointer;
1361*35238bceSAndroid Build Coastguard Worker 
1362*35238bceSAndroid Build Coastguard Worker     // rasterize
1363*35238bceSAndroid Build Coastguard Worker     for (typename ContainerType::const_iterator it = list.begin(); it != list.end(); ++it)
1364*35238bceSAndroid Build Coastguard Worker         rasterizePrimitive(state, renderTarget, program, *it, renderTargetRect, buffers);
1365*35238bceSAndroid Build Coastguard Worker }
1366*35238bceSAndroid Build Coastguard Worker 
1367*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1368*35238bceSAndroid Build Coastguard Worker  * Draws transformed triangles, lines or points to render target
1369*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
1370*35238bceSAndroid Build Coastguard Worker template <typename ContainerType>
drawBasicPrimitives(const RenderState & state,const RenderTarget & renderTarget,const Program & program,ContainerType & primList,VertexPacketAllocator & vpalloc)1371*35238bceSAndroid Build Coastguard Worker void drawBasicPrimitives(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1372*35238bceSAndroid Build Coastguard Worker                          ContainerType &primList, VertexPacketAllocator &vpalloc)
1373*35238bceSAndroid Build Coastguard Worker {
1374*35238bceSAndroid Build Coastguard Worker     const bool clipZ = !state.fragOps.depthClampEnabled;
1375*35238bceSAndroid Build Coastguard Worker 
1376*35238bceSAndroid Build Coastguard Worker     // Transform feedback
1377*35238bceSAndroid Build Coastguard Worker 
1378*35238bceSAndroid Build Coastguard Worker     // Flatshading
1379*35238bceSAndroid Build Coastguard Worker     flatshadeVertices(program, primList);
1380*35238bceSAndroid Build Coastguard Worker 
1381*35238bceSAndroid Build Coastguard Worker     // Clipping
1382*35238bceSAndroid Build Coastguard Worker     // \todo [jarkko] is creating & swapping std::vectors really a good solution?
1383*35238bceSAndroid Build Coastguard Worker     clipPrimitives(primList, program, clipZ, vpalloc);
1384*35238bceSAndroid Build Coastguard Worker 
1385*35238bceSAndroid Build Coastguard Worker     // Transform vertices to window coords
1386*35238bceSAndroid Build Coastguard Worker     transformClipCoordsToWindowCoords(state, primList);
1387*35238bceSAndroid Build Coastguard Worker 
1388*35238bceSAndroid Build Coastguard Worker     // Rasterize and paint
1389*35238bceSAndroid Build Coastguard Worker     rasterize(state, renderTarget, program, primList);
1390*35238bceSAndroid Build Coastguard Worker }
1391*35238bceSAndroid Build Coastguard Worker 
copyVertexPacketPointers(const VertexPacket ** dst,const pa::Point & in)1392*35238bceSAndroid Build Coastguard Worker void copyVertexPacketPointers(const VertexPacket **dst, const pa::Point &in)
1393*35238bceSAndroid Build Coastguard Worker {
1394*35238bceSAndroid Build Coastguard Worker     dst[0] = in.v0;
1395*35238bceSAndroid Build Coastguard Worker }
1396*35238bceSAndroid Build Coastguard Worker 
copyVertexPacketPointers(const VertexPacket ** dst,const pa::Line & in)1397*35238bceSAndroid Build Coastguard Worker void copyVertexPacketPointers(const VertexPacket **dst, const pa::Line &in)
1398*35238bceSAndroid Build Coastguard Worker {
1399*35238bceSAndroid Build Coastguard Worker     dst[0] = in.v0;
1400*35238bceSAndroid Build Coastguard Worker     dst[1] = in.v1;
1401*35238bceSAndroid Build Coastguard Worker }
1402*35238bceSAndroid Build Coastguard Worker 
copyVertexPacketPointers(const VertexPacket ** dst,const pa::Triangle & in)1403*35238bceSAndroid Build Coastguard Worker void copyVertexPacketPointers(const VertexPacket **dst, const pa::Triangle &in)
1404*35238bceSAndroid Build Coastguard Worker {
1405*35238bceSAndroid Build Coastguard Worker     dst[0] = in.v0;
1406*35238bceSAndroid Build Coastguard Worker     dst[1] = in.v1;
1407*35238bceSAndroid Build Coastguard Worker     dst[2] = in.v2;
1408*35238bceSAndroid Build Coastguard Worker }
1409*35238bceSAndroid Build Coastguard Worker 
copyVertexPacketPointers(const VertexPacket ** dst,const pa::LineAdjacency & in)1410*35238bceSAndroid Build Coastguard Worker void copyVertexPacketPointers(const VertexPacket **dst, const pa::LineAdjacency &in)
1411*35238bceSAndroid Build Coastguard Worker {
1412*35238bceSAndroid Build Coastguard Worker     dst[0] = in.v0;
1413*35238bceSAndroid Build Coastguard Worker     dst[1] = in.v1;
1414*35238bceSAndroid Build Coastguard Worker     dst[2] = in.v2;
1415*35238bceSAndroid Build Coastguard Worker     dst[3] = in.v3;
1416*35238bceSAndroid Build Coastguard Worker }
1417*35238bceSAndroid Build Coastguard Worker 
copyVertexPacketPointers(const VertexPacket ** dst,const pa::TriangleAdjacency & in)1418*35238bceSAndroid Build Coastguard Worker void copyVertexPacketPointers(const VertexPacket **dst, const pa::TriangleAdjacency &in)
1419*35238bceSAndroid Build Coastguard Worker {
1420*35238bceSAndroid Build Coastguard Worker     dst[0] = in.v0;
1421*35238bceSAndroid Build Coastguard Worker     dst[1] = in.v1;
1422*35238bceSAndroid Build Coastguard Worker     dst[2] = in.v2;
1423*35238bceSAndroid Build Coastguard Worker     dst[3] = in.v3;
1424*35238bceSAndroid Build Coastguard Worker     dst[4] = in.v4;
1425*35238bceSAndroid Build Coastguard Worker     dst[5] = in.v5;
1426*35238bceSAndroid Build Coastguard Worker }
1427*35238bceSAndroid Build Coastguard Worker 
1428*35238bceSAndroid Build Coastguard Worker template <PrimitiveType DrawPrimitiveType> // \note DrawPrimitiveType  can only be Points, line_strip, or triangle_strip
drawGeometryShaderOutputAsPrimitives(const RenderState & state,const RenderTarget & renderTarget,const Program & program,VertexPacket * const * vertices,size_t numVertices,VertexPacketAllocator & vpalloc)1429*35238bceSAndroid Build Coastguard Worker void drawGeometryShaderOutputAsPrimitives(const RenderState &state, const RenderTarget &renderTarget,
1430*35238bceSAndroid Build Coastguard Worker                                           const Program &program, VertexPacket *const *vertices, size_t numVertices,
1431*35238bceSAndroid Build Coastguard Worker                                           VertexPacketAllocator &vpalloc)
1432*35238bceSAndroid Build Coastguard Worker {
1433*35238bceSAndroid Build Coastguard Worker     // Run primitive assembly for generated stream
1434*35238bceSAndroid Build Coastguard Worker 
1435*35238bceSAndroid Build Coastguard Worker     const size_t assemblerPrimitiveCount =
1436*35238bceSAndroid Build Coastguard Worker         PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::getPrimitiveCount(numVertices);
1437*35238bceSAndroid Build Coastguard Worker     std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::BaseType> inputPrimitives(assemblerPrimitiveCount);
1438*35238bceSAndroid Build Coastguard Worker 
1439*35238bceSAndroid Build Coastguard Worker     PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::exec(
1440*35238bceSAndroid Build Coastguard Worker         inputPrimitives.begin(), vertices, numVertices,
1441*35238bceSAndroid Build Coastguard Worker         state
1442*35238bceSAndroid Build Coastguard Worker             .provokingVertexConvention); // \note input Primitives are baseType_t => only basic primitives (non adjacency) will compile
1443*35238bceSAndroid Build Coastguard Worker 
1444*35238bceSAndroid Build Coastguard Worker     // Make shared vertices distinct
1445*35238bceSAndroid Build Coastguard Worker 
1446*35238bceSAndroid Build Coastguard Worker     makeSharedVerticesDistinct(inputPrimitives, vpalloc);
1447*35238bceSAndroid Build Coastguard Worker 
1448*35238bceSAndroid Build Coastguard Worker     // Draw assembled primitives
1449*35238bceSAndroid Build Coastguard Worker 
1450*35238bceSAndroid Build Coastguard Worker     drawBasicPrimitives(state, renderTarget, program, inputPrimitives, vpalloc);
1451*35238bceSAndroid Build Coastguard Worker }
1452*35238bceSAndroid Build Coastguard Worker 
1453*35238bceSAndroid Build Coastguard Worker template <PrimitiveType DrawPrimitiveType>
drawWithGeometryShader(const RenderState & state,const RenderTarget & renderTarget,const Program & program,std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type> & input,DrawContext & drawContext)1454*35238bceSAndroid Build Coastguard Worker void drawWithGeometryShader(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1455*35238bceSAndroid Build Coastguard Worker                             std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type> &input,
1456*35238bceSAndroid Build Coastguard Worker                             DrawContext &drawContext)
1457*35238bceSAndroid Build Coastguard Worker {
1458*35238bceSAndroid Build Coastguard Worker     // Vertices outputted by geometry shader may have different number of output variables than the original, create new memory allocator
1459*35238bceSAndroid Build Coastguard Worker     VertexPacketAllocator vpalloc(program.geometryShader->getOutputs().size());
1460*35238bceSAndroid Build Coastguard Worker 
1461*35238bceSAndroid Build Coastguard Worker     // Run geometry shader for all primitives
1462*35238bceSAndroid Build Coastguard Worker     GeometryEmitter emitter(vpalloc, program.geometryShader->getNumVerticesOut());
1463*35238bceSAndroid Build Coastguard Worker     std::vector<PrimitivePacket> primitives(input.size());
1464*35238bceSAndroid Build Coastguard Worker     const int numInvocations = (int)program.geometryShader->getNumInvocations();
1465*35238bceSAndroid Build Coastguard Worker     const int verticesIn     = PrimitiveTypeTraits<DrawPrimitiveType>::Type::NUM_VERTICES;
1466*35238bceSAndroid Build Coastguard Worker 
1467*35238bceSAndroid Build Coastguard Worker     for (size_t primitiveNdx = 0; primitiveNdx < input.size(); ++primitiveNdx)
1468*35238bceSAndroid Build Coastguard Worker     {
1469*35238bceSAndroid Build Coastguard Worker         primitives[primitiveNdx].primitiveIDIn = drawContext.primitiveID++;
1470*35238bceSAndroid Build Coastguard Worker         copyVertexPacketPointers(primitives[primitiveNdx].vertices, input[primitiveNdx]);
1471*35238bceSAndroid Build Coastguard Worker     }
1472*35238bceSAndroid Build Coastguard Worker 
1473*35238bceSAndroid Build Coastguard Worker     if (primitives.empty())
1474*35238bceSAndroid Build Coastguard Worker         return;
1475*35238bceSAndroid Build Coastguard Worker 
1476*35238bceSAndroid Build Coastguard Worker     for (int invocationNdx = 0; invocationNdx < numInvocations; ++invocationNdx)
1477*35238bceSAndroid Build Coastguard Worker     {
1478*35238bceSAndroid Build Coastguard Worker         // Shading invocation
1479*35238bceSAndroid Build Coastguard Worker 
1480*35238bceSAndroid Build Coastguard Worker         program.geometryShader->shadePrimitives(emitter, verticesIn, &primitives[0], (int)primitives.size(),
1481*35238bceSAndroid Build Coastguard Worker                                                 invocationNdx);
1482*35238bceSAndroid Build Coastguard Worker 
1483*35238bceSAndroid Build Coastguard Worker         // Find primitives in the emitted vertices
1484*35238bceSAndroid Build Coastguard Worker 
1485*35238bceSAndroid Build Coastguard Worker         std::vector<VertexPacket *> emitted;
1486*35238bceSAndroid Build Coastguard Worker         emitter.moveEmittedTo(emitted);
1487*35238bceSAndroid Build Coastguard Worker 
1488*35238bceSAndroid Build Coastguard Worker         for (size_t primitiveBegin = 0; primitiveBegin < emitted.size();)
1489*35238bceSAndroid Build Coastguard Worker         {
1490*35238bceSAndroid Build Coastguard Worker             size_t primitiveEnd;
1491*35238bceSAndroid Build Coastguard Worker 
1492*35238bceSAndroid Build Coastguard Worker             // Find primitive begin
1493*35238bceSAndroid Build Coastguard Worker             if (!emitted[primitiveBegin])
1494*35238bceSAndroid Build Coastguard Worker             {
1495*35238bceSAndroid Build Coastguard Worker                 ++primitiveBegin;
1496*35238bceSAndroid Build Coastguard Worker                 continue;
1497*35238bceSAndroid Build Coastguard Worker             }
1498*35238bceSAndroid Build Coastguard Worker 
1499*35238bceSAndroid Build Coastguard Worker             // Find primitive end
1500*35238bceSAndroid Build Coastguard Worker 
1501*35238bceSAndroid Build Coastguard Worker             primitiveEnd = primitiveBegin + 1;
1502*35238bceSAndroid Build Coastguard Worker             for (; (primitiveEnd < emitted.size()) && emitted[primitiveEnd]; ++primitiveEnd)
1503*35238bceSAndroid Build Coastguard Worker                 ; // find primitive end
1504*35238bceSAndroid Build Coastguard Worker 
1505*35238bceSAndroid Build Coastguard Worker             // Draw range [begin, end)
1506*35238bceSAndroid Build Coastguard Worker 
1507*35238bceSAndroid Build Coastguard Worker             switch (program.geometryShader->getOutputType())
1508*35238bceSAndroid Build Coastguard Worker             {
1509*35238bceSAndroid Build Coastguard Worker             case rr::GEOMETRYSHADEROUTPUTTYPE_POINTS:
1510*35238bceSAndroid Build Coastguard Worker                 drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_POINTS>(
1511*35238bceSAndroid Build Coastguard Worker                     state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd - primitiveBegin, vpalloc);
1512*35238bceSAndroid Build Coastguard Worker                 break;
1513*35238bceSAndroid Build Coastguard Worker             case rr::GEOMETRYSHADEROUTPUTTYPE_LINE_STRIP:
1514*35238bceSAndroid Build Coastguard Worker                 drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_LINE_STRIP>(
1515*35238bceSAndroid Build Coastguard Worker                     state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd - primitiveBegin, vpalloc);
1516*35238bceSAndroid Build Coastguard Worker                 break;
1517*35238bceSAndroid Build Coastguard Worker             case rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP:
1518*35238bceSAndroid Build Coastguard Worker                 drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP>(
1519*35238bceSAndroid Build Coastguard Worker                     state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd - primitiveBegin, vpalloc);
1520*35238bceSAndroid Build Coastguard Worker                 break;
1521*35238bceSAndroid Build Coastguard Worker             default:
1522*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
1523*35238bceSAndroid Build Coastguard Worker             }
1524*35238bceSAndroid Build Coastguard Worker 
1525*35238bceSAndroid Build Coastguard Worker             // Next primitive
1526*35238bceSAndroid Build Coastguard Worker             primitiveBegin = primitiveEnd + 1;
1527*35238bceSAndroid Build Coastguard Worker         }
1528*35238bceSAndroid Build Coastguard Worker     }
1529*35238bceSAndroid Build Coastguard Worker }
1530*35238bceSAndroid Build Coastguard Worker 
1531*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
1532*35238bceSAndroid Build Coastguard Worker  * Assembles, tesselates, runs geometry shader and draws primitives of any type from vertex list.
1533*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
1534*35238bceSAndroid Build Coastguard Worker template <PrimitiveType DrawPrimitiveType>
drawAsPrimitives(const RenderState & state,const RenderTarget & renderTarget,const Program & program,VertexPacket * const * vertices,int numVertices,DrawContext & drawContext,VertexPacketAllocator & vpalloc)1535*35238bceSAndroid Build Coastguard Worker void drawAsPrimitives(const RenderState &state, const RenderTarget &renderTarget, const Program &program,
1536*35238bceSAndroid Build Coastguard Worker                       VertexPacket *const *vertices, int numVertices, DrawContext &drawContext,
1537*35238bceSAndroid Build Coastguard Worker                       VertexPacketAllocator &vpalloc)
1538*35238bceSAndroid Build Coastguard Worker {
1539*35238bceSAndroid Build Coastguard Worker     // Assemble primitives (deconstruct stips & loops)
1540*35238bceSAndroid Build Coastguard Worker     const size_t assemblerPrimitiveCount =
1541*35238bceSAndroid Build Coastguard Worker         PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::getPrimitiveCount(numVertices);
1542*35238bceSAndroid Build Coastguard Worker     std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type> inputPrimitives(assemblerPrimitiveCount);
1543*35238bceSAndroid Build Coastguard Worker 
1544*35238bceSAndroid Build Coastguard Worker     PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::exec(inputPrimitives.begin(), vertices, (size_t)numVertices,
1545*35238bceSAndroid Build Coastguard Worker                                                             state.provokingVertexConvention);
1546*35238bceSAndroid Build Coastguard Worker 
1547*35238bceSAndroid Build Coastguard Worker     // Tesselate
1548*35238bceSAndroid Build Coastguard Worker     //if (state.tesselation)
1549*35238bceSAndroid Build Coastguard Worker     // primList = state.tesselation.exec(primList);
1550*35238bceSAndroid Build Coastguard Worker 
1551*35238bceSAndroid Build Coastguard Worker     // Geometry shader
1552*35238bceSAndroid Build Coastguard Worker     if (program.geometryShader)
1553*35238bceSAndroid Build Coastguard Worker     {
1554*35238bceSAndroid Build Coastguard Worker         // If there is an active geometry shader, it will convert any primitive type to basic types
1555*35238bceSAndroid Build Coastguard Worker         drawWithGeometryShader<DrawPrimitiveType>(state, renderTarget, program, inputPrimitives, drawContext);
1556*35238bceSAndroid Build Coastguard Worker     }
1557*35238bceSAndroid Build Coastguard Worker     else
1558*35238bceSAndroid Build Coastguard Worker     {
1559*35238bceSAndroid Build Coastguard Worker         std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::BaseType> basePrimitives;
1560*35238bceSAndroid Build Coastguard Worker 
1561*35238bceSAndroid Build Coastguard Worker         // convert types from X_adjacency to X
1562*35238bceSAndroid Build Coastguard Worker         convertPrimitiveToBaseType(basePrimitives, inputPrimitives);
1563*35238bceSAndroid Build Coastguard Worker 
1564*35238bceSAndroid Build Coastguard Worker         // Make shared vertices distinct. Needed for that the translation to screen space happens only once per vertex, and for flatshading
1565*35238bceSAndroid Build Coastguard Worker         makeSharedVerticesDistinct(basePrimitives, vpalloc);
1566*35238bceSAndroid Build Coastguard Worker 
1567*35238bceSAndroid Build Coastguard Worker         // A primitive ID will be generated even if no geometry shader is active
1568*35238bceSAndroid Build Coastguard Worker         generatePrimitiveIDs(basePrimitives, drawContext);
1569*35238bceSAndroid Build Coastguard Worker 
1570*35238bceSAndroid Build Coastguard Worker         // Draw as a basic type
1571*35238bceSAndroid Build Coastguard Worker         drawBasicPrimitives(state, renderTarget, program, basePrimitives, vpalloc);
1572*35238bceSAndroid Build Coastguard Worker     }
1573*35238bceSAndroid Build Coastguard Worker }
1574*35238bceSAndroid Build Coastguard Worker 
isValidCommand(const DrawCommand & command,int numInstances)1575*35238bceSAndroid Build Coastguard Worker bool isValidCommand(const DrawCommand &command, int numInstances)
1576*35238bceSAndroid Build Coastguard Worker {
1577*35238bceSAndroid Build Coastguard Worker     // numInstances should be valid
1578*35238bceSAndroid Build Coastguard Worker     if (numInstances < 0)
1579*35238bceSAndroid Build Coastguard Worker         return false;
1580*35238bceSAndroid Build Coastguard Worker 
1581*35238bceSAndroid Build Coastguard Worker     // Shaders should have the same varyings
1582*35238bceSAndroid Build Coastguard Worker     if (command.program.geometryShader)
1583*35238bceSAndroid Build Coastguard Worker     {
1584*35238bceSAndroid Build Coastguard Worker         if (command.program.vertexShader->getOutputs() != command.program.geometryShader->getInputs())
1585*35238bceSAndroid Build Coastguard Worker             return false;
1586*35238bceSAndroid Build Coastguard Worker 
1587*35238bceSAndroid Build Coastguard Worker         if (command.program.geometryShader->getOutputs() != command.program.fragmentShader->getInputs())
1588*35238bceSAndroid Build Coastguard Worker             return false;
1589*35238bceSAndroid Build Coastguard Worker     }
1590*35238bceSAndroid Build Coastguard Worker     else
1591*35238bceSAndroid Build Coastguard Worker     {
1592*35238bceSAndroid Build Coastguard Worker         if (command.program.vertexShader->getOutputs() != command.program.fragmentShader->getInputs())
1593*35238bceSAndroid Build Coastguard Worker             return false;
1594*35238bceSAndroid Build Coastguard Worker     }
1595*35238bceSAndroid Build Coastguard Worker 
1596*35238bceSAndroid Build Coastguard Worker     // Shader input/output types are set
1597*35238bceSAndroid Build Coastguard Worker     for (size_t varyingNdx = 0; varyingNdx < command.program.vertexShader->getInputs().size(); ++varyingNdx)
1598*35238bceSAndroid Build Coastguard Worker         if (command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1599*35238bceSAndroid Build Coastguard Worker             command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1600*35238bceSAndroid Build Coastguard Worker             command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1601*35238bceSAndroid Build Coastguard Worker             return false;
1602*35238bceSAndroid Build Coastguard Worker     for (size_t varyingNdx = 0; varyingNdx < command.program.vertexShader->getOutputs().size(); ++varyingNdx)
1603*35238bceSAndroid Build Coastguard Worker         if (command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1604*35238bceSAndroid Build Coastguard Worker             command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1605*35238bceSAndroid Build Coastguard Worker             command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1606*35238bceSAndroid Build Coastguard Worker             return false;
1607*35238bceSAndroid Build Coastguard Worker 
1608*35238bceSAndroid Build Coastguard Worker     for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getInputs().size(); ++varyingNdx)
1609*35238bceSAndroid Build Coastguard Worker         if (command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1610*35238bceSAndroid Build Coastguard Worker             command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1611*35238bceSAndroid Build Coastguard Worker             command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1612*35238bceSAndroid Build Coastguard Worker             return false;
1613*35238bceSAndroid Build Coastguard Worker     for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getOutputs().size(); ++varyingNdx)
1614*35238bceSAndroid Build Coastguard Worker         if (command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1615*35238bceSAndroid Build Coastguard Worker             command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1616*35238bceSAndroid Build Coastguard Worker             command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1617*35238bceSAndroid Build Coastguard Worker             return false;
1618*35238bceSAndroid Build Coastguard Worker 
1619*35238bceSAndroid Build Coastguard Worker     if (command.program.geometryShader)
1620*35238bceSAndroid Build Coastguard Worker     {
1621*35238bceSAndroid Build Coastguard Worker         for (size_t varyingNdx = 0; varyingNdx < command.program.geometryShader->getInputs().size(); ++varyingNdx)
1622*35238bceSAndroid Build Coastguard Worker             if (command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1623*35238bceSAndroid Build Coastguard Worker                 command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1624*35238bceSAndroid Build Coastguard Worker                 command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1625*35238bceSAndroid Build Coastguard Worker                 return false;
1626*35238bceSAndroid Build Coastguard Worker         for (size_t varyingNdx = 0; varyingNdx < command.program.geometryShader->getOutputs().size(); ++varyingNdx)
1627*35238bceSAndroid Build Coastguard Worker             if (command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1628*35238bceSAndroid Build Coastguard Worker                 command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1629*35238bceSAndroid Build Coastguard Worker                 command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1630*35238bceSAndroid Build Coastguard Worker                 return false;
1631*35238bceSAndroid Build Coastguard Worker     }
1632*35238bceSAndroid Build Coastguard Worker 
1633*35238bceSAndroid Build Coastguard Worker     // Enough vertex inputs?
1634*35238bceSAndroid Build Coastguard Worker     if ((size_t)command.numVertexAttribs < command.program.vertexShader->getInputs().size())
1635*35238bceSAndroid Build Coastguard Worker         return false;
1636*35238bceSAndroid Build Coastguard Worker 
1637*35238bceSAndroid Build Coastguard Worker     // There is a fragment output sink for each output?
1638*35238bceSAndroid Build Coastguard Worker     if ((size_t)command.renderTarget.getNumColorBuffers() < command.program.fragmentShader->getOutputs().size())
1639*35238bceSAndroid Build Coastguard Worker         return false;
1640*35238bceSAndroid Build Coastguard Worker 
1641*35238bceSAndroid Build Coastguard Worker     // All destination buffers should have same number of samples and same size
1642*35238bceSAndroid Build Coastguard Worker     for (int outputNdx = 0; outputNdx < command.renderTarget.getNumColorBuffers(); ++outputNdx)
1643*35238bceSAndroid Build Coastguard Worker     {
1644*35238bceSAndroid Build Coastguard Worker         if (getBufferSize(command.renderTarget.getColorBuffer(0)) !=
1645*35238bceSAndroid Build Coastguard Worker             getBufferSize(command.renderTarget.getColorBuffer(outputNdx)))
1646*35238bceSAndroid Build Coastguard Worker             return false;
1647*35238bceSAndroid Build Coastguard Worker 
1648*35238bceSAndroid Build Coastguard Worker         if (command.renderTarget.getNumSamples() != command.renderTarget.getColorBuffer(outputNdx).getNumSamples())
1649*35238bceSAndroid Build Coastguard Worker             return false;
1650*35238bceSAndroid Build Coastguard Worker     }
1651*35238bceSAndroid Build Coastguard Worker 
1652*35238bceSAndroid Build Coastguard Worker     // All destination buffers should have same basic type as matching fragment output
1653*35238bceSAndroid Build Coastguard Worker     for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getOutputs().size(); ++varyingNdx)
1654*35238bceSAndroid Build Coastguard Worker     {
1655*35238bceSAndroid Build Coastguard Worker         const tcu::TextureChannelClass colorbufferClass =
1656*35238bceSAndroid Build Coastguard Worker             tcu::getTextureChannelClass(command.renderTarget.getColorBuffer((int)varyingNdx).raw().getFormat().type);
1657*35238bceSAndroid Build Coastguard Worker         const GenericVecType colorType =
1658*35238bceSAndroid Build Coastguard Worker             (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ?
1659*35238bceSAndroid Build Coastguard Worker                 (rr::GENERICVECTYPE_INT32) :
1660*35238bceSAndroid Build Coastguard Worker                 ((colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (rr::GENERICVECTYPE_UINT32) :
1661*35238bceSAndroid Build Coastguard Worker                                                                                    (rr::GENERICVECTYPE_FLOAT));
1662*35238bceSAndroid Build Coastguard Worker 
1663*35238bceSAndroid Build Coastguard Worker         if (command.program.fragmentShader->getOutputs()[varyingNdx].type != colorType)
1664*35238bceSAndroid Build Coastguard Worker             return false;
1665*35238bceSAndroid Build Coastguard Worker     }
1666*35238bceSAndroid Build Coastguard Worker 
1667*35238bceSAndroid Build Coastguard Worker     // Integer values are flatshaded
1668*35238bceSAndroid Build Coastguard Worker     for (size_t outputNdx = 0; outputNdx < command.program.vertexShader->getOutputs().size(); ++outputNdx)
1669*35238bceSAndroid Build Coastguard Worker     {
1670*35238bceSAndroid Build Coastguard Worker         if (!command.program.vertexShader->getOutputs()[outputNdx].flatshade &&
1671*35238bceSAndroid Build Coastguard Worker             (command.program.vertexShader->getOutputs()[outputNdx].type == GENERICVECTYPE_INT32 ||
1672*35238bceSAndroid Build Coastguard Worker              command.program.vertexShader->getOutputs()[outputNdx].type == GENERICVECTYPE_UINT32))
1673*35238bceSAndroid Build Coastguard Worker             return false;
1674*35238bceSAndroid Build Coastguard Worker     }
1675*35238bceSAndroid Build Coastguard Worker     if (command.program.geometryShader)
1676*35238bceSAndroid Build Coastguard Worker         for (size_t outputNdx = 0; outputNdx < command.program.geometryShader->getOutputs().size(); ++outputNdx)
1677*35238bceSAndroid Build Coastguard Worker         {
1678*35238bceSAndroid Build Coastguard Worker             if (!command.program.geometryShader->getOutputs()[outputNdx].flatshade &&
1679*35238bceSAndroid Build Coastguard Worker                 (command.program.geometryShader->getOutputs()[outputNdx].type == GENERICVECTYPE_INT32 ||
1680*35238bceSAndroid Build Coastguard Worker                  command.program.geometryShader->getOutputs()[outputNdx].type == GENERICVECTYPE_UINT32))
1681*35238bceSAndroid Build Coastguard Worker                 return false;
1682*35238bceSAndroid Build Coastguard Worker         }
1683*35238bceSAndroid Build Coastguard Worker 
1684*35238bceSAndroid Build Coastguard Worker     // Draw primitive is valid for geometry shader
1685*35238bceSAndroid Build Coastguard Worker     if (command.program.geometryShader)
1686*35238bceSAndroid Build Coastguard Worker     {
1687*35238bceSAndroid Build Coastguard Worker         if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS &&
1688*35238bceSAndroid Build Coastguard Worker             command.primitives.getPrimitiveType() != PRIMITIVETYPE_POINTS)
1689*35238bceSAndroid Build Coastguard Worker             return false;
1690*35238bceSAndroid Build Coastguard Worker 
1691*35238bceSAndroid Build Coastguard Worker         if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
1692*35238bceSAndroid Build Coastguard Worker             (command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINES &&
1693*35238bceSAndroid Build Coastguard Worker              command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_STRIP &&
1694*35238bceSAndroid Build Coastguard Worker              command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_LOOP))
1695*35238bceSAndroid Build Coastguard Worker             return false;
1696*35238bceSAndroid Build Coastguard Worker 
1697*35238bceSAndroid Build Coastguard Worker         if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
1698*35238bceSAndroid Build Coastguard Worker             (command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLES &&
1699*35238bceSAndroid Build Coastguard Worker              command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_STRIP &&
1700*35238bceSAndroid Build Coastguard Worker              command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_FAN))
1701*35238bceSAndroid Build Coastguard Worker             return false;
1702*35238bceSAndroid Build Coastguard Worker 
1703*35238bceSAndroid Build Coastguard Worker         if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
1704*35238bceSAndroid Build Coastguard Worker             (command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINES_ADJACENCY &&
1705*35238bceSAndroid Build Coastguard Worker              command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_STRIP_ADJACENCY))
1706*35238bceSAndroid Build Coastguard Worker             return false;
1707*35238bceSAndroid Build Coastguard Worker 
1708*35238bceSAndroid Build Coastguard Worker         if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
1709*35238bceSAndroid Build Coastguard Worker             (command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLES_ADJACENCY &&
1710*35238bceSAndroid Build Coastguard Worker              command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY))
1711*35238bceSAndroid Build Coastguard Worker             return false;
1712*35238bceSAndroid Build Coastguard Worker     }
1713*35238bceSAndroid Build Coastguard Worker 
1714*35238bceSAndroid Build Coastguard Worker     return true;
1715*35238bceSAndroid Build Coastguard Worker }
1716*35238bceSAndroid Build Coastguard Worker 
1717*35238bceSAndroid Build Coastguard Worker } // namespace
1718*35238bceSAndroid Build Coastguard Worker 
RenderTarget(const MultisamplePixelBufferAccess & colorMultisampleBuffer,const MultisamplePixelBufferAccess & depthMultisampleBuffer,const MultisamplePixelBufferAccess & stencilMultisampleBuffer)1719*35238bceSAndroid Build Coastguard Worker RenderTarget::RenderTarget(const MultisamplePixelBufferAccess &colorMultisampleBuffer,
1720*35238bceSAndroid Build Coastguard Worker                            const MultisamplePixelBufferAccess &depthMultisampleBuffer,
1721*35238bceSAndroid Build Coastguard Worker                            const MultisamplePixelBufferAccess &stencilMultisampleBuffer)
1722*35238bceSAndroid Build Coastguard Worker     : m_numColorBuffers(1)
1723*35238bceSAndroid Build Coastguard Worker     , m_depthBuffer(MultisamplePixelBufferAccess::fromMultisampleAccess(
1724*35238bceSAndroid Build Coastguard Worker           tcu::getEffectiveDepthStencilAccess(depthMultisampleBuffer.raw(), tcu::Sampler::MODE_DEPTH)))
1725*35238bceSAndroid Build Coastguard Worker     , m_stencilBuffer(MultisamplePixelBufferAccess::fromMultisampleAccess(
1726*35238bceSAndroid Build Coastguard Worker           tcu::getEffectiveDepthStencilAccess(stencilMultisampleBuffer.raw(), tcu::Sampler::MODE_STENCIL)))
1727*35238bceSAndroid Build Coastguard Worker {
1728*35238bceSAndroid Build Coastguard Worker     m_colorBuffers[0] = colorMultisampleBuffer;
1729*35238bceSAndroid Build Coastguard Worker }
1730*35238bceSAndroid Build Coastguard Worker 
getNumSamples(void) const1731*35238bceSAndroid Build Coastguard Worker int RenderTarget::getNumSamples(void) const
1732*35238bceSAndroid Build Coastguard Worker {
1733*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_numColorBuffers > 0);
1734*35238bceSAndroid Build Coastguard Worker     return m_colorBuffers[0].getNumSamples();
1735*35238bceSAndroid Build Coastguard Worker }
1736*35238bceSAndroid Build Coastguard Worker 
DrawIndices(const uint32_t * ptr,int baseVertex_)1737*35238bceSAndroid Build Coastguard Worker DrawIndices::DrawIndices(const uint32_t *ptr, int baseVertex_)
1738*35238bceSAndroid Build Coastguard Worker     : indices(ptr)
1739*35238bceSAndroid Build Coastguard Worker     , indexType(INDEXTYPE_UINT32)
1740*35238bceSAndroid Build Coastguard Worker     , baseVertex(baseVertex_)
1741*35238bceSAndroid Build Coastguard Worker {
1742*35238bceSAndroid Build Coastguard Worker }
1743*35238bceSAndroid Build Coastguard Worker 
DrawIndices(const uint16_t * ptr,int baseVertex_)1744*35238bceSAndroid Build Coastguard Worker DrawIndices::DrawIndices(const uint16_t *ptr, int baseVertex_)
1745*35238bceSAndroid Build Coastguard Worker     : indices(ptr)
1746*35238bceSAndroid Build Coastguard Worker     , indexType(INDEXTYPE_UINT16)
1747*35238bceSAndroid Build Coastguard Worker     , baseVertex(baseVertex_)
1748*35238bceSAndroid Build Coastguard Worker {
1749*35238bceSAndroid Build Coastguard Worker }
1750*35238bceSAndroid Build Coastguard Worker 
DrawIndices(const uint8_t * ptr,int baseVertex_)1751*35238bceSAndroid Build Coastguard Worker DrawIndices::DrawIndices(const uint8_t *ptr, int baseVertex_)
1752*35238bceSAndroid Build Coastguard Worker     : indices(ptr)
1753*35238bceSAndroid Build Coastguard Worker     , indexType(INDEXTYPE_UINT8)
1754*35238bceSAndroid Build Coastguard Worker     , baseVertex(baseVertex_)
1755*35238bceSAndroid Build Coastguard Worker {
1756*35238bceSAndroid Build Coastguard Worker }
1757*35238bceSAndroid Build Coastguard Worker 
DrawIndices(const void * ptr,IndexType type,int baseVertex_)1758*35238bceSAndroid Build Coastguard Worker DrawIndices::DrawIndices(const void *ptr, IndexType type, int baseVertex_)
1759*35238bceSAndroid Build Coastguard Worker     : indices(ptr)
1760*35238bceSAndroid Build Coastguard Worker     , indexType(type)
1761*35238bceSAndroid Build Coastguard Worker     , baseVertex(baseVertex_)
1762*35238bceSAndroid Build Coastguard Worker {
1763*35238bceSAndroid Build Coastguard Worker }
1764*35238bceSAndroid Build Coastguard Worker 
PrimitiveList(PrimitiveType primitiveType,int numElements,const int firstElement)1765*35238bceSAndroid Build Coastguard Worker PrimitiveList::PrimitiveList(PrimitiveType primitiveType, int numElements, const int firstElement)
1766*35238bceSAndroid Build Coastguard Worker     : m_primitiveType(primitiveType)
1767*35238bceSAndroid Build Coastguard Worker     , m_numElements(numElements)
1768*35238bceSAndroid Build Coastguard Worker     , m_indices(DE_NULL)
1769*35238bceSAndroid Build Coastguard Worker     , m_indexType(INDEXTYPE_LAST)
1770*35238bceSAndroid Build Coastguard Worker     , m_baseVertex(firstElement)
1771*35238bceSAndroid Build Coastguard Worker {
1772*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements >= 0 && "Invalid numElements");
1773*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(firstElement >= 0 && "Invalid firstElement");
1774*35238bceSAndroid Build Coastguard Worker }
1775*35238bceSAndroid Build Coastguard Worker 
PrimitiveList(PrimitiveType primitiveType,int numElements,const DrawIndices & indices)1776*35238bceSAndroid Build Coastguard Worker PrimitiveList::PrimitiveList(PrimitiveType primitiveType, int numElements, const DrawIndices &indices)
1777*35238bceSAndroid Build Coastguard Worker     : m_primitiveType(primitiveType)
1778*35238bceSAndroid Build Coastguard Worker     , m_numElements((size_t)numElements)
1779*35238bceSAndroid Build Coastguard Worker     , m_indices(indices.indices)
1780*35238bceSAndroid Build Coastguard Worker     , m_indexType(indices.indexType)
1781*35238bceSAndroid Build Coastguard Worker     , m_baseVertex(indices.baseVertex)
1782*35238bceSAndroid Build Coastguard Worker {
1783*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements >= 0 && "Invalid numElements");
1784*35238bceSAndroid Build Coastguard Worker }
1785*35238bceSAndroid Build Coastguard Worker 
getIndex(size_t elementNdx) const1786*35238bceSAndroid Build Coastguard Worker size_t PrimitiveList::getIndex(size_t elementNdx) const
1787*35238bceSAndroid Build Coastguard Worker {
1788*35238bceSAndroid Build Coastguard Worker     // indices == DE_NULL interpreted as command.indices = [first (=baseVertex) + 0, first + 1, first + 2...]
1789*35238bceSAndroid Build Coastguard Worker     if (m_indices)
1790*35238bceSAndroid Build Coastguard Worker     {
1791*35238bceSAndroid Build Coastguard Worker         int index = m_baseVertex + (int)readIndexArray(m_indexType, m_indices, elementNdx);
1792*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(index >= 0); // do not access indices < 0
1793*35238bceSAndroid Build Coastguard Worker 
1794*35238bceSAndroid Build Coastguard Worker         return (size_t)index;
1795*35238bceSAndroid Build Coastguard Worker     }
1796*35238bceSAndroid Build Coastguard Worker     else
1797*35238bceSAndroid Build Coastguard Worker         return (size_t)(m_baseVertex) + elementNdx;
1798*35238bceSAndroid Build Coastguard Worker }
1799*35238bceSAndroid Build Coastguard Worker 
isRestartIndex(size_t elementNdx,uint32_t restartIndex) const1800*35238bceSAndroid Build Coastguard Worker bool PrimitiveList::isRestartIndex(size_t elementNdx, uint32_t restartIndex) const
1801*35238bceSAndroid Build Coastguard Worker {
1802*35238bceSAndroid Build Coastguard Worker     // implicit index or explicit index (without base vertex) equals restart
1803*35238bceSAndroid Build Coastguard Worker     if (m_indices)
1804*35238bceSAndroid Build Coastguard Worker         return readIndexArray(m_indexType, m_indices, elementNdx) == restartIndex;
1805*35238bceSAndroid Build Coastguard Worker     else
1806*35238bceSAndroid Build Coastguard Worker         return elementNdx == (size_t)restartIndex;
1807*35238bceSAndroid Build Coastguard Worker }
1808*35238bceSAndroid Build Coastguard Worker 
Renderer(void)1809*35238bceSAndroid Build Coastguard Worker Renderer::Renderer(void)
1810*35238bceSAndroid Build Coastguard Worker {
1811*35238bceSAndroid Build Coastguard Worker }
1812*35238bceSAndroid Build Coastguard Worker 
~Renderer(void)1813*35238bceSAndroid Build Coastguard Worker Renderer::~Renderer(void)
1814*35238bceSAndroid Build Coastguard Worker {
1815*35238bceSAndroid Build Coastguard Worker }
1816*35238bceSAndroid Build Coastguard Worker 
draw(const DrawCommand & command) const1817*35238bceSAndroid Build Coastguard Worker void Renderer::draw(const DrawCommand &command) const
1818*35238bceSAndroid Build Coastguard Worker {
1819*35238bceSAndroid Build Coastguard Worker     drawInstanced(command, 1);
1820*35238bceSAndroid Build Coastguard Worker }
1821*35238bceSAndroid Build Coastguard Worker 
drawInstanced(const DrawCommand & command,int numInstances) const1822*35238bceSAndroid Build Coastguard Worker void Renderer::drawInstanced(const DrawCommand &command, int numInstances) const
1823*35238bceSAndroid Build Coastguard Worker {
1824*35238bceSAndroid Build Coastguard Worker     // Do not run bad commands
1825*35238bceSAndroid Build Coastguard Worker     {
1826*35238bceSAndroid Build Coastguard Worker         const bool validCommand = isValidCommand(command, numInstances);
1827*35238bceSAndroid Build Coastguard Worker         if (!validCommand)
1828*35238bceSAndroid Build Coastguard Worker         {
1829*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
1830*35238bceSAndroid Build Coastguard Worker             return;
1831*35238bceSAndroid Build Coastguard Worker         }
1832*35238bceSAndroid Build Coastguard Worker     }
1833*35238bceSAndroid Build Coastguard Worker 
1834*35238bceSAndroid Build Coastguard Worker     // Do not draw if nothing to draw
1835*35238bceSAndroid Build Coastguard Worker     {
1836*35238bceSAndroid Build Coastguard Worker         if (command.primitives.getNumElements() == 0 || numInstances == 0)
1837*35238bceSAndroid Build Coastguard Worker             return;
1838*35238bceSAndroid Build Coastguard Worker     }
1839*35238bceSAndroid Build Coastguard Worker 
1840*35238bceSAndroid Build Coastguard Worker     // Prepare transformation
1841*35238bceSAndroid Build Coastguard Worker 
1842*35238bceSAndroid Build Coastguard Worker     const size_t numVaryings = command.program.vertexShader->getOutputs().size();
1843*35238bceSAndroid Build Coastguard Worker     VertexPacketAllocator vpalloc(numVaryings);
1844*35238bceSAndroid Build Coastguard Worker     std::vector<VertexPacket *> vertexPackets = vpalloc.allocArray(command.primitives.getNumElements());
1845*35238bceSAndroid Build Coastguard Worker     DrawContext drawContext;
1846*35238bceSAndroid Build Coastguard Worker 
1847*35238bceSAndroid Build Coastguard Worker     for (int instanceID = 0; instanceID < numInstances; ++instanceID)
1848*35238bceSAndroid Build Coastguard Worker     {
1849*35238bceSAndroid Build Coastguard Worker         // Each instance has its own primitives
1850*35238bceSAndroid Build Coastguard Worker         drawContext.primitiveID = 0;
1851*35238bceSAndroid Build Coastguard Worker 
1852*35238bceSAndroid Build Coastguard Worker         for (size_t elementNdx = 0; elementNdx < command.primitives.getNumElements(); ++elementNdx)
1853*35238bceSAndroid Build Coastguard Worker         {
1854*35238bceSAndroid Build Coastguard Worker             int numVertexPackets = 0;
1855*35238bceSAndroid Build Coastguard Worker 
1856*35238bceSAndroid Build Coastguard Worker             // collect primitive vertices until restart
1857*35238bceSAndroid Build Coastguard Worker 
1858*35238bceSAndroid Build Coastguard Worker             while (elementNdx < command.primitives.getNumElements() &&
1859*35238bceSAndroid Build Coastguard Worker                    !(command.state.restart.enabled &&
1860*35238bceSAndroid Build Coastguard Worker                      command.primitives.isRestartIndex(elementNdx, command.state.restart.restartIndex)))
1861*35238bceSAndroid Build Coastguard Worker             {
1862*35238bceSAndroid Build Coastguard Worker                 // input
1863*35238bceSAndroid Build Coastguard Worker                 vertexPackets[numVertexPackets]->instanceNdx = instanceID;
1864*35238bceSAndroid Build Coastguard Worker                 vertexPackets[numVertexPackets]->vertexNdx   = (int)command.primitives.getIndex(elementNdx);
1865*35238bceSAndroid Build Coastguard Worker 
1866*35238bceSAndroid Build Coastguard Worker                 // output
1867*35238bceSAndroid Build Coastguard Worker                 vertexPackets[numVertexPackets]->pointSize =
1868*35238bceSAndroid Build Coastguard Worker                     command.state.point.pointSize; // default value from the current state
1869*35238bceSAndroid Build Coastguard Worker                 vertexPackets[numVertexPackets]->position = tcu::Vec4(0, 0, 0, 0); // no undefined values
1870*35238bceSAndroid Build Coastguard Worker 
1871*35238bceSAndroid Build Coastguard Worker                 ++numVertexPackets;
1872*35238bceSAndroid Build Coastguard Worker                 ++elementNdx;
1873*35238bceSAndroid Build Coastguard Worker             }
1874*35238bceSAndroid Build Coastguard Worker 
1875*35238bceSAndroid Build Coastguard Worker             // Duplicated restart shade
1876*35238bceSAndroid Build Coastguard Worker             if (numVertexPackets == 0)
1877*35238bceSAndroid Build Coastguard Worker                 continue;
1878*35238bceSAndroid Build Coastguard Worker 
1879*35238bceSAndroid Build Coastguard Worker             // \todo Vertex cache?
1880*35238bceSAndroid Build Coastguard Worker 
1881*35238bceSAndroid Build Coastguard Worker             // Transform vertices
1882*35238bceSAndroid Build Coastguard Worker 
1883*35238bceSAndroid Build Coastguard Worker             command.program.vertexShader->shadeVertices(command.vertexAttribs, &vertexPackets[0], numVertexPackets);
1884*35238bceSAndroid Build Coastguard Worker 
1885*35238bceSAndroid Build Coastguard Worker             // Draw primitives
1886*35238bceSAndroid Build Coastguard Worker 
1887*35238bceSAndroid Build Coastguard Worker             switch (command.primitives.getPrimitiveType())
1888*35238bceSAndroid Build Coastguard Worker             {
1889*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_TRIANGLES:
1890*35238bceSAndroid Build Coastguard Worker             {
1891*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_TRIANGLES>(command.state, command.renderTarget, command.program,
1892*35238bceSAndroid Build Coastguard Worker                                                           &vertexPackets[0], numVertexPackets, drawContext, vpalloc);
1893*35238bceSAndroid Build Coastguard Worker                 break;
1894*35238bceSAndroid Build Coastguard Worker             }
1895*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_TRIANGLE_STRIP:
1896*35238bceSAndroid Build Coastguard Worker             {
1897*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP>(command.state, command.renderTarget, command.program,
1898*35238bceSAndroid Build Coastguard Worker                                                                &vertexPackets[0], numVertexPackets, drawContext,
1899*35238bceSAndroid Build Coastguard Worker                                                                vpalloc);
1900*35238bceSAndroid Build Coastguard Worker                 break;
1901*35238bceSAndroid Build Coastguard Worker             }
1902*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_TRIANGLE_FAN:
1903*35238bceSAndroid Build Coastguard Worker             {
1904*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_FAN>(command.state, command.renderTarget, command.program,
1905*35238bceSAndroid Build Coastguard Worker                                                              &vertexPackets[0], numVertexPackets, drawContext, vpalloc);
1906*35238bceSAndroid Build Coastguard Worker                 break;
1907*35238bceSAndroid Build Coastguard Worker             }
1908*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_LINES:
1909*35238bceSAndroid Build Coastguard Worker             {
1910*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_LINES>(command.state, command.renderTarget, command.program,
1911*35238bceSAndroid Build Coastguard Worker                                                       &vertexPackets[0], numVertexPackets, drawContext, vpalloc);
1912*35238bceSAndroid Build Coastguard Worker                 break;
1913*35238bceSAndroid Build Coastguard Worker             }
1914*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_LINE_STRIP:
1915*35238bceSAndroid Build Coastguard Worker             {
1916*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_LINE_STRIP>(command.state, command.renderTarget, command.program,
1917*35238bceSAndroid Build Coastguard Worker                                                            &vertexPackets[0], numVertexPackets, drawContext, vpalloc);
1918*35238bceSAndroid Build Coastguard Worker                 break;
1919*35238bceSAndroid Build Coastguard Worker             }
1920*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_LINE_LOOP:
1921*35238bceSAndroid Build Coastguard Worker             {
1922*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_LINE_LOOP>(command.state, command.renderTarget, command.program,
1923*35238bceSAndroid Build Coastguard Worker                                                           &vertexPackets[0], numVertexPackets, drawContext, vpalloc);
1924*35238bceSAndroid Build Coastguard Worker                 break;
1925*35238bceSAndroid Build Coastguard Worker             }
1926*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_POINTS:
1927*35238bceSAndroid Build Coastguard Worker             {
1928*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_POINTS>(command.state, command.renderTarget, command.program,
1929*35238bceSAndroid Build Coastguard Worker                                                        &vertexPackets[0], numVertexPackets, drawContext, vpalloc);
1930*35238bceSAndroid Build Coastguard Worker                 break;
1931*35238bceSAndroid Build Coastguard Worker             }
1932*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_LINES_ADJACENCY:
1933*35238bceSAndroid Build Coastguard Worker             {
1934*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_LINES_ADJACENCY>(command.state, command.renderTarget, command.program,
1935*35238bceSAndroid Build Coastguard Worker                                                                 &vertexPackets[0], numVertexPackets, drawContext,
1936*35238bceSAndroid Build Coastguard Worker                                                                 vpalloc);
1937*35238bceSAndroid Build Coastguard Worker                 break;
1938*35238bceSAndroid Build Coastguard Worker             }
1939*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
1940*35238bceSAndroid Build Coastguard Worker             {
1941*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_LINE_STRIP_ADJACENCY>(command.state, command.renderTarget,
1942*35238bceSAndroid Build Coastguard Worker                                                                      command.program, &vertexPackets[0],
1943*35238bceSAndroid Build Coastguard Worker                                                                      numVertexPackets, drawContext, vpalloc);
1944*35238bceSAndroid Build Coastguard Worker                 break;
1945*35238bceSAndroid Build Coastguard Worker             }
1946*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_TRIANGLES_ADJACENCY:
1947*35238bceSAndroid Build Coastguard Worker             {
1948*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_TRIANGLES_ADJACENCY>(command.state, command.renderTarget,
1949*35238bceSAndroid Build Coastguard Worker                                                                     command.program, &vertexPackets[0],
1950*35238bceSAndroid Build Coastguard Worker                                                                     numVertexPackets, drawContext, vpalloc);
1951*35238bceSAndroid Build Coastguard Worker                 break;
1952*35238bceSAndroid Build Coastguard Worker             }
1953*35238bceSAndroid Build Coastguard Worker             case PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
1954*35238bceSAndroid Build Coastguard Worker             {
1955*35238bceSAndroid Build Coastguard Worker                 drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY>(command.state, command.renderTarget,
1956*35238bceSAndroid Build Coastguard Worker                                                                          command.program, &vertexPackets[0],
1957*35238bceSAndroid Build Coastguard Worker                                                                          numVertexPackets, drawContext, vpalloc);
1958*35238bceSAndroid Build Coastguard Worker                 break;
1959*35238bceSAndroid Build Coastguard Worker             }
1960*35238bceSAndroid Build Coastguard Worker             default:
1961*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
1962*35238bceSAndroid Build Coastguard Worker             }
1963*35238bceSAndroid Build Coastguard Worker         }
1964*35238bceSAndroid Build Coastguard Worker     }
1965*35238bceSAndroid Build Coastguard Worker }
1966*35238bceSAndroid Build Coastguard Worker 
1967*35238bceSAndroid Build Coastguard Worker } // namespace rr
1968