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