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