• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Google Inc.
7  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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 Differing iterpolation decorations tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDrawDifferingInterpolationTests.hpp"
27 
28 #include "vktDrawBaseClass.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vktTestGroupUtil.hpp"
33 
34 #include "deDefs.h"
35 #include "deRandom.hpp"
36 #include "deString.h"
37 
38 #include "tcuTestCase.hpp"
39 #include "tcuRGBA.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuStringTemplate.hpp"
43 
44 #include "rrRenderer.hpp"
45 
46 #include <string>
47 #include <sstream>
48 
49 namespace vkt
50 {
51 namespace Draw
52 {
53 namespace
54 {
55 using namespace vk;
56 using namespace std;
57 
58 struct DrawParams
59 {
60 	string	vertShader;
61 	string	fragShader;
62 	string	refVertShader;
63 	string	refFragShader;
64 	bool	useDynamicRendering;
65 };
66 
67 class DrawTestInstance : public TestInstance
68 {
69 public:
70 						DrawTestInstance	(Context& context, const DrawParams& data);
71 						~DrawTestInstance	(void);
72 	tcu::TestStatus		iterate				(void);
73 private:
74 	DrawParams			m_data;
75 
76 	enum
77 	{
78 		WIDTH = 256,
79 		HEIGHT = 256
80 	};
81 };
82 
DrawTestInstance(Context & context,const DrawParams & data)83 DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
84 	: vkt::TestInstance		(context)
85 	, m_data				(data)
86 {
87 }
88 
~DrawTestInstance(void)89 DrawTestInstance::~DrawTestInstance (void)
90 {
91 }
92 
93 class DrawTestCase : public TestCase
94 {
95 	public:
96 								DrawTestCase		(tcu::TestContext& context, const char* name, const char* desc, const DrawParams data);
97 								~DrawTestCase		(void);
98 	virtual	void				initPrograms		(SourceCollections& programCollection) const;
99 	virtual void				checkSupport		(Context& context) const;
100 	virtual TestInstance*		createInstance		(Context& context) const;
101 
102 private:
103 	DrawParams					m_data;
104 };
105 
DrawTestCase(tcu::TestContext & context,const char * name,const char * desc,const DrawParams data)106 DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data)
107 	: vkt::TestCase	(context, name, desc)
108 	, m_data		(data)
109 {
110 }
111 
~DrawTestCase(void)112 DrawTestCase::~DrawTestCase	(void)
113 {
114 }
115 
initPrograms(SourceCollections & programCollection) const116 void DrawTestCase::initPrograms (SourceCollections& programCollection) const
117 {
118 	const tcu::StringTemplate	vertShader	(string(
119 		"#version 430\n"
120 		"layout(location = 0) in vec4 in_position;\n"
121 		"layout(location = 1) in vec4 in_color;\n"
122 		"layout(location = 0) ${qualifier:opt} out vec4 out_color;\n"
123 		"out gl_PerVertex {\n"
124 		"    vec4  gl_Position;\n"
125 		"    float gl_PointSize;\n"
126 		"};\n"
127 		"void main() {\n"
128 		"    gl_PointSize = 1.0;\n"
129 		"    gl_Position  = in_position;\n"
130 		"    out_color    = in_color;\n"
131 		"}\n"));
132 
133 	const tcu::StringTemplate	fragShader	(string(
134 		"#version 430\n"
135 		"layout(location = 0) ${qualifier:opt} in vec4 in_color;\n"
136 		"layout(location = 0) out vec4 out_color;\n"
137 		"void main()\n"
138 		"{\n"
139 		"    out_color = in_color;\n"
140 		"}\n"));
141 
142 	map<string, string> empty;
143 	map<string, string> flat;
144 	flat["qualifier"] = "flat";
145 	map<string, string> noPerspective;
146 	noPerspective["qualifier"] = "noperspective";
147 
148 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(empty));
149 	programCollection.glslSources.add("vertFlatColor") << glu::VertexSource(vertShader.specialize(flat));
150 	programCollection.glslSources.add("vertNoPerspective") << glu::VertexSource(vertShader.specialize(noPerspective));
151 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(empty));
152 	programCollection.glslSources.add("fragFlatColor") << glu::FragmentSource(fragShader.specialize(flat));
153 	programCollection.glslSources.add("fragNoPerspective") << glu::FragmentSource(fragShader.specialize(noPerspective));
154 }
155 
checkSupport(Context & context) const156 void DrawTestCase::checkSupport(Context& context) const
157 {
158 	if (m_data.useDynamicRendering)
159 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
160 }
161 
createInstance(Context & context) const162 TestInstance* DrawTestCase::createInstance (Context& context) const
163 {
164 	return new DrawTestInstance(context, m_data);
165 }
166 
iterate(void)167 tcu::TestStatus DrawTestInstance::iterate (void)
168 {
169 	tcu::ConstPixelBufferAccess	frames[2];
170 	de::SharedPtr<Image>		colorTargetImages[2];
171 	const string				vertShaderNames[2]	= { m_data.vertShader, m_data.refVertShader };
172 	const string				fragShaderNames[2]	= { m_data.fragShader, m_data.refFragShader };
173 	tcu::TestLog				&log				= m_context.getTestContext().getLog();
174 
175 	// Run two iterations with shaders that have different interpolation decorations. Images should still match.
176 	for (deUint32 frameIdx = 0; frameIdx < DE_LENGTH_OF_ARRAY(frames); frameIdx++)
177 	{
178 		const DeviceInterface&			vk						= m_context.getDeviceInterface();
179 		const VkDevice					device					= m_context.getDevice();
180 		const CmdPoolCreateInfo			cmdPoolCreateInfo		(m_context.getUniversalQueueFamilyIndex());
181 		Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, &cmdPoolCreateInfo);
182 		Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
183 		const Unique<VkShaderModule>	vs						(createShaderModule(vk, device, m_context.getBinaryCollection().get(vertShaderNames[frameIdx].c_str()), 0));
184 		const Unique<VkShaderModule>	fs						(createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShaderNames[frameIdx].c_str()), 0));
185 		const VkFormat					targetImageFormat		= VK_FORMAT_R8G8B8A8_UNORM;
186 		de::SharedPtr<Buffer>			vertexBuffer;
187 		Move<VkRenderPass>				renderPass;
188 		Move<VkImageView>				colorTargetView;
189 		Move<VkFramebuffer>				framebuffer;
190 		Move<VkPipeline>				pipeline;
191 
192 		// Create color buffer image.
193 		{
194 			const VkExtent3D				targetImageExtent		= { WIDTH, HEIGHT, 1 };
195 			const ImageCreateInfo			targetImageCreateInfo	(VK_IMAGE_TYPE_2D, targetImageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
196 				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
197 			colorTargetImages[frameIdx]								= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
198 		}
199 
200 		const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[frameIdx]->object(), VK_IMAGE_VIEW_TYPE_2D, targetImageFormat);
201 		colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
202 
203 		// Create render pass and frame buffer.
204 		if (!m_data.useDynamicRendering)
205 		{
206 			RenderPassCreateInfo			renderPassCreateInfo;
207 			renderPassCreateInfo.addAttachment(AttachmentDescription(targetImageFormat,
208 																	 VK_SAMPLE_COUNT_1_BIT,
209 																	 VK_ATTACHMENT_LOAD_OP_LOAD,
210 																	 VK_ATTACHMENT_STORE_OP_STORE,
211 																	 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
212 																	 VK_ATTACHMENT_STORE_OP_STORE,
213 																	 VK_IMAGE_LAYOUT_GENERAL,
214 																	 VK_IMAGE_LAYOUT_GENERAL));
215 
216 			const VkAttachmentReference		colorAttachmentRef		= { 0, VK_IMAGE_LAYOUT_GENERAL };
217 			renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
218 															   0,
219 															   0,
220 															   DE_NULL,
221 															   1,
222 															   &colorAttachmentRef,
223 															   DE_NULL,
224 															   AttachmentReference(),
225 															   0,
226 															   DE_NULL));
227 
228 			renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
229 
230 			vector<VkImageView>				colorAttachments		{ *colorTargetView };
231 			const FramebufferCreateInfo		framebufferCreateInfo	(*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
232 			framebuffer	= createFramebuffer(vk, device, &framebufferCreateInfo);
233 		}
234 
235 		// Create vertex buffer.
236 		{
237 			const PositionColorVertex	vertices[]	=
238 			{
239 				PositionColorVertex(
240 					tcu::Vec4(-0.8f, -0.7f, 1.0f, 1.0f),	// Coord
241 					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)),		// Color
242 
243 				PositionColorVertex(
244 					tcu::Vec4(0.0f, 0.4f, 0.5f, 0.5f),		// Coord
245 					tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)),		// Color
246 
247 				PositionColorVertex(
248 					tcu::Vec4(0.8f, -0.5f, 1.0f, 1.0f),		// Coord
249 					tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f))		// Color
250 			};
251 
252 			const VkDeviceSize			dataSize	= DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionColorVertex);
253 			vertexBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
254 			deUint8*					ptr			= reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
255 
256 			deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
257 			flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
258 		}
259 
260 		const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo;
261 		Move<VkPipelineLayout>			pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
262 
263 		// Create pipeline
264 		{
265 			const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
266 
267 			VkViewport	viewport	= makeViewport(WIDTH, HEIGHT);
268 			VkRect2D	scissor		= makeRect2D(WIDTH, HEIGHT);
269 
270 			const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
271 
272 			const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
273 			{
274 				{ 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
275 				{ 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float)* 4) }
276 			};
277 
278 			PipelineCreateInfo::VertexInputState vertexInputState	= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
279 
280 			PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
281 			pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
282 			pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
283 			pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
284 			pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
285 			pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
286 			pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
287 			pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
288 			pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
289 			pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
290 
291 			VkPipelineRenderingCreateInfoKHR renderingCreateInfo
292 			{
293 				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
294 				DE_NULL,
295 				0u,
296 				1u,
297 				&targetImageFormat,
298 				VK_FORMAT_UNDEFINED,
299 				VK_FORMAT_UNDEFINED
300 			};
301 
302 			if (m_data.useDynamicRendering)
303 				pipelineCreateInfo.pNext = &renderingCreateInfo;
304 
305 			pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
306 		}
307 
308 		// Queue draw and read results.
309 		{
310 			const VkQueue				queue				= m_context.getUniversalQueue();
311 			const VkClearValue			clearColor			= { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
312 			const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
313 			const VkMemoryBarrier		memBarrier			=
314 			{
315 				VK_STRUCTURE_TYPE_MEMORY_BARRIER,
316 				DE_NULL,
317 				VK_ACCESS_TRANSFER_WRITE_BIT,
318 				VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
319 			};
320 			const VkRect2D				renderArea			= makeRect2D(WIDTH, HEIGHT);
321 			const VkDeviceSize			vertexBufferOffset	= 0;
322 			const VkBuffer				buffer				= vertexBuffer->object();
323 			const VkOffset3D			zeroOffset			= { 0, 0, 0 };
324 
325 			beginCommandBuffer(vk, *cmdBuffer, 0u);
326 
327 			initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[frameIdx]->object(), VK_IMAGE_LAYOUT_GENERAL,
328 										  vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
329 
330 			vk.cmdClearColorImage(*cmdBuffer, colorTargetImages[frameIdx]->object(),
331 				VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);
332 
333 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
334 				VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
335 				0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
336 
337 			if (m_data.useDynamicRendering)
338 				beginRendering(vk, *cmdBuffer, *colorTargetView, renderArea, clearColor);
339 			else
340 				beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea);
341 
342 			vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
343 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
344 			vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
345 
346 			if (m_data.useDynamicRendering)
347 				endRendering(vk, *cmdBuffer);
348 			else
349 				endRenderPass(vk, *cmdBuffer);
350 
351 			endCommandBuffer(vk, *cmdBuffer);
352 
353 			submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
354 
355 			frames[frameIdx] = colorTargetImages[frameIdx]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
356 		}
357 	}
358 
359 	qpTestResult res = QP_TEST_RESULT_PASS;
360 
361 	if (!tcu::intThresholdCompare(log, "Result", "Image comparison result", frames[0], frames[1], tcu::UVec4(0), tcu::COMPARE_LOG_RESULT))
362 		res = QP_TEST_RESULT_FAIL;
363 
364 	return tcu::TestStatus(res, qpGetTestResultName(res));
365 }
366 
createTests(tcu::TestCaseGroup * testGroup,bool useDynamicRendering)367 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
368 {
369 	tcu::TestContext&	testCtx	= testGroup->getTestContext();
370 	const DrawParams	paramsFlat0	= { "vert", "fragFlatColor", "vertFlatColor", "fragFlatColor", useDynamicRendering };
371 	const DrawParams	paramsFlat1	= { "vertFlatColor", "frag", "vert", "frag", useDynamicRendering };
372 
373 	const DrawParams	paramsNoPerspective0	= { "vert", "fragNoPerspective", "vertNoPerspective", "fragNoPerspective", useDynamicRendering };
374 	const DrawParams	paramsNoPerspective1	= { "vertNoPerspective", "frag", "vert", "frag", useDynamicRendering };
375 
376 	testGroup->addChild(new DrawTestCase(testCtx, "flat_0", "Mismatching flat interpolation testcase 0.", paramsFlat0));
377 	testGroup->addChild(new DrawTestCase(testCtx, "flat_1", "Mismatching flat interpolation testcase 1.", paramsFlat1));
378 
379 	testGroup->addChild(new DrawTestCase(testCtx, "noperspective_0", "Mismatching noperspective interpolation testcase 0.", paramsNoPerspective0));
380 	testGroup->addChild(new DrawTestCase(testCtx, "noperspective_1", "Mismatching noperspective interpolation testcase 1.", paramsNoPerspective1));
381 }
382 
383 }	// anonymous
384 
createDifferingInterpolationTests(tcu::TestContext & testCtx,bool useDynamicRendering)385 tcu::TestCaseGroup*	createDifferingInterpolationTests (tcu::TestContext& testCtx, bool useDynamicRendering)
386 {
387 	return createTestGroup(testCtx, "differing_interpolation", "Tests for mismatched interpolation decorations.", createTests, useDynamicRendering);
388 }
389 
390 }	// Draw
391 }	// vkt
392