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