• 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::__anon0fca8ed40111::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 	const SharedGroupParams		groupParams;
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 
187 protected:
188 	void				preRenderCommands		(VkCommandBuffer cmdBuffer, VkImage colorTargetImage) const;
189 	void				beginRenderPass			(VkCommandBuffer cmdBuffer, VkRect2D renderArea,
190 												 const VkClearValue* pClearValues, deUint32 clearValueCount) const;
191 	void				drawCommands			(VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const;
192 
193 #ifndef CTS_USES_VULKANSC
194 	void				beginSecondaryCmdBuffer	(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
195 												 VkRenderingFlagsKHR renderingFlags = 0u) const;
196 	void				beginDynamicRender		(VkCommandBuffer cmdBuffer, VkRect2D renderArea,
197 												 const VkClearValue* pClearValues, VkRenderingFlagsKHR renderingFlags = 0u) const;
198 #endif // CTS_USES_VULKANSC
199 
200 private:
201 	DrawParams						m_data;
202 	Move<VkRenderPass>				m_renderPass;
203 	Move<VkImageView>				m_colorTargetView;
204 	Move<VkImageView>				m_multisampleTargetView;
205 	Move<VkFramebuffer>				m_framebuffer;
206 	Move<VkPipeline>				m_pipeline;
207 	Move<VkPipelineLayout>			m_pipelineLayout;
208 	Move<VkDescriptorPool>			m_descriptorPool;
209 	Move<VkDescriptorSet>			m_descriptorSet;
210 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
211 };
212 
DrawTestInstance(Context & context,const DrawParams & data)213 DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
214 	: vkt::TestInstance		(context)
215 	, m_data				(data)
216 {
217 }
218 
~DrawTestInstance(void)219 DrawTestInstance::~DrawTestInstance (void)
220 {
221 }
222 
223 class DrawTestCase : public TestCase
224 {
225 	public:
226 								DrawTestCase		(tcu::TestContext& context, const char* name, const DrawParams data);
227 								~DrawTestCase		(void);
228 	virtual	void				initPrograms		(SourceCollections& programCollection) const;
229 	virtual TestInstance*		createInstance		(Context& context) const;
230 	virtual void				checkSupport		(Context& context) const;
231 
232 private:
233 	DrawParams					m_data;
234 };
235 
DrawTestCase(tcu::TestContext & context,const char * name,const DrawParams data)236 DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const DrawParams data)
237 	: vkt::TestCase	(context, name)
238 	, m_data		(data)
239 {
240 }
241 
~DrawTestCase(void)242 DrawTestCase::~DrawTestCase	(void)
243 {
244 }
245 
checkSupport(Context & context) const246 void DrawTestCase::checkSupport(Context &context) const
247 {
248 	context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");
249 
250 	if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
251 		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
252 
253 	if (m_data.groupParams->useDynamicRendering)
254 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
255 }
256 
initPrograms(SourceCollections & programCollection) const257 void DrawTestCase::initPrograms (SourceCollections& programCollection) const
258 {
259 	const deUint32				numValues	= WIDTH * HEIGHT * m_data.samples;
260 
261 	const tcu::StringTemplate	vertShader	(string(
262 		"#version 450\n"
263 		"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
264 		"\n"
265 		"layout(location = 0) in vec4 in_position;\n"
266 		"layout(location = 1) in float in_data;\n"
267 		"layout(location = 0) __explicitInterpAMD out float out_data_explicit;\n"
268 		"layout(location = 1) ${auxqualifier} ${qualifier}        out float out_data_${qualifier};\n"
269 		"\n"
270 		"out gl_PerVertex {\n"
271 		"    vec4  gl_Position;\n"
272 		"    float gl_PointSize;\n"
273 		"};\n"
274 		"\n"
275 		"void main() {\n"
276 		"    gl_PointSize              = 1.0;\n"
277 		"    gl_Position               = in_position;\n"
278 		"    out_data_explicit         = in_data;\n"
279 		"    out_data_${qualifier}     = in_data;\n"
280 		"}\n"));
281 
282 	const tcu::StringTemplate	fragShader	(string(
283 		"#version 450\n"
284 		"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
285 		"\n"
286 		"layout(location = 0) __explicitInterpAMD in float in_data_explicit;\n"
287 		"layout(location = 1) ${auxqualifier} ${qualifier}        in float in_data_${qualifier};\n"
288 		"layout(location = 0) out vec4 out_color;\n"
289 		"layout (binding = 0, std140) writeonly buffer Output {\n"
290 		"    vec4 values [${numValues}];\n"
291 		"} sb_out;\n"
292 		"\n"
293 		"void main()\n"
294 		"{\n"
295 		"    uint index = (uint(gl_FragCoord.y) * ${width} * ${samples}) + uint(gl_FragCoord.x) * ${samples} + gl_SampleID;\n"
296 		"    // Barycentric coodinates (I, J, K)\n"
297 		"    vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
298 		"\n"
299 		"    // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
300 		"    float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
301 		"    // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
302 		"    float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
303 		"    // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
304 		"    float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
305 		"    // Match data component with barycentric coordinate\n"
306 		"    vec3  data  = vec3(data1, data2, data0);\n"
307 		"\n"
308 		"    float res      = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
309 		"    float expected = in_data_${qualifier};\n"
310 		"\n"
311 		"    sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
312 		"\n"
313 		"    const float threshold = 0.0005f;\n"
314 		"    if (abs(res - expected) < threshold)\n"
315 		"        out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
316 		"    else\n"
317 		"        out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
318 		"}\n"));
319 
320 	map<string, string> attributes;
321 	attributes["width"]			= de::toString(WIDTH);
322 	attributes["numValues"]		= de::toString(numValues * m_data.samples);
323 	attributes["qualifier"]		= interpolationToString(m_data.interpolation);
324 	attributes["auxqualifier"]	= auxiliaryQualifierToString(m_data.auxiliaryStorage);
325 	attributes["barycoord"]		= barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
326 	attributes["samples"]		= de::toString(m_data.samples);
327 
328 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
329 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
330 }
331 
createInstance(Context & context) const332 TestInstance* DrawTestCase::createInstance (Context& context) const
333 {
334 	return new DrawTestInstance(context, m_data);
335 }
336 
iterate(void)337 tcu::TestStatus DrawTestInstance::iterate (void)
338 {
339 	de::SharedPtr<Image>			colorTargetImage;
340 	de::SharedPtr<Image>			multisampleTargetImage;
341 	tcu::TestLog					&log					= m_context.getTestContext().getLog();
342 
343 	// Run two iterations with shaders that have different interpolation decorations. Images should still match.
344 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
345 	const VkDevice					device					= m_context.getDevice();
346 	const CmdPoolCreateInfo			cmdPoolCreateInfo		(m_context.getUniversalQueueFamilyIndex());
347 	Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, &cmdPoolCreateInfo);
348 	Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
349 	Move<VkCommandBuffer>			secCmdBuffer;
350 	const Unique<VkShaderModule>	vs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
351 	const Unique<VkShaderModule>	fs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
352 	de::SharedPtr<Buffer>			vertexBuffer;
353 	de::SharedPtr<Buffer>			ssboBuffer;
354 
355 	vk::VkFormat					imageFormat				= VK_FORMAT_R8G8B8A8_UNORM;
356 	const deUint32					numValues				= WIDTH * HEIGHT * m_data.samples;
357 	const deBool					useMultisampling		= m_data.samples != VK_SAMPLE_COUNT_1_BIT;
358 
359 	// Create color buffer images.
360 	{
361 		const VkExtent3D			targetImageExtent		= { WIDTH, HEIGHT, 1 };
362 		const ImageCreateInfo		targetImageCreateInfo	(VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
363 															 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
364 		colorTargetImage									= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
365 
366 		if (useMultisampling)
367 		{
368 			const ImageCreateInfo		multisampleTargetImageCreateInfo	(VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples,
369 																			 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
370 			multisampleTargetImage											= Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
371 		}
372 	}
373 
374 	const ImageViewCreateInfo colorTargetViewInfo(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
375 	m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
376 
377 	if (useMultisampling)
378 	{
379 		const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat);
380 		m_multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
381 	}
382 
383 	// Create render pass
384 	if (!m_data.groupParams->useDynamicRendering)
385 	{
386 		RenderPassCreateInfo			renderPassCreateInfo;
387 		renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
388 																 VK_SAMPLE_COUNT_1_BIT,
389 																 VK_ATTACHMENT_LOAD_OP_CLEAR,
390 																 VK_ATTACHMENT_STORE_OP_STORE,
391 																 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
392 																 VK_ATTACHMENT_STORE_OP_STORE,
393 																 VK_IMAGE_LAYOUT_UNDEFINED,
394 																 VK_IMAGE_LAYOUT_GENERAL));
395 
396 		const VkAttachmentReference		colorAttachmentRef			= { 0u, VK_IMAGE_LAYOUT_GENERAL };
397 		const VkAttachmentReference		multisampleAttachmentRef	= { 1u, VK_IMAGE_LAYOUT_GENERAL };
398 
399 		if (useMultisampling)
400 		{
401 			renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
402 																	 m_data.samples,
403 																	 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
404 																	 vk::VK_ATTACHMENT_STORE_OP_STORE,
405 																	 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
406 																	 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
407 																	 vk::VK_IMAGE_LAYOUT_UNDEFINED,
408 																	 vk::VK_IMAGE_LAYOUT_GENERAL));
409 		}
410 
411 		renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
412 														   0,
413 														   0,
414 														   DE_NULL,
415 														   1u,
416 														   useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
417 														   useMultisampling ? &colorAttachmentRef : DE_NULL,
418 														   AttachmentReference(),
419 														   0,
420 														   DE_NULL));
421 
422 		m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
423 
424 		// Create framebuffer
425 		vector<VkImageView> colorAttachments { *m_colorTargetView };
426 		if (useMultisampling)
427 			colorAttachments.push_back(*m_multisampleTargetView);
428 
429 		const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
430 		m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
431 	}
432 
433 	// Create vertex buffer.
434 	{
435 		const PositionValueVertex	vertices[]	=
436 		{
437 			PositionValueVertex(
438 				tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f),		// Coord
439 				float(1.0f)),							// Value
440 
441 			PositionValueVertex(
442 				tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f),	// Coord
443 				float(0.0f)),							// Value
444 			PositionValueVertex(
445 				tcu::Vec4( 1.0f,  1.0f, 0.0f, 2.0f),	// Coord
446 				float(0.5f)),							// Value
447 			PositionValueVertex(
448 				tcu::Vec4( 1.0f, -1.0f, 1.0f, 0.5f),	// Coord
449 				float(1.0f)),							// Value
450 		};
451 
452 		const VkDeviceSize			dataSize	= DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
453 		vertexBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
454 		deUint8*					ptr			= reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
455 
456 		deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
457 		flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
458 	}
459 
460 	// Create SSBO buffer
461 	{
462 		const VkDeviceSize		dataSize	= sizeof(tcu::Vec4) * numValues;
463 		ssboBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
464 		deUint8*				ptr			= reinterpret_cast<deUint8*>(ssboBuffer->getBoundMemory().getHostPtr());
465 
466 		deMemset(ptr, 0, static_cast<size_t>(dataSize));
467 		flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(), ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
468 	}
469 
470 	// Create Descriptor Set layout
471 	{
472 		m_descriptorSetLayout = DescriptorSetLayoutBuilder()
473 			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
474 			.build(vk, device);
475 	}
476 
477 	// Create Descriptor Set
478 	{
479 		m_descriptorPool = DescriptorPoolBuilder()
480 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
481 			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
482 
483 		m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
484 
485 		const VkDescriptorBufferInfo	bufferInfo =
486 		{
487 			ssboBuffer->object(),		// VkBuffer		buffer;
488 			0u,							// VkDeviceSize	offset;
489 			VK_WHOLE_SIZE				// VkDeviceSize	range;
490 		};
491 
492 		DescriptorSetUpdateBuilder()
493 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
494 			.update(vk, device);
495 	}
496 
497 	// Create pipeline
498 	{
499 		const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
500 
501 		VkViewport	viewport	= makeViewport(WIDTH, HEIGHT);
502 		VkRect2D	scissor		= makeRect2D(WIDTH, HEIGHT);
503 
504 		const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX };
505 
506 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
507 		{
508 			{ 0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
509 			{ 1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (deUint32)(sizeof(float)* 4) }
510 		};
511 
512 		PipelineCreateInfo::VertexInputState vertexInputState	= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
513 
514 		m_pipelineLayout = makePipelineLayout	(vk, device, *m_descriptorSetLayout);
515 
516 		PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
517 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
518 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
519 		pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
520 		pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
521 		pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
522 		pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
523 		pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
524 		pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
525 		pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));
526 
527 #ifndef CTS_USES_VULKANSC
528 		VkPipelineRenderingCreateInfoKHR renderingCreateInfo
529 		{
530 			VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
531 			DE_NULL,
532 			0u,
533 			1u,
534 			&imageFormat,
535 			VK_FORMAT_UNDEFINED,
536 			VK_FORMAT_UNDEFINED
537 		};
538 
539 		if (m_data.groupParams->useDynamicRendering)
540 			pipelineCreateInfo.pNext = &renderingCreateInfo;
541 #endif // CTS_USES_VULKANSC
542 
543 		m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
544 	}
545 
546 	// Queue draw and read results.
547 	{
548 		const VkQueue				queue				= m_context.getUniversalQueue();
549 		const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
550 		const tcu::Vec4				clearColor			= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
551 		const VkRect2D				renderArea			= makeRect2D(WIDTH, HEIGHT);
552 		const VkBuffer				buffer				= vertexBuffer->object();
553 
554 		vector<VkClearValue>		clearColors;
555 		clearColors.push_back(makeClearValueColor(clearColor));
556 		if (useMultisampling)
557 			clearColors.push_back(makeClearValueColor(clearColor));
558 
559 #ifndef CTS_USES_VULKANSC
560 		if (m_data.groupParams->useSecondaryCmdBuffer)
561 		{
562 			secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
563 
564 			// record secondary command buffer
565 			if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
566 			{
567 				beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
568 				beginDynamicRender(*secCmdBuffer, renderArea, clearColors.data());
569 			}
570 			else
571 				beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat);
572 
573 			drawCommands(*secCmdBuffer, buffer);
574 
575 			if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
576 				endRendering(vk, *secCmdBuffer);
577 
578 			endCommandBuffer(vk, *secCmdBuffer);
579 
580 			// record primary command buffer
581 			beginCommandBuffer(vk, *cmdBuffer, 0u);
582 
583 			if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
584 				beginDynamicRender(*cmdBuffer, renderArea, clearColors.data(), VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
585 
586 			vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
587 
588 			if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
589 				endRendering(vk, *cmdBuffer);
590 
591 			endCommandBuffer(vk, *cmdBuffer);
592 		}
593 		else if (m_data.groupParams->useDynamicRendering)
594 		{
595 			beginCommandBuffer(vk, *cmdBuffer);
596 			beginDynamicRender(*cmdBuffer, renderArea, clearColors.data());
597 			drawCommands(*cmdBuffer, buffer);
598 			endRendering(vk, *cmdBuffer);
599 			endCommandBuffer(vk, *cmdBuffer);
600 		}
601 #endif // CTS_USES_VULKANSC
602 
603 		if (!m_data.groupParams->useDynamicRendering)
604 		{
605 			beginCommandBuffer(vk, *cmdBuffer);
606 			beginRenderPass(*cmdBuffer, renderArea, clearColors.data(), (deUint32)clearColors.size());
607 			drawCommands(*cmdBuffer, buffer);
608 			endRenderPass(vk, *cmdBuffer);
609 			endCommandBuffer(vk, *cmdBuffer);
610 		}
611 
612 		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
613 	}
614 
615 	qpTestResult res = QP_TEST_RESULT_PASS;
616 
617 	{
618 		const Allocation& resultAlloc = ssboBuffer->getBoundMemory();
619 		invalidateAlloc(vk, device, resultAlloc);
620 
621 		const tcu::Vec4*	ptr		= reinterpret_cast<tcu::Vec4*>(resultAlloc.getHostPtr());
622 		for (deUint32 valueNdx = 0u; valueNdx < numValues; valueNdx++)
623 		{
624 			if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
625 			{
626 				log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got " << ptr[valueNdx].y()
627 					<< tcu::TestLog::EndMessage;
628 				res = QP_TEST_RESULT_FAIL;
629 			}
630 		}
631 	}
632 
633 	return tcu::TestStatus(res, qpGetTestResultName(res));
634 }
635 
beginRenderPass(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,deUint32 clearValueCount) const636 void DrawTestInstance::beginRenderPass(VkCommandBuffer cmdBuffer, VkRect2D renderArea,
637 									   const VkClearValue* pClearValues, deUint32 clearValueCount) const
638 {
639 	const DeviceInterface& vk = m_context.getDeviceInterface();
640 
641 	const VkRenderPassBeginInfo renderPassBeginInfo
642 	{
643 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType						sType;
644 		DE_NULL,												// const void*							pNext;
645 		*m_renderPass,											// VkRenderPass							renderPass;
646 		*m_framebuffer,											// VkFramebuffer						framebuffer;
647 		renderArea,												// VkRect2D								renderArea;
648 		clearValueCount,										// deUint32								clearValueCount;
649 		pClearValues,											// const VkClearValue*					pClearValues;
650 	};
651 
652 	vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
653 }
654 
drawCommands(VkCommandBuffer cmdBuffer,VkBuffer vertexBuffer) const655 void DrawTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const
656 {
657 	const DeviceInterface&	vk = m_context.getDeviceInterface();
658 	const VkDeviceSize		vertexBufferOffset = 0;
659 
660 	vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
661 	vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
662 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
663 	vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
664 }
665 
666 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat colorFormat,VkRenderingFlagsKHR renderingFlags) const667 void DrawTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat, VkRenderingFlagsKHR renderingFlags) const
668 {
669 	VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
670 	{
671 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
672 		DE_NULL,																// const void*						pNext;
673 		renderingFlags,															// VkRenderingFlagsKHR				flags;
674 		0u,																		// uint32_t							viewMask;
675 		1u,																		// uint32_t							colorAttachmentCount;
676 		&colorFormat,															// const VkFormat*					pColorAttachmentFormats;
677 		VK_FORMAT_UNDEFINED,													// VkFormat							depthAttachmentFormat;
678 		VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
679 		m_data.samples,															// VkSampleCountFlagBits			rasterizationSamples;
680 	};
681 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
682 
683 	VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
684 	if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
685 		usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
686 
687 	const VkCommandBufferBeginInfo commandBufBeginParams
688 	{
689 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
690 		DE_NULL,																// const void*						pNext;
691 		usageFlags,																// VkCommandBufferUsageFlags		flags;
692 		&bufferInheritanceInfo
693 	};
694 
695 	const DeviceInterface& vk = m_context.getDeviceInterface();
696 	VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
697 }
698 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,VkRenderingFlagsKHR renderingFlags) const699 void DrawTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkRect2D renderArea, const VkClearValue* pClearValues, VkRenderingFlagsKHR renderingFlags) const
700 {
701 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
702 	const deBool			useMultisampling	= m_data.samples != VK_SAMPLE_COUNT_1_BIT;
703 
704 	VkRenderingAttachmentInfoKHR colorAttachment
705 	{
706 		VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,								// VkStructureType						sType;
707 		DE_NULL,																		// const void*							pNext;
708 		useMultisampling ? *m_multisampleTargetView : *m_colorTargetView,				// VkImageView							imageView;
709 		VK_IMAGE_LAYOUT_GENERAL,														// VkImageLayout						imageLayout;
710 		useMultisampling ? VK_RESOLVE_MODE_AVERAGE_BIT : VK_RESOLVE_MODE_NONE,			// VkResolveModeFlagBits				resolveMode;
711 		useMultisampling ? *m_colorTargetView : DE_NULL,								// VkImageView							resolveImageView;
712 		VK_IMAGE_LAYOUT_GENERAL,														// VkImageLayout						resolveImageLayout;
713 		useMultisampling ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD,	// VkAttachmentLoadOp					loadOp;
714 		VK_ATTACHMENT_STORE_OP_STORE,													// VkAttachmentStoreOp					storeOp;
715 		pClearValues[0]																	// VkClearValue							clearValue;
716 	};
717 
718 	VkRenderingInfoKHR renderingInfo
719 	{
720 		VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
721 		DE_NULL,
722 		renderingFlags,											// VkRenderingFlagsKHR					flags;
723 		renderArea,												// VkRect2D								renderArea;
724 		1u,														// deUint32								layerCount;
725 		0u,														// deUint32								viewMask;
726 		1u,														// deUint32								colorAttachmentCount;
727 		&colorAttachment,										// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
728 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
729 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
730 	};
731 
732 	vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
733 }
734 #endif // CTS_USES_VULKANSC
735 
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)736 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
737 {
738 	tcu::TestContext&	testCtx		= testGroup->getTestContext();
739 
740 	const VkSampleCountFlagBits samples[] =
741 	{
742 		VK_SAMPLE_COUNT_1_BIT,
743 		VK_SAMPLE_COUNT_2_BIT,
744 		VK_SAMPLE_COUNT_4_BIT,
745 		VK_SAMPLE_COUNT_8_BIT,
746 		VK_SAMPLE_COUNT_16_BIT,
747 		VK_SAMPLE_COUNT_32_BIT,
748 		VK_SAMPLE_COUNT_64_BIT,
749 	};
750 
751 	const Interpolation interTypes[] =
752 	{
753 		SMOOTH,
754 		NOPERSPECTIVE
755 	};
756 
757 	const AuxiliaryQualifier auxQualifiers[] =
758 	{
759 		AUX_NONE,
760 		AUX_SAMPLE,
761 		AUX_CENTROID,
762 	};
763 
764 	for (deUint32 sampleNdx	= 0; sampleNdx < DE_LENGTH_OF_ARRAY(samples); sampleNdx++)
765 	{
766 		// reduce number of tests for dynamic rendering cases where secondary command buffer is used
767 		if (groupParams->useSecondaryCmdBuffer && (sampleNdx > VK_SAMPLE_COUNT_2_BIT))
768 			continue;
769 
770 		for (deUint32 auxNdx	= 0;	auxNdx		< DE_LENGTH_OF_ARRAY(auxQualifiers);	auxNdx++)
771 		for (deUint32 interNdx	= 0;	interNdx	< DE_LENGTH_OF_ARRAY(interTypes);		interNdx++)
772 		{
773 			if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
774 				continue;
775 
776 			const DrawParams params
777 			{
778 				interTypes[interNdx],
779 				samples[sampleNdx],
780 				auxQualifiers[auxNdx],
781 				groupParams
782 			};
783 			testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), params));
784 		}
785 	}
786 }
787 
788 }	// anonymous
789 
createExplicitVertexParameterTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)790 tcu::TestCaseGroup*	createExplicitVertexParameterTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
791 {
792 	// Tests for VK_AMD_shader_explicit_vertex_parameter.
793 	return createTestGroup(testCtx, "explicit_vertex_parameter", createTests, groupParams);
794 }
795 
796 }	// Draw
797 }	// vkt
798