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