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