1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Reference renderer.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineReferenceRenderer.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "rrShadingContext.hpp"
28 #include "rrVertexAttrib.hpp"
29 
30 namespace vkt
31 {
32 namespace pipeline
33 {
34 
35 using namespace vk;
36 
mapVkBlendFactor(VkBlendFactor blend)37 rr::BlendFunc mapVkBlendFactor (VkBlendFactor blend)
38 {
39 	switch (blend)
40 	{
41 		case VK_BLEND_FACTOR_ZERO:						return rr::BLENDFUNC_ZERO;
42 		case VK_BLEND_FACTOR_ONE:						return rr::BLENDFUNC_ONE;
43 		case VK_BLEND_FACTOR_SRC_COLOR:					return rr::BLENDFUNC_SRC_COLOR;
44 		case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:		return rr::BLENDFUNC_ONE_MINUS_SRC_COLOR;
45 		case VK_BLEND_FACTOR_DST_COLOR:					return rr::BLENDFUNC_DST_COLOR;
46 		case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:		return rr::BLENDFUNC_ONE_MINUS_DST_COLOR;
47 		case VK_BLEND_FACTOR_SRC_ALPHA:					return rr::BLENDFUNC_SRC_ALPHA;
48 		case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:		return rr::BLENDFUNC_ONE_MINUS_SRC_ALPHA;
49 		case VK_BLEND_FACTOR_DST_ALPHA:					return rr::BLENDFUNC_DST_ALPHA;
50 		case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:		return rr::BLENDFUNC_ONE_MINUS_DST_ALPHA;
51 		case VK_BLEND_FACTOR_CONSTANT_COLOR:			return rr::BLENDFUNC_CONSTANT_COLOR;
52 		case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:	return rr::BLENDFUNC_ONE_MINUS_CONSTANT_COLOR;
53 		case VK_BLEND_FACTOR_CONSTANT_ALPHA:			return rr::BLENDFUNC_CONSTANT_ALPHA;
54 		case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:	return rr::BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA;
55 		case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:		return rr::BLENDFUNC_SRC_ALPHA_SATURATE;
56 		case VK_BLEND_FACTOR_SRC1_COLOR:				return rr::BLENDFUNC_SRC1_COLOR;
57 		case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:		return rr::BLENDFUNC_ONE_MINUS_SRC1_COLOR;
58 		case VK_BLEND_FACTOR_SRC1_ALPHA:				return rr::BLENDFUNC_SRC1_ALPHA;
59 		case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:		return rr::BLENDFUNC_ONE_MINUS_SRC1_ALPHA;
60 		default:
61 			DE_ASSERT(false);
62 	}
63 	return rr::BLENDFUNC_LAST;
64 }
65 
mapVkBlendOp(VkBlendOp blendOp)66 rr::BlendEquation mapVkBlendOp (VkBlendOp blendOp)
67 {
68 	switch (blendOp)
69 	{
70 		case VK_BLEND_OP_ADD:					return rr::BLENDEQUATION_ADD;
71 		case VK_BLEND_OP_SUBTRACT:				return rr::BLENDEQUATION_SUBTRACT;
72 		case VK_BLEND_OP_REVERSE_SUBTRACT:		return rr::BLENDEQUATION_REVERSE_SUBTRACT;
73 		case VK_BLEND_OP_MIN:					return rr::BLENDEQUATION_MIN;
74 		case VK_BLEND_OP_MAX:					return rr::BLENDEQUATION_MAX;
75 		default:
76 			DE_ASSERT(false);
77 	}
78 	return rr::BLENDEQUATION_LAST;
79 }
80 
mapVkColorComponentFlags(VkColorComponentFlags flags)81 tcu::BVec4 mapVkColorComponentFlags (VkColorComponentFlags flags)
82 {
83 	return tcu::BVec4((flags & VK_COLOR_COMPONENT_R_BIT) != 0,
84 					  (flags & VK_COLOR_COMPONENT_G_BIT) != 0,
85 					  (flags & VK_COLOR_COMPONENT_B_BIT) != 0,
86 					  (flags & VK_COLOR_COMPONENT_A_BIT) != 0);
87 }
88 
mapVkCompareOp(VkCompareOp compareFunc)89 rr::TestFunc mapVkCompareOp (VkCompareOp compareFunc)
90 {
91 	switch (compareFunc)
92 	{
93 		case VK_COMPARE_OP_NEVER:				return rr::TESTFUNC_NEVER;
94 		case VK_COMPARE_OP_LESS:				return rr::TESTFUNC_LESS;
95 		case VK_COMPARE_OP_EQUAL:				return rr::TESTFUNC_EQUAL;
96 		case VK_COMPARE_OP_LESS_OR_EQUAL:		return rr::TESTFUNC_LEQUAL;
97 		case VK_COMPARE_OP_GREATER:				return rr::TESTFUNC_GREATER;
98 		case VK_COMPARE_OP_NOT_EQUAL:			return rr::TESTFUNC_NOTEQUAL;
99 		case VK_COMPARE_OP_GREATER_OR_EQUAL:	return rr::TESTFUNC_GEQUAL;
100 		case VK_COMPARE_OP_ALWAYS:				return rr::TESTFUNC_ALWAYS;
101 		default:
102 			DE_ASSERT(false);
103 	}
104 	return rr::TESTFUNC_LAST;
105 }
106 
mapVkPrimitiveTopology(VkPrimitiveTopology primitiveTopology)107 rr::PrimitiveType mapVkPrimitiveTopology (VkPrimitiveTopology primitiveTopology)
108 {
109 	switch (primitiveTopology)
110 	{
111 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:						return rr::PRIMITIVETYPE_POINTS;
112 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						return rr::PRIMITIVETYPE_LINES;
113 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:						return rr::PRIMITIVETYPE_LINE_STRIP;
114 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					return rr::PRIMITIVETYPE_TRIANGLES;
115 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:					return rr::PRIMITIVETYPE_TRIANGLE_FAN;
116 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:					return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
117 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINES_ADJACENCY;
118 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
119 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
120 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
121 		default:
122 			DE_ASSERT(false);
123 	}
124 	return rr::PRIMITIVETYPE_LAST;
125 }
126 
mapVkStencilOp(vk::VkStencilOp stencilOp)127 rr::StencilOp mapVkStencilOp (vk::VkStencilOp stencilOp)
128 {
129 	switch (stencilOp)
130 	{
131 		case VK_STENCIL_OP_KEEP:					return rr::STENCILOP_KEEP;
132 		case VK_STENCIL_OP_ZERO:					return rr::STENCILOP_ZERO;
133 		case VK_STENCIL_OP_REPLACE:					return rr::STENCILOP_REPLACE;
134 		case VK_STENCIL_OP_INCREMENT_AND_CLAMP:		return rr::STENCILOP_INCR;
135 		case VK_STENCIL_OP_DECREMENT_AND_CLAMP:		return rr::STENCILOP_DECR;
136 		case VK_STENCIL_OP_INVERT:					return rr::STENCILOP_INVERT;
137 		case VK_STENCIL_OP_INCREMENT_AND_WRAP:		return rr::STENCILOP_INCR_WRAP;
138 		case VK_STENCIL_OP_DECREMENT_AND_WRAP:		return rr::STENCILOP_DECR_WRAP;
139 		default:
140 			DE_ASSERT(false);
141 	}
142 	return rr::STENCILOP_LAST;
143 }
144 
swizzle(const tcu::Vec4 & color,const tcu::UVec4 & swizzle)145 tcu::Vec4 swizzle (const tcu::Vec4& color, const tcu::UVec4& swizzle)
146 {
147 	const float channelValues[] =
148 	{
149 		0.0f,
150 		1.0f,
151 		color.x(),
152 		color.y(),
153 		color.z(),
154 		color.w()
155 	};
156 
157 	return tcu::Vec4(channelValues[swizzle.x()],
158 					 channelValues[swizzle.y()],
159 					 channelValues[swizzle.z()],
160 					 channelValues[swizzle.w()]);
161 }
162 
ReferenceRenderer(int surfaceWidth,int surfaceHeight,int numSamples,const tcu::TextureFormat & colorFormat,const tcu::TextureFormat & depthStencilFormat,const rr::Program * const program)163 ReferenceRenderer::ReferenceRenderer(int						surfaceWidth,
164 									 int						surfaceHeight,
165 									 int						numSamples,
166 									 const tcu::TextureFormat&	colorFormat,
167 									 const tcu::TextureFormat&	depthStencilFormat,
168 									 const rr::Program* const	program)
169 	: m_surfaceWidth		(surfaceWidth)
170 	, m_surfaceHeight		(surfaceHeight)
171 	, m_numSamples			(numSamples)
172 	, m_colorFormat			(colorFormat)
173 	, m_depthStencilFormat	(depthStencilFormat)
174 	, m_program				(program)
175 {
176 	const tcu::TextureChannelClass	formatClass				= tcu::getTextureChannelClass(colorFormat.type);
177 	const bool						hasDepthStencil			= (m_depthStencilFormat.order != tcu::TextureFormat::CHANNELORDER_LAST);
178 	const bool						hasDepthBufferOnly		= (m_depthStencilFormat.order == tcu::TextureFormat::D);
179 	const bool						hasStencilBufferOnly	= (m_depthStencilFormat.order == tcu::TextureFormat::S);
180 	const int						actualSamples			= (formatClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || formatClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)? 1: m_numSamples;
181 
182 	m_colorBuffer.setStorage(m_colorFormat, actualSamples, m_surfaceWidth, m_surfaceHeight);
183 	m_resolveColorBuffer.setStorage(m_colorFormat, m_surfaceWidth, m_surfaceHeight);
184 
185 	if (formatClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
186 	{
187 		tcu::clear(m_colorBuffer.getAccess(), defaultClearColorInt(m_colorFormat));
188 		tcu::clear(m_resolveColorBuffer.getAccess(), defaultClearColorInt(m_colorFormat));
189 	}
190 	else if (formatClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
191 	{
192 		tcu::clear(m_colorBuffer.getAccess(), defaultClearColorUint(m_colorFormat));
193 		tcu::clear(m_resolveColorBuffer.getAccess(), defaultClearColorUint(m_colorFormat));
194 	}
195 	else
196 	{
197 		tcu::Vec4 clearColor = defaultClearColor(m_colorFormat);
198 
199 		if (isSRGB(m_colorFormat))
200 			clearColor = tcu::linearToSRGB(clearColor);
201 
202 		tcu::clear(m_colorBuffer.getAccess(), clearColor);
203 		tcu::clear(m_resolveColorBuffer.getAccess(), clearColor);
204 	}
205 
206 	if (hasDepthStencil)
207 	{
208 		if (hasDepthBufferOnly)
209 		{
210 			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
211 			tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());
212 
213 			m_resolveDepthStencilBuffer.setStorage(m_depthStencilFormat, surfaceWidth, surfaceHeight);
214 			tcu::clearDepth(m_resolveDepthStencilBuffer.getAccess(), defaultClearDepth());
215 
216 			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
217 												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
218 		}
219 		else if (hasStencilBufferOnly)
220 		{
221 			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
222 			tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());
223 
224 			m_resolveDepthStencilBuffer.setStorage(m_depthStencilFormat, surfaceWidth, surfaceHeight);
225 			tcu::clearStencil(m_resolveDepthStencilBuffer.getAccess(), defaultClearStencil());
226 
227 			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
228 												  rr::MultisamplePixelBufferAccess(),
229 												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
230 		}
231 		else
232 		{
233 			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
234 
235 			tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());
236 			tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());
237 
238 			m_resolveDepthStencilBuffer.setStorage(m_depthStencilFormat, surfaceWidth, surfaceHeight);
239 			tcu::clearDepth(m_resolveDepthStencilBuffer.getAccess(), defaultClearDepth());
240 
241 			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
242 												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()),
243 												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
244 		}
245 	}
246 	else
247 	{
248 		m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()));
249 	}
250 }
251 
~ReferenceRenderer(void)252 ReferenceRenderer::~ReferenceRenderer (void)
253 {
254 	delete m_renderTarget;
255 }
256 
colorClear(const tcu::Vec4 & color)257 void ReferenceRenderer::colorClear(const tcu::Vec4& color)
258 {
259 	tcu::clear(m_colorBuffer.getAccess(), color);
260 	tcu::clear(m_resolveColorBuffer.getAccess(), color);
261 }
262 
draw(const rr::RenderState & renderState,const rr::PrimitiveType primitive,const std::vector<Vertex4RGBA> & vertexBuffer)263 void ReferenceRenderer::draw (const rr::RenderState&			renderState,
264 							  const rr::PrimitiveType			primitive,
265 							  const std::vector<Vertex4RGBA>&	vertexBuffer)
266 {
267 	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
268 
269 	std::vector<tcu::Vec4> positions;
270 	std::vector<tcu::Vec4> colors;
271 
272 	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
273 	{
274 		const Vertex4RGBA& v = vertexBuffer[vertexNdx];
275 		positions.push_back(v.position);
276 		colors.push_back(v.color);
277 	}
278 
279 	rr::VertexAttrib vertexAttribs[2];
280 
281 	// Position attribute
282 	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
283 	vertexAttribs[0].size		= 4;
284 	vertexAttribs[0].pointer	= positions.data();
285 	// UV attribute
286 	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
287 	vertexAttribs[1].size		= 4;
288 	vertexAttribs[1].pointer	= colors.data();
289 
290 	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);
291 
292 	m_renderer.draw(drawQuadCommand);
293 }
draw(const rr::RenderState & renderState,const rr::PrimitiveType primitive,const std::vector<Vertex4RGBARGBA> & vertexBuffer)294 void ReferenceRenderer::draw (const rr::RenderState&				renderState,
295 							  const rr::PrimitiveType				primitive,
296 							  const std::vector<Vertex4RGBARGBA>&	vertexBuffer)
297 {
298 	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
299 
300 	std::vector<tcu::Vec4> positions;
301 	std::vector<tcu::Vec4> color0s;
302 	std::vector<tcu::Vec4> color1s;
303 
304 	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
305 	{
306 		const Vertex4RGBARGBA& v = vertexBuffer[vertexNdx];
307 		positions.push_back(v.position);
308 		color0s.push_back(v.color0);
309 		color1s.push_back(v.color1);
310 	}
311 
312 	rr::VertexAttrib vertexAttribs[3];
313 
314 	// Position attribute
315 	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
316 	vertexAttribs[0].size		= 4;
317 	vertexAttribs[0].pointer	= positions.data();
318 	// Color0 attribute
319 	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
320 	vertexAttribs[1].size		= 4;
321 	vertexAttribs[1].pointer	= color0s.data();
322 	// Color1 attribute
323 	vertexAttribs[2].type		= rr::VERTEXATTRIBTYPE_FLOAT;
324 	vertexAttribs[2].size		= 4;
325 	vertexAttribs[2].pointer	= color1s.data();
326 
327 	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 3, vertexAttribs, primitives);
328 
329 	m_renderer.draw(drawQuadCommand);
330 }
331 
draw(const rr::RenderState & renderState,const rr::PrimitiveType primitive,const std::vector<Vertex4Tex4> & vertexBuffer)332 void ReferenceRenderer::draw (const rr::RenderState&			renderState,
333 							  const rr::PrimitiveType			primitive,
334 							  const std::vector<Vertex4Tex4>&	vertexBuffer)
335 {
336 	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
337 
338 	std::vector<tcu::Vec4> positions;
339 	std::vector<tcu::Vec4> texCoords;
340 
341 	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
342 	{
343 		const Vertex4Tex4& v = vertexBuffer[vertexNdx];
344 		positions.push_back(v.position);
345 		texCoords.push_back(v.texCoord);
346 	}
347 
348 	rr::VertexAttrib vertexAttribs[2];
349 
350 	// Position attribute
351 	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
352 	vertexAttribs[0].size		= 4;
353 	vertexAttribs[0].pointer	= positions.data();
354 	// UV attribute
355 	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
356 	vertexAttribs[1].size		= 4;
357 	vertexAttribs[1].pointer	= texCoords.data();
358 
359 	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);
360 
361 	m_renderer.draw(drawQuadCommand);
362 }
363 
getAccess(void)364 tcu::PixelBufferAccess ReferenceRenderer::getAccess (void)
365 {
366 	rr::MultisampleConstPixelBufferAccess multiSampleAccess = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess());
367 	rr::resolveMultisampleColorBuffer(m_resolveColorBuffer.getAccess(), multiSampleAccess);
368 
369 	return m_resolveColorBuffer.getAccess();
370 }
371 
getDepthStencilAccess(void)372 tcu::PixelBufferAccess ReferenceRenderer::getDepthStencilAccess (void)
373 {
374 	rr::MultisampleConstPixelBufferAccess multiSampleAccess = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess());
375 	rr::resolveMultisampleColorBuffer(m_resolveDepthStencilBuffer.getAccess(), multiSampleAccess);
376 
377 	return m_resolveDepthStencilBuffer.getAccess();
378 }
379 
getViewportState(void) const380 const rr::ViewportState ReferenceRenderer::getViewportState (void) const
381 {
382 	return rr::ViewportState(rr::WindowRectangle(0, 0, m_surfaceWidth, m_surfaceHeight));
383 }
384 
385 } // pipeline
386 } // vkt
387