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