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