#ifndef _RRSHADINGCONTEXT_HPP #define _RRSHADINGCONTEXT_HPP /*------------------------------------------------------------------------- * drawElements Quality Program Reference Renderer * ----------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Shading context *//*--------------------------------------------------------------------*/ #include "rrDefs.hpp" #include "rrGenericVector.hpp" #include "rrFragmentPacket.hpp" namespace rr { /*--------------------------------------------------------------------*//*! * \brief Fragment shading context * * Contains per-primitive information used in fragment shading *//*--------------------------------------------------------------------*/ struct FragmentShadingContext { FragmentShadingContext (const GenericVec4* varying0, const GenericVec4* varying1, const GenericVec4* varying2, GenericVec4* outputArray, float* fragmentDepths, int primitiveID, int numFragmentOutputs, int numSamples, FaceType visibleFace_); const GenericVec4* varyings[3]; //!< Vertex shader outputs. Pointer will be NULL if there is no such vertex. GenericVec4* const outputArray; //!< Fragment output array const int primitiveID; //!< Geometry shader output const int numFragmentOutputs; //!< Fragment output count const int numSamples; //!< Number of samples float* fragmentDepths; //!< Fragment packet depths. Pointer will be NULL if there is no depth buffer. Each sample has per-sample depth values FaceType visibleFace; //!< Which face (front or back) is visible }; // Write output template void writeFragmentOutput (const FragmentShadingContext& context, int packetNdx, int fragNdx, int outputNdx, const T& value) { DE_ASSERT(packetNdx >= 0); DE_ASSERT(fragNdx >= 0 && fragNdx < 4); DE_ASSERT(outputNdx >= 0 && outputNdx < context.numFragmentOutputs); context.outputArray[outputNdx + context.numFragmentOutputs*(fragNdx + packetNdx*4)] = value; } // Read Varying template tcu::Vector readPointVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx) { DE_UNREF(fragNdx); DE_UNREF(packet); return context.varyings[0][varyingLoc].get(); } template tcu::Vector readLineVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx) { return packet.barycentric[0][fragNdx] * context.varyings[0][varyingLoc].get() + packet.barycentric[1][fragNdx] * context.varyings[1][varyingLoc].get(); } template tcu::Vector readTriangleVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx) { return packet.barycentric[0][fragNdx] * context.varyings[0][varyingLoc].get() + packet.barycentric[1][fragNdx] * context.varyings[1][varyingLoc].get() + packet.barycentric[2][fragNdx] * context.varyings[2][varyingLoc].get(); } template tcu::Vector readVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx) { if (context.varyings[1] == DE_NULL) return readPointVarying (packet, context, varyingLoc, fragNdx); if (context.varyings[2] == DE_NULL) return readLineVarying (packet, context, varyingLoc, fragNdx); return readTriangleVarying (packet, context, varyingLoc, fragNdx); } // Derivative template void dFdxLocal (tcu::Vector outFragmentdFdx[4], const tcu::Vector func[4]) { const tcu::Vector dFdx[2] = { func[1] - func[0], func[3] - func[2] }; outFragmentdFdx[0] = dFdx[0]; outFragmentdFdx[1] = dFdx[0]; outFragmentdFdx[2] = dFdx[1]; outFragmentdFdx[3] = dFdx[1]; } template void dFdyLocal (tcu::Vector outFragmentdFdy[4], const tcu::Vector func[4]) { const tcu::Vector dFdy[2] = { func[2] - func[0], func[3] - func[1] }; outFragmentdFdy[0] = dFdy[0]; outFragmentdFdy[1] = dFdy[1]; outFragmentdFdy[2] = dFdy[0]; outFragmentdFdy[3] = dFdy[1]; } template inline void dFdxVarying (tcu::Vector outFragmentdFdx[4], const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc) { const tcu::Vector func[4] = { readVarying(packet, context, varyingLoc, 0), readVarying(packet, context, varyingLoc, 1), readVarying(packet, context, varyingLoc, 2), readVarying(packet, context, varyingLoc, 3), }; dFdxLocal(outFragmentdFdx, func); } template inline void dFdyVarying (tcu::Vector outFragmentdFdy[4], const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc) { const tcu::Vector func[4] = { readVarying(packet, context, varyingLoc, 0), readVarying(packet, context, varyingLoc, 1), readVarying(packet, context, varyingLoc, 2), readVarying(packet, context, varyingLoc, 3), }; dFdyLocal(outFragmentdFdy, func); } // Fragent depth inline float readFragmentDepth (const FragmentShadingContext& context, int packetNdx, int fragNdx, int sampleNdx) { // Reading or writing to fragment depth values while there is no depth buffer is legal but not supported by rr DE_ASSERT(context.fragmentDepths); return context.fragmentDepths[(packetNdx * 4 + fragNdx) * context.numSamples + sampleNdx]; } inline void writeFragmentDepth (const FragmentShadingContext& context, int packetNdx, int fragNdx, int sampleNdx, float depthValue) { // Reading or writing to fragment depth values while there is no depth buffer is legal but not supported by rr DE_ASSERT(context.fragmentDepths); context.fragmentDepths[(packetNdx * 4 + fragNdx) * context.numSamples + sampleNdx] = depthValue; } } // rr #endif // _RRSHADINGCONTEXT_HPP