1#ifndef _RRSHADINGCONTEXT_HPP
2#define _RRSHADINGCONTEXT_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program Reference Renderer
5 * -----------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Shading context
24 *//*--------------------------------------------------------------------*/
25
26#include "rrDefs.hpp"
27#include "rrGenericVector.hpp"
28#include "rrFragmentPacket.hpp"
29
30namespace rr
31{
32
33/*--------------------------------------------------------------------*//*!
34 * \brief Fragment shading context
35 *
36 * Contains per-primitive information used in fragment shading
37 *//*--------------------------------------------------------------------*/
38struct FragmentShadingContext
39{
40								FragmentShadingContext (const GenericVec4* varying0, const GenericVec4* varying1, const GenericVec4* varying2, GenericVec4* outputArray, GenericVec4* outputArraySrc1, float* fragmentDepths, int primitiveID, int numFragmentOutputs, int numSamples, FaceType visibleFace_);
41
42	const GenericVec4*			varyings[3];		//!< Vertex shader outputs. Pointer will be NULL if there is no such vertex.
43	GenericVec4* const			outputArray;		//!< Fragment output array
44	GenericVec4* const			outputArraySrc1;	//!< Fragment output array for source 1.
45	const int					primitiveID;		//!< Geometry shader output
46	const int					numFragmentOutputs;	//!< Fragment output count
47	const int					numSamples;			//!< Number of samples
48	float*						fragmentDepths;		//!< Fragment packet depths. Pointer will be NULL if there is no depth buffer. Each sample has per-sample depth values
49	FaceType					visibleFace;		//!< Which face (front or back) is visible
50};
51
52// Write output
53
54template <typename T>
55void writeFragmentOutput (const FragmentShadingContext& context, int packetNdx, int fragNdx, int outputNdx, const T& value)
56{
57	DE_ASSERT(packetNdx >= 0);
58	DE_ASSERT(fragNdx >= 0 && fragNdx < 4);
59	DE_ASSERT(outputNdx >= 0 && outputNdx < context.numFragmentOutputs);
60
61	context.outputArray[outputNdx + context.numFragmentOutputs*(fragNdx + packetNdx*4)] = value;
62}
63
64template <typename T>
65void writeFragmentOutputDualSource (const FragmentShadingContext& context, int packetNdx, int fragNdx, int outputNdx, const T& value, const T& value1)
66{
67	DE_ASSERT(packetNdx >= 0);
68	DE_ASSERT(fragNdx >= 0 && fragNdx < 4);
69	DE_ASSERT(outputNdx >= 0 && outputNdx < context.numFragmentOutputs);
70
71	context.outputArray[outputNdx + context.numFragmentOutputs*(fragNdx + packetNdx*4)] = value;
72	context.outputArraySrc1[outputNdx + context.numFragmentOutputs*(fragNdx + packetNdx*4)] = value1;
73}
74
75// Read Varying
76
77template <typename T>
78tcu::Vector<T, 4> readPointVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx)
79{
80	DE_UNREF(fragNdx);
81	DE_UNREF(packet);
82
83	return context.varyings[0][varyingLoc].get<T>();
84}
85
86template <typename T>
87tcu::Vector<T, 4> readLineVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx)
88{
89	return   packet.barycentric[0][fragNdx] * context.varyings[0][varyingLoc].get<T>()
90		   + packet.barycentric[1][fragNdx] * context.varyings[1][varyingLoc].get<T>();
91}
92
93template <typename T>
94tcu::Vector<T, 4> readTriangleVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx)
95{
96	return   packet.barycentric[0][fragNdx] * context.varyings[0][varyingLoc].get<T>()
97		   + packet.barycentric[1][fragNdx] * context.varyings[1][varyingLoc].get<T>()
98		   + packet.barycentric[2][fragNdx] * context.varyings[2][varyingLoc].get<T>();
99}
100
101template <typename T>
102tcu::Vector<T, 4> readVarying (const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc, int fragNdx)
103{
104	if (context.varyings[1] == DE_NULL)	return readPointVarying<T>		(packet, context, varyingLoc, fragNdx);
105	if (context.varyings[2] == DE_NULL)	return readLineVarying<T>		(packet, context, varyingLoc, fragNdx);
106										return readTriangleVarying<T>	(packet, context, varyingLoc, fragNdx);
107}
108
109// Derivative
110
111template <typename T, int Size>
112void dFdxLocal (tcu::Vector<T, Size> outFragmentdFdx[4], const tcu::Vector<T, Size> func[4])
113{
114	const tcu::Vector<T, Size> dFdx[2] =
115	{
116		func[1] - func[0],
117		func[3] - func[2]
118	};
119
120	outFragmentdFdx[0] = dFdx[0];
121	outFragmentdFdx[1] = dFdx[0];
122	outFragmentdFdx[2] = dFdx[1];
123	outFragmentdFdx[3] = dFdx[1];
124}
125
126template <typename T, int Size>
127void dFdyLocal (tcu::Vector<T, Size> outFragmentdFdy[4], const tcu::Vector<T, Size> func[4])
128{
129	const tcu::Vector<T, Size> dFdy[2] =
130	{
131		func[2] - func[0],
132		func[3] - func[1]
133	};
134
135	outFragmentdFdy[0] = dFdy[0];
136	outFragmentdFdy[1] = dFdy[1];
137	outFragmentdFdy[2] = dFdy[0];
138	outFragmentdFdy[3] = dFdy[1];
139}
140
141template <typename T>
142inline void dFdxVarying (tcu::Vector<T, 4> outFragmentdFdx[4], const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc)
143{
144	const tcu::Vector<T, 4> func[4] =
145	{
146		readVarying<T>(packet, context, varyingLoc, 0),
147		readVarying<T>(packet, context, varyingLoc, 1),
148		readVarying<T>(packet, context, varyingLoc, 2),
149		readVarying<T>(packet, context, varyingLoc, 3),
150	};
151
152	dFdxLocal(outFragmentdFdx, func);
153}
154
155template <typename T>
156inline void dFdyVarying (tcu::Vector<T, 4> outFragmentdFdy[4], const FragmentPacket& packet, const FragmentShadingContext& context, int varyingLoc)
157{
158	const tcu::Vector<T, 4> func[4] =
159	{
160		readVarying<T>(packet, context, varyingLoc, 0),
161		readVarying<T>(packet, context, varyingLoc, 1),
162		readVarying<T>(packet, context, varyingLoc, 2),
163		readVarying<T>(packet, context, varyingLoc, 3),
164	};
165
166	dFdyLocal(outFragmentdFdy, func);
167}
168
169// Fragent depth
170
171inline float readFragmentDepth (const FragmentShadingContext& context, int packetNdx, int fragNdx, int sampleNdx)
172{
173	// Reading or writing to fragment depth values while there is no depth buffer is legal but not supported by rr
174	DE_ASSERT(context.fragmentDepths);
175	return context.fragmentDepths[(packetNdx * 4 + fragNdx) * context.numSamples + sampleNdx];
176}
177
178inline void writeFragmentDepth (const FragmentShadingContext& context, int packetNdx, int fragNdx, int sampleNdx, float depthValue)
179{
180	// Reading or writing to fragment depth values while there is no depth buffer is legal but not supported by rr
181	DE_ASSERT(context.fragmentDepths);
182	context.fragmentDepths[(packetNdx * 4 + fragNdx) * context.numSamples + sampleNdx] = depthValue;
183}
184
185} // rr
186
187#endif // _RRSHADINGCONTEXT_HPP
188