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