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
30namespace vkt
31{
32namespace pipeline
33{
34
35using namespace vk;
36
37rr::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
66rr::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
81tcu::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
89rr::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
107rr::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
127rr::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
145tcu::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
163ReferenceRenderer::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_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
214												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
215		}
216		else if (hasStencilBufferOnly)
217		{
218			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
219			tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());
220
221			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
222												  rr::MultisamplePixelBufferAccess(),
223												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
224		}
225		else
226		{
227			m_depthStencilBuffer.setStorage(m_depthStencilFormat, actualSamples, surfaceWidth, surfaceHeight);
228
229			tcu::clearDepth(m_depthStencilBuffer.getAccess(), defaultClearDepth());
230			tcu::clearStencil(m_depthStencilBuffer.getAccess(), defaultClearStencil());
231
232			m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()),
233												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()),
234												  rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_depthStencilBuffer.getAccess()));
235		}
236	}
237	else
238	{
239		m_renderTarget = new rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess()));
240	}
241}
242
243ReferenceRenderer::~ReferenceRenderer (void)
244{
245	delete m_renderTarget;
246}
247
248void ReferenceRenderer::colorClear(const tcu::Vec4& color)
249{
250	tcu::clear(m_colorBuffer.getAccess(), color);
251	tcu::clear(m_resolveColorBuffer.getAccess(), color);
252}
253
254void ReferenceRenderer::draw (const rr::RenderState&			renderState,
255							  const rr::PrimitiveType			primitive,
256							  const std::vector<Vertex4RGBA>&	vertexBuffer)
257{
258	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
259
260	std::vector<tcu::Vec4> positions;
261	std::vector<tcu::Vec4> colors;
262
263	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
264	{
265		const Vertex4RGBA& v = vertexBuffer[vertexNdx];
266		positions.push_back(v.position);
267		colors.push_back(v.color);
268	}
269
270	rr::VertexAttrib vertexAttribs[2];
271
272	// Position attribute
273	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
274	vertexAttribs[0].size		= 4;
275	vertexAttribs[0].pointer	= positions.data();
276	// UV attribute
277	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
278	vertexAttribs[1].size		= 4;
279	vertexAttribs[1].pointer	= colors.data();
280
281	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);
282
283	m_renderer.draw(drawQuadCommand);
284}
285
286void ReferenceRenderer::draw (const rr::RenderState&			renderState,
287							  const rr::PrimitiveType			primitive,
288							  const std::vector<Vertex4Tex4>&	vertexBuffer)
289{
290	const rr::PrimitiveList primitives(primitive, (int)vertexBuffer.size(), 0);
291
292	std::vector<tcu::Vec4> positions;
293	std::vector<tcu::Vec4> texCoords;
294
295	for (size_t vertexNdx = 0; vertexNdx < vertexBuffer.size(); vertexNdx++)
296	{
297		const Vertex4Tex4& v = vertexBuffer[vertexNdx];
298		positions.push_back(v.position);
299		texCoords.push_back(v.texCoord);
300	}
301
302	rr::VertexAttrib vertexAttribs[2];
303
304	// Position attribute
305	vertexAttribs[0].type		= rr::VERTEXATTRIBTYPE_FLOAT;
306	vertexAttribs[0].size		= 4;
307	vertexAttribs[0].pointer	= positions.data();
308	// UV attribute
309	vertexAttribs[1].type		= rr::VERTEXATTRIBTYPE_FLOAT;
310	vertexAttribs[1].size		= 4;
311	vertexAttribs[1].pointer	= texCoords.data();
312
313	rr::DrawCommand drawQuadCommand(renderState, *m_renderTarget, *m_program, 2, vertexAttribs, primitives);
314
315	m_renderer.draw(drawQuadCommand);
316}
317
318tcu::PixelBufferAccess ReferenceRenderer::getAccess (void)
319{
320	rr::MultisampleConstPixelBufferAccess multiSampleAccess = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(m_colorBuffer.getAccess());
321	rr::resolveMultisampleColorBuffer(m_resolveColorBuffer.getAccess(), multiSampleAccess);
322
323	return m_resolveColorBuffer.getAccess();
324}
325
326const rr::ViewportState ReferenceRenderer::getViewportState (void) const
327{
328	return rr::ViewportState(rr::WindowRectangle(0, 0, m_surfaceWidth, m_surfaceHeight));
329}
330
331} // pipeline
332} // vkt
333