1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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 Simple Draw Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktDrawSimpleTest.hpp"
26
27#include "vktTestCaseUtil.hpp"
28#include "vktDrawTestCaseUtil.hpp"
29
30#include "vktDrawBaseClass.hpp"
31
32#include "tcuTestLog.hpp"
33#include "tcuResource.hpp"
34#include "tcuImageCompare.hpp"
35#include "tcuTextureUtil.hpp"
36#include "tcuRGBA.hpp"
37
38#include "vkDefs.hpp"
39
40namespace vkt
41{
42namespace Draw
43{
44namespace
45{
46class SimpleDraw : public DrawTestsBaseClass
47{
48public:
49	typedef TestSpecBase	TestSpec;
50							SimpleDraw				(Context &context, TestSpec testSpec);
51	virtual tcu::TestStatus iterate					(void);
52};
53
54class SimpleDrawInstanced : public SimpleDraw
55{
56public:
57	typedef TestSpec		TestSpec;
58							SimpleDrawInstanced		(Context &context, TestSpec testSpec);
59	tcu::TestStatus			iterate					(void);
60};
61
62SimpleDraw::SimpleDraw (Context &context, TestSpec testSpec)
63	: DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
64{
65	m_data.push_back(VertexElementData(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
66	m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
67
68	int refVertexIndex = 2;
69
70	switch (m_topology)
71	{
72		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
73			m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,	-0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
74			m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,	 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
75			m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,	-0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
76			m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,	-0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
77			m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,	 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
78			m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,	 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
79			break;
80		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
81			m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,	-0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
82			m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,	 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
83			m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,	-0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
84			m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,	 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
85			m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,	 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
86			break;
87		case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
88		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
89		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
90		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
91		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
92		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
93		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
94		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
95		case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
96		case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
97			DE_FATAL("Topology not implemented");
98			break;
99		default:
100			DE_FATAL("Unknown topology");
101			break;
102	}
103
104	m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
105
106	initialize();
107}
108
109tcu::TestStatus SimpleDraw::iterate (void)
110{
111	tcu::TestLog &log							= m_context.getTestContext().getLog();
112	const vk::VkQueue queue						= m_context.getUniversalQueue();
113
114	beginRenderPass();
115
116	const vk::VkDeviceSize vertexBufferOffset	= 0;
117	const vk::VkBuffer vertexBuffer				= m_vertexBuffer->object();
118
119	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
120	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
121
122	switch (m_topology)
123	{
124		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
125			m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 2, 0);
126			break;
127		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
128			m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 2, 0);
129			break;
130		case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
131		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
132		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
133		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
134		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
135		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
136		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
137		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
138		case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
139		case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
140			DE_FATAL("Topology not implemented");
141			break;
142		default:
143			DE_FATAL("Unknown topology");
144			break;
145	}
146
147	m_vk.cmdEndRenderPass(*m_cmdBuffer);
148	m_vk.endCommandBuffer(*m_cmdBuffer);
149
150	vk::VkSubmitInfo submitInfo =
151	{
152		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
153		DE_NULL,							// const void*				pNext;
154		0,										// deUint32					waitSemaphoreCount;
155		DE_NULL,								// const VkSemaphore*		pWaitSemaphores;
156		(const vk::VkPipelineStageFlags*)DE_NULL,
157		1,										// deUint32					commandBufferCount;
158		&m_cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
159		0,										// deUint32					signalSemaphoreCount;
160		DE_NULL								// const VkSemaphore*		pSignalSemaphores;
161	};
162	VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
163
164	VK_CHECK(m_vk.queueWaitIdle(queue));
165
166	// Validation
167	tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
168
169	referenceFrame.allocLevel(0);
170
171	const deInt32 frameWidth	= referenceFrame.getWidth();
172	const deInt32 frameHeight	= referenceFrame.getHeight();
173
174	tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
175
176	ReferenceImageCoordinates refCoords;
177
178	for (int y = 0; y < frameHeight; y++)
179	{
180		const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
181
182		for (int x = 0; x < frameWidth; x++)
183		{
184			const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
185
186			if ((yCoord >= refCoords.bottom	&&
187				 yCoord <= refCoords.top	&&
188				 xCoord >= refCoords.left	&&
189				 xCoord <= refCoords.right))
190				referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
191		}
192	}
193
194	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
195	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
196		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
197
198	qpTestResult res = QP_TEST_RESULT_PASS;
199
200	if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
201		referenceFrame.getLevel(0), renderedFrame, 0.05f,
202		tcu::COMPARE_LOG_RESULT)) {
203		res = QP_TEST_RESULT_FAIL;
204	}
205
206	return tcu::TestStatus(res, qpGetTestResultName(res));
207
208}
209
210SimpleDrawInstanced::SimpleDrawInstanced (Context &context, TestSpec testSpec)
211	: SimpleDraw	(context, testSpec) {}
212
213tcu::TestStatus SimpleDrawInstanced::iterate (void)
214{
215	tcu::TestLog &log		= m_context.getTestContext().getLog();
216
217	const vk::VkQueue queue = m_context.getUniversalQueue();
218
219	beginRenderPass();
220
221	const vk::VkDeviceSize vertexBufferOffset = 0;
222	const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
223
224	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
225
226	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
227
228	switch (m_topology)
229	{
230		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
231			m_vk.cmdDraw(*m_cmdBuffer, 6, 4, 2, 2);
232			break;
233		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
234			m_vk.cmdDraw(*m_cmdBuffer, 4, 4, 2, 2);
235			break;
236		case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
237		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
238		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
239		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
240		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
241		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
242		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
243		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
244		case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
245		case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
246			DE_FATAL("Topology not implemented");
247			break;
248		default:
249			DE_FATAL("Unknown topology");
250			break;
251	}
252
253	m_vk.cmdEndRenderPass(*m_cmdBuffer);
254	m_vk.endCommandBuffer(*m_cmdBuffer);
255
256	vk::VkSubmitInfo submitInfo =
257	{
258		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
259		DE_NULL,							// const void*				pNext;
260		0,										// deUint32					waitSemaphoreCount;
261		DE_NULL,								// const VkSemaphore*		pWaitSemaphores;
262		(const vk::VkPipelineStageFlags*)DE_NULL,
263		1,										// deUint32					commandBufferCount;
264		&m_cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
265		0,										// deUint32					signalSemaphoreCount;
266		DE_NULL								// const VkSemaphore*		pSignalSemaphores;
267	};
268	VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
269
270	VK_CHECK(m_vk.queueWaitIdle(queue));
271
272	// Validation
273	VK_CHECK(m_vk.queueWaitIdle(queue));
274
275	tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
276
277	referenceFrame.allocLevel(0);
278
279	const deInt32 frameWidth	= referenceFrame.getWidth();
280	const deInt32 frameHeight	= referenceFrame.getHeight();
281
282	tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
283
284	ReferenceImageInstancedCoordinates refInstancedCoords;
285
286	for (int y = 0; y < frameHeight; y++)
287	{
288		const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
289
290		for (int x = 0; x < frameWidth; x++)
291		{
292			const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
293
294			if ((yCoord >= refInstancedCoords.bottom	&&
295				 yCoord <= refInstancedCoords.top		&&
296				 xCoord >= refInstancedCoords.left		&&
297				 xCoord <= refInstancedCoords.right))
298				referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
299		}
300	}
301
302	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
303	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
304		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
305
306	qpTestResult res = QP_TEST_RESULT_PASS;
307
308	if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
309		referenceFrame.getLevel(0), renderedFrame, 0.05f,
310		tcu::COMPARE_LOG_RESULT)) {
311		res = QP_TEST_RESULT_FAIL;
312	}
313
314	return tcu::TestStatus(res, qpGetTestResultName(res));
315}
316
317}	// anonymous
318
319SimpleDrawTests::SimpleDrawTests (tcu::TestContext &testCtx)
320: TestCaseGroup	(testCtx, "simple_draw", "drawing simple geometry")
321{
322	/* Left blank on purpose */
323}
324
325SimpleDrawTests::~SimpleDrawTests (void) {}
326
327
328void SimpleDrawTests::init (void)
329{
330	{
331		SimpleDraw::TestSpec testSpec;
332		testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetch.vert";
333		testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
334
335		testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
336		addChild(new InstanceFactory<SimpleDraw>(m_testCtx, "simple_draw_triangle_list", "Draws triangle list", testSpec));
337		testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
338		addChild(new InstanceFactory<SimpleDraw>(m_testCtx, "simple_draw_triangle_strip", "Draws triangle strip", testSpec));
339	}
340	{
341		SimpleDrawInstanced::TestSpec testSpec;
342		testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
343		testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
344
345		testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
346		addChild(new InstanceFactory<SimpleDrawInstanced>(m_testCtx, "simple_draw_instanced_triangle_list", "Draws an instanced triangle list", testSpec));
347		testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
348		addChild(new InstanceFactory<SimpleDrawInstanced>(m_testCtx, "simple_draw_instanced_triangle_strip", "Draws an instanced triangle strip", testSpec));
349	}
350}
351
352}	// DrawTests
353}	// vkt
354