Home | History | Annotate | Download | only in binding_model
      1 /*-------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 Google Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Binding shader access tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktBindingShaderAccessTests.hpp"
     25 
     26 #include "vktTestCase.hpp"
     27 
     28 #include "vkDefs.hpp"
     29 #include "vkRef.hpp"
     30 #include "vkRefUtil.hpp"
     31 #include "vkPlatform.hpp"
     32 #include "vkPrograms.hpp"
     33 #include "vkMemUtil.hpp"
     34 #include "vkBuilderUtil.hpp"
     35 #include "vkQueryUtil.hpp"
     36 #include "vkImageUtil.hpp"
     37 #include "vkTypeUtil.hpp"
     38 
     39 #include "tcuVector.hpp"
     40 #include "tcuVectorUtil.hpp"
     41 #include "tcuTexture.hpp"
     42 #include "tcuTextureUtil.hpp"
     43 #include "tcuResultCollector.hpp"
     44 #include "tcuTestLog.hpp"
     45 #include "tcuRGBA.hpp"
     46 #include "tcuSurface.hpp"
     47 #include "tcuImageCompare.hpp"
     48 
     49 #include "deUniquePtr.hpp"
     50 #include "deSharedPtr.hpp"
     51 #include "deStringUtil.hpp"
     52 #include "deArrayUtil.hpp"
     53 
     54 #include "qpInfo.h"
     55 
     56 namespace vkt
     57 {
     58 namespace BindingModel
     59 {
     60 namespace
     61 {
     62 
     63 enum ResourceFlag
     64 {
     65 	RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
     66 
     67 	RESOURCE_FLAG_LAST				= (1u << 1u)
     68 };
     69 
     70 static const char* const s_quadrantGenVertexPosSource =	"	highp int quadPhase = gl_VertexIndex % 6;\n"
     71 														"	highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
     72 														"	highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
     73 														"	highp int quadOriginX = (gl_VertexIndex / 6) % 2;\n"
     74 														"	highp int quadOriginY = (gl_VertexIndex / 6) / 2;\n"
     75 														"	quadrant_id = gl_VertexIndex / 6;\n"
     76 														"	result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
     77 
     78 bool isUniformDescriptorType (vk::VkDescriptorType type)
     79 {
     80 	return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
     81 		   type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
     82 		   type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
     83 }
     84 
     85 bool isDynamicDescriptorType (vk::VkDescriptorType type)
     86 {
     87 	return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
     88 }
     89 
     90 void verifyDriverSupport(const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
     91 						 vk::VkDescriptorType					descType,
     92 						 vk::VkShaderStageFlags					activeStages)
     93 {
     94 	switch (descType)
     95 	{
     96 		case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
     97 		case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
     98 		case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
     99 		case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
    100 		case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
    101 		case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
    102 			// These are supported in all stages
    103 			return;
    104 
    105 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
    106 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
    107 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
    108 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
    109 			if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT |
    110 								vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
    111 								vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
    112 								vk::VK_SHADER_STAGE_GEOMETRY_BIT))
    113 			{
    114 				if (!deviceFeatures.vertexPipelineStoresAndAtomics)
    115 					TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
    116 			}
    117 
    118 			if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
    119 			{
    120 				if (!deviceFeatures.fragmentStoresAndAtomics)
    121 					TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in fragment shaders").c_str());
    122 			}
    123 			return;
    124 
    125 		default:
    126 			DE_FATAL("Impossible");
    127 	}
    128 }
    129 
    130 vk::VkImageType viewTypeToImageType (vk::VkImageViewType type)
    131 {
    132 	switch (type)
    133 	{
    134 		case vk::VK_IMAGE_VIEW_TYPE_1D:
    135 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:	return vk::VK_IMAGE_TYPE_1D;
    136 		case vk::VK_IMAGE_VIEW_TYPE_2D:
    137 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:	return vk::VK_IMAGE_TYPE_2D;
    138 		case vk::VK_IMAGE_VIEW_TYPE_3D:			return vk::VK_IMAGE_TYPE_3D;
    139 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
    140 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:	return vk::VK_IMAGE_TYPE_2D;
    141 
    142 		default:
    143 			DE_FATAL("Impossible");
    144 			return (vk::VkImageType)0;
    145 	}
    146 }
    147 
    148 vk::VkImageLayout getImageLayoutForDescriptorType (vk::VkDescriptorType descType)
    149 {
    150 	if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
    151 		return vk::VK_IMAGE_LAYOUT_GENERAL;
    152 	else
    153 		return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    154 }
    155 
    156 deUint32 getTextureLevelPyramidDataSize (const tcu::TextureLevelPyramid& srcImage)
    157 {
    158 	deUint32 dataSize = 0;
    159 	for (int level = 0; level < srcImage.getNumLevels(); ++level)
    160 	{
    161 		const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
    162 
    163 		// tightly packed
    164 		DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
    165 
    166 		dataSize += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
    167 	}
    168 	return dataSize;
    169 }
    170 
    171 void writeTextureLevelPyramidData (void* dst, deUint32 dstLen, const tcu::TextureLevelPyramid& srcImage, vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy>* copySlices)
    172 {
    173 	// \note cube is copied face-by-face
    174 	const deUint32	arraySize	= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (srcImage.getLevel(0).getHeight()) :
    175 								  (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (srcImage.getLevel(0).getDepth()) :
    176 								  (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)														? (1) :
    177 								  (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (srcImage.getLevel(0).getDepth()) :
    178 								  ((deUint32)0);
    179 	deUint32		levelOffset	= 0;
    180 
    181 	DE_ASSERT(arraySize != 0);
    182 
    183 	for (int level = 0; level < srcImage.getNumLevels(); ++level)
    184 	{
    185 		const tcu::ConstPixelBufferAccess	srcAccess		= srcImage.getLevel(level);
    186 		const tcu::PixelBufferAccess		dstAccess		(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), (deUint8*)dst + levelOffset);
    187 		const deUint32						dataSize		= srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
    188 		const deUint32						sliceDataSize	= dataSize / arraySize;
    189 		const deInt32						sliceHeight		= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (srcAccess.getHeight());
    190 		const deInt32						sliceDepth		= (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
    191 		const tcu::IVec3					sliceSize		(srcAccess.getWidth(), sliceHeight, sliceDepth);
    192 
    193 		// tightly packed
    194 		DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
    195 
    196 		for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
    197 		{
    198 			const vk::VkBufferImageCopy copySlice =
    199 			{
    200 				(vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize,	// bufferOffset
    201 				(deUint32)sliceSize.x(),									// bufferRowLength
    202 				(deUint32)sliceSize.y(),									// bufferImageHeight
    203 				{
    204 					vk::VK_IMAGE_ASPECT_COLOR_BIT,		// aspectMask
    205 					(deUint32)level,					// mipLevel
    206 					(deUint32)sliceNdx,					// arrayLayer
    207 					1u,									// arraySize
    208 				},															// imageSubresource
    209 				{
    210 					0,
    211 					0,
    212 					0,
    213 				},															// imageOffset
    214 				{
    215 					(deUint32)sliceSize.x(),
    216 					(deUint32)sliceSize.y(),
    217 					(deUint32)sliceSize.z(),
    218 				}															// imageExtent
    219 			};
    220 			copySlices->push_back(copySlice);
    221 		}
    222 
    223 		DE_ASSERT(arraySize * sliceDataSize == dataSize);
    224 
    225 		tcu::copy(dstAccess, srcAccess);
    226 		levelOffset += dataSize;
    227 	}
    228 
    229 	DE_ASSERT(dstLen == levelOffset);
    230 	DE_UNREF(dstLen);
    231 }
    232 
    233 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkBuffer buffer, vk::MemoryRequirement requirement)
    234 {
    235 	const vk::VkMemoryRequirements	requirements	= vk::getBufferMemoryRequirements(vki, device, buffer);
    236 	de::MovePtr<vk::Allocation>		allocation		= allocator.allocate(requirements, requirement);
    237 
    238 	VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
    239 	return allocation;
    240 }
    241 
    242 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkImage image, vk::MemoryRequirement requirement)
    243 {
    244 	const vk::VkMemoryRequirements	requirements	= vk::getImageMemoryRequirements(vki, device, image);
    245 	de::MovePtr<vk::Allocation>		allocation		= allocator.allocate(requirements, requirement);
    246 
    247 	VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
    248 	return allocation;
    249 }
    250 
    251 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkSampler sampler)
    252 {
    253 	return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0);
    254 }
    255 
    256 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkImageView imageView, vk::VkImageLayout layout)
    257 {
    258 	return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout);
    259 }
    260 
    261 void drawQuadrantReferenceResult (const tcu::PixelBufferAccess& dst, const tcu::Vec4& c1, const tcu::Vec4& c2, const tcu::Vec4& c3, const tcu::Vec4& c4)
    262 {
    263 	tcu::clear(tcu::getSubregion(dst, 0,					0,						dst.getWidth() / 2,						dst.getHeight() / 2),					c1);
    264 	tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2,	0,						dst.getWidth() - dst.getWidth() / 2,	dst.getHeight() / 2),					c2);
    265 	tcu::clear(tcu::getSubregion(dst, 0,					dst.getHeight() / 2,	dst.getWidth() / 2,						dst.getHeight() - dst.getHeight() / 2),	c3);
    266 	tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2,	dst.getHeight() / 2,	dst.getWidth() - dst.getWidth() / 2,	dst.getHeight() - dst.getHeight() / 2),	c4);
    267 }
    268 
    269 class SingleTargetRenderInstance : public vkt::TestInstance
    270 {
    271 public:
    272 											SingleTargetRenderInstance	(Context&			context,
    273 																		 const tcu::UVec2&	size);
    274 
    275 private:
    276 	static vk::Move<vk::VkImage>			createColorAttachment		(const vk::DeviceInterface&		vki,
    277 																		 vk::VkDevice					device,
    278 																		 vk::Allocator&					allocator,
    279 																		 const tcu::TextureFormat&		format,
    280 																		 const tcu::UVec2&				size,
    281 																		 de::MovePtr<vk::Allocation>*	outAllocation);
    282 
    283 	static vk::Move<vk::VkImageView>		createColorAttachmentView	(const vk::DeviceInterface&	vki,
    284 																		 vk::VkDevice				device,
    285 																		 const tcu::TextureFormat&	format,
    286 																		 vk::VkImage				image);
    287 
    288 	static vk::Move<vk::VkRenderPass>		createRenderPass			(const vk::DeviceInterface&	vki,
    289 																		 vk::VkDevice				device,
    290 																		 const tcu::TextureFormat&	format);
    291 
    292 	static vk::Move<vk::VkFramebuffer>		createFramebuffer			(const vk::DeviceInterface&	vki,
    293 																		 vk::VkDevice				device,
    294 																		 vk::VkRenderPass			renderpass,
    295 																		 vk::VkImageView			colorAttachmentView,
    296 																		 const tcu::UVec2&			size);
    297 
    298 	static vk::Move<vk::VkCommandPool>		createCommandPool			(const vk::DeviceInterface&	vki,
    299 																		 vk::VkDevice				device,
    300 																		 deUint32					queueFamilyIndex);
    301 
    302 	virtual void							logTestPlan					(void) const = 0;
    303 	virtual void							renderToTarget				(void) = 0;
    304 	virtual tcu::TestStatus					verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const = 0;
    305 
    306 	void									readRenderTarget			(tcu::TextureLevel& dst);
    307 	tcu::TestStatus							iterate						(void);
    308 
    309 protected:
    310 	const tcu::TextureFormat				m_targetFormat;
    311 	const tcu::UVec2						m_targetSize;
    312 
    313 	const vk::DeviceInterface&				m_vki;
    314 	const vk::VkDevice						m_device;
    315 	const vk::VkQueue						m_queue;
    316 	const deUint32							m_queueFamilyIndex;
    317 	vk::Allocator&							m_allocator;
    318 	de::MovePtr<vk::Allocation>				m_colorAttachmentMemory;
    319 	const vk::Unique<vk::VkImage>			m_colorAttachmentImage;
    320 	const vk::Unique<vk::VkImageView>		m_colorAttachmentView;
    321 	const vk::Unique<vk::VkRenderPass>		m_renderPass;
    322 	const vk::Unique<vk::VkFramebuffer>		m_framebuffer;
    323 	const vk::Unique<vk::VkCommandPool>		m_cmdPool;
    324 
    325 	bool									m_firstIteration;
    326 };
    327 
    328 SingleTargetRenderInstance::SingleTargetRenderInstance (Context&			context,
    329 														const tcu::UVec2&	size)
    330 	: vkt::TestInstance			(context)
    331 	, m_targetFormat			(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
    332 	, m_targetSize				(size)
    333 	, m_vki						(context.getDeviceInterface())
    334 	, m_device					(context.getDevice())
    335 	, m_queue					(context.getUniversalQueue())
    336 	, m_queueFamilyIndex		(context.getUniversalQueueFamilyIndex())
    337 	, m_allocator				(context.getDefaultAllocator())
    338 	, m_colorAttachmentMemory	(DE_NULL)
    339 	, m_colorAttachmentImage	(createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
    340 	, m_colorAttachmentView		(createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
    341 	, m_renderPass				(createRenderPass(m_vki, m_device, m_targetFormat))
    342 	, m_framebuffer				(createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
    343 	, m_cmdPool					(createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
    344 	, m_firstIteration			(true)
    345 {
    346 }
    347 
    348 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment (const vk::DeviceInterface&		vki,
    349 																		 vk::VkDevice					device,
    350 																		 vk::Allocator&					allocator,
    351 																		 const tcu::TextureFormat&		format,
    352 																		 const tcu::UVec2&				size,
    353 																		 de::MovePtr<vk::Allocation>*	outAllocation)
    354 {
    355 	const vk::VkImageCreateInfo	imageInfo	=
    356 	{
    357 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
    358 		DE_NULL,
    359 		(vk::VkImageCreateFlags)0,
    360 		vk::VK_IMAGE_TYPE_2D,							// imageType
    361 		vk::mapTextureFormat(format),					// format
    362 		{ size.x(), size.y(), 1u },						// extent
    363 		1,												// mipLevels
    364 		1,												// arraySize
    365 		vk::VK_SAMPLE_COUNT_1_BIT,						// samples
    366 		vk::VK_IMAGE_TILING_OPTIMAL,					// tiling
    367 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// usage
    368 		vk::VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
    369 		0u,												// queueFamilyCount
    370 		DE_NULL,										// pQueueFamilyIndices
    371 		vk::VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
    372 	};
    373 
    374 	vk::Move<vk::VkImage>		image		(vk::createImage(vki, device, &imageInfo));
    375 	de::MovePtr<vk::Allocation>	allocation	(allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
    376 
    377 	*outAllocation = allocation;
    378 	return image;
    379 }
    380 
    381 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView (const vk::DeviceInterface&	vki,
    382 																				 vk::VkDevice				device,
    383 																				 const tcu::TextureFormat&	format,
    384 																				 vk::VkImage				image)
    385 {
    386 	const vk::VkImageViewCreateInfo createInfo =
    387 	{
    388 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
    389 		DE_NULL,
    390 		(vk::VkImageViewCreateFlags)0,
    391 		image,							// image
    392 		vk::VK_IMAGE_VIEW_TYPE_2D,		// viewType
    393 		vk::mapTextureFormat(format),	// format
    394 		vk::makeComponentMappingRGBA(),
    395 		{
    396 			vk::VK_IMAGE_ASPECT_COLOR_BIT,	// aspectMask
    397 			0u,								// baseMipLevel
    398 			1u,								// mipLevels
    399 			0u,								// baseArrayLayer
    400 			1u,								// arraySize
    401 		},
    402 	};
    403 
    404 	return vk::createImageView(vki, device, &createInfo);
    405 }
    406 
    407 vk::Move<vk::VkRenderPass> SingleTargetRenderInstance::createRenderPass (const vk::DeviceInterface&		vki,
    408 																		 vk::VkDevice					device,
    409 																		 const tcu::TextureFormat&		format)
    410 {
    411 	const vk::VkAttachmentDescription	attachmentDescription	=
    412 	{
    413 		(vk::VkAttachmentDescriptionFlags)0,
    414 		vk::mapTextureFormat(format),					// format
    415 		vk::VK_SAMPLE_COUNT_1_BIT,						// samples
    416 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				// loadOp
    417 		vk::VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
    418 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
    419 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
    420 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// initialLayout
    421 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// finalLayout
    422 	};
    423 	const vk::VkAttachmentReference		colorAttachment			=
    424 	{
    425 		0u,												// attachment
    426 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// layout
    427 	};
    428 	const vk::VkAttachmentReference		depthStencilAttachment	=
    429 	{
    430 		vk::VK_NO_ATTACHMENT,							// attachment
    431 		vk::VK_IMAGE_LAYOUT_UNDEFINED					// layout
    432 	};
    433 	const vk::VkSubpassDescription		subpass					=
    434 	{
    435 		(vk::VkSubpassDescriptionFlags)0,
    436 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,			// pipelineBindPoint
    437 		0u,												// inputAttachmentCount
    438 		DE_NULL,										// pInputAttachments
    439 		1u,												// colorAttachmentCount
    440 		&colorAttachment,								// pColorAttachments
    441 		DE_NULL,										// pResolveAttachments
    442 		&depthStencilAttachment,						// pDepthStencilAttachment
    443 		0u,												// preserveAttachmentCount
    444 		DE_NULL											// pPreserveAttachments
    445 	};
    446 	const vk::VkRenderPassCreateInfo	renderPassCreateInfo	=
    447 	{
    448 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
    449 		DE_NULL,
    450 		(vk::VkRenderPassCreateFlags)0,
    451 		1u,												// attachmentCount
    452 		&attachmentDescription,							// pAttachments
    453 		1u,												// subpassCount
    454 		&subpass,										// pSubpasses
    455 		0u,												// dependencyCount
    456 		DE_NULL,										// pDependencies
    457 	};
    458 
    459 	return vk::createRenderPass(vki, device, &renderPassCreateInfo);
    460 }
    461 
    462 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer (const vk::DeviceInterface&	vki,
    463 																		   vk::VkDevice					device,
    464 																		   vk::VkRenderPass				renderpass,
    465 																		   vk::VkImageView				colorAttachmentView,
    466 																		   const tcu::UVec2&			size)
    467 {
    468 	const vk::VkFramebufferCreateInfo	framebufferCreateInfo	=
    469 	{
    470 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
    471 		DE_NULL,
    472 		(vk::VkFramebufferCreateFlags)0,
    473 		renderpass,				// renderPass
    474 		1u,						// attachmentCount
    475 		&colorAttachmentView,	// pAttachments
    476 		size.x(),				// width
    477 		size.y(),				// height
    478 		1,						// layers
    479 	};
    480 
    481 	return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
    482 }
    483 
    484 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool (const vk::DeviceInterface&	vki,
    485 																		   vk::VkDevice					device,
    486 																		   deUint32						queueFamilyIndex)
    487 {
    488 	const vk::VkCommandPoolCreateInfo createInfo =
    489 	{
    490 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
    491 		DE_NULL,
    492 		vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,	// flags
    493 		queueFamilyIndex,							// queueFamilyIndex
    494 	};
    495 	return vk::createCommandPool(vki, device, &createInfo);
    496 }
    497 
    498 void SingleTargetRenderInstance::readRenderTarget (tcu::TextureLevel& dst)
    499 {
    500 	const deUint64							pixelDataSize				= (deUint64)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
    501 	const vk::VkBufferCreateInfo			bufferCreateInfo			=
    502 	{
    503 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
    504 		DE_NULL,
    505 		0u,												// flags
    506 		pixelDataSize,									// size
    507 		vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// usage
    508 		vk::VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
    509 		0u,												// queueFamilyCount
    510 		DE_NULL,										// pQueueFamilyIndices
    511 	};
    512 	const vk::Unique<vk::VkBuffer>			buffer						(vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
    513 	const vk::VkImageSubresourceRange		fullSubrange				=
    514 	{
    515 		vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
    516 		0u,												// baseMipLevel
    517 		1u,												// mipLevels
    518 		0u,												// baseArraySlice
    519 		1u,												// arraySize
    520 	};
    521 	const vk::VkImageMemoryBarrier			imageBarrier				=
    522 	{
    523 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
    524 		DE_NULL,
    525 		vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// srcAccessMask
    526 		vk::VK_ACCESS_TRANSFER_READ_BIT,				// dstAccessMask
    527 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// oldLayout
    528 		vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// newLayout
    529 		vk::VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
    530 		vk::VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
    531 		*m_colorAttachmentImage,						// image
    532 		fullSubrange,									// subresourceRange
    533 	};
    534 	const vk::VkBufferMemoryBarrier			memoryBarrier				=
    535 	{
    536 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
    537 		DE_NULL,
    538 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// srcAccessMask
    539 		vk::VK_ACCESS_HOST_READ_BIT,					// dstAccessMask
    540 		vk::VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
    541 		vk::VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
    542 		*buffer,										// buffer
    543 		0u,												// offset
    544 		(vk::VkDeviceSize)pixelDataSize					// size
    545 	};
    546 	const vk::VkCommandBufferAllocateInfo	cmdBufAllocInfo				=
    547 	{
    548 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
    549 		DE_NULL,
    550 		*m_cmdPool,								// cmdPool
    551 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,	// level
    552 		1u,										// bufferCount
    553 	};
    554 	const vk::VkFenceCreateInfo				fenceCreateInfo				=
    555 	{
    556 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
    557 		DE_NULL,
    558 		0u,												// flags
    559 	};
    560 	const vk::VkCommandBufferBeginInfo		cmdBufBeginInfo				=
    561 	{
    562 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
    563 		DE_NULL,
    564 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
    565 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
    566 	};
    567 	const vk::VkImageSubresourceLayers		firstSlice					=
    568 	{
    569 		vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspect
    570 		0,												// mipLevel
    571 		0,												// arrayLayer
    572 		1,												// arraySize
    573 	};
    574 	const vk::VkBufferImageCopy				copyRegion					=
    575 	{
    576 		0u,												// bufferOffset
    577 		m_targetSize.x(),								// bufferRowLength
    578 		m_targetSize.y(),								// bufferImageHeight
    579 		firstSlice,										// imageSubresource
    580 		{ 0, 0, 0 },									// imageOffset
    581 		{ m_targetSize.x(), m_targetSize.y(), 1u }		// imageExtent
    582 	};
    583 
    584 	const de::MovePtr<vk::Allocation>		bufferMemory				= allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
    585 
    586 	const vk::Unique<vk::VkCommandBuffer>	cmd							(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
    587 	const vk::Unique<vk::VkFence>			cmdCompleteFence			(vk::createFence(m_vki, m_device, &fenceCreateInfo));
    588 	const deUint64							infiniteTimeout				= ~(deUint64)0u;
    589 
    590 	// copy content to buffer
    591 	VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
    592 	m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
    593 							 0, (const vk::VkMemoryBarrier*)DE_NULL,
    594 							 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
    595 							 1, &imageBarrier);
    596 	m_vki.cmdCopyImageToBuffer(*cmd, *m_colorAttachmentImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, &copyRegion);
    597 	m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
    598 							 0, (const vk::VkMemoryBarrier*)DE_NULL,
    599 							 1, &memoryBarrier,
    600 							 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
    601 	VK_CHECK(m_vki.endCommandBuffer(*cmd));
    602 
    603 	// wait for transfer to complete
    604 	{
    605 		const vk::VkSubmitInfo	submitInfo	=
    606 		{
    607 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
    608 			DE_NULL,
    609 			0u,
    610 			(const vk::VkSemaphore*)0,
    611 			(const vk::VkPipelineStageFlags*)DE_NULL,
    612 			1u,
    613 			&cmd.get(),
    614 			0u,
    615 			(const vk::VkSemaphore*)0,
    616 		};
    617 
    618 		VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *cmdCompleteFence));
    619 	}
    620 	VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
    621 
    622 	dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
    623 
    624 	// copy data
    625 	invalidateMappedMemoryRange(m_vki, m_device, bufferMemory->getMemory(), bufferMemory->getOffset(), pixelDataSize);
    626 	tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
    627 }
    628 
    629 tcu::TestStatus SingleTargetRenderInstance::iterate (void)
    630 {
    631 	tcu::TextureLevel resultImage;
    632 
    633 	// log
    634 	if (m_firstIteration)
    635 	{
    636 		logTestPlan();
    637 		m_firstIteration = false;
    638 	}
    639 
    640 	// render
    641 	{
    642 		// transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    643 		const vk::VkImageSubresourceRange		fullSubrange				=
    644 		{
    645 			vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
    646 			0u,												// baseMipLevel
    647 			1u,												// mipLevels
    648 			0u,												// baseArraySlice
    649 			1u,												// arraySize
    650 		};
    651 		const vk::VkImageMemoryBarrier			imageBarrier				=
    652 		{
    653 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
    654 			DE_NULL,
    655 			0u,												// srcAccessMask
    656 			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// dstAccessMask
    657 			vk::VK_IMAGE_LAYOUT_UNDEFINED,					// oldLayout
    658 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// newLayout
    659 			vk::VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
    660 			vk::VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
    661 			*m_colorAttachmentImage,						// image
    662 			fullSubrange,									// subresourceRange
    663 		};
    664 		const vk::VkCommandBufferAllocateInfo	cmdBufAllocInfo				=
    665 		{
    666 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
    667 			DE_NULL,
    668 			*m_cmdPool,										// cmdPool
    669 			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,			// level
    670 			1u,												// count
    671 		};
    672 		const vk::VkCommandBufferBeginInfo		cmdBufBeginInfo				=
    673 		{
    674 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
    675 			DE_NULL,
    676 			vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
    677 			(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
    678 		};
    679 		const vk::VkFenceCreateInfo				fenceCreateInfo				=
    680 		{
    681 			vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
    682 			DE_NULL,
    683 			(vk::VkFenceCreateFlags)0,
    684 		};
    685 
    686 		const vk::Unique<vk::VkCommandBuffer>	cmd					(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
    687 		const vk::Unique<vk::VkFence>			fence				(vk::createFence(m_vki, m_device, &fenceCreateInfo));
    688 		const deUint64							infiniteTimeout		= ~(deUint64)0u;
    689 
    690 		VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
    691 		m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
    692 								 0, (const vk::VkMemoryBarrier*)DE_NULL,
    693 								 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
    694 								 1, &imageBarrier);
    695 		VK_CHECK(m_vki.endCommandBuffer(*cmd));
    696 
    697 		{
    698 			const vk::VkSubmitInfo	submitInfo	=
    699 			{
    700 				vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
    701 				DE_NULL,
    702 				0u,
    703 				(const vk::VkSemaphore*)0,
    704 				(const vk::VkPipelineStageFlags*)DE_NULL,
    705 				1u,
    706 				&cmd.get(),
    707 				0u,
    708 				(const vk::VkSemaphore*)0,
    709 			};
    710 
    711 			VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence));
    712 		}
    713 		VK_CHECK(m_vki.waitForFences(m_device, 1u, &fence.get(), vk::VK_TRUE, infiniteTimeout));
    714 
    715 		// and then render to
    716 		renderToTarget();
    717 	}
    718 
    719 	// read and verify
    720 	readRenderTarget(resultImage);
    721 	return verifyResultImage(resultImage.getAccess());
    722 }
    723 
    724 class RenderInstanceShaders
    725 {
    726 public:
    727 														RenderInstanceShaders		(const vk::DeviceInterface&				vki,
    728 																					 vk::VkDevice							device,
    729 																					 const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
    730 																					 const vk::BinaryCollection&			programCollection);
    731 
    732 	inline bool											hasTessellationStage		(void) const { return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0;	}
    733 	inline deUint32										getNumStages				(void) const { return (deUint32)m_stageInfos.size();								}
    734 	inline const vk::VkPipelineShaderStageCreateInfo*	getStages					(void) const { return &m_stageInfos[0];												}
    735 
    736 private:
    737 	void												addStage					(const vk::DeviceInterface&				vki,
    738 																					 vk::VkDevice							device,
    739 																					 const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
    740 																					 const vk::BinaryCollection&			programCollection,
    741 																					 const char*							name,
    742 																					 vk::VkShaderStageFlagBits				stage,
    743 																					 vk::Move<vk::VkShaderModule>*			outModule);
    744 
    745 	vk::VkPipelineShaderStageCreateInfo					getShaderStageCreateInfo	(vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const;
    746 
    747 	vk::Move<vk::VkShaderModule>						m_vertexShaderModule;
    748 	vk::Move<vk::VkShaderModule>						m_tessCtrlShaderModule;
    749 	vk::Move<vk::VkShaderModule>						m_tessEvalShaderModule;
    750 	vk::Move<vk::VkShaderModule>						m_geometryShaderModule;
    751 	vk::Move<vk::VkShaderModule>						m_fragmentShaderModule;
    752 	std::vector<vk::VkPipelineShaderStageCreateInfo>	m_stageInfos;
    753 };
    754 
    755 RenderInstanceShaders::RenderInstanceShaders (const vk::DeviceInterface&			vki,
    756 											  vk::VkDevice							device,
    757 											  const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
    758 											  const vk::BinaryCollection&			programCollection)
    759 {
    760 	addStage(vki, device, deviceFeatures, programCollection, "vertex",		vk::VK_SHADER_STAGE_VERTEX_BIT,						&m_vertexShaderModule);
    761 	addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl",	vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		&m_tessCtrlShaderModule);
    762 	addStage(vki, device, deviceFeatures, programCollection, "tess_eval",	vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	&m_tessEvalShaderModule);
    763 	addStage(vki, device, deviceFeatures, programCollection, "geometry",	vk::VK_SHADER_STAGE_GEOMETRY_BIT,					&m_geometryShaderModule);
    764 	addStage(vki, device, deviceFeatures, programCollection, "fragment",	vk::VK_SHADER_STAGE_FRAGMENT_BIT,					&m_fragmentShaderModule);
    765 
    766 	DE_ASSERT(!m_stageInfos.empty());
    767 }
    768 
    769 void RenderInstanceShaders::addStage (const vk::DeviceInterface&			vki,
    770 									  vk::VkDevice							device,
    771 									  const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
    772 									  const vk::BinaryCollection&			programCollection,
    773 									  const char*							name,
    774 									  vk::VkShaderStageFlagBits				stage,
    775 									  vk::Move<vk::VkShaderModule>*			outModule)
    776 {
    777 	if (programCollection.contains(name))
    778 	{
    779 		if (vk::isShaderStageSupported(deviceFeatures, stage))
    780 		{
    781 			vk::Move<vk::VkShaderModule>	module	= createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
    782 
    783 			m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
    784 			*outModule = module;
    785 		}
    786 		else
    787 		{
    788 			// Wait for the GPU to idle so that throwing the exception
    789 			// below doesn't free in-use GPU resource.
    790 			vki.deviceWaitIdle(device);
    791 			TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
    792 		}
    793 	}
    794 }
    795 
    796 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const
    797 {
    798 	const vk::VkPipelineShaderStageCreateInfo	stageCreateInfo	=
    799 	{
    800 		vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
    801 		DE_NULL,
    802 		(vk::VkPipelineShaderStageCreateFlags)0,
    803 		stage,			// stage
    804 		shader,			// shader
    805 		"main",
    806 		DE_NULL,		// pSpecializationInfo
    807 	};
    808 	return stageCreateInfo;
    809 }
    810 
    811 class SingleCmdRenderInstance : public SingleTargetRenderInstance
    812 {
    813 public:
    814 									SingleCmdRenderInstance	(Context&			context,
    815 															 bool				isPrimaryCmdBuf,
    816 															 const tcu::UVec2&	renderSize);
    817 
    818 private:
    819 	vk::Move<vk::VkPipeline>		createPipeline				(vk::VkPipelineLayout pipelineLayout);
    820 
    821 	virtual vk::VkPipelineLayout	getPipelineLayout			(void) const = 0;
    822 	virtual void					writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const = 0;
    823 
    824 	void							renderToTarget				(void);
    825 
    826 	const bool						m_isPrimaryCmdBuf;
    827 };
    828 
    829 SingleCmdRenderInstance::SingleCmdRenderInstance (Context&			context,
    830 												  bool				isPrimaryCmdBuf,
    831 												  const tcu::UVec2&	renderSize)
    832 	: SingleTargetRenderInstance	(context, renderSize)
    833 	, m_isPrimaryCmdBuf				(isPrimaryCmdBuf)
    834 {
    835 }
    836 
    837 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline (vk::VkPipelineLayout pipelineLayout)
    838 {
    839 	const RenderInstanceShaders							shaderStages		(m_vki, m_device, m_context.getDeviceFeatures(), m_context.getBinaryCollection());
    840 	const vk::VkPrimitiveTopology						topology			= shaderStages.hasTessellationStage() ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
    841 	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputState	=
    842 	{
    843 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
    844 		DE_NULL,
    845 		(vk::VkPipelineVertexInputStateCreateFlags)0,
    846 		0u,											// bindingCount
    847 		DE_NULL,									// pVertexBindingDescriptions
    848 		0u,											// attributeCount
    849 		DE_NULL,									// pVertexAttributeDescriptions
    850 	};
    851 	const vk::VkPipelineInputAssemblyStateCreateInfo	iaState				=
    852 	{
    853 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
    854 		DE_NULL,
    855 		(vk::VkPipelineInputAssemblyStateCreateFlags)0,
    856 		topology,									// topology
    857 		vk::VK_FALSE,								// primitiveRestartEnable
    858 	};
    859 	const vk::VkPipelineTessellationStateCreateInfo		tessState			=
    860 	{
    861 		vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
    862 		DE_NULL,
    863 		(vk::VkPipelineTessellationStateCreateFlags)0,
    864 		3u,											// patchControlPoints
    865 	};
    866 	const vk::VkViewport								viewport			=
    867 	{
    868 		0.0f,										// originX
    869 		0.0f,										// originY
    870 		float(m_targetSize.x()),					// width
    871 		float(m_targetSize.y()),					// height
    872 		0.0f,										// minDepth
    873 		1.0f,										// maxDepth
    874 	};
    875 	const vk::VkRect2D									renderArea			=
    876 	{
    877 		{ 0, 0 },									// offset
    878 		{ m_targetSize.x(), m_targetSize.y() },		// extent
    879 	};
    880 	const vk::VkPipelineViewportStateCreateInfo			vpState				=
    881 	{
    882 		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
    883 		DE_NULL,
    884 		(vk::VkPipelineViewportStateCreateFlags)0,
    885 		1u,											// viewportCount
    886 		&viewport,
    887 		1u,
    888 		&renderArea,
    889 	};
    890 	const vk::VkPipelineRasterizationStateCreateInfo	rsState				=
    891 	{
    892 		vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
    893 		DE_NULL,
    894 		(vk::VkPipelineRasterizationStateCreateFlags)0,
    895 		vk::VK_TRUE,								// depthClipEnable
    896 		vk::VK_FALSE,								// rasterizerDiscardEnable
    897 		vk::VK_POLYGON_MODE_FILL,					// fillMode
    898 		vk::VK_CULL_MODE_NONE,						// cullMode
    899 		vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,		// frontFace
    900 		vk::VK_FALSE,								// depthBiasEnable
    901 		0.0f,										// depthBias
    902 		0.0f,										// depthBiasClamp
    903 		0.0f,										// slopeScaledDepthBias
    904 		1.0f,										// lineWidth
    905 	};
    906 	const vk::VkSampleMask								sampleMask			= 0x01u;
    907 	const vk::VkPipelineMultisampleStateCreateInfo		msState				=
    908 	{
    909 		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
    910 		DE_NULL,
    911 		(vk::VkPipelineMultisampleStateCreateFlags)0,
    912 		vk::VK_SAMPLE_COUNT_1_BIT,					// rasterSamples
    913 		vk::VK_FALSE,								// sampleShadingEnable
    914 		0.0f,										// minSampleShading
    915 		&sampleMask,								// sampleMask
    916 		vk::VK_FALSE,								// alphaToCoverageEnable
    917 		vk::VK_FALSE,								// alphaToOneEnable
    918 	};
    919 	const vk::VkPipelineDepthStencilStateCreateInfo		dsState				=
    920 	{
    921 		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
    922 		DE_NULL,
    923 		(vk::VkPipelineDepthStencilStateCreateFlags)0,
    924 		vk::VK_FALSE,								// depthTestEnable
    925 		vk::VK_FALSE,								// depthWriteEnable
    926 		vk::VK_COMPARE_OP_ALWAYS,					// depthCompareOp
    927 		vk::VK_FALSE,								// depthBoundsTestEnable
    928 		vk::VK_FALSE,								// stencilTestEnable
    929 		{ vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },	// front
    930 		{ vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },	// back
    931 		-1.0f,										// minDepthBounds
    932 		+1.0f,										// maxDepthBounds
    933 	};
    934 	const vk::VkPipelineColorBlendAttachmentState		cbAttachment		=
    935 	{
    936 		vk::VK_FALSE,								// blendEnable
    937 		vk::VK_BLEND_FACTOR_ZERO,					// srcBlendColor
    938 		vk::VK_BLEND_FACTOR_ZERO,					// destBlendColor
    939 		vk::VK_BLEND_OP_ADD,						// blendOpColor
    940 		vk::VK_BLEND_FACTOR_ZERO,					// srcBlendAlpha
    941 		vk::VK_BLEND_FACTOR_ZERO,					// destBlendAlpha
    942 		vk::VK_BLEND_OP_ADD,						// blendOpAlpha
    943 		(vk::VK_COLOR_COMPONENT_R_BIT |
    944 		 vk::VK_COLOR_COMPONENT_G_BIT |
    945 		 vk::VK_COLOR_COMPONENT_B_BIT |
    946 		 vk::VK_COLOR_COMPONENT_A_BIT),				// channelWriteMask
    947 	};
    948 	const vk::VkPipelineColorBlendStateCreateInfo		cbState				=
    949 	{
    950 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
    951 		DE_NULL,
    952 		(vk::VkPipelineColorBlendStateCreateFlags)0,
    953 		vk::VK_FALSE,								// logicOpEnable
    954 		vk::VK_LOGIC_OP_CLEAR,						// logicOp
    955 		1u,											// attachmentCount
    956 		&cbAttachment,								// pAttachments
    957 		{ 0.0f, 0.0f, 0.0f, 0.0f },					// blendConst
    958 	};
    959 	const vk::VkGraphicsPipelineCreateInfo createInfo =
    960 	{
    961 		vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
    962 		DE_NULL,
    963 		(vk::VkPipelineCreateFlags)0,
    964 		shaderStages.getNumStages(),									// stageCount
    965 		shaderStages.getStages(),										// pStages
    966 		&vertexInputState,												// pVertexInputState
    967 		&iaState,														// pInputAssemblyState
    968 		(shaderStages.hasTessellationStage() ? &tessState : DE_NULL),	// pTessellationState
    969 		&vpState,														// pViewportState
    970 		&rsState,														// pRasterState
    971 		&msState,														// pMultisampleState
    972 		&dsState,														// pDepthStencilState
    973 		&cbState,														// pColorBlendState
    974 		(const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL,			// pDynamicState
    975 		pipelineLayout,													// layout
    976 		*m_renderPass,													// renderPass
    977 		0u,																// subpass
    978 		(vk::VkPipeline)0,												// basePipelineHandle
    979 		0u,																// basePipelineIndex
    980 	};
    981 	return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
    982 }
    983 
    984 void SingleCmdRenderInstance::renderToTarget (void)
    985 {
    986 	const vk::VkRect2D									renderArea						=
    987 	{
    988 		{ 0, 0 },								// offset
    989 		{ m_targetSize.x(), m_targetSize.y() },	// extent
    990 	};
    991 	const vk::VkCommandBufferAllocateInfo				mainCmdBufCreateInfo			=
    992 	{
    993 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
    994 		DE_NULL,
    995 		*m_cmdPool,								// cmdPool
    996 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,	// level
    997 		1u,										// count
    998 	};
    999 	const vk::VkCommandBufferBeginInfo					mainCmdBufBeginInfo				=
   1000 	{
   1001 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
   1002 		DE_NULL,
   1003 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
   1004 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
   1005 	};
   1006 	const vk::VkCommandBufferAllocateInfo				passCmdBufCreateInfo			=
   1007 	{
   1008 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
   1009 		DE_NULL,
   1010 		*m_cmdPool,								// cmdPool
   1011 		vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY,	// level
   1012 		1u,										// count
   1013 	};
   1014 	const vk::VkCommandBufferInheritanceInfo			passCmdBufInheritInfo			=
   1015 	{
   1016 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
   1017 		DE_NULL,
   1018 		(vk::VkRenderPass)*m_renderPass,						// renderPass
   1019 		0u,														// subpass
   1020 		(vk::VkFramebuffer)*m_framebuffer,						// framebuffer
   1021 		vk::VK_FALSE,											// occlusionQueryEnable
   1022 		(vk::VkQueryControlFlags)0,
   1023 		(vk::VkQueryPipelineStatisticFlags)0,
   1024 	};
   1025 	const vk::VkCommandBufferBeginInfo					passCmdBufBeginInfo				=
   1026 	{
   1027 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
   1028 		DE_NULL,
   1029 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
   1030 		vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,	// flags
   1031 		&passCmdBufInheritInfo,
   1032 	};
   1033 	const vk::VkFenceCreateInfo							fenceCreateInfo				=
   1034 	{
   1035 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
   1036 		DE_NULL,
   1037 		0u,			// flags
   1038 	};
   1039 	const vk::VkClearValue								clearValue					= vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
   1040 	const vk::VkRenderPassBeginInfo						renderPassBeginInfo			=
   1041 	{
   1042 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
   1043 		DE_NULL,
   1044 		*m_renderPass,		// renderPass
   1045 		*m_framebuffer,		// framebuffer
   1046 		renderArea,			// renderArea
   1047 		1u,					// clearValueCount
   1048 		&clearValue,		// pClearValues
   1049 	};
   1050 
   1051 	const vk::VkPipelineLayout							pipelineLayout				(getPipelineLayout());
   1052 	const vk::Unique<vk::VkPipeline>					pipeline					(createPipeline(pipelineLayout));
   1053 	const vk::Unique<vk::VkCommandBuffer>				mainCmd						(vk::allocateCommandBuffer(m_vki, m_device, &mainCmdBufCreateInfo));
   1054 	const vk::Unique<vk::VkCommandBuffer>				passCmd						((m_isPrimaryCmdBuf) ? (vk::Move<vk::VkCommandBuffer>()) : (vk::allocateCommandBuffer(m_vki, m_device, &passCmdBufCreateInfo)));
   1055 	const vk::Unique<vk::VkFence>						fence						(vk::createFence(m_vki, m_device, &fenceCreateInfo));
   1056 	const deUint64										infiniteTimeout				= ~(deUint64)0u;
   1057 	const vk::VkSubpassContents							passContents				= (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
   1058 
   1059 	VK_CHECK(m_vki.beginCommandBuffer(*mainCmd, &mainCmdBufBeginInfo));
   1060 	m_vki.cmdBeginRenderPass(*mainCmd, &renderPassBeginInfo, passContents);
   1061 
   1062 	if (m_isPrimaryCmdBuf)
   1063 	{
   1064 		m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
   1065 		writeDrawCmdBuffer(*mainCmd);
   1066 	}
   1067 	else
   1068 	{
   1069 		VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
   1070 		m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
   1071 		writeDrawCmdBuffer(*passCmd);
   1072 		VK_CHECK(m_vki.endCommandBuffer(*passCmd));
   1073 
   1074 		m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
   1075 	}
   1076 
   1077 	m_vki.cmdEndRenderPass(*mainCmd);
   1078 	VK_CHECK(m_vki.endCommandBuffer(*mainCmd));
   1079 
   1080 	// submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
   1081 	{
   1082 		const vk::VkSubmitInfo	submitInfo	=
   1083 		{
   1084 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1085 			DE_NULL,
   1086 			0u,
   1087 			(const vk::VkSemaphore*)0,
   1088 			(const vk::VkPipelineStageFlags*)DE_NULL,
   1089 			1u,
   1090 			&mainCmd.get(),
   1091 			0u,
   1092 			(const vk::VkSemaphore*)0,
   1093 		};
   1094 		VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *fence));
   1095 	}
   1096 	VK_CHECK(m_vki.waitForFences(m_device, 1, &fence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
   1097 }
   1098 
   1099 enum ShaderInputInterface
   1100 {
   1101 	SHADER_INPUT_SINGLE_DESCRIPTOR = 0,					//!< one descriptor
   1102 	SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS,		//!< multiple descriptors with contiguous binding id's
   1103 	SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS,	//!< multiple descriptors with discontiguous binding id's
   1104 	SHADER_INPUT_DESCRIPTOR_ARRAY,						//!< descriptor array
   1105 
   1106 	SHADER_INPUT_LAST
   1107 };
   1108 
   1109 deUint32 getInterfaceNumResources (ShaderInputInterface shaderInterface)
   1110 {
   1111 	switch (shaderInterface)
   1112 	{
   1113 		case SHADER_INPUT_SINGLE_DESCRIPTOR:					return 1u;
   1114 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:		return 2u;
   1115 		case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:	return 2u;
   1116 		case SHADER_INPUT_DESCRIPTOR_ARRAY:						return 2u;
   1117 
   1118 		default:
   1119 			DE_FATAL("Impossible");
   1120 			return 0u;
   1121 	}
   1122 }
   1123 
   1124 class BufferRenderInstance : public SingleCmdRenderInstance
   1125 {
   1126 public:
   1127 													BufferRenderInstance		(Context&					context,
   1128 																				 bool						isPrimaryCmdBuf,
   1129 																				 vk::VkDescriptorType		descriptorType,
   1130 																				 vk::VkShaderStageFlags		stageFlags,
   1131 																				 ShaderInputInterface		shaderInterface,
   1132 																				 bool						viewOffset,
   1133 																				 bool						dynamicOffset,
   1134 																				 bool						dynamicOffsetNonZero);
   1135 
   1136 	static vk::Move<vk::VkBuffer>					createSourceBuffer			(const vk::DeviceInterface&		vki,
   1137 																				 vk::VkDevice					device,
   1138 																				 vk::Allocator&					allocator,
   1139 																				 vk::VkDescriptorType			descriptorType,
   1140 																				 deUint32						offset,
   1141 																				 deUint32						bufferSize,
   1142 																				 de::MovePtr<vk::Allocation>*	outMemory);
   1143 
   1144 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(const vk::DeviceInterface&	vki,
   1145 																				 vk::VkDevice				device,
   1146 																				 vk::VkDescriptorType		descriptorType,
   1147 																				 ShaderInputInterface		shaderInterface);
   1148 
   1149 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(const vk::DeviceInterface&	vki,
   1150 																				 vk::VkDevice				device,
   1151 																				 vk::VkDescriptorType		descriptorType,
   1152 																				 ShaderInputInterface		shaderInterface,
   1153 																				 vk::VkShaderStageFlags		stageFlags);
   1154 
   1155 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(const vk::DeviceInterface&	vki,
   1156 																				 vk::VkDevice				device,
   1157 																				 vk::VkDescriptorSetLayout	descriptorSetLayout,
   1158 																				 vk::VkDescriptorPool		descriptorPool,
   1159 																				 vk::VkDescriptorType		descriptorType,
   1160 																				 ShaderInputInterface		shaderInterface,
   1161 																				 vk::VkBuffer				sourceBufferA,
   1162 																				 const deUint32				viewOffsetA,
   1163 																				 vk::VkBuffer				sourceBufferB,
   1164 																				 const deUint32				viewOffsetB);
   1165 
   1166 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout		(const vk::DeviceInterface&	vki,
   1167 																				 vk::VkDevice				device,
   1168 																				 vk::VkDescriptorSetLayout	descriptorSetLayout);
   1169 
   1170 	void											logTestPlan					(void) const;
   1171 	vk::VkPipelineLayout							getPipelineLayout			(void) const;
   1172 	void											writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const;
   1173 	tcu::TestStatus									verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const;
   1174 
   1175 	enum
   1176 	{
   1177 		RENDER_SIZE				= 128,
   1178 		BUFFER_DATA_SIZE		= 8 * sizeof(float),
   1179 		BUFFER_SIZE_A			= 2048, //!< a lot more than required
   1180 		BUFFER_SIZE_B			= 2560, //!< a lot more than required
   1181 
   1182 		STATIC_OFFSET_VALUE_A	= 256,
   1183 		DYNAMIC_OFFSET_VALUE_A	= 512,
   1184 		STATIC_OFFSET_VALUE_B	= 1024,
   1185 		DYNAMIC_OFFSET_VALUE_B	= 768,
   1186 	};
   1187 
   1188 	const vk::VkDescriptorType						m_descriptorType;
   1189 	const ShaderInputInterface						m_shaderInterface;
   1190 	const bool										m_setViewOffset;
   1191 	const bool										m_setDynamicOffset;
   1192 	const bool										m_dynamicOffsetNonZero;
   1193 	const vk::VkShaderStageFlags					m_stageFlags;
   1194 
   1195 	const deUint32									m_viewOffsetA;
   1196 	const deUint32									m_viewOffsetB;
   1197 	const deUint32									m_dynamicOffsetA;
   1198 	const deUint32									m_dynamicOffsetB;
   1199 	const deUint32									m_effectiveOffsetA;
   1200 	const deUint32									m_effectiveOffsetB;
   1201 	const deUint32									m_bufferSizeA;
   1202 	const deUint32									m_bufferSizeB;
   1203 
   1204 	de::MovePtr<vk::Allocation>						m_bufferMemoryA;
   1205 	de::MovePtr<vk::Allocation>						m_bufferMemoryB;
   1206 	const vk::Unique<vk::VkBuffer>					m_sourceBufferA;
   1207 	const vk::Unique<vk::VkBuffer>					m_sourceBufferB;
   1208 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
   1209 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
   1210 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
   1211 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
   1212 };
   1213 
   1214 BufferRenderInstance::BufferRenderInstance	(Context&				context,
   1215 											 bool					isPrimaryCmdBuf,
   1216 											 vk::VkDescriptorType	descriptorType,
   1217 											 vk::VkShaderStageFlags	stageFlags,
   1218 											 ShaderInputInterface	shaderInterface,
   1219 											 bool					viewOffset,
   1220 											 bool					dynamicOffset,
   1221 											 bool					dynamicOffsetNonZero)
   1222 	: SingleCmdRenderInstance		(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
   1223 	, m_descriptorType				(descriptorType)
   1224 	, m_shaderInterface				(shaderInterface)
   1225 	, m_setViewOffset				(viewOffset)
   1226 	, m_setDynamicOffset			(dynamicOffset)
   1227 	, m_dynamicOffsetNonZero		(dynamicOffsetNonZero)
   1228 	, m_stageFlags					(stageFlags)
   1229 	, m_viewOffsetA					((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u))
   1230 	, m_viewOffsetB					((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u))
   1231 	, m_dynamicOffsetA				((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u))
   1232 	, m_dynamicOffsetB				((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u))
   1233 	, m_effectiveOffsetA			((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetA + m_dynamicOffsetA) : (m_viewOffsetA))
   1234 	, m_effectiveOffsetB			((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetB + m_dynamicOffsetB) : (m_viewOffsetB))
   1235 	, m_bufferSizeA					(BUFFER_SIZE_A)
   1236 	, m_bufferSizeB					(BUFFER_SIZE_B)
   1237 	, m_bufferMemoryA				(DE_NULL)
   1238 	, m_bufferMemoryB				(DE_NULL)
   1239 	, m_sourceBufferA				(createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetA, m_bufferSizeA, &m_bufferMemoryA))
   1240 	, m_sourceBufferB				((getInterfaceNumResources(m_shaderInterface) == 1u)
   1241 										? vk::Move<vk::VkBuffer>()
   1242 										: createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetB, m_bufferSizeB, &m_bufferMemoryB))
   1243 	, m_descriptorPool				(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
   1244 	, m_descriptorSetLayout			(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
   1245 	, m_descriptorSet				(createDescriptorSet(m_vki, m_device, *m_descriptorSetLayout, *m_descriptorPool, m_descriptorType, m_shaderInterface, *m_sourceBufferA, m_viewOffsetA, *m_sourceBufferB, m_viewOffsetB))
   1246 	, m_pipelineLayout				(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
   1247 {
   1248 	if (m_setDynamicOffset)
   1249 		DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
   1250 	if (m_dynamicOffsetNonZero)
   1251 		DE_ASSERT(m_setDynamicOffset);
   1252 }
   1253 
   1254 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer (const vk::DeviceInterface&		vki,
   1255 																 vk::VkDevice					device,
   1256 																 vk::Allocator&					allocator,
   1257 																 vk::VkDescriptorType			descriptorType,
   1258 																 deUint32						offset,
   1259 																 deUint32						bufferSize,
   1260 																 de::MovePtr<vk::Allocation>*	outMemory)
   1261 {
   1262 	static const float				s_colors[]			=
   1263 	{
   1264 		0.0f, 1.0f, 0.0f, 1.0f,		// green
   1265 		1.0f, 1.0f, 0.0f, 1.0f,		// yellow
   1266 	};
   1267 	DE_STATIC_ASSERT(sizeof(s_colors) == BUFFER_DATA_SIZE);
   1268 	DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
   1269 	DE_ASSERT(offset % sizeof(float) == 0);
   1270 	DE_ASSERT(bufferSize % sizeof(float) == 0);
   1271 
   1272 	const bool						isUniformBuffer		= isUniformDescriptorType(descriptorType);
   1273 	const vk::VkBufferUsageFlags	usageFlags			= (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
   1274 	const float						preGuardValue		= 0.5f;
   1275 	const float						postGuardValue		= 0.75f;
   1276 	const vk::VkBufferCreateInfo	bufferCreateInfo	=
   1277 	{
   1278 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
   1279 		DE_NULL,
   1280 		0u,								// flags
   1281 		bufferSize,						// size
   1282 		usageFlags,						// usage
   1283 		vk::VK_SHARING_MODE_EXCLUSIVE,	// sharingMode
   1284 		0u,								// queueFamilyCount
   1285 		DE_NULL,						// pQueueFamilyIndices
   1286 	};
   1287 	vk::Move<vk::VkBuffer>			buffer				(vk::createBuffer(vki, device, &bufferCreateInfo));
   1288 	de::MovePtr<vk::Allocation>		bufferMemory		= allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
   1289 	void* const						mapPtr				= bufferMemory->getHostPtr();
   1290 
   1291 	// guard with interesting values
   1292 	for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
   1293 		deMemcpy((deUint8*)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
   1294 
   1295 	deMemcpy((deUint8*)mapPtr + offset, s_colors, sizeof(s_colors));
   1296 	for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors); postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
   1297 		deMemcpy((deUint8*)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
   1298 	deMemset((deUint8*)mapPtr + offset + sizeof(s_colors), 0x5A, (size_t)bufferSize - (size_t)offset - sizeof(s_colors)); // fill with interesting pattern that produces valid floats
   1299 
   1300 	flushMappedMemoryRange(vki, device, bufferMemory->getMemory(), bufferMemory->getOffset(), bufferSize);
   1301 
   1302 	// Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
   1303 
   1304 	*outMemory = bufferMemory;
   1305 	return buffer;
   1306 }
   1307 
   1308 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
   1309 																		   vk::VkDevice					device,
   1310 																		   vk::VkDescriptorType			descriptorType,
   1311 																		   ShaderInputInterface			shaderInterface)
   1312 {
   1313 	return vk::DescriptorPoolBuilder()
   1314 		.addType(descriptorType, getInterfaceNumResources(shaderInterface))
   1315 		.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   1316 }
   1317 
   1318 vk::Move<vk::VkDescriptorSetLayout> BufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&	vki,
   1319 																					 vk::VkDevice				device,
   1320 																					 vk::VkDescriptorType		descriptorType,
   1321 																					 ShaderInputInterface		shaderInterface,
   1322 																					 vk::VkShaderStageFlags		stageFlags)
   1323 {
   1324 	vk::DescriptorSetLayoutBuilder builder;
   1325 
   1326 	switch (shaderInterface)
   1327 	{
   1328 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   1329 			builder.addSingleBinding(descriptorType, stageFlags);
   1330 			break;
   1331 
   1332 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   1333 			builder.addSingleBinding(descriptorType, stageFlags);
   1334 			builder.addSingleBinding(descriptorType, stageFlags);
   1335 			break;
   1336 
   1337 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   1338 			builder.addArrayBinding(descriptorType, 2u, stageFlags);
   1339 			break;
   1340 
   1341 		default:
   1342 			DE_FATAL("Impossible");
   1343 	}
   1344 
   1345 	return builder.build(vki, device);
   1346 }
   1347 
   1348 vk::Move<vk::VkDescriptorSet> BufferRenderInstance::createDescriptorSet (const vk::DeviceInterface&	vki,
   1349 																		 vk::VkDevice				device,
   1350 																		 vk::VkDescriptorSetLayout	descriptorSetLayout,
   1351 																		 vk::VkDescriptorPool		descriptorPool,
   1352 																		 vk::VkDescriptorType		descriptorType,
   1353 																		 ShaderInputInterface		shaderInterface,
   1354 																		 vk::VkBuffer				bufferA,
   1355 																		 deUint32					offsetA,
   1356 																		 vk::VkBuffer				bufferB,
   1357 																		 deUint32					offsetB)
   1358 {
   1359 	const vk::VkDescriptorBufferInfo		bufferInfos[2]	=
   1360 	{
   1361 		vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
   1362 		vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
   1363 	};
   1364 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
   1365 	{
   1366 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   1367 		DE_NULL,
   1368 		descriptorPool,
   1369 		1u,
   1370 		&descriptorSetLayout
   1371 	};
   1372 
   1373 	vk::Move<vk::VkDescriptorSet>	descriptorSet	= allocateDescriptorSet(vki, device, &allocInfo);
   1374 	vk::DescriptorSetUpdateBuilder	builder;
   1375 
   1376 	switch (shaderInterface)
   1377 	{
   1378 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   1379 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
   1380 			break;
   1381 
   1382 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   1383 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
   1384 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &bufferInfos[1]);
   1385 			break;
   1386 
   1387 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   1388 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, bufferInfos);
   1389 			break;
   1390 
   1391 		default:
   1392 			DE_FATAL("Impossible");
   1393 	}
   1394 
   1395 	builder.update(vki, device);
   1396 	return descriptorSet;
   1397 }
   1398 
   1399 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
   1400 																		   vk::VkDevice					device,
   1401 																		   vk::VkDescriptorSetLayout	descriptorSetLayout)
   1402 {
   1403 	const vk::VkPipelineLayoutCreateInfo createInfo =
   1404 	{
   1405 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
   1406 		DE_NULL,
   1407 		(vk::VkPipelineLayoutCreateFlags)0,
   1408 		1,						// descriptorSetCount
   1409 		&descriptorSetLayout,	// pSetLayouts
   1410 		0u,						// pushConstantRangeCount
   1411 		DE_NULL,				// pPushConstantRanges
   1412 	};
   1413 
   1414 	return vk::createPipelineLayout(vki, device, &createInfo);
   1415 }
   1416 
   1417 void BufferRenderInstance::logTestPlan (void) const
   1418 {
   1419 	std::ostringstream msg;
   1420 
   1421 	msg << "Rendering 2x2 yellow-green grid.\n"
   1422 		<< "Single descriptor set. Descriptor set contains "
   1423 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   1424 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   1425 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   1426 			    (const char*)DE_NULL)
   1427 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
   1428 		<< "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
   1429 
   1430 	if (isDynamicDescriptorType(m_descriptorType))
   1431 	{
   1432 		if (m_setDynamicOffset)
   1433 		{
   1434 			msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
   1435 				<< "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
   1436 		}
   1437 		else
   1438 		{
   1439 			msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
   1440 		}
   1441 	}
   1442 
   1443 	if (m_stageFlags == 0u)
   1444 	{
   1445 		msg << "Descriptors are not accessed in any shader stage.\n";
   1446 	}
   1447 	else
   1448 	{
   1449 		msg << "Descriptors are accessed in {"
   1450 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
   1451 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
   1452 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
   1453 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
   1454 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
   1455 			<< " } stages.\n";
   1456 	}
   1457 
   1458 	m_context.getTestContext().getLog()
   1459 		<< tcu::TestLog::Message
   1460 		<< msg.str()
   1461 		<< tcu::TestLog::EndMessage;
   1462 }
   1463 
   1464 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout (void) const
   1465 {
   1466 	return *m_pipelineLayout;
   1467 }
   1468 
   1469 void BufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
   1470 {
   1471 	// \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
   1472 	const deUint32						dynamicOffsets[]	=
   1473 	{
   1474 		m_dynamicOffsetA,
   1475 		m_dynamicOffsetB,
   1476 	};
   1477 	const deUint32						numOffsets			= (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
   1478 	const deUint32* const				dynamicOffsetPtr	= (!m_setDynamicOffset) ? (DE_NULL) : (dynamicOffsets);
   1479 
   1480 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), numOffsets, dynamicOffsetPtr);
   1481 	m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
   1482 }
   1483 
   1484 tcu::TestStatus BufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
   1485 {
   1486 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
   1487 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
   1488 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
   1489 
   1490 	drawQuadrantReferenceResult(reference.getAccess(), yellow, green, green, yellow);
   1491 
   1492 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
   1493 		return tcu::TestStatus::fail("Image verification failed");
   1494 	else
   1495 		return tcu::TestStatus::pass("Pass");
   1496 }
   1497 
   1498 class ComputeInstanceResultBuffer
   1499 {
   1500 public:
   1501 	enum
   1502 	{
   1503 		DATA_SIZE = sizeof(tcu::Vec4[4])
   1504 	};
   1505 
   1506 											ComputeInstanceResultBuffer	(const vk::DeviceInterface&		vki,
   1507 																		 vk::VkDevice					device,
   1508 																		 vk::Allocator&					allocator);
   1509 
   1510 	void									readResultContentsTo		(tcu::Vec4 (*results)[4]) const;
   1511 
   1512 	inline vk::VkBuffer						getBuffer					(void) const { return *m_buffer;			}
   1513 	inline const vk::VkBufferMemoryBarrier*	getResultReadBarrier		(void) const { return &m_bufferBarrier;		}
   1514 
   1515 private:
   1516 	static vk::Move<vk::VkBuffer>			createResultBuffer			(const vk::DeviceInterface&		vki,
   1517 																		 vk::VkDevice					device,
   1518 																		 vk::Allocator&					allocator,
   1519 																		 de::MovePtr<vk::Allocation>*	outAllocation);
   1520 
   1521 	static vk::VkBufferMemoryBarrier		createResultBufferBarrier	(vk::VkBuffer buffer);
   1522 
   1523 	const vk::DeviceInterface&				m_vki;
   1524 	const vk::VkDevice						m_device;
   1525 
   1526 	de::MovePtr<vk::Allocation>				m_bufferMem;
   1527 	const vk::Unique<vk::VkBuffer>			m_buffer;
   1528 	const vk::VkBufferMemoryBarrier			m_bufferBarrier;
   1529 };
   1530 
   1531 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const vk::DeviceInterface&	vki,
   1532 														  vk::VkDevice					device,
   1533 														  vk::Allocator&				allocator)
   1534 	: m_vki				(vki)
   1535 	, m_device			(device)
   1536 	, m_bufferMem		(DE_NULL)
   1537 	, m_buffer			(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
   1538 	, m_bufferBarrier	(createResultBufferBarrier(*m_buffer))
   1539 {
   1540 }
   1541 
   1542 void ComputeInstanceResultBuffer::readResultContentsTo (tcu::Vec4 (*results)[4]) const
   1543 {
   1544 	invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*results));
   1545 	deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
   1546 }
   1547 
   1548 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer (const vk::DeviceInterface&		vki,
   1549 																		vk::VkDevice					device,
   1550 																		vk::Allocator&					allocator,
   1551 																		de::MovePtr<vk::Allocation>*	outAllocation)
   1552 {
   1553 	const vk::VkBufferCreateInfo	createInfo	=
   1554 	{
   1555 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
   1556 		DE_NULL,
   1557 		0u,											// flags
   1558 		(vk::VkDeviceSize)DATA_SIZE,				// size
   1559 		vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// usage
   1560 		vk::VK_SHARING_MODE_EXCLUSIVE,				// sharingMode
   1561 		0u,											// queueFamilyCount
   1562 		DE_NULL,									// pQueueFamilyIndices
   1563 	};
   1564 	vk::Move<vk::VkBuffer>			buffer		(vk::createBuffer(vki, device, &createInfo));
   1565 	de::MovePtr<vk::Allocation>		allocation	(allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
   1566 	const float						clearValue	= -1.0f;
   1567 	void*							mapPtr		= allocation->getHostPtr();
   1568 
   1569 	for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
   1570 		deMemcpy(((deUint8*)mapPtr) + offset, &clearValue, sizeof(float));
   1571 
   1572 	flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), (vk::VkDeviceSize)DATA_SIZE);
   1573 
   1574 	*outAllocation = allocation;
   1575 	return buffer;
   1576 }
   1577 
   1578 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier (vk::VkBuffer buffer)
   1579 {
   1580 	const vk::VkBufferMemoryBarrier bufferBarrier =
   1581 	{
   1582 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   1583 		DE_NULL,
   1584 		vk::VK_ACCESS_SHADER_WRITE_BIT,				// outputMask
   1585 		vk::VK_ACCESS_HOST_READ_BIT,				// inputMask
   1586 		vk::VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
   1587 		vk::VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
   1588 		buffer,										// buffer
   1589 		(vk::VkDeviceSize)0u,						// offset
   1590 		DATA_SIZE,									// size
   1591 	};
   1592 	return bufferBarrier;
   1593 }
   1594 
   1595 class ComputePipeline
   1596 {
   1597 public:
   1598 											ComputePipeline			(const vk::DeviceInterface&			vki,
   1599 																	 vk::VkDevice						device,
   1600 																	 const vk::BinaryCollection&		programCollection,
   1601 																	 deUint32							numDescriptorSets,
   1602 																	 const vk::VkDescriptorSetLayout*	descriptorSetLayouts);
   1603 
   1604 	inline vk::VkPipeline					getPipeline				(void) const { return *m_pipeline;			};
   1605 	inline vk::VkPipelineLayout				getPipelineLayout		(void) const { return *m_pipelineLayout;	};
   1606 
   1607 private:
   1608 	static vk::Move<vk::VkPipelineLayout>	createPipelineLayout	(const vk::DeviceInterface&			vki,
   1609 																	 vk::VkDevice						device,
   1610 																	 deUint32							numDescriptorSets,
   1611 																	 const vk::VkDescriptorSetLayout*	descriptorSetLayouts);
   1612 
   1613 	static vk::Move<vk::VkPipeline>			createPipeline			(const vk::DeviceInterface&			vki,
   1614 																	 vk::VkDevice						device,
   1615 																	 const vk::BinaryCollection&		programCollection,
   1616 																	 vk::VkPipelineLayout				layout);
   1617 
   1618 	const vk::Unique<vk::VkPipelineLayout>	m_pipelineLayout;
   1619 	const vk::Unique<vk::VkPipeline>		m_pipeline;
   1620 };
   1621 
   1622 ComputePipeline::ComputePipeline (const vk::DeviceInterface&		vki,
   1623 								  vk::VkDevice						device,
   1624 								  const vk::BinaryCollection&		programCollection,
   1625 								  deUint32							numDescriptorSets,
   1626 								  const vk::VkDescriptorSetLayout*	descriptorSetLayouts)
   1627 	: m_pipelineLayout	(createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
   1628 	, m_pipeline		(createPipeline(vki, device, programCollection, *m_pipelineLayout))
   1629 {
   1630 }
   1631 
   1632 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout (const vk::DeviceInterface&		vki,
   1633 																	  vk::VkDevice						device,
   1634 																	  deUint32							numDescriptorSets,
   1635 																	  const vk::VkDescriptorSetLayout*	descriptorSetLayouts)
   1636 {
   1637 	const vk::VkPipelineLayoutCreateInfo createInfo =
   1638 	{
   1639 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
   1640 		DE_NULL,
   1641 		(vk::VkPipelineLayoutCreateFlags)0,
   1642 		numDescriptorSets,		// descriptorSetCount
   1643 		descriptorSetLayouts,	// pSetLayouts
   1644 		0u,						// pushConstantRangeCount
   1645 		DE_NULL,				// pPushConstantRanges
   1646 	};
   1647 	return vk::createPipelineLayout(vki, device, &createInfo);
   1648 }
   1649 
   1650 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline (const vk::DeviceInterface&	vki,
   1651 														  vk::VkDevice					device,
   1652 														  const vk::BinaryCollection&	programCollection,
   1653 														  vk::VkPipelineLayout			layout)
   1654 {
   1655 	const vk::Unique<vk::VkShaderModule>		computeModule		(vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
   1656 	const vk::VkPipelineShaderStageCreateInfo	cs					=
   1657 	{
   1658 		vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
   1659 		DE_NULL,
   1660 		(vk::VkPipelineShaderStageCreateFlags)0,
   1661 		vk::VK_SHADER_STAGE_COMPUTE_BIT,	// stage
   1662 		*computeModule,						// shader
   1663 		"main",
   1664 		DE_NULL,							// pSpecializationInfo
   1665 	};
   1666 	const vk::VkComputePipelineCreateInfo		createInfo			=
   1667 	{
   1668 		vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
   1669 		DE_NULL,
   1670 		0u,								// flags
   1671 		cs,								// cs
   1672 		layout,							// layout
   1673 		(vk::VkPipeline)0,				// basePipelineHandle
   1674 		0u,								// basePipelineIndex
   1675 	};
   1676 	return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
   1677 }
   1678 
   1679 class ComputeCommand
   1680 {
   1681 public:
   1682 											ComputeCommand	(const vk::DeviceInterface&			vki,
   1683 															 vk::VkDevice						device,
   1684 															 vk::VkPipeline						pipeline,
   1685 															 vk::VkPipelineLayout				pipelineLayout,
   1686 															 const tcu::UVec3&					numWorkGroups,
   1687 															 int								numDescriptorSets,
   1688 															 const vk::VkDescriptorSet*			descriptorSets,
   1689 															 int								numDynamicOffsets,
   1690 															 const deUint32*					dynamicOffsets,
   1691 															 int								numPreBarriers,
   1692 															 const vk::VkBufferMemoryBarrier*	preBarriers,
   1693 															 int								numPostBarriers,
   1694 															 const vk::VkBufferMemoryBarrier*	postBarriers);
   1695 
   1696 	void									submitAndWait	(deUint32 queueFamilyIndex, vk::VkQueue queue) const;
   1697 
   1698 private:
   1699 	const vk::DeviceInterface&				m_vki;
   1700 	const vk::VkDevice						m_device;
   1701 	const vk::VkPipeline					m_pipeline;
   1702 	const vk::VkPipelineLayout				m_pipelineLayout;
   1703 	const tcu::UVec3						m_numWorkGroups;
   1704 	const int								m_numDescriptorSets;
   1705 	const vk::VkDescriptorSet* const		m_descriptorSets;
   1706 	const int								m_numDynamicOffsets;
   1707 	const deUint32* const					m_dynamicOffsets;
   1708 	const int								m_numPreBarriers;
   1709 	const vk::VkBufferMemoryBarrier* const	m_preBarriers;
   1710 	const int								m_numPostBarriers;
   1711 	const vk::VkBufferMemoryBarrier* const	m_postBarriers;
   1712 };
   1713 
   1714 ComputeCommand::ComputeCommand (const vk::DeviceInterface&			vki,
   1715 								vk::VkDevice						device,
   1716 								vk::VkPipeline						pipeline,
   1717 								vk::VkPipelineLayout				pipelineLayout,
   1718 								const tcu::UVec3&					numWorkGroups,
   1719 								int									numDescriptorSets,
   1720 								const vk::VkDescriptorSet*			descriptorSets,
   1721 								int									numDynamicOffsets,
   1722 								const deUint32*						dynamicOffsets,
   1723 								int									numPreBarriers,
   1724 								const vk::VkBufferMemoryBarrier*	preBarriers,
   1725 								int									numPostBarriers,
   1726 								const vk::VkBufferMemoryBarrier*	postBarriers)
   1727 	: m_vki					(vki)
   1728 	, m_device				(device)
   1729 	, m_pipeline			(pipeline)
   1730 	, m_pipelineLayout		(pipelineLayout)
   1731 	, m_numWorkGroups		(numWorkGroups)
   1732 	, m_numDescriptorSets	(numDescriptorSets)
   1733 	, m_descriptorSets		(descriptorSets)
   1734 	, m_numDynamicOffsets	(numDynamicOffsets)
   1735 	, m_dynamicOffsets		(dynamicOffsets)
   1736 	, m_numPreBarriers		(numPreBarriers)
   1737 	, m_preBarriers			(preBarriers)
   1738 	, m_numPostBarriers		(numPostBarriers)
   1739 	, m_postBarriers		(postBarriers)
   1740 {
   1741 }
   1742 
   1743 void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const
   1744 {
   1745 	const vk::VkCommandPoolCreateInfo				cmdPoolCreateInfo	=
   1746 	{
   1747 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
   1748 		DE_NULL,
   1749 		vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// flags
   1750 		queueFamilyIndex,									// queueFamilyIndex
   1751 	};
   1752 	const vk::Unique<vk::VkCommandPool>				cmdPool				(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
   1753 
   1754 	const vk::VkFenceCreateInfo						fenceCreateInfo		=
   1755 	{
   1756 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
   1757 		DE_NULL,
   1758 		0u,			// flags
   1759 	};
   1760 
   1761 	const vk::VkCommandBufferAllocateInfo			cmdBufCreateInfo	=
   1762 	{
   1763 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
   1764 		DE_NULL,
   1765 		*cmdPool,											// cmdPool
   1766 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// level
   1767 		1u,													// count
   1768 	};
   1769 	const vk::VkCommandBufferBeginInfo				cmdBufBeginInfo		=
   1770 	{
   1771 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
   1772 		DE_NULL,
   1773 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
   1774 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
   1775 	};
   1776 
   1777 	const vk::Unique<vk::VkFence>					cmdCompleteFence	(vk::createFence(m_vki, m_device, &fenceCreateInfo));
   1778 	const vk::Unique<vk::VkCommandBuffer>			cmd					(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
   1779 	const deUint64									infiniteTimeout		= ~(deUint64)0u;
   1780 
   1781 	VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
   1782 
   1783 	m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
   1784 	m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets);
   1785 
   1786 	if (m_numPreBarriers)
   1787 		m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0,
   1788 								 0, (const vk::VkMemoryBarrier*)DE_NULL,
   1789 								 m_numPreBarriers, m_preBarriers,
   1790 								 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
   1791 
   1792 	m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
   1793 	m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
   1794 							 0, (const vk::VkMemoryBarrier*)DE_NULL,
   1795 							 m_numPostBarriers, m_postBarriers,
   1796 							 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
   1797 	VK_CHECK(m_vki.endCommandBuffer(*cmd));
   1798 
   1799 	// run
   1800 	{
   1801 		const vk::VkSubmitInfo	submitInfo	=
   1802 		{
   1803 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1804 			DE_NULL,
   1805 			0u,
   1806 			(const vk::VkSemaphore*)0,
   1807 			(const vk::VkPipelineStageFlags*)DE_NULL,
   1808 			1u,
   1809 			&cmd.get(),
   1810 			0u,
   1811 			(const vk::VkSemaphore*)0,
   1812 		};
   1813 		VK_CHECK(m_vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
   1814 	}
   1815 	VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
   1816 }
   1817 
   1818 class BufferComputeInstance : public vkt::TestInstance
   1819 {
   1820 public:
   1821 											BufferComputeInstance		(Context&				context,
   1822 																		 vk::VkDescriptorType	descriptorType,
   1823 																		 ShaderInputInterface	shaderInterface,
   1824 																		 bool					viewOffset,
   1825 																		 bool					dynamicOffset,
   1826 																		 bool					dynamicOffsetNonZero);
   1827 
   1828 private:
   1829 	vk::Move<vk::VkBuffer>					createColorDataBuffer		(deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation);
   1830 	vk::Move<vk::VkBufferView>				createBufferView			(vk::VkBuffer buffer, deUint32 offset) const;
   1831 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(void) const;
   1832 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(void) const;
   1833 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const;
   1834 
   1835 	tcu::TestStatus							iterate						(void);
   1836 	void									logTestPlan					(void) const;
   1837 	tcu::TestStatus							testResourceAccess			(void);
   1838 
   1839 	enum
   1840 	{
   1841 		STATIC_OFFSET_VALUE_A	= 256,
   1842 		DYNAMIC_OFFSET_VALUE_A	= 512,
   1843 		STATIC_OFFSET_VALUE_B	= 1024,
   1844 		DYNAMIC_OFFSET_VALUE_B	= 768,
   1845 	};
   1846 
   1847 	const vk::VkDescriptorType				m_descriptorType;
   1848 	const ShaderInputInterface				m_shaderInterface;
   1849 	const bool								m_setViewOffset;
   1850 	const bool								m_setDynamicOffset;
   1851 	const bool								m_dynamicOffsetNonZero;
   1852 
   1853 	const vk::DeviceInterface&				m_vki;
   1854 	const vk::VkDevice						m_device;
   1855 	const vk::VkQueue						m_queue;
   1856 	const deUint32							m_queueFamilyIndex;
   1857 	vk::Allocator&							m_allocator;
   1858 
   1859 	const ComputeInstanceResultBuffer		m_result;
   1860 };
   1861 
   1862 BufferComputeInstance::BufferComputeInstance (Context&					context,
   1863 											  vk::VkDescriptorType		descriptorType,
   1864 											  ShaderInputInterface		shaderInterface,
   1865 											  bool						viewOffset,
   1866 											  bool						dynamicOffset,
   1867 											  bool						dynamicOffsetNonZero)
   1868 	: vkt::TestInstance			(context)
   1869 	, m_descriptorType			(descriptorType)
   1870 	, m_shaderInterface			(shaderInterface)
   1871 	, m_setViewOffset			(viewOffset)
   1872 	, m_setDynamicOffset		(dynamicOffset)
   1873 	, m_dynamicOffsetNonZero	(dynamicOffsetNonZero)
   1874 	, m_vki						(context.getDeviceInterface())
   1875 	, m_device					(context.getDevice())
   1876 	, m_queue					(context.getUniversalQueue())
   1877 	, m_queueFamilyIndex		(context.getUniversalQueueFamilyIndex())
   1878 	, m_allocator				(context.getDefaultAllocator())
   1879 	, m_result					(m_vki, m_device, m_allocator)
   1880 {
   1881 	if (m_dynamicOffsetNonZero)
   1882 		DE_ASSERT(m_setDynamicOffset);
   1883 }
   1884 
   1885 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation)
   1886 {
   1887 	DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
   1888 
   1889 	const bool						isUniformBuffer		= isUniformDescriptorType(m_descriptorType);
   1890 	const vk::VkBufferUsageFlags	usageFlags			= (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
   1891 	const vk::VkBufferCreateInfo	createInfo =
   1892 	{
   1893 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
   1894 		DE_NULL,
   1895 		0u,								// flags
   1896 		(vk::VkDeviceSize)bufferSize,	// size
   1897 		usageFlags,						// usage
   1898 		vk::VK_SHARING_MODE_EXCLUSIVE,	// sharingMode
   1899 		0u,								// queueFamilyCount
   1900 		DE_NULL,						// pQueueFamilyIndices
   1901 	};
   1902 	vk::Move<vk::VkBuffer>			buffer				(vk::createBuffer(m_vki, m_device, &createInfo));
   1903 	de::MovePtr<vk::Allocation>		allocation			(allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
   1904 	void*							mapPtr				= allocation->getHostPtr();
   1905 
   1906 	if (offset)
   1907 		deMemset(mapPtr, 0x5A, (size_t)offset);
   1908 	deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
   1909 	deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
   1910 	deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
   1911 
   1912 	flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize);
   1913 
   1914 	*outAllocation = allocation;
   1915 	return buffer;
   1916 }
   1917 
   1918 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout (void) const
   1919 {
   1920 	vk::DescriptorSetLayoutBuilder builder;
   1921 
   1922 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   1923 
   1924 	switch (m_shaderInterface)
   1925 	{
   1926 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   1927 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   1928 			break;
   1929 
   1930 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   1931 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   1932 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   1933 			break;
   1934 
   1935 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   1936 			builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   1937 			break;
   1938 
   1939 		default:
   1940 			DE_FATAL("Impossible");
   1941 	};
   1942 
   1943 	return builder.build(m_vki, m_device);
   1944 }
   1945 
   1946 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool (void) const
   1947 {
   1948 	return vk::DescriptorPoolBuilder()
   1949 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
   1950 		.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
   1951 		.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   1952 }
   1953 
   1954 vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const
   1955 {
   1956 	const vk::VkDescriptorBufferInfo		resultInfo		= vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
   1957 	const vk::VkDescriptorBufferInfo		bufferInfos[2]	=
   1958 	{
   1959 		vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
   1960 		vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
   1961 	};
   1962 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
   1963 	{
   1964 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   1965 		DE_NULL,
   1966 		pool,
   1967 		1u,
   1968 		&layout
   1969 	};
   1970 
   1971 	vk::Move<vk::VkDescriptorSet>	descriptorSet	= allocateDescriptorSet(m_vki, m_device, &allocInfo);
   1972 	vk::DescriptorSetUpdateBuilder	builder;
   1973 
   1974 	// result
   1975 	builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
   1976 
   1977 	// buffers
   1978 	switch (m_shaderInterface)
   1979 	{
   1980 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   1981 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
   1982 			break;
   1983 
   1984 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   1985 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
   1986 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &bufferInfos[1]);
   1987 			break;
   1988 
   1989 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   1990 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, bufferInfos);
   1991 			break;
   1992 
   1993 		default:
   1994 			DE_FATAL("Impossible");
   1995 	}
   1996 
   1997 	builder.update(m_vki, m_device);
   1998 	return descriptorSet;
   1999 }
   2000 
   2001 tcu::TestStatus BufferComputeInstance::iterate (void)
   2002 {
   2003 	logTestPlan();
   2004 	return testResourceAccess();
   2005 }
   2006 
   2007 void BufferComputeInstance::logTestPlan (void) const
   2008 {
   2009 	std::ostringstream msg;
   2010 
   2011 	msg << "Accessing resource in a compute program.\n"
   2012 		<< "Single descriptor set. Descriptor set contains "
   2013 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   2014 				(m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   2015 				(m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   2016 				(const char*)DE_NULL)
   2017 		<< " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
   2018 		<< " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
   2019 		<< "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
   2020 
   2021 	if (isDynamicDescriptorType(m_descriptorType))
   2022 	{
   2023 		if (m_setDynamicOffset)
   2024 		{
   2025 			msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
   2026 				<< "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
   2027 		}
   2028 		else
   2029 		{
   2030 			msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
   2031 		}
   2032 	}
   2033 
   2034 	msg << "Destination buffer is pre-initialized to -1.\n";
   2035 
   2036 	m_context.getTestContext().getLog()
   2037 		<< tcu::TestLog::Message
   2038 		<< msg.str()
   2039 		<< tcu::TestLog::EndMessage;
   2040 }
   2041 
   2042 tcu::TestStatus BufferComputeInstance::testResourceAccess (void)
   2043 {
   2044 	enum
   2045 	{
   2046 		ADDRESSABLE_SIZE = 256, // allocate a lot more than required
   2047 	};
   2048 
   2049 	const bool										isDynamicCase		= isDynamicDescriptorType(m_descriptorType);
   2050 	const bool										isUniformBuffer		= isUniformDescriptorType(m_descriptorType);
   2051 	const deUint32									bindTimeOffsets[]	=
   2052 	{
   2053 		(m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u),
   2054 		(m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u),
   2055 	};
   2056 
   2057 	const tcu::Vec4									colorA1				= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
   2058 	const tcu::Vec4									colorA2				= tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
   2059 	const tcu::Vec4									colorB1				= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
   2060 	const tcu::Vec4									colorB2				= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
   2061 
   2062 	const deUint32									dataOffsetA			= ((isDynamicCase) ? (bindTimeOffsets[0]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u));
   2063 	const deUint32									dataOffsetB			= ((isDynamicCase) ? (bindTimeOffsets[1]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u));
   2064 	const deUint32									viewOffsetA			= (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
   2065 	const deUint32									viewOffsetB			= (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
   2066 	const deUint32									bufferSizeA			= dataOffsetA + ADDRESSABLE_SIZE;
   2067 	const deUint32									bufferSizeB			= dataOffsetB + ADDRESSABLE_SIZE;
   2068 
   2069 	de::MovePtr<vk::Allocation>						bufferMemA;
   2070 	const vk::Unique<vk::VkBuffer>					bufferA				(createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA));
   2071 
   2072 	de::MovePtr<vk::Allocation>						bufferMemB;
   2073 	const vk::Unique<vk::VkBuffer>					bufferB				((getInterfaceNumResources(m_shaderInterface) == 1u)
   2074 																			? (vk::Move<vk::VkBuffer>())
   2075 																			: (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB)));
   2076 
   2077 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
   2078 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
   2079 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer()));
   2080 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
   2081 
   2082 	const vk::VkAccessFlags							inputBit			= (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
   2083 	const vk::VkBufferMemoryBarrier					bufferBarriers[]	=
   2084 	{
   2085 		{
   2086 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   2087 			DE_NULL,
   2088 			vk::VK_ACCESS_HOST_WRITE_BIT,				// outputMask
   2089 			inputBit,									// inputMask
   2090 			vk::VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
   2091 			vk::VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
   2092 			*bufferA,									// buffer
   2093 			(vk::VkDeviceSize)0u,						// offset
   2094 			(vk::VkDeviceSize)bufferSizeA,				// size
   2095 		},
   2096 		{
   2097 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   2098 			DE_NULL,
   2099 			vk::VK_ACCESS_HOST_WRITE_BIT,				// outputMask
   2100 			inputBit,									// inputMask
   2101 			vk::VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
   2102 			vk::VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
   2103 			*bufferB,									// buffer
   2104 			(vk::VkDeviceSize)0u,						// offset
   2105 			(vk::VkDeviceSize)bufferSizeB,				// size
   2106 		}
   2107 	};
   2108 
   2109 	const deUint32									numSrcBuffers		= getInterfaceNumResources(m_shaderInterface);
   2110 
   2111 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
   2112 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
   2113 	const deUint32* const							dynamicOffsets		= (m_setDynamicOffset) ? (bindTimeOffsets) : (DE_NULL);
   2114 	const deUint32									numDynamicOffsets	= (m_setDynamicOffset) ? (numSrcBuffers) : (0);
   2115 	const vk::VkBufferMemoryBarrier* const			preBarriers			= bufferBarriers;
   2116 	const int										numPreBarriers		= numSrcBuffers;
   2117 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
   2118 	const int										numPostBarriers		= 1;
   2119 
   2120 	const ComputeCommand							compute				(m_vki,
   2121 																		 m_device,
   2122 																		 pipeline.getPipeline(),
   2123 																		 pipeline.getPipelineLayout(),
   2124 																		 tcu::UVec3(4, 1, 1),
   2125 																		 numDescriptorSets,	descriptorSets,
   2126 																		 numDynamicOffsets,	dynamicOffsets,
   2127 																		 numPreBarriers,	preBarriers,
   2128 																		 numPostBarriers,	postBarriers);
   2129 
   2130 	const tcu::Vec4									refQuadrantValue14	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? (colorA2) :
   2131 																		  (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? (colorB2) :
   2132 																		  (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? (colorB2) :
   2133 																																					(tcu::Vec4(-2.0f));
   2134 	const tcu::Vec4									refQuadrantValue23	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? (colorA1) :
   2135 																		  (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? (colorA1) :
   2136 																		  (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? (colorA1) :
   2137 																																					(tcu::Vec4(-2.0f));
   2138 	const tcu::Vec4									references[4]		=
   2139 	{
   2140 		refQuadrantValue14,
   2141 		refQuadrantValue23,
   2142 		refQuadrantValue23,
   2143 		refQuadrantValue14,
   2144 	};
   2145 	tcu::Vec4										results[4];
   2146 
   2147 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
   2148 	m_result.readResultContentsTo(&results);
   2149 
   2150 	// verify
   2151 	if (results[0] == references[0] &&
   2152 		results[1] == references[1] &&
   2153 		results[2] == references[2] &&
   2154 		results[3] == references[3])
   2155 	{
   2156 		return tcu::TestStatus::pass("Pass");
   2157 	}
   2158 	else if (results[0] == tcu::Vec4(-1.0f) &&
   2159 			 results[1] == tcu::Vec4(-1.0f) &&
   2160 			 results[2] == tcu::Vec4(-1.0f) &&
   2161 			 results[3] == tcu::Vec4(-1.0f))
   2162 	{
   2163 		m_context.getTestContext().getLog()
   2164 			<< tcu::TestLog::Message
   2165 			<< "Result buffer was not written to."
   2166 			<< tcu::TestLog::EndMessage;
   2167 		return tcu::TestStatus::fail("Result buffer was not written to");
   2168 	}
   2169 	else
   2170 	{
   2171 		m_context.getTestContext().getLog()
   2172 			<< tcu::TestLog::Message
   2173 			<< "Error expected ["
   2174 				<< references[0] << ", "
   2175 				<< references[1] << ", "
   2176 				<< references[2] << ", "
   2177 				<< references[3] << "], got ["
   2178 				<< results[0] << ", "
   2179 				<< results[1] << ", "
   2180 				<< results[2] << ", "
   2181 				<< results[3] << "]"
   2182 			<< tcu::TestLog::EndMessage;
   2183 		return tcu::TestStatus::fail("Invalid result values");
   2184 	}
   2185 }
   2186 
   2187 class QuadrantRendederCase : public vkt::TestCase
   2188 {
   2189 public:
   2190 									QuadrantRendederCase		(tcu::TestContext&		testCtx,
   2191 																 const char*			name,
   2192 																 const char*			description,
   2193 																 glu::GLSLVersion		glslVersion,
   2194 																 vk::VkShaderStageFlags	exitingStages,
   2195 																 vk::VkShaderStageFlags	activeStages);
   2196 private:
   2197 	virtual std::string				genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const = 0;
   2198 	virtual std::string				genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
   2199 	virtual std::string				genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const = 0;
   2200 	virtual std::string				genNoAccessSource			(void) const = 0;
   2201 
   2202 	std::string						genVertexSource				(void) const;
   2203 	std::string						genTessCtrlSource			(void) const;
   2204 	std::string						genTessEvalSource			(void) const;
   2205 	std::string						genGeometrySource			(void) const;
   2206 	std::string						genFragmentSource			(void) const;
   2207 	std::string						genComputeSource			(void) const;
   2208 
   2209 	void							initPrograms				(vk::SourceCollections& programCollection) const;
   2210 
   2211 protected:
   2212 	const glu::GLSLVersion			m_glslVersion;
   2213 	const vk::VkShaderStageFlags	m_exitingStages;
   2214 	const vk::VkShaderStageFlags	m_activeStages;
   2215 };
   2216 
   2217 QuadrantRendederCase::QuadrantRendederCase (tcu::TestContext&		testCtx,
   2218 											const char*				name,
   2219 											const char*				description,
   2220 											glu::GLSLVersion		glslVersion,
   2221 											vk::VkShaderStageFlags	exitingStages,
   2222 											vk::VkShaderStageFlags	activeStages)
   2223 	: vkt::TestCase		(testCtx, name, description)
   2224 	, m_glslVersion		(glslVersion)
   2225 	, m_exitingStages	(exitingStages)
   2226 	, m_activeStages	(activeStages)
   2227 {
   2228 	DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
   2229 }
   2230 
   2231 std::string QuadrantRendederCase::genVertexSource (void) const
   2232 {
   2233 	const char* const	nextStageName	= ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)	? ("tsc")
   2234 										: ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)				? ("geo")
   2235 										: ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)				? ("frag")
   2236 										: (DE_NULL);
   2237 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
   2238 	std::ostringstream	buf;
   2239 
   2240 	if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
   2241 	{
   2242 		const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
   2243 
   2244 		// active vertex shader
   2245 		buf << versionDecl << "\n"
   2246 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
   2247 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0)
   2248 			<< "layout(location = 0) out highp vec4 " << nextStageName << "_color;\n"
   2249 			<< (onlyVS ? "" : "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
   2250 			<< "void main (void)\n"
   2251 			<< "{\n"
   2252 			<< "	highp vec4 result_position;\n"
   2253 			<< "	highp int quadrant_id;\n"
   2254 			<< s_quadrantGenVertexPosSource
   2255 			<< "	gl_Position = result_position;\n"
   2256 			<< (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n")
   2257 			<< "\n"
   2258 			<< "	highp vec4 result_color;\n"
   2259 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT)
   2260 			<< "	" << nextStageName << "_color = result_color;\n"
   2261 			<< "}\n";
   2262 	}
   2263 	else
   2264 	{
   2265 		// do nothing
   2266 		buf << versionDecl << "\n"
   2267 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
   2268 			<< "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
   2269 			<< "void main (void)\n"
   2270 			<< "{\n"
   2271 			<< "	highp vec4 result_position;\n"
   2272 			<< "	highp int quadrant_id;\n"
   2273 			<< s_quadrantGenVertexPosSource
   2274 			<< "	gl_Position = result_position;\n"
   2275 			<< "	" << nextStageName << "_quadrant_id = quadrant_id;\n"
   2276 			<< "}\n";
   2277 	}
   2278 
   2279 	return buf.str();
   2280 }
   2281 
   2282 std::string QuadrantRendederCase::genTessCtrlSource (void) const
   2283 {
   2284 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
   2285 	const bool			extRequired		= glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
   2286 	const char* const	tessExtDecl		= extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
   2287 	std::ostringstream	buf;
   2288 
   2289 	if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
   2290 	{
   2291 		// contributing not implemented
   2292 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
   2293 
   2294 		// active tc shader
   2295 		buf << versionDecl << "\n"
   2296 			<< tessExtDecl
   2297 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
   2298 			<< "layout(vertices=3) out;\n"
   2299 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
   2300 			<< "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
   2301 			<< "layout(location = 0) out highp vec4 tes_color[];\n"
   2302 			<< "void main (void)\n"
   2303 			<< "{\n"
   2304 			<< "	highp vec4 result_color;\n"
   2305 			<< "	highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
   2306 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
   2307 			<< "\n"
   2308 			<< "	tes_color[gl_InvocationID] = result_color;\n"
   2309 			<< "\n"
   2310 			<< "	// no dynamic input block indexing\n"
   2311 			<< "	highp vec4 position;\n"
   2312 			<< "	if (gl_InvocationID == 0)\n"
   2313 			<< "		position = gl_in[0].gl_Position;\n"
   2314 			<< "	else if (gl_InvocationID == 1)\n"
   2315 			<< "		position = gl_in[1].gl_Position;\n"
   2316 			<< "	else\n"
   2317 			<< "		position = gl_in[2].gl_Position;\n"
   2318 			<< "	gl_out[gl_InvocationID].gl_Position = position;\n"
   2319 			<< "	gl_TessLevelInner[0] = 2.8;\n"
   2320 			<< "	gl_TessLevelInner[1] = 2.8;\n"
   2321 			<< "	gl_TessLevelOuter[0] = 2.8;\n"
   2322 			<< "	gl_TessLevelOuter[1] = 2.8;\n"
   2323 			<< "	gl_TessLevelOuter[2] = 2.8;\n"
   2324 			<< "	gl_TessLevelOuter[3] = 2.8;\n"
   2325 			<< "}\n";
   2326 	}
   2327 	else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
   2328 	{
   2329 		// active te shader, tc passthru
   2330 		buf << versionDecl << "\n"
   2331 			<< tessExtDecl
   2332 			<< "layout(vertices=3) out;\n"
   2333 			<< "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
   2334 			<< "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
   2335 			<< "void main (void)\n"
   2336 			<< "{\n"
   2337 			<< "	tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
   2338 			<< "\n"
   2339 			<< "	// no dynamic input block indexing\n"
   2340 			<< "	highp vec4 position;\n"
   2341 			<< "	if (gl_InvocationID == 0)\n"
   2342 			<< "		position = gl_in[0].gl_Position;\n"
   2343 			<< "	else if (gl_InvocationID == 1)\n"
   2344 			<< "		position = gl_in[1].gl_Position;\n"
   2345 			<< "	else\n"
   2346 			<< "		position = gl_in[2].gl_Position;\n"
   2347 			<< "	gl_out[gl_InvocationID].gl_Position = position;\n"
   2348 			<< "	gl_TessLevelInner[0] = 2.8;\n"
   2349 			<< "	gl_TessLevelInner[1] = 2.8;\n"
   2350 			<< "	gl_TessLevelOuter[0] = 2.8;\n"
   2351 			<< "	gl_TessLevelOuter[1] = 2.8;\n"
   2352 			<< "	gl_TessLevelOuter[2] = 2.8;\n"
   2353 			<< "	gl_TessLevelOuter[3] = 2.8;\n"
   2354 			<< "}\n";
   2355 	}
   2356 	else
   2357 	{
   2358 		// passthrough not implemented
   2359 		DE_FATAL("not implemented");
   2360 	}
   2361 
   2362 	return buf.str();
   2363 }
   2364 
   2365 std::string QuadrantRendederCase::genTessEvalSource (void) const
   2366 {
   2367 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
   2368 	const bool			extRequired		= glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
   2369 	const char* const	tessExtDecl		= extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
   2370 	std::ostringstream	buf;
   2371 
   2372 	if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
   2373 	{
   2374 		// contributing not implemented
   2375 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
   2376 
   2377 		// active te shader
   2378 		buf << versionDecl << "\n"
   2379 			<< tessExtDecl
   2380 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
   2381 			<< "layout(triangles) in;\n"
   2382 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
   2383 			<< "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
   2384 			<< "layout(location = 0) out highp vec4 frag_color;\n"
   2385 			<< "void main (void)\n"
   2386 			<< "{\n"
   2387 			<< "	highp vec4 result_color;\n"
   2388 			<< "	highp int quadrant_id = tes_quadrant_id[0];\n"
   2389 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
   2390 			<< "\n"
   2391 			<< "	frag_color = result_color;\n"
   2392 			<< "	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
   2393 			<< "}\n";
   2394 	}
   2395 	else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
   2396 	{
   2397 		// contributing not implemented
   2398 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
   2399 
   2400 		// active tc shader, te is passthru
   2401 		buf << versionDecl << "\n"
   2402 			<< tessExtDecl
   2403 			<< "layout(triangles) in;\n"
   2404 			<< "layout(location = 0) in highp vec4 tes_color[];\n"
   2405 			<< "layout(location = 0) out highp vec4 frag_color;\n"
   2406 			<< "void main (void)\n"
   2407 			<< "{\n"
   2408 			<< "	frag_color = tes_color[0];\n"
   2409 			<< "	gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
   2410 			<< "}\n";
   2411 	}
   2412 	else
   2413 	{
   2414 		// passthrough not implemented
   2415 		DE_FATAL("not implemented");
   2416 	}
   2417 
   2418 	return buf.str();
   2419 }
   2420 
   2421 std::string QuadrantRendederCase::genGeometrySource (void) const
   2422 {
   2423 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
   2424 	const bool			extRequired		= glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
   2425 	const char* const	geomExtDecl		= extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
   2426 	std::ostringstream	buf;
   2427 
   2428 	if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
   2429 	{
   2430 		// contributing not implemented
   2431 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
   2432 
   2433 		// active geometry shader
   2434 		buf << versionDecl << "\n"
   2435 			<< geomExtDecl
   2436 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
   2437 			<< "layout(triangles) in;\n"
   2438 			<< "layout(triangle_strip, max_vertices=4) out;\n"
   2439 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
   2440 			<< "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
   2441 			<< "layout(location = 0) out highp vec4 frag_color;\n"
   2442 			<< "void main (void)\n"
   2443 			<< "{\n"
   2444 			<< "	highp int quadrant_id;\n"
   2445 			<< "	highp vec4 result_color;\n"
   2446 			<< "\n"
   2447 			<< "	quadrant_id = geo_quadrant_id[0];\n"
   2448 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
   2449 			<< "	frag_color = result_color;\n"
   2450 			<< "	gl_Position = gl_in[0].gl_Position;\n"
   2451 			<< "	EmitVertex();\n"
   2452 			<< "\n"
   2453 			<< "	quadrant_id = geo_quadrant_id[1];\n"
   2454 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
   2455 			<< "	frag_color = result_color;\n"
   2456 			<< "	gl_Position = gl_in[1].gl_Position;\n"
   2457 			<< "	EmitVertex();\n"
   2458 			<< "\n"
   2459 			<< "	quadrant_id = geo_quadrant_id[2];\n"
   2460 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
   2461 			<< "	frag_color = result_color;\n"
   2462 			<< "	gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
   2463 			<< "	EmitVertex();\n"
   2464 			<< "\n"
   2465 			<< "	quadrant_id = geo_quadrant_id[0];\n"
   2466 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
   2467 			<< "	frag_color = result_color;\n"
   2468 			<< "	gl_Position = gl_in[2].gl_Position;\n"
   2469 			<< "	EmitVertex();\n"
   2470 			<< "}\n";
   2471 	}
   2472 	else
   2473 	{
   2474 		// passthrough not implemented
   2475 		DE_FATAL("not implemented");
   2476 	}
   2477 
   2478 	return buf.str();
   2479 }
   2480 
   2481 std::string QuadrantRendederCase::genFragmentSource (void) const
   2482 {
   2483 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
   2484 	std::ostringstream	buf;
   2485 
   2486 	if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
   2487 	{
   2488 		buf << versionDecl << "\n"
   2489 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
   2490 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
   2491 
   2492 		if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
   2493 		{
   2494 			// there are other stages, this is just a contributor
   2495 			buf << "layout(location = 0) in mediump vec4 frag_color;\n";
   2496 		}
   2497 
   2498 		buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
   2499 			<< "layout(location = 0) out mediump vec4 o_color;\n"
   2500 			<< "void main (void)\n"
   2501 			<< "{\n"
   2502 			<< "	highp int quadrant_id = frag_quadrant_id;\n"
   2503 			<< "	highp vec4 result_color;\n"
   2504 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
   2505 
   2506 		if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
   2507 		{
   2508 			// just contributor
   2509 			buf	<< "	if (frag_quadrant_id < 2)\n"
   2510 				<< "		o_color = result_color;\n"
   2511 				<< "	else\n"
   2512 				<< "		o_color = frag_color;\n";
   2513 		}
   2514 		else
   2515 			buf << "	o_color = result_color;\n";
   2516 
   2517 		buf << "}\n";
   2518 	}
   2519 	else if (m_activeStages == 0u)
   2520 	{
   2521 		// special case, no active stages
   2522 		buf << versionDecl << "\n"
   2523 			<< "layout(location = 1) flat in highp int frag_quadrant_id;\n"
   2524 			<< "layout(location = 0) out mediump vec4 o_color;\n"
   2525 			<< "void main (void)\n"
   2526 			<< "{\n"
   2527 			<< "	highp int quadrant_id = frag_quadrant_id;\n"
   2528 			<< "	highp vec4 result_color;\n"
   2529 			<< genNoAccessSource()
   2530 			<< "	o_color = result_color;\n"
   2531 			<< "}\n";
   2532 	}
   2533 	else
   2534 	{
   2535 		// passthrough
   2536 		buf <<	versionDecl << "\n"
   2537 			<<	"layout(location = 0) in mediump vec4 frag_color;\n"
   2538 				"layout(location = 0) out mediump vec4 o_color;\n"
   2539 				"void main (void)\n"
   2540 				"{\n"
   2541 				"	o_color = frag_color;\n"
   2542 				"}\n";
   2543 	}
   2544 
   2545 	return buf.str();
   2546 }
   2547 
   2548 std::string QuadrantRendederCase::genComputeSource (void) const
   2549 {
   2550 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
   2551 	std::ostringstream	buf;
   2552 
   2553 	buf	<< versionDecl << "\n"
   2554 		<< genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
   2555 		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
   2556 		<< genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
   2557 		<< "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
   2558 		<< "{\n"
   2559 		<< "	highp vec4 read_colors[4];\n"
   2560 		<< "} b_out;\n"
   2561 		<< "void main (void)\n"
   2562 		<< "{\n"
   2563 		<< "	highp int quadrant_id = int(gl_WorkGroupID.x);\n"
   2564 		<< "	highp vec4 result_color;\n"
   2565 		<< genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
   2566 		<< "	b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
   2567 		<< "}\n";
   2568 
   2569 	return buf.str();
   2570 }
   2571 
   2572 void QuadrantRendederCase::initPrograms (vk::SourceCollections& programCollection) const
   2573 {
   2574 	if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
   2575 		programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
   2576 
   2577 	if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
   2578 		programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
   2579 
   2580 	if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
   2581 		programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
   2582 
   2583 	if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
   2584 		programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
   2585 
   2586 	if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
   2587 		programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
   2588 
   2589 	if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
   2590 		programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
   2591 }
   2592 
   2593 class BufferDescriptorCase : public QuadrantRendederCase
   2594 {
   2595 public:
   2596 	enum
   2597 	{
   2598 		FLAG_VIEW_OFFSET			= (1u << 1u),
   2599 		FLAG_DYNAMIC_OFFSET_ZERO	= (1u << 2u),
   2600 		FLAG_DYNAMIC_OFFSET_NONZERO	= (1u << 3u),
   2601 	};
   2602 	// enum continues where resource flags ends
   2603 	DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
   2604 
   2605 									BufferDescriptorCase		(tcu::TestContext&		testCtx,
   2606 																 const char*			name,
   2607 																 const char*			description,
   2608 																 bool					isPrimaryCmdBuf,
   2609 																 vk::VkDescriptorType	descriptorType,
   2610 																 vk::VkShaderStageFlags	exitingStages,
   2611 																 vk::VkShaderStageFlags	activeStages,
   2612 																 ShaderInputInterface	shaderInterface,
   2613 																 deUint32				flags);
   2614 
   2615 private:
   2616 	std::string						genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const;
   2617 	std::string						genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
   2618 	std::string						genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const;
   2619 	std::string						genNoAccessSource			(void) const;
   2620 
   2621 	vkt::TestInstance*				createInstance				(vkt::Context& context) const;
   2622 
   2623 	const bool						m_viewOffset;
   2624 	const bool						m_dynamicOffsetSet;
   2625 	const bool						m_dynamicOffsetNonZero;
   2626 	const bool						m_isPrimaryCmdBuf;
   2627 	const vk::VkDescriptorType		m_descriptorType;
   2628 	const ShaderInputInterface		m_shaderInterface;
   2629 };
   2630 
   2631 BufferDescriptorCase::BufferDescriptorCase (tcu::TestContext&		testCtx,
   2632 											const char*				name,
   2633 											const char*				description,
   2634 											bool					isPrimaryCmdBuf,
   2635 											vk::VkDescriptorType	descriptorType,
   2636 											vk::VkShaderStageFlags	exitingStages,
   2637 											vk::VkShaderStageFlags	activeStages,
   2638 											ShaderInputInterface	shaderInterface,
   2639 											deUint32				flags)
   2640 	: QuadrantRendederCase		(testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
   2641 	, m_viewOffset				((flags & FLAG_VIEW_OFFSET) != 0u)
   2642 	, m_dynamicOffsetSet		((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
   2643 	, m_dynamicOffsetNonZero	((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
   2644 	, m_isPrimaryCmdBuf			(isPrimaryCmdBuf)
   2645 	, m_descriptorType			(descriptorType)
   2646 	, m_shaderInterface			(shaderInterface)
   2647 {
   2648 }
   2649 
   2650 std::string BufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
   2651 {
   2652 	DE_UNREF(stage);
   2653 	return "";
   2654 }
   2655 
   2656 std::string BufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
   2657 {
   2658 	DE_UNREF(stage);
   2659 
   2660 	const bool			isUniform		= isUniformDescriptorType(m_descriptorType);
   2661 	const char* const	storageType		= (isUniform) ? ("uniform") : ("buffer");
   2662 	std::ostringstream	buf;
   2663 
   2664 	switch (m_shaderInterface)
   2665 	{
   2666 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   2667 			buf	<< "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
   2668 				<< "{\n"
   2669 				<< "	highp vec4 colorA;\n"
   2670 				<< "	highp vec4 colorB;\n"
   2671 				<< "} b_instance;\n";
   2672 			break;
   2673 
   2674 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   2675 			buf	<< "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferNameA\n"
   2676 				<< "{\n"
   2677 				<< "	highp vec4 colorA;\n"
   2678 				<< "	highp vec4 colorB;\n"
   2679 				<< "} b_instanceA;\n"
   2680 				<< "layout(set = 0, binding = " << (numUsedBindings+1) << ", std140) " << storageType << " BufferNameB\n"
   2681 				<< "{\n"
   2682 				<< "	highp vec4 colorA;\n"
   2683 				<< "	highp vec4 colorB;\n"
   2684 				<< "} b_instanceB;\n";
   2685 			break;
   2686 
   2687 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   2688 			buf	<< "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
   2689 				<< "{\n"
   2690 				<< "	highp vec4 colorA;\n"
   2691 				<< "	highp vec4 colorB;\n"
   2692 				<< "} b_instances[2];\n";
   2693 			break;
   2694 
   2695 		default:
   2696 			DE_FATAL("Impossible");
   2697 	}
   2698 
   2699 	return buf.str();
   2700 }
   2701 
   2702 std::string BufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
   2703 {
   2704 	DE_UNREF(stage);
   2705 
   2706 	std::ostringstream buf;
   2707 
   2708 	switch (m_shaderInterface)
   2709 	{
   2710 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   2711 			buf << "	if (quadrant_id == 1 || quadrant_id == 2)\n"
   2712 				<< "		result_color = b_instance.colorA;\n"
   2713 				<< "	else\n"
   2714 				<< "		result_color = b_instance.colorB;\n";
   2715 			break;
   2716 
   2717 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   2718 			buf << "	if (quadrant_id == 1 || quadrant_id == 2)\n"
   2719 				<< "		result_color = b_instanceA.colorA;\n"
   2720 				<< "	else\n"
   2721 				<< "		result_color = b_instanceB.colorB;\n";
   2722 			break;
   2723 
   2724 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   2725 			buf << "	if (quadrant_id == 1 || quadrant_id == 2)\n"
   2726 				<< "		result_color = b_instances[0].colorA;\n"
   2727 				<< "	else\n"
   2728 				<< "		result_color = b_instances[1].colorB;\n";
   2729 			break;
   2730 
   2731 		default:
   2732 			DE_FATAL("Impossible");
   2733 	}
   2734 
   2735 	return buf.str();
   2736 }
   2737 
   2738 std::string BufferDescriptorCase::genNoAccessSource (void) const
   2739 {
   2740 	return "	if (quadrant_id == 1 || quadrant_id == 2)\n"
   2741 		   "		result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
   2742 		   "	else\n"
   2743 		   "		result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
   2744 }
   2745 
   2746 vkt::TestInstance* BufferDescriptorCase::createInstance (vkt::Context& context) const
   2747 {
   2748 	verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
   2749 
   2750 	if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
   2751 	{
   2752 		DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
   2753 		return new BufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
   2754 	}
   2755 	else
   2756 		return new BufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
   2757 }
   2758 
   2759 class ImageInstanceImages
   2760 {
   2761 public:
   2762 										ImageInstanceImages		(const vk::DeviceInterface&		vki,
   2763 																 vk::VkDevice					device,
   2764 																 deUint32						queueFamilyIndex,
   2765 																 vk::VkQueue					queue,
   2766 																 vk::Allocator&					allocator,
   2767 																 vk::VkDescriptorType			descriptorType,
   2768 																 vk::VkImageViewType			viewType,
   2769 																 int							numImages,
   2770 																 deUint32						baseMipLevel,
   2771 																 deUint32						baseArraySlice);
   2772 
   2773 private:
   2774 	static vk::Move<vk::VkImage>		createImage				(const vk::DeviceInterface&			vki,
   2775 																 vk::VkDevice						device,
   2776 																 vk::Allocator&						allocator,
   2777 																 vk::VkDescriptorType				descriptorType,
   2778 																 vk::VkImageViewType				viewType,
   2779 																 const tcu::TextureLevelPyramid&	sourceImage,
   2780 																 de::MovePtr<vk::Allocation>*		outAllocation);
   2781 
   2782 	static vk::Move<vk::VkImageView>	createImageView			(const vk::DeviceInterface&			vki,
   2783 																 vk::VkDevice						device,
   2784 																 vk::VkImageViewType				viewType,
   2785 																 const tcu::TextureLevelPyramid&	sourceImage,
   2786 																 vk::VkImage						image,
   2787 																 deUint32							baseMipLevel,
   2788 																 deUint32							baseArraySlice);
   2789 
   2790 	void								populateSourceImage		(tcu::TextureLevelPyramid*			dst,
   2791 																 bool								isFirst) const;
   2792 
   2793 	void								uploadImage				(const vk::DeviceInterface&			vki,
   2794 																 vk::VkDevice						device,
   2795 																 deUint32							queueFamilyIndex,
   2796 																 vk::VkQueue						queue,
   2797 																 vk::Allocator&						allocator,
   2798 																 vk::VkImage						image,
   2799 																 vk::VkImageLayout					layout,
   2800 																 const tcu::TextureLevelPyramid&	data);
   2801 
   2802 protected:
   2803 	enum
   2804 	{
   2805 		IMAGE_SIZE		= 64,
   2806 		NUM_MIP_LEVELS	= 2,
   2807 		ARRAY_SIZE		= 2,
   2808 	};
   2809 
   2810 	const vk::VkImageViewType			m_viewType;
   2811 	const deUint32						m_baseMipLevel;
   2812 	const deUint32						m_baseArraySlice;
   2813 
   2814 	const tcu::TextureFormat			m_imageFormat;
   2815 	tcu::TextureLevelPyramid			m_sourceImageA;
   2816 	tcu::TextureLevelPyramid			m_sourceImageB;
   2817 
   2818 	de::MovePtr<vk::Allocation>			m_imageMemoryA;
   2819 	de::MovePtr<vk::Allocation>			m_imageMemoryB;
   2820 	vk::Move<vk::VkImage>				m_imageA;
   2821 	vk::Move<vk::VkImage>				m_imageB;
   2822 	vk::Move<vk::VkImageView>			m_imageViewA;
   2823 	vk::Move<vk::VkImageView>			m_imageViewB;
   2824 };
   2825 
   2826 ImageInstanceImages::ImageInstanceImages (const vk::DeviceInterface&	vki,
   2827 										  vk::VkDevice					device,
   2828 										  deUint32						queueFamilyIndex,
   2829 										  vk::VkQueue					queue,
   2830 										  vk::Allocator&				allocator,
   2831 										  vk::VkDescriptorType			descriptorType,
   2832 										  vk::VkImageViewType			viewType,
   2833 										  int							numImages,
   2834 										  deUint32						baseMipLevel,
   2835 										  deUint32						baseArraySlice)
   2836 	: m_viewType		(viewType)
   2837 	, m_baseMipLevel	(baseMipLevel)
   2838 	, m_baseArraySlice	(baseArraySlice)
   2839 	, m_imageFormat		(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
   2840 	, m_sourceImageA	(m_imageFormat, NUM_MIP_LEVELS)
   2841 	, m_sourceImageB	(m_imageFormat, NUM_MIP_LEVELS)
   2842 	, m_imageMemoryA	(DE_NULL)
   2843 	, m_imageMemoryB	(DE_NULL)
   2844 	, m_imageA			(vk::Move<vk::VkImage>())
   2845 	, m_imageB			(vk::Move<vk::VkImage>())
   2846 	, m_imageViewA		(vk::Move<vk::VkImageView>())
   2847 	, m_imageViewB		(vk::Move<vk::VkImageView>())
   2848 {
   2849 	const vk::VkImageLayout	layout	= getImageLayoutForDescriptorType(descriptorType);
   2850 
   2851 	DE_ASSERT(numImages == 1 || numImages == 2);
   2852 
   2853 	populateSourceImage(&m_sourceImageA, true);
   2854 	m_imageA = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageA, &m_imageMemoryA);
   2855 	m_imageViewA = createImageView(vki, device, viewType, m_sourceImageA, *m_imageA, m_baseMipLevel, m_baseArraySlice);
   2856 	uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageA, layout, m_sourceImageA);
   2857 
   2858 	if (numImages == 2)
   2859 	{
   2860 		populateSourceImage(&m_sourceImageB, false);
   2861 		m_imageB = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageB, &m_imageMemoryB);
   2862 		m_imageViewB = createImageView(vki, device, viewType, m_sourceImageB, *m_imageB, m_baseMipLevel, m_baseArraySlice);
   2863 		uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageB, layout, m_sourceImageB);
   2864 	}
   2865 }
   2866 
   2867 vk::Move<vk::VkImage> ImageInstanceImages::createImage (const vk::DeviceInterface&			vki,
   2868 														vk::VkDevice						device,
   2869 														vk::Allocator&						allocator,
   2870 														vk::VkDescriptorType				descriptorType,
   2871 														vk::VkImageViewType					viewType,
   2872 														const tcu::TextureLevelPyramid&		sourceImage,
   2873 														de::MovePtr<vk::Allocation>*		outAllocation)
   2874 {
   2875 	const tcu::ConstPixelBufferAccess	baseLevel	= sourceImage.getLevel(0);
   2876 	const bool							isCube		= (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
   2877 	const bool							isStorage	= (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
   2878 	const deUint32						readUsage	= (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
   2879 	const deUint32						arraySize	= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (baseLevel.getHeight())
   2880 													: (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (baseLevel.getDepth())
   2881 													: (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)														? (1)
   2882 													: (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (baseLevel.getDepth()) // cube: numFaces * numLayers
   2883 																																					: (0);
   2884 	const vk::VkExtent3D				extent		=
   2885 	{
   2886 		// x
   2887 		(deUint32)baseLevel.getWidth(),
   2888 
   2889 		// y
   2890 		(viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1u) : (deUint32)baseLevel.getHeight(),
   2891 
   2892 		// z
   2893 		(viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((deUint32)baseLevel.getDepth()) : (1u),
   2894 	};
   2895 	const vk::VkImageCreateInfo			createInfo	=
   2896 	{
   2897 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
   2898 		DE_NULL,
   2899 		isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
   2900 		viewTypeToImageType(viewType),											// imageType
   2901 		vk::mapTextureFormat(baseLevel.getFormat()),							// format
   2902 		extent,																	// extent
   2903 		(deUint32)sourceImage.getNumLevels(),									// mipLevels
   2904 		arraySize,																// arraySize
   2905 		vk::VK_SAMPLE_COUNT_1_BIT,												// samples
   2906 		vk::VK_IMAGE_TILING_OPTIMAL,											// tiling
   2907 		readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,						// usage
   2908 		vk::VK_SHARING_MODE_EXCLUSIVE,											// sharingMode
   2909 		0u,																		// queueFamilyCount
   2910 		DE_NULL,																// pQueueFamilyIndices
   2911 		vk::VK_IMAGE_LAYOUT_UNDEFINED,											// initialLayout
   2912 	};
   2913 	vk::Move<vk::VkImage>				image		(vk::createImage(vki, device, &createInfo));
   2914 
   2915 	*outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
   2916 	return image;
   2917 }
   2918 
   2919 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView (const vk::DeviceInterface&			vki,
   2920 																vk::VkDevice						device,
   2921 																vk::VkImageViewType					viewType,
   2922 																const tcu::TextureLevelPyramid&		sourceImage,
   2923 																vk::VkImage							image,
   2924 																deUint32							baseMipLevel,
   2925 																deUint32							baseArraySlice)
   2926 {
   2927 	const tcu::ConstPixelBufferAccess	baseLevel			= sourceImage.getLevel(0);
   2928 	const deUint32						viewTypeBaseSlice	= (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * baseArraySlice) : (baseArraySlice);
   2929 	const deUint32						viewArraySize		= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D)			? (1)
   2930 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (baseLevel.getHeight() - viewTypeBaseSlice)
   2931 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_2D)			? (1)
   2932 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (baseLevel.getDepth() - viewTypeBaseSlice)
   2933 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)			? (1)
   2934 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)			? (6)
   2935 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (baseLevel.getDepth() - viewTypeBaseSlice) // cube: numFaces * numLayers
   2936 																												: (0);
   2937 
   2938 	DE_ASSERT(viewArraySize > 0);
   2939 
   2940 	const vk::VkImageSubresourceRange	resourceRange	=
   2941 	{
   2942 		vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
   2943 		baseMipLevel,									// baseMipLevel
   2944 		sourceImage.getNumLevels() - baseMipLevel,		// mipLevels
   2945 		viewTypeBaseSlice,								// baseArraySlice
   2946 		viewArraySize,									// arraySize
   2947 	};
   2948 	const vk::VkImageViewCreateInfo		createInfo		=
   2949 	{
   2950 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
   2951 		DE_NULL,
   2952 		(vk::VkImageViewCreateFlags)0,
   2953 		image,											// image
   2954 		viewType,										// viewType
   2955 		vk::mapTextureFormat(baseLevel.getFormat()),	// format
   2956 		{
   2957 			vk::VK_COMPONENT_SWIZZLE_R,
   2958 			vk::VK_COMPONENT_SWIZZLE_G,
   2959 			vk::VK_COMPONENT_SWIZZLE_B,
   2960 			vk::VK_COMPONENT_SWIZZLE_A
   2961 		},												// channels
   2962 		resourceRange,									// subresourceRange
   2963 	};
   2964 	return vk::createImageView(vki, device, &createInfo);
   2965 }
   2966 
   2967 void ImageInstanceImages::populateSourceImage (tcu::TextureLevelPyramid* dst, bool isFirst) const
   2968 {
   2969 	const int numLevels = dst->getNumLevels();
   2970 
   2971 	for (int level = 0; level < numLevels; ++level)
   2972 	{
   2973 		const int	width	= IMAGE_SIZE >> level;
   2974 		const int	height	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (ARRAY_SIZE)
   2975 																																: (IMAGE_SIZE >> level);
   2976 		const int	depth	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (1)
   2977 							: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (ARRAY_SIZE)
   2978 							: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (6 * ARRAY_SIZE)
   2979 							: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)															? (IMAGE_SIZE >> level)
   2980 																																: (1);
   2981 
   2982 		dst->allocLevel(level, width, height, depth);
   2983 
   2984 		{
   2985 			const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
   2986 
   2987 			for (int z = 0; z < depth; ++z)
   2988 			for (int y = 0; y < height; ++y)
   2989 			for (int x = 0; x < width; ++x)
   2990 			{
   2991 				const int			gradPos	= x + y + z;
   2992 				const int			gradMax	= width + height + depth - 3;
   2993 
   2994 				const int			red		= 255 * gradPos / gradMax;													//!< gradient from 0 -> max (detects large offset errors)
   2995 				const int			green	= ((gradPos % 2 == 0) ? (127) : (0)) + ((gradPos % 4 < 3) ? (128) : (0));	//!< 3-level M pattern (detects small offset errors)
   2996 				const int			blue	= (128 * level / numLevels) + (isFirst ? 127 : 0);							//!< level and image index (detects incorrect lod / image)
   2997 
   2998 				DE_ASSERT(de::inRange(red, 0, 255));
   2999 				DE_ASSERT(de::inRange(green, 0, 255));
   3000 				DE_ASSERT(de::inRange(blue, 0, 255));
   3001 
   3002 				levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
   3003 			}
   3004 		}
   3005 	}
   3006 }
   3007 
   3008 void ImageInstanceImages::uploadImage (const vk::DeviceInterface&		vki,
   3009 									   vk::VkDevice						device,
   3010 									   deUint32							queueFamilyIndex,
   3011 									   vk::VkQueue						queue,
   3012 									   vk::Allocator&					allocator,
   3013 									   vk::VkImage						image,
   3014 									   vk::VkImageLayout				layout,
   3015 									   const tcu::TextureLevelPyramid&	data)
   3016 {
   3017 	const deUint32						arraySize					= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
   3018 																	  (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * (deUint32)ARRAY_SIZE) :
   3019 																	  ((deUint32)ARRAY_SIZE);
   3020 	const deUint32						dataBufferSize				= getTextureLevelPyramidDataSize(data);
   3021 	const vk::VkBufferCreateInfo		bufferCreateInfo			=
   3022 	{
   3023 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
   3024 		DE_NULL,
   3025 		0u,													// flags
   3026 		dataBufferSize,										// size
   3027 		vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,				// usage
   3028 		vk::VK_SHARING_MODE_EXCLUSIVE,						// sharingMode
   3029 		0u,													// queueFamilyCount
   3030 		DE_NULL,											// pQueueFamilyIndices
   3031 	};
   3032 	const vk::Unique<vk::VkBuffer>		dataBuffer					(vk::createBuffer(vki, device, &bufferCreateInfo));
   3033 	const de::MovePtr<vk::Allocation>	dataBufferMemory			= allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
   3034 	const vk::VkFenceCreateInfo			fenceCreateInfo				=
   3035 	{
   3036 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
   3037 		DE_NULL,
   3038 		0u,													// flags
   3039 	};
   3040 	const vk::VkBufferMemoryBarrier		preMemoryBarrier			=
   3041 	{
   3042 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   3043 		DE_NULL,
   3044 		vk::VK_ACCESS_HOST_WRITE_BIT,					// outputMask
   3045 		vk::VK_ACCESS_TRANSFER_READ_BIT,					// inputMask
   3046 		vk::VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex
   3047 		vk::VK_QUEUE_FAMILY_IGNORED,						// destQueueFamilyIndex
   3048 		*dataBuffer,										// buffer
   3049 		0u,													// offset
   3050 		dataBufferSize,										// size
   3051 	};
   3052 	const vk::VkImageSubresourceRange	fullSubrange				=
   3053 	{
   3054 		vk::VK_IMAGE_ASPECT_COLOR_BIT,						// aspectMask
   3055 		0u,													// baseMipLevel
   3056 		(deUint32)data.getNumLevels(),						// mipLevels
   3057 		0u,													// baseArraySlice
   3058 		arraySize,											// arraySize
   3059 	};
   3060 	const vk::VkImageMemoryBarrier		preImageBarrier				=
   3061 	{
   3062 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
   3063 		DE_NULL,
   3064 		0u,													// outputMask
   3065 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// inputMask
   3066 		vk::VK_IMAGE_LAYOUT_UNDEFINED,						// oldLayout
   3067 		vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// newLayout
   3068 		vk::VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex
   3069 		vk::VK_QUEUE_FAMILY_IGNORED,						// destQueueFamilyIndex
   3070 		image,												// image
   3071 		fullSubrange										// subresourceRange
   3072 	};
   3073 	const vk::VkImageMemoryBarrier		postImageBarrier			=
   3074 	{
   3075 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
   3076 		DE_NULL,
   3077 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// outputMask
   3078 		vk::VK_ACCESS_SHADER_READ_BIT,						// inputMask
   3079 		vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// oldLayout
   3080 		layout,												// newLayout
   3081 		vk::VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex
   3082 		vk::VK_QUEUE_FAMILY_IGNORED,						// destQueueFamilyIndex
   3083 		image,												// image
   3084 		fullSubrange										// subresourceRange
   3085 	};
   3086 	const vk::VkCommandPoolCreateInfo		cmdPoolCreateInfo			=
   3087 	{
   3088 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
   3089 		DE_NULL,
   3090 		vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// flags
   3091 		queueFamilyIndex,									// queueFamilyIndex
   3092 	};
   3093 	const vk::Unique<vk::VkCommandPool>		cmdPool						(vk::createCommandPool(vki, device, &cmdPoolCreateInfo));
   3094 	const vk::VkCommandBufferAllocateInfo	cmdBufCreateInfo			=
   3095 	{
   3096 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
   3097 		DE_NULL,
   3098 		*cmdPool,											// cmdPool
   3099 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// level
   3100 		1u,													// count
   3101 	};
   3102 	const vk::VkCommandBufferBeginInfo		cmdBufBeginInfo				=
   3103 	{
   3104 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
   3105 		DE_NULL,
   3106 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
   3107 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
   3108 	};
   3109 
   3110 	const vk::Unique<vk::VkCommandBuffer>	cmd							(vk::allocateCommandBuffer(vki, device, &cmdBufCreateInfo));
   3111 	const vk::Unique<vk::VkFence>			cmdCompleteFence			(vk::createFence(vki, device, &fenceCreateInfo));
   3112 	const deUint64							infiniteTimeout				= ~(deUint64)0u;
   3113 	std::vector<vk::VkBufferImageCopy>		copySlices;
   3114 
   3115 	// copy data to buffer
   3116 	writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, m_viewType , &copySlices);
   3117 	flushMappedMemoryRange(vki, device, dataBufferMemory->getMemory(), dataBufferMemory->getOffset(), dataBufferSize);
   3118 
   3119 	// record command buffer
   3120 	VK_CHECK(vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
   3121 	vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
   3122 						   0, (const vk::VkMemoryBarrier*)DE_NULL,
   3123 						   1, &preMemoryBarrier,
   3124 						   1, &preImageBarrier);
   3125 	vki.cmdCopyBufferToImage(*cmd, *dataBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copySlices.size(), &copySlices[0]);
   3126 	vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
   3127 						   0, (const vk::VkMemoryBarrier*)DE_NULL,
   3128 						   0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
   3129 						   1, &postImageBarrier);
   3130 	VK_CHECK(vki.endCommandBuffer(*cmd));
   3131 
   3132 	// submit and wait for command buffer to complete before killing it
   3133 	{
   3134 		const vk::VkSubmitInfo	submitInfo	=
   3135 		{
   3136 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
   3137 			DE_NULL,
   3138 			0u,
   3139 			(const vk::VkSemaphore*)0,
   3140 			(const vk::VkPipelineStageFlags*)DE_NULL,
   3141 			1u,
   3142 			&cmd.get(),
   3143 			0u,
   3144 			(const vk::VkSemaphore*)0,
   3145 		};
   3146 		VK_CHECK(vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
   3147 	}
   3148 	VK_CHECK(vki.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
   3149 }
   3150 
   3151 class ImageFetchInstanceImages : private ImageInstanceImages
   3152 {
   3153 public:
   3154 								ImageFetchInstanceImages	(const vk::DeviceInterface&		vki,
   3155 															 vk::VkDevice					device,
   3156 															 deUint32						queueFamilyIndex,
   3157 															 vk::VkQueue					queue,
   3158 															 vk::Allocator&					allocator,
   3159 															 vk::VkDescriptorType			descriptorType,
   3160 															 ShaderInputInterface			shaderInterface,
   3161 															 vk::VkImageViewType			viewType,
   3162 															 deUint32						baseMipLevel,
   3163 															 deUint32						baseArraySlice);
   3164 
   3165 	static tcu::IVec3			getFetchPos					(vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx);
   3166 	tcu::Vec4					fetchImageValue				(int fetchPosNdx) const;
   3167 
   3168 	inline vk::VkImageView		getImageViewA				(void) const { return *m_imageViewA; }
   3169 	inline vk::VkImageView		getImageViewB				(void) const { return *m_imageViewB; }
   3170 
   3171 private:
   3172 	enum
   3173 	{
   3174 		// some arbitrary sample points for all four quadrants
   3175 		SAMPLE_POINT_0_X = 6,
   3176 		SAMPLE_POINT_0_Y = 13,
   3177 		SAMPLE_POINT_0_Z = 49,
   3178 
   3179 		SAMPLE_POINT_1_X = 51,
   3180 		SAMPLE_POINT_1_Y = 40,
   3181 		SAMPLE_POINT_1_Z = 44,
   3182 
   3183 		SAMPLE_POINT_2_X = 42,
   3184 		SAMPLE_POINT_2_Y = 26,
   3185 		SAMPLE_POINT_2_Z = 19,
   3186 
   3187 		SAMPLE_POINT_3_X = 25,
   3188 		SAMPLE_POINT_3_Y = 25,
   3189 		SAMPLE_POINT_3_Z = 18,
   3190 	};
   3191 
   3192 	const ShaderInputInterface	m_shaderInterface;
   3193 };
   3194 
   3195 ImageFetchInstanceImages::ImageFetchInstanceImages (const vk::DeviceInterface&	vki,
   3196 													vk::VkDevice				device,
   3197 													deUint32					queueFamilyIndex,
   3198 													vk::VkQueue					queue,
   3199 													vk::Allocator&				allocator,
   3200 													vk::VkDescriptorType		descriptorType,
   3201 													ShaderInputInterface		shaderInterface,
   3202 													vk::VkImageViewType			viewType,
   3203 													deUint32					baseMipLevel,
   3204 													deUint32					baseArraySlice)
   3205 	: ImageInstanceImages	(vki,
   3206 							 device,
   3207 							 queueFamilyIndex,
   3208 							 queue,
   3209 							 allocator,
   3210 							 descriptorType,
   3211 							 viewType,
   3212 							 getInterfaceNumResources(shaderInterface),	// numImages
   3213 							 baseMipLevel,
   3214 							 baseArraySlice)
   3215 	, m_shaderInterface		(shaderInterface)
   3216 {
   3217 }
   3218 
   3219 bool isImageViewTypeArray (vk::VkImageViewType type)
   3220 {
   3221 	return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
   3222 }
   3223 
   3224 tcu::IVec3 ImageFetchInstanceImages::getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx)
   3225 {
   3226 	const tcu::IVec3	fetchPositions[4]	=
   3227 	{
   3228 		tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
   3229 		tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
   3230 		tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
   3231 		tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
   3232 	};
   3233 	const tcu::IVec3	coord				= de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
   3234 	const deUint32		imageSize			= (deUint32)IMAGE_SIZE >> baseMipLevel;
   3235 	const deUint32		arraySize			= isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
   3236 
   3237 	switch (viewType)
   3238 	{
   3239 		case vk::VK_IMAGE_VIEW_TYPE_1D:
   3240 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:	return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
   3241 		case vk::VK_IMAGE_VIEW_TYPE_2D:
   3242 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:	return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
   3243 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
   3244 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:	return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
   3245 		case vk::VK_IMAGE_VIEW_TYPE_3D:			return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
   3246 		default:
   3247 			DE_FATAL("Impossible");
   3248 			return tcu::IVec3();
   3249 	}
   3250 }
   3251 
   3252 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue (int fetchPosNdx) const
   3253 {
   3254 	DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
   3255 
   3256 	const tcu::TextureLevelPyramid&	fetchSrcA	= m_sourceImageA;
   3257 	const tcu::TextureLevelPyramid&	fetchSrcB	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
   3258 	const tcu::TextureLevelPyramid&	fetchSrc	= ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
   3259 	tcu::IVec3						fetchPos	= getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
   3260 
   3261 	// add base array layer into the appropriate coordinate, based on the view type
   3262 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
   3263 		fetchPos.z() += 6 * m_baseArraySlice;
   3264 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
   3265 		fetchPos.y() += m_baseArraySlice;
   3266 	else
   3267 		fetchPos.z() += m_baseArraySlice;
   3268 
   3269 	return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
   3270 }
   3271 
   3272 class ImageFetchRenderInstance : public SingleCmdRenderInstance
   3273 {
   3274 public:
   3275 													ImageFetchRenderInstance	(vkt::Context&			context,
   3276 																				 bool					isPrimaryCmdBuf,
   3277 																				 vk::VkDescriptorType	descriptorType,
   3278 																				 vk::VkShaderStageFlags	stageFlags,
   3279 																				 ShaderInputInterface	shaderInterface,
   3280 																				 vk::VkImageViewType	viewType,
   3281 																				 deUint32				baseMipLevel,
   3282 																				 deUint32				baseArraySlice);
   3283 
   3284 private:
   3285 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(const vk::DeviceInterface&	vki,
   3286 																				 vk::VkDevice				device,
   3287 																				 vk::VkDescriptorType		descriptorType,
   3288 																				 ShaderInputInterface		shaderInterface,
   3289 																				 vk::VkShaderStageFlags		stageFlags);
   3290 
   3291 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout		(const vk::DeviceInterface&	vki,
   3292 																				 vk::VkDevice				device,
   3293 																				 vk::VkDescriptorSetLayout	descriptorSetLayout);
   3294 
   3295 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(const vk::DeviceInterface&	vki,
   3296 																				 vk::VkDevice				device,
   3297 																				 vk::VkDescriptorType		descriptorType,
   3298 																				 ShaderInputInterface		shaderInterface);
   3299 
   3300 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(const vk::DeviceInterface&	vki,
   3301 																				 vk::VkDevice				device,
   3302 																				 vk::VkDescriptorType		descriptorType,
   3303 																				 ShaderInputInterface		shaderInterface,
   3304 																				 vk::VkDescriptorSetLayout	layout,
   3305 																				 vk::VkDescriptorPool		pool,
   3306 																				 vk::VkImageView			viewA,
   3307 																				 vk::VkImageView			viewB);
   3308 
   3309 	void											logTestPlan					(void) const;
   3310 	vk::VkPipelineLayout							getPipelineLayout			(void) const;
   3311 	void											writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const;
   3312 	tcu::TestStatus									verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const;
   3313 
   3314 	enum
   3315 	{
   3316 		RENDER_SIZE = 128,
   3317 	};
   3318 
   3319 	const vk::VkDescriptorType						m_descriptorType;
   3320 	const vk::VkShaderStageFlags					m_stageFlags;
   3321 	const ShaderInputInterface						m_shaderInterface;
   3322 	const vk::VkImageViewType						m_viewType;
   3323 	const deUint32									m_baseMipLevel;
   3324 	const deUint32									m_baseArraySlice;
   3325 
   3326 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
   3327 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
   3328 	const ImageFetchInstanceImages					m_images;
   3329 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
   3330 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
   3331 };
   3332 
   3333 ImageFetchRenderInstance::ImageFetchRenderInstance	(vkt::Context&			context,
   3334 													 bool					isPrimaryCmdBuf,
   3335 													 vk::VkDescriptorType	descriptorType,
   3336 													 vk::VkShaderStageFlags	stageFlags,
   3337 													 ShaderInputInterface	shaderInterface,
   3338 													 vk::VkImageViewType	viewType,
   3339 													 deUint32				baseMipLevel,
   3340 													 deUint32				baseArraySlice)
   3341 	: SingleCmdRenderInstance	(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
   3342 	, m_descriptorType			(descriptorType)
   3343 	, m_stageFlags				(stageFlags)
   3344 	, m_shaderInterface			(shaderInterface)
   3345 	, m_viewType				(viewType)
   3346 	, m_baseMipLevel			(baseMipLevel)
   3347 	, m_baseArraySlice			(baseArraySlice)
   3348 	, m_descriptorSetLayout		(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
   3349 	, m_pipelineLayout			(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
   3350 	, m_images					(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
   3351 	, m_descriptorPool			(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
   3352 	, m_descriptorSet			(createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_images.getImageViewA(), m_images.getImageViewB()))
   3353 {
   3354 }
   3355 
   3356 vk::Move<vk::VkDescriptorSetLayout> ImageFetchRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&		vki,
   3357 																						 vk::VkDevice					device,
   3358 																						 vk::VkDescriptorType			descriptorType,
   3359 																						 ShaderInputInterface			shaderInterface,
   3360 																						 vk::VkShaderStageFlags			stageFlags)
   3361 {
   3362 	vk::DescriptorSetLayoutBuilder builder;
   3363 
   3364 	switch (shaderInterface)
   3365 	{
   3366 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   3367 			builder.addSingleBinding(descriptorType, stageFlags);
   3368 			break;
   3369 
   3370 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   3371 			builder.addSingleBinding(descriptorType, stageFlags);
   3372 			builder.addSingleBinding(descriptorType, stageFlags);
   3373 			break;
   3374 
   3375 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   3376 			builder.addArrayBinding(descriptorType, 2u, stageFlags);
   3377 			break;
   3378 
   3379 		default:
   3380 			DE_FATAL("Impossible");
   3381 	}
   3382 
   3383 	return builder.build(vki, device);
   3384 }
   3385 
   3386 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
   3387 																			   vk::VkDevice					device,
   3388 																			   vk::VkDescriptorSetLayout	descriptorSetLayout)
   3389 {
   3390 	const vk::VkPipelineLayoutCreateInfo createInfo =
   3391 	{
   3392 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
   3393 		DE_NULL,
   3394 		(vk::VkPipelineLayoutCreateFlags)0,
   3395 		1,						// descriptorSetCount
   3396 		&descriptorSetLayout,	// pSetLayouts
   3397 		0u,						// pushConstantRangeCount
   3398 		DE_NULL,				// pPushConstantRanges
   3399 	};
   3400 	return vk::createPipelineLayout(vki, device, &createInfo);
   3401 }
   3402 
   3403 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
   3404 																			   vk::VkDevice					device,
   3405 																			   vk::VkDescriptorType			descriptorType,
   3406 																			   ShaderInputInterface			shaderInterface)
   3407 {
   3408 	return vk::DescriptorPoolBuilder()
   3409 		.addType(descriptorType, getInterfaceNumResources(shaderInterface))
   3410 		.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   3411 }
   3412 
   3413 vk::Move<vk::VkDescriptorSet> ImageFetchRenderInstance::createDescriptorSet (const vk::DeviceInterface&		vki,
   3414 																			 vk::VkDevice					device,
   3415 																			 vk::VkDescriptorType			descriptorType,
   3416 																			 ShaderInputInterface			shaderInterface,
   3417 																			 vk::VkDescriptorSetLayout		layout,
   3418 																			 vk::VkDescriptorPool			pool,
   3419 																			 vk::VkImageView				viewA,
   3420 																			 vk::VkImageView				viewB)
   3421 {
   3422 	const vk::VkImageLayout					imageLayout		= getImageLayoutForDescriptorType(descriptorType);
   3423 	const vk::VkDescriptorImageInfo			imageInfos[2]	=
   3424 	{
   3425 		makeDescriptorImageInfo(viewA, imageLayout),
   3426 		makeDescriptorImageInfo(viewB, imageLayout),
   3427 	};
   3428 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
   3429 	{
   3430 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   3431 		DE_NULL,
   3432 		pool,
   3433 		1u,
   3434 		&layout
   3435 	};
   3436 
   3437 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(vki, device, &allocInfo);
   3438 	vk::DescriptorSetUpdateBuilder			builder;
   3439 
   3440 	switch (shaderInterface)
   3441 	{
   3442 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   3443 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
   3444 			break;
   3445 
   3446 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   3447 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
   3448 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &imageInfos[1]);
   3449 			break;
   3450 
   3451 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   3452 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, imageInfos);
   3453 			break;
   3454 
   3455 		default:
   3456 			DE_FATAL("Impossible");
   3457 	}
   3458 
   3459 	builder.update(vki, device);
   3460 	return descriptorSet;
   3461 }
   3462 
   3463 void ImageFetchRenderInstance::logTestPlan (void) const
   3464 {
   3465 	std::ostringstream msg;
   3466 
   3467 	msg << "Rendering 2x2 grid.\n"
   3468 		<< "Single descriptor set. Descriptor set contains "
   3469 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   3470 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   3471 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   3472 			    (const char*)DE_NULL)
   3473 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
   3474 		<< "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
   3475 
   3476 	if (m_baseMipLevel)
   3477 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
   3478 	if (m_baseArraySlice)
   3479 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
   3480 
   3481 	if (m_stageFlags == 0u)
   3482 	{
   3483 		msg << "Descriptors are not accessed in any shader stage.\n";
   3484 	}
   3485 	else
   3486 	{
   3487 		msg << "Color in each cell is fetched using the descriptor(s):\n";
   3488 
   3489 		for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   3490 		{
   3491 			msg << "Test sample " << resultNdx << ": fetching at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
   3492 
   3493 			if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
   3494 			{
   3495 				const int srcResourceNdx = (resultNdx % 2); // ABAB source
   3496 				msg << " from descriptor " << srcResourceNdx;
   3497 			}
   3498 
   3499 			msg << "\n";
   3500 		}
   3501 
   3502 		msg << "Descriptors are accessed in {"
   3503 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
   3504 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
   3505 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
   3506 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
   3507 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
   3508 			<< " } stages.";
   3509 	}
   3510 
   3511 	m_context.getTestContext().getLog()
   3512 		<< tcu::TestLog::Message
   3513 		<< msg.str()
   3514 		<< tcu::TestLog::EndMessage;
   3515 }
   3516 
   3517 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout (void) const
   3518 {
   3519 	return *m_pipelineLayout;
   3520 }
   3521 
   3522 void ImageFetchRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
   3523 {
   3524 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
   3525 	m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
   3526 }
   3527 
   3528 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
   3529 {
   3530 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
   3531 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
   3532 	const bool			doFetch		= (m_stageFlags != 0u); // no active stages? Then don't fetch
   3533 	const tcu::Vec4		sample0		= (!doFetch) ? (yellow)	: (m_images.fetchImageValue(0));
   3534 	const tcu::Vec4		sample1		= (!doFetch) ? (green)	: (m_images.fetchImageValue(1));
   3535 	const tcu::Vec4		sample2		= (!doFetch) ? (green)	: (m_images.fetchImageValue(2));
   3536 	const tcu::Vec4		sample3		= (!doFetch) ? (yellow)	: (m_images.fetchImageValue(3));
   3537 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
   3538 
   3539 	drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
   3540 
   3541 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
   3542 		return tcu::TestStatus::fail("Image verification failed");
   3543 	else
   3544 		return tcu::TestStatus::pass("Pass");
   3545 }
   3546 
   3547 class ImageFetchComputeInstance : public vkt::TestInstance
   3548 {
   3549 public:
   3550 											ImageFetchComputeInstance	(vkt::Context&			context,
   3551 																		 vk::VkDescriptorType	descriptorType,
   3552 																		 ShaderInputInterface	shaderInterface,
   3553 																		 vk::VkImageViewType	viewType,
   3554 																		 deUint32				baseMipLevel,
   3555 																		 deUint32				baseArraySlice);
   3556 
   3557 private:
   3558 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(void) const;
   3559 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(void) const;
   3560 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
   3561 
   3562 	tcu::TestStatus							iterate						(void);
   3563 	void									logTestPlan					(void) const;
   3564 	tcu::TestStatus							testResourceAccess			(void);
   3565 
   3566 	const vk::VkDescriptorType				m_descriptorType;
   3567 	const ShaderInputInterface				m_shaderInterface;
   3568 	const vk::VkImageViewType				m_viewType;
   3569 	const deUint32							m_baseMipLevel;
   3570 	const deUint32							m_baseArraySlice;
   3571 
   3572 	const vk::DeviceInterface&				m_vki;
   3573 	const vk::VkDevice						m_device;
   3574 	const vk::VkQueue						m_queue;
   3575 	const deUint32							m_queueFamilyIndex;
   3576 	vk::Allocator&							m_allocator;
   3577 
   3578 	const ComputeInstanceResultBuffer		m_result;
   3579 	const ImageFetchInstanceImages			m_images;
   3580 };
   3581 
   3582 ImageFetchComputeInstance::ImageFetchComputeInstance (Context&				context,
   3583 													  vk::VkDescriptorType	descriptorType,
   3584 													  ShaderInputInterface	shaderInterface,
   3585 													  vk::VkImageViewType	viewType,
   3586 													  deUint32				baseMipLevel,
   3587 													  deUint32				baseArraySlice)
   3588 	: vkt::TestInstance		(context)
   3589 	, m_descriptorType		(descriptorType)
   3590 	, m_shaderInterface		(shaderInterface)
   3591 	, m_viewType			(viewType)
   3592 	, m_baseMipLevel		(baseMipLevel)
   3593 	, m_baseArraySlice		(baseArraySlice)
   3594 	, m_vki					(context.getDeviceInterface())
   3595 	, m_device				(context.getDevice())
   3596 	, m_queue				(context.getUniversalQueue())
   3597 	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
   3598 	, m_allocator			(context.getDefaultAllocator())
   3599 	, m_result				(m_vki, m_device, m_allocator)
   3600 	, m_images				(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
   3601 {
   3602 }
   3603 
   3604 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout (void) const
   3605 {
   3606 	vk::DescriptorSetLayoutBuilder builder;
   3607 
   3608 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   3609 
   3610 	switch (m_shaderInterface)
   3611 	{
   3612 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   3613 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   3614 			break;
   3615 
   3616 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   3617 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   3618 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   3619 			break;
   3620 
   3621 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   3622 			builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   3623 			break;
   3624 
   3625 		default:
   3626 			DE_FATAL("Impossible");
   3627 	};
   3628 
   3629 	return builder.build(m_vki, m_device);
   3630 }
   3631 
   3632 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool (void) const
   3633 {
   3634 	return vk::DescriptorPoolBuilder()
   3635 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
   3636 		.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
   3637 		.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   3638 }
   3639 
   3640 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
   3641 {
   3642 	const vk::VkDescriptorBufferInfo		resultInfo		= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
   3643 	const vk::VkImageLayout					imageLayout		= getImageLayoutForDescriptorType(m_descriptorType);
   3644 	const vk::VkDescriptorImageInfo			imageInfos[2]	=
   3645 	{
   3646 		makeDescriptorImageInfo(m_images.getImageViewA(), imageLayout),
   3647 		makeDescriptorImageInfo(m_images.getImageViewB(), imageLayout),
   3648 	};
   3649 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
   3650 	{
   3651 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   3652 		DE_NULL,
   3653 		pool,
   3654 		1u,
   3655 		&layout
   3656 	};
   3657 
   3658 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(m_vki, m_device, &allocInfo);
   3659 	vk::DescriptorSetUpdateBuilder			builder;
   3660 
   3661 	// result
   3662 	builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
   3663 
   3664 	// images
   3665 	switch (m_shaderInterface)
   3666 	{
   3667 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   3668 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
   3669 			break;
   3670 
   3671 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   3672 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
   3673 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &imageInfos[1]);
   3674 			break;
   3675 
   3676 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   3677 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, imageInfos);
   3678 			break;
   3679 
   3680 		default:
   3681 			DE_FATAL("Impossible");
   3682 	}
   3683 
   3684 	builder.update(m_vki, m_device);
   3685 	return descriptorSet;
   3686 }
   3687 
   3688 tcu::TestStatus ImageFetchComputeInstance::iterate (void)
   3689 {
   3690 	logTestPlan();
   3691 	return testResourceAccess();
   3692 }
   3693 
   3694 void ImageFetchComputeInstance::logTestPlan (void) const
   3695 {
   3696 	std::ostringstream msg;
   3697 
   3698 	msg << "Fetching 4 values from image in compute shader.\n"
   3699 		<< "Single descriptor set. Descriptor set contains "
   3700 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   3701 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   3702 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   3703 			    (const char*)DE_NULL)
   3704 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
   3705 		<< "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
   3706 
   3707 	if (m_baseMipLevel)
   3708 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
   3709 	if (m_baseArraySlice)
   3710 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
   3711 
   3712 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   3713 	{
   3714 		msg << "Test sample " << resultNdx << ": fetch at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
   3715 
   3716 		if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
   3717 		{
   3718 			const int srcResourceNdx = (resultNdx % 2); // ABAB source
   3719 			msg << " from descriptor " << srcResourceNdx;
   3720 		}
   3721 
   3722 		msg << "\n";
   3723 	}
   3724 
   3725 	m_context.getTestContext().getLog()
   3726 		<< tcu::TestLog::Message
   3727 		<< msg.str()
   3728 		<< tcu::TestLog::EndMessage;
   3729 }
   3730 
   3731 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess (void)
   3732 {
   3733 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
   3734 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
   3735 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout));
   3736 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
   3737 
   3738 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
   3739 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
   3740 	const deUint32* const							dynamicOffsets		= DE_NULL;
   3741 	const int										numDynamicOffsets	= 0;
   3742 	const vk::VkBufferMemoryBarrier* const			preBarriers			= DE_NULL;
   3743 	const int										numPreBarriers		= 0;
   3744 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
   3745 	const int										numPostBarriers		= 1;
   3746 
   3747 	const ComputeCommand							compute				(m_vki,
   3748 																		 m_device,
   3749 																		 pipeline.getPipeline(),
   3750 																		 pipeline.getPipelineLayout(),
   3751 																		 tcu::UVec3(4, 1, 1),
   3752 																		 numDescriptorSets,	descriptorSets,
   3753 																		 numDynamicOffsets,	dynamicOffsets,
   3754 																		 numPreBarriers,	preBarriers,
   3755 																		 numPostBarriers,	postBarriers);
   3756 
   3757 	tcu::Vec4										results[4];
   3758 	bool											anyResultSet		= false;
   3759 	bool											allResultsOk		= true;
   3760 
   3761 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
   3762 	m_result.readResultContentsTo(&results);
   3763 
   3764 	// verify
   3765 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   3766 	{
   3767 		const tcu::Vec4	result				= results[resultNdx];
   3768 		const tcu::Vec4	reference			= m_images.fetchImageValue(resultNdx);
   3769 		const tcu::Vec4	conversionThreshold	= tcu::Vec4(1.0f / 255.0f);
   3770 
   3771 		if (result != tcu::Vec4(-1.0f))
   3772 			anyResultSet = true;
   3773 
   3774 		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
   3775 		{
   3776 			allResultsOk = false;
   3777 
   3778 			m_context.getTestContext().getLog()
   3779 				<< tcu::TestLog::Message
   3780 				<< "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
   3781 				<< tcu::TestLog::EndMessage;
   3782 		}
   3783 	}
   3784 
   3785 	// read back and verify
   3786 	if (allResultsOk)
   3787 		return tcu::TestStatus::pass("Pass");
   3788 	else if (anyResultSet)
   3789 		return tcu::TestStatus::fail("Invalid result values");
   3790 	else
   3791 	{
   3792 		m_context.getTestContext().getLog()
   3793 			<< tcu::TestLog::Message
   3794 			<< "Result buffer was not written to."
   3795 			<< tcu::TestLog::EndMessage;
   3796 		return tcu::TestStatus::fail("Result buffer was not written to");
   3797 	}
   3798 }
   3799 
   3800 class ImageSampleInstanceImages : private ImageInstanceImages
   3801 {
   3802 public:
   3803 										ImageSampleInstanceImages	(const vk::DeviceInterface&		vki,
   3804 																	 vk::VkDevice					device,
   3805 																	 deUint32						queueFamilyIndex,
   3806 																	 vk::VkQueue					queue,
   3807 																	 vk::Allocator&					allocator,
   3808 																	 vk::VkDescriptorType			descriptorType,
   3809 																	 ShaderInputInterface			shaderInterface,
   3810 																	 vk::VkImageViewType			viewType,
   3811 																	 deUint32						baseMipLevel,
   3812 																	 deUint32						baseArraySlice,
   3813 																	 bool							immutable);
   3814 
   3815 	static tcu::Vec4					getSamplePos				(vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx);
   3816 	tcu::Vec4							fetchSampleValue			(int samplePosNdx) const;
   3817 
   3818 	inline vk::VkImageView				getImageViewA				(void) const { return *m_imageViewA;	}
   3819 	inline vk::VkImageView				getImageViewB				(void) const { return *m_imageViewB;	}
   3820 	inline vk::VkSampler				getSamplerA					(void) const { return *m_samplerA;		}
   3821 	inline vk::VkSampler				getSamplerB					(void) const { return *m_samplerB;		}
   3822 	inline bool							isImmutable					(void) const { return m_isImmutable;	}
   3823 
   3824 private:
   3825 	static int							getNumImages				(vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface);
   3826 	static tcu::Sampler					createRefSampler			(bool isFirst);
   3827 	static vk::Move<vk::VkSampler>		createSampler				(const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format);
   3828 
   3829 	static tcu::Texture1DArrayView		getRef1DView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
   3830 	static tcu::Texture2DArrayView		getRef2DView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
   3831 	static tcu::Texture3DView			getRef3DView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
   3832 	static tcu::TextureCubeArrayView	getRefCubeView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
   3833 
   3834 	const vk::VkDescriptorType			m_descriptorType;
   3835 	const ShaderInputInterface			m_shaderInterface;
   3836 	const bool							m_isImmutable;
   3837 
   3838 	const tcu::Sampler					m_refSamplerA;
   3839 	const tcu::Sampler					m_refSamplerB;
   3840 	const vk::Unique<vk::VkSampler>		m_samplerA;
   3841 	const vk::Unique<vk::VkSampler>		m_samplerB;
   3842 };
   3843 
   3844 ImageSampleInstanceImages::ImageSampleInstanceImages (const vk::DeviceInterface&	vki,
   3845 													  vk::VkDevice					device,
   3846 													  deUint32						queueFamilyIndex,
   3847 													  vk::VkQueue					queue,
   3848 													  vk::Allocator&				allocator,
   3849 													  vk::VkDescriptorType			descriptorType,
   3850 													  ShaderInputInterface			shaderInterface,
   3851 													  vk::VkImageViewType			viewType,
   3852 													  deUint32						baseMipLevel,
   3853 													  deUint32						baseArraySlice,
   3854 													  bool							immutable)
   3855 	: ImageInstanceImages	(vki,
   3856 							 device,
   3857 							 queueFamilyIndex,
   3858 							 queue,
   3859 							 allocator,
   3860 							 descriptorType,
   3861 							 viewType,
   3862 							 getNumImages(descriptorType, shaderInterface),
   3863 							 baseMipLevel,
   3864 							 baseArraySlice)
   3865 	, m_descriptorType		(descriptorType)
   3866 	, m_shaderInterface		(shaderInterface)
   3867 	, m_isImmutable			(immutable)
   3868 	, m_refSamplerA			(createRefSampler(true))
   3869 	, m_refSamplerB			(createRefSampler(false))
   3870 	, m_samplerA			(createSampler(vki, device, m_refSamplerA, m_imageFormat))
   3871 	, m_samplerB			((getInterfaceNumResources(m_shaderInterface) == 1u)
   3872 								? vk::Move<vk::VkSampler>()
   3873 								: createSampler(vki, device, m_refSamplerB, m_imageFormat))
   3874 {
   3875 }
   3876 
   3877 tcu::Vec4 ImageSampleInstanceImages::getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx)
   3878 {
   3879 	DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
   3880 
   3881 	const deUint32	imageSize	= (deUint32)IMAGE_SIZE >> baseMipLevel;
   3882 	const deUint32	arraySize	= isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
   3883 
   3884 	// choose arbitrary values that are not ambiguous with NEAREST filtering
   3885 
   3886 	switch (viewType)
   3887 	{
   3888 		case vk::VK_IMAGE_VIEW_TYPE_1D:
   3889 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
   3890 		case vk::VK_IMAGE_VIEW_TYPE_2D:
   3891 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
   3892 		case vk::VK_IMAGE_VIEW_TYPE_3D:
   3893 		{
   3894 			const tcu::Vec3	coords[4]	=
   3895 			{
   3896 				tcu::Vec3(0.75f,
   3897 						  0.5f,
   3898 						  (float)(12u % imageSize) + 0.25f),
   3899 
   3900 				tcu::Vec3((float)(23u % imageSize) + 0.25f,
   3901 						  (float)(73u % imageSize) + 0.5f,
   3902 						  (float)(16u % imageSize) + 0.5f + (float)imageSize),
   3903 
   3904 				tcu::Vec3(-(float)(43u % imageSize) + 0.25f,
   3905 						  (float)(84u % imageSize) + 0.5f + (float)imageSize,
   3906 						  (float)(117u % imageSize) + 0.75f),
   3907 
   3908 				tcu::Vec3((float)imageSize + 0.5f,
   3909 						  (float)(75u % imageSize) + 0.25f,
   3910 						  (float)(83u % imageSize) + 0.25f + (float)imageSize),
   3911 			};
   3912 			const deUint32	slices[4]	=
   3913 			{
   3914 				0u % arraySize,
   3915 				4u % arraySize,
   3916 				9u % arraySize,
   3917 				2u % arraySize,
   3918 			};
   3919 
   3920 			if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
   3921 				return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
   3922 								 (float)slices[samplePosNdx],
   3923 								 0.0f,
   3924 								 0.0f);
   3925 			else if (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)
   3926 				return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
   3927 								 coords[samplePosNdx].y() / (float)imageSize,
   3928 								 (float)slices[samplePosNdx],
   3929 								 0.0f);
   3930 			else if (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)
   3931 				return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
   3932 								 coords[samplePosNdx].y() / (float)imageSize,
   3933 								 coords[samplePosNdx].z() / (float)imageSize,
   3934 								 0.0f);
   3935 			else
   3936 			{
   3937 				DE_FATAL("Impossible");
   3938 				return tcu::Vec4();
   3939 			}
   3940 		}
   3941 
   3942 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
   3943 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
   3944 		{
   3945 			// \note these values are in [0, texSize]*3 space for convenience
   3946 			const tcu::Vec3	coords[4]	=
   3947 			{
   3948 				tcu::Vec3(0.75f,
   3949 						  0.5f,
   3950 						  (float)imageSize),
   3951 
   3952 				tcu::Vec3((float)(13u % imageSize) + 0.25f,
   3953 						  0.0f,
   3954 						  (float)(16u % imageSize) + 0.5f),
   3955 
   3956 				tcu::Vec3(0.0f,
   3957 						  (float)(84u % imageSize) + 0.5f,
   3958 						  (float)(10u % imageSize) + 0.75f),
   3959 
   3960 				tcu::Vec3((float)imageSize,
   3961 						  (float)(75u % imageSize) + 0.25f,
   3962 						  (float)(83u % imageSize) + 0.75f),
   3963 			};
   3964 			const deUint32	slices[4]	=
   3965 			{
   3966 				1u % arraySize,
   3967 				2u % arraySize,
   3968 				9u % arraySize,
   3969 				5u % arraySize,
   3970 			};
   3971 
   3972 			DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
   3973 			DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
   3974 			DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
   3975 
   3976 			// map to [-1, 1]*3 space
   3977 			return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
   3978 							 coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
   3979 							 coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f,
   3980 							 (float)slices[samplePosNdx]);
   3981 		}
   3982 
   3983 		default:
   3984 			DE_FATAL("Impossible");
   3985 			return tcu::Vec4();
   3986 	}
   3987 }
   3988 
   3989 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue (int samplePosNdx) const
   3990 {
   3991 	DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
   3992 
   3993 	// texture order is ABAB
   3994 	const bool									isSamplerCase	= (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
   3995 	const tcu::TextureLevelPyramid&				sampleSrcA		= m_sourceImageA;
   3996 	const tcu::TextureLevelPyramid&				sampleSrcB		= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
   3997 	const tcu::TextureLevelPyramid&				sampleSrc		= (isSamplerCase) ? (sampleSrcA) : ((samplePosNdx % 2) == 0) ? (sampleSrcA) : (sampleSrcB);
   3998 
   3999 	// sampler order is ABAB
   4000 	const tcu::Sampler&							samplerA		= m_refSamplerA;
   4001 	const tcu::Sampler&							samplerB		= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_refSamplerA) : (m_refSamplerB);
   4002 	const tcu::Sampler&							sampler			= ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
   4003 
   4004 	const tcu::Vec4								samplePos		= getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
   4005 	const float									lod				= 0.0f;
   4006 	std::vector<tcu::ConstPixelBufferAccess>	levelStorage;
   4007 
   4008 	switch (m_viewType)
   4009 	{
   4010 		case vk::VK_IMAGE_VIEW_TYPE_1D:
   4011 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:	return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), lod);
   4012 		case vk::VK_IMAGE_VIEW_TYPE_2D:
   4013 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:	return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
   4014 		case vk::VK_IMAGE_VIEW_TYPE_3D:			return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
   4015 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
   4016 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:	return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod);
   4017 
   4018 		default:
   4019 		{
   4020 			DE_FATAL("Impossible");
   4021 			return tcu::Vec4();
   4022 		}
   4023 	}
   4024 }
   4025 
   4026 int ImageSampleInstanceImages::getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface)
   4027 {
   4028 	// If we are testing separate samplers, just one image is enough
   4029 	if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4030 		return 1;
   4031 	else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4032 	{
   4033 		// combined: numImages == numSamplers
   4034 		return getInterfaceNumResources(shaderInterface);
   4035 	}
   4036 	else
   4037 	{
   4038 		DE_FATAL("Impossible");
   4039 		return 0;
   4040 	}
   4041 }
   4042 
   4043 tcu::Sampler ImageSampleInstanceImages::createRefSampler (bool isFirst)
   4044 {
   4045 	if (isFirst)
   4046 	{
   4047 		// linear, wrapping
   4048 		return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
   4049 	}
   4050 	else
   4051 	{
   4052 		// nearest, clamping
   4053 		return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
   4054 	}
   4055 }
   4056 
   4057 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format)
   4058 {
   4059 	const vk::VkSamplerCreateInfo	createInfo		= vk::mapSampler(sampler, format);
   4060 
   4061 	return vk::createSampler(vki, device, &createInfo);
   4062 }
   4063 
   4064 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
   4065 {
   4066 	DE_ASSERT(levelStorage->empty());
   4067 
   4068 	const deUint32 numSlices = (deUint32)source.getLevel(0).getHeight();
   4069 	const deUint32 numLevels = (deUint32)source.getNumLevels();
   4070 
   4071 	// cut pyramid from baseMipLevel
   4072 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
   4073 	{
   4074 		// cut levels from baseArraySlice
   4075 		const tcu::ConstPixelBufferAccess wholeLevel	= source.getLevel(level);
   4076 		const tcu::ConstPixelBufferAccess cutLevel		= tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
   4077 		levelStorage->push_back(cutLevel);
   4078 	}
   4079 
   4080 	return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
   4081 }
   4082 
   4083 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
   4084 {
   4085 	DE_ASSERT(levelStorage->empty());
   4086 
   4087 	const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth();
   4088 	const deUint32 numLevels = (deUint32)source.getNumLevels();
   4089 
   4090 	// cut pyramid from baseMipLevel
   4091 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
   4092 	{
   4093 		// cut levels from baseArraySlice
   4094 		const tcu::ConstPixelBufferAccess wholeLevel	= source.getLevel(level);
   4095 		const tcu::ConstPixelBufferAccess cutLevel		= tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(), numSlices - baseArraySlice);
   4096 		levelStorage->push_back(cutLevel);
   4097 	}
   4098 
   4099 	return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
   4100 }
   4101 
   4102 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
   4103 {
   4104 	DE_ASSERT(levelStorage->empty());
   4105 	DE_ASSERT(baseArraySlice == 0);
   4106 	DE_UNREF(baseArraySlice);
   4107 
   4108 	const deUint32 numLevels = (deUint32)source.getNumLevels();
   4109 
   4110 	// cut pyramid from baseMipLevel
   4111 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
   4112 		levelStorage->push_back(source.getLevel(level));
   4113 
   4114 	return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
   4115 }
   4116 
   4117 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
   4118 {
   4119 	DE_ASSERT(levelStorage->empty());
   4120 
   4121 	const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth() / 6;
   4122 	const deUint32 numLevels = (deUint32)source.getNumLevels();
   4123 
   4124 	// cut pyramid from baseMipLevel
   4125 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
   4126 	{
   4127 		// cut levels from baseArraySlice
   4128 		const tcu::ConstPixelBufferAccess wholeLevel	= source.getLevel(level);
   4129 		const tcu::ConstPixelBufferAccess cutLevel		= tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(), (numSlices - baseArraySlice) * 6);
   4130 		levelStorage->push_back(cutLevel);
   4131 	}
   4132 
   4133 	return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
   4134 }
   4135 
   4136 class ImageSampleRenderInstance : public SingleCmdRenderInstance
   4137 {
   4138 public:
   4139 													ImageSampleRenderInstance		(vkt::Context&			context,
   4140 																					 bool					isPrimaryCmdBuf,
   4141 																					 vk::VkDescriptorType	descriptorType,
   4142 																					 vk::VkShaderStageFlags	stageFlags,
   4143 																					 ShaderInputInterface	shaderInterface,
   4144 																					 vk::VkImageViewType	viewType,
   4145 																					 deUint32				baseMipLevel,
   4146 																					 deUint32				baseArraySlice,
   4147 																					 bool					isImmutable);
   4148 
   4149 private:
   4150 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout		(const vk::DeviceInterface&			vki,
   4151 																					 vk::VkDevice						device,
   4152 																					 vk::VkDescriptorType				descriptorType,
   4153 																					 ShaderInputInterface				shaderInterface,
   4154 																					 vk::VkShaderStageFlags				stageFlags,
   4155 																					 const ImageSampleInstanceImages&	images);
   4156 
   4157 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout			(const vk::DeviceInterface&	vki,
   4158 																					 vk::VkDevice				device,
   4159 																					 vk::VkDescriptorSetLayout	descriptorSetLayout);
   4160 
   4161 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool			(const vk::DeviceInterface&	vki,
   4162 																					 vk::VkDevice				device,
   4163 																					 vk::VkDescriptorType		descriptorType,
   4164 																					 ShaderInputInterface		shaderInterface);
   4165 
   4166 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet				(const vk::DeviceInterface&			vki,
   4167 																					 vk::VkDevice						device,
   4168 																					 vk::VkDescriptorType				descriptorType,
   4169 																					 ShaderInputInterface				shaderInterface,
   4170 																					 vk::VkDescriptorSetLayout			layout,
   4171 																					 vk::VkDescriptorPool				pool,
   4172 																					 bool								isImmutable,
   4173 																					 const ImageSampleInstanceImages&	images);
   4174 
   4175 	static void										writeSamplerDescriptorSet		(const vk::DeviceInterface&			vki,
   4176 																					 vk::VkDevice						device,
   4177 																					 ShaderInputInterface				shaderInterface,
   4178 																					 bool								isImmutable,
   4179 																					 const ImageSampleInstanceImages&	images,
   4180 																					 vk::VkDescriptorSet				descriptorSet);
   4181 
   4182 	static void										writeImageSamplerDescriptorSet	(const vk::DeviceInterface&			vki,
   4183 																					 vk::VkDevice						device,
   4184 																					 ShaderInputInterface				shaderInterface,
   4185 																					 bool								isImmutable,
   4186 																					 const ImageSampleInstanceImages&	images,
   4187 																					 vk::VkDescriptorSet				descriptorSet);
   4188 
   4189 	void											logTestPlan						(void) const;
   4190 	vk::VkPipelineLayout							getPipelineLayout				(void) const;
   4191 	void											writeDrawCmdBuffer				(vk::VkCommandBuffer cmd) const;
   4192 	tcu::TestStatus									verifyResultImage				(const tcu::ConstPixelBufferAccess& result) const;
   4193 
   4194 	enum
   4195 	{
   4196 		RENDER_SIZE = 128,
   4197 	};
   4198 
   4199 	const vk::VkDescriptorType						m_descriptorType;
   4200 	const vk::VkShaderStageFlags					m_stageFlags;
   4201 	const ShaderInputInterface						m_shaderInterface;
   4202 	const vk::VkImageViewType						m_viewType;
   4203 	const deUint32									m_baseMipLevel;
   4204 	const deUint32									m_baseArraySlice;
   4205 
   4206 	const ImageSampleInstanceImages					m_images;
   4207 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
   4208 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
   4209 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
   4210 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
   4211 };
   4212 
   4213 ImageSampleRenderInstance::ImageSampleRenderInstance (vkt::Context&				context,
   4214 													  bool						isPrimaryCmdBuf,
   4215 													  vk::VkDescriptorType		descriptorType,
   4216 													  vk::VkShaderStageFlags	stageFlags,
   4217 													  ShaderInputInterface		shaderInterface,
   4218 													  vk::VkImageViewType		viewType,
   4219 													  deUint32					baseMipLevel,
   4220 													  deUint32					baseArraySlice,
   4221 													  bool						isImmutable)
   4222 	: SingleCmdRenderInstance	(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
   4223 	, m_descriptorType			(descriptorType)
   4224 	, m_stageFlags				(stageFlags)
   4225 	, m_shaderInterface			(shaderInterface)
   4226 	, m_viewType				(viewType)
   4227 	, m_baseMipLevel			(baseMipLevel)
   4228 	, m_baseArraySlice			(baseArraySlice)
   4229 	, m_images					(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutable)
   4230 	, m_descriptorSetLayout		(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_images))
   4231 	, m_pipelineLayout			(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
   4232 	, m_descriptorPool			(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
   4233 	, m_descriptorSet			(createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, isImmutable, m_images))
   4234 {
   4235 }
   4236 
   4237 vk::Move<vk::VkDescriptorSetLayout> ImageSampleRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&		vki,
   4238 																						  vk::VkDevice						device,
   4239 																						  vk::VkDescriptorType				descriptorType,
   4240 																						  ShaderInputInterface				shaderInterface,
   4241 																						  vk::VkShaderStageFlags			stageFlags,
   4242 																						  const ImageSampleInstanceImages&	images)
   4243 {
   4244 	const vk::VkSampler				samplers[2] =
   4245 	{
   4246 		images.getSamplerA(),
   4247 		images.getSamplerB(),
   4248 	};
   4249 
   4250 	vk::DescriptorSetLayoutBuilder	builder;
   4251 	const bool						addSeparateImage	= descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
   4252 
   4253 	// (combined)samplers follow
   4254 	switch (shaderInterface)
   4255 	{
   4256 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   4257 			if (addSeparateImage)
   4258 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
   4259 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
   4260 			break;
   4261 
   4262 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   4263 			if (addSeparateImage)
   4264 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
   4265 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
   4266 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
   4267 			break;
   4268 
   4269 		case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
   4270 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
   4271 			if (addSeparateImage)
   4272 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
   4273 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
   4274 			break;
   4275 
   4276 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   4277 			if (addSeparateImage)
   4278 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
   4279 			builder.addArraySamplerBinding(descriptorType, 2u, stageFlags, (images.isImmutable()) ? (samplers) : (DE_NULL));
   4280 			break;
   4281 
   4282 		default:
   4283 			DE_FATAL("Impossible");
   4284 	}
   4285 
   4286 	return builder.build(vki, device);
   4287 }
   4288 
   4289 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
   4290 																				vk::VkDevice				device,
   4291 																				vk::VkDescriptorSetLayout	descriptorSetLayout)
   4292 {
   4293 	const vk::VkPipelineLayoutCreateInfo createInfo =
   4294 	{
   4295 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
   4296 		DE_NULL,
   4297 		(vk::VkPipelineLayoutCreateFlags)0,
   4298 		1,						// descriptorSetCount
   4299 		&descriptorSetLayout,	// pSetLayouts
   4300 		0u,						// pushConstantRangeCount
   4301 		DE_NULL,				// pPushConstantRanges
   4302 	};
   4303 	return vk::createPipelineLayout(vki, device, &createInfo);
   4304 }
   4305 
   4306 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
   4307 																				vk::VkDevice				device,
   4308 																				vk::VkDescriptorType		descriptorType,
   4309 																				ShaderInputInterface		shaderInterface)
   4310 {
   4311 	vk::DescriptorPoolBuilder builder;
   4312 
   4313 	if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4314 	{
   4315 		// separate samplers need image to sample
   4316 		builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
   4317 
   4318 		// also need sample to use, indifferent of whether immutable or not
   4319 		builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER, getInterfaceNumResources(shaderInterface));
   4320 	}
   4321 	else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4322 	{
   4323 		// combined image samplers
   4324 		builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, getInterfaceNumResources(shaderInterface));
   4325 	}
   4326 	else
   4327 		DE_FATAL("Impossible");
   4328 
   4329 	return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   4330 }
   4331 
   4332 vk::Move<vk::VkDescriptorSet> ImageSampleRenderInstance::createDescriptorSet (const vk::DeviceInterface&		vki,
   4333 																			  vk::VkDevice						device,
   4334 																			  vk::VkDescriptorType				descriptorType,
   4335 																			  ShaderInputInterface				shaderInterface,
   4336 																			  vk::VkDescriptorSetLayout			layout,
   4337 																			  vk::VkDescriptorPool				pool,
   4338 																			  bool								isImmutable,
   4339 																			  const ImageSampleInstanceImages&	images)
   4340 {
   4341 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
   4342 	{
   4343 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   4344 		DE_NULL,
   4345 		pool,
   4346 		1u,
   4347 		&layout
   4348 	};
   4349 
   4350 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(vki, device, &allocInfo);
   4351 
   4352 	if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4353 		writeSamplerDescriptorSet(vki, device,  shaderInterface, isImmutable, images, *descriptorSet);
   4354 	else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4355 		writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
   4356 	else
   4357 		DE_FATAL("Impossible");
   4358 
   4359 	return descriptorSet;
   4360 }
   4361 
   4362 void ImageSampleRenderInstance::writeSamplerDescriptorSet (const vk::DeviceInterface&		vki,
   4363 														   vk::VkDevice						device,
   4364 														   ShaderInputInterface				shaderInterface,
   4365 														   bool								isImmutable,
   4366 														   const ImageSampleInstanceImages&	images,
   4367 														   vk::VkDescriptorSet				descriptorSet)
   4368 {
   4369 	const vk::VkDescriptorImageInfo		imageInfo			= makeDescriptorImageInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
   4370 	const vk::VkDescriptorImageInfo		samplersInfos[2]	=
   4371 	{
   4372 		makeDescriptorImageInfo(images.getSamplerA()),
   4373 		makeDescriptorImageInfo(images.getSamplerB()),
   4374 	};
   4375 
   4376 	vk::DescriptorSetUpdateBuilder		builder;
   4377 	const deUint32						samplerLocation		= shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
   4378 
   4379 	// stand alone texture
   4380 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
   4381 
   4382 	// samplers
   4383 	if (!isImmutable)
   4384 	{
   4385 		switch (shaderInterface)
   4386 		{
   4387 			case SHADER_INPUT_SINGLE_DESCRIPTOR:
   4388 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
   4389 				break;
   4390 
   4391 			case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   4392 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
   4393 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
   4394 				break;
   4395 
   4396 			case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
   4397 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
   4398 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
   4399 				break;
   4400 
   4401 			case SHADER_INPUT_DESCRIPTOR_ARRAY:
   4402 				builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
   4403 				break;
   4404 
   4405 			default:
   4406 				DE_FATAL("Impossible");
   4407 		}
   4408 	}
   4409 
   4410 	builder.update(vki, device);
   4411 }
   4412 
   4413 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet (const vk::DeviceInterface&			vki,
   4414 																vk::VkDevice						device,
   4415 																ShaderInputInterface				shaderInterface,
   4416 																bool								isImmutable,
   4417 																const ImageSampleInstanceImages&	images,
   4418 																vk::VkDescriptorSet					descriptorSet)
   4419 {
   4420 	const vk::VkSampler					samplers[2]			=
   4421 	{
   4422 		(isImmutable) ? (0) : (images.getSamplerA()),
   4423 		(isImmutable) ? (0) : (images.getSamplerB()),
   4424 	};
   4425 	const vk::VkDescriptorImageInfo		imageSamplers[2]	=
   4426 	{
   4427 		vk::makeDescriptorImageInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
   4428 		vk::makeDescriptorImageInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
   4429 	};
   4430 
   4431 	vk::DescriptorSetUpdateBuilder		builder;
   4432 
   4433 	// combined image samplers
   4434 	switch (shaderInterface)
   4435 	{
   4436 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   4437 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
   4438 			break;
   4439 
   4440 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   4441 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
   4442 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
   4443 			break;
   4444 
   4445 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   4446 			builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
   4447 			break;
   4448 
   4449 		default:
   4450 			DE_FATAL("Impossible");
   4451 	}
   4452 
   4453 	builder.update(vki, device);
   4454 }
   4455 
   4456 void ImageSampleRenderInstance::logTestPlan (void) const
   4457 {
   4458 	std::ostringstream msg;
   4459 
   4460 	msg << "Rendering 2x2 grid.\n";
   4461 
   4462 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4463 	{
   4464 		msg << "Single descriptor set. Descriptor set contains "
   4465 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   4466 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   4467 				(m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
   4468 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   4469 			    (const char*)DE_NULL)
   4470 			<< " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
   4471 	}
   4472 	else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4473 	{
   4474 		msg << "Single descriptor set. Descriptor set contains "
   4475 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   4476 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   4477 				(m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
   4478 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   4479 			    (const char*)DE_NULL)
   4480 			<< " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
   4481 	}
   4482 	else
   4483 		DE_FATAL("Impossible");
   4484 
   4485 	msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
   4486 
   4487 	if (m_baseMipLevel)
   4488 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
   4489 	if (m_baseArraySlice)
   4490 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
   4491 
   4492 	if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
   4493 		msg << "Sampler mode is LINEAR, with WRAP\n";
   4494 	else
   4495 		msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
   4496 
   4497 	if (m_stageFlags == 0u)
   4498 	{
   4499 		msg << "Descriptors are not accessed in any shader stage.\n";
   4500 	}
   4501 	else
   4502 	{
   4503 		msg << "Color in each cell is fetched using the descriptor(s):\n";
   4504 
   4505 		for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   4506 		{
   4507 			msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
   4508 
   4509 			if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
   4510 			{
   4511 				const int srcResourceNdx = (resultNdx % 2); // ABAB source
   4512 
   4513 				if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4514 					msg << " using sampler " << srcResourceNdx;
   4515 				else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4516 					msg << " from combined image sampler " << srcResourceNdx;
   4517 				else
   4518 					DE_FATAL("Impossible");
   4519 			}
   4520 			msg << "\n";
   4521 		}
   4522 
   4523 		msg << "Descriptors are accessed in {"
   4524 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
   4525 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
   4526 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
   4527 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
   4528 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
   4529 			<< " } stages.";
   4530 	}
   4531 
   4532 	m_context.getTestContext().getLog()
   4533 		<< tcu::TestLog::Message
   4534 		<< msg.str()
   4535 		<< tcu::TestLog::EndMessage;
   4536 }
   4537 
   4538 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout (void) const
   4539 {
   4540 	return *m_pipelineLayout;
   4541 }
   4542 
   4543 void ImageSampleRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
   4544 {
   4545 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
   4546 	m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
   4547 }
   4548 
   4549 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
   4550 {
   4551 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
   4552 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
   4553 	const bool			doFetch		= (m_stageFlags != 0u); // no active stages? Then don't fetch
   4554 	const tcu::Vec4		sample0		= (!doFetch) ? (yellow)	: (m_images.fetchSampleValue(0));
   4555 	const tcu::Vec4		sample1		= (!doFetch) ? (green)	: (m_images.fetchSampleValue(1));
   4556 	const tcu::Vec4		sample2		= (!doFetch) ? (green)	: (m_images.fetchSampleValue(2));
   4557 	const tcu::Vec4		sample3		= (!doFetch) ? (yellow)	: (m_images.fetchSampleValue(3));
   4558 	const tcu::RGBA		threshold	= tcu::RGBA(8, 8, 8, 8); // source image is high-frequency so the threshold is quite large to tolerate sampling errors
   4559 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
   4560 
   4561 	drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
   4562 
   4563 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, threshold, tcu::COMPARE_LOG_RESULT))
   4564 		return tcu::TestStatus::fail("Image verification failed");
   4565 	else
   4566 		return tcu::TestStatus::pass("Pass");
   4567 }
   4568 
   4569 class ImageSampleComputeInstance : public vkt::TestInstance
   4570 {
   4571 public:
   4572 											ImageSampleComputeInstance		(vkt::Context&			context,
   4573 																			 vk::VkDescriptorType	descriptorType,
   4574 																			 ShaderInputInterface	shaderInterface,
   4575 																			 vk::VkImageViewType	viewType,
   4576 																			 deUint32				baseMipLevel,
   4577 																			 deUint32				baseArraySlice,
   4578 																			 bool					isImmutableSampler);
   4579 
   4580 private:
   4581 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout		(void) const;
   4582 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool			(void) const;
   4583 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet				(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
   4584 	void									writeImageSamplerDescriptorSet	(vk::VkDescriptorSet descriptorSet) const;
   4585 	void									writeSamplerDescriptorSet		(vk::VkDescriptorSet descriptorSet) const;
   4586 
   4587 	tcu::TestStatus							iterate							(void);
   4588 	void									logTestPlan						(void) const;
   4589 	tcu::TestStatus							testResourceAccess				(void);
   4590 
   4591 	const vk::VkDescriptorType				m_descriptorType;
   4592 	const ShaderInputInterface				m_shaderInterface;
   4593 	const vk::VkImageViewType				m_viewType;
   4594 	const deUint32							m_baseMipLevel;
   4595 	const deUint32							m_baseArraySlice;
   4596 	const bool								m_isImmutableSampler;
   4597 
   4598 	const vk::DeviceInterface&				m_vki;
   4599 	const vk::VkDevice						m_device;
   4600 	const vk::VkQueue						m_queue;
   4601 	const deUint32							m_queueFamilyIndex;
   4602 	vk::Allocator&							m_allocator;
   4603 
   4604 	const ComputeInstanceResultBuffer		m_result;
   4605 	const ImageSampleInstanceImages			m_images;
   4606 };
   4607 
   4608 ImageSampleComputeInstance::ImageSampleComputeInstance (Context&				context,
   4609 														vk::VkDescriptorType	descriptorType,
   4610 														ShaderInputInterface	shaderInterface,
   4611 														vk::VkImageViewType		viewType,
   4612 														deUint32				baseMipLevel,
   4613 														deUint32				baseArraySlice,
   4614 														bool					isImmutableSampler)
   4615 	: vkt::TestInstance		(context)
   4616 	, m_descriptorType		(descriptorType)
   4617 	, m_shaderInterface		(shaderInterface)
   4618 	, m_viewType			(viewType)
   4619 	, m_baseMipLevel		(baseMipLevel)
   4620 	, m_baseArraySlice		(baseArraySlice)
   4621 	, m_isImmutableSampler	(isImmutableSampler)
   4622 	, m_vki					(context.getDeviceInterface())
   4623 	, m_device				(context.getDevice())
   4624 	, m_queue				(context.getUniversalQueue())
   4625 	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
   4626 	, m_allocator			(context.getDefaultAllocator())
   4627 	, m_result				(m_vki, m_device, m_allocator)
   4628 	, m_images				(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
   4629 {
   4630 }
   4631 
   4632 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout (void) const
   4633 {
   4634 	const vk::VkSampler				samplers[2] =
   4635 	{
   4636 		m_images.getSamplerA(),
   4637 		m_images.getSamplerB(),
   4638 	};
   4639 
   4640 	vk::DescriptorSetLayoutBuilder	builder;
   4641 
   4642 	// result buffer
   4643 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   4644 
   4645 	// with samplers, separate texture at binding 0
   4646 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4647 		builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   4648 
   4649 	// (combined)samplers follow
   4650 	switch (m_shaderInterface)
   4651 	{
   4652 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   4653 			builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
   4654 			break;
   4655 
   4656 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   4657 			builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
   4658 			builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
   4659 			break;
   4660 
   4661 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   4662 			builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (samplers) : (DE_NULL));
   4663 			break;
   4664 
   4665 		default:
   4666 			DE_FATAL("Impossible");
   4667 	};
   4668 
   4669 	return builder.build(m_vki, m_device);
   4670 }
   4671 
   4672 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool (void) const
   4673 {
   4674 	vk::DescriptorPoolBuilder builder;
   4675 
   4676 	builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
   4677 	builder.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface));
   4678 
   4679 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4680 		builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
   4681 
   4682 	return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   4683 }
   4684 
   4685 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
   4686 {
   4687 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
   4688 	{
   4689 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   4690 		DE_NULL,
   4691 		pool,
   4692 		1u,
   4693 		&layout
   4694 	};
   4695 
   4696 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(m_vki, m_device, &allocInfo);
   4697 
   4698 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4699 		writeSamplerDescriptorSet(*descriptorSet);
   4700 	else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4701 		writeImageSamplerDescriptorSet(*descriptorSet);
   4702 	else
   4703 		DE_FATAL("Impossible");
   4704 
   4705 	return descriptorSet;
   4706 }
   4707 
   4708 void ImageSampleComputeInstance::writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
   4709 {
   4710 	const vk::VkDescriptorBufferInfo	resultInfo			= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
   4711 	const vk::VkDescriptorImageInfo		imageInfo			= makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
   4712 	const vk::VkDescriptorImageInfo		samplersInfos[2]	=
   4713 	{
   4714 		makeDescriptorImageInfo(m_images.getSamplerA()),
   4715 		makeDescriptorImageInfo(m_images.getSamplerB()),
   4716 	};
   4717 
   4718 	vk::DescriptorSetUpdateBuilder		builder;
   4719 
   4720 	// result
   4721 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
   4722 
   4723 	// stand alone texture
   4724 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
   4725 
   4726 	// samplers
   4727 	if (!m_isImmutableSampler)
   4728 	{
   4729 		switch (m_shaderInterface)
   4730 		{
   4731 			case SHADER_INPUT_SINGLE_DESCRIPTOR:
   4732 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
   4733 				break;
   4734 
   4735 			case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   4736 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
   4737 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(3u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
   4738 				break;
   4739 
   4740 			case SHADER_INPUT_DESCRIPTOR_ARRAY:
   4741 				builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
   4742 				break;
   4743 
   4744 			default:
   4745 				DE_FATAL("Impossible");
   4746 		}
   4747 	}
   4748 
   4749 	builder.update(m_vki, m_device);
   4750 }
   4751 
   4752 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
   4753 {
   4754 	const vk::VkDescriptorBufferInfo	resultInfo			= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
   4755 	const vk::VkSampler					samplers[2]			=
   4756 	{
   4757 		(m_isImmutableSampler) ? (0) : (m_images.getSamplerA()),
   4758 		(m_isImmutableSampler) ? (0) : (m_images.getSamplerB()),
   4759 	};
   4760 	const vk::VkDescriptorImageInfo		imageSamplers[2]	=
   4761 	{
   4762 		makeDescriptorImageInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
   4763 		makeDescriptorImageInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
   4764 	};
   4765 
   4766 	vk::DescriptorSetUpdateBuilder		builder;
   4767 
   4768 	// result
   4769 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
   4770 
   4771 	// combined image samplers
   4772 	switch (m_shaderInterface)
   4773 	{
   4774 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   4775 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
   4776 			break;
   4777 
   4778 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   4779 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
   4780 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
   4781 			break;
   4782 
   4783 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   4784 			builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
   4785 			break;
   4786 
   4787 		default:
   4788 			DE_FATAL("Impossible");
   4789 	}
   4790 
   4791 	builder.update(m_vki, m_device);
   4792 }
   4793 
   4794 tcu::TestStatus ImageSampleComputeInstance::iterate (void)
   4795 {
   4796 	logTestPlan();
   4797 	return testResourceAccess();
   4798 }
   4799 
   4800 void ImageSampleComputeInstance::logTestPlan (void) const
   4801 {
   4802 	std::ostringstream msg;
   4803 
   4804 	msg << "Accessing resource in a compute program.\n";
   4805 
   4806 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4807 	{
   4808 		msg << "Single descriptor set. Descriptor set contains "
   4809 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   4810 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   4811 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   4812 			    (const char*)DE_NULL)
   4813 			<< " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
   4814 	}
   4815 	else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4816 	{
   4817 		msg << "Single descriptor set. Descriptor set contains "
   4818 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   4819 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   4820 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   4821 			    (const char*)DE_NULL)
   4822 			<< " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
   4823 	}
   4824 	else
   4825 		DE_FATAL("Impossible");
   4826 
   4827 	msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
   4828 
   4829 	if (m_baseMipLevel)
   4830 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
   4831 	if (m_baseArraySlice)
   4832 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
   4833 
   4834 	if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
   4835 		msg << "Sampler mode is LINEAR, with WRAP\n";
   4836 	else
   4837 		msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
   4838 
   4839 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   4840 	{
   4841 		msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
   4842 
   4843 		if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
   4844 		{
   4845 			const int srcResourceNdx = (resultNdx % 2); // ABAB source
   4846 
   4847 			if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   4848 				msg << " using sampler " << srcResourceNdx;
   4849 			else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   4850 				msg << " from combined image sampler " << srcResourceNdx;
   4851 			else
   4852 				DE_FATAL("Impossible");
   4853 		}
   4854 		msg << "\n";
   4855 	}
   4856 
   4857 	m_context.getTestContext().getLog()
   4858 		<< tcu::TestLog::Message
   4859 		<< msg.str()
   4860 		<< tcu::TestLog::EndMessage;
   4861 }
   4862 
   4863 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess (void)
   4864 {
   4865 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
   4866 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
   4867 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout));
   4868 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
   4869 
   4870 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
   4871 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
   4872 	const deUint32* const							dynamicOffsets		= DE_NULL;
   4873 	const int										numDynamicOffsets	= 0;
   4874 	const vk::VkBufferMemoryBarrier* const			preBarriers			= DE_NULL;
   4875 	const int										numPreBarriers		= 0;
   4876 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
   4877 	const int										numPostBarriers		= 1;
   4878 
   4879 	const ComputeCommand							compute				(m_vki,
   4880 																		 m_device,
   4881 																		 pipeline.getPipeline(),
   4882 																		 pipeline.getPipelineLayout(),
   4883 																		 tcu::UVec3(4, 1, 1),
   4884 																		 numDescriptorSets,	descriptorSets,
   4885 																		 numDynamicOffsets,	dynamicOffsets,
   4886 																		 numPreBarriers,	preBarriers,
   4887 																		 numPostBarriers,	postBarriers);
   4888 
   4889 	tcu::Vec4										results[4];
   4890 	bool											anyResultSet		= false;
   4891 	bool											allResultsOk		= true;
   4892 
   4893 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
   4894 	m_result.readResultContentsTo(&results);
   4895 
   4896 	// verify
   4897 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   4898 	{
   4899 		const tcu::Vec4	result				= results[resultNdx];
   4900 		const tcu::Vec4	reference			= m_images.fetchSampleValue(resultNdx);
   4901 
   4902 		// source image is high-frequency so the threshold is quite large to tolerate sampling errors
   4903 		const tcu::Vec4	samplingThreshold	= tcu::Vec4(8.0f / 255.0f);
   4904 
   4905 		if (result != tcu::Vec4(-1.0f))
   4906 			anyResultSet = true;
   4907 
   4908 		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
   4909 		{
   4910 			allResultsOk = false;
   4911 
   4912 			m_context.getTestContext().getLog()
   4913 				<< tcu::TestLog::Message
   4914 				<< "Test sample " << resultNdx << ":\n"
   4915 				<< "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx) << "\n"
   4916 				<< "\tError expected " << reference << ", got " << result
   4917 				<< tcu::TestLog::EndMessage;
   4918 		}
   4919 	}
   4920 
   4921 	// read back and verify
   4922 	if (allResultsOk)
   4923 		return tcu::TestStatus::pass("Pass");
   4924 	else if (anyResultSet)
   4925 		return tcu::TestStatus::fail("Invalid result values");
   4926 	else
   4927 	{
   4928 		m_context.getTestContext().getLog()
   4929 			<< tcu::TestLog::Message
   4930 			<< "Result buffer was not written to."
   4931 			<< tcu::TestLog::EndMessage;
   4932 		return tcu::TestStatus::fail("Result buffer was not written to");
   4933 	}
   4934 }
   4935 
   4936 class ImageDescriptorCase : public QuadrantRendederCase
   4937 {
   4938 public:
   4939 	enum
   4940 	{
   4941 		FLAG_BASE_MIP	= (1u << 1u),
   4942 		FLAG_BASE_SLICE	= (1u << 2u),
   4943 	};
   4944 	// enum continues where resource flags ends
   4945 	DE_STATIC_ASSERT((deUint32)FLAG_BASE_MIP == (deUint32)RESOURCE_FLAG_LAST);
   4946 
   4947 								ImageDescriptorCase			(tcu::TestContext&		testCtx,
   4948 															 const char*			name,
   4949 															 const char*			description,
   4950 															 bool					isPrimaryCmdBuf,
   4951 															 vk::VkDescriptorType	descriptorType,
   4952 															 vk::VkShaderStageFlags	exitingStages,
   4953 															 vk::VkShaderStageFlags	activeStages,
   4954 															 ShaderInputInterface	shaderInterface,
   4955 															 vk::VkImageViewType	viewType,
   4956 															 deUint32				flags);
   4957 
   4958 private:
   4959 	std::string					genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const;
   4960 	std::string					genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
   4961 	std::string					genFetchCoordStr			(int fetchPosNdx) const;
   4962 	std::string					genSampleCoordStr			(int samplePosNdx) const;
   4963 	std::string					genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const;
   4964 	std::string					genNoAccessSource			(void) const;
   4965 
   4966 	vkt::TestInstance*			createInstance				(vkt::Context& context) const;
   4967 
   4968 private:
   4969 	const bool					m_isPrimaryCmdBuf;
   4970 	const vk::VkDescriptorType	m_descriptorType;
   4971 	const ShaderInputInterface	m_shaderInterface;
   4972 	const vk::VkImageViewType	m_viewType;
   4973 	const deUint32				m_baseMipLevel;
   4974 	const deUint32				m_baseArraySlice;
   4975 	const bool					m_isImmutableSampler;
   4976 };
   4977 
   4978 ImageDescriptorCase::ImageDescriptorCase (tcu::TestContext&			testCtx,
   4979 										  const char*				name,
   4980 										  const char*				description,
   4981 										  bool						isPrimaryCmdBuf,
   4982 										  vk::VkDescriptorType		descriptorType,
   4983 										  vk::VkShaderStageFlags	exitingStages,
   4984 										  vk::VkShaderStageFlags	activeStages,
   4985 										  ShaderInputInterface		shaderInterface,
   4986 										  vk::VkImageViewType		viewType,
   4987 										  deUint32					flags)
   4988 	: QuadrantRendederCase	(testCtx, name, description,
   4989 							 // \note 1D textures are not supported in ES
   4990 							 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? glu::GLSL_VERSION_440 : glu::GLSL_VERSION_310_ES,
   4991 							 exitingStages, activeStages)
   4992 	, m_isPrimaryCmdBuf		(isPrimaryCmdBuf)
   4993 	, m_descriptorType		(descriptorType)
   4994 	, m_shaderInterface		(shaderInterface)
   4995 	, m_viewType			(viewType)
   4996 	, m_baseMipLevel		(((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
   4997 	, m_baseArraySlice		(((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
   4998 	, m_isImmutableSampler	((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
   4999 {
   5000 }
   5001 
   5002 std::string ImageDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
   5003 {
   5004 	DE_UNREF(stage);
   5005 
   5006 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
   5007 		return "#extension GL_OES_texture_cube_map_array : require\n";
   5008 	else
   5009 		return "";
   5010 }
   5011 
   5012 std::string ImageDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
   5013 {
   5014 	DE_UNREF(stage);
   5015 
   5016 	// Vulkan-style resources are arrays implicitly, OpenGL-style are not
   5017 	const std::string	dimensionBase	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? ("1D")
   5018 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? ("2D")
   5019 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)															? ("3D")
   5020 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? ("Cube")
   5021 										: (DE_NULL);
   5022 	const std::string	dimensionArray	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? ("1DArray")
   5023 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? ("2DArray")
   5024 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)															? ("3D")
   5025 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? ("CubeArray")
   5026 										: (DE_NULL);
   5027 	const std::string	dimension		= isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
   5028 
   5029 	if (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
   5030 		DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
   5031 
   5032 	switch (m_shaderInterface)
   5033 	{
   5034 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   5035 		{
   5036 			switch (m_descriptorType)
   5037 			{
   5038 				case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
   5039 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
   5040 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler;\n";
   5041 				case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
   5042 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler;\n";
   5043 				case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
   5044 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n";
   5045 				case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
   5046 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image;\n";
   5047 				default:
   5048 					DE_FATAL("invalid descriptor");
   5049 					return "";
   5050 			}
   5051 		}
   5052 
   5053 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   5054 		case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
   5055 			switch (m_descriptorType)
   5056 			{
   5057 				case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
   5058 					if (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)
   5059 						return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
   5060 								"layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplerA;\n"
   5061 								"layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
   5062 					else
   5063 						return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler u_separateSamplerA;\n"
   5064 								"layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
   5065 								"layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
   5066 				case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
   5067 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerA;\n"
   5068 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerB;\n";
   5069 				case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
   5070 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTextureA;\n"
   5071 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimensionBase + " u_separateTextureB;\n";
   5072 				case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
   5073 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_imageA;\n"
   5074 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ", rgba8) readonly uniform highp image" + dimension + " u_imageB;\n";
   5075 				default:
   5076 					DE_FATAL("invalid descriptor");
   5077 					return "";
   5078 			}
   5079 
   5080 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   5081 			switch (m_descriptorType)
   5082 			{
   5083 				case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
   5084 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
   5085 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler[2];\n";
   5086 				case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
   5087 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler[2];\n";
   5088 				case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
   5089 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture[2];\n";
   5090 				case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
   5091 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image[2];\n";
   5092 				default:
   5093 					DE_FATAL("invalid descriptor");
   5094 					return "";
   5095 			}
   5096 
   5097 		default:
   5098 			DE_FATAL("Impossible");
   5099 			return "";
   5100 	}
   5101 }
   5102 
   5103 std::string ImageDescriptorCase::genFetchCoordStr (int fetchPosNdx) const
   5104 {
   5105 	DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
   5106 	const tcu::IVec3 fetchPos = ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
   5107 
   5108 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
   5109 	{
   5110 		return de::toString(fetchPos.x());
   5111 	}
   5112 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
   5113 	{
   5114 		std::ostringstream buf;
   5115 		buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
   5116 		return buf.str();
   5117 	}
   5118 	else
   5119 	{
   5120 		std::ostringstream buf;
   5121 		buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
   5122 		return buf.str();
   5123 	}
   5124 }
   5125 
   5126 std::string ImageDescriptorCase::genSampleCoordStr (int samplePosNdx) const
   5127 {
   5128 	DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
   5129 	const tcu::Vec4 fetchPos = ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
   5130 
   5131 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
   5132 	{
   5133 		std::ostringstream buf;
   5134 		buf << "float(" << fetchPos.x() << ")";
   5135 		return buf.str();
   5136 	}
   5137 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
   5138 	{
   5139 		std::ostringstream buf;
   5140 		buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
   5141 		return buf.str();
   5142 	}
   5143 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
   5144 	{
   5145 		std::ostringstream buf;
   5146 		buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "), float(" << fetchPos.w() << "))";
   5147 		return buf.str();
   5148 	}
   5149 	else
   5150 	{
   5151 		std::ostringstream buf;
   5152 		buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
   5153 		return buf.str();
   5154 	}
   5155 }
   5156 
   5157 std::string ImageDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
   5158 {
   5159 	DE_UNREF(stage);
   5160 
   5161 	const char* const	dimension		= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)			? ("1D")
   5162 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)	? ("1DArray")
   5163 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)			? ("2D")
   5164 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)	? ("2DArray")
   5165 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)			? ("3D")
   5166 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)		? ("Cube")
   5167 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? ("CubeArray")
   5168 										: (DE_NULL);
   5169 	const char* const	accessPostfixA	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
   5170 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("A")
   5171 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)	? ("A")
   5172 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[0]")
   5173 										: (DE_NULL);
   5174 	const char* const	accessPostfixB	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
   5175 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("B")
   5176 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)	? ("B")
   5177 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[1]")
   5178 										: (DE_NULL);
   5179 
   5180 	switch (m_descriptorType)
   5181 	{
   5182 		case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
   5183 		case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
   5184 		{
   5185 			const std::string	coodStr[4]	=
   5186 			{
   5187 				genSampleCoordStr(0),
   5188 				genSampleCoordStr(1),
   5189 				genSampleCoordStr(2),
   5190 				genSampleCoordStr(3),
   5191 			};
   5192 			std::ostringstream	buf;
   5193 
   5194 			if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
   5195 			{
   5196 				buf << "	if (quadrant_id == 0)\n"
   5197 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[0] << ", 0.0);\n"
   5198 					<< "	else if (quadrant_id == 1)\n"
   5199 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[1] << ", 0.0);\n"
   5200 					<< "	else if (quadrant_id == 2)\n"
   5201 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[2] << ", 0.0);\n"
   5202 					<< "	else\n"
   5203 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[3] << ", 0.0);\n";
   5204 			}
   5205 			else
   5206 			{
   5207 				buf << "	if (quadrant_id == 0)\n"
   5208 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[0] << ", 0.0);\n"
   5209 					<< "	else if (quadrant_id == 1)\n"
   5210 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[1] << ", 0.0);\n"
   5211 					<< "	else if (quadrant_id == 2)\n"
   5212 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[2] << ", 0.0);\n"
   5213 					<< "	else\n"
   5214 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[3] << ", 0.0);\n";
   5215 			}
   5216 
   5217 			return buf.str();
   5218 		}
   5219 
   5220 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
   5221 		{
   5222 			const std::string	coodStr[4]	=
   5223 			{
   5224 				genFetchCoordStr(0),
   5225 				genFetchCoordStr(1),
   5226 				genFetchCoordStr(2),
   5227 				genFetchCoordStr(3),
   5228 			};
   5229 			std::ostringstream	buf;
   5230 
   5231 			buf << "	if (quadrant_id == 0)\n"
   5232 				<< "		result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[0] << ");\n"
   5233 				<< "	else if (quadrant_id == 1)\n"
   5234 				<< "		result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[1] << ");\n"
   5235 				<< "	else if (quadrant_id == 2)\n"
   5236 				<< "		result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[2] << ");\n"
   5237 				<< "	else\n"
   5238 				<< "		result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[3] << ");\n";
   5239 
   5240 			return buf.str();
   5241 		}
   5242 
   5243 		default:
   5244 			DE_FATAL("invalid descriptor");
   5245 			return "";
   5246 	}
   5247 }
   5248 
   5249 std::string ImageDescriptorCase::genNoAccessSource (void) const
   5250 {
   5251 	return "	if (quadrant_id == 1 || quadrant_id == 2)\n"
   5252 			"		result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
   5253 			"	else\n"
   5254 			"		result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
   5255 }
   5256 
   5257 vkt::TestInstance* ImageDescriptorCase::createInstance (vkt::Context& context) const
   5258 {
   5259 	verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
   5260 
   5261 	switch (m_descriptorType)
   5262 	{
   5263 		case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
   5264 		case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
   5265 			if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
   5266 			{
   5267 				DE_ASSERT(m_isPrimaryCmdBuf);
   5268 				return new ImageSampleComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
   5269 			}
   5270 			else
   5271 				return new ImageSampleRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
   5272 
   5273 		case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
   5274 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
   5275 			if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
   5276 			{
   5277 				DE_ASSERT(m_isPrimaryCmdBuf);
   5278 				return new ImageFetchComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
   5279 			}
   5280 			else
   5281 				return new ImageFetchRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
   5282 
   5283 		default:
   5284 			DE_FATAL("Impossible");
   5285 			return DE_NULL;
   5286 	}
   5287 }
   5288 
   5289 class TexelBufferInstanceBuffers
   5290 {
   5291 public:
   5292 											TexelBufferInstanceBuffers	(const vk::DeviceInterface&		vki,
   5293 																		 vk::VkDevice					device,
   5294 																		 vk::Allocator&					allocator,
   5295 																		 vk::VkDescriptorType			descriptorType,
   5296 																		 int							numTexelBuffers,
   5297 																		 bool							hasViewOffset);
   5298 
   5299 private:
   5300 	static vk::Move<vk::VkBuffer>			createBuffer				(const vk::DeviceInterface&		vki,
   5301 																		 vk::VkDevice					device,
   5302 																		 vk::Allocator&					allocator,
   5303 																		 vk::VkDescriptorType			descriptorType,
   5304 																		 de::MovePtr<vk::Allocation>	*outAllocation);
   5305 
   5306 	static vk::Move<vk::VkBufferView>		createBufferView			(const vk::DeviceInterface&		vki,
   5307 																		 vk::VkDevice					device,
   5308 																		 const tcu::TextureFormat&		textureFormat,
   5309 																		 deUint32						offset,
   5310 																		 vk::VkBuffer					buffer);
   5311 
   5312 	static vk::VkBufferMemoryBarrier		createBarrier				(vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
   5313 
   5314 	void									populateSourceBuffer		(const tcu::PixelBufferAccess& access);
   5315 	void									uploadData					(const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data);
   5316 
   5317 public:
   5318 	static int								getFetchPos					(int fetchPosNdx);
   5319 	tcu::Vec4								fetchTexelValue				(int fetchPosNdx) const;
   5320 
   5321 	inline int								getNumTexelBuffers			(void) const { return m_numTexelBuffers;	}
   5322 	const tcu::TextureFormat&				getTextureFormat			(void) const { return m_imageFormat;		}
   5323 	inline vk::VkBufferView					getBufferViewA				(void) const { return *m_bufferViewA;		}
   5324 	inline vk::VkBufferView					getBufferViewB				(void) const { return *m_bufferViewB;		}
   5325 	inline const vk::VkBufferMemoryBarrier*	getBufferInitBarriers		(void) const { return m_bufferBarriers;		}
   5326 
   5327 private:
   5328 	enum
   5329 	{
   5330 		BUFFER_SIZE			= 512,
   5331 		VIEW_OFFSET_VALUE	= 256,
   5332 		VIEW_DATA_SIZE		= 256,	//!< size in bytes
   5333 		VIEW_WIDTH			= 64,	//!< size in pixels
   5334 	};
   5335 	enum
   5336 	{
   5337 		// some arbitrary points
   5338 		SAMPLE_POINT_0 = 6,
   5339 		SAMPLE_POINT_1 = 51,
   5340 		SAMPLE_POINT_2 = 42,
   5341 		SAMPLE_POINT_3 = 25,
   5342 	};
   5343 
   5344 	const deUint32							m_numTexelBuffers;
   5345 	const tcu::TextureFormat				m_imageFormat;
   5346 	const deUint32							m_viewOffset;
   5347 
   5348 	de::ArrayBuffer<deUint8>				m_sourceBufferA;
   5349 	de::ArrayBuffer<deUint8>				m_sourceBufferB;
   5350 	const tcu::ConstPixelBufferAccess		m_sourceViewA;
   5351 	const tcu::ConstPixelBufferAccess		m_sourceViewB;
   5352 
   5353 	de::MovePtr<vk::Allocation>				m_bufferMemoryA;
   5354 	de::MovePtr<vk::Allocation>				m_bufferMemoryB;
   5355 	const vk::Unique<vk::VkBuffer>			m_bufferA;
   5356 	const vk::Unique<vk::VkBuffer>			m_bufferB;
   5357 	const vk::Unique<vk::VkBufferView>		m_bufferViewA;
   5358 	const vk::Unique<vk::VkBufferView>		m_bufferViewB;
   5359 	vk::VkBufferMemoryBarrier				m_bufferBarriers[2];
   5360 };
   5361 
   5362 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers (const vk::DeviceInterface&		vki,
   5363 														vk::VkDevice					device,
   5364 														vk::Allocator&					allocator,
   5365 														vk::VkDescriptorType			descriptorType,
   5366 														int								numTexelBuffers,
   5367 														bool							hasViewOffset)
   5368 	: m_numTexelBuffers	(numTexelBuffers)
   5369 	, m_imageFormat		(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
   5370 	, m_viewOffset		((hasViewOffset) ? ((deUint32)VIEW_OFFSET_VALUE) : (0u))
   5371 	, m_sourceBufferA	(BUFFER_SIZE)
   5372 	, m_sourceBufferB	((numTexelBuffers == 1)
   5373 							? (0u)
   5374 							: ((size_t)BUFFER_SIZE))
   5375 	, m_sourceViewA		(m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferA.getElementPtr(m_viewOffset))
   5376 	, m_sourceViewB		(m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferB.getElementPtr(m_viewOffset))
   5377 	, m_bufferMemoryA	(DE_NULL)
   5378 	, m_bufferMemoryB	(DE_NULL)
   5379 	, m_bufferA			(createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryA))
   5380 	, m_bufferB			((numTexelBuffers == 1)
   5381 							? vk::Move<vk::VkBuffer>()
   5382 							: createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryB))
   5383 	, m_bufferViewA		(createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferA))
   5384 	, m_bufferViewB		((numTexelBuffers == 1)
   5385 							? vk::Move<vk::VkBufferView>()
   5386 							: createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferB))
   5387 {
   5388 	DE_ASSERT(numTexelBuffers == 1 || numTexelBuffers == 2);
   5389 	DE_ASSERT(VIEW_WIDTH * m_imageFormat.getPixelSize() == VIEW_DATA_SIZE);
   5390 	DE_ASSERT(BUFFER_SIZE % m_imageFormat.getPixelSize() == 0);
   5391 
   5392 	// specify and upload
   5393 
   5394 	populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferA.getPtr()));
   5395 	uploadData(vki, device, *m_bufferMemoryA, m_sourceBufferA);
   5396 
   5397 	if (numTexelBuffers == 2)
   5398 	{
   5399 		populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferB.getPtr()));
   5400 		uploadData(vki, device, *m_bufferMemoryB, m_sourceBufferB);
   5401 	}
   5402 
   5403 	m_bufferBarriers[0] = createBarrier(descriptorType, *m_bufferA);
   5404 	m_bufferBarriers[1] = createBarrier(descriptorType, *m_bufferB);
   5405 }
   5406 
   5407 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer (const vk::DeviceInterface&		vki,
   5408 																 vk::VkDevice					device,
   5409 																 vk::Allocator&					allocator,
   5410 																 vk::VkDescriptorType			descriptorType,
   5411 																 de::MovePtr<vk::Allocation>	*outAllocation)
   5412 {
   5413 	const vk::VkBufferUsageFlags	usage		= (isUniformDescriptorType(descriptorType)) ? (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
   5414 	const vk::VkBufferCreateInfo	createInfo	=
   5415 	{
   5416 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
   5417 		DE_NULL,
   5418 		0u,									// flags
   5419 		(vk::VkDeviceSize)BUFFER_SIZE,		// size
   5420 		usage,								// usage
   5421 		vk::VK_SHARING_MODE_EXCLUSIVE,		// sharingMode
   5422 		0u,									// queueFamilyCount
   5423 		DE_NULL,							// pQueueFamilyIndices
   5424 	};
   5425 	vk::Move<vk::VkBuffer>			buffer		(vk::createBuffer(vki, device, &createInfo));
   5426 	de::MovePtr<vk::Allocation>		allocation	(allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
   5427 
   5428 	*outAllocation = allocation;
   5429 	return buffer;
   5430 }
   5431 
   5432 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView (const vk::DeviceInterface&		vki,
   5433 																		 vk::VkDevice					device,
   5434 																		 const tcu::TextureFormat&		textureFormat,
   5435 																		 deUint32						offset,
   5436 																		 vk::VkBuffer					buffer)
   5437 {
   5438 	const vk::VkBufferViewCreateInfo createInfo =
   5439 	{
   5440 		vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
   5441 		DE_NULL,
   5442 		(vk::VkBufferViewCreateFlags)0,
   5443 		buffer,									// buffer
   5444 		vk::mapTextureFormat(textureFormat),	// format
   5445 		(vk::VkDeviceSize)offset,				// offset
   5446 		(vk::VkDeviceSize)VIEW_DATA_SIZE		// range
   5447 	};
   5448 	return vk::createBufferView(vki, device, &createInfo);
   5449 }
   5450 
   5451 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer)
   5452 {
   5453 	const vk::VkAccessFlags			inputBit	= (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
   5454 	const vk::VkBufferMemoryBarrier	barrier		=
   5455 	{
   5456 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
   5457 		DE_NULL,
   5458 		vk::VK_ACCESS_HOST_WRITE_BIT,			// outputMask
   5459 		inputBit,								// inputMask
   5460 		vk::VK_QUEUE_FAMILY_IGNORED,			// srcQueueFamilyIndex
   5461 		vk::VK_QUEUE_FAMILY_IGNORED,			// destQueueFamilyIndex
   5462 		buffer	,								// buffer
   5463 		0u,										// offset
   5464 		(vk::VkDeviceSize)BUFFER_SIZE			// size
   5465 	};
   5466 	return barrier;
   5467 }
   5468 
   5469 void TexelBufferInstanceBuffers::populateSourceBuffer (const tcu::PixelBufferAccess& access)
   5470 {
   5471 	DE_ASSERT(access.getHeight() == 1);
   5472 	DE_ASSERT(access.getDepth() == 1);
   5473 
   5474 	const deInt32 width = access.getWidth();
   5475 
   5476 	for (int x = 0; x < width; ++x)
   5477 	{
   5478 		const int			red		= 255 * x / width;												//!< gradient from 0 -> max (detects large offset errors)
   5479 		const int			green	= ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0));	//!< 3-level M pattern (detects small offset errors)
   5480 		const int			blue	= 16 * (x % 16);												//!< 16-long triangle wave
   5481 
   5482 		DE_ASSERT(de::inRange(red, 0, 255));
   5483 		DE_ASSERT(de::inRange(green, 0, 255));
   5484 		DE_ASSERT(de::inRange(blue, 0, 255));
   5485 
   5486 		access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
   5487 	}
   5488 }
   5489 
   5490 void TexelBufferInstanceBuffers::uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data)
   5491 {
   5492 	deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
   5493 	flushMappedMemoryRange(vki, device, memory.getMemory(), memory.getOffset(), data.size());
   5494 }
   5495 
   5496 int TexelBufferInstanceBuffers::getFetchPos (int fetchPosNdx)
   5497 {
   5498 	static const int fetchPositions[4] =
   5499 	{
   5500 		SAMPLE_POINT_0,
   5501 		SAMPLE_POINT_1,
   5502 		SAMPLE_POINT_2,
   5503 		SAMPLE_POINT_3,
   5504 	};
   5505 	return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
   5506 }
   5507 
   5508 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue (int fetchPosNdx) const
   5509 {
   5510 	// source order is ABAB
   5511 	const tcu::ConstPixelBufferAccess&	texelSrcA	= m_sourceViewA;
   5512 	const tcu::ConstPixelBufferAccess&	texelSrcB	= (m_numTexelBuffers == 1) ? (m_sourceViewA) : (m_sourceViewB);
   5513 	const tcu::ConstPixelBufferAccess&	texelSrc	= ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
   5514 
   5515 	return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
   5516 }
   5517 
   5518 class TexelBufferRenderInstance : public SingleCmdRenderInstance
   5519 {
   5520 public:
   5521 													TexelBufferRenderInstance	(vkt::Context&			context,
   5522 																				 bool					isPrimaryCmdBuf,
   5523 																				 vk::VkDescriptorType	descriptorType,
   5524 																				 vk::VkShaderStageFlags	stageFlags,
   5525 																				 ShaderInputInterface	shaderInterface,
   5526 																				 bool					nonzeroViewOffset);
   5527 
   5528 private:
   5529 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(const vk::DeviceInterface&	vki,
   5530 																				 vk::VkDevice				device,
   5531 																				 vk::VkDescriptorType		descriptorType,
   5532 																				 ShaderInputInterface		shaderInterface,
   5533 																				 vk::VkShaderStageFlags		stageFlags);
   5534 
   5535 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout		(const vk::DeviceInterface&	vki,
   5536 																				 vk::VkDevice				device,
   5537 																				 vk::VkDescriptorSetLayout	descriptorSetLayout);
   5538 
   5539 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(const vk::DeviceInterface&	vki,
   5540 																				 vk::VkDevice				device,
   5541 																				 vk::VkDescriptorType		descriptorType,
   5542 																				 ShaderInputInterface		shaderInterface);
   5543 
   5544 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(const vk::DeviceInterface&	vki,
   5545 																				 vk::VkDevice				device,
   5546 																				 vk::VkDescriptorType		descriptorType,
   5547 																				 ShaderInputInterface		shaderInterface,
   5548 																				 vk::VkDescriptorSetLayout	layout,
   5549 																				 vk::VkDescriptorPool		pool,
   5550 																				 vk::VkBufferView			viewA,
   5551 																				 vk::VkBufferView			viewB);
   5552 
   5553 	void											logTestPlan					(void) const;
   5554 	vk::VkPipelineLayout							getPipelineLayout			(void) const;
   5555 	void											writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const;
   5556 	tcu::TestStatus									verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const;
   5557 
   5558 	enum
   5559 	{
   5560 		RENDER_SIZE = 128,
   5561 	};
   5562 
   5563 	const vk::VkDescriptorType						m_descriptorType;
   5564 	const vk::VkShaderStageFlags					m_stageFlags;
   5565 	const ShaderInputInterface						m_shaderInterface;
   5566 	const bool										m_nonzeroViewOffset;
   5567 
   5568 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
   5569 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
   5570 	const TexelBufferInstanceBuffers				m_texelBuffers;
   5571 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
   5572 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
   5573 };
   5574 
   5575 TexelBufferRenderInstance::TexelBufferRenderInstance (vkt::Context&				context,
   5576 													  bool						isPrimaryCmdBuf,
   5577 													  vk::VkDescriptorType		descriptorType,
   5578 													  vk::VkShaderStageFlags	stageFlags,
   5579 													  ShaderInputInterface		shaderInterface,
   5580 													  bool						nonzeroViewOffset)
   5581 	: SingleCmdRenderInstance	(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
   5582 	, m_descriptorType			(descriptorType)
   5583 	, m_stageFlags				(stageFlags)
   5584 	, m_shaderInterface			(shaderInterface)
   5585 	, m_nonzeroViewOffset		(nonzeroViewOffset)
   5586 	, m_descriptorSetLayout		(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
   5587 	, m_pipelineLayout			(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
   5588 	, m_texelBuffers			(m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
   5589 	, m_descriptorPool			(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
   5590 	, m_descriptorSet			(createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_texelBuffers.getBufferViewA(), m_texelBuffers.getBufferViewB()))
   5591 {
   5592 }
   5593 
   5594 vk::Move<vk::VkDescriptorSetLayout> TexelBufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&	vki,
   5595 																						  vk::VkDevice					device,
   5596 																						  vk::VkDescriptorType			descriptorType,
   5597 																						  ShaderInputInterface			shaderInterface,
   5598 																						  vk::VkShaderStageFlags		stageFlags)
   5599 {
   5600 	vk::DescriptorSetLayoutBuilder builder;
   5601 
   5602 	switch (shaderInterface)
   5603 	{
   5604 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   5605 			builder.addSingleBinding(descriptorType, stageFlags);
   5606 			break;
   5607 
   5608 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   5609 			builder.addSingleBinding(descriptorType, stageFlags);
   5610 			builder.addSingleBinding(descriptorType, stageFlags);
   5611 			break;
   5612 
   5613 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   5614 			builder.addArrayBinding(descriptorType, 2u, stageFlags);
   5615 			break;
   5616 
   5617 		default:
   5618 			DE_FATAL("Impossible");
   5619 	}
   5620 
   5621 	return builder.build(vki, device);
   5622 }
   5623 
   5624 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
   5625 																				vk::VkDevice				device,
   5626 																				vk::VkDescriptorSetLayout	descriptorSetLayout)
   5627 {
   5628 	const vk::VkPipelineLayoutCreateInfo createInfo =
   5629 	{
   5630 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
   5631 		DE_NULL,
   5632 		(vk::VkPipelineLayoutCreateFlags)0,
   5633 		1,						// descriptorSetCount
   5634 		&descriptorSetLayout,	// pSetLayouts
   5635 		0u,						// pushConstantRangeCount
   5636 		DE_NULL,				// pPushConstantRanges
   5637 	};
   5638 	return vk::createPipelineLayout(vki, device, &createInfo);
   5639 }
   5640 
   5641 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
   5642 																				vk::VkDevice					device,
   5643 																				vk::VkDescriptorType			descriptorType,
   5644 																				ShaderInputInterface			shaderInterface)
   5645 {
   5646 	return vk::DescriptorPoolBuilder()
   5647 		.addType(descriptorType, getInterfaceNumResources(shaderInterface))
   5648 		.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   5649 }
   5650 
   5651 vk::Move<vk::VkDescriptorSet> TexelBufferRenderInstance::createDescriptorSet (const vk::DeviceInterface&	vki,
   5652 																			  vk::VkDevice					device,
   5653 																			  vk::VkDescriptorType			descriptorType,
   5654 																			  ShaderInputInterface			shaderInterface,
   5655 																			  vk::VkDescriptorSetLayout		layout,
   5656 																			  vk::VkDescriptorPool			pool,
   5657 																			  vk::VkBufferView				viewA,
   5658 																			  vk::VkBufferView				viewB)
   5659 {
   5660 	const vk::VkBufferView					texelBufferInfos[2]	=
   5661 	{
   5662 		viewA,
   5663 		viewB,
   5664 	};
   5665 	const vk::VkDescriptorSetAllocateInfo	allocInfo			=
   5666 	{
   5667 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   5668 		DE_NULL,
   5669 		pool,
   5670 		1u,
   5671 		&layout
   5672 	};
   5673 
   5674 	vk::Move<vk::VkDescriptorSet>			descriptorSet		= allocateDescriptorSet(vki, device, &allocInfo);
   5675 	vk::DescriptorSetUpdateBuilder			builder;
   5676 
   5677 	switch (shaderInterface)
   5678 	{
   5679 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   5680 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
   5681 			break;
   5682 
   5683 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   5684 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
   5685 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &texelBufferInfos[1]);
   5686 			break;
   5687 
   5688 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   5689 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, texelBufferInfos);
   5690 			break;
   5691 
   5692 		default:
   5693 			DE_FATAL("Impossible");
   5694 	}
   5695 
   5696 	builder.update(vki, device);
   5697 	return descriptorSet;
   5698 }
   5699 
   5700 void TexelBufferRenderInstance::logTestPlan (void) const
   5701 {
   5702 	std::ostringstream msg;
   5703 
   5704 	msg << "Rendering 2x2 grid.\n"
   5705 		<< "Single descriptor set. Descriptor set contains "
   5706 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   5707 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   5708 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   5709 			    (const char*)DE_NULL)
   5710 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
   5711 		<< "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
   5712 		<< "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
   5713 
   5714 	if (m_stageFlags == 0u)
   5715 	{
   5716 		msg << "Descriptors are not accessed in any shader stage.\n";
   5717 	}
   5718 	else
   5719 	{
   5720 		msg << "Color in each cell is fetched using the descriptor(s):\n";
   5721 
   5722 		for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   5723 		{
   5724 			msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
   5725 
   5726 			if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
   5727 			{
   5728 				const int srcResourceNdx = (resultNdx % 2); // ABAB source
   5729 				msg << " from texelBuffer " << srcResourceNdx;
   5730 			}
   5731 
   5732 			msg << "\n";
   5733 		}
   5734 
   5735 		msg << "Descriptors are accessed in {"
   5736 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
   5737 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
   5738 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
   5739 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
   5740 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
   5741 			<< " } stages.";
   5742 	}
   5743 
   5744 	m_context.getTestContext().getLog()
   5745 		<< tcu::TestLog::Message
   5746 		<< msg.str()
   5747 		<< tcu::TestLog::EndMessage;
   5748 }
   5749 
   5750 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout (void) const
   5751 {
   5752 	return *m_pipelineLayout;
   5753 }
   5754 
   5755 void TexelBufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
   5756 {
   5757 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
   5758 	m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
   5759 }
   5760 
   5761 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
   5762 {
   5763 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
   5764 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
   5765 	const bool			doFetch		= (m_stageFlags != 0u); // no active stages? Then don't fetch
   5766 	const tcu::Vec4		sample0		= (!doFetch) ? (yellow)	: (m_texelBuffers.fetchTexelValue(0));
   5767 	const tcu::Vec4		sample1		= (!doFetch) ? (green)	: (m_texelBuffers.fetchTexelValue(1));
   5768 	const tcu::Vec4		sample2		= (!doFetch) ? (green)	: (m_texelBuffers.fetchTexelValue(2));
   5769 	const tcu::Vec4		sample3		= (!doFetch) ? (yellow)	: (m_texelBuffers.fetchTexelValue(3));
   5770 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
   5771 
   5772 	drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
   5773 
   5774 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
   5775 		return tcu::TestStatus::fail("Image verification failed");
   5776 	else
   5777 		return tcu::TestStatus::pass("Pass");
   5778 }
   5779 
   5780 class TexelBufferComputeInstance : public vkt::TestInstance
   5781 {
   5782 public:
   5783 											TexelBufferComputeInstance	(vkt::Context&			context,
   5784 																		 vk::VkDescriptorType	descriptorType,
   5785 																		 ShaderInputInterface	shaderInterface,
   5786 																		 bool					nonzeroViewOffset);
   5787 
   5788 private:
   5789 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(void) const;
   5790 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(void) const;
   5791 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
   5792 
   5793 	tcu::TestStatus							iterate						(void);
   5794 	void									logTestPlan					(void) const;
   5795 	tcu::TestStatus							testResourceAccess			(void);
   5796 
   5797 	const vk::VkDescriptorType				m_descriptorType;
   5798 	const ShaderInputInterface				m_shaderInterface;
   5799 	const bool								m_nonzeroViewOffset;
   5800 
   5801 	const vk::DeviceInterface&				m_vki;
   5802 	const vk::VkDevice						m_device;
   5803 	const vk::VkQueue						m_queue;
   5804 	const deUint32							m_queueFamilyIndex;
   5805 	vk::Allocator&							m_allocator;
   5806 
   5807 	const ComputeInstanceResultBuffer		m_result;
   5808 	const TexelBufferInstanceBuffers		m_texelBuffers;
   5809 };
   5810 
   5811 TexelBufferComputeInstance::TexelBufferComputeInstance (Context&				context,
   5812 														vk::VkDescriptorType	descriptorType,
   5813 														ShaderInputInterface	shaderInterface,
   5814 														bool					nonzeroViewOffset)
   5815 	: vkt::TestInstance		(context)
   5816 	, m_descriptorType		(descriptorType)
   5817 	, m_shaderInterface		(shaderInterface)
   5818 	, m_nonzeroViewOffset	(nonzeroViewOffset)
   5819 	, m_vki					(context.getDeviceInterface())
   5820 	, m_device				(context.getDevice())
   5821 	, m_queue				(context.getUniversalQueue())
   5822 	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
   5823 	, m_allocator			(context.getDefaultAllocator())
   5824 	, m_result				(m_vki, m_device, m_allocator)
   5825 	, m_texelBuffers		(m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
   5826 {
   5827 }
   5828 
   5829 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout (void) const
   5830 {
   5831 	vk::DescriptorSetLayoutBuilder builder;
   5832 
   5833 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   5834 
   5835 	switch (m_shaderInterface)
   5836 	{
   5837 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   5838 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   5839 			break;
   5840 
   5841 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   5842 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   5843 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   5844 			break;
   5845 
   5846 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   5847 			builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
   5848 			break;
   5849 
   5850 		default:
   5851 			DE_FATAL("Impossible");
   5852 	};
   5853 
   5854 	return builder.build(m_vki, m_device);
   5855 }
   5856 
   5857 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool (void) const
   5858 {
   5859 	return vk::DescriptorPoolBuilder()
   5860 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
   5861 		.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
   5862 		.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
   5863 }
   5864 
   5865 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
   5866 {
   5867 	const vk::VkDescriptorBufferInfo		resultInfo			= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
   5868 	const vk::VkBufferView					texelBufferInfos[2]	=
   5869 	{
   5870 		m_texelBuffers.getBufferViewA(),
   5871 		m_texelBuffers.getBufferViewB(),
   5872 	};
   5873 	const vk::VkDescriptorSetAllocateInfo	allocInfo			=
   5874 	{
   5875 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   5876 		DE_NULL,
   5877 		pool,
   5878 		1u,
   5879 		&layout
   5880 	};
   5881 
   5882 	vk::Move<vk::VkDescriptorSet>			descriptorSet		= allocateDescriptorSet(m_vki, m_device, &allocInfo);
   5883 	vk::DescriptorSetUpdateBuilder			builder;
   5884 
   5885 	// result
   5886 	builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
   5887 
   5888 	// texel buffers
   5889 	switch (m_shaderInterface)
   5890 	{
   5891 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   5892 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
   5893 			break;
   5894 
   5895 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   5896 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
   5897 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &texelBufferInfos[1]);
   5898 			break;
   5899 
   5900 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   5901 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, texelBufferInfos);
   5902 			break;
   5903 
   5904 		default:
   5905 			DE_FATAL("Impossible");
   5906 	}
   5907 
   5908 	builder.update(m_vki, m_device);
   5909 	return descriptorSet;
   5910 }
   5911 
   5912 tcu::TestStatus TexelBufferComputeInstance::iterate (void)
   5913 {
   5914 	logTestPlan();
   5915 	return testResourceAccess();
   5916 }
   5917 
   5918 void TexelBufferComputeInstance::logTestPlan (void) const
   5919 {
   5920 	std::ostringstream msg;
   5921 
   5922 	msg << "Fetching 4 values from image in compute shader.\n"
   5923 		<< "Single descriptor set. Descriptor set contains "
   5924 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
   5925 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
   5926 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
   5927 			    (const char*)DE_NULL)
   5928 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
   5929 		<< "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
   5930 		<< "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
   5931 
   5932 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   5933 	{
   5934 		msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
   5935 
   5936 		if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
   5937 		{
   5938 			const int srcResourceNdx = (resultNdx % 2); // ABAB source
   5939 			msg << " from texelBuffer " << srcResourceNdx;
   5940 		}
   5941 
   5942 		msg << "\n";
   5943 	}
   5944 
   5945 	m_context.getTestContext().getLog()
   5946 		<< tcu::TestLog::Message
   5947 		<< msg.str()
   5948 		<< tcu::TestLog::EndMessage;
   5949 }
   5950 
   5951 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess (void)
   5952 {
   5953 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
   5954 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
   5955 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout));
   5956 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
   5957 
   5958 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
   5959 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
   5960 	const deUint32* const							dynamicOffsets		= DE_NULL;
   5961 	const int										numDynamicOffsets	= 0;
   5962 	const vk::VkBufferMemoryBarrier* const			preBarriers			= m_texelBuffers.getBufferInitBarriers();
   5963 	const int										numPreBarriers		= m_texelBuffers.getNumTexelBuffers();
   5964 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
   5965 	const int										numPostBarriers		= 1;
   5966 
   5967 	const ComputeCommand							compute				(m_vki,
   5968 																		 m_device,
   5969 																		 pipeline.getPipeline(),
   5970 																		 pipeline.getPipelineLayout(),
   5971 																		 tcu::UVec3(4, 1, 1),
   5972 																		 numDescriptorSets,	descriptorSets,
   5973 																		 numDynamicOffsets,	dynamicOffsets,
   5974 																		 numPreBarriers,	preBarriers,
   5975 																		 numPostBarriers,	postBarriers);
   5976 
   5977 	tcu::Vec4										results[4];
   5978 	bool											anyResultSet		= false;
   5979 	bool											allResultsOk		= true;
   5980 
   5981 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
   5982 	m_result.readResultContentsTo(&results);
   5983 
   5984 	// verify
   5985 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
   5986 	{
   5987 		const tcu::Vec4	result				= results[resultNdx];
   5988 		const tcu::Vec4	reference			= m_texelBuffers.fetchTexelValue(resultNdx);
   5989 		const tcu::Vec4	conversionThreshold	= tcu::Vec4(1.0f / 255.0f);
   5990 
   5991 		if (result != tcu::Vec4(-1.0f))
   5992 			anyResultSet = true;
   5993 
   5994 		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
   5995 		{
   5996 			allResultsOk = false;
   5997 
   5998 			m_context.getTestContext().getLog()
   5999 				<< tcu::TestLog::Message
   6000 				<< "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
   6001 				<< tcu::TestLog::EndMessage;
   6002 		}
   6003 	}
   6004 
   6005 	// read back and verify
   6006 	if (allResultsOk)
   6007 		return tcu::TestStatus::pass("Pass");
   6008 	else if (anyResultSet)
   6009 		return tcu::TestStatus::fail("Invalid result values");
   6010 	else
   6011 	{
   6012 		m_context.getTestContext().getLog()
   6013 			<< tcu::TestLog::Message
   6014 			<< "Result buffer was not written to."
   6015 			<< tcu::TestLog::EndMessage;
   6016 		return tcu::TestStatus::fail("Result buffer was not written to");
   6017 	}
   6018 }
   6019 
   6020 class TexelBufferDescriptorCase : public QuadrantRendederCase
   6021 {
   6022 public:
   6023 	enum
   6024 	{
   6025 		FLAG_VIEW_OFFSET = (1u << 1u),
   6026 	};
   6027 	// enum continues where resource flags ends
   6028 	DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
   6029 
   6030 								TexelBufferDescriptorCase	(tcu::TestContext&		testCtx,
   6031 															 const char*			name,
   6032 															 const char*			description,
   6033 															 bool					isPrimaryCmdBuf,
   6034 															 vk::VkDescriptorType	descriptorType,
   6035 															 vk::VkShaderStageFlags	exitingStages,
   6036 															 vk::VkShaderStageFlags	activeStages,
   6037 															 ShaderInputInterface	shaderInterface,
   6038 															 deUint32				flags);
   6039 
   6040 private:
   6041 	std::string					genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const;
   6042 	std::string					genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
   6043 	std::string					genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const;
   6044 	std::string					genNoAccessSource			(void) const;
   6045 
   6046 	vkt::TestInstance*			createInstance				(vkt::Context& context) const;
   6047 
   6048 	const bool					m_isPrimaryCmdBuf;
   6049 	const vk::VkDescriptorType	m_descriptorType;
   6050 	const ShaderInputInterface	m_shaderInterface;
   6051 	const bool					m_nonzeroViewOffset;
   6052 };
   6053 
   6054 TexelBufferDescriptorCase::TexelBufferDescriptorCase (tcu::TestContext&			testCtx,
   6055 													  const char*				name,
   6056 													  const char*				description,
   6057 													  bool						isPrimaryCmdBuf,
   6058 													  vk::VkDescriptorType		descriptorType,
   6059 													  vk::VkShaderStageFlags	exitingStages,
   6060 													  vk::VkShaderStageFlags	activeStages,
   6061 													  ShaderInputInterface		shaderInterface,
   6062 													  deUint32					flags)
   6063 	: QuadrantRendederCase	(testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
   6064 	, m_isPrimaryCmdBuf		(isPrimaryCmdBuf)
   6065 	, m_descriptorType		(descriptorType)
   6066 	, m_shaderInterface		(shaderInterface)
   6067 	, m_nonzeroViewOffset	(((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
   6068 {
   6069 }
   6070 
   6071 std::string TexelBufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
   6072 {
   6073 	DE_UNREF(stage);
   6074 	return "#extension GL_EXT_texture_buffer : require\n";
   6075 }
   6076 
   6077 std::string TexelBufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
   6078 {
   6079 	DE_UNREF(stage);
   6080 
   6081 	const bool			isUniform		= isUniformDescriptorType(m_descriptorType);
   6082 	const char* const	storageType		= (isUniform) ? ("samplerBuffer ") : ("readonly imageBuffer ");
   6083 	const char* const	formatQualifier	= (isUniform) ? ("") : (", rgba8");
   6084 
   6085 	switch (m_shaderInterface)
   6086 	{
   6087 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
   6088 			return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer;\n";
   6089 
   6090 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
   6091 			return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferA;\n"
   6092 				   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferB;\n";
   6093 
   6094 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
   6095 			return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer[2];\n";
   6096 
   6097 		default:
   6098 			DE_FATAL("Impossible");
   6099 			return "";
   6100 	}
   6101 }
   6102 
   6103 std::string TexelBufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
   6104 {
   6105 	DE_UNREF(stage);
   6106 
   6107 	const char* const	accessPostfixA	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
   6108 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("A")
   6109 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[0]")
   6110 										: (DE_NULL);
   6111 	const char* const	accessPostfixB	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
   6112 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("B")
   6113 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[1]")
   6114 										: (DE_NULL);
   6115 	const char* const	fetchFunc		= (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
   6116 	std::ostringstream	buf;
   6117 
   6118 	buf << "	if (quadrant_id == 0)\n"
   6119 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
   6120 		<< "	else if (quadrant_id == 1)\n"
   6121 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
   6122 		<< "	else if (quadrant_id == 2)\n"
   6123 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
   6124 		<< "	else\n"
   6125 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
   6126 
   6127 	return buf.str();
   6128 }
   6129 
   6130 std::string TexelBufferDescriptorCase::genNoAccessSource (void) const
   6131 {
   6132 	return "	if (quadrant_id == 1 || quadrant_id == 2)\n"
   6133 			"		result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
   6134 			"	else\n"
   6135 			"		result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
   6136 }
   6137 
   6138 vkt::TestInstance* TexelBufferDescriptorCase::createInstance (vkt::Context& context) const
   6139 {
   6140 	verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
   6141 
   6142 	if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
   6143 	{
   6144 		DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
   6145 		return new TexelBufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_nonzeroViewOffset);
   6146 	}
   6147 	else
   6148 		return new TexelBufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_nonzeroViewOffset);
   6149 }
   6150 
   6151 void createShaderAccessImageTests (tcu::TestCaseGroup*		group,
   6152 								   bool						isPrimaryCmdBuf,
   6153 								   vk::VkDescriptorType		descriptorType,
   6154 								   vk::VkShaderStageFlags	exitingStages,
   6155 								   vk::VkShaderStageFlags	activeStages,
   6156 								   ShaderInputInterface		dimension,
   6157 								   deUint32					resourceFlags)
   6158 {
   6159 	static const struct
   6160 	{
   6161 		vk::VkImageViewType	viewType;
   6162 		const char*			name;
   6163 		const char*			description;
   6164 		deUint32			flags;
   6165 	} s_imageTypes[] =
   6166 	{
   6167 		{ vk::VK_IMAGE_VIEW_TYPE_1D,			"1d",						"1D image view",								0u										},
   6168 		{ vk::VK_IMAGE_VIEW_TYPE_1D,			"1d_base_mip",				"1D image subview with base mip level",			ImageDescriptorCase::FLAG_BASE_MIP		},
   6169 		{ vk::VK_IMAGE_VIEW_TYPE_1D,			"1d_base_slice",			"1D image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
   6170 
   6171 		{ vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array",					"1D array image view",							0u										},
   6172 		{ vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array_base_mip",		"1D array image subview with base mip level",	ImageDescriptorCase::FLAG_BASE_MIP		},
   6173 		{ vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array_base_slice",		"1D array image subview with base array slice",	ImageDescriptorCase::FLAG_BASE_SLICE	},
   6174 
   6175 		{ vk::VK_IMAGE_VIEW_TYPE_2D,			"2d",						"2D image view",								0u										},
   6176 		{ vk::VK_IMAGE_VIEW_TYPE_2D,			"2d_base_mip",				"2D image subview with base mip level",			ImageDescriptorCase::FLAG_BASE_MIP		},
   6177 		{ vk::VK_IMAGE_VIEW_TYPE_2D,			"2d_base_slice",			"2D image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
   6178 
   6179 		{ vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array",					"2D array image view",							0u										},
   6180 		{ vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array_base_mip",		"2D array image subview with base mip level",	ImageDescriptorCase::FLAG_BASE_MIP		},
   6181 		{ vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array_base_slice",		"2D array image subview with base array slice",	ImageDescriptorCase::FLAG_BASE_SLICE	},
   6182 
   6183 		{ vk::VK_IMAGE_VIEW_TYPE_3D,			"3d",						"3D image view",								0u										},
   6184 		{ vk::VK_IMAGE_VIEW_TYPE_3D,			"3d_base_mip",				"3D image subview with base mip level",			ImageDescriptorCase::FLAG_BASE_MIP		},
   6185 		// no 3d array textures
   6186 
   6187 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE,			"cube",						"Cube image view",								0u										},
   6188 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE,			"cube_base_mip",			"Cube image subview with base mip level",		ImageDescriptorCase::FLAG_BASE_MIP		},
   6189 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE,			"cube_base_slice",			"Cube image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
   6190 
   6191 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array",				"Cube image view",								0u										},
   6192 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array_base_mip",		"Cube image subview with base mip level",		ImageDescriptorCase::FLAG_BASE_MIP		},
   6193 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array_base_slice",	"Cube image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
   6194 	};
   6195 
   6196 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
   6197 	{
   6198 		// never overlap
   6199 		DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
   6200 
   6201 		// SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS only supported in VK_DESCRIPTOR_TYPE_SAMPLER on graphics shaders for now
   6202 		if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS &&
   6203 			(descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER || activeStages == vk::VK_SHADER_STAGE_COMPUTE_BIT))
   6204 			continue;
   6205 
   6206 		group->addChild(new ImageDescriptorCase(group->getTestContext(),
   6207 												s_imageTypes[ndx].name,
   6208 												s_imageTypes[ndx].description,
   6209 												isPrimaryCmdBuf,
   6210 												descriptorType,
   6211 												exitingStages,
   6212 												activeStages,
   6213 												dimension,
   6214 												s_imageTypes[ndx].viewType,
   6215 												s_imageTypes[ndx].flags | resourceFlags));
   6216 	}
   6217 }
   6218 
   6219 void createShaderAccessTexelBufferTests (tcu::TestCaseGroup*	group,
   6220 										 bool					isPrimaryCmdBuf,
   6221 										 vk::VkDescriptorType	descriptorType,
   6222 										 vk::VkShaderStageFlags	exitingStages,
   6223 										 vk::VkShaderStageFlags	activeStages,
   6224 										 ShaderInputInterface	dimension,
   6225 										 deUint32				resourceFlags)
   6226 {
   6227 	DE_ASSERT(resourceFlags == 0);
   6228 	DE_UNREF(resourceFlags);
   6229 
   6230 	static const struct
   6231 	{
   6232 		const char*	name;
   6233 		const char*	description;
   6234 		deUint32	flags;
   6235 	} s_texelBufferTypes[] =
   6236 	{
   6237 		{ "offset_zero",		"View offset is zero",		0u											},
   6238 		{ "offset_nonzero",		"View offset is non-zero",	TexelBufferDescriptorCase::FLAG_VIEW_OFFSET	},
   6239 	};
   6240 
   6241 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
   6242 	{
   6243 		if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
   6244 			continue;
   6245 
   6246 		group->addChild(new TexelBufferDescriptorCase(group->getTestContext(),
   6247 													  s_texelBufferTypes[ndx].name,
   6248 													  s_texelBufferTypes[ndx].description,
   6249 													  isPrimaryCmdBuf,
   6250 													  descriptorType,
   6251 													  exitingStages,
   6252 													  activeStages,
   6253 													  dimension,
   6254 													  s_texelBufferTypes[ndx].flags));
   6255 	}
   6256 }
   6257 
   6258 void createShaderAccessBufferTests (tcu::TestCaseGroup*		group,
   6259 									bool					isPrimaryCmdBuf,
   6260 									vk::VkDescriptorType	descriptorType,
   6261 									vk::VkShaderStageFlags	exitingStages,
   6262 									vk::VkShaderStageFlags	activeStages,
   6263 									ShaderInputInterface	dimension,
   6264 									deUint32				resourceFlags)
   6265 {
   6266 	DE_ASSERT(resourceFlags == 0u);
   6267 	DE_UNREF(resourceFlags);
   6268 
   6269 	static const struct
   6270 	{
   6271 		const char*	name;
   6272 		const char*	description;
   6273 		bool		isForDynamicCases;
   6274 		deUint32	flags;
   6275 	} s_bufferTypes[] =
   6276 	{
   6277 		{ "offset_view_zero",						"View offset is zero",									false,	0u																							},
   6278 		{ "offset_view_nonzero",					"View offset is non-zero",								false,	BufferDescriptorCase::FLAG_VIEW_OFFSET														},
   6279 
   6280 		{ "offset_view_zero_dynamic_zero",			"View offset is zero, dynamic offset is zero",			true,	BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO												},
   6281 		{ "offset_view_zero_dynamic_nonzero",		"View offset is zero, dynamic offset is non-zero",		true,	BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO											},
   6282 		{ "offset_view_nonzero_dynamic_zero",		"View offset is non-zero, dynamic offset is zero",		true,	BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO		},
   6283 		{ "offset_view_nonzero_dynamic_nonzero",	"View offset is non-zero, dynamic offset is non-zero",	true,	BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO	},
   6284 	};
   6285 
   6286 	const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
   6287 
   6288 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
   6289 	{
   6290 		if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
   6291 			continue;
   6292 
   6293 		if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
   6294 			group->addChild(new BufferDescriptorCase(group->getTestContext(),
   6295 													 s_bufferTypes[ndx].name,
   6296 													 s_bufferTypes[ndx].description,
   6297 													 isPrimaryCmdBuf,
   6298 													 descriptorType,
   6299 													 exitingStages,
   6300 													 activeStages,
   6301 													 dimension,
   6302 													 s_bufferTypes[ndx].flags));
   6303 	}
   6304 }
   6305 
   6306 } // anonymous
   6307 
   6308 tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx)
   6309 {
   6310 	static const struct
   6311 	{
   6312 		const bool	isPrimary;
   6313 		const char*	name;
   6314 		const char*	description;
   6315 	} s_bindTypes[] =
   6316 	{
   6317 		{ true,		"primary_cmd_buf",	"Bind in primary command buffer"	},
   6318 		{ false,	"secondary_cmd_buf",	"Bind in secondary command buffer"	},
   6319 	};
   6320 	static const struct
   6321 	{
   6322 		const vk::VkDescriptorType	descriptorType;
   6323 		const char*					name;
   6324 		const char*					description;
   6325 		deUint32					flags;
   6326 	} s_descriptorTypes[] =
   6327 	{
   6328 		{ vk::VK_DESCRIPTOR_TYPE_SAMPLER,					"sampler_mutable",					"VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler",					0u								},
   6329 		{ vk::VK_DESCRIPTOR_TYPE_SAMPLER,					"sampler_immutable",				"VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",				RESOURCE_FLAG_IMMUTABLE_SAMPLER	},
   6330 		{ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	"combined_image_sampler_mutable",	"VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler",	0u								},
   6331 		{ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	"combined_image_sampler_immutable",	"VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler",	RESOURCE_FLAG_IMMUTABLE_SAMPLER	},
   6332 		// \note No way to access SAMPLED_IMAGE without a sampler
   6333 		//{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				"sampled_image",					"VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE",									0u								},
   6334 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,				"storage_image",					"VK_DESCRIPTOR_TYPE_STORAGE_IMAGE",									0u								},
   6335 		{ vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		"uniform_texel_buffer",				"VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",							0u								},
   6336 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,		"storage_texel_buffer",				"VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",							0u								},
   6337 		{ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,			"uniform_buffer",					"VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER",								0u								},
   6338 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			"storage_buffer",					"VK_DESCRIPTOR_TYPE_STORAGE_BUFFER",								0u								},
   6339 		{ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,	"uniform_buffer_dynamic",			"VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC",						0u								},
   6340 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,	"storage_buffer_dynamic",			"VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC",						0u								},
   6341 	};
   6342 	static const struct
   6343 	{
   6344 		const char*				name;
   6345 		const char*				description;
   6346 		vk::VkShaderStageFlags	existingStages;				//!< stages that exists
   6347 		vk::VkShaderStageFlags	activeStages;				//!< stages that access resource
   6348 		bool					supportsSecondaryCmdBufs;
   6349 	} s_shaderStages[] =
   6350 	{
   6351 		{
   6352 			"no_access",
   6353 			"No accessing stages",
   6354 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6355 			0u,
   6356 			true,
   6357 		},
   6358 		{
   6359 			"vertex",
   6360 			"Vertex stage",
   6361 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6362 			vk::VK_SHADER_STAGE_VERTEX_BIT,
   6363 			true,
   6364 		},
   6365 		{
   6366 			"tess_ctrl",
   6367 			"Tessellation control stage",
   6368 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6369 			vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
   6370 			true,
   6371 		},
   6372 		{
   6373 			"tess_eval",
   6374 			"Tessellation evaluation stage",
   6375 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6376 			vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
   6377 			true,
   6378 		},
   6379 		{
   6380 			"geometry",
   6381 			"Geometry stage",
   6382 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6383 			vk::VK_SHADER_STAGE_GEOMETRY_BIT,
   6384 			true,
   6385 		},
   6386 		{
   6387 			"fragment",
   6388 			"Fragment stage",
   6389 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6390 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6391 			true,
   6392 		},
   6393 		{
   6394 			"compute",
   6395 			"Compute stage",
   6396 			vk::VK_SHADER_STAGE_COMPUTE_BIT,
   6397 			vk::VK_SHADER_STAGE_COMPUTE_BIT,
   6398 			false,
   6399 		},
   6400 		{
   6401 			"vertex_fragment",
   6402 			"Vertex and fragment stages",
   6403 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6404 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
   6405 			true,
   6406 		},
   6407 	};
   6408 	static const struct
   6409 	{
   6410 		ShaderInputInterface	dimension;
   6411 		const char*				name;
   6412 		const char*				description;
   6413 	} s_variableDimensions[] =
   6414 	{
   6415 		{ SHADER_INPUT_SINGLE_DESCRIPTOR,					"single_descriptor",					"Single descriptor"		},
   6416 		{ SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS,		"multiple_contiguous_descriptors",		"Multiple descriptors"	},
   6417 		{ SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS,	"multiple_discontiguous_descriptors",	"Multiple descriptors"	},
   6418 		{ SHADER_INPUT_DESCRIPTOR_ARRAY,					"descriptor_array",						"Descriptor array"		},
   6419 	};
   6420 
   6421 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access", "Access resource via descriptor in a single descriptor set"));
   6422 
   6423 	// .primary_cmd_buf...
   6424 	for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
   6425 	{
   6426 		de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name, s_bindTypes[bindTypeNdx].description));
   6427 
   6428 		// .sampler, .combined_image_sampler, other resource types ...
   6429 		for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
   6430 		{
   6431 			de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
   6432 
   6433 			for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
   6434 			{
   6435 				if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
   6436 				{
   6437 					de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name, s_shaderStages[stageNdx].description));
   6438 
   6439 					for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions); ++dimensionNdx)
   6440 					{
   6441 						de::MovePtr<tcu::TestCaseGroup>	dimensionGroup(new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name, s_variableDimensions[dimensionNdx].description));
   6442 						void							(*createTestsFunc)(tcu::TestCaseGroup*		group,
   6443 																		   bool						isPrimaryCmdBuf,
   6444 																		   vk::VkDescriptorType		descriptorType,
   6445 																		   vk::VkShaderStageFlags	existingStages,
   6446 																		   vk::VkShaderStageFlags	activeStages,
   6447 																		   ShaderInputInterface		dimension,
   6448 																		   deUint32					resourceFlags);
   6449 
   6450 						switch (s_descriptorTypes[descriptorNdx].descriptorType)
   6451 						{
   6452 							case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
   6453 							case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
   6454 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
   6455 								createTestsFunc = createShaderAccessImageTests;
   6456 								break;
   6457 
   6458 							case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
   6459 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
   6460 								createTestsFunc = createShaderAccessTexelBufferTests;
   6461 								break;
   6462 
   6463 							case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
   6464 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
   6465 							case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
   6466 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
   6467 								createTestsFunc = createShaderAccessBufferTests;
   6468 								break;
   6469 
   6470 							default:
   6471 								createTestsFunc = DE_NULL;
   6472 								DE_FATAL("Impossible");
   6473 						}
   6474 
   6475 						if (createTestsFunc)
   6476 						{
   6477 							createTestsFunc(dimensionGroup.get(),
   6478 											s_bindTypes[bindTypeNdx].isPrimary,
   6479 											s_descriptorTypes[descriptorNdx].descriptorType,
   6480 											s_shaderStages[stageNdx].existingStages,
   6481 											s_shaderStages[stageNdx].activeStages,
   6482 											s_variableDimensions[dimensionNdx].dimension,
   6483 											s_descriptorTypes[descriptorNdx].flags);
   6484 						}
   6485 						else
   6486 							DE_FATAL("Impossible");
   6487 
   6488 						stageGroup->addChild(dimensionGroup.release());
   6489 					}
   6490 
   6491 					typeGroup->addChild(stageGroup.release());
   6492 				}
   6493 			}
   6494 
   6495 			bindGroup->addChild(typeGroup.release());
   6496 		}
   6497 
   6498 		group->addChild(bindGroup.release());
   6499 	}
   6500 
   6501 	return group.release();
   6502 }
   6503 
   6504 } // BindingModel
   6505 } // vkt
   6506