| #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, GenericVec4 *outputArraySrc1, 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 |
| GenericVec4 *const outputArraySrc1; //!< Fragment output array for source 1. |
| 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 <typename T> |
| 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; |
| } |
| |
| template <typename T> |
| void writeFragmentOutputDualSource(const FragmentShadingContext &context, int packetNdx, int fragNdx, int outputNdx, |
| const T &value, const T &value1) |
| { |
| 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; |
| context.outputArraySrc1[outputNdx + context.numFragmentOutputs * (fragNdx + packetNdx * 4)] = value1; |
| } |
| |
| // Read Varying |
| |
| template <typename T> |
| tcu::Vector<T, 4> readPointVarying(const FragmentPacket &packet, const FragmentShadingContext &context, int varyingLoc, |
| int fragNdx) |
| { |
| DE_UNREF(fragNdx); |
| DE_UNREF(packet); |
| |
| return context.varyings[0][varyingLoc].get<T>(); |
| } |
| |
| template <typename T> |
| tcu::Vector<T, 4> readLineVarying(const FragmentPacket &packet, const FragmentShadingContext &context, int varyingLoc, |
| int fragNdx) |
| { |
| return packet.barycentric[0][fragNdx] * context.varyings[0][varyingLoc].get<T>() + |
| packet.barycentric[1][fragNdx] * context.varyings[1][varyingLoc].get<T>(); |
| } |
| |
| template <typename T> |
| tcu::Vector<T, 4> readTriangleVarying(const FragmentPacket &packet, const FragmentShadingContext &context, |
| int varyingLoc, int fragNdx) |
| { |
| return packet.barycentric[0][fragNdx] * context.varyings[0][varyingLoc].get<T>() + |
| packet.barycentric[1][fragNdx] * context.varyings[1][varyingLoc].get<T>() + |
| packet.barycentric[2][fragNdx] * context.varyings[2][varyingLoc].get<T>(); |
| } |
| |
| template <typename T> |
| tcu::Vector<T, 4> readVarying(const FragmentPacket &packet, const FragmentShadingContext &context, int varyingLoc, |
| int fragNdx) |
| { |
| if (context.varyings[1] == DE_NULL) |
| return readPointVarying<T>(packet, context, varyingLoc, fragNdx); |
| if (context.varyings[2] == DE_NULL) |
| return readLineVarying<T>(packet, context, varyingLoc, fragNdx); |
| return readTriangleVarying<T>(packet, context, varyingLoc, fragNdx); |
| } |
| |
| // Derivative |
| |
| template <typename T, int Size> |
| void dFdxLocal(tcu::Vector<T, Size> outFragmentdFdx[4], const tcu::Vector<T, Size> func[4]) |
| { |
| const tcu::Vector<T, Size> 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 <typename T, int Size> |
| void dFdyLocal(tcu::Vector<T, Size> outFragmentdFdy[4], const tcu::Vector<T, Size> func[4]) |
| { |
| const tcu::Vector<T, Size> 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 <typename T> |
| inline void dFdxVarying(tcu::Vector<T, 4> outFragmentdFdx[4], const FragmentPacket &packet, |
| const FragmentShadingContext &context, int varyingLoc) |
| { |
| const tcu::Vector<T, 4> func[4] = { |
| readVarying<T>(packet, context, varyingLoc, 0), |
| readVarying<T>(packet, context, varyingLoc, 1), |
| readVarying<T>(packet, context, varyingLoc, 2), |
| readVarying<T>(packet, context, varyingLoc, 3), |
| }; |
| |
| dFdxLocal(outFragmentdFdx, func); |
| } |
| |
| template <typename T> |
| inline void dFdyVarying(tcu::Vector<T, 4> outFragmentdFdy[4], const FragmentPacket &packet, |
| const FragmentShadingContext &context, int varyingLoc) |
| { |
| const tcu::Vector<T, 4> func[4] = { |
| readVarying<T>(packet, context, varyingLoc, 0), |
| readVarying<T>(packet, context, varyingLoc, 1), |
| readVarying<T>(packet, context, varyingLoc, 2), |
| readVarying<T>(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; |
| } |
| |
| } // namespace rr |
| |
| #endif // _RRSHADINGCONTEXT_HPP |