Home | History | Annotate | Download | only in robustness
      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 "vkDefs.hpp"
     27 #include "vkImageUtil.hpp"
     28 #include "vkPrograms.hpp"
     29 #include "vkQueryUtil.hpp"
     30 #include "vkRefUtil.hpp"
     31 #include "vkTypeUtil.hpp"
     32 #include "vkCmdUtil.hpp"
     33 #include "vkObjUtil.hpp"
     34 #include "deMath.h"
     35 #include <iomanip>
     36 #include <limits>
     37 #include <sstream>
     38 
     39 namespace vkt
     40 {
     41 namespace robustness
     42 {
     43 
     44 using namespace vk;
     45 
     46 Move<VkDevice> createRobustBufferAccessDevice (Context& context)
     47 {
     48 	const float queuePriority = 1.0f;
     49 
     50 	// Create a universal queue that supports graphics and compute
     51 	const VkDeviceQueueCreateInfo queueParams =
     52 	{
     53 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
     54 		DE_NULL,									// const void*					pNext;
     55 		0u,											// VkDeviceQueueCreateFlags		flags;
     56 		context.getUniversalQueueFamilyIndex(),		// deUint32						queueFamilyIndex;
     57 		1u,											// deUint32						queueCount;
     58 		&queuePriority								// const float*					pQueuePriorities;
     59 	};
     60 
     61 	VkPhysicalDeviceFeatures enabledFeatures = context.getDeviceFeatures();
     62 	enabledFeatures.robustBufferAccess = true;
     63 
     64 	const VkDeviceCreateInfo deviceParams =
     65 	{
     66 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,	// VkStructureType					sType;
     67 		DE_NULL,								// const void*						pNext;
     68 		0u,										// VkDeviceCreateFlags				flags;
     69 		1u,										// deUint32							queueCreateInfoCount;
     70 		&queueParams,							// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
     71 		0u,										// deUint32							enabledLayerCount;
     72 		DE_NULL,								// const char* const*				ppEnabledLayerNames;
     73 		0u,										// deUint32							enabledExtensionCount;
     74 		DE_NULL,								// const char* const*				ppEnabledExtensionNames;
     75 		&enabledFeatures						// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
     76 	};
     77 
     78 	return createDevice(context.getPlatformInterface(), context.getInstance(),
     79 						context.getInstanceInterface(), context.getPhysicalDevice(), &deviceParams);
     80 }
     81 
     82 bool areEqual (float a, float b)
     83 {
     84 	return deFloatAbs(a - b) <= 0.001f;
     85 }
     86 
     87 bool isValueZero (const void* valuePtr, size_t valueSizeInBytes)
     88 {
     89 	const deUint8* bytePtr = reinterpret_cast<const deUint8*>(valuePtr);
     90 
     91 	for (size_t i = 0; i < valueSizeInBytes; i++)
     92 	{
     93 		if (bytePtr[i] != 0)
     94 			return false;
     95 	}
     96 
     97 	return true;
     98 }
     99 
    100 bool isValueWithinBuffer (const void* buffer, VkDeviceSize bufferSize, const void* valuePtr, size_t valueSizeInBytes)
    101 {
    102 	const deUint8* byteBuffer = reinterpret_cast<const deUint8*>(buffer);
    103 
    104 	if (bufferSize < ((VkDeviceSize)valueSizeInBytes))
    105 		return false;
    106 
    107 	for (VkDeviceSize i = 0; i <= (bufferSize - valueSizeInBytes); i++)
    108 	{
    109 		if (!deMemCmp(&byteBuffer[i], valuePtr, valueSizeInBytes))
    110 			return true;
    111 	}
    112 
    113 	return false;
    114 }
    115 
    116 bool isValueWithinBufferOrZero (const void* buffer, VkDeviceSize bufferSize, const void* valuePtr, size_t valueSizeInBytes)
    117 {
    118 	return isValueWithinBuffer(buffer, bufferSize, valuePtr, valueSizeInBytes) || isValueZero(valuePtr, valueSizeInBytes);
    119 }
    120 
    121 bool verifyOutOfBoundsVec4 (const void* vecPtr, VkFormat bufferFormat)
    122 {
    123 	if (isUintFormat(bufferFormat))
    124 	{
    125 		const deUint32* data = (deUint32*)vecPtr;
    126 
    127 		return data[0] == 0u
    128 			&& data[1] == 0u
    129 			&& data[2] == 0u
    130 			&& (data[3] == 0u || data[3] == 1u || data[3] == std::numeric_limits<deUint32>::max());
    131 	}
    132 	else if (isIntFormat(bufferFormat))
    133 	{
    134 		const deInt32* data = (deInt32*)vecPtr;
    135 
    136 		return data[0] == 0
    137 			&& data[1] == 0
    138 			&& data[2] == 0
    139 			&& (data[3] == 0 || data[3] == 1 || data[3] == std::numeric_limits<deInt32>::max());
    140 	}
    141 	else if (isFloatFormat(bufferFormat))
    142 	{
    143 		const float* data = (float*)vecPtr;
    144 
    145 		return areEqual(data[0], 0.0f)
    146 			&& areEqual(data[1], 0.0f)
    147 			&& areEqual(data[2], 0.0f)
    148 			&& (areEqual(data[3], 0.0f) || areEqual(data[3], 1.0f));
    149 	}
    150 	else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    151 	{
    152 		return *((deUint32*)vecPtr) == 0xc0000000u;
    153 	}
    154 
    155 	DE_ASSERT(false);
    156 	return false;
    157 }
    158 
    159 void populateBufferWithTestValues (void* buffer, VkDeviceSize size, VkFormat format)
    160 {
    161 	// Assign a sequence of 32-bit values
    162 	for (VkDeviceSize scalarNdx = 0; scalarNdx < size / 4; scalarNdx++)
    163 	{
    164 		const deUint32 valueIndex = (deUint32)(2 + scalarNdx); // Do not use 0 or 1
    165 
    166 		if (isUintFormat(format))
    167 		{
    168 			reinterpret_cast<deUint32*>(buffer)[scalarNdx] = valueIndex;
    169 		}
    170 		else if (isIntFormat(format))
    171 		{
    172 			reinterpret_cast<deInt32*>(buffer)[scalarNdx] = -deInt32(valueIndex);
    173 		}
    174 		else if (isFloatFormat(format))
    175 		{
    176 			reinterpret_cast<float*>(buffer)[scalarNdx] = float(valueIndex);
    177 		}
    178 		else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    179 		{
    180 			const deUint32	r	= ((valueIndex + 0) & ((2u << 10) - 1u));
    181 			const deUint32	g	= ((valueIndex + 1) & ((2u << 10) - 1u));
    182 			const deUint32	b	= ((valueIndex + 2) & ((2u << 10) - 1u));
    183 			const deUint32	a	= ((valueIndex + 0) & ((2u << 2) - 1u));
    184 
    185 			reinterpret_cast<deUint32*>(buffer)[scalarNdx] = (a << 30) | (b << 20) | (g << 10) | r;
    186 		}
    187 		else
    188 		{
    189 			DE_ASSERT(false);
    190 		}
    191 	}
    192 }
    193 
    194 void logValue (std::ostringstream& logMsg, const void* valuePtr, VkFormat valueFormat, size_t valueSize)
    195 {
    196 	if (isUintFormat(valueFormat))
    197 	{
    198 		logMsg << *reinterpret_cast<const deUint32*>(valuePtr);
    199 	}
    200 	else if (isIntFormat(valueFormat))
    201 	{
    202 		logMsg << *reinterpret_cast<const deInt32*>(valuePtr);
    203 	}
    204 	else if (isFloatFormat(valueFormat))
    205 	{
    206 		logMsg << *reinterpret_cast<const float*>(valuePtr);
    207 	}
    208 	else
    209 	{
    210 		const deUint8*				bytePtr		= reinterpret_cast<const deUint8*>(valuePtr);
    211 		const std::ios::fmtflags	streamFlags	= logMsg.flags();
    212 
    213 		logMsg << std::hex;
    214 		for (size_t i = 0; i < valueSize; i++)
    215 		{
    216 			logMsg << " " << (deUint32)bytePtr[i];
    217 		}
    218 		logMsg.flags(streamFlags);
    219 	}
    220 }
    221 
    222 // TestEnvironment
    223 
    224 TestEnvironment::TestEnvironment (Context&				context,
    225 								  VkDevice				device,
    226 								  VkDescriptorSetLayout	descriptorSetLayout,
    227 								  VkDescriptorSet		descriptorSet)
    228 	: m_context				(context)
    229 	, m_device				(device)
    230 	, m_descriptorSetLayout	(descriptorSetLayout)
    231 	, m_descriptorSet		(descriptorSet)
    232 {
    233 	const DeviceInterface& vk = context.getDeviceInterface();
    234 
    235 	// Create command pool
    236 	{
    237 		const VkCommandPoolCreateInfo commandPoolParams =
    238 		{
    239 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
    240 			DE_NULL,										// const void*				pNext;
    241 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
    242 			context.getUniversalQueueFamilyIndex()			// deUint32					queueFamilyIndex;
    243 		};
    244 
    245 		m_commandPool = createCommandPool(vk, m_device, &commandPoolParams);
    246 	}
    247 
    248 	// Create command buffer
    249 	{
    250 		const VkCommandBufferAllocateInfo commandBufferAllocateInfo =
    251 		{
    252 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    253 			DE_NULL,										// const void*				pNext;
    254 			*m_commandPool,										// VkCommandPool			commandPool;
    255 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    256 			1u,												// deUint32					bufferCount;
    257 		};
    258 
    259 		m_commandBuffer = allocateCommandBuffer(vk, m_device, &commandBufferAllocateInfo);
    260 	}
    261 }
    262 
    263 VkCommandBuffer TestEnvironment::getCommandBuffer (void)
    264 {
    265 	return *m_commandBuffer;
    266 }
    267 
    268 // GraphicsEnvironment
    269 
    270 GraphicsEnvironment::GraphicsEnvironment (Context&					context,
    271 										  VkDevice					device,
    272 										  VkDescriptorSetLayout		descriptorSetLayout,
    273 										  VkDescriptorSet			descriptorSet,
    274 										  const VertexBindings&		vertexBindings,
    275 										  const VertexAttributes&	vertexAttributes,
    276 										  const DrawConfig&			drawConfig)
    277 
    278 	: TestEnvironment		(context, device, descriptorSetLayout, descriptorSet)
    279 	, m_renderSize			(16, 16)
    280 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
    281 {
    282 	const DeviceInterface&		vk						= context.getDeviceInterface();
    283 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    284 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    285 	SimpleAllocator				memAlloc				(vk, m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    286 
    287 	// Create color image and view
    288 	{
    289 		const VkImageCreateInfo colorImageParams =
    290 		{
    291 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    292 			DE_NULL,																	// const void*				pNext;
    293 			0u,																			// VkImageCreateFlags		flags;
    294 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    295 			m_colorFormat,																// VkFormat					format;
    296 			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
    297 			1u,																			// deUint32					mipLevels;
    298 			1u,																			// deUint32					arrayLayers;
    299 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    300 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    301 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
    302 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    303 			1u,																			// deUint32					queueFamilyIndexCount;
    304 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    305 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    306 		};
    307 
    308 		m_colorImage			= createImage(vk, m_device, &colorImageParams);
    309 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, m_device, *m_colorImage), MemoryRequirement::Any);
    310 		VK_CHECK(vk.bindImageMemory(m_device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
    311 
    312 		const VkImageViewCreateInfo colorAttachmentViewParams =
    313 		{
    314 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    315 			DE_NULL,											// const void*				pNext;
    316 			0u,													// VkImageViewCreateFlags	flags;
    317 			*m_colorImage,										// VkImage					image;
    318 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    319 			m_colorFormat,										// VkFormat					format;
    320 			componentMappingRGBA,								// VkComponentMapping		components;
    321 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    322 		};
    323 
    324 		m_colorAttachmentView = createImageView(vk, m_device, &colorAttachmentViewParams);
    325 	}
    326 
    327 	// Create render pass
    328 	m_renderPass = makeRenderPass(vk, m_device, m_colorFormat);
    329 
    330 	// Create framebuffer
    331 	{
    332 		const VkFramebufferCreateInfo framebufferParams =
    333 		{
    334 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
    335 			DE_NULL,											// const void*				pNext;
    336 			0u,													// VkFramebufferCreateFlags	flags;
    337 			*m_renderPass,										// VkRenderPass				renderPass;
    338 			1u,													// deUint32					attachmentCount;
    339 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
    340 			(deUint32)m_renderSize.x(),							// deUint32					width;
    341 			(deUint32)m_renderSize.y(),							// deUint32					height;
    342 			1u													// deUint32					layers;
    343 		};
    344 
    345 		m_framebuffer = createFramebuffer(vk, m_device, &framebufferParams);
    346 	}
    347 
    348 	// Create pipeline layout
    349 	{
    350 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    351 		{
    352 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    353 			DE_NULL,											// const void*					pNext;
    354 			0u,													// VkPipelineLayoutCreateFlags	flags;
    355 			1u,													// deUint32						setLayoutCount;
    356 			&m_descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
    357 			0u,													// deUint32						pushConstantRangeCount;
    358 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
    359 		};
    360 
    361 		m_pipelineLayout = createPipelineLayout(vk, m_device, &pipelineLayoutParams);
    362 	}
    363 
    364 	m_vertexShaderModule	= createShaderModule(vk, m_device, m_context.getBinaryCollection().get("vertex"), 0);
    365 	m_fragmentShaderModule	= createShaderModule(vk, m_device, m_context.getBinaryCollection().get("fragment"), 0);
    366 
    367 	// Create pipeline
    368 	{
    369 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
    370 		{
    371 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
    372 			DE_NULL,														// const void*								pNext;
    373 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
    374 			(deUint32)vertexBindings.size(),								// deUint32									vertexBindingDescriptionCount;
    375 			vertexBindings.data(),											// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
    376 			(deUint32)vertexAttributes.size(),								// deUint32									vertexAttributeDescriptionCount;
    377 			vertexAttributes.data()											// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
    378 		};
    379 
    380 		const std::vector<VkViewport>	viewports	(1, makeViewport(m_renderSize));
    381 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(m_renderSize));
    382 
    383 		m_graphicsPipeline = makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
    384 												  m_device,								// const VkDevice                                device
    385 												  *m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
    386 												  *m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
    387 												  DE_NULL,								// const VkShaderModule                          tessellationControlShaderModule
    388 												  DE_NULL,								// const VkShaderModule                          tessellationEvalShaderModule
    389 												  DE_NULL,								// const VkShaderModule                          geometryShaderModule
    390 												  *m_fragmentShaderModule,				// const VkShaderModule                          fragmentShaderModule
    391 												  *m_renderPass,						// const VkRenderPass                            renderPass
    392 												  viewports,							// const std::vector<VkViewport>&                viewports
    393 												  scissors,								// const std::vector<VkRect2D>&                  scissors
    394 												  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology                     topology
    395 												  0u,									// const deUint32                                subpass
    396 												  0u,									// const deUint32                                patchControlPoints
    397 												  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
    398 	}
    399 
    400 	// Record commands
    401 	{
    402 		const VkImageMemoryBarrier imageLayoutBarrier =
    403 		{
    404 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// VkStructureType			sType;
    405 			DE_NULL,												// const void*				pNext;
    406 			(VkAccessFlags)0,										// VkAccessFlags			srcAccessMask;
    407 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
    408 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			oldLayout;
    409 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			newLayout;
    410 			VK_QUEUE_FAMILY_IGNORED,								// uint32_t					srcQueueFamilyIndex;
    411 			VK_QUEUE_FAMILY_IGNORED,								// uint32_t					dstQueueFamilyIndex;
    412 			*m_colorImage,											// VkImage					image;
    413 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }			// VkImageSubresourceRange	subresourceRange;
    414 		};
    415 
    416 		beginCommandBuffer(vk, *m_commandBuffer, 0u);
    417 		{
    418 			vk.cmdPipelineBarrier(*m_commandBuffer,
    419 								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
    420 								  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
    421 								  (VkDependencyFlags)0,
    422 								  0u, DE_NULL,
    423 								  0u, DE_NULL,
    424 								  1u, &imageLayoutBarrier);
    425 
    426 			beginRenderPass(vk, *m_commandBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.0f));
    427 			{
    428 				const std::vector<VkDeviceSize> vertexBufferOffsets(drawConfig.vertexBuffers.size(), 0ull);
    429 
    430 				vk.cmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
    431 				vk.cmdBindDescriptorSets(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet, 0, DE_NULL);
    432 				vk.cmdBindVertexBuffers(*m_commandBuffer, 0, (deUint32)drawConfig.vertexBuffers.size(), drawConfig.vertexBuffers.data(), vertexBufferOffsets.data());
    433 
    434 				if (drawConfig.indexBuffer == DE_NULL || drawConfig.indexCount == 0)
    435 				{
    436 					vk.cmdDraw(*m_commandBuffer, drawConfig.vertexCount, drawConfig.instanceCount, 0, 0);
    437 				}
    438 				else
    439 				{
    440 					vk.cmdBindIndexBuffer(*m_commandBuffer, drawConfig.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
    441 					vk.cmdDrawIndexed(*m_commandBuffer, drawConfig.indexCount, drawConfig.instanceCount, 0, 0, 0);
    442 				}
    443 			}
    444 			endRenderPass(vk, *m_commandBuffer);
    445 		}
    446 		endCommandBuffer(vk, *m_commandBuffer);
    447 	}
    448 }
    449 
    450 // ComputeEnvironment
    451 
    452 ComputeEnvironment::ComputeEnvironment (Context&				context,
    453 										VkDevice				device,
    454 										VkDescriptorSetLayout	descriptorSetLayout,
    455 										VkDescriptorSet			descriptorSet)
    456 
    457 	: TestEnvironment	(context, device, descriptorSetLayout, descriptorSet)
    458 {
    459 	const DeviceInterface& vk = context.getDeviceInterface();
    460 
    461 	// Create pipeline layout
    462 	{
    463 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    464 		{
    465 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			// VkStructureType					sType;
    466 			DE_NULL,												// const void*						pNext;
    467 			0u,														// VkPipelineLayoutCreateFlags		flags;
    468 			1u,														// deUint32							setLayoutCount;
    469 			&m_descriptorSetLayout,									// const VkDescriptorSetLayout*		pSetLayouts;
    470 			0u,														// deUint32							pushConstantRangeCount;
    471 			DE_NULL													// const VkPushConstantRange*		pPushConstantRanges;
    472 		};
    473 
    474 		m_pipelineLayout = createPipelineLayout(vk, m_device, &pipelineLayoutParams);
    475 	}
    476 
    477 	// Create compute pipeline
    478 	{
    479 		m_computeShaderModule = createShaderModule(vk, m_device, m_context.getBinaryCollection().get("compute"), 0);
    480 
    481 		const VkPipelineShaderStageCreateInfo computeStageParams =
    482 		{
    483 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
    484 			DE_NULL,												// const void*							pNext;
    485 			0u,														// VkPipelineShaderStageCreateFlags		flags;
    486 			VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
    487 			*m_computeShaderModule,									// VkShaderModule						module;
    488 			"main",													// const char*							pName;
    489 			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
    490 		};
    491 
    492 		const VkComputePipelineCreateInfo computePipelineParams =
    493 		{
    494 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType						sType;
    495 			DE_NULL,												// const void*							pNext;
    496 			0u,														// VkPipelineCreateFlags				flags;
    497 			computeStageParams,										// VkPipelineShaderStageCreateInfo		stage;
    498 			*m_pipelineLayout,										// VkPipelineLayout						layout;
    499 			DE_NULL,												// VkPipeline							basePipelineHandle;
    500 			0u														// deInt32								basePipelineIndex;
    501 		};
    502 
    503 		m_computePipeline = createComputePipeline(vk, m_device, DE_NULL, &computePipelineParams);
    504 	}
    505 
    506 	// Record commands
    507 	{
    508 		beginCommandBuffer(vk, *m_commandBuffer, 0u);
    509 		vk.cmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
    510 		vk.cmdBindDescriptorSets(*m_commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &m_descriptorSet, 0, DE_NULL);
    511 		vk.cmdDispatch(*m_commandBuffer, 32, 32, 1);
    512 		endCommandBuffer(vk, *m_commandBuffer);
    513 	}
    514 }
    515 
    516 } // robustness
    517 } // vkt
    518