• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 The Khronos Group Inc.
6  * Copyright (c) 2023 Google Inc.
7  * Copyright (c) 2023 LunarG, Inc.
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 Dynamic vertex attribute tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineDynamicVertexAttributeTests.hpp"
27 #include "vktPipelineClearUtil.hpp"
28 #include "vktPipelineExtendedDynamicStateTests.hpp"
29 
30 #include "vktCustomInstancesDevices.hpp"
31 #include "vktTestCase.hpp"
32 
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 
39 #include "tcuCommandLine.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuTextureUtil.hpp"
43 
44 #include <array>
45 #include <set>
46 
47 namespace vkt
48 {
49 namespace pipeline
50 {
51 
52 namespace
53 {
54 
makeVertexInputAttributeDescription2EXT(deUint32 location,deUint32 binding,vk::VkFormat format,deUint32 offset)55 vk::VkVertexInputAttributeDescription2EXT makeVertexInputAttributeDescription2EXT (deUint32 location, deUint32 binding, vk::VkFormat format, deUint32 offset)
56 {
57 	vk::VkVertexInputAttributeDescription2EXT desc = vk::initVulkanStructure();
58 
59 	desc.location	= location;
60 	desc.binding	= binding;
61 	desc.format		= format;
62 	desc.offset		= offset;
63 
64 	return desc;
65 }
66 
makeVertexInputBindingDescription2EXT(deUint32 binding,deUint32 stride,vk::VkVertexInputRate inputRate)67 vk::VkVertexInputBindingDescription2EXT makeVertexInputBindingDescription2EXT (deUint32 binding, deUint32 stride, vk::VkVertexInputRate inputRate)
68 {
69 	vk::VkVertexInputBindingDescription2EXT desc = vk::initVulkanStructure();
70 
71 	desc.binding	= binding;
72 	desc.stride		= stride;
73 	desc.inputRate	= inputRate;
74 	desc.divisor	= 1u;
75 
76 	return desc;
77 }
78 
makeImageCreateInfo(const tcu::IVec2 & size,const vk::VkFormat format,const vk::VkImageUsageFlags usage)79 vk::VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const vk::VkFormat format, const vk::VkImageUsageFlags usage)
80 {
81 	const vk::VkImageCreateInfo imageParams =
82 	{
83 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
84 		DE_NULL,									// const void*				pNext;
85 		(vk::VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
86 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
87 		format,										// VkFormat					format;
88 		vk::makeExtent3D(size.x(), size.y(), 1),	// VkExtent3D				extent;
89 		1u,											// deUint32					mipLevels;
90 		1u,											// deUint32					arrayLayers;
91 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
92 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
93 		usage,										// VkImageUsageFlags		usage;
94 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
95 		0u,											// deUint32					queueFamilyIndexCount;
96 		DE_NULL,									// const deUint32*			pQueueFamilyIndices;
97 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
98 	};
99 
100 	return imageParams;
101 }
102 
removeExtensions(const std::vector<std::string> & a,const std::vector<const char * > & b)103 static std::vector <std::string> removeExtensions (const std::vector<std::string>& a, const std::vector<const char*>& b)
104 {
105 	std::vector<std::string>	res;
106 	std::set<std::string>		removeExts(b.begin(), b.end());
107 
108 	for (std::vector<std::string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter)
109 	{
110 		if (!de::contains(removeExts, *aIter))
111 			res.push_back(*aIter);
112 	}
113 
114 	return res;
115 }
116 
createDynamicVertexStateDevice(Context & context,const deUint32 testQueueFamilyIndex,const vk::PipelineConstructionType pipelineConstructionType)117 vk::Move<vk::VkDevice> createDynamicVertexStateDevice (Context& context, const deUint32 testQueueFamilyIndex, const vk::PipelineConstructionType pipelineConstructionType)
118 {
119 	DE_UNREF(pipelineConstructionType);
120 
121 	void* pNext = DE_NULL;
122 
123 #ifndef CTS_USES_VULKANSC
124 	vk::VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT	graphicsPipelineFeatures
125 	{
126 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT,	// VkStructureType	sType;
127 		pNext,																			// void*			pNext;
128 		VK_TRUE,																		// VkBool32			graphicsPipelineLibrary;
129 	};
130 
131 	if (vk::isConstructionTypeLibrary(pipelineConstructionType))
132 		pNext = &graphicsPipelineFeatures;
133 	vk::VkPhysicalDeviceDynamicRenderingFeaturesKHR			dynamicRenderingFeatures
134 	{
135 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR,	// VkStructureType	sType;
136 		pNext,																	// void* pNext;
137 		VK_TRUE,																// VkBool32		dynamicRendering;
138 	};
139 	vk::VkPhysicalDeviceShaderObjectFeaturesEXT				shaderObjectFeatures
140 	{
141 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT,	// VkStructureType	sType;
142 		&dynamicRenderingFeatures,											// void*			pNext;
143 		VK_TRUE,															// VkBool32			shaderObject;
144 	};
145 
146 	if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
147 		pNext = &shaderObjectFeatures;
148 #endif
149 
150 	vk::VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT	dynamicVertexState
151 	{
152 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT,	// VkStructureType	sType;
153 		pNext,																			// void*			pNext;
154 		VK_TRUE,																		// VkBool32			vertexInputDynamicState;
155 	};
156 
157 	vk::VkPhysicalDeviceFeatures2							physDeviceFeats2	= context.getDeviceFeatures2();
158 
159 	physDeviceFeats2.features	= context.getDeviceFeatures();
160 	physDeviceFeats2.pNext		= &dynamicVertexState;
161 
162 	const float												queuePriority		= 1.0f;
163 
164 	const vk::VkDeviceQueueCreateInfo						queueParams			=
165 	{
166 		vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType			sType;
167 		DE_NULL,										// const void*				pNext;
168 		0u,												// VkDeviceQueueCreateFlags	flags;
169 		testQueueFamilyIndex,							// deUint32					queueFamilyIndex;
170 		1u,												// deUint32					queueCount;
171 		&queuePriority									// const float*				pQueuePriorities;
172 	};
173 
174 	std::vector<const char*>							extensionPtrs;
175 	std::vector<const char*>							coreExtensions;
176 
177 	vk::getCoreDeviceExtensions(context.getUsedApiVersion(), coreExtensions);
178 
179 	std::vector<std::string>							nonCoreExtensions	(removeExtensions(context.getDeviceExtensions(), coreExtensions));
180 
181 	extensionPtrs.resize(nonCoreExtensions.size());
182 
183 	for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx)
184 		extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str();
185 
186 	const vk::VkDeviceCreateInfo						deviceInfo			=
187 	{
188 		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,	// VkStructureType					sType;
189 		&physDeviceFeats2,							// const void*						pNext;
190 		0u,											// VkDeviceCreateFlags				flags;
191 		1u,											// deUint32							queueCreateInfoCount;
192 		&queueParams,								// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
193 		0u,											// deUint32							enabledLayerCount;
194 		DE_NULL,									// const char* const*				ppEnabledLayerNames;
195 		(deUint32)extensionPtrs.size(),				// deUint32							enabledExtensionCount;
196 		extensionPtrs.data(),						// const char* const*				ppEnabledExtensionNames;
197 		NULL										// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
198 	};
199 
200 	return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(),
201 		context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceInfo);
202 }
203 
204 class NonSequentialInstance : public TestInstance
205 {
206 	public:
NonSequentialInstance(Context & context,const vk::PipelineConstructionType pipelineConstructionType,const deUint32 numInstances,const std::vector<deUint32> attributeLocations)207 								NonSequentialInstance		(Context&							context,
208 															 const vk::PipelineConstructionType	pipelineConstructionType,
209 															 const deUint32						numInstances,
210 															 const std::vector<deUint32>		attributeLocations)
211 								: TestInstance					(context)
212 								, m_pipelineConstructionType	(pipelineConstructionType)
213 								, m_numInstances				(numInstances)
214 								, m_attributeLocations			(attributeLocations)
215 								{}
216 
~NonSequentialInstance()217 								~NonSequentialInstance	()
218 								{}
219 
220 	virtual tcu::TestStatus		iterate						(void);
221 
222 private:
223 	struct VertexInfo
224 	{
225 		tcu::Vec4	position;
226 		tcu::Vec4	color;
227 	};
228 
229 	const vk::PipelineConstructionType	m_pipelineConstructionType;
230 	const deUint32						m_numInstances;
231 	const std::vector<deUint32>			m_attributeLocations;
232 };
233 
iterate(void)234 tcu::TestStatus NonSequentialInstance::iterate (void)
235 {
236 	tcu::TestLog&													log						= m_context.getTestContext().getLog();
237 	const vk::DeviceInterface&										vk						= m_context.getDeviceInterface();
238 	const vk::PlatformInterface&									vkp						= m_context.getPlatformInterface();
239 	const vk::VkInstance											vki						= m_context.getInstance();
240 	const vk::InstanceInterface&									instanceInterface		= m_context.getInstanceInterface();
241 	const deUint32													queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
242 	const vk::VkPhysicalDevice										physicalDevice			= m_context.getPhysicalDevice();
243 	const vk::Move<vk::VkDevice>									device					= createDynamicVertexStateDevice(m_context, queueFamilyIndex, m_pipelineConstructionType);
244 	vk::SimpleAllocator												allocator				(vk, *device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
245 	const vk::DeviceDriver											deviceDriver			(vkp, vki, *device, m_context.getUsedApiVersion());
246 	const vk::VkQueue												queue					= getDeviceQueue(deviceDriver, *device, queueFamilyIndex, 0u);
247 	const auto&														deviceExtensions		= m_context.getDeviceExtensions();
248 
249 	// Create shaders
250 	const std::array<vk::ShaderWrapper, 2>							vertexShaderModules		=
251 	{
252 		vk::ShaderWrapper(vk, *device, m_context.getBinaryCollection().get("vert_0")),
253 		vk::ShaderWrapper(vk, *device, m_context.getBinaryCollection().get("vert_1"))
254 	};
255 
256 	const vk::ShaderWrapper											fragmentShaderModule	= vk::ShaderWrapper(vk, *device, m_context.getBinaryCollection().get("frag"));
257 
258 	const deUint32													vertexBufferBindIndex	= 0u;
259 
260 	// Vertex input state and binding
261 	const vk::VkVertexInputBindingDescription2EXT					bindingDescription2EXT	= makeVertexInputBindingDescription2EXT(vertexBufferBindIndex, sizeof(VertexInfo), vk::VK_VERTEX_INPUT_RATE_VERTEX);
262 
263 	const std::array<vk::VkVertexInputAttributeDescription2EXT, 2>		vertexInputAttributeDesc2EXTGreens
264 	{
265 		makeVertexInputAttributeDescription2EXT(0, vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u),
266 		makeVertexInputAttributeDescription2EXT(m_attributeLocations[0], vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float)) * 4u)
267 	};
268 
269 	const std::array<vk::VkVertexInputAttributeDescription2EXT, 2>		vertexInputAttributeDesc2EXT2Reds
270 	{
271 		makeVertexInputAttributeDescription2EXT(0, vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u),
272 		makeVertexInputAttributeDescription2EXT(m_attributeLocations[1], vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float)) * 4u)
273 	};
274 
275 	const vk::VkPipelineVertexInputStateCreateInfo						vertexInputStateCreateInfo
276 	{
277 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
278 		DE_NULL,														// const void*								pNext;
279 		(vk::VkPipelineVertexInputStateCreateFlags)0u,					// VkPipelineVertexInputStateCreateFlags	flags;
280 		0u,																// uint32_t									vertexBindingDescriptionCount;
281 		DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
282 		0u,																// uint32_t									vertexAttributeDescriptionCount;
283 		DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
284 	};
285 
286 	vk::Move<vk::VkImage>											colorImage				= (makeImage(vk, *device, makeImageCreateInfo(tcu::IVec2(32, 32), vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
287 
288 	// Allocate and bind color image memory
289 	const vk::VkImageSubresourceRange								colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
290 	const de::UniquePtr<vk::Allocation>								colorImageAlloc			(bindImage(vk,*device, allocator, *colorImage, vk::MemoryRequirement::Any));
291 	vk::Move<vk::VkImageView>										colorImageView			= (makeImageView(vk,*device, *colorImage, vk::VK_IMAGE_VIEW_TYPE_2D, vk::VK_FORMAT_R8G8B8A8_UNORM, colorSubresourceRange));
292 
293 	// Create renderpass
294 	const vk::VkAttachmentDescription								attachmentDescription	=
295 	{
296 		(vk::VkAttachmentDescriptionFlags)0u,		// VkAttachmentDescriptionFlags	flags
297 		vk::VK_FORMAT_R8G8B8A8_UNORM,				// VkFormat						format
298 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits		samples
299 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,			// VkAttachmentLoadOp			loadOp
300 		vk::VK_ATTACHMENT_STORE_OP_STORE,			// VkAttachmentStoreOp			storeOp
301 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// VkAttachmentLoadOp			stencilLoadOp
302 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,		// VkAttachmentStoreOp			stencilStoreOp
303 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout				initialLayout
304 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL// VkImageLayout				finalLayout
305 	};
306 
307 	const vk::VkAttachmentReference									attachmentReference		=
308 	{
309 		0u,												// deUint32			attachment
310 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
311 	};
312 
313 	const vk::VkSubpassDescription									subpassDescription		=
314 	{
315 		(vk::VkSubpassDescriptionFlags)0u,	// VkSubpassDescriptionFlags	flags
316 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,// VkPipelineBindPoint			pipelineBindPoint
317 		0u,									// deUint32						inputAttachmentCount
318 		DE_NULL,							// const VkAttachmentReference*	pInputAttachments
319 		1u,									// deUint32						colorAttachmentCount
320 		&attachmentReference,				// const VkAttachmentReference*	pColorAttachments
321 		DE_NULL,							// const VkAttachmentReference*	pResolveAttachments
322 		DE_NULL,							// const VkAttachmentReference*	pDepthStencilAttachment
323 		0u,									// deUint32						preserveAttachmentCount
324 		DE_NULL								// const deUint32*				pPreserveAttachments
325 	};
326 
327 	const vk::VkRenderPassCreateInfo								renderPassInfo			=
328 	{
329 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureTypei					sType
330 		DE_NULL,										// const void*						pNext
331 		(vk::VkRenderPassCreateFlags)0u,				// VkRenderPassCreateFlags			flags
332 		1u,												// deUint32							attachmentCount
333 		&attachmentDescription,							// const VkAttachmentDescription*	pAttachments
334 		1u,												// deUint32							subpassCount
335 		&subpassDescription,							// const VkSubpassDescription*		pSubpasses
336 		0u,												// deUint32							dependencyCount
337 		DE_NULL											// const VkSubpassDependency*		pDependencies
338 	};
339 
340 	vk::RenderPassWrapper											renderPass				= vk::RenderPassWrapper(m_pipelineConstructionType, vk, *device, &renderPassInfo);
341 
342 	// Create framebuffer
343 	const vk::VkImageView											attachmentBindInfos[]	=
344 	{
345 		*colorImageView
346 	};
347 
348 	const vk::VkFramebufferCreateInfo								framebufferCreateInfo	=
349 	{
350 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType				sType;
351 		DE_NULL,										// const void*					pNext;
352 		vk::VkFramebufferCreateFlags(0),				// VkFramebufferCreateFlags		flags;
353 		*renderPass,									// VkRenderPass					renderPass;
354 		1u,												// deUint32						attachmentCount;
355 		attachmentBindInfos,							// const VkImageView*			pAttachments;
356 		32u,											// deUint32						width;
357 		32u,											// deUint32						height;
358 		1u												// deUint32						layers;
359 	};
360 
361 	renderPass.createFramebuffer(vk, *device, &framebufferCreateInfo, { *colorImage });
362 
363 	std::array<vk::VkDynamicState, 1>								dynamicStates
364 	{
365 		vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
366 	};
367 
368 	vk::VkPipelineDynamicStateCreateInfo							pipelineDynamicStateNfo
369 	{
370 		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType;
371 		DE_NULL,													// const void*							pNext;
372 		(vk::VkPipelineDynamicStateCreateFlags)0u,					// VkPipelineDynamicStateCreateFlags	flags;
373 		static_cast<deUint32>(dynamicStates.size()),				// uint32_t								dynamicStateCount;
374 		dynamicStates.data()										// const VkDynamicState*				pDynamicStates;
375 	};
376 
377 	// Create pipeline layout
378 	const vk::VkPipelineLayoutCreateInfo							pipelineLayoutInfo		=
379 	{
380 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType;
381 		DE_NULL,											// const void*					pNext;
382 		0u,													// VkPipelineLayoutCreateFlags	flags;
383 		0u,													// deUint32						descriptorSetCount;
384 		DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
385 		0u,													// deUint32						pushConstantRangeCount;
386 		DE_NULL												// const VkPushDescriptorRange*	pPushDescriptorRanges;
387 	};
388 
389 	vk::PipelineLayoutWrapper										pipelineLayout			(m_pipelineConstructionType, vk, *device, &pipelineLayoutInfo);
390 
391 	// Create graphics pipeline
392 	vk::GraphicsPipelineWrapper										graphicsPipelines[2]	{ { instanceInterface, vk, physicalDevice, *device, deviceExtensions, m_pipelineConstructionType}, { instanceInterface, vk, physicalDevice, *device, deviceExtensions, m_pipelineConstructionType} };
393 
394 	const vk::VkExtent2D											extent					= {32, 32};
395 	const std::vector<vk::VkViewport>								viewports				(1, vk::makeViewport(extent));
396 	const std::vector<vk::VkRect2D>									scissors				(1, vk::makeRect2D(extent));
397 
398 	for (deUint32 i = 0u; i < static_cast<deUint32>(vertexShaderModules.size()); ++i)
399 	{
400 		graphicsPipelines[i].setDefaultDepthStencilState()
401 			.setDefaultColorBlendState()
402 			.setDynamicState(&pipelineDynamicStateNfo)
403 			.setDefaultMultisampleState()
404 			.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
405 			.setDefaultRasterizationState()
406 			.setupVertexInputState(&vertexInputStateCreateInfo)
407 			.setupPreRasterizationShaderState(viewports,
408 				scissors,
409 				pipelineLayout,
410 				*renderPass,
411 				0u,
412 				vertexShaderModules[i])
413 			.setupFragmentShaderState(pipelineLayout,
414 				*renderPass,
415 				0u,
416 				fragmentShaderModule,
417 				DE_NULL,
418 				DE_NULL)
419 			.setupFragmentOutputState(*renderPass)
420 			.setMonolithicPipelineLayout(pipelineLayout)
421 			.buildPipeline();
422 	}
423 
424 	// Create vertex buffer
425 	const deUint32													numVertices				= 6;
426 	const vk::VkDeviceSize											vertexBufferSizeBytes	= 256;
427 
428 	const std::array<vk::Move<vk::VkBuffer>, 2>						vertexBuffers			=
429 	{
430 		(makeBuffer(vk,*device, vertexBufferSizeBytes, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)),
431 		(makeBuffer(vk,*device, vertexBufferSizeBytes, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
432 	};
433 
434 	const std::array<de::MovePtr<vk::Allocation>, 2>				vertexBufferAllocs		=
435 	{
436 		(bindBuffer(vk,*device, allocator, *vertexBuffers[0], vk::MemoryRequirement::HostVisible)),
437 		(bindBuffer(vk,*device, allocator, *vertexBuffers[1], vk::MemoryRequirement::HostVisible))
438 	};
439 
440 	const deUint32													instanceSize			= (deUint32)sqrt(m_numInstances);
441 	const float														posIncrement			= 1.0f / (float)m_numInstances * (float)instanceSize;
442 
443 	for (deUint32 i = 0u; i < static_cast<deUint32>(vertexShaderModules.size()); ++i)
444 	{
445 		tcu::Vec4			vertexColor	= (i == 0u ? tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f) : tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
446 		VertexInfo*	const	pVertices	= static_cast<VertexInfo*>(vertexBufferAllocs[i]->getHostPtr());
447 
448 		pVertices[0]	= { tcu::Vec4( posIncrement, -posIncrement, 0.0f, 1.0f),	vertexColor };
449 		pVertices[1]	= { tcu::Vec4(-posIncrement, -posIncrement, 0.0f, 1.0f),	vertexColor };
450 		pVertices[2]	= { tcu::Vec4(-posIncrement,  posIncrement, 0.0f, 1.0f),	vertexColor };
451 		pVertices[3]	= { tcu::Vec4(-posIncrement,  posIncrement, 1.0f, 1.0f),	vertexColor };
452 		pVertices[4]	= { tcu::Vec4( posIncrement,  posIncrement, 1.0f, 1.0f),	vertexColor };
453 		pVertices[5]	= { tcu::Vec4( posIncrement, -posIncrement, 1.0f, 1.0f),	vertexColor };
454 
455 		flushAlloc(vk,*device, *vertexBufferAllocs[i]);
456 	}
457 
458 	// Command buffer
459 	const vk::Unique<vk::VkCommandPool>								cmdPool					(createCommandPool(vk, *device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
460 	const vk::Unique<vk::VkCommandBuffer>							cmdBuffer				(allocateCommandBuffer(vk,*device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
461 
462 	const vk::VkDeviceSize											vertexBufferOffset		= 0u;
463 
464 	// Render result buffer
465 	const vk::VkDeviceSize											colorBufferSizeBytes	= static_cast<vk::VkDeviceSize>(tcu::getPixelSize(mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)) * 32 * 32);
466 	const vk::Unique<vk::VkBuffer>									colorBuffer				(makeBuffer(vk,*device, colorBufferSizeBytes, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT));
467 	const de::UniquePtr<vk::Allocation>								colorBufferAlloc		(bindBuffer(vk,*device, allocator, *colorBuffer, vk::MemoryRequirement::HostVisible));
468 
469 	const vk::VkClearValue											clearColorValue			= defaultClearValue(vk::VK_FORMAT_R8G8B8A8_UNORM);
470 
471 	beginCommandBuffer(vk, *cmdBuffer);
472 
473 	renderPass.begin(vk, *cmdBuffer, vk::makeRect2D(0, 0, 32u, 32u), clearColorValue);
474 
475 	graphicsPipelines[0].bind(*cmdBuffer);
476 	vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffers[0].get(), &vertexBufferOffset);
477 	vk.cmdSetVertexInputEXT(*cmdBuffer, 1u, &bindingDescription2EXT, static_cast<deUint32>(vertexInputAttributeDesc2EXTGreens.size()), vertexInputAttributeDesc2EXTGreens.data());
478 	vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
479 
480 	graphicsPipelines[1].bind(*cmdBuffer);
481 	vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffers[1].get(), &vertexBufferOffset);
482 	vk.cmdSetVertexInputEXT(*cmdBuffer, 1u, &bindingDescription2EXT, static_cast<deUint32>(vertexInputAttributeDesc2EXT2Reds.size()), vertexInputAttributeDesc2EXT2Reds.data());
483 	vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
484 
485 	renderPass.end(vk, *cmdBuffer);
486 	copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, tcu::IVec2(32, 32), vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
487 
488 	endCommandBuffer(vk, *cmdBuffer);
489 
490 	submitCommandsAndWait(vk,*device, queue, *cmdBuffer);
491 
492 	// Check result image
493 	{
494 		tcu::TextureLevel				referenceTexture	(mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), 32, 32);
495 		const tcu::PixelBufferAccess	referenceAccess		= referenceTexture.getAccess();
496 		const int						segmentSize			= static_cast<deInt32>(32u / instanceSize);
497 		const int						segmentLoc			= (32 - segmentSize) / 2;
498 
499 		tcu::clear(referenceTexture.getAccess(), clearColorValue.color.float32);
500 
501 		// Create reference image
502 		for (int y = 0; y < segmentSize; ++y)
503 		{
504 			for (int x = 0; x < segmentSize; ++x)
505 			{
506 				// While running test for all offsets, we create a nice gradient-like color for the pixels.
507 				referenceAccess.setPixel(tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), segmentLoc + x, segmentLoc + y);
508 			}
509 		}
510 
511 		invalidateAlloc(vk,*device, *colorBufferAlloc);
512 
513 		const tcu::ConstPixelBufferAccess resultPixelAccess(mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), (int)extent.width, (int)extent.height, 1, colorBufferAlloc->getHostPtr());
514 
515 		if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceAccess, resultPixelAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT))
516 			return tcu::TestStatus::fail("Rendered image is not correct");
517 	}
518 
519 	return tcu::TestStatus::pass("Success");
520 }
521 
522 class NonSequentialCase : public vkt::TestCase
523 {
524 public:
NonSequentialCase(tcu::TestContext & testContext,const std::string & name,const vk::PipelineConstructionType pipelineConstructionType,const deUint32 numInstances,const std::vector<deUint32> attributeLocations)525 							NonSequentialCase	(tcu::TestContext&					testContext,
526 												 const std::string&					name,
527 												 const vk::PipelineConstructionType	pipelineConstructionType,
528 												 const deUint32						numInstances,
529 												 const std::vector<deUint32>		attributeLocations)
530 							: vkt::TestCase					(testContext, name)
531 							, m_pipelineConstructionType	(pipelineConstructionType)
532 							, m_numInstances				(numInstances)
533 							, m_attributeLocations			(attributeLocations)
534 							{}
535 
~NonSequentialCase(void)536 							~NonSequentialCase	(void)
537 							{}
538 
539 	virtual void			checkSupport		(Context& context)							const override;
540 	virtual void			initPrograms		(vk::SourceCollections& sourceCollections)	const override;
541 	virtual TestInstance	*createInstance		(Context& context)							const override;
542 
543 private:
544 	const vk::PipelineConstructionType	m_pipelineConstructionType;
545 	const deUint32						m_numInstances;
546 	const std::vector<deUint32>			m_attributeLocations;
547 };
548 
checkSupport(Context & context) const549 void NonSequentialCase::checkSupport (Context& context) const
550 {
551 	const vk::InstanceInterface&	vki			= context.getInstanceInterface();
552 	const vk::VkPhysicalDevice		physDevice	= context.getPhysicalDevice();
553 
554 	std::array<std::string, 3>		extensions	=
555 	{
556 		"VK_EXT_extended_dynamic_state",
557 		"VK_EXT_vertex_input_dynamic_state",
558 		"VK_EXT_extended_dynamic_state2"
559 	};
560 
561 	// Check extension support.
562 	for (const auto& extension : extensions)
563 		context.requireDeviceFunctionality(extension);
564 
565 	vk::checkPipelineConstructionRequirements(vki, physDevice, m_pipelineConstructionType);
566 }
567 
initPrograms(vk::SourceCollections & sourceCollections) const568 void NonSequentialCase::initPrograms (vk::SourceCollections& sourceCollections) const
569 {
570 	// Vertex
571 	{
572 		for (size_t i = 0; i < m_attributeLocations.size(); ++i)
573 		{
574 			std::ostringstream src;
575 
576 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
577 				<< "\n"
578 				<< "layout(location = 0) in vec4 inPosition;\n"
579 				<< "layout(location = " << m_attributeLocations[i] << ") in vec4 inColor;\n"
580 				<< "layout(location = 0) out vec4 outColor;\n"
581 				<< "\n"
582 				<< "void main (void)\n"
583 				<< "{\n"
584 				<< "	gl_Position = inPosition;\n"
585 				<< "	outColor = inColor;\n"
586 				<< "}\n";
587 
588 			sourceCollections.glslSources.add("vert_" + std::to_string(i)) << glu::VertexSource(src.str());
589 		}
590 	}
591 
592 	// Fragment
593 	{
594 		std::ostringstream src;
595 
596 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
597 			<< "\n"
598 			<< "layout(location = 0) in vec4 inColor;\n"
599 			<< "layout(location = 0) out vec4 outColor;\n"
600 			<< "\n"
601 			<< "void main (void)\n"
602 			<< "{\n"
603 			<< "	outColor = inColor;\n"
604 			<< "}\n";
605 
606 		sourceCollections.glslSources.add("frag") << glu::FragmentSource(src.str());
607 	}
608 }
609 
createInstance(Context & context) const610 TestInstance* NonSequentialCase::createInstance (Context& context) const
611 {
612 	return new NonSequentialInstance(context, m_pipelineConstructionType, m_numInstances, m_attributeLocations);
613 }
614 
615 } // anonymous
616 
createDynamicVertexAttributeTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)617 tcu::TestCaseGroup* createDynamicVertexAttributeTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
618 {
619 	de::MovePtr<tcu::TestCaseGroup> nonSequentialTestsGroup(new tcu::TestCaseGroup(testCtx, "dynamic_vertex_attribute"));
620 
621 	nonSequentialTestsGroup->addChild(new NonSequentialCase(testCtx, "nonsequential", pipelineConstructionType, 16u, { 1u, 7u }));
622 
623 	return nonSequentialTestsGroup.release();
624 }
625 
626 } // pipeline
627 } // vkt
628