1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 Valve 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 VK_AMD_shader_explicit_vertex_parameter tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawExplicitVertexParameterTests.hpp"
26 
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 
37 #include "deDefs.h"
38 #include "deRandom.hpp"
39 #include "deString.h"
40 #include "deMath.h"
41 
42 #include "tcuTestCase.hpp"
43 #include "tcuRGBA.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuStringTemplate.hpp"
47 
48 #include "rrRenderer.hpp"
49 
50 #include <string>
51 #include <sstream>
52 
53 namespace vkt
54 {
55 namespace Draw
56 {
57 namespace
58 {
59 using namespace vk;
60 using namespace std;
61 
62 enum Interpolation
63 {
64 	SMOOTH = 0,
65 	NOPERSPECTIVE = 1,
66 };
67 
68 enum AuxiliaryQualifier
69 {
70 	AUX_NONE = 0,
71 	AUX_CENTROID = 1,
72 	AUX_SAMPLE = 2,
73 };
74 
75 
76 enum
77 {
78 	WIDTH = 16,
79 	HEIGHT = 16
80 };
81 
82 struct PositionValueVertex {
PositionValueVertexvkt::Draw::__anon0721d3930111::PositionValueVertex83 	PositionValueVertex(tcu::Vec4 pos, float val)
84 	: position(pos)
85 	, value(val)
86 	{};
87 public:
88 	tcu::Vec4	position;
89 	float		value;
90 };
91 
92 struct DrawParams
93 {
94 	Interpolation				interpolation;
95 	vk::VkSampleCountFlagBits	samples;
96 	AuxiliaryQualifier			auxiliaryStorage;
97 };
98 
interpolationToString(Interpolation interpolation)99 const char* interpolationToString (Interpolation interpolation)
100 {
101 	switch (interpolation)
102 	{
103 		case SMOOTH:
104 			return "smooth";
105 		case NOPERSPECTIVE:
106 			return "noperspective";
107 		default:
108 			DE_FATAL("Invalid interpolation enum");
109 	}
110 
111 	return "";
112 }
113 
barycentricVariableString(Interpolation interpolation,AuxiliaryQualifier aux)114 std::string barycentricVariableString (Interpolation interpolation, AuxiliaryQualifier aux)
115 {
116 	std::ostringstream name;
117 	name << "gl_BaryCoord";
118 	switch (interpolation)
119 	{
120 		case SMOOTH:
121 			name << "Smooth";
122 			break;
123 		case NOPERSPECTIVE:
124 			name << "NoPersp";
125 			break;
126 		default:
127 			DE_FATAL("Invalid interpolation enum");
128 	}
129 
130 	switch (aux)
131 	{
132 		case AUX_CENTROID:
133 			name << "Centroid";
134 			break;
135 		case AUX_SAMPLE:
136 			name << "Sample";
137 			break;
138 		case AUX_NONE:
139 			name << "";
140 			break;
141 		default:
142 			DE_FATAL("Invalid auxiliary storage qualifier enum");
143 	}
144 	name << "AMD";
145 	return name.str();
146 }
147 
auxiliaryQualifierToString(AuxiliaryQualifier aux)148 const char* auxiliaryQualifierToString (AuxiliaryQualifier aux)
149 {
150 	switch (aux)
151 	{
152 		case AUX_CENTROID:
153 			return "centroid";
154 		case AUX_SAMPLE:
155 			return "sample";
156 		case AUX_NONE:
157 			return "";
158 		default:
159 			DE_FATAL("Invalid auxiliary storage qualifier enum");
160 	}
161 
162 	return "";
163 }
164 
getTestName(DrawParams params)165 std::string getTestName (DrawParams params)
166 {
167 	std::ostringstream	name;
168 
169 	name << interpolationToString(params.interpolation) << "_";
170 
171 	if (params.auxiliaryStorage != AUX_NONE)
172 		name << auxiliaryQualifierToString(params.auxiliaryStorage) << "_";
173 
174 	name << "samples_" << de::toString(params.samples);
175 
176 	return name.str();
177 }
178 
179 class DrawTestInstance : public TestInstance
180 {
181 public:
182 						DrawTestInstance	(Context& context, const DrawParams& data);
183 						~DrawTestInstance	(void);
184 	tcu::TestStatus		iterate				(void);
185 private:
186 	DrawParams			m_data;
187 };
188 
DrawTestInstance(Context & context,const DrawParams & data)189 DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
190 	: vkt::TestInstance		(context)
191 	, m_data				(data)
192 {
193 }
194 
~DrawTestInstance(void)195 DrawTestInstance::~DrawTestInstance (void)
196 {
197 }
198 
199 class DrawTestCase : public TestCase
200 {
201 	public:
202 								DrawTestCase		(tcu::TestContext& context, const char* name, const char* desc, const DrawParams data);
203 								~DrawTestCase		(void);
204 	virtual	void				initPrograms		(SourceCollections& programCollection) const;
205 	virtual TestInstance*		createInstance		(Context& context) const;
206 	virtual void				checkSupport	(Context& context) const;
207 
208 private:
209 	DrawParams					m_data;
210 };
211 
DrawTestCase(tcu::TestContext & context,const char * name,const char * desc,const DrawParams data)212 DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data)
213 	: vkt::TestCase	(context, name, desc)
214 	, m_data		(data)
215 {
216 }
217 
~DrawTestCase(void)218 DrawTestCase::~DrawTestCase	(void)
219 {
220 }
221 
checkSupport(Context & context) const222 void DrawTestCase::checkSupport(Context &context) const
223 {
224 	context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");
225 
226 	if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
227 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
228 }
229 
initPrograms(SourceCollections & programCollection) const230 void DrawTestCase::initPrograms (SourceCollections& programCollection) const
231 {
232 	const deUint32				numValues	= WIDTH * HEIGHT * m_data.samples;
233 
234 	const tcu::StringTemplate	vertShader	(string(
235 		"#version 450\n"
236 		"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
237 		"\n"
238 		"layout(location = 0) in vec4 in_position;\n"
239 		"layout(location = 1) in float in_data;\n"
240 		"layout(location = 0) __explicitInterpAMD out float out_data_explicit;\n"
241 		"layout(location = 1) ${auxqualifier} ${qualifier}        out float out_data_${qualifier};\n"
242 		"\n"
243 		"out gl_PerVertex {\n"
244 		"    vec4  gl_Position;\n"
245 		"    float gl_PointSize;\n"
246 		"};\n"
247 		"\n"
248 		"void main() {\n"
249 		"    gl_PointSize              = 1.0;\n"
250 		"    gl_Position               = in_position;\n"
251 		"    out_data_explicit         = in_data;\n"
252 		"    out_data_${qualifier}     = in_data;\n"
253 		"}\n"));
254 
255 	const tcu::StringTemplate	fragShader	(string(
256 		"#version 450\n"
257 		"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
258 		"\n"
259 		"layout(location = 0) __explicitInterpAMD in float in_data_explicit;\n"
260 		"layout(location = 1) ${auxqualifier} ${qualifier}        in float in_data_${qualifier};\n"
261 		"layout(location = 0) out vec4 out_color;\n"
262 		"layout (binding = 0, std140) writeonly buffer Output {\n"
263 		"    vec4 values [${numValues}];\n"
264 		"} sb_out;\n"
265 		"\n"
266 		"void main()\n"
267 		"{\n"
268 		"    uint index = (uint(gl_FragCoord.y) * ${width} * ${samples}) + uint(gl_FragCoord.x) * ${samples} + gl_SampleID;\n"
269 		"    // Barycentric coodinates (I, J, K)\n"
270 		"    vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
271 		"\n"
272 		"    // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
273 		"    float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
274 		"    // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
275 		"    float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
276 		"    // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
277 		"    float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
278 		"    // Match data component with barycentric coordinate\n"
279 		"    vec3  data  = vec3(data1, data2, data0);\n"
280 		"\n"
281 		"    float res      = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
282 		"    float expected = in_data_${qualifier};\n"
283 		"\n"
284 		"    sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
285 		"\n"
286 		"    const float threshold = 0.0005f;\n"
287 		"    if (abs(res - expected) < threshold)\n"
288 		"        out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
289 		"    else\n"
290 		"        out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
291 		"}\n"));
292 
293 	map<string, string> attributes;
294 	attributes["width"]			= de::toString(WIDTH);
295 	attributes["numValues"]		= de::toString(numValues * m_data.samples);
296 	attributes["qualifier"]		= interpolationToString(m_data.interpolation);
297 	attributes["auxqualifier"]	= auxiliaryQualifierToString(m_data.auxiliaryStorage);
298 	attributes["barycoord"]		= barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
299 	attributes["samples"]		= de::toString(m_data.samples);
300 
301 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
302 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
303 }
304 
createInstance(Context & context) const305 TestInstance* DrawTestCase::createInstance (Context& context) const
306 {
307 	return new DrawTestInstance(context, m_data);
308 }
309 
iterate(void)310 tcu::TestStatus DrawTestInstance::iterate (void)
311 {
312 	de::SharedPtr<Image>			colorTargetImage;
313 	de::SharedPtr<Image>			multisampleTargetImage;
314 	tcu::TestLog					&log					= m_context.getTestContext().getLog();
315 
316 	// Run two iterations with shaders that have different interpolation decorations. Images should still match.
317 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
318 	const VkDevice					device					= m_context.getDevice();
319 	const CmdPoolCreateInfo			cmdPoolCreateInfo		(m_context.getUniversalQueueFamilyIndex());
320 	Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, &cmdPoolCreateInfo);
321 	Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
322 	const Unique<VkShaderModule>	vs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
323 	const Unique<VkShaderModule>	fs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
324 	de::SharedPtr<Buffer>			vertexBuffer;
325 	de::SharedPtr<Buffer>			ssboBuffer;
326 	Move<VkRenderPass>				renderPass;
327 	Move<VkImageView>				colorTargetView;
328 	Move<VkImageView>				multisampleTargetView;
329 	Move<VkFramebuffer>				framebuffer;
330 	Move<VkPipeline>				pipeline;
331 	Move<VkPipelineLayout>			pipelineLayout;
332 	Move<VkDescriptorPool>			descriptorPool;
333 	Move<VkDescriptorSet>			descriptorSet;
334 	Move<VkDescriptorSetLayout>		descriptorSetLayout;
335 
336 	vk::VkFormat					imageFormat				= VK_FORMAT_R8G8B8A8_UNORM;
337 	const deUint32					numValues				= WIDTH * HEIGHT * m_data.samples;
338 	const deBool					useMultisampling		= m_data.samples != VK_SAMPLE_COUNT_1_BIT;
339 
340 	// Create color buffer images.
341 	{
342 		const VkExtent3D			targetImageExtent		= { WIDTH, HEIGHT, 1 };
343 		const ImageCreateInfo		targetImageCreateInfo	(VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
344 															 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
345 		colorTargetImage									= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
346 
347 		if (useMultisampling)
348 		{
349 			const ImageCreateInfo		multisampleTargetImageCreateInfo	(VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples,
350 																			 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
351 			multisampleTargetImage											= Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
352 		}
353 	}
354 
355 	// Create render pass and frame buffer.
356 	{
357 		const ImageViewCreateInfo		colorTargetViewInfo		(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
358 		colorTargetView	= createImageView(vk, device, &colorTargetViewInfo);
359 
360 		RenderPassCreateInfo			renderPassCreateInfo;
361 		renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
362 																 VK_SAMPLE_COUNT_1_BIT,
363 																 VK_ATTACHMENT_LOAD_OP_LOAD,
364 																 VK_ATTACHMENT_STORE_OP_STORE,
365 																 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
366 																 VK_ATTACHMENT_STORE_OP_STORE,
367 																 VK_IMAGE_LAYOUT_UNDEFINED,
368 																 VK_IMAGE_LAYOUT_GENERAL));
369 
370 		const VkAttachmentReference		colorAttachmentRef			= { 0u, VK_IMAGE_LAYOUT_GENERAL };
371 		const VkAttachmentReference		multisampleAttachmentRef	= { 1u, VK_IMAGE_LAYOUT_GENERAL };
372 		vector<VkImageView>				colorAttachments;
373 		colorAttachments.push_back(*colorTargetView);
374 
375 		if (useMultisampling)
376 		{
377 			const ImageViewCreateInfo		multisamplingTargetViewInfo		(multisampleTargetImage->object(),
378 																			 vk::VK_IMAGE_VIEW_TYPE_2D,
379 																			 imageFormat);
380 
381 
382 			multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
383 			colorAttachments.push_back(*multisampleTargetView);
384 
385 			renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
386 																	 m_data.samples,
387 																	 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
388 																	 vk::VK_ATTACHMENT_STORE_OP_STORE,
389 																	 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
390 																	 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
391 																	 vk::VK_IMAGE_LAYOUT_UNDEFINED,
392 																	 vk::VK_IMAGE_LAYOUT_GENERAL));
393 		}
394 
395 		renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
396 														   0,
397 														   0,
398 														   DE_NULL,
399 														   1u,
400 														   useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
401 														   useMultisampling ? &colorAttachmentRef : DE_NULL,
402 														   AttachmentReference(),
403 														   0,
404 														   DE_NULL));
405 
406 		renderPass			= createRenderPass(vk, device, &renderPassCreateInfo);
407 
408 		const FramebufferCreateInfo		framebufferCreateInfo	(*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
409 		framebuffer	= createFramebuffer(vk, device, &framebufferCreateInfo);
410 	}
411 
412 	// Create vertex buffer.
413 	{
414 		const PositionValueVertex	vertices[]	=
415 		{
416 			PositionValueVertex(
417 				tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f),		// Coord
418 				float(1.0f)),							// Value
419 
420 			PositionValueVertex(
421 				tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f),	// Coord
422 				float(0.0f)),							// Value
423 			PositionValueVertex(
424 				tcu::Vec4( 1.0f,  1.0f, 0.0f, 2.0f),	// Coord
425 				float(0.5f)),							// Value
426 			PositionValueVertex(
427 				tcu::Vec4( 1.0f, -1.0f, 1.0f, 0.5f),	// Coord
428 				float(1.0f)),							// Value
429 		};
430 
431 		const VkDeviceSize			dataSize	= DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
432 		vertexBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
433 		deUint8*					ptr			= reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
434 
435 		deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
436 		flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
437 	}
438 
439 	// Create SSBO buffer
440 	{
441 		const VkDeviceSize		dataSize	= sizeof(tcu::Vec4) * numValues;
442 		ssboBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
443 		deUint8*				ptr			= reinterpret_cast<deUint8*>(ssboBuffer->getBoundMemory().getHostPtr());
444 
445 		deMemset(ptr, 0, static_cast<size_t>(dataSize));
446 		flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(), ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
447 	}
448 
449 	// Create Descriptor Set layout
450 	{
451 		descriptorSetLayout = DescriptorSetLayoutBuilder()
452 			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
453 			.build(vk, device);
454 	}
455 
456 	// Create Descriptor Set
457 	{
458 		descriptorPool = DescriptorPoolBuilder()
459 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
460 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
461 
462 	    descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
463 
464 		const VkDescriptorBufferInfo	bufferInfo =
465 		{
466 			ssboBuffer->object(),		// VkBuffer		buffer;
467 			0u,							// VkDeviceSize	offset;
468 			VK_WHOLE_SIZE				// VkDeviceSize	range;
469 		};
470 
471 		DescriptorSetUpdateBuilder()
472 			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
473 			.update(vk, device);
474 	}
475 
476 	// Create pipeline
477 	{
478 		const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
479 
480 		VkViewport	viewport	= makeViewport(WIDTH, HEIGHT);
481 		VkRect2D	scissor		= makeRect2D(WIDTH, HEIGHT);
482 
483 		const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX };
484 
485 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
486 		{
487 			{ 0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
488 			{ 1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (deUint32)(sizeof(float)* 4) }
489 		};
490 
491 		PipelineCreateInfo::VertexInputState vertexInputState	= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
492 
493 		pipelineLayout = makePipelineLayout	(vk, device, *descriptorSetLayout);
494 
495 		PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
496 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
497 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
498 		pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
499 		pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
500 		pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
501 		pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
502 		pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
503 		pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
504 		pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));
505 
506 		pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
507 	}
508 
509 	// Queue draw and read results.
510 	{
511 		const VkQueue				queue				= m_context.getUniversalQueue();
512 		const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
513 		const tcu::Vec4				clearColor			= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
514 		const VkRect2D				renderArea			= makeRect2D(WIDTH, HEIGHT);
515 		const VkDeviceSize			vertexBufferOffset	= 0;
516 		const VkBuffer				buffer				= vertexBuffer->object();
517 
518 		vector<VkClearValue>		clearColors;
519 		clearColors.push_back(makeClearValueColor(clearColor));
520 
521 		if (useMultisampling)
522 			clearColors.push_back(makeClearValueColor(clearColor));
523 
524 		beginCommandBuffer(vk, *cmdBuffer, 0u);
525 		const VkRenderPassBeginInfo renderPassBeginInfo =
526 		{
527 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType;
528 			DE_NULL,									// const void*             pNext;
529 			*renderPass,								// VkRenderPass            renderPass;
530 			*framebuffer,								// VkFramebuffer           framebuffer;
531 			renderArea,									// VkRect2D                renderArea;
532 			(deUint32)clearColors.size(),				// deUint32                clearValueCount;
533 			clearColors.data(),							// const VkClearValue*     pClearValues;
534 		};
535 
536 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
537 		vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
538 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
539 		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
540 		vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
541 		endRenderPass(vk, *cmdBuffer);
542 		endCommandBuffer(vk, *cmdBuffer);
543 
544 		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
545 	}
546 
547 	qpTestResult res = QP_TEST_RESULT_PASS;
548 
549 	{
550 		const Allocation& resultAlloc = ssboBuffer->getBoundMemory();
551 		invalidateAlloc(vk, device, resultAlloc);
552 
553 		const tcu::Vec4*	ptr		= reinterpret_cast<tcu::Vec4*>(resultAlloc.getHostPtr());
554 		for (deUint32 valueNdx = 0u; valueNdx < numValues; valueNdx++)
555 		{
556 			if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
557 			{
558 				log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got " << ptr[valueNdx].y()
559 					<< tcu::TestLog::EndMessage;
560 				res = QP_TEST_RESULT_FAIL;
561 			}
562 		}
563 	}
564 
565 	return tcu::TestStatus(res, qpGetTestResultName(res));
566 }
567 
createTests(tcu::TestCaseGroup * testGroup)568 void createTests (tcu::TestCaseGroup* testGroup)
569 {
570 	tcu::TestContext&	testCtx		= testGroup->getTestContext();
571 
572 	const VkSampleCountFlagBits samples[] =
573 	{
574 		VK_SAMPLE_COUNT_1_BIT,
575 		VK_SAMPLE_COUNT_2_BIT,
576 		VK_SAMPLE_COUNT_4_BIT,
577 		VK_SAMPLE_COUNT_8_BIT,
578 		VK_SAMPLE_COUNT_16_BIT,
579 		VK_SAMPLE_COUNT_32_BIT,
580 		VK_SAMPLE_COUNT_64_BIT,
581 	};
582 
583 	const Interpolation interTypes[] =
584 	{
585 		SMOOTH,
586 		NOPERSPECTIVE
587 	};
588 
589 	const AuxiliaryQualifier auxQualifiers[] =
590 	{
591 		AUX_NONE,
592 		AUX_SAMPLE,
593 		AUX_CENTROID,
594 	};
595 
596 	for (deUint32 sampleNdx	= 0;	sampleNdx	< DE_LENGTH_OF_ARRAY(samples);			sampleNdx++)
597 	for (deUint32 auxNdx	= 0;	auxNdx		< DE_LENGTH_OF_ARRAY(auxQualifiers);	auxNdx++)
598     for (deUint32 interNdx	= 0;	interNdx	< DE_LENGTH_OF_ARRAY(interTypes);		interNdx++)
599 	{
600 		if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
601 			continue;
602 
603 		const DrawParams params =
604 		{
605 			interTypes[interNdx],
606 			samples[sampleNdx],
607 			auxQualifiers[auxNdx],
608 		};
609 		testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), "", params));
610 	}
611 }
612 
613 }	// anonymous
614 
createExplicitVertexParameterTests(tcu::TestContext & testCtx)615 tcu::TestCaseGroup*	createExplicitVertexParameterTests (tcu::TestContext& testCtx)
616 {
617 	return createTestGroup(testCtx, "explicit_vertex_parameter", "Tests for VK_AMD_shader_explicit_vertex_parameter.", createTests);
618 }
619 
620 }	// Draw
621 }	// vkt
622