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 
56 namespace vkt
57 {
58 namespace BindingModel
59 {
60 namespace
61 {
62 
63 enum ResourceFlag
64 {
65 	RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
66 
67 	RESOURCE_FLAG_LAST				= (1u << 1u)
68 };
69 
70 static const char* const s_quadrantGenVertexPosSource =	"	highp int quadPhase = gl_VertexIndex % 6;\n"
71 														"	highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
72 														"	highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
73 														"	highp int quadOriginX = (gl_VertexIndex / 6) % 2;\n"
74 														"	highp int quadOriginY = (gl_VertexIndex / 6) / 2;\n"
75 														"	quadrant_id = gl_VertexIndex / 6;\n"
76 														"	result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
77 
isUniformDescriptorType(vk::VkDescriptorType type)78 bool isUniformDescriptorType (vk::VkDescriptorType type)
79 {
80 	return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
81 		   type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
82 		   type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
83 }
84 
isDynamicDescriptorType(vk::VkDescriptorType type)85 bool isDynamicDescriptorType (vk::VkDescriptorType type)
86 {
87 	return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
88 }
89 
verifyDriverSupport(const vk::VkPhysicalDeviceFeatures & deviceFeatures,vk::VkDescriptorType descType,vk::VkShaderStageFlags activeStages)90 void verifyDriverSupport(const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
91 						 vk::VkDescriptorType					descType,
92 						 vk::VkShaderStageFlags					activeStages)
93 {
94 	switch (descType)
95 	{
96 		case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
97 		case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
98 		case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
99 		case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
100 		case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
101 		case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
102 			// These are supported in all stages
103 			return;
104 
105 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
106 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
107 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
108 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
109 			if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT |
110 								vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
111 								vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
112 								vk::VK_SHADER_STAGE_GEOMETRY_BIT))
113 			{
114 				if (!deviceFeatures.vertexPipelineStoresAndAtomics)
115 					TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
116 			}
117 
118 			if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
119 			{
120 				if (!deviceFeatures.fragmentStoresAndAtomics)
121 					TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in fragment shaders").c_str());
122 			}
123 			return;
124 
125 		default:
126 			DE_FATAL("Impossible");
127 	}
128 }
129 
viewTypeToImageType(vk::VkImageViewType type)130 vk::VkImageType viewTypeToImageType (vk::VkImageViewType type)
131 {
132 	switch (type)
133 	{
134 		case vk::VK_IMAGE_VIEW_TYPE_1D:
135 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:	return vk::VK_IMAGE_TYPE_1D;
136 		case vk::VK_IMAGE_VIEW_TYPE_2D:
137 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:	return vk::VK_IMAGE_TYPE_2D;
138 		case vk::VK_IMAGE_VIEW_TYPE_3D:			return vk::VK_IMAGE_TYPE_3D;
139 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
140 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:	return vk::VK_IMAGE_TYPE_2D;
141 
142 		default:
143 			DE_FATAL("Impossible");
144 			return (vk::VkImageType)0;
145 	}
146 }
147 
getImageLayoutForDescriptorType(vk::VkDescriptorType descType)148 vk::VkImageLayout getImageLayoutForDescriptorType (vk::VkDescriptorType descType)
149 {
150 	if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
151 		return vk::VK_IMAGE_LAYOUT_GENERAL;
152 	else
153 		return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
154 }
155 
getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid & srcImage)156 deUint32 getTextureLevelPyramidDataSize (const tcu::TextureLevelPyramid& srcImage)
157 {
158 	deUint32 dataSize = 0;
159 	for (int level = 0; level < srcImage.getNumLevels(); ++level)
160 	{
161 		const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
162 
163 		// tightly packed
164 		DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
165 
166 		dataSize += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
167 	}
168 	return dataSize;
169 }
170 
writeTextureLevelPyramidData(void * dst,deUint32 dstLen,const tcu::TextureLevelPyramid & srcImage,vk::VkImageViewType viewType,std::vector<vk::VkBufferImageCopy> * copySlices)171 void writeTextureLevelPyramidData (void* dst, deUint32 dstLen, const tcu::TextureLevelPyramid& srcImage, vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy>* copySlices)
172 {
173 	// \note cube is copied face-by-face
174 	const deUint32	arraySize	= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (srcImage.getLevel(0).getHeight()) :
175 								  (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (srcImage.getLevel(0).getDepth()) :
176 								  (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)														? (1) :
177 								  (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (srcImage.getLevel(0).getDepth()) :
178 								  ((deUint32)0);
179 	deUint32		levelOffset	= 0;
180 
181 	DE_ASSERT(arraySize != 0);
182 
183 	for (int level = 0; level < srcImage.getNumLevels(); ++level)
184 	{
185 		const tcu::ConstPixelBufferAccess	srcAccess		= srcImage.getLevel(level);
186 		const tcu::PixelBufferAccess		dstAccess		(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), (deUint8*)dst + levelOffset);
187 		const deUint32						dataSize		= srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
188 		const deUint32						sliceDataSize	= dataSize / arraySize;
189 		const deInt32						sliceHeight		= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (srcAccess.getHeight());
190 		const deInt32						sliceDepth		= (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
191 		const tcu::IVec3					sliceSize		(srcAccess.getWidth(), sliceHeight, sliceDepth);
192 
193 		// tightly packed
194 		DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
195 
196 		for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
197 		{
198 			const vk::VkBufferImageCopy copySlice =
199 			{
200 				(vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize,	// bufferOffset
201 				(deUint32)sliceSize.x(),									// bufferRowLength
202 				(deUint32)sliceSize.y(),									// bufferImageHeight
203 				{
204 					vk::VK_IMAGE_ASPECT_COLOR_BIT,		// aspectMask
205 					(deUint32)level,					// mipLevel
206 					(deUint32)sliceNdx,					// arrayLayer
207 					1u,									// arraySize
208 				},															// imageSubresource
209 				{
210 					0,
211 					0,
212 					0,
213 				},															// imageOffset
214 				{
215 					(deUint32)sliceSize.x(),
216 					(deUint32)sliceSize.y(),
217 					(deUint32)sliceSize.z(),
218 				}															// imageExtent
219 			};
220 			copySlices->push_back(copySlice);
221 		}
222 
223 		DE_ASSERT(arraySize * sliceDataSize == dataSize);
224 
225 		tcu::copy(dstAccess, srcAccess);
226 		levelOffset += dataSize;
227 	}
228 
229 	DE_ASSERT(dstLen == levelOffset);
230 	DE_UNREF(dstLen);
231 }
232 
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkBuffer buffer,vk::MemoryRequirement requirement)233 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkBuffer buffer, vk::MemoryRequirement requirement)
234 {
235 	const vk::VkMemoryRequirements	requirements	= vk::getBufferMemoryRequirements(vki, device, buffer);
236 	de::MovePtr<vk::Allocation>		allocation		= allocator.allocate(requirements, requirement);
237 
238 	VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
239 	return allocation;
240 }
241 
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkImage image,vk::MemoryRequirement requirement)242 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkImage image, vk::MemoryRequirement requirement)
243 {
244 	const vk::VkMemoryRequirements	requirements	= vk::getImageMemoryRequirements(vki, device, image);
245 	de::MovePtr<vk::Allocation>		allocation		= allocator.allocate(requirements, requirement);
246 
247 	VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
248 	return allocation;
249 }
250 
makeDescriptorImageInfo(vk::VkSampler sampler)251 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkSampler sampler)
252 {
253 	return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0);
254 }
255 
makeDescriptorImageInfo(vk::VkImageView imageView,vk::VkImageLayout layout)256 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkImageView imageView, vk::VkImageLayout layout)
257 {
258 	return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout);
259 }
260 
drawQuadrantReferenceResult(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & c1,const tcu::Vec4 & c2,const tcu::Vec4 & c3,const tcu::Vec4 & c4)261 void drawQuadrantReferenceResult (const tcu::PixelBufferAccess& dst, const tcu::Vec4& c1, const tcu::Vec4& c2, const tcu::Vec4& c3, const tcu::Vec4& c4)
262 {
263 	tcu::clear(tcu::getSubregion(dst, 0,					0,						dst.getWidth() / 2,						dst.getHeight() / 2),					c1);
264 	tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2,	0,						dst.getWidth() - dst.getWidth() / 2,	dst.getHeight() / 2),					c2);
265 	tcu::clear(tcu::getSubregion(dst, 0,					dst.getHeight() / 2,	dst.getWidth() / 2,						dst.getHeight() - dst.getHeight() / 2),	c3);
266 	tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2,	dst.getHeight() / 2,	dst.getWidth() - dst.getWidth() / 2,	dst.getHeight() - dst.getHeight() / 2),	c4);
267 }
268 
269 class SingleTargetRenderInstance : public vkt::TestInstance
270 {
271 public:
272 											SingleTargetRenderInstance	(Context&			context,
273 																		 const tcu::UVec2&	size);
274 
275 private:
276 	static vk::Move<vk::VkImage>			createColorAttachment		(const vk::DeviceInterface&		vki,
277 																		 vk::VkDevice					device,
278 																		 vk::Allocator&					allocator,
279 																		 const tcu::TextureFormat&		format,
280 																		 const tcu::UVec2&				size,
281 																		 de::MovePtr<vk::Allocation>*	outAllocation);
282 
283 	static vk::Move<vk::VkImageView>		createColorAttachmentView	(const vk::DeviceInterface&	vki,
284 																		 vk::VkDevice				device,
285 																		 const tcu::TextureFormat&	format,
286 																		 vk::VkImage				image);
287 
288 	static vk::Move<vk::VkRenderPass>		createRenderPass			(const vk::DeviceInterface&	vki,
289 																		 vk::VkDevice				device,
290 																		 const tcu::TextureFormat&	format);
291 
292 	static vk::Move<vk::VkFramebuffer>		createFramebuffer			(const vk::DeviceInterface&	vki,
293 																		 vk::VkDevice				device,
294 																		 vk::VkRenderPass			renderpass,
295 																		 vk::VkImageView			colorAttachmentView,
296 																		 const tcu::UVec2&			size);
297 
298 	static vk::Move<vk::VkCommandPool>		createCommandPool			(const vk::DeviceInterface&	vki,
299 																		 vk::VkDevice				device,
300 																		 deUint32					queueFamilyIndex);
301 
302 	virtual void							logTestPlan					(void) const = 0;
303 	virtual void							renderToTarget				(void) = 0;
304 	virtual tcu::TestStatus					verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const = 0;
305 
306 	void									readRenderTarget			(tcu::TextureLevel& dst);
307 	tcu::TestStatus							iterate						(void);
308 
309 protected:
310 	const tcu::TextureFormat				m_targetFormat;
311 	const tcu::UVec2						m_targetSize;
312 
313 	const vk::DeviceInterface&				m_vki;
314 	const vk::VkDevice						m_device;
315 	const vk::VkQueue						m_queue;
316 	const deUint32							m_queueFamilyIndex;
317 	vk::Allocator&							m_allocator;
318 	de::MovePtr<vk::Allocation>				m_colorAttachmentMemory;
319 	const vk::Unique<vk::VkImage>			m_colorAttachmentImage;
320 	const vk::Unique<vk::VkImageView>		m_colorAttachmentView;
321 	const vk::Unique<vk::VkRenderPass>		m_renderPass;
322 	const vk::Unique<vk::VkFramebuffer>		m_framebuffer;
323 	const vk::Unique<vk::VkCommandPool>		m_cmdPool;
324 
325 	bool									m_firstIteration;
326 };
327 
SingleTargetRenderInstance(Context & context,const tcu::UVec2 & size)328 SingleTargetRenderInstance::SingleTargetRenderInstance (Context&			context,
329 														const tcu::UVec2&	size)
330 	: vkt::TestInstance			(context)
331 	, m_targetFormat			(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
332 	, m_targetSize				(size)
333 	, m_vki						(context.getDeviceInterface())
334 	, m_device					(context.getDevice())
335 	, m_queue					(context.getUniversalQueue())
336 	, m_queueFamilyIndex		(context.getUniversalQueueFamilyIndex())
337 	, m_allocator				(context.getDefaultAllocator())
338 	, m_colorAttachmentMemory	(DE_NULL)
339 	, m_colorAttachmentImage	(createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
340 	, m_colorAttachmentView		(createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
341 	, m_renderPass				(createRenderPass(m_vki, m_device, m_targetFormat))
342 	, m_framebuffer				(createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
343 	, m_cmdPool					(createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
344 	, m_firstIteration			(true)
345 {
346 }
347 
createColorAttachment(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,const tcu::TextureFormat & format,const tcu::UVec2 & size,de::MovePtr<vk::Allocation> * outAllocation)348 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment (const vk::DeviceInterface&		vki,
349 																		 vk::VkDevice					device,
350 																		 vk::Allocator&					allocator,
351 																		 const tcu::TextureFormat&		format,
352 																		 const tcu::UVec2&				size,
353 																		 de::MovePtr<vk::Allocation>*	outAllocation)
354 {
355 	const vk::VkImageCreateInfo	imageInfo	=
356 	{
357 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
358 		DE_NULL,
359 		(vk::VkImageCreateFlags)0,
360 		vk::VK_IMAGE_TYPE_2D,							// imageType
361 		vk::mapTextureFormat(format),					// format
362 		{ size.x(), size.y(), 1u },						// extent
363 		1,												// mipLevels
364 		1,												// arraySize
365 		vk::VK_SAMPLE_COUNT_1_BIT,						// samples
366 		vk::VK_IMAGE_TILING_OPTIMAL,					// tiling
367 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// usage
368 		vk::VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
369 		0u,												// queueFamilyCount
370 		DE_NULL,										// pQueueFamilyIndices
371 		vk::VK_IMAGE_LAYOUT_UNDEFINED,					// initialLayout
372 	};
373 
374 	vk::Move<vk::VkImage>		image		(vk::createImage(vki, device, &imageInfo));
375 	de::MovePtr<vk::Allocation>	allocation	(allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
376 
377 	*outAllocation = allocation;
378 	return image;
379 }
380 
createColorAttachmentView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format,vk::VkImage image)381 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView (const vk::DeviceInterface&	vki,
382 																				 vk::VkDevice				device,
383 																				 const tcu::TextureFormat&	format,
384 																				 vk::VkImage				image)
385 {
386 	const vk::VkImageViewCreateInfo createInfo =
387 	{
388 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
389 		DE_NULL,
390 		(vk::VkImageViewCreateFlags)0,
391 		image,							// image
392 		vk::VK_IMAGE_VIEW_TYPE_2D,		// viewType
393 		vk::mapTextureFormat(format),	// format
394 		vk::makeComponentMappingRGBA(),
395 		{
396 			vk::VK_IMAGE_ASPECT_COLOR_BIT,	// aspectMask
397 			0u,								// baseMipLevel
398 			1u,								// mipLevels
399 			0u,								// baseArrayLayer
400 			1u,								// arraySize
401 		},
402 	};
403 
404 	return vk::createImageView(vki, device, &createInfo);
405 }
406 
createRenderPass(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format)407 vk::Move<vk::VkRenderPass> SingleTargetRenderInstance::createRenderPass (const vk::DeviceInterface&		vki,
408 																		 vk::VkDevice					device,
409 																		 const tcu::TextureFormat&		format)
410 {
411 	const vk::VkAttachmentDescription	attachmentDescription	=
412 	{
413 		(vk::VkAttachmentDescriptionFlags)0,
414 		vk::mapTextureFormat(format),					// format
415 		vk::VK_SAMPLE_COUNT_1_BIT,						// samples
416 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				// loadOp
417 		vk::VK_ATTACHMENT_STORE_OP_STORE,				// storeOp
418 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// stencilLoadOp
419 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// stencilStoreOp
420 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// initialLayout
421 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// finalLayout
422 	};
423 	const vk::VkAttachmentReference		colorAttachment			=
424 	{
425 		0u,												// attachment
426 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// layout
427 	};
428 	const vk::VkAttachmentReference		depthStencilAttachment	=
429 	{
430 		vk::VK_NO_ATTACHMENT,							// attachment
431 		vk::VK_IMAGE_LAYOUT_UNDEFINED					// layout
432 	};
433 	const vk::VkSubpassDescription		subpass					=
434 	{
435 		(vk::VkSubpassDescriptionFlags)0,
436 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,			// pipelineBindPoint
437 		0u,												// inputAttachmentCount
438 		DE_NULL,										// pInputAttachments
439 		1u,												// colorAttachmentCount
440 		&colorAttachment,								// pColorAttachments
441 		DE_NULL,										// pResolveAttachments
442 		&depthStencilAttachment,						// pDepthStencilAttachment
443 		0u,												// preserveAttachmentCount
444 		DE_NULL											// pPreserveAttachments
445 	};
446 	const vk::VkRenderPassCreateInfo	renderPassCreateInfo	=
447 	{
448 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
449 		DE_NULL,
450 		(vk::VkRenderPassCreateFlags)0,
451 		1u,												// attachmentCount
452 		&attachmentDescription,							// pAttachments
453 		1u,												// subpassCount
454 		&subpass,										// pSubpasses
455 		0u,												// dependencyCount
456 		DE_NULL,										// pDependencies
457 	};
458 
459 	return vk::createRenderPass(vki, device, &renderPassCreateInfo);
460 }
461 
createFramebuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkRenderPass renderpass,vk::VkImageView colorAttachmentView,const tcu::UVec2 & size)462 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer (const vk::DeviceInterface&	vki,
463 																		   vk::VkDevice					device,
464 																		   vk::VkRenderPass				renderpass,
465 																		   vk::VkImageView				colorAttachmentView,
466 																		   const tcu::UVec2&			size)
467 {
468 	const vk::VkFramebufferCreateInfo	framebufferCreateInfo	=
469 	{
470 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
471 		DE_NULL,
472 		(vk::VkFramebufferCreateFlags)0,
473 		renderpass,				// renderPass
474 		1u,						// attachmentCount
475 		&colorAttachmentView,	// pAttachments
476 		size.x(),				// width
477 		size.y(),				// height
478 		1,						// layers
479 	};
480 
481 	return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
482 }
483 
createCommandPool(const vk::DeviceInterface & vki,vk::VkDevice device,deUint32 queueFamilyIndex)484 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool (const vk::DeviceInterface&	vki,
485 																		   vk::VkDevice					device,
486 																		   deUint32						queueFamilyIndex)
487 {
488 	const vk::VkCommandPoolCreateInfo createInfo =
489 	{
490 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
491 		DE_NULL,
492 		vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,	// flags
493 		queueFamilyIndex,							// queueFamilyIndex
494 	};
495 	return vk::createCommandPool(vki, device, &createInfo);
496 }
497 
readRenderTarget(tcu::TextureLevel & dst)498 void SingleTargetRenderInstance::readRenderTarget (tcu::TextureLevel& dst)
499 {
500 	const deUint64							pixelDataSize				= (deUint64)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
501 	const vk::VkBufferCreateInfo			bufferCreateInfo			=
502 	{
503 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
504 		DE_NULL,
505 		0u,												// flags
506 		pixelDataSize,									// size
507 		vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// usage
508 		vk::VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
509 		0u,												// queueFamilyCount
510 		DE_NULL,										// pQueueFamilyIndices
511 	};
512 	const vk::Unique<vk::VkBuffer>			buffer						(vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
513 	const vk::VkImageSubresourceRange		fullSubrange				=
514 	{
515 		vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
516 		0u,												// baseMipLevel
517 		1u,												// mipLevels
518 		0u,												// baseArraySlice
519 		1u,												// arraySize
520 	};
521 	const vk::VkImageMemoryBarrier			imageBarrier				=
522 	{
523 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
524 		DE_NULL,
525 		vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// srcAccessMask
526 		vk::VK_ACCESS_TRANSFER_READ_BIT,				// dstAccessMask
527 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// oldLayout
528 		vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// newLayout
529 		vk::VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
530 		vk::VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
531 		*m_colorAttachmentImage,						// image
532 		fullSubrange,									// subresourceRange
533 	};
534 	const vk::VkBufferMemoryBarrier			memoryBarrier				=
535 	{
536 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
537 		DE_NULL,
538 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// srcAccessMask
539 		vk::VK_ACCESS_HOST_READ_BIT,					// dstAccessMask
540 		vk::VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
541 		vk::VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
542 		*buffer,										// buffer
543 		0u,												// offset
544 		(vk::VkDeviceSize)pixelDataSize					// size
545 	};
546 	const vk::VkCommandBufferAllocateInfo	cmdBufAllocInfo				=
547 	{
548 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
549 		DE_NULL,
550 		*m_cmdPool,								// cmdPool
551 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,	// level
552 		1u,										// bufferCount
553 	};
554 	const vk::VkFenceCreateInfo				fenceCreateInfo				=
555 	{
556 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
557 		DE_NULL,
558 		0u,												// flags
559 	};
560 	const vk::VkCommandBufferBeginInfo		cmdBufBeginInfo				=
561 	{
562 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
563 		DE_NULL,
564 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
565 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
566 	};
567 	const vk::VkImageSubresourceLayers		firstSlice					=
568 	{
569 		vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspect
570 		0,												// mipLevel
571 		0,												// arrayLayer
572 		1,												// arraySize
573 	};
574 	const vk::VkBufferImageCopy				copyRegion					=
575 	{
576 		0u,												// bufferOffset
577 		m_targetSize.x(),								// bufferRowLength
578 		m_targetSize.y(),								// bufferImageHeight
579 		firstSlice,										// imageSubresource
580 		{ 0, 0, 0 },									// imageOffset
581 		{ m_targetSize.x(), m_targetSize.y(), 1u }		// imageExtent
582 	};
583 
584 	const de::MovePtr<vk::Allocation>		bufferMemory				= allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
585 
586 	const vk::Unique<vk::VkCommandBuffer>	cmd							(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
587 	const vk::Unique<vk::VkFence>			cmdCompleteFence			(vk::createFence(m_vki, m_device, &fenceCreateInfo));
588 	const deUint64							infiniteTimeout				= ~(deUint64)0u;
589 
590 	// copy content to buffer
591 	VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
592 	m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
593 							 0, (const vk::VkMemoryBarrier*)DE_NULL,
594 							 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
595 							 1, &imageBarrier);
596 	m_vki.cmdCopyImageToBuffer(*cmd, *m_colorAttachmentImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, &copyRegion);
597 	m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
598 							 0, (const vk::VkMemoryBarrier*)DE_NULL,
599 							 1, &memoryBarrier,
600 							 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
601 	VK_CHECK(m_vki.endCommandBuffer(*cmd));
602 
603 	// wait for transfer to complete
604 	{
605 		const vk::VkSubmitInfo	submitInfo	=
606 		{
607 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
608 			DE_NULL,
609 			0u,
610 			(const vk::VkSemaphore*)0,
611 			(const vk::VkPipelineStageFlags*)DE_NULL,
612 			1u,
613 			&cmd.get(),
614 			0u,
615 			(const vk::VkSemaphore*)0,
616 		};
617 
618 		VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *cmdCompleteFence));
619 	}
620 	VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
621 
622 	dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
623 
624 	// copy data
625 	invalidateMappedMemoryRange(m_vki, m_device, bufferMemory->getMemory(), bufferMemory->getOffset(), pixelDataSize);
626 	tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
627 }
628 
iterate(void)629 tcu::TestStatus SingleTargetRenderInstance::iterate (void)
630 {
631 	tcu::TextureLevel resultImage;
632 
633 	// log
634 	if (m_firstIteration)
635 	{
636 		logTestPlan();
637 		m_firstIteration = false;
638 	}
639 
640 	// render
641 	{
642 		// transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
643 		const vk::VkImageSubresourceRange		fullSubrange				=
644 		{
645 			vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
646 			0u,												// baseMipLevel
647 			1u,												// mipLevels
648 			0u,												// baseArraySlice
649 			1u,												// arraySize
650 		};
651 		const vk::VkImageMemoryBarrier			imageBarrier				=
652 		{
653 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
654 			DE_NULL,
655 			0u,												// srcAccessMask
656 			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// dstAccessMask
657 			vk::VK_IMAGE_LAYOUT_UNDEFINED,					// oldLayout
658 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// newLayout
659 			vk::VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
660 			vk::VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
661 			*m_colorAttachmentImage,						// image
662 			fullSubrange,									// subresourceRange
663 		};
664 		const vk::VkCommandBufferAllocateInfo	cmdBufAllocInfo				=
665 		{
666 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
667 			DE_NULL,
668 			*m_cmdPool,										// cmdPool
669 			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,			// level
670 			1u,												// count
671 		};
672 		const vk::VkCommandBufferBeginInfo		cmdBufBeginInfo				=
673 		{
674 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
675 			DE_NULL,
676 			vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
677 			(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
678 		};
679 		const vk::VkFenceCreateInfo				fenceCreateInfo				=
680 		{
681 			vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
682 			DE_NULL,
683 			(vk::VkFenceCreateFlags)0,
684 		};
685 
686 		const vk::Unique<vk::VkCommandBuffer>	cmd					(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo));
687 		const vk::Unique<vk::VkFence>			fence				(vk::createFence(m_vki, m_device, &fenceCreateInfo));
688 		const deUint64							infiniteTimeout		= ~(deUint64)0u;
689 
690 		VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
691 		m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
692 								 0, (const vk::VkMemoryBarrier*)DE_NULL,
693 								 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
694 								 1, &imageBarrier);
695 		VK_CHECK(m_vki.endCommandBuffer(*cmd));
696 
697 		{
698 			const vk::VkSubmitInfo	submitInfo	=
699 			{
700 				vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
701 				DE_NULL,
702 				0u,
703 				(const vk::VkSemaphore*)0,
704 				(const vk::VkPipelineStageFlags*)DE_NULL,
705 				1u,
706 				&cmd.get(),
707 				0u,
708 				(const vk::VkSemaphore*)0,
709 			};
710 
711 			VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence));
712 		}
713 		VK_CHECK(m_vki.waitForFences(m_device, 1u, &fence.get(), vk::VK_TRUE, infiniteTimeout));
714 
715 		// and then render to
716 		renderToTarget();
717 	}
718 
719 	// read and verify
720 	readRenderTarget(resultImage);
721 	return verifyResultImage(resultImage.getAccess());
722 }
723 
724 class RenderInstanceShaders
725 {
726 public:
727 														RenderInstanceShaders		(const vk::DeviceInterface&				vki,
728 																					 vk::VkDevice							device,
729 																					 const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
730 																					 const vk::BinaryCollection&			programCollection);
731 
hasTessellationStage(void) const732 	inline bool											hasTessellationStage		(void) const { return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0;	}
getNumStages(void) const733 	inline deUint32										getNumStages				(void) const { return (deUint32)m_stageInfos.size();								}
getStages(void) const734 	inline const vk::VkPipelineShaderStageCreateInfo*	getStages					(void) const { return &m_stageInfos[0];												}
735 
736 private:
737 	void												addStage					(const vk::DeviceInterface&				vki,
738 																					 vk::VkDevice							device,
739 																					 const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
740 																					 const vk::BinaryCollection&			programCollection,
741 																					 const char*							name,
742 																					 vk::VkShaderStageFlagBits				stage,
743 																					 vk::Move<vk::VkShaderModule>*			outModule);
744 
745 	vk::VkPipelineShaderStageCreateInfo					getShaderStageCreateInfo	(vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const;
746 
747 	vk::Move<vk::VkShaderModule>						m_vertexShaderModule;
748 	vk::Move<vk::VkShaderModule>						m_tessCtrlShaderModule;
749 	vk::Move<vk::VkShaderModule>						m_tessEvalShaderModule;
750 	vk::Move<vk::VkShaderModule>						m_geometryShaderModule;
751 	vk::Move<vk::VkShaderModule>						m_fragmentShaderModule;
752 	std::vector<vk::VkPipelineShaderStageCreateInfo>	m_stageInfos;
753 };
754 
RenderInstanceShaders(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection)755 RenderInstanceShaders::RenderInstanceShaders (const vk::DeviceInterface&			vki,
756 											  vk::VkDevice							device,
757 											  const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
758 											  const vk::BinaryCollection&			programCollection)
759 {
760 	addStage(vki, device, deviceFeatures, programCollection, "vertex",		vk::VK_SHADER_STAGE_VERTEX_BIT,						&m_vertexShaderModule);
761 	addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl",	vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		&m_tessCtrlShaderModule);
762 	addStage(vki, device, deviceFeatures, programCollection, "tess_eval",	vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	&m_tessEvalShaderModule);
763 	addStage(vki, device, deviceFeatures, programCollection, "geometry",	vk::VK_SHADER_STAGE_GEOMETRY_BIT,					&m_geometryShaderModule);
764 	addStage(vki, device, deviceFeatures, programCollection, "fragment",	vk::VK_SHADER_STAGE_FRAGMENT_BIT,					&m_fragmentShaderModule);
765 
766 	DE_ASSERT(!m_stageInfos.empty());
767 }
768 
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)769 void RenderInstanceShaders::addStage (const vk::DeviceInterface&			vki,
770 									  vk::VkDevice							device,
771 									  const vk::VkPhysicalDeviceFeatures&	deviceFeatures,
772 									  const vk::BinaryCollection&			programCollection,
773 									  const char*							name,
774 									  vk::VkShaderStageFlagBits				stage,
775 									  vk::Move<vk::VkShaderModule>*			outModule)
776 {
777 	if (programCollection.contains(name))
778 	{
779 		if (vk::isShaderStageSupported(deviceFeatures, stage))
780 		{
781 			vk::Move<vk::VkShaderModule>	module	= createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
782 
783 			m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
784 			*outModule = module;
785 		}
786 		else
787 		{
788 			// Wait for the GPU to idle so that throwing the exception
789 			// below doesn't free in-use GPU resource.
790 			vki.deviceWaitIdle(device);
791 			TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
792 		}
793 	}
794 }
795 
getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,vk::VkShaderModule shader) const796 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const
797 {
798 	const vk::VkPipelineShaderStageCreateInfo	stageCreateInfo	=
799 	{
800 		vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
801 		DE_NULL,
802 		(vk::VkPipelineShaderStageCreateFlags)0,
803 		stage,			// stage
804 		shader,			// shader
805 		"main",
806 		DE_NULL,		// pSpecializationInfo
807 	};
808 	return stageCreateInfo;
809 }
810 
811 class SingleCmdRenderInstance : public SingleTargetRenderInstance
812 {
813 public:
814 									SingleCmdRenderInstance	(Context&			context,
815 															 bool				isPrimaryCmdBuf,
816 															 const tcu::UVec2&	renderSize);
817 
818 private:
819 	vk::Move<vk::VkPipeline>		createPipeline				(vk::VkPipelineLayout pipelineLayout);
820 
821 	virtual vk::VkPipelineLayout	getPipelineLayout			(void) const = 0;
822 	virtual void					writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const = 0;
823 
824 	void							renderToTarget				(void);
825 
826 	const bool						m_isPrimaryCmdBuf;
827 };
828 
SingleCmdRenderInstance(Context & context,bool isPrimaryCmdBuf,const tcu::UVec2 & renderSize)829 SingleCmdRenderInstance::SingleCmdRenderInstance (Context&			context,
830 												  bool				isPrimaryCmdBuf,
831 												  const tcu::UVec2&	renderSize)
832 	: SingleTargetRenderInstance	(context, renderSize)
833 	, m_isPrimaryCmdBuf				(isPrimaryCmdBuf)
834 {
835 }
836 
createPipeline(vk::VkPipelineLayout pipelineLayout)837 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline (vk::VkPipelineLayout pipelineLayout)
838 {
839 	const RenderInstanceShaders							shaderStages		(m_vki, m_device, m_context.getDeviceFeatures(), m_context.getBinaryCollection());
840 	const vk::VkPrimitiveTopology						topology			= shaderStages.hasTessellationStage() ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
841 	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputState	=
842 	{
843 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
844 		DE_NULL,
845 		(vk::VkPipelineVertexInputStateCreateFlags)0,
846 		0u,											// bindingCount
847 		DE_NULL,									// pVertexBindingDescriptions
848 		0u,											// attributeCount
849 		DE_NULL,									// pVertexAttributeDescriptions
850 	};
851 	const vk::VkPipelineInputAssemblyStateCreateInfo	iaState				=
852 	{
853 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
854 		DE_NULL,
855 		(vk::VkPipelineInputAssemblyStateCreateFlags)0,
856 		topology,									// topology
857 		vk::VK_FALSE,								// primitiveRestartEnable
858 	};
859 	const vk::VkPipelineTessellationStateCreateInfo		tessState			=
860 	{
861 		vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
862 		DE_NULL,
863 		(vk::VkPipelineTessellationStateCreateFlags)0,
864 		3u,											// patchControlPoints
865 	};
866 	const vk::VkViewport								viewport			=
867 	{
868 		0.0f,										// originX
869 		0.0f,										// originY
870 		float(m_targetSize.x()),					// width
871 		float(m_targetSize.y()),					// height
872 		0.0f,										// minDepth
873 		1.0f,										// maxDepth
874 	};
875 	const vk::VkRect2D									renderArea			=
876 	{
877 		{ 0, 0 },									// offset
878 		{ m_targetSize.x(), m_targetSize.y() },		// extent
879 	};
880 	const vk::VkPipelineViewportStateCreateInfo			vpState				=
881 	{
882 		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
883 		DE_NULL,
884 		(vk::VkPipelineViewportStateCreateFlags)0,
885 		1u,											// viewportCount
886 		&viewport,
887 		1u,
888 		&renderArea,
889 	};
890 	const vk::VkPipelineRasterizationStateCreateInfo	rsState				=
891 	{
892 		vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
893 		DE_NULL,
894 		(vk::VkPipelineRasterizationStateCreateFlags)0,
895 		vk::VK_TRUE,								// depthClipEnable
896 		vk::VK_FALSE,								// rasterizerDiscardEnable
897 		vk::VK_POLYGON_MODE_FILL,					// fillMode
898 		vk::VK_CULL_MODE_NONE,						// cullMode
899 		vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,		// frontFace
900 		vk::VK_FALSE,								// depthBiasEnable
901 		0.0f,										// depthBias
902 		0.0f,										// depthBiasClamp
903 		0.0f,										// slopeScaledDepthBias
904 		1.0f,										// lineWidth
905 	};
906 	const vk::VkSampleMask								sampleMask			= 0x01u;
907 	const vk::VkPipelineMultisampleStateCreateInfo		msState				=
908 	{
909 		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
910 		DE_NULL,
911 		(vk::VkPipelineMultisampleStateCreateFlags)0,
912 		vk::VK_SAMPLE_COUNT_1_BIT,					// rasterSamples
913 		vk::VK_FALSE,								// sampleShadingEnable
914 		0.0f,										// minSampleShading
915 		&sampleMask,								// sampleMask
916 		vk::VK_FALSE,								// alphaToCoverageEnable
917 		vk::VK_FALSE,								// alphaToOneEnable
918 	};
919 	const vk::VkPipelineDepthStencilStateCreateInfo		dsState				=
920 	{
921 		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
922 		DE_NULL,
923 		(vk::VkPipelineDepthStencilStateCreateFlags)0,
924 		vk::VK_FALSE,								// depthTestEnable
925 		vk::VK_FALSE,								// depthWriteEnable
926 		vk::VK_COMPARE_OP_ALWAYS,					// depthCompareOp
927 		vk::VK_FALSE,								// depthBoundsTestEnable
928 		vk::VK_FALSE,								// stencilTestEnable
929 		{ vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },	// front
930 		{ vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },	// back
931 		-1.0f,										// minDepthBounds
932 		+1.0f,										// maxDepthBounds
933 	};
934 	const vk::VkPipelineColorBlendAttachmentState		cbAttachment		=
935 	{
936 		vk::VK_FALSE,								// blendEnable
937 		vk::VK_BLEND_FACTOR_ZERO,					// srcBlendColor
938 		vk::VK_BLEND_FACTOR_ZERO,					// destBlendColor
939 		vk::VK_BLEND_OP_ADD,						// blendOpColor
940 		vk::VK_BLEND_FACTOR_ZERO,					// srcBlendAlpha
941 		vk::VK_BLEND_FACTOR_ZERO,					// destBlendAlpha
942 		vk::VK_BLEND_OP_ADD,						// blendOpAlpha
943 		(vk::VK_COLOR_COMPONENT_R_BIT |
944 		 vk::VK_COLOR_COMPONENT_G_BIT |
945 		 vk::VK_COLOR_COMPONENT_B_BIT |
946 		 vk::VK_COLOR_COMPONENT_A_BIT),				// channelWriteMask
947 	};
948 	const vk::VkPipelineColorBlendStateCreateInfo		cbState				=
949 	{
950 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
951 		DE_NULL,
952 		(vk::VkPipelineColorBlendStateCreateFlags)0,
953 		vk::VK_FALSE,								// logicOpEnable
954 		vk::VK_LOGIC_OP_CLEAR,						// logicOp
955 		1u,											// attachmentCount
956 		&cbAttachment,								// pAttachments
957 		{ 0.0f, 0.0f, 0.0f, 0.0f },					// blendConst
958 	};
959 	const vk::VkGraphicsPipelineCreateInfo createInfo =
960 	{
961 		vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
962 		DE_NULL,
963 		(vk::VkPipelineCreateFlags)0,
964 		shaderStages.getNumStages(),									// stageCount
965 		shaderStages.getStages(),										// pStages
966 		&vertexInputState,												// pVertexInputState
967 		&iaState,														// pInputAssemblyState
968 		(shaderStages.hasTessellationStage() ? &tessState : DE_NULL),	// pTessellationState
969 		&vpState,														// pViewportState
970 		&rsState,														// pRasterState
971 		&msState,														// pMultisampleState
972 		&dsState,														// pDepthStencilState
973 		&cbState,														// pColorBlendState
974 		(const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL,			// pDynamicState
975 		pipelineLayout,													// layout
976 		*m_renderPass,													// renderPass
977 		0u,																// subpass
978 		(vk::VkPipeline)0,												// basePipelineHandle
979 		0u,																// basePipelineIndex
980 	};
981 	return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
982 }
983 
renderToTarget(void)984 void SingleCmdRenderInstance::renderToTarget (void)
985 {
986 	const vk::VkRect2D									renderArea						=
987 	{
988 		{ 0, 0 },								// offset
989 		{ m_targetSize.x(), m_targetSize.y() },	// extent
990 	};
991 	const vk::VkCommandBufferAllocateInfo				mainCmdBufCreateInfo			=
992 	{
993 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
994 		DE_NULL,
995 		*m_cmdPool,								// cmdPool
996 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,	// level
997 		1u,										// count
998 	};
999 	const vk::VkCommandBufferBeginInfo					mainCmdBufBeginInfo				=
1000 	{
1001 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1002 		DE_NULL,
1003 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
1004 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1005 	};
1006 	const vk::VkCommandBufferAllocateInfo				passCmdBufCreateInfo			=
1007 	{
1008 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1009 		DE_NULL,
1010 		*m_cmdPool,								// cmdPool
1011 		vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY,	// level
1012 		1u,										// count
1013 	};
1014 	const vk::VkCommandBufferInheritanceInfo			passCmdBufInheritInfo			=
1015 	{
1016 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1017 		DE_NULL,
1018 		(vk::VkRenderPass)*m_renderPass,						// renderPass
1019 		0u,														// subpass
1020 		(vk::VkFramebuffer)*m_framebuffer,						// framebuffer
1021 		vk::VK_FALSE,											// occlusionQueryEnable
1022 		(vk::VkQueryControlFlags)0,
1023 		(vk::VkQueryPipelineStatisticFlags)0,
1024 	};
1025 	const vk::VkCommandBufferBeginInfo					passCmdBufBeginInfo				=
1026 	{
1027 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1028 		DE_NULL,
1029 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
1030 		vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,	// flags
1031 		&passCmdBufInheritInfo,
1032 	};
1033 	const vk::VkFenceCreateInfo							fenceCreateInfo				=
1034 	{
1035 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1036 		DE_NULL,
1037 		0u,			// flags
1038 	};
1039 	const vk::VkClearValue								clearValue					= vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
1040 	const vk::VkRenderPassBeginInfo						renderPassBeginInfo			=
1041 	{
1042 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1043 		DE_NULL,
1044 		*m_renderPass,		// renderPass
1045 		*m_framebuffer,		// framebuffer
1046 		renderArea,			// renderArea
1047 		1u,					// clearValueCount
1048 		&clearValue,		// pClearValues
1049 	};
1050 
1051 	const vk::VkPipelineLayout							pipelineLayout				(getPipelineLayout());
1052 	const vk::Unique<vk::VkPipeline>					pipeline					(createPipeline(pipelineLayout));
1053 	const vk::Unique<vk::VkCommandBuffer>				mainCmd						(vk::allocateCommandBuffer(m_vki, m_device, &mainCmdBufCreateInfo));
1054 	const vk::Unique<vk::VkCommandBuffer>				passCmd						((m_isPrimaryCmdBuf) ? (vk::Move<vk::VkCommandBuffer>()) : (vk::allocateCommandBuffer(m_vki, m_device, &passCmdBufCreateInfo)));
1055 	const vk::Unique<vk::VkFence>						fence						(vk::createFence(m_vki, m_device, &fenceCreateInfo));
1056 	const deUint64										infiniteTimeout				= ~(deUint64)0u;
1057 	const vk::VkSubpassContents							passContents				= (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1058 
1059 	VK_CHECK(m_vki.beginCommandBuffer(*mainCmd, &mainCmdBufBeginInfo));
1060 	m_vki.cmdBeginRenderPass(*mainCmd, &renderPassBeginInfo, passContents);
1061 
1062 	if (m_isPrimaryCmdBuf)
1063 	{
1064 		m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1065 		writeDrawCmdBuffer(*mainCmd);
1066 	}
1067 	else
1068 	{
1069 		VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1070 		m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1071 		writeDrawCmdBuffer(*passCmd);
1072 		VK_CHECK(m_vki.endCommandBuffer(*passCmd));
1073 
1074 		m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1075 	}
1076 
1077 	m_vki.cmdEndRenderPass(*mainCmd);
1078 	VK_CHECK(m_vki.endCommandBuffer(*mainCmd));
1079 
1080 	// submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1081 	{
1082 		const vk::VkSubmitInfo	submitInfo	=
1083 		{
1084 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1085 			DE_NULL,
1086 			0u,
1087 			(const vk::VkSemaphore*)0,
1088 			(const vk::VkPipelineStageFlags*)DE_NULL,
1089 			1u,
1090 			&mainCmd.get(),
1091 			0u,
1092 			(const vk::VkSemaphore*)0,
1093 		};
1094 		VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *fence));
1095 	}
1096 	VK_CHECK(m_vki.waitForFences(m_device, 1, &fence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
1097 }
1098 
1099 enum ShaderInputInterface
1100 {
1101 	SHADER_INPUT_SINGLE_DESCRIPTOR = 0,					//!< one descriptor
1102 	SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS,		//!< multiple descriptors with contiguous binding id's
1103 	SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS,	//!< multiple descriptors with discontiguous binding id's
1104 	SHADER_INPUT_DESCRIPTOR_ARRAY,						//!< descriptor array
1105 
1106 	SHADER_INPUT_LAST
1107 };
1108 
getInterfaceNumResources(ShaderInputInterface shaderInterface)1109 deUint32 getInterfaceNumResources (ShaderInputInterface shaderInterface)
1110 {
1111 	switch (shaderInterface)
1112 	{
1113 		case SHADER_INPUT_SINGLE_DESCRIPTOR:					return 1u;
1114 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:		return 2u;
1115 		case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:	return 2u;
1116 		case SHADER_INPUT_DESCRIPTOR_ARRAY:						return 2u;
1117 
1118 		default:
1119 			DE_FATAL("Impossible");
1120 			return 0u;
1121 	}
1122 }
1123 
1124 class BufferRenderInstance : public SingleCmdRenderInstance
1125 {
1126 public:
1127 													BufferRenderInstance		(Context&					context,
1128 																				 bool						isPrimaryCmdBuf,
1129 																				 vk::VkDescriptorType		descriptorType,
1130 																				 vk::VkShaderStageFlags		stageFlags,
1131 																				 ShaderInputInterface		shaderInterface,
1132 																				 bool						viewOffset,
1133 																				 bool						dynamicOffset,
1134 																				 bool						dynamicOffsetNonZero);
1135 
1136 	static vk::Move<vk::VkBuffer>					createSourceBuffer			(const vk::DeviceInterface&		vki,
1137 																				 vk::VkDevice					device,
1138 																				 vk::Allocator&					allocator,
1139 																				 vk::VkDescriptorType			descriptorType,
1140 																				 deUint32						offset,
1141 																				 deUint32						bufferSize,
1142 																				 de::MovePtr<vk::Allocation>*	outMemory);
1143 
1144 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(const vk::DeviceInterface&	vki,
1145 																				 vk::VkDevice				device,
1146 																				 vk::VkDescriptorType		descriptorType,
1147 																				 ShaderInputInterface		shaderInterface);
1148 
1149 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(const vk::DeviceInterface&	vki,
1150 																				 vk::VkDevice				device,
1151 																				 vk::VkDescriptorType		descriptorType,
1152 																				 ShaderInputInterface		shaderInterface,
1153 																				 vk::VkShaderStageFlags		stageFlags);
1154 
1155 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(const vk::DeviceInterface&	vki,
1156 																				 vk::VkDevice				device,
1157 																				 vk::VkDescriptorSetLayout	descriptorSetLayout,
1158 																				 vk::VkDescriptorPool		descriptorPool,
1159 																				 vk::VkDescriptorType		descriptorType,
1160 																				 ShaderInputInterface		shaderInterface,
1161 																				 vk::VkBuffer				sourceBufferA,
1162 																				 const deUint32				viewOffsetA,
1163 																				 vk::VkBuffer				sourceBufferB,
1164 																				 const deUint32				viewOffsetB);
1165 
1166 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout		(const vk::DeviceInterface&	vki,
1167 																				 vk::VkDevice				device,
1168 																				 vk::VkDescriptorSetLayout	descriptorSetLayout);
1169 
1170 	void											logTestPlan					(void) const;
1171 	vk::VkPipelineLayout							getPipelineLayout			(void) const;
1172 	void											writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const;
1173 	tcu::TestStatus									verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const;
1174 
1175 	enum
1176 	{
1177 		RENDER_SIZE				= 128,
1178 		BUFFER_DATA_SIZE		= 8 * sizeof(float),
1179 		BUFFER_SIZE_A			= 2048, //!< a lot more than required
1180 		BUFFER_SIZE_B			= 2560, //!< a lot more than required
1181 
1182 		STATIC_OFFSET_VALUE_A	= 256,
1183 		DYNAMIC_OFFSET_VALUE_A	= 512,
1184 		STATIC_OFFSET_VALUE_B	= 1024,
1185 		DYNAMIC_OFFSET_VALUE_B	= 768,
1186 	};
1187 
1188 	const vk::VkDescriptorType						m_descriptorType;
1189 	const ShaderInputInterface						m_shaderInterface;
1190 	const bool										m_setViewOffset;
1191 	const bool										m_setDynamicOffset;
1192 	const bool										m_dynamicOffsetNonZero;
1193 	const vk::VkShaderStageFlags					m_stageFlags;
1194 
1195 	const deUint32									m_viewOffsetA;
1196 	const deUint32									m_viewOffsetB;
1197 	const deUint32									m_dynamicOffsetA;
1198 	const deUint32									m_dynamicOffsetB;
1199 	const deUint32									m_effectiveOffsetA;
1200 	const deUint32									m_effectiveOffsetB;
1201 	const deUint32									m_bufferSizeA;
1202 	const deUint32									m_bufferSizeB;
1203 
1204 	de::MovePtr<vk::Allocation>						m_bufferMemoryA;
1205 	de::MovePtr<vk::Allocation>						m_bufferMemoryB;
1206 	const vk::Unique<vk::VkBuffer>					m_sourceBufferA;
1207 	const vk::Unique<vk::VkBuffer>					m_sourceBufferB;
1208 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
1209 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
1210 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
1211 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
1212 };
1213 
BufferRenderInstance(Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero)1214 BufferRenderInstance::BufferRenderInstance	(Context&				context,
1215 											 bool					isPrimaryCmdBuf,
1216 											 vk::VkDescriptorType	descriptorType,
1217 											 vk::VkShaderStageFlags	stageFlags,
1218 											 ShaderInputInterface	shaderInterface,
1219 											 bool					viewOffset,
1220 											 bool					dynamicOffset,
1221 											 bool					dynamicOffsetNonZero)
1222 	: SingleCmdRenderInstance		(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
1223 	, m_descriptorType				(descriptorType)
1224 	, m_shaderInterface				(shaderInterface)
1225 	, m_setViewOffset				(viewOffset)
1226 	, m_setDynamicOffset			(dynamicOffset)
1227 	, m_dynamicOffsetNonZero		(dynamicOffsetNonZero)
1228 	, m_stageFlags					(stageFlags)
1229 	, m_viewOffsetA					((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u))
1230 	, m_viewOffsetB					((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u))
1231 	, m_dynamicOffsetA				((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u))
1232 	, m_dynamicOffsetB				((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u))
1233 	, m_effectiveOffsetA			((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetA + m_dynamicOffsetA) : (m_viewOffsetA))
1234 	, m_effectiveOffsetB			((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetB + m_dynamicOffsetB) : (m_viewOffsetB))
1235 	, m_bufferSizeA					(BUFFER_SIZE_A)
1236 	, m_bufferSizeB					(BUFFER_SIZE_B)
1237 	, m_bufferMemoryA				(DE_NULL)
1238 	, m_bufferMemoryB				(DE_NULL)
1239 	, m_sourceBufferA				(createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetA, m_bufferSizeA, &m_bufferMemoryA))
1240 	, m_sourceBufferB				((getInterfaceNumResources(m_shaderInterface) == 1u)
1241 										? vk::Move<vk::VkBuffer>()
1242 										: createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetB, m_bufferSizeB, &m_bufferMemoryB))
1243 	, m_descriptorPool				(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
1244 	, m_descriptorSetLayout			(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
1245 	, m_descriptorSet				(createDescriptorSet(m_vki, m_device, *m_descriptorSetLayout, *m_descriptorPool, m_descriptorType, m_shaderInterface, *m_sourceBufferA, m_viewOffsetA, *m_sourceBufferB, m_viewOffsetB))
1246 	, m_pipelineLayout				(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
1247 {
1248 	if (m_setDynamicOffset)
1249 		DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1250 	if (m_dynamicOffsetNonZero)
1251 		DE_ASSERT(m_setDynamicOffset);
1252 }
1253 
createSourceBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,deUint32 offset,deUint32 bufferSize,de::MovePtr<vk::Allocation> * outMemory)1254 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer (const vk::DeviceInterface&		vki,
1255 																 vk::VkDevice					device,
1256 																 vk::Allocator&					allocator,
1257 																 vk::VkDescriptorType			descriptorType,
1258 																 deUint32						offset,
1259 																 deUint32						bufferSize,
1260 																 de::MovePtr<vk::Allocation>*	outMemory)
1261 {
1262 	static const float				s_colors[]			=
1263 	{
1264 		0.0f, 1.0f, 0.0f, 1.0f,		// green
1265 		1.0f, 1.0f, 0.0f, 1.0f,		// yellow
1266 	};
1267 	DE_STATIC_ASSERT(sizeof(s_colors) == BUFFER_DATA_SIZE);
1268 	DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1269 	DE_ASSERT(offset % sizeof(float) == 0);
1270 	DE_ASSERT(bufferSize % sizeof(float) == 0);
1271 
1272 	const bool						isUniformBuffer		= isUniformDescriptorType(descriptorType);
1273 	const vk::VkBufferUsageFlags	usageFlags			= (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1274 	const float						preGuardValue		= 0.5f;
1275 	const float						postGuardValue		= 0.75f;
1276 	const vk::VkBufferCreateInfo	bufferCreateInfo	=
1277 	{
1278 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1279 		DE_NULL,
1280 		0u,								// flags
1281 		bufferSize,						// size
1282 		usageFlags,						// usage
1283 		vk::VK_SHARING_MODE_EXCLUSIVE,	// sharingMode
1284 		0u,								// queueFamilyCount
1285 		DE_NULL,						// pQueueFamilyIndices
1286 	};
1287 	vk::Move<vk::VkBuffer>			buffer				(vk::createBuffer(vki, device, &bufferCreateInfo));
1288 	de::MovePtr<vk::Allocation>		bufferMemory		= allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1289 	void* const						mapPtr				= bufferMemory->getHostPtr();
1290 
1291 	// guard with interesting values
1292 	for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1293 		deMemcpy((deUint8*)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1294 
1295 	deMemcpy((deUint8*)mapPtr + offset, s_colors, sizeof(s_colors));
1296 	for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors); postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1297 		deMemcpy((deUint8*)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1298 	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
1299 
1300 	flushMappedMemoryRange(vki, device, bufferMemory->getMemory(), bufferMemory->getOffset(), bufferSize);
1301 
1302 	// Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
1303 
1304 	*outMemory = bufferMemory;
1305 	return buffer;
1306 }
1307 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)1308 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
1309 																		   vk::VkDevice					device,
1310 																		   vk::VkDescriptorType			descriptorType,
1311 																		   ShaderInputInterface			shaderInterface)
1312 {
1313 	return vk::DescriptorPoolBuilder()
1314 		.addType(descriptorType, getInterfaceNumResources(shaderInterface))
1315 		.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1316 }
1317 
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags)1318 vk::Move<vk::VkDescriptorSetLayout> BufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&	vki,
1319 																					 vk::VkDevice				device,
1320 																					 vk::VkDescriptorType		descriptorType,
1321 																					 ShaderInputInterface		shaderInterface,
1322 																					 vk::VkShaderStageFlags		stageFlags)
1323 {
1324 	vk::DescriptorSetLayoutBuilder builder;
1325 
1326 	switch (shaderInterface)
1327 	{
1328 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
1329 			builder.addSingleBinding(descriptorType, stageFlags);
1330 			break;
1331 
1332 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1333 			builder.addSingleBinding(descriptorType, stageFlags);
1334 			builder.addSingleBinding(descriptorType, stageFlags);
1335 			break;
1336 
1337 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
1338 			builder.addArrayBinding(descriptorType, 2u, stageFlags);
1339 			break;
1340 
1341 		default:
1342 			DE_FATAL("Impossible");
1343 	}
1344 
1345 	return builder.build(vki, device);
1346 }
1347 
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkBuffer bufferA,deUint32 offsetA,vk::VkBuffer bufferB,deUint32 offsetB)1348 vk::Move<vk::VkDescriptorSet> BufferRenderInstance::createDescriptorSet (const vk::DeviceInterface&	vki,
1349 																		 vk::VkDevice				device,
1350 																		 vk::VkDescriptorSetLayout	descriptorSetLayout,
1351 																		 vk::VkDescriptorPool		descriptorPool,
1352 																		 vk::VkDescriptorType		descriptorType,
1353 																		 ShaderInputInterface		shaderInterface,
1354 																		 vk::VkBuffer				bufferA,
1355 																		 deUint32					offsetA,
1356 																		 vk::VkBuffer				bufferB,
1357 																		 deUint32					offsetB)
1358 {
1359 	const vk::VkDescriptorBufferInfo		bufferInfos[2]	=
1360 	{
1361 		vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1362 		vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1363 	};
1364 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
1365 	{
1366 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1367 		DE_NULL,
1368 		descriptorPool,
1369 		1u,
1370 		&descriptorSetLayout
1371 	};
1372 
1373 	vk::Move<vk::VkDescriptorSet>	descriptorSet	= allocateDescriptorSet(vki, device, &allocInfo);
1374 	vk::DescriptorSetUpdateBuilder	builder;
1375 
1376 	switch (shaderInterface)
1377 	{
1378 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
1379 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
1380 			break;
1381 
1382 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1383 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
1384 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &bufferInfos[1]);
1385 			break;
1386 
1387 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
1388 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, bufferInfos);
1389 			break;
1390 
1391 		default:
1392 			DE_FATAL("Impossible");
1393 	}
1394 
1395 	builder.update(vki, device);
1396 	return descriptorSet;
1397 }
1398 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)1399 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
1400 																		   vk::VkDevice					device,
1401 																		   vk::VkDescriptorSetLayout	descriptorSetLayout)
1402 {
1403 	const vk::VkPipelineLayoutCreateInfo createInfo =
1404 	{
1405 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1406 		DE_NULL,
1407 		(vk::VkPipelineLayoutCreateFlags)0,
1408 		1,						// descriptorSetCount
1409 		&descriptorSetLayout,	// pSetLayouts
1410 		0u,						// pushConstantRangeCount
1411 		DE_NULL,				// pPushConstantRanges
1412 	};
1413 
1414 	return vk::createPipelineLayout(vki, device, &createInfo);
1415 }
1416 
logTestPlan(void) const1417 void BufferRenderInstance::logTestPlan (void) const
1418 {
1419 	std::ostringstream msg;
1420 
1421 	msg << "Rendering 2x2 yellow-green grid.\n"
1422 		<< "Single descriptor set. Descriptor set contains "
1423 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
1424 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
1425 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
1426 			    (const char*)DE_NULL)
1427 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1428 		<< "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1429 
1430 	if (isDynamicDescriptorType(m_descriptorType))
1431 	{
1432 		if (m_setDynamicOffset)
1433 		{
1434 			msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1435 				<< "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1436 		}
1437 		else
1438 		{
1439 			msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1440 		}
1441 	}
1442 
1443 	if (m_stageFlags == 0u)
1444 	{
1445 		msg << "Descriptors are not accessed in any shader stage.\n";
1446 	}
1447 	else
1448 	{
1449 		msg << "Descriptors are accessed in {"
1450 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
1451 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
1452 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
1453 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
1454 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
1455 			<< " } stages.\n";
1456 	}
1457 
1458 	m_context.getTestContext().getLog()
1459 		<< tcu::TestLog::Message
1460 		<< msg.str()
1461 		<< tcu::TestLog::EndMessage;
1462 }
1463 
getPipelineLayout(void) const1464 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout (void) const
1465 {
1466 	return *m_pipelineLayout;
1467 }
1468 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const1469 void BufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
1470 {
1471 	// \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1472 	const deUint32						dynamicOffsets[]	=
1473 	{
1474 		m_dynamicOffsetA,
1475 		m_dynamicOffsetB,
1476 	};
1477 	const deUint32						numOffsets			= (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1478 	const deUint32* const				dynamicOffsetPtr	= (!m_setDynamicOffset) ? (DE_NULL) : (dynamicOffsets);
1479 
1480 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), numOffsets, dynamicOffsetPtr);
1481 	m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1482 }
1483 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const1484 tcu::TestStatus BufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
1485 {
1486 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
1487 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
1488 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
1489 
1490 	drawQuadrantReferenceResult(reference.getAccess(), yellow, green, green, yellow);
1491 
1492 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1493 		return tcu::TestStatus::fail("Image verification failed");
1494 	else
1495 		return tcu::TestStatus::pass("Pass");
1496 }
1497 
1498 class ComputeInstanceResultBuffer
1499 {
1500 public:
1501 	enum
1502 	{
1503 		DATA_SIZE = sizeof(tcu::Vec4[4])
1504 	};
1505 
1506 											ComputeInstanceResultBuffer	(const vk::DeviceInterface&		vki,
1507 																		 vk::VkDevice					device,
1508 																		 vk::Allocator&					allocator);
1509 
1510 	void									readResultContentsTo		(tcu::Vec4 (*results)[4]) const;
1511 
getBuffer(void) const1512 	inline vk::VkBuffer						getBuffer					(void) const { return *m_buffer;			}
getResultReadBarrier(void) const1513 	inline const vk::VkBufferMemoryBarrier*	getResultReadBarrier		(void) const { return &m_bufferBarrier;		}
1514 
1515 private:
1516 	static vk::Move<vk::VkBuffer>			createResultBuffer			(const vk::DeviceInterface&		vki,
1517 																		 vk::VkDevice					device,
1518 																		 vk::Allocator&					allocator,
1519 																		 de::MovePtr<vk::Allocation>*	outAllocation);
1520 
1521 	static vk::VkBufferMemoryBarrier		createResultBufferBarrier	(vk::VkBuffer buffer);
1522 
1523 	const vk::DeviceInterface&				m_vki;
1524 	const vk::VkDevice						m_device;
1525 
1526 	de::MovePtr<vk::Allocation>				m_bufferMem;
1527 	const vk::Unique<vk::VkBuffer>			m_buffer;
1528 	const vk::VkBufferMemoryBarrier			m_bufferBarrier;
1529 };
1530 
ComputeInstanceResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator)1531 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const vk::DeviceInterface&	vki,
1532 														  vk::VkDevice					device,
1533 														  vk::Allocator&				allocator)
1534 	: m_vki				(vki)
1535 	, m_device			(device)
1536 	, m_bufferMem		(DE_NULL)
1537 	, m_buffer			(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
1538 	, m_bufferBarrier	(createResultBufferBarrier(*m_buffer))
1539 {
1540 }
1541 
readResultContentsTo(tcu::Vec4 (* results)[4]) const1542 void ComputeInstanceResultBuffer::readResultContentsTo (tcu::Vec4 (*results)[4]) const
1543 {
1544 	invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*results));
1545 	deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
1546 }
1547 
createResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,de::MovePtr<vk::Allocation> * outAllocation)1548 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer (const vk::DeviceInterface&		vki,
1549 																		vk::VkDevice					device,
1550 																		vk::Allocator&					allocator,
1551 																		de::MovePtr<vk::Allocation>*	outAllocation)
1552 {
1553 	const vk::VkBufferCreateInfo	createInfo	=
1554 	{
1555 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1556 		DE_NULL,
1557 		0u,											// flags
1558 		(vk::VkDeviceSize)DATA_SIZE,				// size
1559 		vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// usage
1560 		vk::VK_SHARING_MODE_EXCLUSIVE,				// sharingMode
1561 		0u,											// queueFamilyCount
1562 		DE_NULL,									// pQueueFamilyIndices
1563 	};
1564 	vk::Move<vk::VkBuffer>			buffer		(vk::createBuffer(vki, device, &createInfo));
1565 	de::MovePtr<vk::Allocation>		allocation	(allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
1566 	const float						clearValue	= -1.0f;
1567 	void*							mapPtr		= allocation->getHostPtr();
1568 
1569 	for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
1570 		deMemcpy(((deUint8*)mapPtr) + offset, &clearValue, sizeof(float));
1571 
1572 	flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), (vk::VkDeviceSize)DATA_SIZE);
1573 
1574 	*outAllocation = allocation;
1575 	return buffer;
1576 }
1577 
createResultBufferBarrier(vk::VkBuffer buffer)1578 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier (vk::VkBuffer buffer)
1579 {
1580 	const vk::VkBufferMemoryBarrier bufferBarrier =
1581 	{
1582 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1583 		DE_NULL,
1584 		vk::VK_ACCESS_SHADER_WRITE_BIT,				// outputMask
1585 		vk::VK_ACCESS_HOST_READ_BIT,				// inputMask
1586 		vk::VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
1587 		vk::VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
1588 		buffer,										// buffer
1589 		(vk::VkDeviceSize)0u,						// offset
1590 		DATA_SIZE,									// size
1591 	};
1592 	return bufferBarrier;
1593 }
1594 
1595 class ComputePipeline
1596 {
1597 public:
1598 											ComputePipeline			(const vk::DeviceInterface&			vki,
1599 																	 vk::VkDevice						device,
1600 																	 const vk::BinaryCollection&		programCollection,
1601 																	 deUint32							numDescriptorSets,
1602 																	 const vk::VkDescriptorSetLayout*	descriptorSetLayouts);
1603 
getPipeline(void) const1604 	inline vk::VkPipeline					getPipeline				(void) const { return *m_pipeline;			};
getPipelineLayout(void) const1605 	inline vk::VkPipelineLayout				getPipelineLayout		(void) const { return *m_pipelineLayout;	};
1606 
1607 private:
1608 	static vk::Move<vk::VkPipelineLayout>	createPipelineLayout	(const vk::DeviceInterface&			vki,
1609 																	 vk::VkDevice						device,
1610 																	 deUint32							numDescriptorSets,
1611 																	 const vk::VkDescriptorSetLayout*	descriptorSetLayouts);
1612 
1613 	static vk::Move<vk::VkPipeline>			createPipeline			(const vk::DeviceInterface&			vki,
1614 																	 vk::VkDevice						device,
1615 																	 const vk::BinaryCollection&		programCollection,
1616 																	 vk::VkPipelineLayout				layout);
1617 
1618 	const vk::Unique<vk::VkPipelineLayout>	m_pipelineLayout;
1619 	const vk::Unique<vk::VkPipeline>		m_pipeline;
1620 };
1621 
ComputePipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,deUint32 numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)1622 ComputePipeline::ComputePipeline (const vk::DeviceInterface&		vki,
1623 								  vk::VkDevice						device,
1624 								  const vk::BinaryCollection&		programCollection,
1625 								  deUint32							numDescriptorSets,
1626 								  const vk::VkDescriptorSetLayout*	descriptorSetLayouts)
1627 	: m_pipelineLayout	(createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
1628 	, m_pipeline		(createPipeline(vki, device, programCollection, *m_pipelineLayout))
1629 {
1630 }
1631 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,deUint32 numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)1632 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout (const vk::DeviceInterface&		vki,
1633 																	  vk::VkDevice						device,
1634 																	  deUint32							numDescriptorSets,
1635 																	  const vk::VkDescriptorSetLayout*	descriptorSetLayouts)
1636 {
1637 	const vk::VkPipelineLayoutCreateInfo createInfo =
1638 	{
1639 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1640 		DE_NULL,
1641 		(vk::VkPipelineLayoutCreateFlags)0,
1642 		numDescriptorSets,		// descriptorSetCount
1643 		descriptorSetLayouts,	// pSetLayouts
1644 		0u,						// pushConstantRangeCount
1645 		DE_NULL,				// pPushConstantRanges
1646 	};
1647 	return vk::createPipelineLayout(vki, device, &createInfo);
1648 }
1649 
createPipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,vk::VkPipelineLayout layout)1650 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline (const vk::DeviceInterface&	vki,
1651 														  vk::VkDevice					device,
1652 														  const vk::BinaryCollection&	programCollection,
1653 														  vk::VkPipelineLayout			layout)
1654 {
1655 	const vk::Unique<vk::VkShaderModule>		computeModule		(vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
1656 	const vk::VkPipelineShaderStageCreateInfo	cs					=
1657 	{
1658 		vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1659 		DE_NULL,
1660 		(vk::VkPipelineShaderStageCreateFlags)0,
1661 		vk::VK_SHADER_STAGE_COMPUTE_BIT,	// stage
1662 		*computeModule,						// shader
1663 		"main",
1664 		DE_NULL,							// pSpecializationInfo
1665 	};
1666 	const vk::VkComputePipelineCreateInfo		createInfo			=
1667 	{
1668 		vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1669 		DE_NULL,
1670 		0u,								// flags
1671 		cs,								// cs
1672 		layout,							// layout
1673 		(vk::VkPipeline)0,				// basePipelineHandle
1674 		0u,								// basePipelineIndex
1675 	};
1676 	return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
1677 }
1678 
1679 class ComputeCommand
1680 {
1681 public:
1682 											ComputeCommand	(const vk::DeviceInterface&			vki,
1683 															 vk::VkDevice						device,
1684 															 vk::VkPipeline						pipeline,
1685 															 vk::VkPipelineLayout				pipelineLayout,
1686 															 const tcu::UVec3&					numWorkGroups,
1687 															 int								numDescriptorSets,
1688 															 const vk::VkDescriptorSet*			descriptorSets,
1689 															 int								numDynamicOffsets,
1690 															 const deUint32*					dynamicOffsets,
1691 															 int								numPreBarriers,
1692 															 const vk::VkBufferMemoryBarrier*	preBarriers,
1693 															 int								numPostBarriers,
1694 															 const vk::VkBufferMemoryBarrier*	postBarriers);
1695 
1696 	void									submitAndWait	(deUint32 queueFamilyIndex, vk::VkQueue queue) const;
1697 
1698 private:
1699 	const vk::DeviceInterface&				m_vki;
1700 	const vk::VkDevice						m_device;
1701 	const vk::VkPipeline					m_pipeline;
1702 	const vk::VkPipelineLayout				m_pipelineLayout;
1703 	const tcu::UVec3						m_numWorkGroups;
1704 	const int								m_numDescriptorSets;
1705 	const vk::VkDescriptorSet* const		m_descriptorSets;
1706 	const int								m_numDynamicOffsets;
1707 	const deUint32* const					m_dynamicOffsets;
1708 	const int								m_numPreBarriers;
1709 	const vk::VkBufferMemoryBarrier* const	m_preBarriers;
1710 	const int								m_numPostBarriers;
1711 	const vk::VkBufferMemoryBarrier* const	m_postBarriers;
1712 };
1713 
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)1714 ComputeCommand::ComputeCommand (const vk::DeviceInterface&			vki,
1715 								vk::VkDevice						device,
1716 								vk::VkPipeline						pipeline,
1717 								vk::VkPipelineLayout				pipelineLayout,
1718 								const tcu::UVec3&					numWorkGroups,
1719 								int									numDescriptorSets,
1720 								const vk::VkDescriptorSet*			descriptorSets,
1721 								int									numDynamicOffsets,
1722 								const deUint32*						dynamicOffsets,
1723 								int									numPreBarriers,
1724 								const vk::VkBufferMemoryBarrier*	preBarriers,
1725 								int									numPostBarriers,
1726 								const vk::VkBufferMemoryBarrier*	postBarriers)
1727 	: m_vki					(vki)
1728 	, m_device				(device)
1729 	, m_pipeline			(pipeline)
1730 	, m_pipelineLayout		(pipelineLayout)
1731 	, m_numWorkGroups		(numWorkGroups)
1732 	, m_numDescriptorSets	(numDescriptorSets)
1733 	, m_descriptorSets		(descriptorSets)
1734 	, m_numDynamicOffsets	(numDynamicOffsets)
1735 	, m_dynamicOffsets		(dynamicOffsets)
1736 	, m_numPreBarriers		(numPreBarriers)
1737 	, m_preBarriers			(preBarriers)
1738 	, m_numPostBarriers		(numPostBarriers)
1739 	, m_postBarriers		(postBarriers)
1740 {
1741 }
1742 
submitAndWait(deUint32 queueFamilyIndex,vk::VkQueue queue) const1743 void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const
1744 {
1745 	const vk::VkCommandPoolCreateInfo				cmdPoolCreateInfo	=
1746 	{
1747 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1748 		DE_NULL,
1749 		vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// flags
1750 		queueFamilyIndex,									// queueFamilyIndex
1751 	};
1752 	const vk::Unique<vk::VkCommandPool>				cmdPool				(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
1753 
1754 	const vk::VkFenceCreateInfo						fenceCreateInfo		=
1755 	{
1756 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1757 		DE_NULL,
1758 		0u,			// flags
1759 	};
1760 
1761 	const vk::VkCommandBufferAllocateInfo			cmdBufCreateInfo	=
1762 	{
1763 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1764 		DE_NULL,
1765 		*cmdPool,											// cmdPool
1766 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// level
1767 		1u,													// count
1768 	};
1769 	const vk::VkCommandBufferBeginInfo				cmdBufBeginInfo		=
1770 	{
1771 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1772 		DE_NULL,
1773 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
1774 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1775 	};
1776 
1777 	const vk::Unique<vk::VkFence>					cmdCompleteFence	(vk::createFence(m_vki, m_device, &fenceCreateInfo));
1778 	const vk::Unique<vk::VkCommandBuffer>			cmd					(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
1779 	const deUint64									infiniteTimeout		= ~(deUint64)0u;
1780 
1781 	VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
1782 
1783 	m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
1784 	m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets);
1785 
1786 	if (m_numPreBarriers)
1787 		m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0,
1788 								 0, (const vk::VkMemoryBarrier*)DE_NULL,
1789 								 m_numPreBarriers, m_preBarriers,
1790 								 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1791 
1792 	m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
1793 	m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
1794 							 0, (const vk::VkMemoryBarrier*)DE_NULL,
1795 							 m_numPostBarriers, m_postBarriers,
1796 							 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1797 	VK_CHECK(m_vki.endCommandBuffer(*cmd));
1798 
1799 	// run
1800 	{
1801 		const vk::VkSubmitInfo	submitInfo	=
1802 		{
1803 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1804 			DE_NULL,
1805 			0u,
1806 			(const vk::VkSemaphore*)0,
1807 			(const vk::VkPipelineStageFlags*)DE_NULL,
1808 			1u,
1809 			&cmd.get(),
1810 			0u,
1811 			(const vk::VkSemaphore*)0,
1812 		};
1813 		VK_CHECK(m_vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
1814 	}
1815 	VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
1816 }
1817 
1818 class BufferComputeInstance : public vkt::TestInstance
1819 {
1820 public:
1821 											BufferComputeInstance		(Context&				context,
1822 																		 vk::VkDescriptorType	descriptorType,
1823 																		 ShaderInputInterface	shaderInterface,
1824 																		 bool					viewOffset,
1825 																		 bool					dynamicOffset,
1826 																		 bool					dynamicOffsetNonZero);
1827 
1828 private:
1829 	vk::Move<vk::VkBuffer>					createColorDataBuffer		(deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation);
1830 	vk::Move<vk::VkBufferView>				createBufferView			(vk::VkBuffer buffer, deUint32 offset) const;
1831 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(void) const;
1832 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(void) const;
1833 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const;
1834 
1835 	tcu::TestStatus							iterate						(void);
1836 	void									logTestPlan					(void) const;
1837 	tcu::TestStatus							testResourceAccess			(void);
1838 
1839 	enum
1840 	{
1841 		STATIC_OFFSET_VALUE_A	= 256,
1842 		DYNAMIC_OFFSET_VALUE_A	= 512,
1843 		STATIC_OFFSET_VALUE_B	= 1024,
1844 		DYNAMIC_OFFSET_VALUE_B	= 768,
1845 	};
1846 
1847 	const vk::VkDescriptorType				m_descriptorType;
1848 	const ShaderInputInterface				m_shaderInterface;
1849 	const bool								m_setViewOffset;
1850 	const bool								m_setDynamicOffset;
1851 	const bool								m_dynamicOffsetNonZero;
1852 
1853 	const vk::DeviceInterface&				m_vki;
1854 	const vk::VkDevice						m_device;
1855 	const vk::VkQueue						m_queue;
1856 	const deUint32							m_queueFamilyIndex;
1857 	vk::Allocator&							m_allocator;
1858 
1859 	const ComputeInstanceResultBuffer		m_result;
1860 };
1861 
BufferComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero)1862 BufferComputeInstance::BufferComputeInstance (Context&					context,
1863 											  vk::VkDescriptorType		descriptorType,
1864 											  ShaderInputInterface		shaderInterface,
1865 											  bool						viewOffset,
1866 											  bool						dynamicOffset,
1867 											  bool						dynamicOffsetNonZero)
1868 	: vkt::TestInstance			(context)
1869 	, m_descriptorType			(descriptorType)
1870 	, m_shaderInterface			(shaderInterface)
1871 	, m_setViewOffset			(viewOffset)
1872 	, m_setDynamicOffset		(dynamicOffset)
1873 	, m_dynamicOffsetNonZero	(dynamicOffsetNonZero)
1874 	, m_vki						(context.getDeviceInterface())
1875 	, m_device					(context.getDevice())
1876 	, m_queue					(context.getUniversalQueue())
1877 	, m_queueFamilyIndex		(context.getUniversalQueueFamilyIndex())
1878 	, m_allocator				(context.getDefaultAllocator())
1879 	, m_result					(m_vki, m_device, m_allocator)
1880 {
1881 	if (m_dynamicOffsetNonZero)
1882 		DE_ASSERT(m_setDynamicOffset);
1883 }
1884 
createColorDataBuffer(deUint32 offset,deUint32 bufferSize,const tcu::Vec4 & value1,const tcu::Vec4 & value2,de::MovePtr<vk::Allocation> * outAllocation)1885 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation)
1886 {
1887 	DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
1888 
1889 	const bool						isUniformBuffer		= isUniformDescriptorType(m_descriptorType);
1890 	const vk::VkBufferUsageFlags	usageFlags			= (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1891 	const vk::VkBufferCreateInfo	createInfo =
1892 	{
1893 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1894 		DE_NULL,
1895 		0u,								// flags
1896 		(vk::VkDeviceSize)bufferSize,	// size
1897 		usageFlags,						// usage
1898 		vk::VK_SHARING_MODE_EXCLUSIVE,	// sharingMode
1899 		0u,								// queueFamilyCount
1900 		DE_NULL,						// pQueueFamilyIndices
1901 	};
1902 	vk::Move<vk::VkBuffer>			buffer				(vk::createBuffer(m_vki, m_device, &createInfo));
1903 	de::MovePtr<vk::Allocation>		allocation			(allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
1904 	void*							mapPtr				= allocation->getHostPtr();
1905 
1906 	if (offset)
1907 		deMemset(mapPtr, 0x5A, (size_t)offset);
1908 	deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
1909 	deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
1910 	deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
1911 
1912 	flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize);
1913 
1914 	*outAllocation = allocation;
1915 	return buffer;
1916 }
1917 
createDescriptorSetLayout(void) const1918 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout (void) const
1919 {
1920 	vk::DescriptorSetLayoutBuilder builder;
1921 
1922 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1923 
1924 	switch (m_shaderInterface)
1925 	{
1926 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
1927 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1928 			break;
1929 
1930 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1931 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1932 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1933 			break;
1934 
1935 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
1936 			builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1937 			break;
1938 
1939 		default:
1940 			DE_FATAL("Impossible");
1941 	};
1942 
1943 	return builder.build(m_vki, m_device);
1944 }
1945 
createDescriptorPool(void) const1946 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool (void) const
1947 {
1948 	return vk::DescriptorPoolBuilder()
1949 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1950 		.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
1951 		.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1952 }
1953 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,vk::VkBuffer viewA,deUint32 offsetA,vk::VkBuffer viewB,deUint32 offsetB,vk::VkBuffer resBuf) const1954 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) const
1955 {
1956 	const vk::VkDescriptorBufferInfo		resultInfo		= vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
1957 	const vk::VkDescriptorBufferInfo		bufferInfos[2]	=
1958 	{
1959 		vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
1960 		vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
1961 	};
1962 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
1963 	{
1964 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1965 		DE_NULL,
1966 		pool,
1967 		1u,
1968 		&layout
1969 	};
1970 
1971 	vk::Move<vk::VkDescriptorSet>	descriptorSet	= allocateDescriptorSet(m_vki, m_device, &allocInfo);
1972 	vk::DescriptorSetUpdateBuilder	builder;
1973 
1974 	// result
1975 	builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
1976 
1977 	// buffers
1978 	switch (m_shaderInterface)
1979 	{
1980 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
1981 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
1982 			break;
1983 
1984 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1985 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
1986 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &bufferInfos[1]);
1987 			break;
1988 
1989 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
1990 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, bufferInfos);
1991 			break;
1992 
1993 		default:
1994 			DE_FATAL("Impossible");
1995 	}
1996 
1997 	builder.update(m_vki, m_device);
1998 	return descriptorSet;
1999 }
2000 
iterate(void)2001 tcu::TestStatus BufferComputeInstance::iterate (void)
2002 {
2003 	logTestPlan();
2004 	return testResourceAccess();
2005 }
2006 
logTestPlan(void) const2007 void BufferComputeInstance::logTestPlan (void) const
2008 {
2009 	std::ostringstream msg;
2010 
2011 	msg << "Accessing resource in a compute program.\n"
2012 		<< "Single descriptor set. Descriptor set contains "
2013 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
2014 				(m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
2015 				(m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
2016 				(const char*)DE_NULL)
2017 		<< " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2018 		<< " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2019 		<< "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2020 
2021 	if (isDynamicDescriptorType(m_descriptorType))
2022 	{
2023 		if (m_setDynamicOffset)
2024 		{
2025 			msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2026 				<< "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2027 		}
2028 		else
2029 		{
2030 			msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2031 		}
2032 	}
2033 
2034 	msg << "Destination buffer is pre-initialized to -1.\n";
2035 
2036 	m_context.getTestContext().getLog()
2037 		<< tcu::TestLog::Message
2038 		<< msg.str()
2039 		<< tcu::TestLog::EndMessage;
2040 }
2041 
testResourceAccess(void)2042 tcu::TestStatus BufferComputeInstance::testResourceAccess (void)
2043 {
2044 	enum
2045 	{
2046 		ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2047 	};
2048 
2049 	const bool										isDynamicCase		= isDynamicDescriptorType(m_descriptorType);
2050 	const bool										isUniformBuffer		= isUniformDescriptorType(m_descriptorType);
2051 	const deUint32									bindTimeOffsets[]	=
2052 	{
2053 		(m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u),
2054 		(m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u),
2055 	};
2056 
2057 	const tcu::Vec4									colorA1				= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2058 	const tcu::Vec4									colorA2				= tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
2059 	const tcu::Vec4									colorB1				= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2060 	const tcu::Vec4									colorB2				= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2061 
2062 	const deUint32									dataOffsetA			= ((isDynamicCase) ? (bindTimeOffsets[0]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u));
2063 	const deUint32									dataOffsetB			= ((isDynamicCase) ? (bindTimeOffsets[1]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u));
2064 	const deUint32									viewOffsetA			= (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
2065 	const deUint32									viewOffsetB			= (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
2066 	const deUint32									bufferSizeA			= dataOffsetA + ADDRESSABLE_SIZE;
2067 	const deUint32									bufferSizeB			= dataOffsetB + ADDRESSABLE_SIZE;
2068 
2069 	de::MovePtr<vk::Allocation>						bufferMemA;
2070 	const vk::Unique<vk::VkBuffer>					bufferA				(createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA));
2071 
2072 	de::MovePtr<vk::Allocation>						bufferMemB;
2073 	const vk::Unique<vk::VkBuffer>					bufferB				((getInterfaceNumResources(m_shaderInterface) == 1u)
2074 																			? (vk::Move<vk::VkBuffer>())
2075 																			: (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB)));
2076 
2077 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
2078 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
2079 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer()));
2080 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
2081 
2082 	const vk::VkAccessFlags							inputBit			= (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
2083 	const vk::VkBufferMemoryBarrier					bufferBarriers[]	=
2084 	{
2085 		{
2086 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2087 			DE_NULL,
2088 			vk::VK_ACCESS_HOST_WRITE_BIT,				// outputMask
2089 			inputBit,									// inputMask
2090 			vk::VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
2091 			vk::VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
2092 			*bufferA,									// buffer
2093 			(vk::VkDeviceSize)0u,						// offset
2094 			(vk::VkDeviceSize)bufferSizeA,				// size
2095 		},
2096 		{
2097 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2098 			DE_NULL,
2099 			vk::VK_ACCESS_HOST_WRITE_BIT,				// outputMask
2100 			inputBit,									// inputMask
2101 			vk::VK_QUEUE_FAMILY_IGNORED,				// srcQueueFamilyIndex
2102 			vk::VK_QUEUE_FAMILY_IGNORED,				// destQueueFamilyIndex
2103 			*bufferB,									// buffer
2104 			(vk::VkDeviceSize)0u,						// offset
2105 			(vk::VkDeviceSize)bufferSizeB,				// size
2106 		}
2107 	};
2108 
2109 	const deUint32									numSrcBuffers		= getInterfaceNumResources(m_shaderInterface);
2110 
2111 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
2112 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
2113 	const deUint32* const							dynamicOffsets		= (m_setDynamicOffset) ? (bindTimeOffsets) : (DE_NULL);
2114 	const deUint32									numDynamicOffsets	= (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2115 	const vk::VkBufferMemoryBarrier* const			preBarriers			= bufferBarriers;
2116 	const int										numPreBarriers		= numSrcBuffers;
2117 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
2118 	const int										numPostBarriers		= 1;
2119 
2120 	const ComputeCommand							compute				(m_vki,
2121 																		 m_device,
2122 																		 pipeline.getPipeline(),
2123 																		 pipeline.getPipelineLayout(),
2124 																		 tcu::UVec3(4, 1, 1),
2125 																		 numDescriptorSets,	descriptorSets,
2126 																		 numDynamicOffsets,	dynamicOffsets,
2127 																		 numPreBarriers,	preBarriers,
2128 																		 numPostBarriers,	postBarriers);
2129 
2130 	const tcu::Vec4									refQuadrantValue14	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? (colorA2) :
2131 																		  (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? (colorB2) :
2132 																		  (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? (colorB2) :
2133 																																					(tcu::Vec4(-2.0f));
2134 	const tcu::Vec4									refQuadrantValue23	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? (colorA1) :
2135 																		  (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? (colorA1) :
2136 																		  (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? (colorA1) :
2137 																																					(tcu::Vec4(-2.0f));
2138 	const tcu::Vec4									references[4]		=
2139 	{
2140 		refQuadrantValue14,
2141 		refQuadrantValue23,
2142 		refQuadrantValue23,
2143 		refQuadrantValue14,
2144 	};
2145 	tcu::Vec4										results[4];
2146 
2147 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
2148 	m_result.readResultContentsTo(&results);
2149 
2150 	// verify
2151 	if (results[0] == references[0] &&
2152 		results[1] == references[1] &&
2153 		results[2] == references[2] &&
2154 		results[3] == references[3])
2155 	{
2156 		return tcu::TestStatus::pass("Pass");
2157 	}
2158 	else if (results[0] == tcu::Vec4(-1.0f) &&
2159 			 results[1] == tcu::Vec4(-1.0f) &&
2160 			 results[2] == tcu::Vec4(-1.0f) &&
2161 			 results[3] == tcu::Vec4(-1.0f))
2162 	{
2163 		m_context.getTestContext().getLog()
2164 			<< tcu::TestLog::Message
2165 			<< "Result buffer was not written to."
2166 			<< tcu::TestLog::EndMessage;
2167 		return tcu::TestStatus::fail("Result buffer was not written to");
2168 	}
2169 	else
2170 	{
2171 		m_context.getTestContext().getLog()
2172 			<< tcu::TestLog::Message
2173 			<< "Error expected ["
2174 				<< references[0] << ", "
2175 				<< references[1] << ", "
2176 				<< references[2] << ", "
2177 				<< references[3] << "], got ["
2178 				<< results[0] << ", "
2179 				<< results[1] << ", "
2180 				<< results[2] << ", "
2181 				<< results[3] << "]"
2182 			<< tcu::TestLog::EndMessage;
2183 		return tcu::TestStatus::fail("Invalid result values");
2184 	}
2185 }
2186 
2187 class QuadrantRendederCase : public vkt::TestCase
2188 {
2189 public:
2190 									QuadrantRendederCase		(tcu::TestContext&		testCtx,
2191 																 const char*			name,
2192 																 const char*			description,
2193 																 glu::GLSLVersion		glslVersion,
2194 																 vk::VkShaderStageFlags	exitingStages,
2195 																 vk::VkShaderStageFlags	activeStages);
2196 private:
2197 	virtual std::string				genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const = 0;
2198 	virtual std::string				genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
2199 	virtual std::string				genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const = 0;
2200 	virtual std::string				genNoAccessSource			(void) const = 0;
2201 
2202 	std::string						genVertexSource				(void) const;
2203 	std::string						genTessCtrlSource			(void) const;
2204 	std::string						genTessEvalSource			(void) const;
2205 	std::string						genGeometrySource			(void) const;
2206 	std::string						genFragmentSource			(void) const;
2207 	std::string						genComputeSource			(void) const;
2208 
2209 	void							initPrograms				(vk::SourceCollections& programCollection) const;
2210 
2211 protected:
2212 	const glu::GLSLVersion			m_glslVersion;
2213 	const vk::VkShaderStageFlags	m_exitingStages;
2214 	const vk::VkShaderStageFlags	m_activeStages;
2215 };
2216 
QuadrantRendederCase(tcu::TestContext & testCtx,const char * name,const char * description,glu::GLSLVersion glslVersion,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages)2217 QuadrantRendederCase::QuadrantRendederCase (tcu::TestContext&		testCtx,
2218 											const char*				name,
2219 											const char*				description,
2220 											glu::GLSLVersion		glslVersion,
2221 											vk::VkShaderStageFlags	exitingStages,
2222 											vk::VkShaderStageFlags	activeStages)
2223 	: vkt::TestCase		(testCtx, name, description)
2224 	, m_glslVersion		(glslVersion)
2225 	, m_exitingStages	(exitingStages)
2226 	, m_activeStages	(activeStages)
2227 {
2228 	DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
2229 }
2230 
genVertexSource(void) const2231 std::string QuadrantRendederCase::genVertexSource (void) const
2232 {
2233 	const char* const	nextStageName	= ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)	? ("tsc")
2234 										: ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)				? ("geo")
2235 										: ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)				? ("frag")
2236 										: (DE_NULL);
2237 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
2238 	std::ostringstream	buf;
2239 
2240 	if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
2241 	{
2242 		const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
2243 
2244 		// active vertex shader
2245 		buf << versionDecl << "\n"
2246 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
2247 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0)
2248 			<< "layout(location = 0) out highp vec4 " << nextStageName << "_color;\n"
2249 			<< (onlyVS ? "" : "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
2250 			<< "void main (void)\n"
2251 			<< "{\n"
2252 			<< "	highp vec4 result_position;\n"
2253 			<< "	highp int quadrant_id;\n"
2254 			<< s_quadrantGenVertexPosSource
2255 			<< "	gl_Position = result_position;\n"
2256 			<< (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n")
2257 			<< "\n"
2258 			<< "	highp vec4 result_color;\n"
2259 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT)
2260 			<< "	" << nextStageName << "_color = result_color;\n"
2261 			<< "}\n";
2262 	}
2263 	else
2264 	{
2265 		// do nothing
2266 		buf << versionDecl << "\n"
2267 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT)
2268 			<< "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
2269 			<< "void main (void)\n"
2270 			<< "{\n"
2271 			<< "	highp vec4 result_position;\n"
2272 			<< "	highp int quadrant_id;\n"
2273 			<< s_quadrantGenVertexPosSource
2274 			<< "	gl_Position = result_position;\n"
2275 			<< "	" << nextStageName << "_quadrant_id = quadrant_id;\n"
2276 			<< "}\n";
2277 	}
2278 
2279 	return buf.str();
2280 }
2281 
genTessCtrlSource(void) const2282 std::string QuadrantRendederCase::genTessCtrlSource (void) const
2283 {
2284 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
2285 	const bool			extRequired		= glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2286 	const char* const	tessExtDecl		= extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
2287 	std::ostringstream	buf;
2288 
2289 	if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
2290 	{
2291 		// contributing not implemented
2292 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
2293 
2294 		// active tc shader
2295 		buf << versionDecl << "\n"
2296 			<< tessExtDecl
2297 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2298 			<< "layout(vertices=3) out;\n"
2299 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
2300 			<< "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
2301 			<< "layout(location = 0) out highp vec4 tes_color[];\n"
2302 			<< "void main (void)\n"
2303 			<< "{\n"
2304 			<< "	highp vec4 result_color;\n"
2305 			<< "	highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
2306 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
2307 			<< "\n"
2308 			<< "	tes_color[gl_InvocationID] = result_color;\n"
2309 			<< "\n"
2310 			<< "	// no dynamic input block indexing\n"
2311 			<< "	highp vec4 position;\n"
2312 			<< "	if (gl_InvocationID == 0)\n"
2313 			<< "		position = gl_in[0].gl_Position;\n"
2314 			<< "	else if (gl_InvocationID == 1)\n"
2315 			<< "		position = gl_in[1].gl_Position;\n"
2316 			<< "	else\n"
2317 			<< "		position = gl_in[2].gl_Position;\n"
2318 			<< "	gl_out[gl_InvocationID].gl_Position = position;\n"
2319 			<< "	gl_TessLevelInner[0] = 2.8;\n"
2320 			<< "	gl_TessLevelInner[1] = 2.8;\n"
2321 			<< "	gl_TessLevelOuter[0] = 2.8;\n"
2322 			<< "	gl_TessLevelOuter[1] = 2.8;\n"
2323 			<< "	gl_TessLevelOuter[2] = 2.8;\n"
2324 			<< "	gl_TessLevelOuter[3] = 2.8;\n"
2325 			<< "}\n";
2326 	}
2327 	else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
2328 	{
2329 		// active te shader, tc passthru
2330 		buf << versionDecl << "\n"
2331 			<< tessExtDecl
2332 			<< "layout(vertices=3) out;\n"
2333 			<< "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
2334 			<< "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
2335 			<< "void main (void)\n"
2336 			<< "{\n"
2337 			<< "	tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
2338 			<< "\n"
2339 			<< "	// no dynamic input block indexing\n"
2340 			<< "	highp vec4 position;\n"
2341 			<< "	if (gl_InvocationID == 0)\n"
2342 			<< "		position = gl_in[0].gl_Position;\n"
2343 			<< "	else if (gl_InvocationID == 1)\n"
2344 			<< "		position = gl_in[1].gl_Position;\n"
2345 			<< "	else\n"
2346 			<< "		position = gl_in[2].gl_Position;\n"
2347 			<< "	gl_out[gl_InvocationID].gl_Position = position;\n"
2348 			<< "	gl_TessLevelInner[0] = 2.8;\n"
2349 			<< "	gl_TessLevelInner[1] = 2.8;\n"
2350 			<< "	gl_TessLevelOuter[0] = 2.8;\n"
2351 			<< "	gl_TessLevelOuter[1] = 2.8;\n"
2352 			<< "	gl_TessLevelOuter[2] = 2.8;\n"
2353 			<< "	gl_TessLevelOuter[3] = 2.8;\n"
2354 			<< "}\n";
2355 	}
2356 	else
2357 	{
2358 		// passthrough not implemented
2359 		DE_FATAL("not implemented");
2360 	}
2361 
2362 	return buf.str();
2363 }
2364 
genTessEvalSource(void) const2365 std::string QuadrantRendederCase::genTessEvalSource (void) const
2366 {
2367 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
2368 	const bool			extRequired		= glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2369 	const char* const	tessExtDecl		= extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
2370 	std::ostringstream	buf;
2371 
2372 	if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
2373 	{
2374 		// contributing not implemented
2375 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
2376 
2377 		// active te shader
2378 		buf << versionDecl << "\n"
2379 			<< tessExtDecl
2380 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2381 			<< "layout(triangles) in;\n"
2382 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
2383 			<< "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
2384 			<< "layout(location = 0) out highp vec4 frag_color;\n"
2385 			<< "void main (void)\n"
2386 			<< "{\n"
2387 			<< "	highp vec4 result_color;\n"
2388 			<< "	highp int quadrant_id = tes_quadrant_id[0];\n"
2389 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2390 			<< "\n"
2391 			<< "	frag_color = result_color;\n"
2392 			<< "	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"
2393 			<< "}\n";
2394 	}
2395 	else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
2396 	{
2397 		// contributing not implemented
2398 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
2399 
2400 		// active tc shader, te is passthru
2401 		buf << versionDecl << "\n"
2402 			<< tessExtDecl
2403 			<< "layout(triangles) in;\n"
2404 			<< "layout(location = 0) in highp vec4 tes_color[];\n"
2405 			<< "layout(location = 0) out highp vec4 frag_color;\n"
2406 			<< "void main (void)\n"
2407 			<< "{\n"
2408 			<< "	frag_color = tes_color[0];\n"
2409 			<< "	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"
2410 			<< "}\n";
2411 	}
2412 	else
2413 	{
2414 		// passthrough not implemented
2415 		DE_FATAL("not implemented");
2416 	}
2417 
2418 	return buf.str();
2419 }
2420 
genGeometrySource(void) const2421 std::string QuadrantRendederCase::genGeometrySource (void) const
2422 {
2423 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
2424 	const bool			extRequired		= glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2425 	const char* const	geomExtDecl		= extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
2426 	std::ostringstream	buf;
2427 
2428 	if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
2429 	{
2430 		// contributing not implemented
2431 		DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
2432 
2433 		// active geometry shader
2434 		buf << versionDecl << "\n"
2435 			<< geomExtDecl
2436 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2437 			<< "layout(triangles) in;\n"
2438 			<< "layout(triangle_strip, max_vertices=4) out;\n"
2439 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
2440 			<< "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
2441 			<< "layout(location = 0) out highp vec4 frag_color;\n"
2442 			<< "void main (void)\n"
2443 			<< "{\n"
2444 			<< "	highp int quadrant_id;\n"
2445 			<< "	highp vec4 result_color;\n"
2446 			<< "\n"
2447 			<< "	quadrant_id = geo_quadrant_id[0];\n"
2448 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2449 			<< "	frag_color = result_color;\n"
2450 			<< "	gl_Position = gl_in[0].gl_Position;\n"
2451 			<< "	EmitVertex();\n"
2452 			<< "\n"
2453 			<< "	quadrant_id = geo_quadrant_id[1];\n"
2454 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2455 			<< "	frag_color = result_color;\n"
2456 			<< "	gl_Position = gl_in[1].gl_Position;\n"
2457 			<< "	EmitVertex();\n"
2458 			<< "\n"
2459 			<< "	quadrant_id = geo_quadrant_id[2];\n"
2460 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2461 			<< "	frag_color = result_color;\n"
2462 			<< "	gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
2463 			<< "	EmitVertex();\n"
2464 			<< "\n"
2465 			<< "	quadrant_id = geo_quadrant_id[0];\n"
2466 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2467 			<< "	frag_color = result_color;\n"
2468 			<< "	gl_Position = gl_in[2].gl_Position;\n"
2469 			<< "	EmitVertex();\n"
2470 			<< "}\n";
2471 	}
2472 	else
2473 	{
2474 		// passthrough not implemented
2475 		DE_FATAL("not implemented");
2476 	}
2477 
2478 	return buf.str();
2479 }
2480 
genFragmentSource(void) const2481 std::string QuadrantRendederCase::genFragmentSource (void) const
2482 {
2483 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
2484 	std::ostringstream	buf;
2485 
2486 	if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
2487 	{
2488 		buf << versionDecl << "\n"
2489 			<< genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
2490 			<< genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
2491 
2492 		if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
2493 		{
2494 			// there are other stages, this is just a contributor
2495 			buf << "layout(location = 0) in mediump vec4 frag_color;\n";
2496 		}
2497 
2498 		buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
2499 			<< "layout(location = 0) out mediump vec4 o_color;\n"
2500 			<< "void main (void)\n"
2501 			<< "{\n"
2502 			<< "	highp int quadrant_id = frag_quadrant_id;\n"
2503 			<< "	highp vec4 result_color;\n"
2504 			<< genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
2505 
2506 		if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
2507 		{
2508 			// just contributor
2509 			buf	<< "	if (frag_quadrant_id < 2)\n"
2510 				<< "		o_color = result_color;\n"
2511 				<< "	else\n"
2512 				<< "		o_color = frag_color;\n";
2513 		}
2514 		else
2515 			buf << "	o_color = result_color;\n";
2516 
2517 		buf << "}\n";
2518 	}
2519 	else if (m_activeStages == 0u)
2520 	{
2521 		// special case, no active stages
2522 		buf << versionDecl << "\n"
2523 			<< "layout(location = 1) flat in highp int frag_quadrant_id;\n"
2524 			<< "layout(location = 0) out mediump vec4 o_color;\n"
2525 			<< "void main (void)\n"
2526 			<< "{\n"
2527 			<< "	highp int quadrant_id = frag_quadrant_id;\n"
2528 			<< "	highp vec4 result_color;\n"
2529 			<< genNoAccessSource()
2530 			<< "	o_color = result_color;\n"
2531 			<< "}\n";
2532 	}
2533 	else
2534 	{
2535 		// passthrough
2536 		buf <<	versionDecl << "\n"
2537 			<<	"layout(location = 0) in mediump vec4 frag_color;\n"
2538 				"layout(location = 0) out mediump vec4 o_color;\n"
2539 				"void main (void)\n"
2540 				"{\n"
2541 				"	o_color = frag_color;\n"
2542 				"}\n";
2543 	}
2544 
2545 	return buf.str();
2546 }
2547 
genComputeSource(void) const2548 std::string QuadrantRendederCase::genComputeSource (void) const
2549 {
2550 	const char* const	versionDecl		= glu::getGLSLVersionDeclaration(m_glslVersion);
2551 	std::ostringstream	buf;
2552 
2553 	buf	<< versionDecl << "\n"
2554 		<< genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
2555 		<< "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2556 		<< genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
2557 		<< "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
2558 		<< "{\n"
2559 		<< "	highp vec4 read_colors[4];\n"
2560 		<< "} b_out;\n"
2561 		<< "void main (void)\n"
2562 		<< "{\n"
2563 		<< "	highp int quadrant_id = int(gl_WorkGroupID.x);\n"
2564 		<< "	highp vec4 result_color;\n"
2565 		<< genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
2566 		<< "	b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
2567 		<< "}\n";
2568 
2569 	return buf.str();
2570 }
2571 
initPrograms(vk::SourceCollections & programCollection) const2572 void QuadrantRendederCase::initPrograms (vk::SourceCollections& programCollection) const
2573 {
2574 	if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
2575 		programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
2576 
2577 	if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
2578 		programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
2579 
2580 	if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
2581 		programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
2582 
2583 	if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
2584 		programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
2585 
2586 	if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
2587 		programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
2588 
2589 	if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
2590 		programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
2591 }
2592 
2593 class BufferDescriptorCase : public QuadrantRendederCase
2594 {
2595 public:
2596 	enum
2597 	{
2598 		FLAG_VIEW_OFFSET			= (1u << 1u),
2599 		FLAG_DYNAMIC_OFFSET_ZERO	= (1u << 2u),
2600 		FLAG_DYNAMIC_OFFSET_NONZERO	= (1u << 3u),
2601 	};
2602 	// enum continues where resource flags ends
2603 	DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
2604 
2605 									BufferDescriptorCase		(tcu::TestContext&		testCtx,
2606 																 const char*			name,
2607 																 const char*			description,
2608 																 bool					isPrimaryCmdBuf,
2609 																 vk::VkDescriptorType	descriptorType,
2610 																 vk::VkShaderStageFlags	exitingStages,
2611 																 vk::VkShaderStageFlags	activeStages,
2612 																 ShaderInputInterface	shaderInterface,
2613 																 deUint32				flags);
2614 
2615 private:
2616 	std::string						genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const;
2617 	std::string						genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
2618 	std::string						genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const;
2619 	std::string						genNoAccessSource			(void) const;
2620 
2621 	vkt::TestInstance*				createInstance				(vkt::Context& context) const;
2622 
2623 	const bool						m_viewOffset;
2624 	const bool						m_dynamicOffsetSet;
2625 	const bool						m_dynamicOffsetNonZero;
2626 	const bool						m_isPrimaryCmdBuf;
2627 	const vk::VkDescriptorType		m_descriptorType;
2628 	const ShaderInputInterface		m_shaderInterface;
2629 };
2630 
BufferDescriptorCase(tcu::TestContext & testCtx,const char * name,const char * description,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface shaderInterface,deUint32 flags)2631 BufferDescriptorCase::BufferDescriptorCase (tcu::TestContext&		testCtx,
2632 											const char*				name,
2633 											const char*				description,
2634 											bool					isPrimaryCmdBuf,
2635 											vk::VkDescriptorType	descriptorType,
2636 											vk::VkShaderStageFlags	exitingStages,
2637 											vk::VkShaderStageFlags	activeStages,
2638 											ShaderInputInterface	shaderInterface,
2639 											deUint32				flags)
2640 	: QuadrantRendederCase		(testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
2641 	, m_viewOffset				((flags & FLAG_VIEW_OFFSET) != 0u)
2642 	, m_dynamicOffsetSet		((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
2643 	, m_dynamicOffsetNonZero	((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
2644 	, m_isPrimaryCmdBuf			(isPrimaryCmdBuf)
2645 	, m_descriptorType			(descriptorType)
2646 	, m_shaderInterface			(shaderInterface)
2647 {
2648 }
2649 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const2650 std::string BufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
2651 {
2652 	DE_UNREF(stage);
2653 	return "";
2654 }
2655 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const2656 std::string BufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
2657 {
2658 	DE_UNREF(stage);
2659 
2660 	const bool			isUniform		= isUniformDescriptorType(m_descriptorType);
2661 	const char* const	storageType		= (isUniform) ? ("uniform") : ("buffer");
2662 	std::ostringstream	buf;
2663 
2664 	switch (m_shaderInterface)
2665 	{
2666 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
2667 			buf	<< "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
2668 				<< "{\n"
2669 				<< "	highp vec4 colorA;\n"
2670 				<< "	highp vec4 colorB;\n"
2671 				<< "} b_instance;\n";
2672 			break;
2673 
2674 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2675 			buf	<< "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferNameA\n"
2676 				<< "{\n"
2677 				<< "	highp vec4 colorA;\n"
2678 				<< "	highp vec4 colorB;\n"
2679 				<< "} b_instanceA;\n"
2680 				<< "layout(set = 0, binding = " << (numUsedBindings+1) << ", std140) " << storageType << " BufferNameB\n"
2681 				<< "{\n"
2682 				<< "	highp vec4 colorA;\n"
2683 				<< "	highp vec4 colorB;\n"
2684 				<< "} b_instanceB;\n";
2685 			break;
2686 
2687 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
2688 			buf	<< "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
2689 				<< "{\n"
2690 				<< "	highp vec4 colorA;\n"
2691 				<< "	highp vec4 colorB;\n"
2692 				<< "} b_instances[2];\n";
2693 			break;
2694 
2695 		default:
2696 			DE_FATAL("Impossible");
2697 	}
2698 
2699 	return buf.str();
2700 }
2701 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const2702 std::string BufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
2703 {
2704 	DE_UNREF(stage);
2705 
2706 	std::ostringstream buf;
2707 
2708 	switch (m_shaderInterface)
2709 	{
2710 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
2711 			buf << "	if (quadrant_id == 1 || quadrant_id == 2)\n"
2712 				<< "		result_color = b_instance.colorA;\n"
2713 				<< "	else\n"
2714 				<< "		result_color = b_instance.colorB;\n";
2715 			break;
2716 
2717 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2718 			buf << "	if (quadrant_id == 1 || quadrant_id == 2)\n"
2719 				<< "		result_color = b_instanceA.colorA;\n"
2720 				<< "	else\n"
2721 				<< "		result_color = b_instanceB.colorB;\n";
2722 			break;
2723 
2724 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
2725 			buf << "	if (quadrant_id == 1 || quadrant_id == 2)\n"
2726 				<< "		result_color = b_instances[0].colorA;\n"
2727 				<< "	else\n"
2728 				<< "		result_color = b_instances[1].colorB;\n";
2729 			break;
2730 
2731 		default:
2732 			DE_FATAL("Impossible");
2733 	}
2734 
2735 	return buf.str();
2736 }
2737 
genNoAccessSource(void) const2738 std::string BufferDescriptorCase::genNoAccessSource (void) const
2739 {
2740 	return "	if (quadrant_id == 1 || quadrant_id == 2)\n"
2741 		   "		result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
2742 		   "	else\n"
2743 		   "		result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
2744 }
2745 
createInstance(vkt::Context & context) const2746 vkt::TestInstance* BufferDescriptorCase::createInstance (vkt::Context& context) const
2747 {
2748 	verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
2749 
2750 	if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
2751 	{
2752 		DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
2753 		return new BufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
2754 	}
2755 	else
2756 		return new BufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
2757 }
2758 
2759 class ImageInstanceImages
2760 {
2761 public:
2762 										ImageInstanceImages		(const vk::DeviceInterface&		vki,
2763 																 vk::VkDevice					device,
2764 																 deUint32						queueFamilyIndex,
2765 																 vk::VkQueue					queue,
2766 																 vk::Allocator&					allocator,
2767 																 vk::VkDescriptorType			descriptorType,
2768 																 vk::VkImageViewType			viewType,
2769 																 int							numImages,
2770 																 deUint32						baseMipLevel,
2771 																 deUint32						baseArraySlice);
2772 
2773 private:
2774 	static vk::Move<vk::VkImage>		createImage				(const vk::DeviceInterface&			vki,
2775 																 vk::VkDevice						device,
2776 																 vk::Allocator&						allocator,
2777 																 vk::VkDescriptorType				descriptorType,
2778 																 vk::VkImageViewType				viewType,
2779 																 const tcu::TextureLevelPyramid&	sourceImage,
2780 																 de::MovePtr<vk::Allocation>*		outAllocation);
2781 
2782 	static vk::Move<vk::VkImageView>	createImageView			(const vk::DeviceInterface&			vki,
2783 																 vk::VkDevice						device,
2784 																 vk::VkImageViewType				viewType,
2785 																 const tcu::TextureLevelPyramid&	sourceImage,
2786 																 vk::VkImage						image,
2787 																 deUint32							baseMipLevel,
2788 																 deUint32							baseArraySlice);
2789 
2790 	void								populateSourceImage		(tcu::TextureLevelPyramid*			dst,
2791 																 bool								isFirst) const;
2792 
2793 	void								uploadImage				(const vk::DeviceInterface&			vki,
2794 																 vk::VkDevice						device,
2795 																 deUint32							queueFamilyIndex,
2796 																 vk::VkQueue						queue,
2797 																 vk::Allocator&						allocator,
2798 																 vk::VkImage						image,
2799 																 vk::VkImageLayout					layout,
2800 																 const tcu::TextureLevelPyramid&	data);
2801 
2802 protected:
2803 	enum
2804 	{
2805 		IMAGE_SIZE		= 64,
2806 		NUM_MIP_LEVELS	= 2,
2807 		ARRAY_SIZE		= 2,
2808 	};
2809 
2810 	const vk::VkImageViewType			m_viewType;
2811 	const deUint32						m_baseMipLevel;
2812 	const deUint32						m_baseArraySlice;
2813 
2814 	const tcu::TextureFormat			m_imageFormat;
2815 	tcu::TextureLevelPyramid			m_sourceImageA;
2816 	tcu::TextureLevelPyramid			m_sourceImageB;
2817 
2818 	de::MovePtr<vk::Allocation>			m_imageMemoryA;
2819 	de::MovePtr<vk::Allocation>			m_imageMemoryB;
2820 	vk::Move<vk::VkImage>				m_imageA;
2821 	vk::Move<vk::VkImage>				m_imageB;
2822 	vk::Move<vk::VkImageView>			m_imageViewA;
2823 	vk::Move<vk::VkImageView>			m_imageViewB;
2824 };
2825 
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)2826 ImageInstanceImages::ImageInstanceImages (const vk::DeviceInterface&	vki,
2827 										  vk::VkDevice					device,
2828 										  deUint32						queueFamilyIndex,
2829 										  vk::VkQueue					queue,
2830 										  vk::Allocator&				allocator,
2831 										  vk::VkDescriptorType			descriptorType,
2832 										  vk::VkImageViewType			viewType,
2833 										  int							numImages,
2834 										  deUint32						baseMipLevel,
2835 										  deUint32						baseArraySlice)
2836 	: m_viewType		(viewType)
2837 	, m_baseMipLevel	(baseMipLevel)
2838 	, m_baseArraySlice	(baseArraySlice)
2839 	, m_imageFormat		(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
2840 	, m_sourceImageA	(m_imageFormat, NUM_MIP_LEVELS)
2841 	, m_sourceImageB	(m_imageFormat, NUM_MIP_LEVELS)
2842 	, m_imageMemoryA	(DE_NULL)
2843 	, m_imageMemoryB	(DE_NULL)
2844 	, m_imageA			(vk::Move<vk::VkImage>())
2845 	, m_imageB			(vk::Move<vk::VkImage>())
2846 	, m_imageViewA		(vk::Move<vk::VkImageView>())
2847 	, m_imageViewB		(vk::Move<vk::VkImageView>())
2848 {
2849 	const vk::VkImageLayout	layout	= getImageLayoutForDescriptorType(descriptorType);
2850 
2851 	DE_ASSERT(numImages == 1 || numImages == 2);
2852 
2853 	populateSourceImage(&m_sourceImageA, true);
2854 	m_imageA = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageA, &m_imageMemoryA);
2855 	m_imageViewA = createImageView(vki, device, viewType, m_sourceImageA, *m_imageA, m_baseMipLevel, m_baseArraySlice);
2856 	uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageA, layout, m_sourceImageA);
2857 
2858 	if (numImages == 2)
2859 	{
2860 		populateSourceImage(&m_sourceImageB, false);
2861 		m_imageB = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageB, &m_imageMemoryB);
2862 		m_imageViewB = createImageView(vki, device, viewType, m_sourceImageB, *m_imageB, m_baseMipLevel, m_baseArraySlice);
2863 		uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageB, layout, m_sourceImageB);
2864 	}
2865 }
2866 
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)2867 vk::Move<vk::VkImage> ImageInstanceImages::createImage (const vk::DeviceInterface&			vki,
2868 														vk::VkDevice						device,
2869 														vk::Allocator&						allocator,
2870 														vk::VkDescriptorType				descriptorType,
2871 														vk::VkImageViewType					viewType,
2872 														const tcu::TextureLevelPyramid&		sourceImage,
2873 														de::MovePtr<vk::Allocation>*		outAllocation)
2874 {
2875 	const tcu::ConstPixelBufferAccess	baseLevel	= sourceImage.getLevel(0);
2876 	const bool							isCube		= (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
2877 	const bool							isStorage	= (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
2878 	const deUint32						readUsage	= (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
2879 	const deUint32						arraySize	= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (baseLevel.getHeight())
2880 													: (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (baseLevel.getDepth())
2881 													: (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)														? (1)
2882 													: (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (baseLevel.getDepth()) // cube: numFaces * numLayers
2883 																																					: (0);
2884 	const vk::VkExtent3D				extent		=
2885 	{
2886 		// x
2887 		(deUint32)baseLevel.getWidth(),
2888 
2889 		// y
2890 		(viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1u) : (deUint32)baseLevel.getHeight(),
2891 
2892 		// z
2893 		(viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((deUint32)baseLevel.getDepth()) : (1u),
2894 	};
2895 	const vk::VkImageCreateInfo			createInfo	=
2896 	{
2897 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2898 		DE_NULL,
2899 		isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
2900 		viewTypeToImageType(viewType),											// imageType
2901 		vk::mapTextureFormat(baseLevel.getFormat()),							// format
2902 		extent,																	// extent
2903 		(deUint32)sourceImage.getNumLevels(),									// mipLevels
2904 		arraySize,																// arraySize
2905 		vk::VK_SAMPLE_COUNT_1_BIT,												// samples
2906 		vk::VK_IMAGE_TILING_OPTIMAL,											// tiling
2907 		readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,						// usage
2908 		vk::VK_SHARING_MODE_EXCLUSIVE,											// sharingMode
2909 		0u,																		// queueFamilyCount
2910 		DE_NULL,																// pQueueFamilyIndices
2911 		vk::VK_IMAGE_LAYOUT_UNDEFINED,											// initialLayout
2912 	};
2913 	vk::Move<vk::VkImage>				image		(vk::createImage(vki, device, &createInfo));
2914 
2915 	*outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
2916 	return image;
2917 }
2918 
createImageView(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,vk::VkImage image,deUint32 baseMipLevel,deUint32 baseArraySlice)2919 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView (const vk::DeviceInterface&			vki,
2920 																vk::VkDevice						device,
2921 																vk::VkImageViewType					viewType,
2922 																const tcu::TextureLevelPyramid&		sourceImage,
2923 																vk::VkImage							image,
2924 																deUint32							baseMipLevel,
2925 																deUint32							baseArraySlice)
2926 {
2927 	const tcu::ConstPixelBufferAccess	baseLevel			= sourceImage.getLevel(0);
2928 	const deUint32						viewTypeBaseSlice	= (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * baseArraySlice) : (baseArraySlice);
2929 	const deUint32						viewArraySize		= (viewType == vk::VK_IMAGE_VIEW_TYPE_1D)			? (1)
2930 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (baseLevel.getHeight() - viewTypeBaseSlice)
2931 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_2D)			? (1)
2932 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (baseLevel.getDepth() - viewTypeBaseSlice)
2933 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)			? (1)
2934 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)			? (6)
2935 															: (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (baseLevel.getDepth() - viewTypeBaseSlice) // cube: numFaces * numLayers
2936 																												: (0);
2937 
2938 	DE_ASSERT(viewArraySize > 0);
2939 
2940 	const vk::VkImageSubresourceRange	resourceRange	=
2941 	{
2942 		vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
2943 		baseMipLevel,									// baseMipLevel
2944 		sourceImage.getNumLevels() - baseMipLevel,		// mipLevels
2945 		viewTypeBaseSlice,								// baseArraySlice
2946 		viewArraySize,									// arraySize
2947 	};
2948 	const vk::VkImageViewCreateInfo		createInfo		=
2949 	{
2950 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2951 		DE_NULL,
2952 		(vk::VkImageViewCreateFlags)0,
2953 		image,											// image
2954 		viewType,										// viewType
2955 		vk::mapTextureFormat(baseLevel.getFormat()),	// format
2956 		{
2957 			vk::VK_COMPONENT_SWIZZLE_R,
2958 			vk::VK_COMPONENT_SWIZZLE_G,
2959 			vk::VK_COMPONENT_SWIZZLE_B,
2960 			vk::VK_COMPONENT_SWIZZLE_A
2961 		},												// channels
2962 		resourceRange,									// subresourceRange
2963 	};
2964 	return vk::createImageView(vki, device, &createInfo);
2965 }
2966 
populateSourceImage(tcu::TextureLevelPyramid * dst,bool isFirst) const2967 void ImageInstanceImages::populateSourceImage (tcu::TextureLevelPyramid* dst, bool isFirst) const
2968 {
2969 	const int numLevels = dst->getNumLevels();
2970 
2971 	for (int level = 0; level < numLevels; ++level)
2972 	{
2973 		const int	width	= IMAGE_SIZE >> level;
2974 		const int	height	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (ARRAY_SIZE)
2975 																																: (IMAGE_SIZE >> level);
2976 		const int	depth	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? (1)
2977 							: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? (ARRAY_SIZE)
2978 							: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? (6 * ARRAY_SIZE)
2979 							: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)															? (IMAGE_SIZE >> level)
2980 																																: (1);
2981 
2982 		dst->allocLevel(level, width, height, depth);
2983 
2984 		{
2985 			const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
2986 
2987 			for (int z = 0; z < depth; ++z)
2988 			for (int y = 0; y < height; ++y)
2989 			for (int x = 0; x < width; ++x)
2990 			{
2991 				const int			gradPos	= x + y + z;
2992 				const int			gradMax	= width + height + depth - 3;
2993 
2994 				const int			red		= 255 * gradPos / gradMax;													//!< gradient from 0 -> max (detects large offset errors)
2995 				const int			green	= ((gradPos % 2 == 0) ? (127) : (0)) + ((gradPos % 4 < 3) ? (128) : (0));	//!< 3-level M pattern (detects small offset errors)
2996 				const int			blue	= (128 * level / numLevels) + (isFirst ? 127 : 0);							//!< level and image index (detects incorrect lod / image)
2997 
2998 				DE_ASSERT(de::inRange(red, 0, 255));
2999 				DE_ASSERT(de::inRange(green, 0, 255));
3000 				DE_ASSERT(de::inRange(blue, 0, 255));
3001 
3002 				levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3003 			}
3004 		}
3005 	}
3006 }
3007 
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)3008 void ImageInstanceImages::uploadImage (const vk::DeviceInterface&		vki,
3009 									   vk::VkDevice						device,
3010 									   deUint32							queueFamilyIndex,
3011 									   vk::VkQueue						queue,
3012 									   vk::Allocator&					allocator,
3013 									   vk::VkImage						image,
3014 									   vk::VkImageLayout				layout,
3015 									   const tcu::TextureLevelPyramid&	data)
3016 {
3017 	const deUint32						arraySize					= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3018 																	  (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * (deUint32)ARRAY_SIZE) :
3019 																	  ((deUint32)ARRAY_SIZE);
3020 	const deUint32						dataBufferSize				= getTextureLevelPyramidDataSize(data);
3021 	const vk::VkBufferCreateInfo		bufferCreateInfo			=
3022 	{
3023 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3024 		DE_NULL,
3025 		0u,													// flags
3026 		dataBufferSize,										// size
3027 		vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,				// usage
3028 		vk::VK_SHARING_MODE_EXCLUSIVE,						// sharingMode
3029 		0u,													// queueFamilyCount
3030 		DE_NULL,											// pQueueFamilyIndices
3031 	};
3032 	const vk::Unique<vk::VkBuffer>		dataBuffer					(vk::createBuffer(vki, device, &bufferCreateInfo));
3033 	const de::MovePtr<vk::Allocation>	dataBufferMemory			= allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3034 	const vk::VkFenceCreateInfo			fenceCreateInfo				=
3035 	{
3036 		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
3037 		DE_NULL,
3038 		0u,													// flags
3039 	};
3040 	const vk::VkBufferMemoryBarrier		preMemoryBarrier			=
3041 	{
3042 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3043 		DE_NULL,
3044 		vk::VK_ACCESS_HOST_WRITE_BIT,					// outputMask
3045 		vk::VK_ACCESS_TRANSFER_READ_BIT,					// inputMask
3046 		vk::VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex
3047 		vk::VK_QUEUE_FAMILY_IGNORED,						// destQueueFamilyIndex
3048 		*dataBuffer,										// buffer
3049 		0u,													// offset
3050 		dataBufferSize,										// size
3051 	};
3052 	const vk::VkImageSubresourceRange	fullSubrange				=
3053 	{
3054 		vk::VK_IMAGE_ASPECT_COLOR_BIT,						// aspectMask
3055 		0u,													// baseMipLevel
3056 		(deUint32)data.getNumLevels(),						// mipLevels
3057 		0u,													// baseArraySlice
3058 		arraySize,											// arraySize
3059 	};
3060 	const vk::VkImageMemoryBarrier		preImageBarrier				=
3061 	{
3062 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3063 		DE_NULL,
3064 		0u,													// outputMask
3065 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// inputMask
3066 		vk::VK_IMAGE_LAYOUT_UNDEFINED,						// oldLayout
3067 		vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// newLayout
3068 		vk::VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex
3069 		vk::VK_QUEUE_FAMILY_IGNORED,						// destQueueFamilyIndex
3070 		image,												// image
3071 		fullSubrange										// subresourceRange
3072 	};
3073 	const vk::VkImageMemoryBarrier		postImageBarrier			=
3074 	{
3075 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3076 		DE_NULL,
3077 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// outputMask
3078 		vk::VK_ACCESS_SHADER_READ_BIT,						// inputMask
3079 		vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// oldLayout
3080 		layout,												// newLayout
3081 		vk::VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex
3082 		vk::VK_QUEUE_FAMILY_IGNORED,						// destQueueFamilyIndex
3083 		image,												// image
3084 		fullSubrange										// subresourceRange
3085 	};
3086 	const vk::VkCommandPoolCreateInfo		cmdPoolCreateInfo			=
3087 	{
3088 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
3089 		DE_NULL,
3090 		vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// flags
3091 		queueFamilyIndex,									// queueFamilyIndex
3092 	};
3093 	const vk::Unique<vk::VkCommandPool>		cmdPool						(vk::createCommandPool(vki, device, &cmdPoolCreateInfo));
3094 	const vk::VkCommandBufferAllocateInfo	cmdBufCreateInfo			=
3095 	{
3096 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
3097 		DE_NULL,
3098 		*cmdPool,											// cmdPool
3099 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// level
3100 		1u,													// count
3101 	};
3102 	const vk::VkCommandBufferBeginInfo		cmdBufBeginInfo				=
3103 	{
3104 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3105 		DE_NULL,
3106 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// flags
3107 		(const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
3108 	};
3109 
3110 	const vk::Unique<vk::VkCommandBuffer>	cmd							(vk::allocateCommandBuffer(vki, device, &cmdBufCreateInfo));
3111 	const vk::Unique<vk::VkFence>			cmdCompleteFence			(vk::createFence(vki, device, &fenceCreateInfo));
3112 	const deUint64							infiniteTimeout				= ~(deUint64)0u;
3113 	std::vector<vk::VkBufferImageCopy>		copySlices;
3114 
3115 	// copy data to buffer
3116 	writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, m_viewType , &copySlices);
3117 	flushMappedMemoryRange(vki, device, dataBufferMemory->getMemory(), dataBufferMemory->getOffset(), dataBufferSize);
3118 
3119 	// record command buffer
3120 	VK_CHECK(vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
3121 	vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
3122 						   0, (const vk::VkMemoryBarrier*)DE_NULL,
3123 						   1, &preMemoryBarrier,
3124 						   1, &preImageBarrier);
3125 	vki.cmdCopyBufferToImage(*cmd, *dataBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copySlices.size(), &copySlices[0]);
3126 	vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
3127 						   0, (const vk::VkMemoryBarrier*)DE_NULL,
3128 						   0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
3129 						   1, &postImageBarrier);
3130 	VK_CHECK(vki.endCommandBuffer(*cmd));
3131 
3132 	// submit and wait for command buffer to complete before killing it
3133 	{
3134 		const vk::VkSubmitInfo	submitInfo	=
3135 		{
3136 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
3137 			DE_NULL,
3138 			0u,
3139 			(const vk::VkSemaphore*)0,
3140 			(const vk::VkPipelineStageFlags*)DE_NULL,
3141 			1u,
3142 			&cmd.get(),
3143 			0u,
3144 			(const vk::VkSemaphore*)0,
3145 		};
3146 		VK_CHECK(vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence));
3147 	}
3148 	VK_CHECK(vki.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
3149 }
3150 
3151 class ImageFetchInstanceImages : private ImageInstanceImages
3152 {
3153 public:
3154 								ImageFetchInstanceImages	(const vk::DeviceInterface&		vki,
3155 															 vk::VkDevice					device,
3156 															 deUint32						queueFamilyIndex,
3157 															 vk::VkQueue					queue,
3158 															 vk::Allocator&					allocator,
3159 															 vk::VkDescriptorType			descriptorType,
3160 															 ShaderInputInterface			shaderInterface,
3161 															 vk::VkImageViewType			viewType,
3162 															 deUint32						baseMipLevel,
3163 															 deUint32						baseArraySlice);
3164 
3165 	static tcu::IVec3			getFetchPos					(vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx);
3166 	tcu::Vec4					fetchImageValue				(int fetchPosNdx) const;
3167 
getImageViewA(void) const3168 	inline vk::VkImageView		getImageViewA				(void) const { return *m_imageViewA; }
getImageViewB(void) const3169 	inline vk::VkImageView		getImageViewB				(void) const { return *m_imageViewB; }
3170 
3171 private:
3172 	enum
3173 	{
3174 		// some arbitrary sample points for all four quadrants
3175 		SAMPLE_POINT_0_X = 6,
3176 		SAMPLE_POINT_0_Y = 13,
3177 		SAMPLE_POINT_0_Z = 49,
3178 
3179 		SAMPLE_POINT_1_X = 51,
3180 		SAMPLE_POINT_1_Y = 40,
3181 		SAMPLE_POINT_1_Z = 44,
3182 
3183 		SAMPLE_POINT_2_X = 42,
3184 		SAMPLE_POINT_2_Y = 26,
3185 		SAMPLE_POINT_2_Z = 19,
3186 
3187 		SAMPLE_POINT_3_X = 25,
3188 		SAMPLE_POINT_3_Y = 25,
3189 		SAMPLE_POINT_3_Z = 18,
3190 	};
3191 
3192 	const ShaderInputInterface	m_shaderInterface;
3193 };
3194 
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)3195 ImageFetchInstanceImages::ImageFetchInstanceImages (const vk::DeviceInterface&	vki,
3196 													vk::VkDevice				device,
3197 													deUint32					queueFamilyIndex,
3198 													vk::VkQueue					queue,
3199 													vk::Allocator&				allocator,
3200 													vk::VkDescriptorType		descriptorType,
3201 													ShaderInputInterface		shaderInterface,
3202 													vk::VkImageViewType			viewType,
3203 													deUint32					baseMipLevel,
3204 													deUint32					baseArraySlice)
3205 	: ImageInstanceImages	(vki,
3206 							 device,
3207 							 queueFamilyIndex,
3208 							 queue,
3209 							 allocator,
3210 							 descriptorType,
3211 							 viewType,
3212 							 getInterfaceNumResources(shaderInterface),	// numImages
3213 							 baseMipLevel,
3214 							 baseArraySlice)
3215 	, m_shaderInterface		(shaderInterface)
3216 {
3217 }
3218 
isImageViewTypeArray(vk::VkImageViewType type)3219 bool isImageViewTypeArray (vk::VkImageViewType type)
3220 {
3221 	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;
3222 }
3223 
getFetchPos(vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,int fetchPosNdx)3224 tcu::IVec3 ImageFetchInstanceImages::getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx)
3225 {
3226 	const tcu::IVec3	fetchPositions[4]	=
3227 	{
3228 		tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
3229 		tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
3230 		tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
3231 		tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
3232 	};
3233 	const tcu::IVec3	coord				= de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
3234 	const deUint32		imageSize			= (deUint32)IMAGE_SIZE >> baseMipLevel;
3235 	const deUint32		arraySize			= isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
3236 
3237 	switch (viewType)
3238 	{
3239 		case vk::VK_IMAGE_VIEW_TYPE_1D:
3240 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:	return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
3241 		case vk::VK_IMAGE_VIEW_TYPE_2D:
3242 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:	return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
3243 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
3244 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:	return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
3245 		case vk::VK_IMAGE_VIEW_TYPE_3D:			return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
3246 		default:
3247 			DE_FATAL("Impossible");
3248 			return tcu::IVec3();
3249 	}
3250 }
3251 
fetchImageValue(int fetchPosNdx) const3252 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue (int fetchPosNdx) const
3253 {
3254 	DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
3255 
3256 	const tcu::TextureLevelPyramid&	fetchSrcA	= m_sourceImageA;
3257 	const tcu::TextureLevelPyramid&	fetchSrcB	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
3258 	const tcu::TextureLevelPyramid&	fetchSrc	= ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
3259 	tcu::IVec3						fetchPos	= getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
3260 
3261 	// add base array layer into the appropriate coordinate, based on the view type
3262 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
3263 		fetchPos.z() += 6 * m_baseArraySlice;
3264 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
3265 		fetchPos.y() += m_baseArraySlice;
3266 	else
3267 		fetchPos.z() += m_baseArraySlice;
3268 
3269 	return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
3270 }
3271 
3272 class ImageFetchRenderInstance : public SingleCmdRenderInstance
3273 {
3274 public:
3275 													ImageFetchRenderInstance	(vkt::Context&			context,
3276 																				 bool					isPrimaryCmdBuf,
3277 																				 vk::VkDescriptorType	descriptorType,
3278 																				 vk::VkShaderStageFlags	stageFlags,
3279 																				 ShaderInputInterface	shaderInterface,
3280 																				 vk::VkImageViewType	viewType,
3281 																				 deUint32				baseMipLevel,
3282 																				 deUint32				baseArraySlice);
3283 
3284 private:
3285 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(const vk::DeviceInterface&	vki,
3286 																				 vk::VkDevice				device,
3287 																				 vk::VkDescriptorType		descriptorType,
3288 																				 ShaderInputInterface		shaderInterface,
3289 																				 vk::VkShaderStageFlags		stageFlags);
3290 
3291 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout		(const vk::DeviceInterface&	vki,
3292 																				 vk::VkDevice				device,
3293 																				 vk::VkDescriptorSetLayout	descriptorSetLayout);
3294 
3295 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(const vk::DeviceInterface&	vki,
3296 																				 vk::VkDevice				device,
3297 																				 vk::VkDescriptorType		descriptorType,
3298 																				 ShaderInputInterface		shaderInterface);
3299 
3300 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(const vk::DeviceInterface&	vki,
3301 																				 vk::VkDevice				device,
3302 																				 vk::VkDescriptorType		descriptorType,
3303 																				 ShaderInputInterface		shaderInterface,
3304 																				 vk::VkDescriptorSetLayout	layout,
3305 																				 vk::VkDescriptorPool		pool,
3306 																				 vk::VkImageView			viewA,
3307 																				 vk::VkImageView			viewB);
3308 
3309 	void											logTestPlan					(void) const;
3310 	vk::VkPipelineLayout							getPipelineLayout			(void) const;
3311 	void											writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const;
3312 	tcu::TestStatus									verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const;
3313 
3314 	enum
3315 	{
3316 		RENDER_SIZE = 128,
3317 	};
3318 
3319 	const vk::VkDescriptorType						m_descriptorType;
3320 	const vk::VkShaderStageFlags					m_stageFlags;
3321 	const ShaderInputInterface						m_shaderInterface;
3322 	const vk::VkImageViewType						m_viewType;
3323 	const deUint32									m_baseMipLevel;
3324 	const deUint32									m_baseArraySlice;
3325 
3326 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
3327 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
3328 	const ImageFetchInstanceImages					m_images;
3329 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
3330 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
3331 };
3332 
ImageFetchRenderInstance(vkt::Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice)3333 ImageFetchRenderInstance::ImageFetchRenderInstance	(vkt::Context&			context,
3334 													 bool					isPrimaryCmdBuf,
3335 													 vk::VkDescriptorType	descriptorType,
3336 													 vk::VkShaderStageFlags	stageFlags,
3337 													 ShaderInputInterface	shaderInterface,
3338 													 vk::VkImageViewType	viewType,
3339 													 deUint32				baseMipLevel,
3340 													 deUint32				baseArraySlice)
3341 	: SingleCmdRenderInstance	(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
3342 	, m_descriptorType			(descriptorType)
3343 	, m_stageFlags				(stageFlags)
3344 	, m_shaderInterface			(shaderInterface)
3345 	, m_viewType				(viewType)
3346 	, m_baseMipLevel			(baseMipLevel)
3347 	, m_baseArraySlice			(baseArraySlice)
3348 	, m_descriptorSetLayout		(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
3349 	, m_pipelineLayout			(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
3350 	, m_images					(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
3351 	, m_descriptorPool			(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
3352 	, m_descriptorSet			(createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_images.getImageViewA(), m_images.getImageViewB()))
3353 {
3354 }
3355 
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags)3356 vk::Move<vk::VkDescriptorSetLayout> ImageFetchRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&		vki,
3357 																						 vk::VkDevice					device,
3358 																						 vk::VkDescriptorType			descriptorType,
3359 																						 ShaderInputInterface			shaderInterface,
3360 																						 vk::VkShaderStageFlags			stageFlags)
3361 {
3362 	vk::DescriptorSetLayoutBuilder builder;
3363 
3364 	switch (shaderInterface)
3365 	{
3366 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
3367 			builder.addSingleBinding(descriptorType, stageFlags);
3368 			break;
3369 
3370 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3371 			builder.addSingleBinding(descriptorType, stageFlags);
3372 			builder.addSingleBinding(descriptorType, stageFlags);
3373 			break;
3374 
3375 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
3376 			builder.addArrayBinding(descriptorType, 2u, stageFlags);
3377 			break;
3378 
3379 		default:
3380 			DE_FATAL("Impossible");
3381 	}
3382 
3383 	return builder.build(vki, device);
3384 }
3385 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)3386 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
3387 																			   vk::VkDevice					device,
3388 																			   vk::VkDescriptorSetLayout	descriptorSetLayout)
3389 {
3390 	const vk::VkPipelineLayoutCreateInfo createInfo =
3391 	{
3392 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
3393 		DE_NULL,
3394 		(vk::VkPipelineLayoutCreateFlags)0,
3395 		1,						// descriptorSetCount
3396 		&descriptorSetLayout,	// pSetLayouts
3397 		0u,						// pushConstantRangeCount
3398 		DE_NULL,				// pPushConstantRanges
3399 	};
3400 	return vk::createPipelineLayout(vki, device, &createInfo);
3401 }
3402 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)3403 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
3404 																			   vk::VkDevice					device,
3405 																			   vk::VkDescriptorType			descriptorType,
3406 																			   ShaderInputInterface			shaderInterface)
3407 {
3408 	return vk::DescriptorPoolBuilder()
3409 		.addType(descriptorType, getInterfaceNumResources(shaderInterface))
3410 		.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
3411 }
3412 
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkImageView viewA,vk::VkImageView viewB)3413 vk::Move<vk::VkDescriptorSet> ImageFetchRenderInstance::createDescriptorSet (const vk::DeviceInterface&		vki,
3414 																			 vk::VkDevice					device,
3415 																			 vk::VkDescriptorType			descriptorType,
3416 																			 ShaderInputInterface			shaderInterface,
3417 																			 vk::VkDescriptorSetLayout		layout,
3418 																			 vk::VkDescriptorPool			pool,
3419 																			 vk::VkImageView				viewA,
3420 																			 vk::VkImageView				viewB)
3421 {
3422 	const vk::VkImageLayout					imageLayout		= getImageLayoutForDescriptorType(descriptorType);
3423 	const vk::VkDescriptorImageInfo			imageInfos[2]	=
3424 	{
3425 		makeDescriptorImageInfo(viewA, imageLayout),
3426 		makeDescriptorImageInfo(viewB, imageLayout),
3427 	};
3428 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
3429 	{
3430 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
3431 		DE_NULL,
3432 		pool,
3433 		1u,
3434 		&layout
3435 	};
3436 
3437 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(vki, device, &allocInfo);
3438 	vk::DescriptorSetUpdateBuilder			builder;
3439 
3440 	switch (shaderInterface)
3441 	{
3442 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
3443 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
3444 			break;
3445 
3446 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3447 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
3448 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &imageInfos[1]);
3449 			break;
3450 
3451 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
3452 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, imageInfos);
3453 			break;
3454 
3455 		default:
3456 			DE_FATAL("Impossible");
3457 	}
3458 
3459 	builder.update(vki, device);
3460 	return descriptorSet;
3461 }
3462 
logTestPlan(void) const3463 void ImageFetchRenderInstance::logTestPlan (void) const
3464 {
3465 	std::ostringstream msg;
3466 
3467 	msg << "Rendering 2x2 grid.\n"
3468 		<< "Single descriptor set. Descriptor set contains "
3469 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
3470 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
3471 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
3472 			    (const char*)DE_NULL)
3473 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
3474 		<< "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
3475 
3476 	if (m_baseMipLevel)
3477 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
3478 	if (m_baseArraySlice)
3479 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
3480 
3481 	if (m_stageFlags == 0u)
3482 	{
3483 		msg << "Descriptors are not accessed in any shader stage.\n";
3484 	}
3485 	else
3486 	{
3487 		msg << "Color in each cell is fetched using the descriptor(s):\n";
3488 
3489 		for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3490 		{
3491 			msg << "Test sample " << resultNdx << ": fetching at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
3492 
3493 			if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
3494 			{
3495 				const int srcResourceNdx = (resultNdx % 2); // ABAB source
3496 				msg << " from descriptor " << srcResourceNdx;
3497 			}
3498 
3499 			msg << "\n";
3500 		}
3501 
3502 		msg << "Descriptors are accessed in {"
3503 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
3504 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
3505 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
3506 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
3507 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
3508 			<< " } stages.";
3509 	}
3510 
3511 	m_context.getTestContext().getLog()
3512 		<< tcu::TestLog::Message
3513 		<< msg.str()
3514 		<< tcu::TestLog::EndMessage;
3515 }
3516 
getPipelineLayout(void) const3517 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout (void) const
3518 {
3519 	return *m_pipelineLayout;
3520 }
3521 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const3522 void ImageFetchRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
3523 {
3524 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
3525 	m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
3526 }
3527 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const3528 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
3529 {
3530 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
3531 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
3532 	const bool			doFetch		= (m_stageFlags != 0u); // no active stages? Then don't fetch
3533 	const tcu::Vec4		sample0		= (!doFetch) ? (yellow)	: (m_images.fetchImageValue(0));
3534 	const tcu::Vec4		sample1		= (!doFetch) ? (green)	: (m_images.fetchImageValue(1));
3535 	const tcu::Vec4		sample2		= (!doFetch) ? (green)	: (m_images.fetchImageValue(2));
3536 	const tcu::Vec4		sample3		= (!doFetch) ? (yellow)	: (m_images.fetchImageValue(3));
3537 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
3538 
3539 	drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
3540 
3541 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
3542 		return tcu::TestStatus::fail("Image verification failed");
3543 	else
3544 		return tcu::TestStatus::pass("Pass");
3545 }
3546 
3547 class ImageFetchComputeInstance : public vkt::TestInstance
3548 {
3549 public:
3550 											ImageFetchComputeInstance	(vkt::Context&			context,
3551 																		 vk::VkDescriptorType	descriptorType,
3552 																		 ShaderInputInterface	shaderInterface,
3553 																		 vk::VkImageViewType	viewType,
3554 																		 deUint32				baseMipLevel,
3555 																		 deUint32				baseArraySlice);
3556 
3557 private:
3558 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(void) const;
3559 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(void) const;
3560 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
3561 
3562 	tcu::TestStatus							iterate						(void);
3563 	void									logTestPlan					(void) const;
3564 	tcu::TestStatus							testResourceAccess			(void);
3565 
3566 	const vk::VkDescriptorType				m_descriptorType;
3567 	const ShaderInputInterface				m_shaderInterface;
3568 	const vk::VkImageViewType				m_viewType;
3569 	const deUint32							m_baseMipLevel;
3570 	const deUint32							m_baseArraySlice;
3571 
3572 	const vk::DeviceInterface&				m_vki;
3573 	const vk::VkDevice						m_device;
3574 	const vk::VkQueue						m_queue;
3575 	const deUint32							m_queueFamilyIndex;
3576 	vk::Allocator&							m_allocator;
3577 
3578 	const ComputeInstanceResultBuffer		m_result;
3579 	const ImageFetchInstanceImages			m_images;
3580 };
3581 
ImageFetchComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice)3582 ImageFetchComputeInstance::ImageFetchComputeInstance (Context&				context,
3583 													  vk::VkDescriptorType	descriptorType,
3584 													  ShaderInputInterface	shaderInterface,
3585 													  vk::VkImageViewType	viewType,
3586 													  deUint32				baseMipLevel,
3587 													  deUint32				baseArraySlice)
3588 	: vkt::TestInstance		(context)
3589 	, m_descriptorType		(descriptorType)
3590 	, m_shaderInterface		(shaderInterface)
3591 	, m_viewType			(viewType)
3592 	, m_baseMipLevel		(baseMipLevel)
3593 	, m_baseArraySlice		(baseArraySlice)
3594 	, m_vki					(context.getDeviceInterface())
3595 	, m_device				(context.getDevice())
3596 	, m_queue				(context.getUniversalQueue())
3597 	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
3598 	, m_allocator			(context.getDefaultAllocator())
3599 	, m_result				(m_vki, m_device, m_allocator)
3600 	, m_images				(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
3601 {
3602 }
3603 
createDescriptorSetLayout(void) const3604 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout (void) const
3605 {
3606 	vk::DescriptorSetLayoutBuilder builder;
3607 
3608 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3609 
3610 	switch (m_shaderInterface)
3611 	{
3612 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
3613 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3614 			break;
3615 
3616 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3617 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3618 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3619 			break;
3620 
3621 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
3622 			builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3623 			break;
3624 
3625 		default:
3626 			DE_FATAL("Impossible");
3627 	};
3628 
3629 	return builder.build(m_vki, m_device);
3630 }
3631 
createDescriptorPool(void) const3632 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool (void) const
3633 {
3634 	return vk::DescriptorPoolBuilder()
3635 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3636 		.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
3637 		.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
3638 }
3639 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout) const3640 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
3641 {
3642 	const vk::VkDescriptorBufferInfo		resultInfo		= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
3643 	const vk::VkImageLayout					imageLayout		= getImageLayoutForDescriptorType(m_descriptorType);
3644 	const vk::VkDescriptorImageInfo			imageInfos[2]	=
3645 	{
3646 		makeDescriptorImageInfo(m_images.getImageViewA(), imageLayout),
3647 		makeDescriptorImageInfo(m_images.getImageViewB(), imageLayout),
3648 	};
3649 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
3650 	{
3651 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
3652 		DE_NULL,
3653 		pool,
3654 		1u,
3655 		&layout
3656 	};
3657 
3658 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(m_vki, m_device, &allocInfo);
3659 	vk::DescriptorSetUpdateBuilder			builder;
3660 
3661 	// result
3662 	builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
3663 
3664 	// images
3665 	switch (m_shaderInterface)
3666 	{
3667 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
3668 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
3669 			break;
3670 
3671 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3672 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
3673 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &imageInfos[1]);
3674 			break;
3675 
3676 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
3677 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, imageInfos);
3678 			break;
3679 
3680 		default:
3681 			DE_FATAL("Impossible");
3682 	}
3683 
3684 	builder.update(m_vki, m_device);
3685 	return descriptorSet;
3686 }
3687 
iterate(void)3688 tcu::TestStatus ImageFetchComputeInstance::iterate (void)
3689 {
3690 	logTestPlan();
3691 	return testResourceAccess();
3692 }
3693 
logTestPlan(void) const3694 void ImageFetchComputeInstance::logTestPlan (void) const
3695 {
3696 	std::ostringstream msg;
3697 
3698 	msg << "Fetching 4 values from image in compute shader.\n"
3699 		<< "Single descriptor set. Descriptor set contains "
3700 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
3701 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
3702 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
3703 			    (const char*)DE_NULL)
3704 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
3705 		<< "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
3706 
3707 	if (m_baseMipLevel)
3708 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
3709 	if (m_baseArraySlice)
3710 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
3711 
3712 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3713 	{
3714 		msg << "Test sample " << resultNdx << ": fetch at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
3715 
3716 		if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
3717 		{
3718 			const int srcResourceNdx = (resultNdx % 2); // ABAB source
3719 			msg << " from descriptor " << srcResourceNdx;
3720 		}
3721 
3722 		msg << "\n";
3723 	}
3724 
3725 	m_context.getTestContext().getLog()
3726 		<< tcu::TestLog::Message
3727 		<< msg.str()
3728 		<< tcu::TestLog::EndMessage;
3729 }
3730 
testResourceAccess(void)3731 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess (void)
3732 {
3733 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
3734 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
3735 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout));
3736 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
3737 
3738 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
3739 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
3740 	const deUint32* const							dynamicOffsets		= DE_NULL;
3741 	const int										numDynamicOffsets	= 0;
3742 	const vk::VkBufferMemoryBarrier* const			preBarriers			= DE_NULL;
3743 	const int										numPreBarriers		= 0;
3744 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
3745 	const int										numPostBarriers		= 1;
3746 
3747 	const ComputeCommand							compute				(m_vki,
3748 																		 m_device,
3749 																		 pipeline.getPipeline(),
3750 																		 pipeline.getPipelineLayout(),
3751 																		 tcu::UVec3(4, 1, 1),
3752 																		 numDescriptorSets,	descriptorSets,
3753 																		 numDynamicOffsets,	dynamicOffsets,
3754 																		 numPreBarriers,	preBarriers,
3755 																		 numPostBarriers,	postBarriers);
3756 
3757 	tcu::Vec4										results[4];
3758 	bool											anyResultSet		= false;
3759 	bool											allResultsOk		= true;
3760 
3761 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
3762 	m_result.readResultContentsTo(&results);
3763 
3764 	// verify
3765 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3766 	{
3767 		const tcu::Vec4	result				= results[resultNdx];
3768 		const tcu::Vec4	reference			= m_images.fetchImageValue(resultNdx);
3769 		const tcu::Vec4	conversionThreshold	= tcu::Vec4(1.0f / 255.0f);
3770 
3771 		if (result != tcu::Vec4(-1.0f))
3772 			anyResultSet = true;
3773 
3774 		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
3775 		{
3776 			allResultsOk = false;
3777 
3778 			m_context.getTestContext().getLog()
3779 				<< tcu::TestLog::Message
3780 				<< "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
3781 				<< tcu::TestLog::EndMessage;
3782 		}
3783 	}
3784 
3785 	// read back and verify
3786 	if (allResultsOk)
3787 		return tcu::TestStatus::pass("Pass");
3788 	else if (anyResultSet)
3789 		return tcu::TestStatus::fail("Invalid result values");
3790 	else
3791 	{
3792 		m_context.getTestContext().getLog()
3793 			<< tcu::TestLog::Message
3794 			<< "Result buffer was not written to."
3795 			<< tcu::TestLog::EndMessage;
3796 		return tcu::TestStatus::fail("Result buffer was not written to");
3797 	}
3798 }
3799 
3800 class ImageSampleInstanceImages : private ImageInstanceImages
3801 {
3802 public:
3803 										ImageSampleInstanceImages	(const vk::DeviceInterface&		vki,
3804 																	 vk::VkDevice					device,
3805 																	 deUint32						queueFamilyIndex,
3806 																	 vk::VkQueue					queue,
3807 																	 vk::Allocator&					allocator,
3808 																	 vk::VkDescriptorType			descriptorType,
3809 																	 ShaderInputInterface			shaderInterface,
3810 																	 vk::VkImageViewType			viewType,
3811 																	 deUint32						baseMipLevel,
3812 																	 deUint32						baseArraySlice,
3813 																	 bool							immutable);
3814 
3815 	static tcu::Vec4					getSamplePos				(vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx);
3816 	tcu::Vec4							fetchSampleValue			(int samplePosNdx) const;
3817 
getImageViewA(void) const3818 	inline vk::VkImageView				getImageViewA				(void) const { return *m_imageViewA;	}
getImageViewB(void) const3819 	inline vk::VkImageView				getImageViewB				(void) const { return *m_imageViewB;	}
getSamplerA(void) const3820 	inline vk::VkSampler				getSamplerA					(void) const { return *m_samplerA;		}
getSamplerB(void) const3821 	inline vk::VkSampler				getSamplerB					(void) const { return *m_samplerB;		}
isImmutable(void) const3822 	inline bool							isImmutable					(void) const { return m_isImmutable;	}
3823 
3824 private:
3825 	static int							getNumImages				(vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface);
3826 	static tcu::Sampler					createRefSampler			(bool isFirst);
3827 	static vk::Move<vk::VkSampler>		createSampler				(const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format);
3828 
3829 	static tcu::Texture1DArrayView		getRef1DView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3830 	static tcu::Texture2DArrayView		getRef2DView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3831 	static tcu::Texture3DView			getRef3DView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3832 	static tcu::TextureCubeArrayView	getRefCubeView				(const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3833 
3834 	const vk::VkDescriptorType			m_descriptorType;
3835 	const ShaderInputInterface			m_shaderInterface;
3836 	const bool							m_isImmutable;
3837 
3838 	const tcu::Sampler					m_refSamplerA;
3839 	const tcu::Sampler					m_refSamplerB;
3840 	const vk::Unique<vk::VkSampler>		m_samplerA;
3841 	const vk::Unique<vk::VkSampler>		m_samplerB;
3842 };
3843 
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)3844 ImageSampleInstanceImages::ImageSampleInstanceImages (const vk::DeviceInterface&	vki,
3845 													  vk::VkDevice					device,
3846 													  deUint32						queueFamilyIndex,
3847 													  vk::VkQueue					queue,
3848 													  vk::Allocator&				allocator,
3849 													  vk::VkDescriptorType			descriptorType,
3850 													  ShaderInputInterface			shaderInterface,
3851 													  vk::VkImageViewType			viewType,
3852 													  deUint32						baseMipLevel,
3853 													  deUint32						baseArraySlice,
3854 													  bool							immutable)
3855 	: ImageInstanceImages	(vki,
3856 							 device,
3857 							 queueFamilyIndex,
3858 							 queue,
3859 							 allocator,
3860 							 descriptorType,
3861 							 viewType,
3862 							 getNumImages(descriptorType, shaderInterface),
3863 							 baseMipLevel,
3864 							 baseArraySlice)
3865 	, m_descriptorType		(descriptorType)
3866 	, m_shaderInterface		(shaderInterface)
3867 	, m_isImmutable			(immutable)
3868 	, m_refSamplerA			(createRefSampler(true))
3869 	, m_refSamplerB			(createRefSampler(false))
3870 	, m_samplerA			(createSampler(vki, device, m_refSamplerA, m_imageFormat))
3871 	, m_samplerB			((getInterfaceNumResources(m_shaderInterface) == 1u)
3872 								? vk::Move<vk::VkSampler>()
3873 								: createSampler(vki, device, m_refSamplerB, m_imageFormat))
3874 {
3875 }
3876 
getSamplePos(vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,int samplePosNdx)3877 tcu::Vec4 ImageSampleInstanceImages::getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx)
3878 {
3879 	DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
3880 
3881 	const deUint32	imageSize	= (deUint32)IMAGE_SIZE >> baseMipLevel;
3882 	const deUint32	arraySize	= isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
3883 
3884 	// choose arbitrary values that are not ambiguous with NEAREST filtering
3885 
3886 	switch (viewType)
3887 	{
3888 		case vk::VK_IMAGE_VIEW_TYPE_1D:
3889 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
3890 		case vk::VK_IMAGE_VIEW_TYPE_2D:
3891 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
3892 		case vk::VK_IMAGE_VIEW_TYPE_3D:
3893 		{
3894 			const tcu::Vec3	coords[4]	=
3895 			{
3896 				tcu::Vec3(0.75f,
3897 						  0.5f,
3898 						  (float)(12u % imageSize) + 0.25f),
3899 
3900 				tcu::Vec3((float)(23u % imageSize) + 0.25f,
3901 						  (float)(73u % imageSize) + 0.5f,
3902 						  (float)(16u % imageSize) + 0.5f + (float)imageSize),
3903 
3904 				tcu::Vec3(-(float)(43u % imageSize) + 0.25f,
3905 						  (float)(84u % imageSize) + 0.5f + (float)imageSize,
3906 						  (float)(117u % imageSize) + 0.75f),
3907 
3908 				tcu::Vec3((float)imageSize + 0.5f,
3909 						  (float)(75u % imageSize) + 0.25f,
3910 						  (float)(83u % imageSize) + 0.25f + (float)imageSize),
3911 			};
3912 			const deUint32	slices[4]	=
3913 			{
3914 				0u % arraySize,
3915 				4u % arraySize,
3916 				9u % arraySize,
3917 				2u % arraySize,
3918 			};
3919 
3920 			if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
3921 				return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3922 								 (float)slices[samplePosNdx],
3923 								 0.0f,
3924 								 0.0f);
3925 			else if (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)
3926 				return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3927 								 coords[samplePosNdx].y() / (float)imageSize,
3928 								 (float)slices[samplePosNdx],
3929 								 0.0f);
3930 			else if (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)
3931 				return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3932 								 coords[samplePosNdx].y() / (float)imageSize,
3933 								 coords[samplePosNdx].z() / (float)imageSize,
3934 								 0.0f);
3935 			else
3936 			{
3937 				DE_FATAL("Impossible");
3938 				return tcu::Vec4();
3939 			}
3940 		}
3941 
3942 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
3943 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
3944 		{
3945 			// \note these values are in [0, texSize]*3 space for convenience
3946 			const tcu::Vec3	coords[4]	=
3947 			{
3948 				tcu::Vec3(0.75f,
3949 						  0.5f,
3950 						  (float)imageSize),
3951 
3952 				tcu::Vec3((float)(13u % imageSize) + 0.25f,
3953 						  0.0f,
3954 						  (float)(16u % imageSize) + 0.5f),
3955 
3956 				tcu::Vec3(0.0f,
3957 						  (float)(84u % imageSize) + 0.5f,
3958 						  (float)(10u % imageSize) + 0.75f),
3959 
3960 				tcu::Vec3((float)imageSize,
3961 						  (float)(75u % imageSize) + 0.25f,
3962 						  (float)(83u % imageSize) + 0.75f),
3963 			};
3964 			const deUint32	slices[4]	=
3965 			{
3966 				1u % arraySize,
3967 				2u % arraySize,
3968 				9u % arraySize,
3969 				5u % arraySize,
3970 			};
3971 
3972 			DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
3973 			DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
3974 			DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
3975 
3976 			// map to [-1, 1]*3 space
3977 			return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
3978 							 coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
3979 							 coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f,
3980 							 (float)slices[samplePosNdx]);
3981 		}
3982 
3983 		default:
3984 			DE_FATAL("Impossible");
3985 			return tcu::Vec4();
3986 	}
3987 }
3988 
fetchSampleValue(int samplePosNdx) const3989 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue (int samplePosNdx) const
3990 {
3991 	DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
3992 
3993 	// texture order is ABAB
3994 	const bool									isSamplerCase	= (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
3995 	const tcu::TextureLevelPyramid&				sampleSrcA		= m_sourceImageA;
3996 	const tcu::TextureLevelPyramid&				sampleSrcB		= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
3997 	const tcu::TextureLevelPyramid&				sampleSrc		= (isSamplerCase) ? (sampleSrcA) : ((samplePosNdx % 2) == 0) ? (sampleSrcA) : (sampleSrcB);
3998 
3999 	// sampler order is ABAB
4000 	const tcu::Sampler&							samplerA		= m_refSamplerA;
4001 	const tcu::Sampler&							samplerB		= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_refSamplerA) : (m_refSamplerB);
4002 	const tcu::Sampler&							sampler			= ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
4003 
4004 	const tcu::Vec4								samplePos		= getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
4005 	const float									lod				= 0.0f;
4006 	std::vector<tcu::ConstPixelBufferAccess>	levelStorage;
4007 
4008 	switch (m_viewType)
4009 	{
4010 		case vk::VK_IMAGE_VIEW_TYPE_1D:
4011 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:	return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), lod);
4012 		case vk::VK_IMAGE_VIEW_TYPE_2D:
4013 		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);
4014 		case vk::VK_IMAGE_VIEW_TYPE_3D:			return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
4015 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4016 		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);
4017 
4018 		default:
4019 		{
4020 			DE_FATAL("Impossible");
4021 			return tcu::Vec4();
4022 		}
4023 	}
4024 }
4025 
getNumImages(vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)4026 int ImageSampleInstanceImages::getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface)
4027 {
4028 	// If we are testing separate samplers, just one image is enough
4029 	if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4030 		return 1;
4031 	else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4032 	{
4033 		// combined: numImages == numSamplers
4034 		return getInterfaceNumResources(shaderInterface);
4035 	}
4036 	else
4037 	{
4038 		DE_FATAL("Impossible");
4039 		return 0;
4040 	}
4041 }
4042 
createRefSampler(bool isFirst)4043 tcu::Sampler ImageSampleInstanceImages::createRefSampler (bool isFirst)
4044 {
4045 	if (isFirst)
4046 	{
4047 		// linear, wrapping
4048 		return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
4049 	}
4050 	else
4051 	{
4052 		// nearest, clamping
4053 		return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
4054 	}
4055 }
4056 
createSampler(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::Sampler & sampler,const tcu::TextureFormat & format)4057 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format)
4058 {
4059 	const vk::VkSamplerCreateInfo	createInfo		= vk::mapSampler(sampler, format);
4060 
4061 	return vk::createSampler(vki, device, &createInfo);
4062 }
4063 
getRef1DView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4064 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4065 {
4066 	DE_ASSERT(levelStorage->empty());
4067 
4068 	const deUint32 numSlices = (deUint32)source.getLevel(0).getHeight();
4069 	const deUint32 numLevels = (deUint32)source.getNumLevels();
4070 
4071 	// cut pyramid from baseMipLevel
4072 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4073 	{
4074 		// cut levels from baseArraySlice
4075 		const tcu::ConstPixelBufferAccess wholeLevel	= source.getLevel(level);
4076 		const tcu::ConstPixelBufferAccess cutLevel		= tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
4077 		levelStorage->push_back(cutLevel);
4078 	}
4079 
4080 	return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
4081 }
4082 
getRef2DView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4083 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4084 {
4085 	DE_ASSERT(levelStorage->empty());
4086 
4087 	const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth();
4088 	const deUint32 numLevels = (deUint32)source.getNumLevels();
4089 
4090 	// cut pyramid from baseMipLevel
4091 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4092 	{
4093 		// cut levels from baseArraySlice
4094 		const tcu::ConstPixelBufferAccess wholeLevel	= source.getLevel(level);
4095 		const tcu::ConstPixelBufferAccess cutLevel		= tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(), numSlices - baseArraySlice);
4096 		levelStorage->push_back(cutLevel);
4097 	}
4098 
4099 	return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
4100 }
4101 
getRef3DView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4102 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4103 {
4104 	DE_ASSERT(levelStorage->empty());
4105 	DE_ASSERT(baseArraySlice == 0);
4106 	DE_UNREF(baseArraySlice);
4107 
4108 	const deUint32 numLevels = (deUint32)source.getNumLevels();
4109 
4110 	// cut pyramid from baseMipLevel
4111 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4112 		levelStorage->push_back(source.getLevel(level));
4113 
4114 	return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
4115 }
4116 
getRefCubeView(const tcu::TextureLevelPyramid & source,deUint32 baseMipLevel,deUint32 baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)4117 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4118 {
4119 	DE_ASSERT(levelStorage->empty());
4120 
4121 	const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth() / 6;
4122 	const deUint32 numLevels = (deUint32)source.getNumLevels();
4123 
4124 	// cut pyramid from baseMipLevel
4125 	for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4126 	{
4127 		// cut levels from baseArraySlice
4128 		const tcu::ConstPixelBufferAccess wholeLevel	= source.getLevel(level);
4129 		const tcu::ConstPixelBufferAccess cutLevel		= tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(), (numSlices - baseArraySlice) * 6);
4130 		levelStorage->push_back(cutLevel);
4131 	}
4132 
4133 	return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
4134 }
4135 
4136 class ImageSampleRenderInstance : public SingleCmdRenderInstance
4137 {
4138 public:
4139 													ImageSampleRenderInstance		(vkt::Context&			context,
4140 																					 bool					isPrimaryCmdBuf,
4141 																					 vk::VkDescriptorType	descriptorType,
4142 																					 vk::VkShaderStageFlags	stageFlags,
4143 																					 ShaderInputInterface	shaderInterface,
4144 																					 vk::VkImageViewType	viewType,
4145 																					 deUint32				baseMipLevel,
4146 																					 deUint32				baseArraySlice,
4147 																					 bool					isImmutable);
4148 
4149 private:
4150 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout		(const vk::DeviceInterface&			vki,
4151 																					 vk::VkDevice						device,
4152 																					 vk::VkDescriptorType				descriptorType,
4153 																					 ShaderInputInterface				shaderInterface,
4154 																					 vk::VkShaderStageFlags				stageFlags,
4155 																					 const ImageSampleInstanceImages&	images);
4156 
4157 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout			(const vk::DeviceInterface&	vki,
4158 																					 vk::VkDevice				device,
4159 																					 vk::VkDescriptorSetLayout	descriptorSetLayout);
4160 
4161 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool			(const vk::DeviceInterface&	vki,
4162 																					 vk::VkDevice				device,
4163 																					 vk::VkDescriptorType		descriptorType,
4164 																					 ShaderInputInterface		shaderInterface);
4165 
4166 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet				(const vk::DeviceInterface&			vki,
4167 																					 vk::VkDevice						device,
4168 																					 vk::VkDescriptorType				descriptorType,
4169 																					 ShaderInputInterface				shaderInterface,
4170 																					 vk::VkDescriptorSetLayout			layout,
4171 																					 vk::VkDescriptorPool				pool,
4172 																					 bool								isImmutable,
4173 																					 const ImageSampleInstanceImages&	images);
4174 
4175 	static void										writeSamplerDescriptorSet		(const vk::DeviceInterface&			vki,
4176 																					 vk::VkDevice						device,
4177 																					 ShaderInputInterface				shaderInterface,
4178 																					 bool								isImmutable,
4179 																					 const ImageSampleInstanceImages&	images,
4180 																					 vk::VkDescriptorSet				descriptorSet);
4181 
4182 	static void										writeImageSamplerDescriptorSet	(const vk::DeviceInterface&			vki,
4183 																					 vk::VkDevice						device,
4184 																					 ShaderInputInterface				shaderInterface,
4185 																					 bool								isImmutable,
4186 																					 const ImageSampleInstanceImages&	images,
4187 																					 vk::VkDescriptorSet				descriptorSet);
4188 
4189 	void											logTestPlan						(void) const;
4190 	vk::VkPipelineLayout							getPipelineLayout				(void) const;
4191 	void											writeDrawCmdBuffer				(vk::VkCommandBuffer cmd) const;
4192 	tcu::TestStatus									verifyResultImage				(const tcu::ConstPixelBufferAccess& result) const;
4193 
4194 	enum
4195 	{
4196 		RENDER_SIZE = 128,
4197 	};
4198 
4199 	const vk::VkDescriptorType						m_descriptorType;
4200 	const vk::VkShaderStageFlags					m_stageFlags;
4201 	const ShaderInputInterface						m_shaderInterface;
4202 	const vk::VkImageViewType						m_viewType;
4203 	const deUint32									m_baseMipLevel;
4204 	const deUint32									m_baseArraySlice;
4205 
4206 	const ImageSampleInstanceImages					m_images;
4207 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
4208 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
4209 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
4210 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
4211 };
4212 
ImageSampleRenderInstance(vkt::Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,bool isImmutable)4213 ImageSampleRenderInstance::ImageSampleRenderInstance (vkt::Context&				context,
4214 													  bool						isPrimaryCmdBuf,
4215 													  vk::VkDescriptorType		descriptorType,
4216 													  vk::VkShaderStageFlags	stageFlags,
4217 													  ShaderInputInterface		shaderInterface,
4218 													  vk::VkImageViewType		viewType,
4219 													  deUint32					baseMipLevel,
4220 													  deUint32					baseArraySlice,
4221 													  bool						isImmutable)
4222 	: SingleCmdRenderInstance	(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
4223 	, m_descriptorType			(descriptorType)
4224 	, m_stageFlags				(stageFlags)
4225 	, m_shaderInterface			(shaderInterface)
4226 	, m_viewType				(viewType)
4227 	, m_baseMipLevel			(baseMipLevel)
4228 	, m_baseArraySlice			(baseArraySlice)
4229 	, m_images					(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutable)
4230 	, m_descriptorSetLayout		(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_images))
4231 	, m_pipelineLayout			(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
4232 	, m_descriptorPool			(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
4233 	, m_descriptorSet			(createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, isImmutable, m_images))
4234 {
4235 }
4236 
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,const ImageSampleInstanceImages & images)4237 vk::Move<vk::VkDescriptorSetLayout> ImageSampleRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&		vki,
4238 																						  vk::VkDevice						device,
4239 																						  vk::VkDescriptorType				descriptorType,
4240 																						  ShaderInputInterface				shaderInterface,
4241 																						  vk::VkShaderStageFlags			stageFlags,
4242 																						  const ImageSampleInstanceImages&	images)
4243 {
4244 	const vk::VkSampler				samplers[2] =
4245 	{
4246 		images.getSamplerA(),
4247 		images.getSamplerB(),
4248 	};
4249 
4250 	vk::DescriptorSetLayoutBuilder	builder;
4251 	const bool						addSeparateImage	= descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
4252 
4253 	// (combined)samplers follow
4254 	switch (shaderInterface)
4255 	{
4256 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
4257 			if (addSeparateImage)
4258 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4259 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4260 			break;
4261 
4262 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4263 			if (addSeparateImage)
4264 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4265 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4266 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4267 			break;
4268 
4269 		case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4270 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4271 			if (addSeparateImage)
4272 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4273 			builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4274 			break;
4275 
4276 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
4277 			if (addSeparateImage)
4278 				builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4279 			builder.addArraySamplerBinding(descriptorType, 2u, stageFlags, (images.isImmutable()) ? (samplers) : (DE_NULL));
4280 			break;
4281 
4282 		default:
4283 			DE_FATAL("Impossible");
4284 	}
4285 
4286 	return builder.build(vki, device);
4287 }
4288 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)4289 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
4290 																				vk::VkDevice				device,
4291 																				vk::VkDescriptorSetLayout	descriptorSetLayout)
4292 {
4293 	const vk::VkPipelineLayoutCreateInfo createInfo =
4294 	{
4295 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4296 		DE_NULL,
4297 		(vk::VkPipelineLayoutCreateFlags)0,
4298 		1,						// descriptorSetCount
4299 		&descriptorSetLayout,	// pSetLayouts
4300 		0u,						// pushConstantRangeCount
4301 		DE_NULL,				// pPushConstantRanges
4302 	};
4303 	return vk::createPipelineLayout(vki, device, &createInfo);
4304 }
4305 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)4306 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
4307 																				vk::VkDevice				device,
4308 																				vk::VkDescriptorType		descriptorType,
4309 																				ShaderInputInterface		shaderInterface)
4310 {
4311 	vk::DescriptorPoolBuilder builder;
4312 
4313 	if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4314 	{
4315 		// separate samplers need image to sample
4316 		builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
4317 
4318 		// also need sample to use, indifferent of whether immutable or not
4319 		builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER, getInterfaceNumResources(shaderInterface));
4320 	}
4321 	else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4322 	{
4323 		// combined image samplers
4324 		builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, getInterfaceNumResources(shaderInterface));
4325 	}
4326 	else
4327 		DE_FATAL("Impossible");
4328 
4329 	return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
4330 }
4331 
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,bool isImmutable,const ImageSampleInstanceImages & images)4332 vk::Move<vk::VkDescriptorSet> ImageSampleRenderInstance::createDescriptorSet (const vk::DeviceInterface&		vki,
4333 																			  vk::VkDevice						device,
4334 																			  vk::VkDescriptorType				descriptorType,
4335 																			  ShaderInputInterface				shaderInterface,
4336 																			  vk::VkDescriptorSetLayout			layout,
4337 																			  vk::VkDescriptorPool				pool,
4338 																			  bool								isImmutable,
4339 																			  const ImageSampleInstanceImages&	images)
4340 {
4341 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
4342 	{
4343 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
4344 		DE_NULL,
4345 		pool,
4346 		1u,
4347 		&layout
4348 	};
4349 
4350 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(vki, device, &allocInfo);
4351 
4352 	if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4353 		writeSamplerDescriptorSet(vki, device,  shaderInterface, isImmutable, images, *descriptorSet);
4354 	else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4355 		writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
4356 	else
4357 		DE_FATAL("Impossible");
4358 
4359 	return descriptorSet;
4360 }
4361 
writeSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet)4362 void ImageSampleRenderInstance::writeSamplerDescriptorSet (const vk::DeviceInterface&		vki,
4363 														   vk::VkDevice						device,
4364 														   ShaderInputInterface				shaderInterface,
4365 														   bool								isImmutable,
4366 														   const ImageSampleInstanceImages&	images,
4367 														   vk::VkDescriptorSet				descriptorSet)
4368 {
4369 	const vk::VkDescriptorImageInfo		imageInfo			= makeDescriptorImageInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4370 	const vk::VkDescriptorImageInfo		samplersInfos[2]	=
4371 	{
4372 		makeDescriptorImageInfo(images.getSamplerA()),
4373 		makeDescriptorImageInfo(images.getSamplerB()),
4374 	};
4375 
4376 	vk::DescriptorSetUpdateBuilder		builder;
4377 	const deUint32						samplerLocation		= shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
4378 
4379 	// stand alone texture
4380 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
4381 
4382 	// samplers
4383 	if (!isImmutable)
4384 	{
4385 		switch (shaderInterface)
4386 		{
4387 			case SHADER_INPUT_SINGLE_DESCRIPTOR:
4388 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4389 				break;
4390 
4391 			case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4392 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4393 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4394 				break;
4395 
4396 			case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4397 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4398 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4399 				break;
4400 
4401 			case SHADER_INPUT_DESCRIPTOR_ARRAY:
4402 				builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
4403 				break;
4404 
4405 			default:
4406 				DE_FATAL("Impossible");
4407 		}
4408 	}
4409 
4410 	builder.update(vki, device);
4411 }
4412 
writeImageSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet)4413 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet (const vk::DeviceInterface&			vki,
4414 																vk::VkDevice						device,
4415 																ShaderInputInterface				shaderInterface,
4416 																bool								isImmutable,
4417 																const ImageSampleInstanceImages&	images,
4418 																vk::VkDescriptorSet					descriptorSet)
4419 {
4420 	const vk::VkSampler					samplers[2]			=
4421 	{
4422 		(isImmutable) ? (0) : (images.getSamplerA()),
4423 		(isImmutable) ? (0) : (images.getSamplerB()),
4424 	};
4425 	const vk::VkDescriptorImageInfo		imageSamplers[2]	=
4426 	{
4427 		vk::makeDescriptorImageInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4428 		vk::makeDescriptorImageInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4429 	};
4430 
4431 	vk::DescriptorSetUpdateBuilder		builder;
4432 
4433 	// combined image samplers
4434 	switch (shaderInterface)
4435 	{
4436 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
4437 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4438 			break;
4439 
4440 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4441 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4442 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
4443 			break;
4444 
4445 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
4446 			builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
4447 			break;
4448 
4449 		default:
4450 			DE_FATAL("Impossible");
4451 	}
4452 
4453 	builder.update(vki, device);
4454 }
4455 
logTestPlan(void) const4456 void ImageSampleRenderInstance::logTestPlan (void) const
4457 {
4458 	std::ostringstream msg;
4459 
4460 	msg << "Rendering 2x2 grid.\n";
4461 
4462 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4463 	{
4464 		msg << "Single descriptor set. Descriptor set contains "
4465 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4466 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4467 				(m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4468 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4469 			    (const char*)DE_NULL)
4470 			<< " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
4471 	}
4472 	else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4473 	{
4474 		msg << "Single descriptor set. Descriptor set contains "
4475 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4476 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4477 				(m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4478 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4479 			    (const char*)DE_NULL)
4480 			<< " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
4481 	}
4482 	else
4483 		DE_FATAL("Impossible");
4484 
4485 	msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4486 
4487 	if (m_baseMipLevel)
4488 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4489 	if (m_baseArraySlice)
4490 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4491 
4492 	if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
4493 		msg << "Sampler mode is LINEAR, with WRAP\n";
4494 	else
4495 		msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
4496 
4497 	if (m_stageFlags == 0u)
4498 	{
4499 		msg << "Descriptors are not accessed in any shader stage.\n";
4500 	}
4501 	else
4502 	{
4503 		msg << "Color in each cell is fetched using the descriptor(s):\n";
4504 
4505 		for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4506 		{
4507 			msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4508 
4509 			if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4510 			{
4511 				const int srcResourceNdx = (resultNdx % 2); // ABAB source
4512 
4513 				if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4514 					msg << " using sampler " << srcResourceNdx;
4515 				else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4516 					msg << " from combined image sampler " << srcResourceNdx;
4517 				else
4518 					DE_FATAL("Impossible");
4519 			}
4520 			msg << "\n";
4521 		}
4522 
4523 		msg << "Descriptors are accessed in {"
4524 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
4525 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
4526 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
4527 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
4528 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
4529 			<< " } stages.";
4530 	}
4531 
4532 	m_context.getTestContext().getLog()
4533 		<< tcu::TestLog::Message
4534 		<< msg.str()
4535 		<< tcu::TestLog::EndMessage;
4536 }
4537 
getPipelineLayout(void) const4538 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout (void) const
4539 {
4540 	return *m_pipelineLayout;
4541 }
4542 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const4543 void ImageSampleRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
4544 {
4545 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
4546 	m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
4547 }
4548 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const4549 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
4550 {
4551 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
4552 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
4553 	const bool			doFetch		= (m_stageFlags != 0u); // no active stages? Then don't fetch
4554 	const tcu::Vec4		sample0		= (!doFetch) ? (yellow)	: (m_images.fetchSampleValue(0));
4555 	const tcu::Vec4		sample1		= (!doFetch) ? (green)	: (m_images.fetchSampleValue(1));
4556 	const tcu::Vec4		sample2		= (!doFetch) ? (green)	: (m_images.fetchSampleValue(2));
4557 	const tcu::Vec4		sample3		= (!doFetch) ? (yellow)	: (m_images.fetchSampleValue(3));
4558 	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
4559 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
4560 
4561 	drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4562 
4563 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, threshold, tcu::COMPARE_LOG_RESULT))
4564 		return tcu::TestStatus::fail("Image verification failed");
4565 	else
4566 		return tcu::TestStatus::pass("Pass");
4567 }
4568 
4569 class ImageSampleComputeInstance : public vkt::TestInstance
4570 {
4571 public:
4572 											ImageSampleComputeInstance		(vkt::Context&			context,
4573 																			 vk::VkDescriptorType	descriptorType,
4574 																			 ShaderInputInterface	shaderInterface,
4575 																			 vk::VkImageViewType	viewType,
4576 																			 deUint32				baseMipLevel,
4577 																			 deUint32				baseArraySlice,
4578 																			 bool					isImmutableSampler);
4579 
4580 private:
4581 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout		(void) const;
4582 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool			(void) const;
4583 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet				(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
4584 	void									writeImageSamplerDescriptorSet	(vk::VkDescriptorSet descriptorSet) const;
4585 	void									writeSamplerDescriptorSet		(vk::VkDescriptorSet descriptorSet) const;
4586 
4587 	tcu::TestStatus							iterate							(void);
4588 	void									logTestPlan						(void) const;
4589 	tcu::TestStatus							testResourceAccess				(void);
4590 
4591 	const vk::VkDescriptorType				m_descriptorType;
4592 	const ShaderInputInterface				m_shaderInterface;
4593 	const vk::VkImageViewType				m_viewType;
4594 	const deUint32							m_baseMipLevel;
4595 	const deUint32							m_baseArraySlice;
4596 	const bool								m_isImmutableSampler;
4597 
4598 	const vk::DeviceInterface&				m_vki;
4599 	const vk::VkDevice						m_device;
4600 	const vk::VkQueue						m_queue;
4601 	const deUint32							m_queueFamilyIndex;
4602 	vk::Allocator&							m_allocator;
4603 
4604 	const ComputeInstanceResultBuffer		m_result;
4605 	const ImageSampleInstanceImages			m_images;
4606 };
4607 
ImageSampleComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 baseMipLevel,deUint32 baseArraySlice,bool isImmutableSampler)4608 ImageSampleComputeInstance::ImageSampleComputeInstance (Context&				context,
4609 														vk::VkDescriptorType	descriptorType,
4610 														ShaderInputInterface	shaderInterface,
4611 														vk::VkImageViewType		viewType,
4612 														deUint32				baseMipLevel,
4613 														deUint32				baseArraySlice,
4614 														bool					isImmutableSampler)
4615 	: vkt::TestInstance		(context)
4616 	, m_descriptorType		(descriptorType)
4617 	, m_shaderInterface		(shaderInterface)
4618 	, m_viewType			(viewType)
4619 	, m_baseMipLevel		(baseMipLevel)
4620 	, m_baseArraySlice		(baseArraySlice)
4621 	, m_isImmutableSampler	(isImmutableSampler)
4622 	, m_vki					(context.getDeviceInterface())
4623 	, m_device				(context.getDevice())
4624 	, m_queue				(context.getUniversalQueue())
4625 	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
4626 	, m_allocator			(context.getDefaultAllocator())
4627 	, m_result				(m_vki, m_device, m_allocator)
4628 	, m_images				(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
4629 {
4630 }
4631 
createDescriptorSetLayout(void) const4632 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout (void) const
4633 {
4634 	const vk::VkSampler				samplers[2] =
4635 	{
4636 		m_images.getSamplerA(),
4637 		m_images.getSamplerB(),
4638 	};
4639 
4640 	vk::DescriptorSetLayoutBuilder	builder;
4641 
4642 	// result buffer
4643 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4644 
4645 	// with samplers, separate texture at binding 0
4646 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4647 		builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4648 
4649 	// (combined)samplers follow
4650 	switch (m_shaderInterface)
4651 	{
4652 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
4653 			builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4654 			break;
4655 
4656 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4657 			builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4658 			builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4659 			break;
4660 
4661 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
4662 			builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (samplers) : (DE_NULL));
4663 			break;
4664 
4665 		default:
4666 			DE_FATAL("Impossible");
4667 	};
4668 
4669 	return builder.build(m_vki, m_device);
4670 }
4671 
createDescriptorPool(void) const4672 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool (void) const
4673 {
4674 	vk::DescriptorPoolBuilder builder;
4675 
4676 	builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
4677 	builder.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface));
4678 
4679 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4680 		builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
4681 
4682 	return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
4683 }
4684 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout) const4685 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
4686 {
4687 	const vk::VkDescriptorSetAllocateInfo	allocInfo		=
4688 	{
4689 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
4690 		DE_NULL,
4691 		pool,
4692 		1u,
4693 		&layout
4694 	};
4695 
4696 	vk::Move<vk::VkDescriptorSet>			descriptorSet	= allocateDescriptorSet(m_vki, m_device, &allocInfo);
4697 
4698 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4699 		writeSamplerDescriptorSet(*descriptorSet);
4700 	else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4701 		writeImageSamplerDescriptorSet(*descriptorSet);
4702 	else
4703 		DE_FATAL("Impossible");
4704 
4705 	return descriptorSet;
4706 }
4707 
writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet) const4708 void ImageSampleComputeInstance::writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
4709 {
4710 	const vk::VkDescriptorBufferInfo	resultInfo			= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4711 	const vk::VkDescriptorImageInfo		imageInfo			= makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4712 	const vk::VkDescriptorImageInfo		samplersInfos[2]	=
4713 	{
4714 		makeDescriptorImageInfo(m_images.getSamplerA()),
4715 		makeDescriptorImageInfo(m_images.getSamplerB()),
4716 	};
4717 
4718 	vk::DescriptorSetUpdateBuilder		builder;
4719 
4720 	// result
4721 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4722 
4723 	// stand alone texture
4724 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
4725 
4726 	// samplers
4727 	if (!m_isImmutableSampler)
4728 	{
4729 		switch (m_shaderInterface)
4730 		{
4731 			case SHADER_INPUT_SINGLE_DESCRIPTOR:
4732 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4733 				break;
4734 
4735 			case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4736 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4737 				builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(3u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4738 				break;
4739 
4740 			case SHADER_INPUT_DESCRIPTOR_ARRAY:
4741 				builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
4742 				break;
4743 
4744 			default:
4745 				DE_FATAL("Impossible");
4746 		}
4747 	}
4748 
4749 	builder.update(m_vki, m_device);
4750 }
4751 
writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet) const4752 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
4753 {
4754 	const vk::VkDescriptorBufferInfo	resultInfo			= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4755 	const vk::VkSampler					samplers[2]			=
4756 	{
4757 		(m_isImmutableSampler) ? (0) : (m_images.getSamplerA()),
4758 		(m_isImmutableSampler) ? (0) : (m_images.getSamplerB()),
4759 	};
4760 	const vk::VkDescriptorImageInfo		imageSamplers[2]	=
4761 	{
4762 		makeDescriptorImageInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4763 		makeDescriptorImageInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4764 	};
4765 
4766 	vk::DescriptorSetUpdateBuilder		builder;
4767 
4768 	// result
4769 	builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4770 
4771 	// combined image samplers
4772 	switch (m_shaderInterface)
4773 	{
4774 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
4775 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4776 			break;
4777 
4778 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4779 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4780 			builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
4781 			break;
4782 
4783 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
4784 			builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
4785 			break;
4786 
4787 		default:
4788 			DE_FATAL("Impossible");
4789 	}
4790 
4791 	builder.update(m_vki, m_device);
4792 }
4793 
iterate(void)4794 tcu::TestStatus ImageSampleComputeInstance::iterate (void)
4795 {
4796 	logTestPlan();
4797 	return testResourceAccess();
4798 }
4799 
logTestPlan(void) const4800 void ImageSampleComputeInstance::logTestPlan (void) const
4801 {
4802 	std::ostringstream msg;
4803 
4804 	msg << "Accessing resource in a compute program.\n";
4805 
4806 	if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4807 	{
4808 		msg << "Single descriptor set. Descriptor set contains "
4809 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4810 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4811 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4812 			    (const char*)DE_NULL)
4813 			<< " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
4814 	}
4815 	else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4816 	{
4817 		msg << "Single descriptor set. Descriptor set contains "
4818 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4819 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
4820 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4821 			    (const char*)DE_NULL)
4822 			<< " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
4823 	}
4824 	else
4825 		DE_FATAL("Impossible");
4826 
4827 	msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4828 
4829 	if (m_baseMipLevel)
4830 		msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4831 	if (m_baseArraySlice)
4832 		msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4833 
4834 	if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
4835 		msg << "Sampler mode is LINEAR, with WRAP\n";
4836 	else
4837 		msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
4838 
4839 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4840 	{
4841 		msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4842 
4843 		if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4844 		{
4845 			const int srcResourceNdx = (resultNdx % 2); // ABAB source
4846 
4847 			if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4848 				msg << " using sampler " << srcResourceNdx;
4849 			else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4850 				msg << " from combined image sampler " << srcResourceNdx;
4851 			else
4852 				DE_FATAL("Impossible");
4853 		}
4854 		msg << "\n";
4855 	}
4856 
4857 	m_context.getTestContext().getLog()
4858 		<< tcu::TestLog::Message
4859 		<< msg.str()
4860 		<< tcu::TestLog::EndMessage;
4861 }
4862 
testResourceAccess(void)4863 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess (void)
4864 {
4865 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
4866 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
4867 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout));
4868 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
4869 
4870 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
4871 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
4872 	const deUint32* const							dynamicOffsets		= DE_NULL;
4873 	const int										numDynamicOffsets	= 0;
4874 	const vk::VkBufferMemoryBarrier* const			preBarriers			= DE_NULL;
4875 	const int										numPreBarriers		= 0;
4876 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
4877 	const int										numPostBarriers		= 1;
4878 
4879 	const ComputeCommand							compute				(m_vki,
4880 																		 m_device,
4881 																		 pipeline.getPipeline(),
4882 																		 pipeline.getPipelineLayout(),
4883 																		 tcu::UVec3(4, 1, 1),
4884 																		 numDescriptorSets,	descriptorSets,
4885 																		 numDynamicOffsets,	dynamicOffsets,
4886 																		 numPreBarriers,	preBarriers,
4887 																		 numPostBarriers,	postBarriers);
4888 
4889 	tcu::Vec4										results[4];
4890 	bool											anyResultSet		= false;
4891 	bool											allResultsOk		= true;
4892 
4893 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
4894 	m_result.readResultContentsTo(&results);
4895 
4896 	// verify
4897 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4898 	{
4899 		const tcu::Vec4	result				= results[resultNdx];
4900 		const tcu::Vec4	reference			= m_images.fetchSampleValue(resultNdx);
4901 
4902 		// source image is high-frequency so the threshold is quite large to tolerate sampling errors
4903 		const tcu::Vec4	samplingThreshold	= tcu::Vec4(8.0f / 255.0f);
4904 
4905 		if (result != tcu::Vec4(-1.0f))
4906 			anyResultSet = true;
4907 
4908 		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
4909 		{
4910 			allResultsOk = false;
4911 
4912 			m_context.getTestContext().getLog()
4913 				<< tcu::TestLog::Message
4914 				<< "Test sample " << resultNdx << ":\n"
4915 				<< "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx) << "\n"
4916 				<< "\tError expected " << reference << ", got " << result
4917 				<< tcu::TestLog::EndMessage;
4918 		}
4919 	}
4920 
4921 	// read back and verify
4922 	if (allResultsOk)
4923 		return tcu::TestStatus::pass("Pass");
4924 	else if (anyResultSet)
4925 		return tcu::TestStatus::fail("Invalid result values");
4926 	else
4927 	{
4928 		m_context.getTestContext().getLog()
4929 			<< tcu::TestLog::Message
4930 			<< "Result buffer was not written to."
4931 			<< tcu::TestLog::EndMessage;
4932 		return tcu::TestStatus::fail("Result buffer was not written to");
4933 	}
4934 }
4935 
4936 class ImageDescriptorCase : public QuadrantRendederCase
4937 {
4938 public:
4939 	enum
4940 	{
4941 		FLAG_BASE_MIP	= (1u << 1u),
4942 		FLAG_BASE_SLICE	= (1u << 2u),
4943 	};
4944 	// enum continues where resource flags ends
4945 	DE_STATIC_ASSERT((deUint32)FLAG_BASE_MIP == (deUint32)RESOURCE_FLAG_LAST);
4946 
4947 								ImageDescriptorCase			(tcu::TestContext&		testCtx,
4948 															 const char*			name,
4949 															 const char*			description,
4950 															 bool					isPrimaryCmdBuf,
4951 															 vk::VkDescriptorType	descriptorType,
4952 															 vk::VkShaderStageFlags	exitingStages,
4953 															 vk::VkShaderStageFlags	activeStages,
4954 															 ShaderInputInterface	shaderInterface,
4955 															 vk::VkImageViewType	viewType,
4956 															 deUint32				flags);
4957 
4958 private:
4959 	std::string					genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const;
4960 	std::string					genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
4961 	std::string					genFetchCoordStr			(int fetchPosNdx) const;
4962 	std::string					genSampleCoordStr			(int samplePosNdx) const;
4963 	std::string					genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const;
4964 	std::string					genNoAccessSource			(void) const;
4965 
4966 	vkt::TestInstance*			createInstance				(vkt::Context& context) const;
4967 
4968 private:
4969 	const bool					m_isPrimaryCmdBuf;
4970 	const vk::VkDescriptorType	m_descriptorType;
4971 	const ShaderInputInterface	m_shaderInterface;
4972 	const vk::VkImageViewType	m_viewType;
4973 	const deUint32				m_baseMipLevel;
4974 	const deUint32				m_baseArraySlice;
4975 	const bool					m_isImmutableSampler;
4976 };
4977 
ImageDescriptorCase(tcu::TestContext & testCtx,const char * name,const char * description,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,deUint32 flags)4978 ImageDescriptorCase::ImageDescriptorCase (tcu::TestContext&			testCtx,
4979 										  const char*				name,
4980 										  const char*				description,
4981 										  bool						isPrimaryCmdBuf,
4982 										  vk::VkDescriptorType		descriptorType,
4983 										  vk::VkShaderStageFlags	exitingStages,
4984 										  vk::VkShaderStageFlags	activeStages,
4985 										  ShaderInputInterface		shaderInterface,
4986 										  vk::VkImageViewType		viewType,
4987 										  deUint32					flags)
4988 	: QuadrantRendederCase	(testCtx, name, description,
4989 							 // \note 1D textures are not supported in ES
4990 							 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? glu::GLSL_VERSION_440 : glu::GLSL_VERSION_310_ES,
4991 							 exitingStages, activeStages)
4992 	, m_isPrimaryCmdBuf		(isPrimaryCmdBuf)
4993 	, m_descriptorType		(descriptorType)
4994 	, m_shaderInterface		(shaderInterface)
4995 	, m_viewType			(viewType)
4996 	, m_baseMipLevel		(((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
4997 	, m_baseArraySlice		(((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
4998 	, m_isImmutableSampler	((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
4999 {
5000 }
5001 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const5002 std::string ImageDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
5003 {
5004 	DE_UNREF(stage);
5005 
5006 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
5007 		return "#extension GL_OES_texture_cube_map_array : require\n";
5008 	else
5009 		return "";
5010 }
5011 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const5012 std::string ImageDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
5013 {
5014 	DE_UNREF(stage);
5015 
5016 	// Vulkan-style resources are arrays implicitly, OpenGL-style are not
5017 	const std::string	dimensionBase	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? ("1D")
5018 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? ("2D")
5019 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)															? ("3D")
5020 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? ("Cube")
5021 										: (DE_NULL);
5022 	const std::string	dimensionArray	= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)		? ("1DArray")
5023 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)		? ("2DArray")
5024 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)															? ("3D")
5025 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? ("CubeArray")
5026 										: (DE_NULL);
5027 	const std::string	dimension		= isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
5028 
5029 	if (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
5030 		DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
5031 
5032 	switch (m_shaderInterface)
5033 	{
5034 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
5035 		{
5036 			switch (m_descriptorType)
5037 			{
5038 				case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5039 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5040 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler;\n";
5041 				case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5042 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler;\n";
5043 				case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5044 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n";
5045 				case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5046 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image;\n";
5047 				default:
5048 					DE_FATAL("invalid descriptor");
5049 					return "";
5050 			}
5051 		}
5052 
5053 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5054 		case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5055 			switch (m_descriptorType)
5056 			{
5057 				case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5058 					if (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)
5059 						return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5060 								"layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplerA;\n"
5061 								"layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
5062 					else
5063 						return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler u_separateSamplerA;\n"
5064 								"layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5065 								"layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
5066 				case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5067 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerA;\n"
5068 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerB;\n";
5069 				case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5070 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTextureA;\n"
5071 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimensionBase + " u_separateTextureB;\n";
5072 				case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5073 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_imageA;\n"
5074 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ", rgba8) readonly uniform highp image" + dimension + " u_imageB;\n";
5075 				default:
5076 					DE_FATAL("invalid descriptor");
5077 					return "";
5078 			}
5079 
5080 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
5081 			switch (m_descriptorType)
5082 			{
5083 				case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5084 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n"
5085 						   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler[2];\n";
5086 				case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5087 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler[2];\n";
5088 				case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5089 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture[2];\n";
5090 				case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5091 					return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image[2];\n";
5092 				default:
5093 					DE_FATAL("invalid descriptor");
5094 					return "";
5095 			}
5096 
5097 		default:
5098 			DE_FATAL("Impossible");
5099 			return "";
5100 	}
5101 }
5102 
genFetchCoordStr(int fetchPosNdx) const5103 std::string ImageDescriptorCase::genFetchCoordStr (int fetchPosNdx) const
5104 {
5105 	DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
5106 	const tcu::IVec3 fetchPos = ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
5107 
5108 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
5109 	{
5110 		return de::toString(fetchPos.x());
5111 	}
5112 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
5113 	{
5114 		std::ostringstream buf;
5115 		buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
5116 		return buf.str();
5117 	}
5118 	else
5119 	{
5120 		std::ostringstream buf;
5121 		buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
5122 		return buf.str();
5123 	}
5124 }
5125 
genSampleCoordStr(int samplePosNdx) const5126 std::string ImageDescriptorCase::genSampleCoordStr (int samplePosNdx) const
5127 {
5128 	DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
5129 	const tcu::Vec4 fetchPos = ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5130 
5131 	if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
5132 	{
5133 		std::ostringstream buf;
5134 		buf << "float(" << fetchPos.x() << ")";
5135 		return buf.str();
5136 	}
5137 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
5138 	{
5139 		std::ostringstream buf;
5140 		buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
5141 		return buf.str();
5142 	}
5143 	else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
5144 	{
5145 		std::ostringstream buf;
5146 		buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "), float(" << fetchPos.w() << "))";
5147 		return buf.str();
5148 	}
5149 	else
5150 	{
5151 		std::ostringstream buf;
5152 		buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
5153 		return buf.str();
5154 	}
5155 }
5156 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const5157 std::string ImageDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
5158 {
5159 	DE_UNREF(stage);
5160 
5161 	const char* const	dimension		= (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)			? ("1D")
5162 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)	? ("1DArray")
5163 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)			? ("2D")
5164 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)	? ("2DArray")
5165 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)			? ("3D")
5166 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)		? ("Cube")
5167 										: (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)	? ("CubeArray")
5168 										: (DE_NULL);
5169 	const char* const	accessPostfixA	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
5170 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("A")
5171 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)	? ("A")
5172 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[0]")
5173 										: (DE_NULL);
5174 	const char* const	accessPostfixB	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
5175 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("B")
5176 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)	? ("B")
5177 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[1]")
5178 										: (DE_NULL);
5179 
5180 	switch (m_descriptorType)
5181 	{
5182 		case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5183 		case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5184 		{
5185 			const std::string	coodStr[4]	=
5186 			{
5187 				genSampleCoordStr(0),
5188 				genSampleCoordStr(1),
5189 				genSampleCoordStr(2),
5190 				genSampleCoordStr(3),
5191 			};
5192 			std::ostringstream	buf;
5193 
5194 			if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5195 			{
5196 				buf << "	if (quadrant_id == 0)\n"
5197 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[0] << ", 0.0);\n"
5198 					<< "	else if (quadrant_id == 1)\n"
5199 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[1] << ", 0.0);\n"
5200 					<< "	else if (quadrant_id == 2)\n"
5201 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[2] << ", 0.0);\n"
5202 					<< "	else\n"
5203 					<< "		result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[3] << ", 0.0);\n";
5204 			}
5205 			else
5206 			{
5207 				buf << "	if (quadrant_id == 0)\n"
5208 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[0] << ", 0.0);\n"
5209 					<< "	else if (quadrant_id == 1)\n"
5210 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[1] << ", 0.0);\n"
5211 					<< "	else if (quadrant_id == 2)\n"
5212 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[2] << ", 0.0);\n"
5213 					<< "	else\n"
5214 					<< "		result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[3] << ", 0.0);\n";
5215 			}
5216 
5217 			return buf.str();
5218 		}
5219 
5220 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5221 		{
5222 			const std::string	coodStr[4]	=
5223 			{
5224 				genFetchCoordStr(0),
5225 				genFetchCoordStr(1),
5226 				genFetchCoordStr(2),
5227 				genFetchCoordStr(3),
5228 			};
5229 			std::ostringstream	buf;
5230 
5231 			buf << "	if (quadrant_id == 0)\n"
5232 				<< "		result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[0] << ");\n"
5233 				<< "	else if (quadrant_id == 1)\n"
5234 				<< "		result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[1] << ");\n"
5235 				<< "	else if (quadrant_id == 2)\n"
5236 				<< "		result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[2] << ");\n"
5237 				<< "	else\n"
5238 				<< "		result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[3] << ");\n";
5239 
5240 			return buf.str();
5241 		}
5242 
5243 		default:
5244 			DE_FATAL("invalid descriptor");
5245 			return "";
5246 	}
5247 }
5248 
genNoAccessSource(void) const5249 std::string ImageDescriptorCase::genNoAccessSource (void) const
5250 {
5251 	return "	if (quadrant_id == 1 || quadrant_id == 2)\n"
5252 			"		result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
5253 			"	else\n"
5254 			"		result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
5255 }
5256 
createInstance(vkt::Context & context) const5257 vkt::TestInstance* ImageDescriptorCase::createInstance (vkt::Context& context) const
5258 {
5259 	verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
5260 
5261 	switch (m_descriptorType)
5262 	{
5263 		case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5264 		case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5265 			if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
5266 			{
5267 				DE_ASSERT(m_isPrimaryCmdBuf);
5268 				return new ImageSampleComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
5269 			}
5270 			else
5271 				return new ImageSampleRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
5272 
5273 		case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5274 		case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5275 			if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
5276 			{
5277 				DE_ASSERT(m_isPrimaryCmdBuf);
5278 				return new ImageFetchComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
5279 			}
5280 			else
5281 				return new ImageFetchRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
5282 
5283 		default:
5284 			DE_FATAL("Impossible");
5285 			return DE_NULL;
5286 	}
5287 }
5288 
5289 class TexelBufferInstanceBuffers
5290 {
5291 public:
5292 											TexelBufferInstanceBuffers	(const vk::DeviceInterface&		vki,
5293 																		 vk::VkDevice					device,
5294 																		 vk::Allocator&					allocator,
5295 																		 vk::VkDescriptorType			descriptorType,
5296 																		 int							numTexelBuffers,
5297 																		 bool							hasViewOffset);
5298 
5299 private:
5300 	static vk::Move<vk::VkBuffer>			createBuffer				(const vk::DeviceInterface&		vki,
5301 																		 vk::VkDevice					device,
5302 																		 vk::Allocator&					allocator,
5303 																		 vk::VkDescriptorType			descriptorType,
5304 																		 de::MovePtr<vk::Allocation>	*outAllocation);
5305 
5306 	static vk::Move<vk::VkBufferView>		createBufferView			(const vk::DeviceInterface&		vki,
5307 																		 vk::VkDevice					device,
5308 																		 const tcu::TextureFormat&		textureFormat,
5309 																		 deUint32						offset,
5310 																		 vk::VkBuffer					buffer);
5311 
5312 	static vk::VkBufferMemoryBarrier		createBarrier				(vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
5313 
5314 	void									populateSourceBuffer		(const tcu::PixelBufferAccess& access);
5315 	void									uploadData					(const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data);
5316 
5317 public:
5318 	static int								getFetchPos					(int fetchPosNdx);
5319 	tcu::Vec4								fetchTexelValue				(int fetchPosNdx) const;
5320 
getNumTexelBuffers(void) const5321 	inline int								getNumTexelBuffers			(void) const { return m_numTexelBuffers;	}
getTextureFormat(void) const5322 	const tcu::TextureFormat&				getTextureFormat			(void) const { return m_imageFormat;		}
getBufferViewA(void) const5323 	inline vk::VkBufferView					getBufferViewA				(void) const { return *m_bufferViewA;		}
getBufferViewB(void) const5324 	inline vk::VkBufferView					getBufferViewB				(void) const { return *m_bufferViewB;		}
getBufferInitBarriers(void) const5325 	inline const vk::VkBufferMemoryBarrier*	getBufferInitBarriers		(void) const { return m_bufferBarriers;		}
5326 
5327 private:
5328 	enum
5329 	{
5330 		BUFFER_SIZE			= 512,
5331 		VIEW_OFFSET_VALUE	= 256,
5332 		VIEW_DATA_SIZE		= 256,	//!< size in bytes
5333 		VIEW_WIDTH			= 64,	//!< size in pixels
5334 	};
5335 	enum
5336 	{
5337 		// some arbitrary points
5338 		SAMPLE_POINT_0 = 6,
5339 		SAMPLE_POINT_1 = 51,
5340 		SAMPLE_POINT_2 = 42,
5341 		SAMPLE_POINT_3 = 25,
5342 	};
5343 
5344 	const deUint32							m_numTexelBuffers;
5345 	const tcu::TextureFormat				m_imageFormat;
5346 	const deUint32							m_viewOffset;
5347 
5348 	de::ArrayBuffer<deUint8>				m_sourceBufferA;
5349 	de::ArrayBuffer<deUint8>				m_sourceBufferB;
5350 	const tcu::ConstPixelBufferAccess		m_sourceViewA;
5351 	const tcu::ConstPixelBufferAccess		m_sourceViewB;
5352 
5353 	de::MovePtr<vk::Allocation>				m_bufferMemoryA;
5354 	de::MovePtr<vk::Allocation>				m_bufferMemoryB;
5355 	const vk::Unique<vk::VkBuffer>			m_bufferA;
5356 	const vk::Unique<vk::VkBuffer>			m_bufferB;
5357 	const vk::Unique<vk::VkBufferView>		m_bufferViewA;
5358 	const vk::Unique<vk::VkBufferView>		m_bufferViewB;
5359 	vk::VkBufferMemoryBarrier				m_bufferBarriers[2];
5360 };
5361 
TexelBufferInstanceBuffers(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,int numTexelBuffers,bool hasViewOffset)5362 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers (const vk::DeviceInterface&		vki,
5363 														vk::VkDevice					device,
5364 														vk::Allocator&					allocator,
5365 														vk::VkDescriptorType			descriptorType,
5366 														int								numTexelBuffers,
5367 														bool							hasViewOffset)
5368 	: m_numTexelBuffers	(numTexelBuffers)
5369 	, m_imageFormat		(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
5370 	, m_viewOffset		((hasViewOffset) ? ((deUint32)VIEW_OFFSET_VALUE) : (0u))
5371 	, m_sourceBufferA	(BUFFER_SIZE)
5372 	, m_sourceBufferB	((numTexelBuffers == 1)
5373 							? (0u)
5374 							: ((size_t)BUFFER_SIZE))
5375 	, m_sourceViewA		(m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferA.getElementPtr(m_viewOffset))
5376 	, m_sourceViewB		(m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferB.getElementPtr(m_viewOffset))
5377 	, m_bufferMemoryA	(DE_NULL)
5378 	, m_bufferMemoryB	(DE_NULL)
5379 	, m_bufferA			(createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryA))
5380 	, m_bufferB			((numTexelBuffers == 1)
5381 							? vk::Move<vk::VkBuffer>()
5382 							: createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryB))
5383 	, m_bufferViewA		(createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferA))
5384 	, m_bufferViewB		((numTexelBuffers == 1)
5385 							? vk::Move<vk::VkBufferView>()
5386 							: createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferB))
5387 {
5388 	DE_ASSERT(numTexelBuffers == 1 || numTexelBuffers == 2);
5389 	DE_ASSERT(VIEW_WIDTH * m_imageFormat.getPixelSize() == VIEW_DATA_SIZE);
5390 	DE_ASSERT(BUFFER_SIZE % m_imageFormat.getPixelSize() == 0);
5391 
5392 	// specify and upload
5393 
5394 	populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferA.getPtr()));
5395 	uploadData(vki, device, *m_bufferMemoryA, m_sourceBufferA);
5396 
5397 	if (numTexelBuffers == 2)
5398 	{
5399 		populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferB.getPtr()));
5400 		uploadData(vki, device, *m_bufferMemoryB, m_sourceBufferB);
5401 	}
5402 
5403 	m_bufferBarriers[0] = createBarrier(descriptorType, *m_bufferA);
5404 	m_bufferBarriers[1] = createBarrier(descriptorType, *m_bufferB);
5405 }
5406 
createBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,de::MovePtr<vk::Allocation> * outAllocation)5407 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer (const vk::DeviceInterface&		vki,
5408 																 vk::VkDevice					device,
5409 																 vk::Allocator&					allocator,
5410 																 vk::VkDescriptorType			descriptorType,
5411 																 de::MovePtr<vk::Allocation>	*outAllocation)
5412 {
5413 	const vk::VkBufferUsageFlags	usage		= (isUniformDescriptorType(descriptorType)) ? (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
5414 	const vk::VkBufferCreateInfo	createInfo	=
5415 	{
5416 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
5417 		DE_NULL,
5418 		0u,									// flags
5419 		(vk::VkDeviceSize)BUFFER_SIZE,		// size
5420 		usage,								// usage
5421 		vk::VK_SHARING_MODE_EXCLUSIVE,		// sharingMode
5422 		0u,									// queueFamilyCount
5423 		DE_NULL,							// pQueueFamilyIndices
5424 	};
5425 	vk::Move<vk::VkBuffer>			buffer		(vk::createBuffer(vki, device, &createInfo));
5426 	de::MovePtr<vk::Allocation>		allocation	(allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
5427 
5428 	*outAllocation = allocation;
5429 	return buffer;
5430 }
5431 
createBufferView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & textureFormat,deUint32 offset,vk::VkBuffer buffer)5432 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView (const vk::DeviceInterface&		vki,
5433 																		 vk::VkDevice					device,
5434 																		 const tcu::TextureFormat&		textureFormat,
5435 																		 deUint32						offset,
5436 																		 vk::VkBuffer					buffer)
5437 {
5438 	const vk::VkBufferViewCreateInfo createInfo =
5439 	{
5440 		vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
5441 		DE_NULL,
5442 		(vk::VkBufferViewCreateFlags)0,
5443 		buffer,									// buffer
5444 		vk::mapTextureFormat(textureFormat),	// format
5445 		(vk::VkDeviceSize)offset,				// offset
5446 		(vk::VkDeviceSize)VIEW_DATA_SIZE		// range
5447 	};
5448 	return vk::createBufferView(vki, device, &createInfo);
5449 }
5450 
createBarrier(vk::VkDescriptorType descriptorType,vk::VkBuffer buffer)5451 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer)
5452 {
5453 	const vk::VkAccessFlags			inputBit	= (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
5454 	const vk::VkBufferMemoryBarrier	barrier		=
5455 	{
5456 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
5457 		DE_NULL,
5458 		vk::VK_ACCESS_HOST_WRITE_BIT,			// outputMask
5459 		inputBit,								// inputMask
5460 		vk::VK_QUEUE_FAMILY_IGNORED,			// srcQueueFamilyIndex
5461 		vk::VK_QUEUE_FAMILY_IGNORED,			// destQueueFamilyIndex
5462 		buffer	,								// buffer
5463 		0u,										// offset
5464 		(vk::VkDeviceSize)BUFFER_SIZE			// size
5465 	};
5466 	return barrier;
5467 }
5468 
populateSourceBuffer(const tcu::PixelBufferAccess & access)5469 void TexelBufferInstanceBuffers::populateSourceBuffer (const tcu::PixelBufferAccess& access)
5470 {
5471 	DE_ASSERT(access.getHeight() == 1);
5472 	DE_ASSERT(access.getDepth() == 1);
5473 
5474 	const deInt32 width = access.getWidth();
5475 
5476 	for (int x = 0; x < width; ++x)
5477 	{
5478 		const int			red		= 255 * x / width;												//!< gradient from 0 -> max (detects large offset errors)
5479 		const int			green	= ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0));	//!< 3-level M pattern (detects small offset errors)
5480 		const int			blue	= 16 * (x % 16);												//!< 16-long triangle wave
5481 
5482 		DE_ASSERT(de::inRange(red, 0, 255));
5483 		DE_ASSERT(de::inRange(green, 0, 255));
5484 		DE_ASSERT(de::inRange(blue, 0, 255));
5485 
5486 		access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
5487 	}
5488 }
5489 
uploadData(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::Allocation & memory,const de::ArrayBuffer<deUint8> & data)5490 void TexelBufferInstanceBuffers::uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data)
5491 {
5492 	deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
5493 	flushMappedMemoryRange(vki, device, memory.getMemory(), memory.getOffset(), data.size());
5494 }
5495 
getFetchPos(int fetchPosNdx)5496 int TexelBufferInstanceBuffers::getFetchPos (int fetchPosNdx)
5497 {
5498 	static const int fetchPositions[4] =
5499 	{
5500 		SAMPLE_POINT_0,
5501 		SAMPLE_POINT_1,
5502 		SAMPLE_POINT_2,
5503 		SAMPLE_POINT_3,
5504 	};
5505 	return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
5506 }
5507 
fetchTexelValue(int fetchPosNdx) const5508 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue (int fetchPosNdx) const
5509 {
5510 	// source order is ABAB
5511 	const tcu::ConstPixelBufferAccess&	texelSrcA	= m_sourceViewA;
5512 	const tcu::ConstPixelBufferAccess&	texelSrcB	= (m_numTexelBuffers == 1) ? (m_sourceViewA) : (m_sourceViewB);
5513 	const tcu::ConstPixelBufferAccess&	texelSrc	= ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
5514 
5515 	return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
5516 }
5517 
5518 class TexelBufferRenderInstance : public SingleCmdRenderInstance
5519 {
5520 public:
5521 													TexelBufferRenderInstance	(vkt::Context&			context,
5522 																				 bool					isPrimaryCmdBuf,
5523 																				 vk::VkDescriptorType	descriptorType,
5524 																				 vk::VkShaderStageFlags	stageFlags,
5525 																				 ShaderInputInterface	shaderInterface,
5526 																				 bool					nonzeroViewOffset);
5527 
5528 private:
5529 	static vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(const vk::DeviceInterface&	vki,
5530 																				 vk::VkDevice				device,
5531 																				 vk::VkDescriptorType		descriptorType,
5532 																				 ShaderInputInterface		shaderInterface,
5533 																				 vk::VkShaderStageFlags		stageFlags);
5534 
5535 	static vk::Move<vk::VkPipelineLayout>			createPipelineLayout		(const vk::DeviceInterface&	vki,
5536 																				 vk::VkDevice				device,
5537 																				 vk::VkDescriptorSetLayout	descriptorSetLayout);
5538 
5539 	static vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(const vk::DeviceInterface&	vki,
5540 																				 vk::VkDevice				device,
5541 																				 vk::VkDescriptorType		descriptorType,
5542 																				 ShaderInputInterface		shaderInterface);
5543 
5544 	static vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(const vk::DeviceInterface&	vki,
5545 																				 vk::VkDevice				device,
5546 																				 vk::VkDescriptorType		descriptorType,
5547 																				 ShaderInputInterface		shaderInterface,
5548 																				 vk::VkDescriptorSetLayout	layout,
5549 																				 vk::VkDescriptorPool		pool,
5550 																				 vk::VkBufferView			viewA,
5551 																				 vk::VkBufferView			viewB);
5552 
5553 	void											logTestPlan					(void) const;
5554 	vk::VkPipelineLayout							getPipelineLayout			(void) const;
5555 	void											writeDrawCmdBuffer			(vk::VkCommandBuffer cmd) const;
5556 	tcu::TestStatus									verifyResultImage			(const tcu::ConstPixelBufferAccess& result) const;
5557 
5558 	enum
5559 	{
5560 		RENDER_SIZE = 128,
5561 	};
5562 
5563 	const vk::VkDescriptorType						m_descriptorType;
5564 	const vk::VkShaderStageFlags					m_stageFlags;
5565 	const ShaderInputInterface						m_shaderInterface;
5566 	const bool										m_nonzeroViewOffset;
5567 
5568 	const vk::Unique<vk::VkDescriptorSetLayout>		m_descriptorSetLayout;
5569 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
5570 	const TexelBufferInstanceBuffers				m_texelBuffers;
5571 	const vk::Unique<vk::VkDescriptorPool>			m_descriptorPool;
5572 	const vk::Unique<vk::VkDescriptorSet>			m_descriptorSet;
5573 };
5574 
TexelBufferRenderInstance(vkt::Context & context,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags stageFlags,ShaderInputInterface shaderInterface,bool nonzeroViewOffset)5575 TexelBufferRenderInstance::TexelBufferRenderInstance (vkt::Context&				context,
5576 													  bool						isPrimaryCmdBuf,
5577 													  vk::VkDescriptorType		descriptorType,
5578 													  vk::VkShaderStageFlags	stageFlags,
5579 													  ShaderInputInterface		shaderInterface,
5580 													  bool						nonzeroViewOffset)
5581 	: SingleCmdRenderInstance	(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
5582 	, m_descriptorType			(descriptorType)
5583 	, m_stageFlags				(stageFlags)
5584 	, m_shaderInterface			(shaderInterface)
5585 	, m_nonzeroViewOffset		(nonzeroViewOffset)
5586 	, m_descriptorSetLayout		(createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
5587 	, m_pipelineLayout			(createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
5588 	, m_texelBuffers			(m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
5589 	, m_descriptorPool			(createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
5590 	, m_descriptorSet			(createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_texelBuffers.getBufferViewA(), m_texelBuffers.getBufferViewB()))
5591 {
5592 }
5593 
createDescriptorSetLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags)5594 vk::Move<vk::VkDescriptorSetLayout> TexelBufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&	vki,
5595 																						  vk::VkDevice					device,
5596 																						  vk::VkDescriptorType			descriptorType,
5597 																						  ShaderInputInterface			shaderInterface,
5598 																						  vk::VkShaderStageFlags		stageFlags)
5599 {
5600 	vk::DescriptorSetLayoutBuilder builder;
5601 
5602 	switch (shaderInterface)
5603 	{
5604 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
5605 			builder.addSingleBinding(descriptorType, stageFlags);
5606 			break;
5607 
5608 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5609 			builder.addSingleBinding(descriptorType, stageFlags);
5610 			builder.addSingleBinding(descriptorType, stageFlags);
5611 			break;
5612 
5613 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
5614 			builder.addArrayBinding(descriptorType, 2u, stageFlags);
5615 			break;
5616 
5617 		default:
5618 			DE_FATAL("Impossible");
5619 	}
5620 
5621 	return builder.build(vki, device);
5622 }
5623 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout descriptorSetLayout)5624 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout (const vk::DeviceInterface&	vki,
5625 																				vk::VkDevice				device,
5626 																				vk::VkDescriptorSetLayout	descriptorSetLayout)
5627 {
5628 	const vk::VkPipelineLayoutCreateInfo createInfo =
5629 	{
5630 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5631 		DE_NULL,
5632 		(vk::VkPipelineLayoutCreateFlags)0,
5633 		1,						// descriptorSetCount
5634 		&descriptorSetLayout,	// pSetLayouts
5635 		0u,						// pushConstantRangeCount
5636 		DE_NULL,				// pPushConstantRanges
5637 	};
5638 	return vk::createPipelineLayout(vki, device, &createInfo);
5639 }
5640 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface)5641 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool (const vk::DeviceInterface&	vki,
5642 																				vk::VkDevice					device,
5643 																				vk::VkDescriptorType			descriptorType,
5644 																				ShaderInputInterface			shaderInterface)
5645 {
5646 	return vk::DescriptorPoolBuilder()
5647 		.addType(descriptorType, getInterfaceNumResources(shaderInterface))
5648 		.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
5649 }
5650 
createDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkBufferView viewA,vk::VkBufferView viewB)5651 vk::Move<vk::VkDescriptorSet> TexelBufferRenderInstance::createDescriptorSet (const vk::DeviceInterface&	vki,
5652 																			  vk::VkDevice					device,
5653 																			  vk::VkDescriptorType			descriptorType,
5654 																			  ShaderInputInterface			shaderInterface,
5655 																			  vk::VkDescriptorSetLayout		layout,
5656 																			  vk::VkDescriptorPool			pool,
5657 																			  vk::VkBufferView				viewA,
5658 																			  vk::VkBufferView				viewB)
5659 {
5660 	const vk::VkBufferView					texelBufferInfos[2]	=
5661 	{
5662 		viewA,
5663 		viewB,
5664 	};
5665 	const vk::VkDescriptorSetAllocateInfo	allocInfo			=
5666 	{
5667 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5668 		DE_NULL,
5669 		pool,
5670 		1u,
5671 		&layout
5672 	};
5673 
5674 	vk::Move<vk::VkDescriptorSet>			descriptorSet		= allocateDescriptorSet(vki, device, &allocInfo);
5675 	vk::DescriptorSetUpdateBuilder			builder;
5676 
5677 	switch (shaderInterface)
5678 	{
5679 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
5680 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
5681 			break;
5682 
5683 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5684 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
5685 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &texelBufferInfos[1]);
5686 			break;
5687 
5688 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
5689 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, texelBufferInfos);
5690 			break;
5691 
5692 		default:
5693 			DE_FATAL("Impossible");
5694 	}
5695 
5696 	builder.update(vki, device);
5697 	return descriptorSet;
5698 }
5699 
logTestPlan(void) const5700 void TexelBufferRenderInstance::logTestPlan (void) const
5701 {
5702 	std::ostringstream msg;
5703 
5704 	msg << "Rendering 2x2 grid.\n"
5705 		<< "Single descriptor set. Descriptor set contains "
5706 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5707 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
5708 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5709 			    (const char*)DE_NULL)
5710 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5711 		<< "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
5712 		<< "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
5713 
5714 	if (m_stageFlags == 0u)
5715 	{
5716 		msg << "Descriptors are not accessed in any shader stage.\n";
5717 	}
5718 	else
5719 	{
5720 		msg << "Color in each cell is fetched using the descriptor(s):\n";
5721 
5722 		for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5723 		{
5724 			msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
5725 
5726 			if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5727 			{
5728 				const int srcResourceNdx = (resultNdx % 2); // ABAB source
5729 				msg << " from texelBuffer " << srcResourceNdx;
5730 			}
5731 
5732 			msg << "\n";
5733 		}
5734 
5735 		msg << "Descriptors are accessed in {"
5736 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)					? (" vertex")			: (""))
5737 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0)	? (" tess_control")		: (""))
5738 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)	? (" tess_evaluation")	: (""))
5739 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)				? (" geometry")			: (""))
5740 			<< (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)				? (" fragment")			: (""))
5741 			<< " } stages.";
5742 	}
5743 
5744 	m_context.getTestContext().getLog()
5745 		<< tcu::TestLog::Message
5746 		<< msg.str()
5747 		<< tcu::TestLog::EndMessage;
5748 }
5749 
getPipelineLayout(void) const5750 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout (void) const
5751 {
5752 	return *m_pipelineLayout;
5753 }
5754 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const5755 void TexelBufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const
5756 {
5757 	m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
5758 	m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
5759 }
5760 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const5761 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
5762 {
5763 	const tcu::Vec4		green		(0.0f, 1.0f, 0.0f, 1.0f);
5764 	const tcu::Vec4		yellow		(1.0f, 1.0f, 0.0f, 1.0f);
5765 	const bool			doFetch		= (m_stageFlags != 0u); // no active stages? Then don't fetch
5766 	const tcu::Vec4		sample0		= (!doFetch) ? (yellow)	: (m_texelBuffers.fetchTexelValue(0));
5767 	const tcu::Vec4		sample1		= (!doFetch) ? (green)	: (m_texelBuffers.fetchTexelValue(1));
5768 	const tcu::Vec4		sample2		= (!doFetch) ? (green)	: (m_texelBuffers.fetchTexelValue(2));
5769 	const tcu::Vec4		sample3		= (!doFetch) ? (yellow)	: (m_texelBuffers.fetchTexelValue(3));
5770 	tcu::Surface		reference	(m_targetSize.x(), m_targetSize.y());
5771 
5772 	drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
5773 
5774 	if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
5775 		return tcu::TestStatus::fail("Image verification failed");
5776 	else
5777 		return tcu::TestStatus::pass("Pass");
5778 }
5779 
5780 class TexelBufferComputeInstance : public vkt::TestInstance
5781 {
5782 public:
5783 											TexelBufferComputeInstance	(vkt::Context&			context,
5784 																		 vk::VkDescriptorType	descriptorType,
5785 																		 ShaderInputInterface	shaderInterface,
5786 																		 bool					nonzeroViewOffset);
5787 
5788 private:
5789 	vk::Move<vk::VkDescriptorSetLayout>		createDescriptorSetLayout	(void) const;
5790 	vk::Move<vk::VkDescriptorPool>			createDescriptorPool		(void) const;
5791 	vk::Move<vk::VkDescriptorSet>			createDescriptorSet			(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
5792 
5793 	tcu::TestStatus							iterate						(void);
5794 	void									logTestPlan					(void) const;
5795 	tcu::TestStatus							testResourceAccess			(void);
5796 
5797 	const vk::VkDescriptorType				m_descriptorType;
5798 	const ShaderInputInterface				m_shaderInterface;
5799 	const bool								m_nonzeroViewOffset;
5800 
5801 	const vk::DeviceInterface&				m_vki;
5802 	const vk::VkDevice						m_device;
5803 	const vk::VkQueue						m_queue;
5804 	const deUint32							m_queueFamilyIndex;
5805 	vk::Allocator&							m_allocator;
5806 
5807 	const ComputeInstanceResultBuffer		m_result;
5808 	const TexelBufferInstanceBuffers		m_texelBuffers;
5809 };
5810 
TexelBufferComputeInstance(Context & context,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,bool nonzeroViewOffset)5811 TexelBufferComputeInstance::TexelBufferComputeInstance (Context&				context,
5812 														vk::VkDescriptorType	descriptorType,
5813 														ShaderInputInterface	shaderInterface,
5814 														bool					nonzeroViewOffset)
5815 	: vkt::TestInstance		(context)
5816 	, m_descriptorType		(descriptorType)
5817 	, m_shaderInterface		(shaderInterface)
5818 	, m_nonzeroViewOffset	(nonzeroViewOffset)
5819 	, m_vki					(context.getDeviceInterface())
5820 	, m_device				(context.getDevice())
5821 	, m_queue				(context.getUniversalQueue())
5822 	, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
5823 	, m_allocator			(context.getDefaultAllocator())
5824 	, m_result				(m_vki, m_device, m_allocator)
5825 	, m_texelBuffers		(m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
5826 {
5827 }
5828 
createDescriptorSetLayout(void) const5829 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout (void) const
5830 {
5831 	vk::DescriptorSetLayoutBuilder builder;
5832 
5833 	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5834 
5835 	switch (m_shaderInterface)
5836 	{
5837 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
5838 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5839 			break;
5840 
5841 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5842 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5843 			builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5844 			break;
5845 
5846 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
5847 			builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5848 			break;
5849 
5850 		default:
5851 			DE_FATAL("Impossible");
5852 	};
5853 
5854 	return builder.build(m_vki, m_device);
5855 }
5856 
createDescriptorPool(void) const5857 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool (void) const
5858 {
5859 	return vk::DescriptorPoolBuilder()
5860 		.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
5861 		.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
5862 		.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
5863 }
5864 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout) const5865 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
5866 {
5867 	const vk::VkDescriptorBufferInfo		resultInfo			= vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
5868 	const vk::VkBufferView					texelBufferInfos[2]	=
5869 	{
5870 		m_texelBuffers.getBufferViewA(),
5871 		m_texelBuffers.getBufferViewB(),
5872 	};
5873 	const vk::VkDescriptorSetAllocateInfo	allocInfo			=
5874 	{
5875 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
5876 		DE_NULL,
5877 		pool,
5878 		1u,
5879 		&layout
5880 	};
5881 
5882 	vk::Move<vk::VkDescriptorSet>			descriptorSet		= allocateDescriptorSet(m_vki, m_device, &allocInfo);
5883 	vk::DescriptorSetUpdateBuilder			builder;
5884 
5885 	// result
5886 	builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
5887 
5888 	// texel buffers
5889 	switch (m_shaderInterface)
5890 	{
5891 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
5892 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
5893 			break;
5894 
5895 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5896 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
5897 			builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &texelBufferInfos[1]);
5898 			break;
5899 
5900 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
5901 			builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, texelBufferInfos);
5902 			break;
5903 
5904 		default:
5905 			DE_FATAL("Impossible");
5906 	}
5907 
5908 	builder.update(m_vki, m_device);
5909 	return descriptorSet;
5910 }
5911 
iterate(void)5912 tcu::TestStatus TexelBufferComputeInstance::iterate (void)
5913 {
5914 	logTestPlan();
5915 	return testResourceAccess();
5916 }
5917 
logTestPlan(void) const5918 void TexelBufferComputeInstance::logTestPlan (void) const
5919 {
5920 	std::ostringstream msg;
5921 
5922 	msg << "Fetching 4 values from image in compute shader.\n"
5923 		<< "Single descriptor set. Descriptor set contains "
5924 			<< ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5925 			    (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" :
5926 			    (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5927 			    (const char*)DE_NULL)
5928 		<< " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5929 		<< "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
5930 		<< "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
5931 
5932 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5933 	{
5934 		msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
5935 
5936 		if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5937 		{
5938 			const int srcResourceNdx = (resultNdx % 2); // ABAB source
5939 			msg << " from texelBuffer " << srcResourceNdx;
5940 		}
5941 
5942 		msg << "\n";
5943 	}
5944 
5945 	m_context.getTestContext().getLog()
5946 		<< tcu::TestLog::Message
5947 		<< msg.str()
5948 		<< tcu::TestLog::EndMessage;
5949 }
5950 
testResourceAccess(void)5951 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess (void)
5952 {
5953 	const vk::Unique<vk::VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout());
5954 	const vk::Unique<vk::VkDescriptorPool>			descriptorPool		(createDescriptorPool());
5955 	const vk::Unique<vk::VkDescriptorSet>			descriptorSet		(createDescriptorSet(*descriptorPool, *descriptorSetLayout));
5956 	const ComputePipeline							pipeline			(m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
5957 
5958 	const vk::VkDescriptorSet						descriptorSets[]	= { *descriptorSet };
5959 	const int										numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);
5960 	const deUint32* const							dynamicOffsets		= DE_NULL;
5961 	const int										numDynamicOffsets	= 0;
5962 	const vk::VkBufferMemoryBarrier* const			preBarriers			= m_texelBuffers.getBufferInitBarriers();
5963 	const int										numPreBarriers		= m_texelBuffers.getNumTexelBuffers();
5964 	const vk::VkBufferMemoryBarrier* const			postBarriers		= m_result.getResultReadBarrier();
5965 	const int										numPostBarriers		= 1;
5966 
5967 	const ComputeCommand							compute				(m_vki,
5968 																		 m_device,
5969 																		 pipeline.getPipeline(),
5970 																		 pipeline.getPipelineLayout(),
5971 																		 tcu::UVec3(4, 1, 1),
5972 																		 numDescriptorSets,	descriptorSets,
5973 																		 numDynamicOffsets,	dynamicOffsets,
5974 																		 numPreBarriers,	preBarriers,
5975 																		 numPostBarriers,	postBarriers);
5976 
5977 	tcu::Vec4										results[4];
5978 	bool											anyResultSet		= false;
5979 	bool											allResultsOk		= true;
5980 
5981 	compute.submitAndWait(m_queueFamilyIndex, m_queue);
5982 	m_result.readResultContentsTo(&results);
5983 
5984 	// verify
5985 	for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5986 	{
5987 		const tcu::Vec4	result				= results[resultNdx];
5988 		const tcu::Vec4	reference			= m_texelBuffers.fetchTexelValue(resultNdx);
5989 		const tcu::Vec4	conversionThreshold	= tcu::Vec4(1.0f / 255.0f);
5990 
5991 		if (result != tcu::Vec4(-1.0f))
5992 			anyResultSet = true;
5993 
5994 		if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5995 		{
5996 			allResultsOk = false;
5997 
5998 			m_context.getTestContext().getLog()
5999 				<< tcu::TestLog::Message
6000 				<< "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
6001 				<< tcu::TestLog::EndMessage;
6002 		}
6003 	}
6004 
6005 	// read back and verify
6006 	if (allResultsOk)
6007 		return tcu::TestStatus::pass("Pass");
6008 	else if (anyResultSet)
6009 		return tcu::TestStatus::fail("Invalid result values");
6010 	else
6011 	{
6012 		m_context.getTestContext().getLog()
6013 			<< tcu::TestLog::Message
6014 			<< "Result buffer was not written to."
6015 			<< tcu::TestLog::EndMessage;
6016 		return tcu::TestStatus::fail("Result buffer was not written to");
6017 	}
6018 }
6019 
6020 class TexelBufferDescriptorCase : public QuadrantRendederCase
6021 {
6022 public:
6023 	enum
6024 	{
6025 		FLAG_VIEW_OFFSET = (1u << 1u),
6026 	};
6027 	// enum continues where resource flags ends
6028 	DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
6029 
6030 								TexelBufferDescriptorCase	(tcu::TestContext&		testCtx,
6031 															 const char*			name,
6032 															 const char*			description,
6033 															 bool					isPrimaryCmdBuf,
6034 															 vk::VkDescriptorType	descriptorType,
6035 															 vk::VkShaderStageFlags	exitingStages,
6036 															 vk::VkShaderStageFlags	activeStages,
6037 															 ShaderInputInterface	shaderInterface,
6038 															 deUint32				flags);
6039 
6040 private:
6041 	std::string					genExtensionDeclarations	(vk::VkShaderStageFlagBits stage) const;
6042 	std::string					genResourceDeclarations		(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
6043 	std::string					genResourceAccessSource		(vk::VkShaderStageFlagBits stage) const;
6044 	std::string					genNoAccessSource			(void) const;
6045 
6046 	vkt::TestInstance*			createInstance				(vkt::Context& context) const;
6047 
6048 	const bool					m_isPrimaryCmdBuf;
6049 	const vk::VkDescriptorType	m_descriptorType;
6050 	const ShaderInputInterface	m_shaderInterface;
6051 	const bool					m_nonzeroViewOffset;
6052 };
6053 
TexelBufferDescriptorCase(tcu::TestContext & testCtx,const char * name,const char * description,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface shaderInterface,deUint32 flags)6054 TexelBufferDescriptorCase::TexelBufferDescriptorCase (tcu::TestContext&			testCtx,
6055 													  const char*				name,
6056 													  const char*				description,
6057 													  bool						isPrimaryCmdBuf,
6058 													  vk::VkDescriptorType		descriptorType,
6059 													  vk::VkShaderStageFlags	exitingStages,
6060 													  vk::VkShaderStageFlags	activeStages,
6061 													  ShaderInputInterface		shaderInterface,
6062 													  deUint32					flags)
6063 	: QuadrantRendederCase	(testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
6064 	, m_isPrimaryCmdBuf		(isPrimaryCmdBuf)
6065 	, m_descriptorType		(descriptorType)
6066 	, m_shaderInterface		(shaderInterface)
6067 	, m_nonzeroViewOffset	(((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
6068 {
6069 }
6070 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const6071 std::string TexelBufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const
6072 {
6073 	DE_UNREF(stage);
6074 	return "#extension GL_EXT_texture_buffer : require\n";
6075 }
6076 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const6077 std::string TexelBufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const
6078 {
6079 	DE_UNREF(stage);
6080 
6081 	const bool			isUniform		= isUniformDescriptorType(m_descriptorType);
6082 	const char* const	storageType		= (isUniform) ? ("samplerBuffer ") : ("readonly imageBuffer ");
6083 	const char* const	formatQualifier	= (isUniform) ? ("") : (", rgba8");
6084 
6085 	switch (m_shaderInterface)
6086 	{
6087 		case SHADER_INPUT_SINGLE_DESCRIPTOR:
6088 			return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer;\n";
6089 
6090 		case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6091 			return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferA;\n"
6092 				   "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferB;\n";
6093 
6094 		case SHADER_INPUT_DESCRIPTOR_ARRAY:
6095 			return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer[2];\n";
6096 
6097 		default:
6098 			DE_FATAL("Impossible");
6099 			return "";
6100 	}
6101 }
6102 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const6103 std::string TexelBufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const
6104 {
6105 	DE_UNREF(stage);
6106 
6107 	const char* const	accessPostfixA	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
6108 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("A")
6109 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[0]")
6110 										: (DE_NULL);
6111 	const char* const	accessPostfixB	= (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)						? ("")
6112 										: (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)		? ("B")
6113 										: (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)						? ("[1]")
6114 										: (DE_NULL);
6115 	const char* const	fetchFunc		= (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
6116 	std::ostringstream	buf;
6117 
6118 	buf << "	if (quadrant_id == 0)\n"
6119 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
6120 		<< "	else if (quadrant_id == 1)\n"
6121 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
6122 		<< "	else if (quadrant_id == 2)\n"
6123 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
6124 		<< "	else\n"
6125 		<< "		result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
6126 
6127 	return buf.str();
6128 }
6129 
genNoAccessSource(void) const6130 std::string TexelBufferDescriptorCase::genNoAccessSource (void) const
6131 {
6132 	return "	if (quadrant_id == 1 || quadrant_id == 2)\n"
6133 			"		result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
6134 			"	else\n"
6135 			"		result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
6136 }
6137 
createInstance(vkt::Context & context) const6138 vkt::TestInstance* TexelBufferDescriptorCase::createInstance (vkt::Context& context) const
6139 {
6140 	verifyDriverSupport(context.getDeviceFeatures(), m_descriptorType, m_activeStages);
6141 
6142 	if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
6143 	{
6144 		DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
6145 		return new TexelBufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_nonzeroViewOffset);
6146 	}
6147 	else
6148 		return new TexelBufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_nonzeroViewOffset);
6149 }
6150 
createShaderAccessImageTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface dimension,deUint32 resourceFlags)6151 void createShaderAccessImageTests (tcu::TestCaseGroup*		group,
6152 								   bool						isPrimaryCmdBuf,
6153 								   vk::VkDescriptorType		descriptorType,
6154 								   vk::VkShaderStageFlags	exitingStages,
6155 								   vk::VkShaderStageFlags	activeStages,
6156 								   ShaderInputInterface		dimension,
6157 								   deUint32					resourceFlags)
6158 {
6159 	static const struct
6160 	{
6161 		vk::VkImageViewType	viewType;
6162 		const char*			name;
6163 		const char*			description;
6164 		deUint32			flags;
6165 	} s_imageTypes[] =
6166 	{
6167 		{ vk::VK_IMAGE_VIEW_TYPE_1D,			"1d",						"1D image view",								0u										},
6168 		{ vk::VK_IMAGE_VIEW_TYPE_1D,			"1d_base_mip",				"1D image subview with base mip level",			ImageDescriptorCase::FLAG_BASE_MIP		},
6169 		{ vk::VK_IMAGE_VIEW_TYPE_1D,			"1d_base_slice",			"1D image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
6170 
6171 		{ vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array",					"1D array image view",							0u										},
6172 		{ vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array_base_mip",		"1D array image subview with base mip level",	ImageDescriptorCase::FLAG_BASE_MIP		},
6173 		{ vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array_base_slice",		"1D array image subview with base array slice",	ImageDescriptorCase::FLAG_BASE_SLICE	},
6174 
6175 		{ vk::VK_IMAGE_VIEW_TYPE_2D,			"2d",						"2D image view",								0u										},
6176 		{ vk::VK_IMAGE_VIEW_TYPE_2D,			"2d_base_mip",				"2D image subview with base mip level",			ImageDescriptorCase::FLAG_BASE_MIP		},
6177 		{ vk::VK_IMAGE_VIEW_TYPE_2D,			"2d_base_slice",			"2D image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
6178 
6179 		{ vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array",					"2D array image view",							0u										},
6180 		{ vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array_base_mip",		"2D array image subview with base mip level",	ImageDescriptorCase::FLAG_BASE_MIP		},
6181 		{ vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array_base_slice",		"2D array image subview with base array slice",	ImageDescriptorCase::FLAG_BASE_SLICE	},
6182 
6183 		{ vk::VK_IMAGE_VIEW_TYPE_3D,			"3d",						"3D image view",								0u										},
6184 		{ vk::VK_IMAGE_VIEW_TYPE_3D,			"3d_base_mip",				"3D image subview with base mip level",			ImageDescriptorCase::FLAG_BASE_MIP		},
6185 		// no 3d array textures
6186 
6187 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE,			"cube",						"Cube image view",								0u										},
6188 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE,			"cube_base_mip",			"Cube image subview with base mip level",		ImageDescriptorCase::FLAG_BASE_MIP		},
6189 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE,			"cube_base_slice",			"Cube image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
6190 
6191 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array",				"Cube image view",								0u										},
6192 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array_base_mip",		"Cube image subview with base mip level",		ImageDescriptorCase::FLAG_BASE_MIP		},
6193 		{ vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array_base_slice",	"Cube image subview with base array slice",		ImageDescriptorCase::FLAG_BASE_SLICE	},
6194 	};
6195 
6196 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
6197 	{
6198 		// never overlap
6199 		DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
6200 
6201 		// SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS only supported in VK_DESCRIPTOR_TYPE_SAMPLER on graphics shaders for now
6202 		if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS &&
6203 			(descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER || activeStages == vk::VK_SHADER_STAGE_COMPUTE_BIT))
6204 			continue;
6205 
6206 		group->addChild(new ImageDescriptorCase(group->getTestContext(),
6207 												s_imageTypes[ndx].name,
6208 												s_imageTypes[ndx].description,
6209 												isPrimaryCmdBuf,
6210 												descriptorType,
6211 												exitingStages,
6212 												activeStages,
6213 												dimension,
6214 												s_imageTypes[ndx].viewType,
6215 												s_imageTypes[ndx].flags | resourceFlags));
6216 	}
6217 }
6218 
createShaderAccessTexelBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface dimension,deUint32 resourceFlags)6219 void createShaderAccessTexelBufferTests (tcu::TestCaseGroup*	group,
6220 										 bool					isPrimaryCmdBuf,
6221 										 vk::VkDescriptorType	descriptorType,
6222 										 vk::VkShaderStageFlags	exitingStages,
6223 										 vk::VkShaderStageFlags	activeStages,
6224 										 ShaderInputInterface	dimension,
6225 										 deUint32				resourceFlags)
6226 {
6227 	DE_ASSERT(resourceFlags == 0);
6228 	DE_UNREF(resourceFlags);
6229 
6230 	static const struct
6231 	{
6232 		const char*	name;
6233 		const char*	description;
6234 		deUint32	flags;
6235 	} s_texelBufferTypes[] =
6236 	{
6237 		{ "offset_zero",		"View offset is zero",		0u											},
6238 		{ "offset_nonzero",		"View offset is non-zero",	TexelBufferDescriptorCase::FLAG_VIEW_OFFSET	},
6239 	};
6240 
6241 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
6242 	{
6243 		if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
6244 			continue;
6245 
6246 		group->addChild(new TexelBufferDescriptorCase(group->getTestContext(),
6247 													  s_texelBufferTypes[ndx].name,
6248 													  s_texelBufferTypes[ndx].description,
6249 													  isPrimaryCmdBuf,
6250 													  descriptorType,
6251 													  exitingStages,
6252 													  activeStages,
6253 													  dimension,
6254 													  s_texelBufferTypes[ndx].flags));
6255 	}
6256 }
6257 
createShaderAccessBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,ShaderInputInterface dimension,deUint32 resourceFlags)6258 void createShaderAccessBufferTests (tcu::TestCaseGroup*		group,
6259 									bool					isPrimaryCmdBuf,
6260 									vk::VkDescriptorType	descriptorType,
6261 									vk::VkShaderStageFlags	exitingStages,
6262 									vk::VkShaderStageFlags	activeStages,
6263 									ShaderInputInterface	dimension,
6264 									deUint32				resourceFlags)
6265 {
6266 	DE_ASSERT(resourceFlags == 0u);
6267 	DE_UNREF(resourceFlags);
6268 
6269 	static const struct
6270 	{
6271 		const char*	name;
6272 		const char*	description;
6273 		bool		isForDynamicCases;
6274 		deUint32	flags;
6275 	} s_bufferTypes[] =
6276 	{
6277 		{ "offset_view_zero",						"View offset is zero",									false,	0u																							},
6278 		{ "offset_view_nonzero",					"View offset is non-zero",								false,	BufferDescriptorCase::FLAG_VIEW_OFFSET														},
6279 
6280 		{ "offset_view_zero_dynamic_zero",			"View offset is zero, dynamic offset is zero",			true,	BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO												},
6281 		{ "offset_view_zero_dynamic_nonzero",		"View offset is zero, dynamic offset is non-zero",		true,	BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO											},
6282 		{ "offset_view_nonzero_dynamic_zero",		"View offset is non-zero, dynamic offset is zero",		true,	BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO		},
6283 		{ "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	},
6284 	};
6285 
6286 	const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
6287 
6288 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
6289 	{
6290 		if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS)
6291 			continue;
6292 
6293 		if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
6294 			group->addChild(new BufferDescriptorCase(group->getTestContext(),
6295 													 s_bufferTypes[ndx].name,
6296 													 s_bufferTypes[ndx].description,
6297 													 isPrimaryCmdBuf,
6298 													 descriptorType,
6299 													 exitingStages,
6300 													 activeStages,
6301 													 dimension,
6302 													 s_bufferTypes[ndx].flags));
6303 	}
6304 }
6305 
6306 } // anonymous
6307 
createShaderAccessTests(tcu::TestContext & testCtx)6308 tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx)
6309 {
6310 	static const struct
6311 	{
6312 		const bool	isPrimary;
6313 		const char*	name;
6314 		const char*	description;
6315 	} s_bindTypes[] =
6316 	{
6317 		{ true,		"primary_cmd_buf",	"Bind in primary command buffer"	},
6318 		{ false,	"secondary_cmd_buf",	"Bind in secondary command buffer"	},
6319 	};
6320 	static const struct
6321 	{
6322 		const vk::VkDescriptorType	descriptorType;
6323 		const char*					name;
6324 		const char*					description;
6325 		deUint32					flags;
6326 	} s_descriptorTypes[] =
6327 	{
6328 		{ vk::VK_DESCRIPTOR_TYPE_SAMPLER,					"sampler_mutable",					"VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler",					0u								},
6329 		{ vk::VK_DESCRIPTOR_TYPE_SAMPLER,					"sampler_immutable",				"VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",				RESOURCE_FLAG_IMMUTABLE_SAMPLER	},
6330 		{ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	"combined_image_sampler_mutable",	"VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler",	0u								},
6331 		{ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	"combined_image_sampler_immutable",	"VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler",	RESOURCE_FLAG_IMMUTABLE_SAMPLER	},
6332 		// \note No way to access SAMPLED_IMAGE without a sampler
6333 		//{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				"sampled_image",					"VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE",									0u								},
6334 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,				"storage_image",					"VK_DESCRIPTOR_TYPE_STORAGE_IMAGE",									0u								},
6335 		{ vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		"uniform_texel_buffer",				"VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",							0u								},
6336 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,		"storage_texel_buffer",				"VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",							0u								},
6337 		{ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,			"uniform_buffer",					"VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER",								0u								},
6338 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,			"storage_buffer",					"VK_DESCRIPTOR_TYPE_STORAGE_BUFFER",								0u								},
6339 		{ vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,	"uniform_buffer_dynamic",			"VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC",						0u								},
6340 		{ vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,	"storage_buffer_dynamic",			"VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC",						0u								},
6341 	};
6342 	static const struct
6343 	{
6344 		const char*				name;
6345 		const char*				description;
6346 		vk::VkShaderStageFlags	existingStages;				//!< stages that exists
6347 		vk::VkShaderStageFlags	activeStages;				//!< stages that access resource
6348 		bool					supportsSecondaryCmdBufs;
6349 	} s_shaderStages[] =
6350 	{
6351 		{
6352 			"no_access",
6353 			"No accessing stages",
6354 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6355 			0u,
6356 			true,
6357 		},
6358 		{
6359 			"vertex",
6360 			"Vertex stage",
6361 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6362 			vk::VK_SHADER_STAGE_VERTEX_BIT,
6363 			true,
6364 		},
6365 		{
6366 			"tess_ctrl",
6367 			"Tessellation control stage",
6368 			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,
6369 			vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
6370 			true,
6371 		},
6372 		{
6373 			"tess_eval",
6374 			"Tessellation evaluation stage",
6375 			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,
6376 			vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
6377 			true,
6378 		},
6379 		{
6380 			"geometry",
6381 			"Geometry stage",
6382 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6383 			vk::VK_SHADER_STAGE_GEOMETRY_BIT,
6384 			true,
6385 		},
6386 		{
6387 			"fragment",
6388 			"Fragment stage",
6389 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6390 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6391 			true,
6392 		},
6393 		{
6394 			"compute",
6395 			"Compute stage",
6396 			vk::VK_SHADER_STAGE_COMPUTE_BIT,
6397 			vk::VK_SHADER_STAGE_COMPUTE_BIT,
6398 			false,
6399 		},
6400 		{
6401 			"vertex_fragment",
6402 			"Vertex and fragment stages",
6403 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6404 			vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6405 			true,
6406 		},
6407 	};
6408 	static const struct
6409 	{
6410 		ShaderInputInterface	dimension;
6411 		const char*				name;
6412 		const char*				description;
6413 	} s_variableDimensions[] =
6414 	{
6415 		{ SHADER_INPUT_SINGLE_DESCRIPTOR,					"single_descriptor",					"Single descriptor"		},
6416 		{ SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS,		"multiple_contiguous_descriptors",		"Multiple descriptors"	},
6417 		{ SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS,	"multiple_discontiguous_descriptors",	"Multiple descriptors"	},
6418 		{ SHADER_INPUT_DESCRIPTOR_ARRAY,					"descriptor_array",						"Descriptor array"		},
6419 	};
6420 
6421 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access", "Access resource via descriptor in a single descriptor set"));
6422 
6423 	// .primary_cmd_buf...
6424 	for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
6425 	{
6426 		de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name, s_bindTypes[bindTypeNdx].description));
6427 
6428 		// .sampler, .combined_image_sampler, other resource types ...
6429 		for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
6430 		{
6431 			de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
6432 
6433 			for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
6434 			{
6435 				if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
6436 				{
6437 					de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name, s_shaderStages[stageNdx].description));
6438 
6439 					for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions); ++dimensionNdx)
6440 					{
6441 						de::MovePtr<tcu::TestCaseGroup>	dimensionGroup(new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name, s_variableDimensions[dimensionNdx].description));
6442 						void							(*createTestsFunc)(tcu::TestCaseGroup*		group,
6443 																		   bool						isPrimaryCmdBuf,
6444 																		   vk::VkDescriptorType		descriptorType,
6445 																		   vk::VkShaderStageFlags	existingStages,
6446 																		   vk::VkShaderStageFlags	activeStages,
6447 																		   ShaderInputInterface		dimension,
6448 																		   deUint32					resourceFlags);
6449 
6450 						switch (s_descriptorTypes[descriptorNdx].descriptorType)
6451 						{
6452 							case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
6453 							case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
6454 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
6455 								createTestsFunc = createShaderAccessImageTests;
6456 								break;
6457 
6458 							case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
6459 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
6460 								createTestsFunc = createShaderAccessTexelBufferTests;
6461 								break;
6462 
6463 							case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
6464 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
6465 							case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
6466 							case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
6467 								createTestsFunc = createShaderAccessBufferTests;
6468 								break;
6469 
6470 							default:
6471 								createTestsFunc = DE_NULL;
6472 								DE_FATAL("Impossible");
6473 						}
6474 
6475 						if (createTestsFunc)
6476 						{
6477 							createTestsFunc(dimensionGroup.get(),
6478 											s_bindTypes[bindTypeNdx].isPrimary,
6479 											s_descriptorTypes[descriptorNdx].descriptorType,
6480 											s_shaderStages[stageNdx].existingStages,
6481 											s_shaderStages[stageNdx].activeStages,
6482 											s_variableDimensions[dimensionNdx].dimension,
6483 											s_descriptorTypes[descriptorNdx].flags);
6484 						}
6485 						else
6486 							DE_FATAL("Impossible");
6487 
6488 						stageGroup->addChild(dimensionGroup.release());
6489 					}
6490 
6491 					typeGroup->addChild(stageGroup.release());
6492 				}
6493 			}
6494 
6495 			bindGroup->addChild(typeGroup.release());
6496 		}
6497 
6498 		group->addChild(bindGroup.release());
6499 	}
6500 
6501 	return group.release();
6502 }
6503 
6504 } // BindingModel
6505 } // vkt
6506