1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Reference Renderer
3 * -----------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Reference renderer interface.
22 *//*--------------------------------------------------------------------*/
24 #include "rrRenderer.hpp"
25 #include "tcuVectorUtil.hpp"
26 #include "tcuTextureUtil.hpp"
27 #include "tcuFloat.hpp"
28 #include "rrPrimitiveAssembler.hpp"
29 #include "rrFragmentOperations.hpp"
30 #include "rrRasterizer.hpp"
40 typedef double ClipFloat; // floating point type used in clipping
42 typedef tcu::Vector<ClipFloat, 4> ClipVec4;
44 struct RasterizationInternalBuffers
46 std::vector<FragmentPacket> fragmentPackets;
47 std::vector<GenericVec4> shaderOutputs;
48 std::vector<Fragment> shadedFragments;
49 float* fragmentDepthBuffer;
52 deUint32 readIndexArray (const IndexType type, const void* ptr, size_t ndx)
57 return ((const deUint8*)ptr)[ndx];
59 case INDEXTYPE_UINT16:
62 deMemcpy(&retVal, (const deUint8*)ptr + ndx * sizeof(deUint16), sizeof(deUint16));
67 case INDEXTYPE_UINT32:
70 deMemcpy(&retVal, (const deUint8*)ptr + ndx * sizeof(deUint32), sizeof(deUint32));
81 tcu::IVec4 getBufferSize (const rr::MultisampleConstPixelBufferAccess& multisampleBuffer)
83 return tcu::IVec4(0, 0, multisampleBuffer.raw().getHeight(), multisampleBuffer.raw().getDepth());
86 bool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
88 return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
101 /*--------------------------------------------------------------------*//*!
102 * \brief Calculates intersection of two rects given as (left, bottom, width, height)
103 *//*--------------------------------------------------------------------*/
104 tcu::IVec4 rectIntersection (const tcu::IVec4& a, const tcu::IVec4& b)
106 const tcu::IVec2 pos = tcu::IVec2(de::max(a.x(), b.x()), de::max(a.y(), b.y()));
107 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 return tcu::IVec4(pos.x(), pos.y(), endPos.x() - pos.x(), endPos.y() - pos.y());
112 void convertPrimitiveToBaseType(std::vector<pa::Triangle>& output, std::vector<pa::Triangle>& input)
114 std::swap(output, input);
117 void convertPrimitiveToBaseType(std::vector<pa::Line>& output, std::vector<pa::Line>& input)
119 std::swap(output, input);
122 void convertPrimitiveToBaseType(std::vector<pa::Point>& output, std::vector<pa::Point>& input)
124 std::swap(output, input);
127 void convertPrimitiveToBaseType(std::vector<pa::Line>& output, std::vector<pa::LineAdjacency>& input)
129 output.resize(input.size());
130 for (size_t i = 0; i < input.size(); ++i)
132 const int adjacentProvokingVertex = input[i].provokingIndex;
133 const int baseProvokingVertexIndex = adjacentProvokingVertex-1;
134 output[i] = pa::Line(input[i].v1, input[i].v2, baseProvokingVertexIndex);
138 void convertPrimitiveToBaseType(std::vector<pa::Triangle>& output, std::vector<pa::TriangleAdjacency>& input)
140 output.resize(input.size());
141 for (size_t i = 0; i < input.size(); ++i)
143 const int adjacentProvokingVertex = input[i].provokingIndex;
144 const int baseProvokingVertexIndex = adjacentProvokingVertex/2;
145 output[i] = pa::Triangle(input[i].v0, input[i].v2, input[i].v4, baseProvokingVertexIndex);
152 /*--------------------------------------------------------------------*//*!
153 * \brief Get clipped portion of the second endpoint
155 * Calculate the intersection of line segment v0-v1 and a given plane. Line
156 * segment is defined by a pair of one-dimensional homogeneous coordinates.
158 *//*--------------------------------------------------------------------*/
159 ClipFloat getSegmentVolumeEdgeClip (const ClipFloat v0,
163 const ClipFloat plane)
165 return (plane*w0 - v0) / ((v1 - v0) - plane*(w1 - w0));
168 /*--------------------------------------------------------------------*//*!
169 * \brief Get clipped portion of the endpoint
171 * How much (in [0-1] range) of a line segment v0-v1 would be clipped
172 * of the v0 end of the line segment by clipping.
173 *//*--------------------------------------------------------------------*/
174 ClipFloat getLineEndpointClipping (const ClipVec4& v0, const ClipVec4& v1)
176 const ClipFloat clipVolumeSize = (ClipFloat)1.0;
181 return getSegmentVolumeEdgeClip(v0.z(), v0.w(), v1.z(), v1.w(), clipVolumeSize);
183 else if (v0.z() < -v0.w())
186 return getSegmentVolumeEdgeClip(v0.z(), v0.w(), v1.z(), v1.w(), -clipVolumeSize);
191 return (ClipFloat)0.0;
195 ClipVec4 vec4ToClipVec4 (const tcu::Vec4& v)
197 return ClipVec4((ClipFloat)v.x(), (ClipFloat)v.y(), (ClipFloat)v.z(), (ClipFloat)v.w());
200 tcu::Vec4 clipVec4ToVec4 (const ClipVec4& v)
202 return tcu::Vec4((float)v.x(), (float)v.y(), (float)v.z(), (float)v.w());
205 class ClipVolumePlane
208 virtual bool pointInClipVolume (const ClipVec4& p) const = 0;
209 virtual ClipFloat clipLineSegmentEnd (const ClipVec4& v0, const ClipVec4& v1) const = 0;
210 virtual ClipVec4 getLineIntersectionPoint (const ClipVec4& v0, const ClipVec4& v1) const = 0;
213 template <int Sign, int CompNdx>
214 class ComponentPlane : public ClipVolumePlane
216 DE_STATIC_ASSERT(Sign == +1 || Sign == -1);
219 bool pointInClipVolume (const ClipVec4& p) const;
220 ClipFloat clipLineSegmentEnd (const ClipVec4& v0, const ClipVec4& v1) const;
221 ClipVec4 getLineIntersectionPoint (const ClipVec4& v0, const ClipVec4& v1) const;
224 template <int Sign, int CompNdx>
225 bool ComponentPlane<Sign, CompNdx>::pointInClipVolume (const ClipVec4& p) const
227 const ClipFloat clipVolumeSize = (ClipFloat)1.0;
229 return (ClipFloat)(Sign * p[CompNdx]) <= clipVolumeSize * p.w();
232 template <int Sign, int CompNdx>
233 ClipFloat ComponentPlane<Sign, CompNdx>::clipLineSegmentEnd (const ClipVec4& v0, const ClipVec4& v1) const
235 const ClipFloat clipVolumeSize = (ClipFloat)1.0;
237 return getSegmentVolumeEdgeClip(v0[CompNdx], v0.w(),
239 (ClipFloat)Sign * clipVolumeSize);
242 template <int Sign, int CompNdx>
243 ClipVec4 ComponentPlane<Sign, CompNdx>::getLineIntersectionPoint (const ClipVec4& v0, const ClipVec4& v1) const
245 // A point on line might be far away, causing clipping ratio (clipLineSegmentEnd) to become extremely close to 1.0
246 // even if the another point is not on the plane. Prevent clipping ratio from saturating by using points on line
247 // that are (nearly) on this and (nearly) on the opposite plane.
249 const ClipVec4 clippedV0 = tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
250 const ClipVec4 clippedV1 = tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
251 const ClipFloat clipRatio = clipLineSegmentEnd(clippedV0, clippedV1);
253 // Find intersection point of line from v0 to v1 and the current plane. Avoid ratios near 1.0
254 if (clipRatio <= (ClipFloat)0.5)
255 return tcu::mix(clippedV0, clippedV1, clipRatio);
258 const ClipFloat complementClipRatio = clipLineSegmentEnd(clippedV1, clippedV0);
259 return tcu::mix(clippedV1, clippedV0, complementClipRatio);
263 struct TriangleVertex
266 ClipFloat weight[3]; //!< barycentrics
271 TriangleVertex vertices[3];
274 void clipTriangleOneVertex (std::vector<TriangleVertex>& clippedEdges, const ClipVolumePlane& plane, const TriangleVertex& clipped, const TriangleVertex& v1, const TriangleVertex& v2)
276 const ClipFloat degenerateLimit = (ClipFloat)1.0;
281 bool outputDegenerate = false;
284 const TriangleVertex& inside = v1;
285 const TriangleVertex& outside = clipped;
286 TriangleVertex& middle = mid1;
288 const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
290 if (hitDist >= degenerateLimit)
292 // do not generate degenerate triangles
293 outputDegenerate = true;
297 const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
298 const ClipVec4 anotherPointOnLine = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
300 middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
301 middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
302 middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
303 middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
308 const TriangleVertex& inside = v2;
309 const TriangleVertex& outside = clipped;
310 TriangleVertex& middle = mid2;
312 const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
314 if (hitDist >= degenerateLimit)
316 // do not generate degenerate triangles
317 outputDegenerate = true;
321 const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
322 const ClipVec4 anotherPointOnLine = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
324 middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
325 middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
326 middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
327 middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
331 if (!outputDegenerate)
333 // gen quad (v1) -> mid1 -> mid2 -> (v2)
334 clippedEdges.push_back(v1);
335 clippedEdges.push_back(mid1);
336 clippedEdges.push_back(mid2);
337 clippedEdges.push_back(v2);
342 clippedEdges.push_back(v1);
343 clippedEdges.push_back(clipped);
344 clippedEdges.push_back(v2);
348 void clipTriangleTwoVertices (std::vector<TriangleVertex>& clippedEdges, const ClipVolumePlane& plane, const TriangleVertex& v0, const TriangleVertex& clipped1, const TriangleVertex& clipped2)
350 const ClipFloat unclippableLimit = (ClipFloat)1.0;
355 bool unclippableVertex1 = false;
356 bool unclippableVertex2 = false;
359 const TriangleVertex& inside = v0;
360 const TriangleVertex& outside = clipped1;
361 TriangleVertex& middle = mid1;
363 const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
365 if (hitDist >= unclippableLimit)
367 // this edge cannot be clipped because the edge is really close to the volume boundary
368 unclippableVertex1 = true;
372 const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
373 const ClipVec4 anotherPointOnLine = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
375 middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
376 middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
377 middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
378 middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
383 const TriangleVertex& inside = v0;
384 const TriangleVertex& outside = clipped2;
385 TriangleVertex& middle = mid2;
387 const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
389 if (hitDist >= unclippableLimit)
391 // this edge cannot be clipped because the edge is really close to the volume boundary
392 unclippableVertex2 = true;
396 const ClipVec4 approximatedClipPoint = tcu::mix(inside.position, outside.position, hitDist);
397 const ClipVec4 anotherPointOnLine = (hitDist > (ClipFloat)0.5) ? (inside.position) : (outside.position);
399 middle.position = plane.getLineIntersectionPoint(approximatedClipPoint, anotherPointOnLine);
400 middle.weight[0] = tcu::mix(inside.weight[0], outside.weight[0], hitDist);
401 middle.weight[1] = tcu::mix(inside.weight[1], outside.weight[1], hitDist);
402 middle.weight[2] = tcu::mix(inside.weight[2], outside.weight[2], hitDist);
406 if (!unclippableVertex1 && !unclippableVertex2)
408 // gen triangle (v0) -> mid1 -> mid2
409 clippedEdges.push_back(v0);
410 clippedEdges.push_back(mid1);
411 clippedEdges.push_back(mid2);
413 else if (!unclippableVertex1 && unclippableVertex2)
415 // clip just vertex 1
416 clippedEdges.push_back(v0);
417 clippedEdges.push_back(mid1);
418 clippedEdges.push_back(clipped2);
420 else if (unclippableVertex1 && !unclippableVertex2)
422 // clip just vertex 2
423 clippedEdges.push_back(v0);
424 clippedEdges.push_back(clipped1);
425 clippedEdges.push_back(mid2);
430 clippedEdges.push_back(v0);
431 clippedEdges.push_back(clipped1);
432 clippedEdges.push_back(clipped2);
436 void clipTriangleToPlane (std::vector<TriangleVertex>& clippedEdges, const TriangleVertex* vertices, const ClipVolumePlane& plane)
438 const bool v0Clipped = !plane.pointInClipVolume(vertices[0].position);
439 const bool v1Clipped = !plane.pointInClipVolume(vertices[1].position);
440 const bool v2Clipped = !plane.pointInClipVolume(vertices[2].position);
441 const int clipCount = ((v0Clipped) ? (1) : (0)) + ((v1Clipped) ? (1) : (0)) + ((v2Clipped) ? (1) : (0));
446 clippedEdges.insert(clippedEdges.begin(), vertices, vertices + 3);
448 else if (clipCount == 1)
451 if (v0Clipped) clipTriangleOneVertex(clippedEdges, plane, vertices[0], vertices[1], vertices[2]);
452 else if (v1Clipped) clipTriangleOneVertex(clippedEdges, plane, vertices[1], vertices[2], vertices[0]);
453 else clipTriangleOneVertex(clippedEdges, plane, vertices[2], vertices[0], vertices[1]);
455 else if (clipCount == 2)
458 if (!v0Clipped) clipTriangleTwoVertices(clippedEdges, plane, vertices[0], vertices[1], vertices[2]);
459 else if (!v1Clipped) clipTriangleTwoVertices(clippedEdges, plane, vertices[1], vertices[2], vertices[0]);
460 else clipTriangleTwoVertices(clippedEdges, plane, vertices[2], vertices[0], vertices[1]);
462 else if (clipCount == 3)
474 tcu::Vec2 to2DCartesian (const tcu::Vec4& p)
476 return tcu::Vec2(p.x(), p.y()) / p.w();
479 float cross2D (const tcu::Vec2& a, const tcu::Vec2& b)
481 return tcu::cross(tcu::Vec3(a.x(), a.y(), 0.0f), tcu::Vec3(b.x(), b.y(), 0.0f)).z();
484 void flatshadePrimitiveVertices (pa::Triangle& target, size_t outputNdx)
486 const rr::GenericVec4 flatValue = target.getProvokingVertex()->outputs[outputNdx];
487 target.v0->outputs[outputNdx] = flatValue;
488 target.v1->outputs[outputNdx] = flatValue;
489 target.v2->outputs[outputNdx] = flatValue;
492 void flatshadePrimitiveVertices (pa::Line& target, size_t outputNdx)
494 const rr::GenericVec4 flatValue = target.getProvokingVertex()->outputs[outputNdx];
495 target.v0->outputs[outputNdx] = flatValue;
496 target.v1->outputs[outputNdx] = flatValue;
499 void flatshadePrimitiveVertices (pa::Point& target, size_t outputNdx)
505 template <typename ContainerType>
506 void flatshadeVertices (const Program& program, ContainerType& list)
509 const std::vector<rr::VertexVaryingInfo>& fragInputs = (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
511 for (size_t inputNdx = 0; inputNdx < fragInputs.size(); ++inputNdx)
512 if (fragInputs[inputNdx].flatshade)
513 for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
514 flatshadePrimitiveVertices(*it, inputNdx);
517 /*--------------------------------------------------------------------*//*!
518 * Clip triangles to the clip volume.
519 *//*--------------------------------------------------------------------*/
520 void clipPrimitives (std::vector<pa::Triangle>& list,
521 const Program& program,
522 bool clipWithZPlanes,
523 VertexPacketAllocator& vpalloc)
525 using namespace cliputil;
527 cliputil::ComponentPlane<+1, 0> clipPosX;
528 cliputil::ComponentPlane<-1, 0> clipNegX;
529 cliputil::ComponentPlane<+1, 1> clipPosY;
530 cliputil::ComponentPlane<-1, 1> clipNegY;
531 cliputil::ComponentPlane<+1, 2> clipPosZ;
532 cliputil::ComponentPlane<-1, 2> clipNegZ;
534 const std::vector<rr::VertexVaryingInfo>& fragInputs = (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
535 const ClipVolumePlane* planes[] = { &clipPosX, &clipNegX, &clipPosY, &clipNegY, &clipPosZ, &clipNegZ };
536 const int numPlanes = (clipWithZPlanes) ? (6) : (4);
538 std::vector<pa::Triangle> outputTriangles;
540 for (int inputTriangleNdx = 0; inputTriangleNdx < (int)list.size(); ++inputTriangleNdx)
542 bool clippedByPlane[6];
546 bool discardPrimitive = false;
547 bool fullyInClipVolume = true;
549 for (int planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
551 const ClipVolumePlane* plane = planes[planeNdx];
552 const bool v0InsidePlane = plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v0->position));
553 const bool v1InsidePlane = plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v1->position));
554 const bool v2InsidePlane = plane->pointInClipVolume(vec4ToClipVec4(list[inputTriangleNdx].v2->position));
557 if (!v0InsidePlane && !v1InsidePlane && !v2InsidePlane)
559 discardPrimitive = true;
563 else if (!v0InsidePlane || !v1InsidePlane || !v2InsidePlane)
565 clippedByPlane[planeNdx] = true;
566 fullyInClipVolume = false;
570 clippedByPlane[planeNdx] = false;
573 if (discardPrimitive)
576 if (fullyInClipVolume)
578 outputTriangles.push_back(list[inputTriangleNdx]);
585 std::vector<SubTriangle> subTriangles (1);
586 SubTriangle& initialTri = subTriangles[0];
588 initialTri.vertices[0].position = vec4ToClipVec4(list[inputTriangleNdx].v0->position);
589 initialTri.vertices[0].weight[0] = (ClipFloat)1.0;
590 initialTri.vertices[0].weight[1] = (ClipFloat)0.0;
591 initialTri.vertices[0].weight[2] = (ClipFloat)0.0;
593 initialTri.vertices[1].position = vec4ToClipVec4(list[inputTriangleNdx].v1->position);
594 initialTri.vertices[1].weight[0] = (ClipFloat)0.0;
595 initialTri.vertices[1].weight[1] = (ClipFloat)1.0;
596 initialTri.vertices[1].weight[2] = (ClipFloat)0.0;
598 initialTri.vertices[2].position = vec4ToClipVec4(list[inputTriangleNdx].v2->position);
599 initialTri.vertices[2].weight[0] = (ClipFloat)0.0;
600 initialTri.vertices[2].weight[1] = (ClipFloat)0.0;
601 initialTri.vertices[2].weight[2] = (ClipFloat)1.0;
603 // Clip all subtriangles to all relevant planes
604 for (int planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
606 std::vector<SubTriangle> nextPhaseSubTriangles;
608 if (!clippedByPlane[planeNdx])
611 for (int subTriangleNdx = 0; subTriangleNdx < (int)subTriangles.size(); ++subTriangleNdx)
613 std::vector<TriangleVertex> convexPrimitive;
615 // Clip triangle and form a convex n-gon ( n c {3, 4} )
616 clipTriangleToPlane(convexPrimitive, subTriangles[subTriangleNdx].vertices, *planes[planeNdx]);
618 // Subtriangle completely discarded
619 if (convexPrimitive.empty())
622 DE_ASSERT(convexPrimitive.size() == 3 || convexPrimitive.size() == 4);
624 //Triangulate planar convex n-gon
626 TriangleVertex& v0 = convexPrimitive[0];
628 for (int subsubTriangleNdx = 1; subsubTriangleNdx + 1 < (int)convexPrimitive.size(); ++subsubTriangleNdx)
630 const float degenerateEpsilon = 1.0e-6f;
631 const TriangleVertex& v1 = convexPrimitive[subsubTriangleNdx];
632 const TriangleVertex& v2 = convexPrimitive[subsubTriangleNdx + 1];
633 const float visibleArea = de::abs(cross2D(to2DCartesian(clipVec4ToVec4(v1.position)) - to2DCartesian(clipVec4ToVec4(v0.position)),
634 to2DCartesian(clipVec4ToVec4(v2.position)) - to2DCartesian(clipVec4ToVec4(v0.position))));
636 // has surface area (is not a degenerate)
637 if (visibleArea >= degenerateEpsilon)
639 SubTriangle subsubTriangle;
641 subsubTriangle.vertices[0] = v0;
642 subsubTriangle.vertices[1] = v1;
643 subsubTriangle.vertices[2] = v2;
645 nextPhaseSubTriangles.push_back(subsubTriangle);
651 subTriangles.swap(nextPhaseSubTriangles);
654 // Rebuild pa::Triangles from subtriangles
655 for (int subTriangleNdx = 0; subTriangleNdx < (int)subTriangles.size(); ++subTriangleNdx)
657 VertexPacket* p0 = vpalloc.alloc();
658 VertexPacket* p1 = vpalloc.alloc();
659 VertexPacket* p2 = vpalloc.alloc();
660 pa::Triangle ngonFragment (p0, p1, p2, -1);
662 p0->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[0].position);
663 p1->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[1].position);
664 p2->position = clipVec4ToVec4(subTriangles[subTriangleNdx].vertices[2].position);
666 for (size_t outputNdx = 0; outputNdx < fragInputs.size(); ++outputNdx)
668 if (fragInputs[outputNdx].type == GENERICVECTYPE_FLOAT)
670 const tcu::Vec4 out0 = list[inputTriangleNdx].v0->outputs[outputNdx].get<float>();
671 const tcu::Vec4 out1 = list[inputTriangleNdx].v1->outputs[outputNdx].get<float>();
672 const tcu::Vec4 out2 = list[inputTriangleNdx].v2->outputs[outputNdx].get<float>();
674 p0->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[0].weight[0] * out0
675 + (float)subTriangles[subTriangleNdx].vertices[0].weight[1] * out1
676 + (float)subTriangles[subTriangleNdx].vertices[0].weight[2] * out2;
678 p1->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[1].weight[0] * out0
679 + (float)subTriangles[subTriangleNdx].vertices[1].weight[1] * out1
680 + (float)subTriangles[subTriangleNdx].vertices[1].weight[2] * out2;
682 p2->outputs[outputNdx] = (float)subTriangles[subTriangleNdx].vertices[2].weight[0] * out0
683 + (float)subTriangles[subTriangleNdx].vertices[2].weight[1] * out1
684 + (float)subTriangles[subTriangleNdx].vertices[2].weight[2] * out2;
688 // only floats are interpolated, all others must be flatshaded then
689 p0->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
690 p1->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
691 p2->outputs[outputNdx] = list[inputTriangleNdx].getProvokingVertex()->outputs[outputNdx];
695 outputTriangles.push_back(ngonFragment);
701 list.swap(outputTriangles);
704 /*--------------------------------------------------------------------*//*!
705 * Clip lines to the near and far clip planes.
707 * Clipping to other planes is a by-product of the viewport test (i.e.
708 * rasterization area selection).
709 *//*--------------------------------------------------------------------*/
710 void clipPrimitives (std::vector<pa::Line>& list,
711 const Program& program,
712 bool clipWithZPlanes,
713 VertexPacketAllocator& vpalloc)
717 using namespace cliputil;
719 // Lines are clipped only by the far and the near planes here. Line clipping by other planes done in the rasterization phase
721 const std::vector<rr::VertexVaryingInfo>& fragInputs = (program.geometryShader) ? (program.geometryShader->getOutputs()) : (program.vertexShader->getOutputs());
722 std::vector<pa::Line> visibleLines;
724 // Z-clipping disabled, don't do anything
725 if (!clipWithZPlanes)
728 for (size_t ndx = 0; ndx < list.size(); ++ndx)
730 pa::Line& l = list[ndx];
732 // Totally discarded?
733 if ((l.v0->position.z() < -l.v0->position.w() && l.v1->position.z() < -l.v1->position.w()) ||
734 (l.v0->position.z() > l.v0->position.w() && l.v1->position.z() > l.v1->position.w()))
737 // Something is visible
739 const ClipVec4 p0 = vec4ToClipVec4(l.v0->position);
740 const ClipVec4 p1 = vec4ToClipVec4(l.v1->position);
741 const ClipFloat t0 = getLineEndpointClipping(p0, p1);
742 const ClipFloat t1 = getLineEndpointClipping(p1, p0);
744 // Not clipped at all?
745 if (t0 == (ClipFloat)0.0 && t1 == (ClipFloat)0.0)
747 visibleLines.push_back(pa::Line(l.v0, l.v1, -1));
752 l.v0->position = clipVec4ToVec4(tcu::mix(p0, p1, t0));
753 l.v1->position = clipVec4ToVec4(tcu::mix(p1, p0, t1));
756 for (size_t outputNdx = 0; outputNdx < fragInputs.size(); ++outputNdx)
758 // only floats are clipped, other types are flatshaded
759 if (fragInputs[outputNdx].type == GENERICVECTYPE_FLOAT)
761 const tcu::Vec4 a0 = l.v0->outputs[outputNdx].get<float>();
762 const tcu::Vec4 a1 = l.v1->outputs[outputNdx].get<float>();
764 l.v0->outputs[outputNdx] = tcu::mix(a0, a1, (float)t0);
765 l.v1->outputs[outputNdx] = tcu::mix(a1, a0, (float)t1);
769 visibleLines.push_back(pa::Line(l.v0, l.v1, -1));
773 // return visible in list
774 std::swap(visibleLines, list);
777 /*--------------------------------------------------------------------*//*!
778 * Discard points not within clip volume. Clipping is a by-product
779 * of the viewport test.
780 *//*--------------------------------------------------------------------*/
781 void clipPrimitives (std::vector<pa::Point>& list,
782 const Program& program,
783 bool clipWithZPlanes,
784 VertexPacketAllocator& vpalloc)
789 std::vector<pa::Point> visiblePoints;
791 // Z-clipping disabled, don't do anything
792 if (!clipWithZPlanes)
795 for (size_t ndx = 0; ndx < list.size(); ++ndx)
797 pa::Point& p = list[ndx];
799 // points are discarded if Z is not in range. (Wide) point clipping is done in the rasterization phase
800 if (de::inRange(p.v0->position.z(), -p.v0->position.w(), p.v0->position.w()))
801 visiblePoints.push_back(pa::Point(p.v0));
804 // return visible in list
805 std::swap(visiblePoints, list);
808 void transformVertexClipCoordsToWindowCoords (const RenderState& state, VertexPacket& packet)
810 // To normalized device coords
812 packet.position = tcu::Vec4(packet.position.x()/packet.position.w(),
813 packet.position.y()/packet.position.w(),
814 packet.position.z()/packet.position.w(),
815 1.0f /packet.position.w());
820 const WindowRectangle& viewport = state.viewport.rect;
821 const float halfW = (float)(viewport.width) / 2.0f;
822 const float halfH = (float)(viewport.height) / 2.0f;
823 const float oX = (float)viewport.left + halfW;
824 const float oY = (float)viewport.bottom + halfH;
825 const float zn = state.viewport.zn;
826 const float zf = state.viewport.zf;
828 packet.position = tcu::Vec4(packet.position.x()*halfW + oX,
829 packet.position.y()*halfH + oY,
830 packet.position.z()*(zf - zn)/2.0f + (zn + zf)/2.0f,
831 packet.position.w());
835 void transformPrimitiveClipCoordsToWindowCoords (const RenderState& state, pa::Triangle& target)
837 transformVertexClipCoordsToWindowCoords(state, *target.v0);
838 transformVertexClipCoordsToWindowCoords(state, *target.v1);
839 transformVertexClipCoordsToWindowCoords(state, *target.v2);
842 void transformPrimitiveClipCoordsToWindowCoords (const RenderState& state, pa::Line& target)
844 transformVertexClipCoordsToWindowCoords(state, *target.v0);
845 transformVertexClipCoordsToWindowCoords(state, *target.v1);
848 void transformPrimitiveClipCoordsToWindowCoords (const RenderState& state, pa::Point& target)
850 transformVertexClipCoordsToWindowCoords(state, *target.v0);
853 template <typename ContainerType>
854 void transformClipCoordsToWindowCoords (const RenderState& state, ContainerType& list)
856 for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
857 transformPrimitiveClipCoordsToWindowCoords(state, *it);
860 void makeSharedVerticeDistinct (VertexPacket*& packet, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
863 if (vertices.find(packet) == vertices.end())
865 vertices.insert(packet);
869 VertexPacket* newPacket = vpalloc.alloc();
871 // copy packet output values
872 newPacket->position = packet->position;
873 newPacket->pointSize = packet->pointSize;
874 newPacket->primitiveID = packet->primitiveID;
876 for (size_t outputNdx = 0; outputNdx < vpalloc.getNumVertexOutputs(); ++outputNdx)
877 newPacket->outputs[outputNdx] = packet->outputs[outputNdx];
879 // no need to insert new packet to "vertices" as newPacket is unique
884 void makeSharedVerticesDistinct (pa::Triangle& target, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
886 makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
887 makeSharedVerticeDistinct(target.v1, vertices, vpalloc);
888 makeSharedVerticeDistinct(target.v2, vertices, vpalloc);
891 void makeSharedVerticesDistinct (pa::Line& target, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
893 makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
894 makeSharedVerticeDistinct(target.v1, vertices, vpalloc);
897 void makeSharedVerticesDistinct (pa::Point& target, std::set<VertexPacket*, std::less<void*> >& vertices, VertexPacketAllocator& vpalloc)
899 makeSharedVerticeDistinct(target.v0, vertices, vpalloc);
902 template <typename ContainerType>
903 void makeSharedVerticesDistinct (ContainerType& list, VertexPacketAllocator& vpalloc)
905 std::set<VertexPacket*, std::less<void*> > vertices;
907 for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
908 makeSharedVerticesDistinct(*it, vertices, vpalloc);
911 void generatePrimitiveIDs (pa::Triangle& target, int id)
913 target.v0->primitiveID = id;
914 target.v1->primitiveID = id;
915 target.v2->primitiveID = id;
918 void generatePrimitiveIDs (pa::Line& target, int id)
920 target.v0->primitiveID = id;
921 target.v1->primitiveID = id;
924 void generatePrimitiveIDs (pa::Point& target, int id)
926 target.v0->primitiveID = id;
929 template <typename ContainerType>
930 void generatePrimitiveIDs (ContainerType& list, DrawContext& drawContext)
932 for (typename ContainerType::iterator it = list.begin(); it != list.end(); ++it)
933 generatePrimitiveIDs(*it, drawContext.primitiveID++);
936 static float findTriangleVertexDepthSlope (const tcu::Vec4& p, const tcu::Vec4& v0, const tcu::Vec4& v1)
939 const tcu::Vec3 ssp = p.swizzle(0, 1, 2);
940 const tcu::Vec3 ssv0 = v0.swizzle(0, 1, 2);
941 const tcu::Vec3 ssv1 = v1.swizzle(0, 1, 2);
945 const tcu::Vec3 a = ssv0.swizzle(0,1,2) - ssp.swizzle(0,1,2);
946 const tcu::Vec3 b = ssv1.swizzle(0,1,2) - ssp.swizzle(0,1,2);
947 const float epsilon = 0.0001f;
948 const float det = (a.x() * b.y() - b.x() * a.y());
950 // degenerate triangle, it won't generate any fragments anyway. Return value doesn't matter
951 if (de::abs(det) < epsilon)
954 const tcu::Vec2 dxDir = tcu::Vec2( b.y(), -a.y()) / det;
955 const tcu::Vec2 dyDir = tcu::Vec2(-b.x(), a.x()) / det;
957 const float dzdx = dxDir.x() * a.z() + dxDir.y() * b.z();
958 const float dzdy = dyDir.x() * a.z() + dyDir.y() * b.z();
960 // approximate using max(|dz/dx|, |dz/dy|)
961 return de::max(de::abs(dzdx), de::abs(dzdy));
964 static float findPrimitiveMaximumDepthSlope (const pa::Triangle& triangle)
966 const float d1 = findTriangleVertexDepthSlope(triangle.v0->position, triangle.v1->position, triangle.v2->position);
967 const float d2 = findTriangleVertexDepthSlope(triangle.v1->position, triangle.v2->position, triangle.v0->position);
968 const float d3 = findTriangleVertexDepthSlope(triangle.v2->position, triangle.v0->position, triangle.v1->position);
970 return de::max(d1, de::max(d2, d3));
973 static float getFloatingPointMinimumResolvableDifference (float maxZValue, tcu::TextureFormat::ChannelType type)
975 if (type == tcu::TextureFormat::FLOAT)
978 const int maxExponent = tcu::Float32(maxZValue).exponent();
979 return tcu::Float32::construct(+1, maxExponent - 23, 1 << 23).asFloat();
987 static float getFixedPointMinimumResolvableDifference (int numBits)
989 return tcu::Float32::construct(+1, -numBits, 1 << 23).asFloat();
992 static float findPrimitiveMinimumResolvableDifference (const pa::Triangle& triangle, const rr::MultisampleConstPixelBufferAccess& depthAccess)
994 const float maxZvalue = de::max(de::max(triangle.v0->position.z(), triangle.v1->position.z()), triangle.v2->position.z());
995 const tcu::TextureFormat format = depthAccess.raw().getFormat();
996 const tcu::TextureFormat::ChannelOrder order = format.order;
998 if (order == tcu::TextureFormat::D)
1001 const tcu::TextureFormat::ChannelType channelType = format.type;
1002 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(channelType);
1003 const int numBits = tcu::getTextureFormatBitDepth(format).x();
1005 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1006 return getFloatingPointMinimumResolvableDifference(maxZvalue, channelType);
1008 // \note channelClass might be CLASS_LAST but that's ok
1009 return getFixedPointMinimumResolvableDifference(numBits);
1011 else if (order == tcu::TextureFormat::DS)
1013 // depth stencil, special cases for possible combined formats
1014 if (format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
1015 return getFloatingPointMinimumResolvableDifference(maxZvalue, tcu::TextureFormat::FLOAT);
1016 else if (format.type == tcu::TextureFormat::UNSIGNED_INT_24_8)
1017 return getFixedPointMinimumResolvableDifference(24);
1020 // unexpected format
1025 void writeFragmentPackets (const RenderState& state,
1026 const RenderTarget& renderTarget,
1027 const Program& program,
1028 const FragmentPacket* fragmentPackets,
1029 int numRasterizedPackets,
1030 rr::FaceType facetype,
1031 const std::vector<rr::GenericVec4>& fragmentOutputArray,
1032 const float* depthValues,
1033 std::vector<Fragment>& fragmentBuffer)
1035 const int numSamples = renderTarget.getNumSamples();
1036 const size_t numOutputs = program.fragmentShader->getOutputs().size();
1037 FragmentProcessor fragProcessor;
1039 DE_ASSERT(fragmentOutputArray.size() >= (size_t)numRasterizedPackets*4*numOutputs);
1040 DE_ASSERT(fragmentBuffer.size() >= (size_t)numRasterizedPackets*4);
1042 // Translate fragments but do not set the value yet
1045 for (int packetNdx = 0; packetNdx < numRasterizedPackets; ++packetNdx)
1046 for (int fragNdx = 0; fragNdx < 4; fragNdx++)
1048 const FragmentPacket& packet = fragmentPackets[packetNdx];
1049 const int xo = fragNdx%2;
1050 const int yo = fragNdx/2;
1052 if (getCoverageAnyFragmentSampleLive(packet.coverage, numSamples, xo, yo))
1054 Fragment& fragment = fragmentBuffer[fragCount++];
1056 fragment.pixelCoord = packet.position + tcu::IVec2(xo, yo);
1057 fragment.coverage = (deUint32)((packet.coverage & getCoverageFragmentSampleBits(numSamples, xo, yo)) >> getCoverageOffset(numSamples, xo, yo));
1058 fragment.sampleDepths = (depthValues) ? (&depthValues[(packetNdx*4 + yo*2 + xo)*numSamples]) : (DE_NULL);
1063 // Set per output output values
1065 rr::FragmentOperationState noStencilDepthWriteState(state.fragOps);
1066 noStencilDepthWriteState.depthMask = false;
1067 noStencilDepthWriteState.stencilStates[facetype].sFail = STENCILOP_KEEP;
1068 noStencilDepthWriteState.stencilStates[facetype].dpFail = STENCILOP_KEEP;
1069 noStencilDepthWriteState.stencilStates[facetype].dpPass = STENCILOP_KEEP;
1072 for (size_t outputNdx = 0; outputNdx < numOutputs; ++outputNdx)
1074 // Only the last output-pass has default state, other passes have stencil & depth writemask=0
1075 const rr::FragmentOperationState& fragOpsState = (outputNdx == numOutputs-1) ? (state.fragOps) : (noStencilDepthWriteState);
1077 for (int packetNdx = 0; packetNdx < numRasterizedPackets; ++packetNdx)
1078 for (int fragNdx = 0; fragNdx < 4; fragNdx++)
1080 const FragmentPacket& packet = fragmentPackets[packetNdx];
1081 const int xo = fragNdx%2;
1082 const int yo = fragNdx/2;
1084 // Add only fragments that have live samples to shaded fragments queue.
1085 if (getCoverageAnyFragmentSampleLive(packet.coverage, numSamples, xo, yo))
1087 Fragment& fragment = fragmentBuffer[fragCount++];
1088 fragment.value = fragmentOutputArray[(packetNdx*4 + fragNdx) * numOutputs + outputNdx];
1092 // Execute per-fragment ops and write
1093 fragProcessor.render(renderTarget.getColorBuffer((int)outputNdx), renderTarget.getDepthBuffer(), renderTarget.getStencilBuffer(), &fragmentBuffer[0], fragCount, facetype, fragOpsState);
1098 void rasterizePrimitive (const RenderState& state,
1099 const RenderTarget& renderTarget,
1100 const Program& program,
1101 const pa::Triangle& triangle,
1102 const tcu::IVec4& renderTargetRect,
1103 RasterizationInternalBuffers& buffers)
1105 const int numSamples = renderTarget.getNumSamples();
1106 const float depthClampMin = de::min(state.viewport.zn, state.viewport.zf);
1107 const float depthClampMax = de::max(state.viewport.zn, state.viewport.zf);
1108 TriangleRasterizer rasterizer (renderTargetRect, numSamples, state.rasterization);
1109 float depthOffset = 0.0f;
1111 rasterizer.init(triangle.v0->position, triangle.v1->position, triangle.v2->position);
1114 const FaceType visibleFace = rasterizer.getVisibleFace();
1115 if ((state.cullMode == CULLMODE_FRONT && visibleFace == FACETYPE_FRONT) ||
1116 (state.cullMode == CULLMODE_BACK && visibleFace == FACETYPE_BACK))
1120 FragmentShadingContext shadingContext(triangle.v0->outputs, triangle.v1->outputs, triangle.v2->outputs, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, triangle.v2->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
1123 if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
1125 const float maximumDepthSlope = findPrimitiveMaximumDepthSlope(triangle);
1126 const float minimumResolvableDifference = findPrimitiveMinimumResolvableDifference(triangle, renderTarget.getDepthBuffer());
1128 depthOffset = maximumDepthSlope * state.fragOps.polygonOffsetFactor + minimumResolvableDifference * state.fragOps.polygonOffsetUnits;
1131 // Execute rasterize - shade - write loop
1134 const int maxFragmentPackets = (int)buffers.fragmentPackets.size();
1135 int numRasterizedPackets = 0;
1139 rasterizer.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
1141 // numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
1143 if (!numRasterizedPackets)
1144 break; // Rasterization finished.
1147 if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
1148 for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1149 buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx] + depthOffset, 0.0f, 1.0f);
1153 program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
1156 if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
1157 for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1158 buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
1160 // Handle fragment shader outputs
1162 writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets, visibleFace, buffers.shaderOutputs, buffers.fragmentDepthBuffer, buffers.shadedFragments);
1166 void rasterizePrimitive (const RenderState& state,
1167 const RenderTarget& renderTarget,
1168 const Program& program,
1169 const pa::Line& line,
1170 const tcu::IVec4& renderTargetRect,
1171 RasterizationInternalBuffers& buffers)
1173 const int numSamples = renderTarget.getNumSamples();
1174 const float depthClampMin = de::min(state.viewport.zn, state.viewport.zf);
1175 const float depthClampMax = de::max(state.viewport.zn, state.viewport.zf);
1176 const bool msaa = numSamples > 1;
1177 FragmentShadingContext shadingContext (line.v0->outputs, line.v1->outputs, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, line.v1->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
1178 SingleSampleLineRasterizer aliasedRasterizer (renderTargetRect);
1179 MultiSampleLineRasterizer msaaRasterizer (numSamples, renderTargetRect);
1181 // Initialize rasterization.
1183 msaaRasterizer.init(line.v0->position, line.v1->position, state.line.lineWidth);
1185 aliasedRasterizer.init(line.v0->position, line.v1->position, state.line.lineWidth);
1189 const int maxFragmentPackets = (int)buffers.fragmentPackets.size();
1190 int numRasterizedPackets = 0;
1195 msaaRasterizer.rasterize (&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
1197 aliasedRasterizer.rasterize (&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
1199 // numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
1201 if (!numRasterizedPackets)
1202 break; // Rasterization finished.
1206 program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
1209 if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
1210 for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1211 buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
1213 // Handle fragment shader outputs
1215 writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets, rr::FACETYPE_FRONT, buffers.shaderOutputs, buffers.fragmentDepthBuffer, buffers.shadedFragments);
1219 void rasterizePrimitive (const RenderState& state,
1220 const RenderTarget& renderTarget,
1221 const Program& program,
1222 const pa::Point& point,
1223 const tcu::IVec4& renderTargetRect,
1224 RasterizationInternalBuffers& buffers)
1226 const int numSamples = renderTarget.getNumSamples();
1227 const float depthClampMin = de::min(state.viewport.zn, state.viewport.zf);
1228 const float depthClampMax = de::max(state.viewport.zn, state.viewport.zf);
1229 TriangleRasterizer rasterizer1 (renderTargetRect, numSamples, state.rasterization);
1230 TriangleRasterizer rasterizer2 (renderTargetRect, numSamples, state.rasterization);
1232 // draw point as two triangles
1233 const float offset = point.v0->pointSize / 2.0f;
1234 const tcu::Vec4 w0 = tcu::Vec4(point.v0->position.x() + offset, point.v0->position.y() + offset, point.v0->position.z(), point.v0->position.w());
1235 const tcu::Vec4 w1 = tcu::Vec4(point.v0->position.x() - offset, point.v0->position.y() + offset, point.v0->position.z(), point.v0->position.w());
1236 const tcu::Vec4 w2 = tcu::Vec4(point.v0->position.x() - offset, point.v0->position.y() - offset, point.v0->position.z(), point.v0->position.w());
1237 const tcu::Vec4 w3 = tcu::Vec4(point.v0->position.x() + offset, point.v0->position.y() - offset, point.v0->position.z(), point.v0->position.w());
1239 rasterizer1.init(w0, w1, w2);
1240 rasterizer2.init(w0, w2, w3);
1243 FragmentShadingContext shadingContext(point.v0->outputs, DE_NULL, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, point.v0->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
1245 // Execute rasterize - shade - write loop
1248 const int maxFragmentPackets = (int)buffers.fragmentPackets.size();
1249 int numRasterizedPackets = 0;
1251 // Rasterize both triangles
1253 rasterizer1.rasterize(&buffers.fragmentPackets[0], buffers.fragmentDepthBuffer, maxFragmentPackets, numRasterizedPackets);
1254 if (numRasterizedPackets != maxFragmentPackets)
1256 float* const depthBufferAppendPointer = (buffers.fragmentDepthBuffer) ? (buffers.fragmentDepthBuffer + numRasterizedPackets*numSamples*4) : (DE_NULL);
1257 int numRasterizedPackets2 = 0;
1259 rasterizer2.rasterize(&buffers.fragmentPackets[numRasterizedPackets], depthBufferAppendPointer, maxFragmentPackets - numRasterizedPackets, numRasterizedPackets2);
1261 numRasterizedPackets += numRasterizedPackets2;
1264 // numRasterizedPackets is guaranteed to be greater than zero for shadeFragments()
1266 if (!numRasterizedPackets)
1267 break; // Rasterization finished.
1271 program.fragmentShader->shadeFragments(&buffers.fragmentPackets[0], numRasterizedPackets, shadingContext);
1274 if (buffers.fragmentDepthBuffer && state.fragOps.depthClampEnabled)
1275 for (int sampleNdx = 0; sampleNdx < numRasterizedPackets * 4 * numSamples; ++sampleNdx)
1276 buffers.fragmentDepthBuffer[sampleNdx] = de::clamp(buffers.fragmentDepthBuffer[sampleNdx], depthClampMin, depthClampMax);
1278 // Handle fragment shader outputs
1280 writeFragmentPackets(state, renderTarget, program, &buffers.fragmentPackets[0], numRasterizedPackets, rr::FACETYPE_FRONT, buffers.shaderOutputs, buffers.fragmentDepthBuffer, buffers.shadedFragments);
1284 template <typename ContainerType>
1285 void rasterize (const RenderState& state,
1286 const RenderTarget& renderTarget,
1287 const Program& program,
1288 const ContainerType& list)
1290 const int numSamples = renderTarget.getNumSamples();
1291 const int numFragmentOutputs = (int)program.fragmentShader->getOutputs().size();
1292 const size_t maxFragmentPackets = 128;
1294 const tcu::IVec4 viewportRect = tcu::IVec4(state.viewport.rect.left, state.viewport.rect.bottom, state.viewport.rect.width, state.viewport.rect.height);
1295 const tcu::IVec4 bufferRect = getBufferSize(renderTarget.getColorBuffer(0));
1296 const tcu::IVec4 renderTargetRect = rectIntersection(viewportRect, bufferRect);
1298 // shared buffers for all primitives
1299 std::vector<FragmentPacket> fragmentPackets (maxFragmentPackets);
1300 std::vector<GenericVec4> shaderOutputs (maxFragmentPackets*4*numFragmentOutputs);
1301 std::vector<Fragment> shadedFragments (maxFragmentPackets*4);
1302 std::vector<float> depthValues (0);
1303 float* depthBufferPointer = DE_NULL;
1305 RasterizationInternalBuffers buffers;
1307 // calculate depth only if we have a depth buffer
1308 if (!isEmpty(renderTarget.getDepthBuffer()))
1310 depthValues.resize(maxFragmentPackets*4*numSamples);
1311 depthBufferPointer = &depthValues[0];
1315 buffers.fragmentPackets.swap(fragmentPackets);
1316 buffers.shaderOutputs.swap(shaderOutputs);
1317 buffers.shadedFragments.swap(shadedFragments);
1318 buffers.fragmentDepthBuffer = depthBufferPointer;
1321 for (typename ContainerType::const_iterator it = list.begin(); it != list.end(); ++it)
1322 rasterizePrimitive(state, renderTarget, program, *it, renderTargetRect, buffers);
1325 /*--------------------------------------------------------------------*//*!
1326 * Draws transformed triangles, lines or points to render target
1327 *//*--------------------------------------------------------------------*/
1328 template <typename ContainerType>
1329 void drawBasicPrimitives (const RenderState& state, const RenderTarget& renderTarget, const Program& program, ContainerType& primList, VertexPacketAllocator& vpalloc)
1331 const bool clipZ = !state.fragOps.depthClampEnabled;
1333 // Transform feedback
1336 flatshadeVertices(program, primList);
1339 // \todo [jarkko] is creating & swapping std::vectors really a good solution?
1340 clipPrimitives(primList, program, clipZ, vpalloc);
1342 // Transform vertices to window coords
1343 transformClipCoordsToWindowCoords(state, primList);
1345 // Rasterize and paint
1346 rasterize(state, renderTarget, program, primList);
1349 void copyVertexPacketPointers(const VertexPacket** dst, const pa::Point& in)
1354 void copyVertexPacketPointers(const VertexPacket** dst, const pa::Line& in)
1360 void copyVertexPacketPointers(const VertexPacket** dst, const pa::Triangle& in)
1367 void copyVertexPacketPointers(const VertexPacket** dst, const pa::LineAdjacency& in)
1375 void copyVertexPacketPointers(const VertexPacket** dst, const pa::TriangleAdjacency& in)
1385 template <PrimitiveType DrawPrimitiveType> // \note DrawPrimitiveType can only be Points, line_strip, or triangle_strip
1386 void drawGeometryShaderOutputAsPrimitives (const RenderState& state, const RenderTarget& renderTarget, const Program& program, VertexPacket* const* vertices, size_t numVertices, VertexPacketAllocator& vpalloc)
1388 // Run primitive assembly for generated stream
1390 const size_t assemblerPrimitiveCount = PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::getPrimitiveCount(numVertices);
1391 std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::BaseType> inputPrimitives (assemblerPrimitiveCount);
1393 PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::exec(inputPrimitives.begin(), vertices, numVertices, state.provokingVertexConvention); // \note input Primitives are baseType_t => only basic primitives (non adjacency) will compile
1395 // Make shared vertices distinct
1397 makeSharedVerticesDistinct(inputPrimitives, vpalloc);
1399 // Draw assembled primitives
1401 drawBasicPrimitives(state, renderTarget, program, inputPrimitives, vpalloc);
1404 template <PrimitiveType DrawPrimitiveType>
1405 void drawWithGeometryShader(const RenderState& state, const RenderTarget& renderTarget, const Program& program, std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type>& input, DrawContext& drawContext)
1407 // Vertices outputted by geometry shader may have different number of output variables than the original, create new memory allocator
1408 VertexPacketAllocator vpalloc(program.geometryShader->getOutputs().size());
1410 // Run geometry shader for all primitives
1411 GeometryEmitter emitter (vpalloc, program.geometryShader->getNumVerticesOut());
1412 std::vector<PrimitivePacket> primitives (input.size());
1413 const int numInvocations = (int)program.geometryShader->getNumInvocations();
1414 const int verticesIn = PrimitiveTypeTraits<DrawPrimitiveType>::Type::NUM_VERTICES;
1416 for (size_t primitiveNdx = 0; primitiveNdx < input.size(); ++primitiveNdx)
1418 primitives[primitiveNdx].primitiveIDIn = drawContext.primitiveID++;
1419 copyVertexPacketPointers(primitives[primitiveNdx].vertices, input[primitiveNdx]);
1422 if (primitives.empty())
1425 for (int invocationNdx = 0; invocationNdx < numInvocations; ++invocationNdx)
1427 // Shading invocation
1429 program.geometryShader->shadePrimitives(emitter, verticesIn, &primitives[0], (int)primitives.size(), invocationNdx);
1431 // Find primitives in the emitted vertices
1433 std::vector<VertexPacket*> emitted;
1434 emitter.moveEmittedTo(emitted);
1436 for (size_t primitiveBegin = 0; primitiveBegin < emitted.size();)
1438 size_t primitiveEnd;
1440 // Find primitive begin
1441 if (!emitted[primitiveBegin])
1447 // Find primitive end
1449 primitiveEnd = primitiveBegin + 1;
1450 for (; (primitiveEnd < emitted.size()) && emitted[primitiveEnd]; ++primitiveEnd); // find primitive end
1452 // Draw range [begin, end)
1454 switch (program.geometryShader->getOutputType())
1456 case rr::GEOMETRYSHADEROUTPUTTYPE_POINTS: drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_POINTS> (state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd-primitiveBegin, vpalloc); break;
1457 case rr::GEOMETRYSHADEROUTPUTTYPE_LINE_STRIP: drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_LINE_STRIP> (state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd-primitiveBegin, vpalloc); break;
1458 case rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP: drawGeometryShaderOutputAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP> (state, renderTarget, program, &emitted[primitiveBegin], primitiveEnd-primitiveBegin, vpalloc); break;
1460 DE_ASSERT(DE_FALSE);
1464 primitiveBegin = primitiveEnd + 1;
1469 /*--------------------------------------------------------------------*//*!
1470 * Assembles, tesselates, runs geometry shader and draws primitives of any type from vertex list.
1471 *//*--------------------------------------------------------------------*/
1472 template <PrimitiveType DrawPrimitiveType>
1473 void drawAsPrimitives (const RenderState& state, const RenderTarget& renderTarget, const Program& program, VertexPacket* const* vertices, int numVertices, DrawContext& drawContext, VertexPacketAllocator& vpalloc)
1475 // Assemble primitives (deconstruct stips & loops)
1476 const size_t assemblerPrimitiveCount = PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::getPrimitiveCount(numVertices);
1477 std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::Type> inputPrimitives (assemblerPrimitiveCount);
1479 PrimitiveTypeTraits<DrawPrimitiveType>::Assembler::exec(inputPrimitives.begin(), vertices, (size_t)numVertices, state.provokingVertexConvention);
1482 //if (state.tesselation)
1483 // primList = state.tesselation.exec(primList);
1486 if (program.geometryShader)
1488 // If there is an active geometry shader, it will convert any primitive type to basic types
1489 drawWithGeometryShader<DrawPrimitiveType>(state, renderTarget, program, inputPrimitives, drawContext);
1493 std::vector<typename PrimitiveTypeTraits<DrawPrimitiveType>::BaseType> basePrimitives;
1495 // convert types from X_adjacency to X
1496 convertPrimitiveToBaseType(basePrimitives, inputPrimitives);
1498 // Make shared vertices distinct. Needed for that the translation to screen space happens only once per vertex, and for flatshading
1499 makeSharedVerticesDistinct(basePrimitives, vpalloc);
1501 // A primitive ID will be generated even if no geometry shader is active
1502 generatePrimitiveIDs(basePrimitives, drawContext);
1504 // Draw as a basic type
1505 drawBasicPrimitives(state, renderTarget, program, basePrimitives, vpalloc);
1509 bool isValidCommand (const DrawCommand& command, int numInstances)
1511 // numInstances should be valid
1512 if (numInstances < 1)
1515 // Shaders should have the same varyings
1516 if (command.program.geometryShader)
1518 if (command.program.vertexShader->getOutputs() != command.program.geometryShader->getInputs())
1521 if (command.program.geometryShader->getOutputs() != command.program.fragmentShader->getInputs())
1526 if (command.program.vertexShader->getOutputs() != command.program.fragmentShader->getInputs())
1530 // Shader input/output types are set
1531 for (size_t varyingNdx = 0; varyingNdx < command.program.vertexShader->getInputs().size(); ++varyingNdx)
1532 if (command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1533 command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1534 command.program.vertexShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1536 for (size_t varyingNdx = 0; varyingNdx < command.program.vertexShader->getOutputs().size(); ++varyingNdx)
1537 if (command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1538 command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1539 command.program.vertexShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1542 for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getInputs().size(); ++varyingNdx)
1543 if (command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1544 command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1545 command.program.fragmentShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1547 for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getOutputs().size(); ++varyingNdx)
1548 if (command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1549 command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1550 command.program.fragmentShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1553 if (command.program.geometryShader)
1555 for (size_t varyingNdx = 0; varyingNdx < command.program.geometryShader->getInputs().size(); ++varyingNdx)
1556 if (command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1557 command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1558 command.program.geometryShader->getInputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1560 for (size_t varyingNdx = 0; varyingNdx < command.program.geometryShader->getOutputs().size(); ++varyingNdx)
1561 if (command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_FLOAT &&
1562 command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_INT32 &&
1563 command.program.geometryShader->getOutputs()[varyingNdx].type != GENERICVECTYPE_UINT32)
1567 // Enough vertex inputs?
1568 if ((size_t)command.numVertexAttribs < command.program.vertexShader->getInputs().size())
1571 // There is a fragment output sink for each output?
1572 if ((size_t)command.renderTarget.getNumColorBuffers() < command.program.fragmentShader->getOutputs().size())
1575 // All destination buffers should have same number of samples and same size
1576 for (int outputNdx = 0; outputNdx < command.renderTarget.getNumColorBuffers(); ++outputNdx)
1578 if (getBufferSize(command.renderTarget.getColorBuffer(0)) != getBufferSize(command.renderTarget.getColorBuffer(outputNdx)))
1581 if (command.renderTarget.getNumSamples() != command.renderTarget.getColorBuffer(outputNdx).getNumSamples())
1585 // All destination buffers should have same basic type as matching fragment output
1586 for (size_t varyingNdx = 0; varyingNdx < command.program.fragmentShader->getOutputs().size(); ++varyingNdx)
1588 const tcu::TextureChannelClass colorbufferClass = tcu::getTextureChannelClass(command.renderTarget.getColorBuffer((int)varyingNdx).raw().getFormat().type);
1589 const GenericVecType colorType = (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? (rr::GENERICVECTYPE_INT32) : ((colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (rr::GENERICVECTYPE_UINT32) : (rr::GENERICVECTYPE_FLOAT));
1591 if (command.program.fragmentShader->getOutputs()[varyingNdx].type != colorType)
1595 // Integer values are flatshaded
1596 for (size_t outputNdx = 0; outputNdx < command.program.vertexShader->getOutputs().size(); ++outputNdx)
1598 if (!command.program.vertexShader->getOutputs()[outputNdx].flatshade &&
1599 (command.program.vertexShader->getOutputs()[outputNdx].type == GENERICVECTYPE_INT32 ||
1600 command.program.vertexShader->getOutputs()[outputNdx].type == GENERICVECTYPE_UINT32))
1603 if (command.program.geometryShader)
1604 for (size_t outputNdx = 0; outputNdx < command.program.geometryShader->getOutputs().size(); ++outputNdx)
1606 if (!command.program.geometryShader->getOutputs()[outputNdx].flatshade &&
1607 (command.program.geometryShader->getOutputs()[outputNdx].type == GENERICVECTYPE_INT32 ||
1608 command.program.geometryShader->getOutputs()[outputNdx].type == GENERICVECTYPE_UINT32))
1612 // Draw primitive is valid for geometry shader
1613 if (command.program.geometryShader)
1615 if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && command.primitives.getPrimitiveType() != PRIMITIVETYPE_POINTS)
1618 if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
1619 (command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINES &&
1620 command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_STRIP &&
1621 command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_LOOP))
1624 if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
1625 (command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLES &&
1626 command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_STRIP &&
1627 command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_FAN))
1630 if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
1631 (command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINES_ADJACENCY &&
1632 command.primitives.getPrimitiveType() != PRIMITIVETYPE_LINE_STRIP_ADJACENCY))
1635 if (command.program.geometryShader->getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
1636 (command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLES_ADJACENCY &&
1637 command.primitives.getPrimitiveType() != PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY))
1646 RenderTarget::RenderTarget (const MultisamplePixelBufferAccess& colorMultisampleBuffer,
1647 const MultisamplePixelBufferAccess& depthMultisampleBuffer,
1648 const MultisamplePixelBufferAccess& stencilMultisampleBuffer)
1649 : m_numColorBuffers (1)
1650 , m_depthBuffer (MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(depthMultisampleBuffer.raw(), tcu::Sampler::MODE_DEPTH)))
1651 , m_stencilBuffer (MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(stencilMultisampleBuffer.raw(), tcu::Sampler::MODE_STENCIL)))
1653 m_colorBuffers[0] = colorMultisampleBuffer;
1656 int RenderTarget::getNumSamples (void) const
1658 DE_ASSERT(m_numColorBuffers > 0);
1659 return m_colorBuffers[0].getNumSamples();
1662 DrawIndices::DrawIndices (const deUint32* ptr, int baseVertex_)
1664 , indexType (INDEXTYPE_UINT32)
1665 , baseVertex(baseVertex_)
1669 DrawIndices::DrawIndices (const deUint16* ptr, int baseVertex_)
1671 , indexType (INDEXTYPE_UINT16)
1672 , baseVertex(baseVertex_)
1676 DrawIndices::DrawIndices (const deUint8* ptr, int baseVertex_)
1678 , indexType (INDEXTYPE_UINT8)
1679 , baseVertex(baseVertex_)
1683 DrawIndices::DrawIndices (const void* ptr, IndexType type, int baseVertex_)
1686 , baseVertex(baseVertex_)
1690 PrimitiveList::PrimitiveList (PrimitiveType primitiveType, int numElements, const int firstElement)
1691 : m_primitiveType (primitiveType)
1692 , m_numElements (numElements)
1693 , m_indices (DE_NULL)
1694 , m_indexType (INDEXTYPE_LAST)
1695 , m_baseVertex (firstElement)
1697 DE_ASSERT(numElements >= 0 && "Invalid numElements");
1698 DE_ASSERT(firstElement >= 0 && "Invalid firstElement");
1701 PrimitiveList::PrimitiveList (PrimitiveType primitiveType, int numElements, const DrawIndices& indices)
1702 : m_primitiveType (primitiveType)
1703 , m_numElements ((size_t)numElements)
1704 , m_indices (indices.indices)
1705 , m_indexType (indices.indexType)
1706 , m_baseVertex (indices.baseVertex)
1708 DE_ASSERT(numElements >= 0 && "Invalid numElements");
1711 size_t PrimitiveList::getIndex (size_t elementNdx) const
1713 // indices == DE_NULL interpreted as command.indices = [first (=baseVertex) + 0, first + 1, first + 2...]
1716 int index = m_baseVertex + (int)readIndexArray(m_indexType, m_indices, elementNdx);
1717 DE_ASSERT(index >= 0); // do not access indices < 0
1719 return (size_t)index;
1722 return (size_t)(m_baseVertex) + elementNdx;
1725 bool PrimitiveList::isRestartIndex (size_t elementNdx, deUint32 restartIndex) const
1727 // implicit index or explicit index (without base vertex) equals restart
1729 return readIndexArray(m_indexType, m_indices, elementNdx) == restartIndex;
1731 return elementNdx == (size_t)restartIndex;
1734 Renderer::Renderer (void)
1738 Renderer::~Renderer (void)
1742 void Renderer::draw (const DrawCommand& command) const
1744 drawInstanced(command, 1);
1747 void Renderer::drawInstanced (const DrawCommand& command, int numInstances) const
1749 // Do not run bad commands
1751 const bool validCommand = isValidCommand(command, numInstances);
1759 // Do not draw if nothing to draw
1761 if (command.primitives.getNumElements() == 0 || numInstances == 0)
1765 // Prepare transformation
1767 const size_t numVaryings = command.program.vertexShader->getOutputs().size();
1768 VertexPacketAllocator vpalloc(numVaryings);
1769 std::vector<VertexPacket*> vertexPackets = vpalloc.allocArray(command.primitives.getNumElements());
1770 DrawContext drawContext;
1772 for (int instanceID = 0; instanceID < numInstances; ++instanceID)
1774 // Each instance has its own primitives
1775 drawContext.primitiveID = 0;
1777 for (size_t elementNdx = 0; elementNdx < command.primitives.getNumElements(); ++elementNdx)
1779 int numVertexPackets = 0;
1781 // collect primitive vertices until restart
1783 while (elementNdx < command.primitives.getNumElements() &&
1784 !(command.state.restart.enabled && command.primitives.isRestartIndex(elementNdx, command.state.restart.restartIndex)))
1787 vertexPackets[numVertexPackets]->instanceNdx = instanceID;
1788 vertexPackets[numVertexPackets]->vertexNdx = (int)command.primitives.getIndex(elementNdx);
1791 vertexPackets[numVertexPackets]->pointSize = command.state.point.pointSize; // default value from the current state
1792 vertexPackets[numVertexPackets]->position = tcu::Vec4(0, 0, 0, 0); // no undefined values
1798 // Duplicated restart shade
1799 if (numVertexPackets == 0)
1802 // \todo Vertex cache?
1804 // Transform vertices
1806 command.program.vertexShader->shadeVertices(command.vertexAttribs, &vertexPackets[0], numVertexPackets);
1810 switch (command.primitives.getPrimitiveType())
1812 case PRIMITIVETYPE_TRIANGLES: { drawAsPrimitives<PRIMITIVETYPE_TRIANGLES> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1813 case PRIMITIVETYPE_TRIANGLE_STRIP: { drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1814 case PRIMITIVETYPE_TRIANGLE_FAN: { drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_FAN> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1815 case PRIMITIVETYPE_LINES: { drawAsPrimitives<PRIMITIVETYPE_LINES> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1816 case PRIMITIVETYPE_LINE_STRIP: { drawAsPrimitives<PRIMITIVETYPE_LINE_STRIP> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1817 case PRIMITIVETYPE_LINE_LOOP: { drawAsPrimitives<PRIMITIVETYPE_LINE_LOOP> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1818 case PRIMITIVETYPE_POINTS: { drawAsPrimitives<PRIMITIVETYPE_POINTS> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1819 case PRIMITIVETYPE_LINES_ADJACENCY: { drawAsPrimitives<PRIMITIVETYPE_LINES_ADJACENCY> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1820 case PRIMITIVETYPE_LINE_STRIP_ADJACENCY: { drawAsPrimitives<PRIMITIVETYPE_LINE_STRIP_ADJACENCY> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1821 case PRIMITIVETYPE_TRIANGLES_ADJACENCY: { drawAsPrimitives<PRIMITIVETYPE_TRIANGLES_ADJACENCY> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1822 case PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:{ drawAsPrimitives<PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY> (command.state, command.renderTarget, command.program, &vertexPackets[0], numVertexPackets, drawContext, vpalloc); break; }
1824 DE_ASSERT(DE_FALSE);