1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Imagination Technologies Ltd.
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 Robustness Utilities
23 *//*--------------------------------------------------------------------*/
24
25#include "vktRobustnessUtil.hpp"
26#include "vktCustomInstancesDevices.hpp"
27#include "vkDefs.hpp"
28#include "vkImageUtil.hpp"
29#include "vkPrograms.hpp"
30#include "vkQueryUtil.hpp"
31#include "vkRefUtil.hpp"
32#include "vkTypeUtil.hpp"
33#include "vkCmdUtil.hpp"
34#include "vkObjUtil.hpp"
35#include "vkSafetyCriticalUtil.hpp"
36#include "tcuCommandLine.hpp"
37#include "vkDeviceUtil.hpp"
38#include "deMath.h"
39#include <iomanip>
40#include <limits>
41#include <sstream>
42
43namespace vkt
44{
45namespace robustness
46{
47
48using namespace vk;
49using std::vector;
50using std::string;
51
52Move<VkDevice> createRobustBufferAccessDevice (Context& context, const VkPhysicalDeviceFeatures2* enabledFeatures2)
53{
54	const float queuePriority = 1.0f;
55
56	// Create a universal queue that supports graphics and compute
57	const VkDeviceQueueCreateInfo	queueParams =
58	{
59		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
60		DE_NULL,									// const void*					pNext;
61		0u,											// VkDeviceQueueCreateFlags		flags;
62		context.getUniversalQueueFamilyIndex(),		// deUint32						queueFamilyIndex;
63		1u,											// deUint32						queueCount;
64		&queuePriority								// const float*					pQueuePriorities;
65	};
66
67	VkPhysicalDeviceFeatures enabledFeatures = context.getDeviceFeatures();
68	enabledFeatures.robustBufferAccess = true;
69
70	// \note Extensions in core are not explicitly enabled even though
71	//		 they are in the extension list advertised to tests.
72	const auto& extensionPtrs = context.getDeviceCreationExtensions();
73
74	void* pNext												= (void*)enabledFeatures2;
75#ifdef CTS_USES_VULKANSC
76	VkDeviceObjectReservationCreateInfo memReservationInfo	= context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
77	memReservationInfo.pNext								= pNext;
78	pNext													= &memReservationInfo;
79
80	VkPhysicalDeviceVulkanSC10Features sc10Features			= createDefaultSC10Features();
81	sc10Features.pNext										= pNext;
82	pNext													= &sc10Features;
83
84	VkPipelineCacheCreateInfo			pcCI;
85	std::vector<VkPipelinePoolSize>		poolSizes;
86	if (context.getTestContext().getCommandLine().isSubProcess())
87	{
88		if (context.getResourceInterface()->getCacheDataSize() > 0)
89		{
90			pcCI =
91			{
92				VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,		// VkStructureType				sType;
93				DE_NULL,											// const void*					pNext;
94				VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
95					VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
96				context.getResourceInterface()->getCacheDataSize(),	// deUintptr					initialDataSize;
97				context.getResourceInterface()->getCacheData()		// const void*					pInitialData;
98			};
99			memReservationInfo.pipelineCacheCreateInfoCount		= 1;
100			memReservationInfo.pPipelineCacheCreateInfos		= &pcCI;
101		}
102
103		poolSizes							= context.getResourceInterface()->getPipelinePoolSizes();
104		if (!poolSizes.empty())
105		{
106			memReservationInfo.pipelinePoolSizeCount			= deUint32(poolSizes.size());
107			memReservationInfo.pPipelinePoolSizes				= poolSizes.data();
108		}
109	}
110#endif
111
112	const VkDeviceCreateInfo		deviceParams =
113	{
114		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,	// VkStructureType					sType;
115		pNext,									// const void*						pNext;
116		0u,										// VkDeviceCreateFlags				flags;
117		1u,										// deUint32							queueCreateInfoCount;
118		&queueParams,							// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
119		0u,										// deUint32							enabledLayerCount;
120		nullptr,								// const char* const*				ppEnabledLayerNames;
121		de::sizeU32(extensionPtrs),				// deUint32							enabledExtensionCount;
122		de::dataOrNull(extensionPtrs),			// const char* const*				ppEnabledExtensionNames;
123		enabledFeatures2 ? nullptr : &enabledFeatures	// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
124	};
125
126	// We are creating a custom device with a potentially large amount of extensions and features enabled, using the default device
127	// as a reference. Some implementations may only enable certain device extensions if some instance extensions are enabled, so in
128	// this case it's important to reuse the context instance when creating the device.
129	const auto&	vki				= context.getInstanceInterface();
130	const auto	instance		= context.getInstance();
131	const auto	physicalDevice	= chooseDevice(vki, instance, context.getTestContext().getCommandLine());
132
133	return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(),
134							  instance, vki, physicalDevice, &deviceParams);
135}
136
137bool areEqual (float a, float b)
138{
139	return deFloatAbs(a - b) <= 0.001f;
140}
141
142bool isValueZero (const void* valuePtr, size_t valueSizeInBytes)
143{
144	const deUint8* bytePtr = reinterpret_cast<const deUint8*>(valuePtr);
145
146	for (size_t i = 0; i < valueSizeInBytes; i++)
147	{
148		if (bytePtr[i] != 0)
149			return false;
150	}
151
152	return true;
153}
154
155bool isValueWithinBuffer (const void* buffer, VkDeviceSize bufferSize, const void* valuePtr, size_t valueSizeInBytes)
156{
157	const deUint8* byteBuffer = reinterpret_cast<const deUint8*>(buffer);
158
159	if (bufferSize < ((VkDeviceSize)valueSizeInBytes))
160		return false;
161
162	for (VkDeviceSize i = 0; i <= (bufferSize - valueSizeInBytes); i++)
163	{
164		if (!deMemCmp(&byteBuffer[i], valuePtr, valueSizeInBytes))
165			return true;
166	}
167
168	return false;
169}
170
171bool isValueWithinBufferOrZero (const void* buffer, VkDeviceSize bufferSize, const void* valuePtr, size_t valueSizeInBytes)
172{
173	return isValueWithinBuffer(buffer, bufferSize, valuePtr, valueSizeInBytes) || isValueZero(valuePtr, valueSizeInBytes);
174}
175
176template<typename T>
177bool verifyVec4IntegerValues (const void* vecPtr)
178{
179	const T Tzero	= T{0};
180	const T Tone	= T{1};
181	const T	Tmax	= std::numeric_limits<T>::max();
182
183	T values[4];
184	deMemcpy(values, vecPtr, 4*sizeof(T));
185	return (values[0] == Tzero && values[1] == Tzero && values[2] == Tzero &&
186		    (values[3] == Tzero || values[3] == Tone || values[3] == Tmax));
187}
188
189bool verifyOutOfBoundsVec4 (const void* vecPtr, VkFormat bufferFormat)
190{
191	if (isUintFormat(bufferFormat))
192	{
193		if (bufferFormat == VK_FORMAT_R64_UINT)
194			return verifyVec4IntegerValues<deUint64>(vecPtr);
195		return verifyVec4IntegerValues<deUint32>(vecPtr);
196	}
197	else if (isIntFormat(bufferFormat))
198	{
199		if (bufferFormat == VK_FORMAT_R64_SINT)
200			return verifyVec4IntegerValues<deInt64>(vecPtr);
201		return verifyVec4IntegerValues<deInt32>(vecPtr);
202	}
203	else if (isFloatFormat(bufferFormat))
204	{
205		const float* data = (float*)vecPtr;
206
207		return areEqual(data[0], 0.0f)
208			&& areEqual(data[1], 0.0f)
209			&& areEqual(data[2], 0.0f)
210			&& (areEqual(data[3], 0.0f) || areEqual(data[3], 1.0f));
211	}
212	else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
213	{
214		return *((deUint32*)vecPtr) == 0xc0000000u;
215	}
216
217	DE_ASSERT(false);
218	return false;
219}
220
221void populateBufferWithTestValues (void* buffer, VkDeviceSize size, VkFormat format)
222{
223	// Assign a sequence of 32-bit values
224	for (VkDeviceSize scalarNdx = 0; scalarNdx < size / 4; scalarNdx++)
225	{
226		const deUint32 valueIndex = (deUint32)(2 + scalarNdx); // Do not use 0 or 1
227
228		if (isUintFormat(format))
229		{
230			reinterpret_cast<deUint32*>(buffer)[scalarNdx] = valueIndex;
231		}
232		else if (isIntFormat(format))
233		{
234			reinterpret_cast<deInt32*>(buffer)[scalarNdx] = -deInt32(valueIndex);
235		}
236		else if (isFloatFormat(format))
237		{
238			reinterpret_cast<float*>(buffer)[scalarNdx] = float(valueIndex);
239		}
240		else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
241		{
242			const deUint32	r	= ((valueIndex + 0) & ((2u << 10) - 1u));
243			const deUint32	g	= ((valueIndex + 1) & ((2u << 10) - 1u));
244			const deUint32	b	= ((valueIndex + 2) & ((2u << 10) - 1u));
245			const deUint32	a	= ((valueIndex + 0) & ((2u << 2) - 1u));
246
247			reinterpret_cast<deUint32*>(buffer)[scalarNdx] = (a << 30) | (b << 20) | (g << 10) | r;
248		}
249		else
250		{
251			DE_ASSERT(false);
252		}
253	}
254}
255
256void logValue (std::ostringstream& logMsg, const void* valuePtr, VkFormat valueFormat, size_t valueSize)
257{
258	if (isUintFormat(valueFormat))
259	{
260		logMsg << *reinterpret_cast<const deUint32*>(valuePtr);
261	}
262	else if (isIntFormat(valueFormat))
263	{
264		logMsg << *reinterpret_cast<const deInt32*>(valuePtr);
265	}
266	else if (isFloatFormat(valueFormat))
267	{
268		logMsg << *reinterpret_cast<const float*>(valuePtr);
269	}
270	else
271	{
272		const deUint8*				bytePtr		= reinterpret_cast<const deUint8*>(valuePtr);
273		const std::ios::fmtflags	streamFlags	= logMsg.flags();
274
275		logMsg << std::hex;
276		for (size_t i = 0; i < valueSize; i++)
277		{
278			logMsg << " " << (deUint32)bytePtr[i];
279		}
280		logMsg.flags(streamFlags);
281	}
282}
283
284// TestEnvironment
285
286TestEnvironment::TestEnvironment (Context&					context,
287								  const DeviceInterface&	vk,
288								  VkDevice					device,
289								  VkDescriptorSetLayout		descriptorSetLayout,
290								  VkDescriptorSet			descriptorSet)
291	: m_context				(context)
292	, m_device				(device)
293	, m_descriptorSetLayout	(descriptorSetLayout)
294	, m_descriptorSet		(descriptorSet)
295{
296	// Create command pool
297	{
298		const VkCommandPoolCreateInfo commandPoolParams =
299		{
300			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
301			DE_NULL,										// const void*				pNext;
302			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
303			context.getUniversalQueueFamilyIndex()			// deUint32					queueFamilyIndex;
304		};
305
306		m_commandPool = createCommandPool(vk, m_device, &commandPoolParams);
307	}
308
309	// Create command buffer
310	{
311		const VkCommandBufferAllocateInfo commandBufferAllocateInfo =
312		{
313			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
314			DE_NULL,										// const void*				pNext;
315			*m_commandPool,										// VkCommandPool			commandPool;
316			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
317			1u,												// deUint32					bufferCount;
318		};
319
320		m_commandBuffer = allocateCommandBuffer(vk, m_device, &commandBufferAllocateInfo);
321	}
322}
323
324VkCommandBuffer TestEnvironment::getCommandBuffer (void)
325{
326	return *m_commandBuffer;
327}
328
329// GraphicsEnvironment
330
331GraphicsEnvironment::GraphicsEnvironment (Context&					context,
332										  const DeviceInterface&	vk,
333										  VkDevice					device,
334										  VkDescriptorSetLayout		descriptorSetLayout,
335										  VkDescriptorSet			descriptorSet,
336										  const VertexBindings&		vertexBindings,
337										  const VertexAttributes&	vertexAttributes,
338										  const DrawConfig&			drawConfig,
339										  bool						testPipelineRobustness)
340
341	: TestEnvironment		(context, vk, device, descriptorSetLayout, descriptorSet)
342	, m_renderSize			(16, 16)
343	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
344{
345	const auto&					vki						= context.getInstanceInterface();
346	const auto					instance				= context.getInstance();
347	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
348	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
349	const VkPhysicalDevice		physicalDevice			= chooseDevice(vki, instance, context.getTestContext().getCommandLine());
350	SimpleAllocator				memAlloc				(vk, m_device, getPhysicalDeviceMemoryProperties(vki, physicalDevice));
351
352	// Create color image and view
353	{
354		const VkImageCreateInfo colorImageParams =
355		{
356			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
357			DE_NULL,																	// const void*				pNext;
358			0u,																			// VkImageCreateFlags		flags;
359			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
360			m_colorFormat,																// VkFormat					format;
361			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
362			1u,																			// deUint32					mipLevels;
363			1u,																			// deUint32					arrayLayers;
364			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
365			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
366			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
367			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
368			1u,																			// deUint32					queueFamilyIndexCount;
369			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
370			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
371		};
372
373		m_colorImage			= createImage(vk, m_device, &colorImageParams);
374		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, m_device, *m_colorImage), MemoryRequirement::Any);
375		VK_CHECK(vk.bindImageMemory(m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
376
377		const VkImageViewCreateInfo colorAttachmentViewParams =
378		{
379			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
380			DE_NULL,											// const void*				pNext;
381			0u,													// VkImageViewCreateFlags	flags;
382			*m_colorImage,										// VkImage					image;
383			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
384			m_colorFormat,										// VkFormat					format;
385			componentMappingRGBA,								// VkComponentMapping		components;
386			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
387		};
388
389		m_colorAttachmentView = createImageView(vk, m_device, &colorAttachmentViewParams);
390	}
391
392	// Create render pass
393	m_renderPass = makeRenderPass(vk, m_device, m_colorFormat);
394
395	// Create framebuffer
396	{
397		const VkFramebufferCreateInfo framebufferParams =
398		{
399			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
400			DE_NULL,											// const void*				pNext;
401			0u,													// VkFramebufferCreateFlags	flags;
402			*m_renderPass,										// VkRenderPass				renderPass;
403			1u,													// deUint32					attachmentCount;
404			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
405			(deUint32)m_renderSize.x(),							// deUint32					width;
406			(deUint32)m_renderSize.y(),							// deUint32					height;
407			1u													// deUint32					layers;
408		};
409
410		m_framebuffer = createFramebuffer(vk, m_device, &framebufferParams);
411	}
412
413	// Create pipeline layout
414	{
415		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
416		{
417			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
418			DE_NULL,											// const void*					pNext;
419			0u,													// VkPipelineLayoutCreateFlags	flags;
420			1u,													// deUint32						setLayoutCount;
421			&m_descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
422			0u,													// deUint32						pushConstantRangeCount;
423			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
424		};
425
426		m_pipelineLayout = createPipelineLayout(vk, m_device, &pipelineLayoutParams);
427	}
428
429	m_vertexShaderModule	= createShaderModule(vk, m_device, m_context.getBinaryCollection().get("vertex"), 0);
430	m_fragmentShaderModule	= createShaderModule(vk, m_device, m_context.getBinaryCollection().get("fragment"), 0);
431
432	// Create pipeline
433	{
434		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
435		{
436			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
437			DE_NULL,														// const void*								pNext;
438			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
439			(deUint32)vertexBindings.size(),								// deUint32									vertexBindingDescriptionCount;
440			vertexBindings.data(),											// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
441			(deUint32)vertexAttributes.size(),								// deUint32									vertexAttributeDescriptionCount;
442			vertexAttributes.data()											// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
443		};
444
445		const std::vector<VkViewport>	viewports	(1, makeViewport(m_renderSize));
446		const std::vector<VkRect2D>		scissors	(1, makeRect2D(m_renderSize));
447
448		const void* pNext = DE_NULL;
449#ifndef CTS_USES_VULKANSC
450		VkPipelineRobustnessCreateInfoEXT pipelineRobustnessInfo = initVulkanStructure();
451
452		if (testPipelineRobustness)
453		{
454			pipelineRobustnessInfo.storageBuffers	= VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
455			pipelineRobustnessInfo.uniformBuffers	= VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
456			pipelineRobustnessInfo.vertexInputs		= VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
457			pipelineRobustnessInfo.images			= VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT;
458			pNext									= &pipelineRobustnessInfo;
459		}
460#else
461		DE_UNREF(testPipelineRobustness);
462#endif
463
464		m_graphicsPipeline = makeGraphicsPipeline(vk,															// const DeviceInterface&                        vk
465												  m_device,														// const VkDevice                                device
466												  *m_pipelineLayout,											// const VkPipelineLayout                        pipelineLayout
467												  *m_vertexShaderModule,										// const VkShaderModule                          vertexShaderModule
468												  DE_NULL,														// const VkShaderModule                          tessellationControlShaderModule
469												  DE_NULL,														// const VkShaderModule                          tessellationEvalShaderModule
470												  DE_NULL,														// const VkShaderModule                          geometryShaderModule
471												  *m_fragmentShaderModule,										// const VkShaderModule                          fragmentShaderModule
472												  *m_renderPass,												// const VkRenderPass                            renderPass
473												  viewports,													// const std::vector<VkViewport>&                viewports
474												  scissors,														// const std::vector<VkRect2D>&                  scissors
475												  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,							// const VkPrimitiveTopology                     topology
476												  0u,															// const deUint32                                subpass
477												  0u,															// const deUint32                                patchControlPoints
478												  &vertexInputStateParams,										// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
479												  DE_NULL,														// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
480												  DE_NULL,														// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
481												  DE_NULL,														// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
482												  DE_NULL,														// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
483												  DE_NULL,														// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
484												  pNext);														// void* pNext
485	}
486
487	// Record commands
488	{
489		const VkImageMemoryBarrier imageLayoutBarrier =
490		{
491			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// VkStructureType			sType;
492			DE_NULL,												// const void*				pNext;
493			(VkAccessFlags)0,										// VkAccessFlags			srcAccessMask;
494			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
495			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			oldLayout;
496			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			newLayout;
497			VK_QUEUE_FAMILY_IGNORED,								// uint32_t					srcQueueFamilyIndex;
498			VK_QUEUE_FAMILY_IGNORED,								// uint32_t					dstQueueFamilyIndex;
499			*m_colorImage,											// VkImage					image;
500			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }			// VkImageSubresourceRange	subresourceRange;
501		};
502
503		beginCommandBuffer(vk, *m_commandBuffer, 0u);
504		{
505			vk.cmdPipelineBarrier(*m_commandBuffer,
506								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
507								  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
508								  (VkDependencyFlags)0,
509								  0u, DE_NULL,
510								  0u, DE_NULL,
511								  1u, &imageLayoutBarrier);
512
513			beginRenderPass(vk, *m_commandBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.0f));
514			{
515				const std::vector<VkDeviceSize> vertexBufferOffsets(drawConfig.vertexBuffers.size(), 0ull);
516
517				vk.cmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
518				vk.cmdBindDescriptorSets(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet, 0, DE_NULL);
519				vk.cmdBindVertexBuffers(*m_commandBuffer, 0, (deUint32)drawConfig.vertexBuffers.size(), drawConfig.vertexBuffers.data(), vertexBufferOffsets.data());
520
521				if (drawConfig.indexBuffer == DE_NULL || drawConfig.indexCount == 0)
522				{
523					vk.cmdDraw(*m_commandBuffer, drawConfig.vertexCount, drawConfig.instanceCount, 0, 0);
524				}
525				else
526				{
527					vk.cmdBindIndexBuffer(*m_commandBuffer, drawConfig.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
528					vk.cmdDrawIndexed(*m_commandBuffer, drawConfig.indexCount, drawConfig.instanceCount, 0, 0, 0);
529				}
530			}
531			endRenderPass(vk, *m_commandBuffer);
532		}
533		endCommandBuffer(vk, *m_commandBuffer);
534	}
535}
536
537// ComputeEnvironment
538
539ComputeEnvironment::ComputeEnvironment (Context&					context,
540										const DeviceInterface&		vk,
541										VkDevice					device,
542										VkDescriptorSetLayout		descriptorSetLayout,
543										VkDescriptorSet				descriptorSet,
544										bool						testPipelineRobustness)
545
546	: TestEnvironment	(context, vk, device, descriptorSetLayout, descriptorSet)
547{
548	// Create pipeline layout
549	{
550		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
551		{
552			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			// VkStructureType					sType;
553			DE_NULL,												// const void*						pNext;
554			0u,														// VkPipelineLayoutCreateFlags		flags;
555			1u,														// deUint32							setLayoutCount;
556			&m_descriptorSetLayout,									// const VkDescriptorSetLayout*		pSetLayouts;
557			0u,														// deUint32							pushConstantRangeCount;
558			DE_NULL													// const VkPushConstantRange*		pPushConstantRanges;
559		};
560
561		m_pipelineLayout = createPipelineLayout(vk, m_device, &pipelineLayoutParams);
562	}
563
564	// Create compute pipeline
565	{
566		m_computeShaderModule = createShaderModule(vk, m_device, m_context.getBinaryCollection().get("compute"), 0);
567
568		const VkPipelineShaderStageCreateInfo computeStageParams =
569		{
570			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
571			DE_NULL,												// const void*							pNext;
572			0u,														// VkPipelineShaderStageCreateFlags		flags;
573			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
574			*m_computeShaderModule,									// VkShaderModule						module;
575			"main",													// const char*							pName;
576			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
577		};
578
579		const void* pNext = DE_NULL;
580#ifndef CTS_USES_VULKANSC
581		VkPipelineRobustnessCreateInfoEXT pipelineRobustnessInfo = initVulkanStructure();
582
583		if (testPipelineRobustness)
584		{
585			pipelineRobustnessInfo.storageBuffers	= VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
586			pipelineRobustnessInfo.uniformBuffers	= VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
587			pipelineRobustnessInfo.vertexInputs		= VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT;
588			pipelineRobustnessInfo.images			= VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT;
589			pNext									= &pipelineRobustnessInfo;
590		}
591#else
592		DE_UNREF(testPipelineRobustness);
593#endif
594
595		const VkComputePipelineCreateInfo computePipelineParams =
596		{
597			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,				// VkStructureType						sType;
598			pNext,														// const void*							pNext;
599			0u,															// VkPipelineCreateFlags				flags;
600			computeStageParams,											// VkPipelineShaderStageCreateInfo		stage;
601			*m_pipelineLayout,											// VkPipelineLayout						layout;
602			DE_NULL,													// VkPipeline							basePipelineHandle;
603			0u															// deInt32								basePipelineIndex;
604		};
605
606		m_computePipeline = createComputePipeline(vk, m_device, DE_NULL, &computePipelineParams);
607	}
608
609	// Record commands
610	{
611		beginCommandBuffer(vk, *m_commandBuffer, 0u);
612		vk.cmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
613		vk.cmdBindDescriptorSets(*m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &m_descriptorSet, 0, DE_NULL);
614		vk.cmdDispatch(*m_commandBuffer, 32, 32, 1);
615		endCommandBuffer(vk, *m_commandBuffer);
616	}
617}
618
619} // robustness
620} // vkt
621