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