1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 Valve Corporation.
6  * Copyright (c) 2023 LunarG, Inc.
7  * Copyright (c) 2023 Nintendo
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief VK_EXT_attachment_feedback_loop_layout Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineAttachmentFeedbackLoopLayoutTests.hpp"
27 #include "vktPipelineImageSamplingInstance.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktPipelineClearUtil.hpp"
32 
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBufferWithMemory.hpp"
43 
44 #include "tcuPlatform.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuMaybe.hpp"
49 
50 #include "deStringUtil.hpp"
51 #include "deMemory.h"
52 
53 #include <iomanip>
54 #include <sstream>
55 #include <vector>
56 #include <string>
57 #include <memory>
58 #include <utility>
59 #include <algorithm>
60 
61 namespace vkt
62 {
63 namespace pipeline
64 {
65 
66 using namespace vk;
67 using de::MovePtr;
68 
69 namespace
70 {
71 
72 enum TestMode
73 {
74 	TEST_MODE_READ_ONLY = 0,
75 	TEST_MODE_WRITE_ONLY = 1,
76 	TEST_MODE_READ_WRITE_SAME_PIXEL = 2,		// Sample from and write to the same pixel
77 	TEST_MODE_READ_WRITE_DIFFERENT_AREAS = 3,	// Sample from one half of the image and write the values to the other half
78 };
79 
80 enum ImageAspectTestMode
81 {
82 	IMAGE_ASPECT_TEST_COLOR = 0,
83 	IMAGE_ASPECT_TEST_DEPTH = 1,
84 	IMAGE_ASPECT_TEST_STENCIL = 2,
85 };
86 
testModeToAspectFlags(ImageAspectTestMode testMode)87 VkImageAspectFlagBits testModeToAspectFlags (ImageAspectTestMode testMode)
88 {
89 	switch (testMode)
90 	{
91 	case IMAGE_ASPECT_TEST_COLOR:		return VK_IMAGE_ASPECT_COLOR_BIT;
92 	case IMAGE_ASPECT_TEST_DEPTH:		return VK_IMAGE_ASPECT_DEPTH_BIT;
93 	case IMAGE_ASPECT_TEST_STENCIL:		return VK_IMAGE_ASPECT_STENCIL_BIT;
94 	default:							break;
95 	}
96 
97 	DE_ASSERT(false);
98 	return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
99 }
100 
101 enum class PipelineStateMode
102 {
103 	STATIC = 0,							// Static only.
104 	DYNAMIC_WITH_ZERO_STATIC,			// Dynamic, with static flags 0.
105 	DYNAMIC_WITH_CONTRADICTORY_STATIC,	// Dynamic, with static flags contradicting the dynamic state (see below).
106 };
107 
aspectFlagsToPipelineCreateFlags(VkImageAspectFlags aspectFlags)108 VkPipelineCreateFlags aspectFlagsToPipelineCreateFlags (VkImageAspectFlags aspectFlags)
109 {
110 	VkPipelineCreateFlags pipelineFlags = 0u;
111 
112 	if ((aspectFlags & VK_IMAGE_ASPECT_COLOR_BIT) != 0u)
113 		pipelineFlags |= VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
114 
115 	if ((aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0u)
116 		pipelineFlags |= VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
117 
118 	return pipelineFlags;
119 }
120 
getStaticPipelineCreateFlags(VkImageAspectFlags usedFlags, PipelineStateMode stateMode)121 VkPipelineCreateFlags getStaticPipelineCreateFlags (VkImageAspectFlags usedFlags, PipelineStateMode stateMode)
122 {
123 	if (stateMode == PipelineStateMode::STATIC)
124 		return aspectFlagsToPipelineCreateFlags(usedFlags);
125 
126 	if (stateMode == PipelineStateMode::DYNAMIC_WITH_ZERO_STATIC)
127 		return 0u;
128 
129 	// Statically include all flags which are not present in the used flags that will be set dynamically.
130 	VkPipelineCreateFlags pipelineStaticFlags	= (VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT | VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
131 	VkPipelineCreateFlags pipelineUsedFlags		= aspectFlagsToPipelineCreateFlags(usedFlags);
132 
133 	pipelineStaticFlags &= (~pipelineUsedFlags);
134 	return pipelineStaticFlags;
135 }
136 
137 // Output images are a square of this size
138 const int outputImageSize = 256;
139 
getImageAspectTestMode(const VkFormat format)140 ImageAspectTestMode getImageAspectTestMode (const VkFormat format)
141 {
142 	if (tcu::hasDepthComponent(mapVkFormat(format).order))
143 		return IMAGE_ASPECT_TEST_DEPTH;
144 
145 	if (tcu::hasStencilComponent(mapVkFormat(format).order))
146 		return IMAGE_ASPECT_TEST_STENCIL;
147 
148 	return IMAGE_ASPECT_TEST_COLOR;
149 };
150 
151 class SamplerViewType {
152 public:
SamplerViewType(vk::VkImageViewType type, bool normalized = true)153 	SamplerViewType (vk::VkImageViewType type, bool normalized = true)
154 		: m_viewType(type), m_normalized(normalized)
155 	{
156 		if (!normalized)
157 			DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
158 	}
159 
operator vk::VkImageViewType() const160 	operator vk::VkImageViewType () const
161 	{
162 		return m_viewType;
163 	}
164 
isNormalized() const165 	bool isNormalized () const
166 	{
167 		return m_normalized;
168 	}
169 
170 private:
171 	vk::VkImageViewType m_viewType;
172 	bool				m_normalized;
173 };
174 
allocateImage(const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkImage& image, const MemoryRequirement requirement, Allocator& allocator, AllocationKind allocationKind)175 de::MovePtr<Allocation> allocateImage (const InstanceInterface&		vki,
176 									   const DeviceInterface&		vkd,
177 									   const VkPhysicalDevice&		physDevice,
178 									   const VkDevice				device,
179 									   const VkImage&				image,
180 									   const MemoryRequirement		requirement,
181 									   Allocator&					allocator,
182 									   AllocationKind				allocationKind)
183 {
184 	switch (allocationKind)
185 	{
186 		case ALLOCATION_KIND_SUBALLOCATED:
187 		{
188 			const VkMemoryRequirements	memoryRequirements	= getImageMemoryRequirements(vkd, device, image);
189 
190 			return allocator.allocate(memoryRequirements, requirement);
191 		}
192 
193 		case ALLOCATION_KIND_DEDICATED:
194 		{
195 			return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
196 		}
197 
198 		default:
199 		{
200 			TCU_THROW(InternalError, "Invalid allocation kind");
201 		}
202 	}
203 }
204 
allocateBuffer(const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkBuffer& buffer, const MemoryRequirement requirement, Allocator& allocator, AllocationKind allocationKind)205 de::MovePtr<Allocation> allocateBuffer (const InstanceInterface&	vki,
206 										const DeviceInterface&		vkd,
207 										const VkPhysicalDevice&		physDevice,
208 										const VkDevice				device,
209 										const VkBuffer&				buffer,
210 										const MemoryRequirement		requirement,
211 										Allocator&					allocator,
212 										AllocationKind				allocationKind)
213 {
214 	switch (allocationKind)
215 	{
216 		case ALLOCATION_KIND_SUBALLOCATED:
217 		{
218 			const VkMemoryRequirements	memoryRequirements	= getBufferMemoryRequirements(vkd, device, buffer);
219 
220 			return allocator.allocate(memoryRequirements, requirement);
221 		}
222 
223 		case ALLOCATION_KIND_DEDICATED:
224 		{
225 			return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
226 		}
227 
228 		default:
229 		{
230 			TCU_THROW(InternalError, "Invalid allocation kind");
231 		}
232 	}
233 }
234 
getCompatibleImageType(VkImageViewType viewType)235 static VkImageType getCompatibleImageType (VkImageViewType viewType)
236 {
237 	switch (viewType)
238 	{
239 		case VK_IMAGE_VIEW_TYPE_1D:				return VK_IMAGE_TYPE_1D;
240 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:		return VK_IMAGE_TYPE_1D;
241 		case VK_IMAGE_VIEW_TYPE_2D:				return VK_IMAGE_TYPE_2D;
242 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:		return VK_IMAGE_TYPE_2D;
243 		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
244 		case VK_IMAGE_VIEW_TYPE_CUBE:			return VK_IMAGE_TYPE_2D;
245 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:		return VK_IMAGE_TYPE_2D;
246 		default:
247 			break;
248 	}
249 
250 	DE_ASSERT(false);
251 	return VK_IMAGE_TYPE_1D;
252 }
253 
254 template<typename TcuFormatType>
createTestTexture(const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)255 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
256 {
257 	MovePtr<TestTexture>	texture;
258 	const VkImageType		imageType = getCompatibleImageType(viewType);
259 
260 	switch (imageType)
261 	{
262 		case VK_IMAGE_TYPE_1D:
263 			if (layerCount == 1)
264 				texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
265 			else
266 				texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
267 
268 			break;
269 
270 		case VK_IMAGE_TYPE_2D:
271 			if (layerCount == 1)
272 			{
273 				texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
274 			}
275 			else
276 			{
277 				if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
278 				{
279 					if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
280 					{
281 						texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
282 					}
283 					else
284 					{
285 						DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
286 
287 						texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
288 					}
289 				}
290 				else
291 				{
292 					texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
293 				}
294 			}
295 
296 			break;
297 
298 		case VK_IMAGE_TYPE_3D:
299 			texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
300 			break;
301 
302 		default:
303 			DE_ASSERT(false);
304 	}
305 
306 	return texture;
307 }
308 
getAspectFlags(tcu::TextureFormat format)309 VkImageAspectFlags getAspectFlags (tcu::TextureFormat format)
310 {
311 	VkImageAspectFlags	aspectFlag	= 0;
312 	aspectFlag |= (tcu::hasDepthComponent(format.order)? VK_IMAGE_ASPECT_DEPTH_BIT : 0);
313 	aspectFlag |= (tcu::hasStencilComponent(format.order)? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
314 
315 	if (!aspectFlag)
316 		aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT;
317 
318 	return aspectFlag;
319 }
320 
getAspectFlags(VkFormat format)321 VkImageAspectFlags getAspectFlags (VkFormat format)
322 {
323 	if (isCompressedFormat(format))
324 		return VK_IMAGE_ASPECT_COLOR_BIT;
325 	else
326 		return getAspectFlags(mapVkFormat(format));
327 }
328 
getSizeCompatibleTcuTextureFormat(VkFormat format)329 tcu::TextureFormat getSizeCompatibleTcuTextureFormat (VkFormat format)
330 {
331 	if (isCompressedFormat(format))
332 		return (getBlockSizeInBytes(format) == 8) ? mapVkFormat(VK_FORMAT_R16G16B16A16_UINT) : mapVkFormat(VK_FORMAT_R32G32B32A32_UINT);
333 	else
334 		return mapVkFormat(format);
335 }
336 
337 // Utilities to create test nodes
getFormatCaseName(const VkFormat format)338 std::string getFormatCaseName (const VkFormat format)
339 {
340 	const std::string fullName = getFormatName(format);
341 
342 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
343 
344 	return de::toLower(fullName.substr(10));
345 }
346 
347 class AttachmentFeedbackLoopLayoutImageSamplingInstance : public ImageSamplingInstance
348 {
349 public:
350 								AttachmentFeedbackLoopLayoutImageSamplingInstance	(Context&						context,
351 																					 ImageSamplingInstanceParams	params,
352 																					 bool							useImageAsColorOrDSAttachment_,
353 																					 bool							useDifferentAreasSampleWrite_,
354 																					 bool							interleaveReadWriteComponents_,
355 																					 ImageAspectTestMode			imageAspectTestMode,
356 																					 PipelineStateMode				pipelineStateMode,
357 																					 bool							useMaintenance5_);
358 
359 	virtual						~AttachmentFeedbackLoopLayoutImageSamplingInstance	(void);
360 
361 	virtual tcu::TestStatus		iterate												(void) override;
362 
363 protected:
364 	virtual tcu::TestStatus		verifyImage											(void) override;
365 	virtual void				setup												(void) override;
366 
367 	ImageSamplingInstanceParams		m_params;
368 	const bool						m_useImageAsColorOrDSAttachment;
369 	const bool						m_useDifferentAreasSampleWrite;
370 	const bool						m_interleaveReadWriteComponents;
371 	const ImageAspectTestMode		m_imageAspectTestMode;
372 	const PipelineStateMode			m_pipelineStateMode;
373 	const bool						m_useMaintenance5;
374 };
375 
376 class AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance : public AttachmentFeedbackLoopLayoutImageSamplingInstance
377 {
378 public:
379 								AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance	(Context&						context,
380 																								 ImageSamplingInstanceParams	params,
381 																								 bool							useImageAsColorOrDSAttachment_,
382 																								 bool							useDifferentAreasSampleWrite_,
383 																								 bool							interleaveReadWriteComponents_,
384 																								 ImageAspectTestMode			imageAspectTestMode,
385 																								 PipelineStateMode				pipelineStateMode,
386 																								 bool							useMaintenance5_);
387 
388 	virtual						~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance	(void);
389 
390 	virtual tcu::TestStatus		iterate												(void) override;
391 
392 protected:
393 	virtual tcu::TestStatus		verifyImage											(void) override;
394 	virtual void				setup												(void) override;
395 
396 	bool										m_separateStencilUsage;
397 
398 	std::vector<SharedImagePtr>					m_dsImages;
399 	std::vector<SharedAllocPtr>					m_dsImageAllocs;
400 	std::vector<SharedImageViewPtr>				m_dsAttachmentViews;
401 };
402 
AttachmentFeedbackLoopLayoutImageSamplingInstance(Context& context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_, bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_, ImageAspectTestMode imageAspectTestMode, PipelineStateMode pipelineStateMode, bool useMaintenance5_)403 AttachmentFeedbackLoopLayoutImageSamplingInstance::AttachmentFeedbackLoopLayoutImageSamplingInstance (Context&						context,
404 																									  ImageSamplingInstanceParams	params,
405 																									  bool							useImageAsColorOrDSAttachment_,
406 																									  bool							useDifferentAreasSampleWrite_,
407 																									  bool							interleaveReadWriteComponents_,
408 																									  ImageAspectTestMode			imageAspectTestMode,
409 																									  PipelineStateMode				pipelineStateMode,
410 																									  bool							useMaintenance5_)
411 	: ImageSamplingInstance				(context, params)
412 	, m_params							(params)
413 	, m_useImageAsColorOrDSAttachment	(useImageAsColorOrDSAttachment_)
414 	, m_useDifferentAreasSampleWrite	(useDifferentAreasSampleWrite_)
415 	, m_interleaveReadWriteComponents	(interleaveReadWriteComponents_)
416 	, m_imageAspectTestMode				(imageAspectTestMode)
417 	, m_pipelineStateMode				(pipelineStateMode)
418 	, m_useMaintenance5					(useMaintenance5_)
419 {
420 }
421 
setup(void)422 void AttachmentFeedbackLoopLayoutImageSamplingInstance::setup (void)
423 {
424 	const InstanceInterface&				vki						= m_context.getInstanceInterface();
425 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
426 	const VkPhysicalDevice					physDevice				= m_context.getPhysicalDevice();
427 	const VkDevice							vkDevice				= m_context.getDevice();
428 	const VkQueue							queue					= m_context.getUniversalQueue();
429 	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
430 	SimpleAllocator							memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
431 	const VkComponentMapping				componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
432 	tcu::UVec2								renderSize				= m_useImageAsColorOrDSAttachment ? tcu::UVec2({ (unsigned)m_imageSize.x(), (unsigned)m_imageSize.y() }) : m_renderSize;
433 
434 	DE_ASSERT(m_samplerParams.pNext == DE_NULL);
435 
436 	// Create texture images, views and samplers
437 	{
438 		VkImageCreateFlags			imageFlags			= 0u;
439 
440 		if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
441 			imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
442 
443 		// Initialize texture data
444 		if (isCompressedFormat(m_imageFormat))
445 			m_texture = createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
446 		else
447 			m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
448 
449 		VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
450 			VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
451 
452 		if (isDepthStencilFormat(m_imageFormat))
453 			imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
454 		else
455 			imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
456 
457 		const VkImageCreateInfo	imageParams =
458 		{
459 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
460 			DE_NULL,														// const void*				pNext;
461 			imageFlags,														// VkImageCreateFlags		flags;
462 			getCompatibleImageType(m_imageViewType),						// VkImageType				imageType;
463 			m_imageFormat,													// VkFormat					format;
464 			{																// VkExtent3D				extent;
465 				(deUint32)m_imageSize.x(),
466 				(deUint32)m_imageSize.y(),
467 				(deUint32)m_imageSize.z()
468 			},
469 			(deUint32)m_texture->getNumLevels(),							// deUint32					mipLevels;
470 			(deUint32)m_layerCount,											// deUint32					arrayLayers;
471 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
472 			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
473 			imageUsageFlags,												// VkImageUsageFlags		usage;
474 			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
475 			1u,																// deUint32					queueFamilyIndexCount;
476 			&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
477 			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
478 		};
479 
480 		checkImageSupport(vki, physDevice, imageParams);
481 
482 		m_images.resize(m_imageCount);
483 		m_imageAllocs.resize(m_imageCount);
484 		m_imageViews.resize(m_imageCount);
485 
486 		// Create command pool
487 		m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
488 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
489 
490 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
491 		{
492 			m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
493 			m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
494 			VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset()));
495 
496 			// Upload texture data
497 			uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx], m_imageLayout);
498 
499 			// Create image view and sampler
500 			const VkImageViewCreateInfo imageViewParams =
501 			{
502 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
503 				DE_NULL,									// const void*				pNext;
504 				0u,											// VkImageViewCreateFlags	flags;
505 				**m_images[imgNdx],							// VkImage					image;
506 				m_imageViewType,							// VkImageViewType			viewType;
507 				m_imageFormat,								// VkFormat					format;
508 				m_componentMapping,							// VkComponentMapping		components;
509 				m_subresourceRange,							// VkImageSubresourceRange	subresourceRange;
510 			};
511 
512 			m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
513 		}
514 
515 		m_sampler	= createSampler(vk, vkDevice, &m_samplerParams);
516 	}
517 
518 	// Create descriptor set for image and sampler
519 	{
520 		DescriptorPoolBuilder descriptorPoolBuilder;
521 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
522 			descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
523 		descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
524 		m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
525 			m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
526 
527 		DescriptorSetLayoutBuilder setLayoutBuilder;
528 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
529 			setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
530 		setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
531 		m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
532 
533 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
534 		{
535 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
536 			DE_NULL,											// const void*					pNext;
537 			*m_descriptorPool,									// VkDescriptorPool				descriptorPool;
538 			1u,													// deUint32						setLayoutCount;
539 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
540 		};
541 
542 		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
543 
544 		const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
545 		std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
546 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
547 		{
548 			descriptorImageInfo[imgNdx].sampler		= sampler;									// VkSampler		sampler;
549 			descriptorImageInfo[imgNdx].imageView	= **m_imageViews[imgNdx];					// VkImageView		imageView;
550 			descriptorImageInfo[imgNdx].imageLayout	= m_imageLayout;							// VkImageLayout	imageLayout;
551 		}
552 
553 		DescriptorSetUpdateBuilder setUpdateBuilder;
554 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
555 		{
556 			const VkDescriptorImageInfo descriptorSamplerInfo =
557 			{
558 				*m_sampler,									// VkSampler		sampler;
559 				DE_NULL,									// VkImageView		imageView;
560 				m_imageLayout,								// VkImageLayout	imageLayout;
561 			};
562 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
563 		}
564 
565 		const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
566 		setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data());
567 		setUpdateBuilder.update(vk, vkDevice);
568 	}
569 
570 	// Create color images and views
571 	{
572 		const VkImageCreateInfo colorImageParams =
573 		{
574 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
575 			DE_NULL,																	// const void*				pNext;
576 			0u,																			// VkImageCreateFlags		flags;
577 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
578 			m_colorFormat,																// VkFormat					format;
579 			{ (deUint32)renderSize.x(), (deUint32)renderSize.y(), 1u },					// VkExtent3D				extent;
580 			1u,																			// deUint32					mipLevels;
581 			1u,																			// deUint32					arrayLayers;
582 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
583 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
584 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
585 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
586 			1u,																			// deUint32					queueFamilyIndexCount;
587 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
588 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
589 		};
590 
591 		checkImageSupport(vki, physDevice, colorImageParams);
592 
593 		m_colorImages.resize(m_imageCount);
594 		m_colorImageAllocs.resize(m_imageCount);
595 		m_colorAttachmentViews.resize(m_imageCount);
596 
597 		if (m_useImageAsColorOrDSAttachment)
598 		{
599 			for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
600 			{
601 				m_colorImages[imgNdx] = m_images[imgNdx];
602 				m_colorImageAllocs[imgNdx] = m_imageAllocs[imgNdx];
603 				m_colorAttachmentViews[imgNdx] = m_imageViews[imgNdx];
604 			}
605 		}
606 		else
607 		{
608 			for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
609 			{
610 				m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
611 				m_colorImageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
612 				VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(), (*m_colorImageAllocs[imgNdx])->getOffset()));
613 
614 				const VkImageViewCreateInfo colorAttachmentViewParams =
615 				{
616 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
617 					DE_NULL,											// const void*				pNext;
618 					0u,													// VkImageViewCreateFlags	flags;
619 					**m_colorImages[imgNdx],							// VkImage					image;
620 					VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
621 					m_colorFormat,										// VkFormat					format;
622 					componentMappingRGBA,								// VkComponentMapping		components;
623 					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
624 				};
625 
626 				m_colorAttachmentViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
627 			}
628 		}
629 	}
630 
631 	// Create render pass
632 	{
633 		std::vector<VkAttachmentDescription>	attachmentDescriptions(m_imageCount);
634 		std::vector<VkAttachmentReference>		attachmentReferences(m_imageCount);
635 
636 		VkAttachmentLoadOp	loadOp		= m_useImageAsColorOrDSAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
637 		VkImageLayout		imageLayout	= m_useImageAsColorOrDSAttachment ? m_imageLayout : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
638 
639 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
640 		{
641 			attachmentDescriptions[imgNdx].flags			= 0u;																	// VkAttachmentDescriptionFlags		flags;
642 			attachmentDescriptions[imgNdx].format			= m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;		// VkFormat							format;
643 			attachmentDescriptions[imgNdx].samples			= VK_SAMPLE_COUNT_1_BIT;												// VkSampleCountFlagBits			samples;
644 			attachmentDescriptions[imgNdx].loadOp			= loadOp;																// VkAttachmentLoadOp				loadOp;
645 			attachmentDescriptions[imgNdx].storeOp			= VK_ATTACHMENT_STORE_OP_STORE;											// VkAttachmentStoreOp				storeOp;
646 			attachmentDescriptions[imgNdx].stencilLoadOp	= loadOp;																// VkAttachmentLoadOp				stencilLoadOp;
647 			attachmentDescriptions[imgNdx].stencilStoreOp	= VK_ATTACHMENT_STORE_OP_STORE;											// VkAttachmentStoreOp				stencilStoreOp;
648 			attachmentDescriptions[imgNdx].initialLayout	= imageLayout;															// VkImageLayout					initialLayout;
649 			attachmentDescriptions[imgNdx].finalLayout		= imageLayout;															// VkImageLayout					finalLayout;
650 
651 			attachmentReferences[imgNdx].attachment			= (deUint32)imgNdx;														// deUint32							attachment;
652 			attachmentReferences[imgNdx].layout				= imageLayout;															// VkImageLayout					layout;
653 		}
654 
655 		const VkSubpassDescription subpassDescription =
656 		{
657 			0u,													// VkSubpassDescriptionFlags	flags;
658 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
659 			0u,													// deUint32						inputAttachmentCount;
660 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
661 			(deUint32)m_imageCount,								// deUint32						colorAttachmentCount;
662 			&attachmentReferences[0],							// const VkAttachmentReference*	pColorAttachments;
663 			DE_NULL,											// const VkAttachmentReference*	pResolveAttachments;
664 			DE_NULL,											// const VkAttachmentReference*	pDepthStencilAttachment;
665 			0u,													// deUint32						preserveAttachmentCount;
666 			DE_NULL												// const VkAttachmentReference*	pPreserveAttachments;
667 		};
668 
669 		std::vector<VkSubpassDependency> subpassDependencies;
670 
671 		if (m_useImageAsColorOrDSAttachment)
672 		{
673 			const VkSubpassDependency spdVal =
674 			{
675 				0u,																	//	uint32_t				srcSubpass;
676 				0u,																	//	uint32_t				dstSubpass;
677 				VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,								//	VkPipelineStageFlags	srcStageMask;
678 				VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,						//	VkPipelineStageFlags	dstStageMask;
679 				VK_ACCESS_SHADER_READ_BIT,											//	VkAccessFlags			srcAccessMask;
680 				VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,								//	VkAccessFlags			dstAccessMask;
681 				VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT | VK_DEPENDENCY_BY_REGION_BIT,	//	VkDependencyFlags		dependencyFlags;
682 			};
683 
684 			subpassDependencies.push_back(spdVal);
685 		}
686 
687 		const VkRenderPassCreateInfo renderPassParams =
688 		{
689 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
690 			DE_NULL,											// const void*						pNext;
691 			0u,													// VkRenderPassCreateFlags			flags;
692 			(deUint32)attachmentDescriptions.size(),			// deUint32							attachmentCount;
693 			&attachmentDescriptions[0],							// const VkAttachmentDescription*	pAttachments;
694 			1u,													// deUint32							subpassCount;
695 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
696 			static_cast<uint32_t>(subpassDependencies.size()),	// deUint32							dependencyCount;
697 			de::dataOrNull(subpassDependencies),				// const VkSubpassDependency*		pDependencies;
698 		};
699 
700 		m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
701 	}
702 
703 	// Create framebuffer
704 	{
705 		std::vector<VkImage> images(m_imageCount);
706 		std::vector<VkImageView> pAttachments(m_imageCount);
707 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
708 		{
709 			images[imgNdx] = m_colorImages[imgNdx]->get();
710 			pAttachments[imgNdx] =  m_colorAttachmentViews[imgNdx]->get();
711 		}
712 
713 		const VkFramebufferCreateInfo framebufferParams =
714 		{
715 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
716 			DE_NULL,											// const void*				pNext;
717 			0u,													// VkFramebufferCreateFlags	flags;
718 			*m_renderPass,										// VkRenderPass				renderPass;
719 			(deUint32)m_imageCount,								// deUint32					attachmentCount;
720 			&pAttachments[0],									// const VkImageView*		pAttachments;
721 			(deUint32)renderSize.x(),							// deUint32					width;
722 			(deUint32)renderSize.y(),							// deUint32					height;
723 			1u													// deUint32					layers;
724 		};
725 
726 		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
727 	}
728 
729 	// Create pipeline layouts
730 	{
731 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
732 		{
733 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
734 			DE_NULL,											// const void*					pNext;
735 			VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT,	// VkPipelineLayoutCreateFlags	flags;
736 			0u,													// deUint32						setLayoutCount;
737 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
738 			0u,													// deUint32						pushConstantRangeCount;
739 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
740 		};
741 
742 		m_preRasterizationStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
743 	}
744 	{
745 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
746 		{
747 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
748 			DE_NULL,											// const void*					pNext;
749 			VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT,	// VkPipelineLayoutCreateFlags	flags;
750 			1u,													// deUint32						setLayoutCount;
751 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*	pSetLayouts;
752 			0u,													// deUint32						pushConstantRangeCount;
753 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
754 		};
755 
756 		m_fragmentStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
757 	}
758 
759 	m_vertexShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
760 	m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
761 
762 	// Create pipeline
763 	{
764 		const VkVertexInputBindingDescription vertexInputBindingDescription =
765 		{
766 			0u,									// deUint32					binding;
767 			sizeof(Vertex4Tex4),				// deUint32					strideInBytes;
768 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
769 		};
770 
771 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
772 		{
773 			{
774 				0u,										// deUint32	location;
775 				0u,										// deUint32	binding;
776 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
777 				0u										// deUint32	offset;
778 			},
779 			{
780 				1u,										// deUint32	location;
781 				0u,										// deUint32	binding;
782 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
783 				DE_OFFSET_OF(Vertex4Tex4, texCoord),	// deUint32	offset;
784 			}
785 		};
786 
787 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
788 		{
789 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
790 			DE_NULL,														// const void*								pNext;
791 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
792 			1u,																// deUint32									vertexBindingDescriptionCount;
793 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
794 			2u,																// deUint32									vertexAttributeDescriptionCount;
795 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
796 		};
797 
798 		const std::vector<VkViewport>	viewports	(1, makeViewport(renderSize));
799 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderSize));
800 
801 		std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates(m_imageCount);
802 
803 		VkColorComponentFlags colorComponents = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
804 
805 		if (m_interleaveReadWriteComponents)
806 			colorComponents = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_B_BIT;
807 
808 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
809 		{
810 			colorBlendAttachmentStates[imgNdx].blendEnable			= false;												// VkBool32					blendEnable;
811 			colorBlendAttachmentStates[imgNdx].srcColorBlendFactor	= VK_BLEND_FACTOR_ONE;									// VkBlendFactor			srcColorBlendFactor;
812 			colorBlendAttachmentStates[imgNdx].dstColorBlendFactor	= VK_BLEND_FACTOR_ZERO;									// VkBlendFactor			dstColorBlendFactor;
813 			colorBlendAttachmentStates[imgNdx].colorBlendOp			= VK_BLEND_OP_ADD;										// VkBlendOp				colorBlendOp;
814 			colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor	= VK_BLEND_FACTOR_ONE;									// VkBlendFactor			srcAlphaBlendFactor;
815 			colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor	= VK_BLEND_FACTOR_ZERO;									// VkBlendFactor			dstAlphaBlendFactor;
816 			colorBlendAttachmentStates[imgNdx].alphaBlendOp			= VK_BLEND_OP_ADD;										// VkBlendOp				alphaBlendOp;
817 			colorBlendAttachmentStates[imgNdx].colorWriteMask		= colorComponents;										// VkColorComponentFlags	colorWriteMask;
818 		}
819 
820 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
821 		{
822 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
823 			DE_NULL,													// const void*									pNext;
824 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
825 			false,														// VkBool32										logicOpEnable;
826 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
827 			(deUint32)m_imageCount,										// deUint32										attachmentCount;
828 			&colorBlendAttachmentStates[0],								// const VkPipelineColorBlendAttachmentState*	pAttachments;
829 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
830 		};
831 
832 		std::vector<VkDynamicState> dynamicStates;
833 		if (m_pipelineStateMode != PipelineStateMode::STATIC)
834 			dynamicStates.push_back(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
835 
836 		const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
837 		{
838 			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
839 			nullptr,
840 			0u,
841 			de::sizeU32(dynamicStates),
842 			de::dataOrNull(dynamicStates),
843 		};
844 
845 		if (m_useMaintenance5)
846 			m_graphicsPipeline.setPipelineCreateFlags2(translateCreateFlag(m_params.pipelineCreateFlags));
847 
848 		m_graphicsPipeline.setDynamicState(&dynamicStateInfo)
849 						  .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
850 						  .setDefaultDepthStencilState()
851 						  .setDefaultRasterizationState()
852 						  .setDefaultMultisampleState()
853 						  .setupVertexInputState(&vertexInputStateParams)
854 						  .setupPreRasterizationShaderState(viewports,
855 														scissors,
856 														m_preRasterizationStatePipelineLayout,
857 														*m_renderPass,
858 														0u,
859 														m_vertexShaderModule)
860 						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
861 						  .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
862 						  .buildPipeline();
863 	}
864 
865 	// Create vertex buffer
866 	{
867 		const VkDeviceSize			vertexBufferSize	= (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
868 		const VkBufferCreateInfo	vertexBufferParams	=
869 		{
870 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
871 			DE_NULL,									// const void*			pNext;
872 			0u,											// VkBufferCreateFlags	flags;
873 			vertexBufferSize,							// VkDeviceSize			size;
874 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
875 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
876 			1u,											// deUint32				queueFamilyIndexCount;
877 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
878 		};
879 
880 		DE_ASSERT(vertexBufferSize > 0);
881 
882 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
883 		m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
884 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
885 
886 		// Load vertices into vertex buffer
887 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
888 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
889 	}
890 
891 	// Create command buffer
892 	{
893 		VkFormat clearFormat = m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;
894 		const std::vector<VkClearValue> attachmentClearValues (m_imageCount, defaultClearValue(clearFormat));
895 
896 		std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
897 
898 		VkAccessFlags dstAccessMask = isDepthStencilFormat(m_imageFormat) ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT : VK_ACCESS_SHADER_READ_BIT;
899 		VkPipelineStageFlags pipelineStageFlags = isDepthStencilFormat(m_imageFormat) ? VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
900 
901 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
902 		{
903 			preAttachmentBarriers[imgNdx].sType								= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;								// VkStructureType			sType;
904 			preAttachmentBarriers[imgNdx].pNext								= DE_NULL;																// const void*				pNext;
905 			preAttachmentBarriers[imgNdx].srcAccessMask						= VK_ACCESS_TRANSFER_WRITE_BIT;											// VkAccessFlags			srcAccessMask;
906 			preAttachmentBarriers[imgNdx].dstAccessMask						= dstAccessMask;														// VkAccessFlags			dstAccessMask;
907 			preAttachmentBarriers[imgNdx].oldLayout							= m_imageLayout;														// VkImageLayout			oldLayout;
908 			preAttachmentBarriers[imgNdx].newLayout							= m_imageLayout;														// VkImageLayout			newLayout;
909 			preAttachmentBarriers[imgNdx].srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;												// deUint32					srcQueueFamilyIndex;
910 			preAttachmentBarriers[imgNdx].dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;												// deUint32					dstQueueFamilyIndex;
911 			preAttachmentBarriers[imgNdx].image								= **m_images[imgNdx];													// VkImage					image;
912 			preAttachmentBarriers[imgNdx].subresourceRange					= m_subresourceRange;													// VkImageSubresourceRange	subresourceRange;
913 		}
914 
915 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
916 
917 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineStageFlags, (VkDependencyFlags)0,
918 			0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
919 
920 		if (!m_useImageAsColorOrDSAttachment)
921 		{
922 			// Pipeline barrier for the color attachment, which is a different image than the sampled one.
923 			for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
924 			{
925 				preAttachmentBarriers[imgNdx].sType								= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;								// VkStructureType			sType;
926 				preAttachmentBarriers[imgNdx].pNext								= DE_NULL;																// const void*				pNext;
927 				preAttachmentBarriers[imgNdx].srcAccessMask						= (VkAccessFlagBits)0u;													// VkAccessFlags			srcAccessMask;
928 				preAttachmentBarriers[imgNdx].dstAccessMask						= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;									// VkAccessFlags			dstAccessMask;
929 				preAttachmentBarriers[imgNdx].oldLayout							= VK_IMAGE_LAYOUT_UNDEFINED;											// VkImageLayout			oldLayout;
930 				preAttachmentBarriers[imgNdx].newLayout							= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;								// VkImageLayout			newLayout;
931 				preAttachmentBarriers[imgNdx].srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;												// deUint32					srcQueueFamilyIndex;
932 				preAttachmentBarriers[imgNdx].dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;												// deUint32					dstQueueFamilyIndex;
933 				preAttachmentBarriers[imgNdx].image								= **m_colorImages[imgNdx];												// VkImage					image;
934 				preAttachmentBarriers[imgNdx].subresourceRange.aspectMask		= getAspectFlags(m_colorFormat);										// VkImageSubresourceRange	subresourceRange;
935 				preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel		= 0u;
936 				preAttachmentBarriers[imgNdx].subresourceRange.levelCount		= 1u;
937 				preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer	= 0u;
938 				preAttachmentBarriers[imgNdx].subresourceRange.layerCount		= 1u;
939 			}
940 
941 			vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
942 								  0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
943 
944 			m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), (deUint32)attachmentClearValues.size(), &attachmentClearValues[0]);
945 		}
946 		else
947 		{
948 			// Do not clear the color attachments as we are using the sampled texture as color attachment as well.
949 			m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), 0u, DE_NULL);
950 		}
951 
952 		m_graphicsPipeline.bind(*m_cmdBuffer);
953 
954 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
955 
956 		const VkDeviceSize vertexBufferOffset = 0;
957 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
958 
959 		if (m_pipelineStateMode != PipelineStateMode::STATIC)
960 			vk.cmdSetAttachmentFeedbackLoopEnableEXT(*m_cmdBuffer, testModeToAspectFlags(m_imageAspectTestMode));
961 
962 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
963 
964 		m_renderPass.end(vk, *m_cmdBuffer);
965 		endCommandBuffer(vk, *m_cmdBuffer);
966 	}
967 }
968 
AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(Context& context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_, bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_, ImageAspectTestMode imageAspectTestMode, PipelineStateMode pipelineStateMode, bool useMaintenance5_)969 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance (Context&						context,
970 																															  ImageSamplingInstanceParams	params,
971 																															  bool							useImageAsColorOrDSAttachment_,
972 																															  bool							useDifferentAreasSampleWrite_,
973 																															  bool							interleaveReadWriteComponents_,
974 																															  ImageAspectTestMode			imageAspectTestMode,
975 																															  PipelineStateMode				pipelineStateMode,
976 																															  bool							useMaintenance5_)
977 	: AttachmentFeedbackLoopLayoutImageSamplingInstance		(context, params, useImageAsColorOrDSAttachment_, useDifferentAreasSampleWrite_, interleaveReadWriteComponents_, imageAspectTestMode, pipelineStateMode, useMaintenance5_)
978 	, m_separateStencilUsage								(params.separateStencilUsage)
979 {
980 }
981 
~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void)982 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance (void)
983 {
984 }
985 
setup(void)986 void AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::setup (void)
987 {
988 	const InstanceInterface&				vki						= m_context.getInstanceInterface();
989 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
990 	const VkPhysicalDevice					physDevice				= m_context.getPhysicalDevice();
991 	const VkDevice							vkDevice				= m_context.getDevice();
992 	const VkQueue							queue					= m_context.getUniversalQueue();
993 	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
994 	SimpleAllocator							memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
995 	tcu::UVec2								renderSize				= tcu::UVec2({ (unsigned)m_imageSize.x(), (unsigned)m_imageSize.y() });
996 
997 	DE_ASSERT(m_useImageAsColorOrDSAttachment && isDepthStencilFormat(m_imageFormat));
998 	DE_ASSERT(m_samplerParams.pNext == DE_NULL);
999 
1000 	// Create texture images, views
1001 	{
1002 		VkImageCreateFlags			imageFlags			= 0u;
1003 
1004 		if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
1005 			imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
1006 
1007 		// Initialize texture data
1008 		if (isCompressedFormat(m_imageFormat))
1009 			m_texture = createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
1010 		else
1011 			m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
1012 
1013 		VkImageUsageFlags imageUsageFlags =
1014 			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
1015 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1016 
1017 		const VkImageCreateInfo	imageParams =
1018 		{
1019 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
1020 			DE_NULL,														// const void*				pNext;
1021 			imageFlags,														// VkImageCreateFlags		flags;
1022 			getCompatibleImageType(m_imageViewType),						// VkImageType				imageType;
1023 			m_imageFormat,													// VkFormat					format;
1024 			{																// VkExtent3D				extent;
1025 				(deUint32)m_imageSize.x(),
1026 				(deUint32)m_imageSize.y(),
1027 				(deUint32)m_imageSize.z()
1028 			},
1029 			(deUint32)m_texture->getNumLevels(),							// deUint32					mipLevels;
1030 			(deUint32)m_layerCount,											// deUint32					arrayLayers;
1031 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
1032 			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
1033 			imageUsageFlags,												// VkImageUsageFlags		usage;
1034 			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
1035 			1u,																// deUint32					queueFamilyIndexCount;
1036 			&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
1037 			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
1038 		};
1039 
1040 		checkImageSupport(vki, physDevice, imageParams);
1041 
1042 		m_images.resize(m_imageCount);
1043 		m_imageAllocs.resize(m_imageCount);
1044 
1045 		// Create command pool
1046 		m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1047 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1048 
1049 		int numImageViews = m_interleaveReadWriteComponents ? m_imageCount + 1 : m_imageCount;
1050 		m_imageViews.resize(numImageViews);
1051 
1052 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1053 		{
1054 			m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
1055 			m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind)));
1056 			VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset()));
1057 
1058 			// Upload texture data
1059 			uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx], m_imageLayout);
1060 
1061 		}
1062 
1063 		for (int imgNdx = 0; imgNdx < numImageViews; ++imgNdx)
1064 		{
1065 			VkImage image = (m_interleaveReadWriteComponents && imgNdx == m_imageCount) ? **m_images[imgNdx - 1] : **m_images[imgNdx];
1066 
1067 			// Create image view and sampler
1068 			VkImageViewCreateInfo imageViewParams =
1069 			{
1070 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1071 				DE_NULL,									// const void*				pNext;
1072 				0u,											// VkImageViewCreateFlags	flags;
1073 				image,										// VkImage					image;
1074 				m_imageViewType,							// VkImageViewType			viewType;
1075 				m_imageFormat,								// VkFormat					format;
1076 				m_componentMapping,							// VkComponentMapping		components;
1077 				m_subresourceRange,							// VkImageSubresourceRange	subresourceRange;
1078 			};
1079 
1080 			if (m_interleaveReadWriteComponents && imgNdx == m_imageCount)
1081 			{
1082 				imageViewParams.subresourceRange.aspectMask = getImageAspectFlags(mapVkFormat(m_imageFormat));
1083 			}
1084 
1085 			m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
1086 		}
1087 
1088 		m_sampler	= createSampler(vk, vkDevice, &m_samplerParams);
1089 	}
1090 
1091 	// Create descriptor set for image and sampler
1092 	{
1093 		DescriptorPoolBuilder descriptorPoolBuilder;
1094 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1095 			descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
1096 		descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
1097 		m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1098 			m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
1099 
1100 		DescriptorSetLayoutBuilder setLayoutBuilder;
1101 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1102 			setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
1103 		setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
1104 		m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
1105 
1106 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
1107 		{
1108 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
1109 			DE_NULL,											// const void*					pNext;
1110 			*m_descriptorPool,									// VkDescriptorPool				descriptorPool;
1111 			1u,													// deUint32						setLayoutCount;
1112 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
1113 		};
1114 
1115 		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
1116 
1117 		const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
1118 		std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
1119 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1120 		{
1121 			descriptorImageInfo[imgNdx].sampler		= sampler;									// VkSampler		sampler;
1122 			descriptorImageInfo[imgNdx].imageView	= **m_imageViews[imgNdx];					// VkImageView		imageView;
1123 			descriptorImageInfo[imgNdx].imageLayout	= m_imageLayout;							// VkImageLayout	imageLayout;
1124 		}
1125 
1126 		DescriptorSetUpdateBuilder setUpdateBuilder;
1127 		if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1128 		{
1129 			const VkDescriptorImageInfo descriptorSamplerInfo =
1130 			{
1131 				*m_sampler,									// VkSampler		sampler;
1132 				DE_NULL,									// VkImageView		imageView;
1133 				m_imageLayout,								// VkImageLayout	imageLayout;
1134 			};
1135 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
1136 		}
1137 
1138 		const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
1139 		setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data());
1140 		setUpdateBuilder.update(vk, vkDevice);
1141 	}
1142 
1143 	// Create depth-stencil images and views, no color attachment
1144 	{
1145 		m_dsImages.resize(m_imageCount);
1146 		m_dsImageAllocs.resize(m_imageCount);
1147 		m_dsAttachmentViews.resize(m_imageCount);
1148 
1149 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1150 		{
1151 			m_dsImages[imgNdx] = m_images[imgNdx];
1152 			m_dsImageAllocs[imgNdx] = m_imageAllocs[imgNdx];
1153 			m_dsAttachmentViews[imgNdx] = m_interleaveReadWriteComponents ? m_imageViews[imgNdx + 1] : m_imageViews[imgNdx];
1154 		}
1155 	}
1156 
1157 	// Create render pass
1158 	{
1159 		std::vector<VkAttachmentDescription>	attachmentDescriptions(m_imageCount);
1160 		std::vector<VkAttachmentReference>		attachmentReferences(m_imageCount);
1161 
1162 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1163 		{
1164 			attachmentDescriptions[imgNdx].flags			= 0u;																	// VkAttachmentDescriptionFlags		flags;
1165 			attachmentDescriptions[imgNdx].format			= m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;		// VkFormat							format;
1166 			attachmentDescriptions[imgNdx].samples			= VK_SAMPLE_COUNT_1_BIT;												// VkSampleCountFlagBits			samples;
1167 			attachmentDescriptions[imgNdx].loadOp			= VK_ATTACHMENT_LOAD_OP_LOAD;											// VkAttachmentLoadOp				loadOp;
1168 			attachmentDescriptions[imgNdx].storeOp			= VK_ATTACHMENT_STORE_OP_STORE;											// VkAttachmentStoreOp				storeOp;
1169 			attachmentDescriptions[imgNdx].stencilLoadOp	= VK_ATTACHMENT_LOAD_OP_LOAD;											// VkAttachmentLoadOp				stencilLoadOp;
1170 			attachmentDescriptions[imgNdx].stencilStoreOp	= VK_ATTACHMENT_STORE_OP_STORE;											// VkAttachmentStoreOp				stencilStoreOp;
1171 			attachmentDescriptions[imgNdx].initialLayout	= m_imageLayout;														// VkImageLayout					initialLayout;
1172 			attachmentDescriptions[imgNdx].finalLayout		= m_imageLayout;														// VkImageLayout					finalLayout;
1173 
1174 			attachmentReferences[imgNdx].attachment			= (deUint32)imgNdx;														// deUint32							attachment;
1175 			attachmentReferences[imgNdx].layout				= m_imageLayout;														// VkImageLayout					layout;
1176 		}
1177 
1178 		const VkSubpassDescription subpassDescription =
1179 		{
1180 			0u,																				// VkSubpassDescriptionFlags	flags;
1181 			VK_PIPELINE_BIND_POINT_GRAPHICS,												// VkPipelineBindPoint			pipelineBindPoint;
1182 			0u,																				// deUint32						inputAttachmentCount;
1183 			DE_NULL,																		// const VkAttachmentReference*	pInputAttachments;
1184 			0u,																				// deUint32						colorAttachmentCount;
1185 			DE_NULL,																		// const VkAttachmentReference*	pColorAttachments;
1186 			DE_NULL,																		// const VkAttachmentReference*	pResolveAttachments;
1187 			&attachmentReferences[0],														// const VkAttachmentReference*	pDepthStencilAttachment;
1188 			0u,																				// deUint32						preserveAttachmentCount;
1189 			DE_NULL																			// const VkAttachmentReference*	pPreserveAttachments;
1190 		};
1191 
1192 		std::vector<VkSubpassDependency> subpassDependencies;
1193 
1194 		if (m_useImageAsColorOrDSAttachment)
1195 		{
1196 			const auto srcStageMask		= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
1197 			const auto srcAccessMask	= VK_ACCESS_SHADER_READ_BIT;
1198 			const auto dstStageMask		= (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1199 			const auto dstAccessMask	= (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
1200 
1201 			const VkSubpassDependency spdVal =
1202 			{
1203 				0u,																	//	uint32_t				srcSubpass;
1204 				0u,																	//	uint32_t				dstSubpass;
1205 				srcStageMask,														//	VkPipelineStageFlags	srcStageMask;
1206 				dstStageMask,														//	VkPipelineStageFlags	dstStageMask;
1207 				srcAccessMask,														//	VkAccessFlags			srcAccessMask;
1208 				dstAccessMask,														//	VkAccessFlags			dstAccessMask;
1209 				VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT | VK_DEPENDENCY_BY_REGION_BIT,	//	VkDependencyFlags		dependencyFlags;
1210 			};
1211 
1212 			subpassDependencies.push_back(spdVal);
1213 		}
1214 
1215 		const VkRenderPassCreateInfo renderPassParams =
1216 		{
1217 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1218 			DE_NULL,											// const void*						pNext;
1219 			0u,													// VkRenderPassCreateFlags			flags;
1220 			(deUint32)attachmentDescriptions.size(),			// deUint32							attachmentCount;
1221 			&attachmentDescriptions[0],							// const VkAttachmentDescription*	pAttachments;
1222 			1u,													// deUint32							subpassCount;
1223 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
1224 			static_cast<uint32_t>(subpassDependencies.size()),	// deUint32							dependencyCount;
1225 			de::dataOrNull(subpassDependencies),				// const VkSubpassDependency*		pDependencies;
1226 		};
1227 
1228 		m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
1229 	}
1230 
1231 	// Create framebuffer
1232 	{
1233 		std::vector<VkImage> images(m_imageCount);
1234 		std::vector<VkImageView> pAttachments(m_imageCount);
1235 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1236 		{
1237 			images[imgNdx] = m_dsImages[imgNdx]->get();
1238 			pAttachments[imgNdx] = m_dsAttachmentViews[imgNdx]->get();
1239 		}
1240 
1241 		const VkFramebufferCreateInfo framebufferParams =
1242 		{
1243 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
1244 			DE_NULL,											// const void*				pNext;
1245 			0u,													// VkFramebufferCreateFlags	flags;
1246 			*m_renderPass,										// VkRenderPass				renderPass;
1247 			(deUint32)m_imageCount,								// deUint32					attachmentCount;
1248 			&pAttachments[0],									// const VkImageView*		pAttachments;
1249 			(deUint32)renderSize.x(),							// deUint32					width;
1250 			(deUint32)renderSize.y(),							// deUint32					height;
1251 			1u													// deUint32					layers;
1252 		};
1253 
1254 		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
1255 	}
1256 
1257 	// Create pipeline layouts
1258 	{
1259 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1260 		{
1261 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1262 			DE_NULL,											// const void*					pNext;
1263 			0u,													// VkPipelineLayoutCreateFlags	flags;
1264 			0u,													// deUint32						setLayoutCount;
1265 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
1266 			0u,													// deUint32						pushConstantRangeCount;
1267 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1268 		};
1269 
1270 		m_preRasterizationStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1271 	}
1272 	{
1273 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1274 		{
1275 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1276 			DE_NULL,											// const void*					pNext;
1277 			VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT,	// VkPipelineLayoutCreateFlags	flags;
1278 			0u,													// deUint32						setLayoutCount;
1279 			DE_NULL,											// const VkDescriptorSetLayout*	pSetLayouts;
1280 			0u,													// deUint32						pushConstantRangeCount;
1281 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1282 		};
1283 
1284 		m_preRasterizationStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1285 	}
1286 	{
1287 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1288 		{
1289 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1290 			DE_NULL,											// const void*					pNext;
1291 			VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT,	// VkPipelineLayoutCreateFlags	flags;
1292 			1u,													// deUint32						setLayoutCount;
1293 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*	pSetLayouts;
1294 			0u,													// deUint32						pushConstantRangeCount;
1295 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1296 		};
1297 
1298 		m_fragmentStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1299 	}
1300 
1301 	m_vertexShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
1302 	m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
1303 
1304 	// Create pipeline
1305 	{
1306 		const VkVertexInputBindingDescription vertexInputBindingDescription =
1307 		{
1308 			0u,									// deUint32					binding;
1309 			sizeof(Vertex4Tex4),				// deUint32					strideInBytes;
1310 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
1311 		};
1312 
1313 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
1314 		{
1315 			{
1316 				0u,										// deUint32	location;
1317 				0u,										// deUint32	binding;
1318 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
1319 				0u										// deUint32	offset;
1320 			},
1321 			{
1322 				1u,										// deUint32	location;
1323 				0u,										// deUint32	binding;
1324 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
1325 				DE_OFFSET_OF(Vertex4Tex4, texCoord),	// deUint32	offset;
1326 			}
1327 		};
1328 
1329 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1330 		{
1331 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1332 			DE_NULL,														// const void*								pNext;
1333 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1334 			1u,																// deUint32									vertexBindingDescriptionCount;
1335 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1336 			2u,																// deUint32									vertexAttributeDescriptionCount;
1337 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1338 		};
1339 
1340 		const std::vector<VkViewport>	viewports	(1, makeViewport(renderSize));
1341 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(renderSize));
1342 
1343 		std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates(m_imageCount);
1344 
1345 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1346 		{
1347 			colorBlendAttachmentStates[imgNdx].blendEnable			= false;												// VkBool32					blendEnable;
1348 			colorBlendAttachmentStates[imgNdx].srcColorBlendFactor	= VK_BLEND_FACTOR_ONE;									// VkBlendFactor			srcColorBlendFactor;
1349 			colorBlendAttachmentStates[imgNdx].dstColorBlendFactor	= VK_BLEND_FACTOR_ZERO;									// VkBlendFactor			dstColorBlendFactor;
1350 			colorBlendAttachmentStates[imgNdx].colorBlendOp			= VK_BLEND_OP_ADD;										// VkBlendOp				colorBlendOp;
1351 			colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor	= VK_BLEND_FACTOR_ONE;									// VkBlendFactor			srcAlphaBlendFactor;
1352 			colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor	= VK_BLEND_FACTOR_ZERO;									// VkBlendFactor			dstAlphaBlendFactor;
1353 			colorBlendAttachmentStates[imgNdx].alphaBlendOp			= VK_BLEND_OP_ADD;										// VkBlendOp				alphaBlendOp;
1354 			colorBlendAttachmentStates[imgNdx].colorWriteMask		= 0u;													// VkColorComponentFlags	colorWriteMask;
1355 		}
1356 
1357 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1358 		{
1359 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1360 			DE_NULL,													// const void*									pNext;
1361 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1362 			false,														// VkBool32										logicOpEnable;
1363 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1364 			0u,															// deUint32										attachmentCount;
1365 			DE_NULL,													// const VkPipelineColorBlendAttachmentState*	pAttachments;
1366 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
1367 		};
1368 
1369 		VkBool32 depthTestEnable =
1370 			((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && !m_interleaveReadWriteComponents) ||
1371 			((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && m_interleaveReadWriteComponents);
1372 
1373 		VkBool32 stencilTestEnable =
1374 			((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && !m_interleaveReadWriteComponents) ||
1375 			((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && m_interleaveReadWriteComponents);
1376 
1377 		const auto stencilFrontOpState	= makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_REPLACE, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_NEVER, 0xFFu, 0xFFu, 0u);
1378 		const auto stencilBackOpState	= makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_REPLACE, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
1379 
1380 		const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
1381 		{
1382 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,							// VkStructureType							sType
1383 			DE_NULL,																			// const void*								pNext
1384 			0u,																					// VkPipelineDepthStencilStateCreateFlags	flags
1385 			depthTestEnable,																	// VkBool32									depthTestEnable
1386 			depthTestEnable,																	// VkBool32									depthWriteEnable
1387 			VK_COMPARE_OP_ALWAYS,																// VkCompareOp								depthCompareOp
1388 			DE_FALSE,																			// VkBool32									depthBoundsTestEnable
1389 			stencilTestEnable,																	// VkBool32									stencilTestEnable
1390 			stencilFrontOpState,																// VkStencilOpState							front
1391 			stencilBackOpState,																	// VkStencilOpState							back
1392 			0.0f,																				// float									minDepthBounds
1393 			1.0f,																				// float									maxDepthBounds;
1394 		};
1395 
1396 		std::vector<VkDynamicState> dynamicStates;
1397 		if (m_pipelineStateMode != PipelineStateMode::STATIC)
1398 			dynamicStates.push_back(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
1399 
1400 		const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
1401 		{
1402 			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
1403 			nullptr,
1404 			0u,
1405 			de::sizeU32(dynamicStates),
1406 			de::dataOrNull(dynamicStates),
1407 		};
1408 
1409 		if (m_useMaintenance5)
1410 			m_graphicsPipeline.setPipelineCreateFlags2(translateCreateFlag(m_params.pipelineCreateFlags));
1411 
1412 		m_graphicsPipeline.setDynamicState(&dynamicStateInfo)
1413 						  .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
1414 						  .setDefaultDepthStencilState()
1415 						  .setDefaultRasterizationState()
1416 						  .setDefaultMultisampleState()
1417 						  .setupVertexInputState(&vertexInputStateParams)
1418 						  .setupPreRasterizationShaderState(viewports,
1419 														scissors,
1420 														m_preRasterizationStatePipelineLayout,
1421 														*m_renderPass,
1422 														0u,
1423 														m_vertexShaderModule)
1424 						  .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule, &depthStencilStateCreateInfo)
1425 						  .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1426 						  .buildPipeline();
1427 
1428 	}
1429 
1430 	// Create vertex buffer
1431 	{
1432 		const VkDeviceSize			vertexBufferSize	= (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
1433 		const VkBufferCreateInfo	vertexBufferParams	=
1434 		{
1435 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1436 			DE_NULL,									// const void*			pNext;
1437 			0u,											// VkBufferCreateFlags	flags;
1438 			vertexBufferSize,							// VkDeviceSize			size;
1439 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1440 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1441 			1u,											// deUint32				queueFamilyIndexCount;
1442 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1443 		};
1444 
1445 		DE_ASSERT(vertexBufferSize > 0);
1446 
1447 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
1448 		m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
1449 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1450 
1451 		// Load vertices into vertex buffer
1452 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
1453 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1454 	}
1455 
1456 	// Create command buffer
1457 	{
1458 		std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
1459 
1460 		for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1461 		{
1462 			preAttachmentBarriers[imgNdx].sType								= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;								// VkStructureType			sType;
1463 			preAttachmentBarriers[imgNdx].pNext								= DE_NULL;																// const void*				pNext;
1464 			preAttachmentBarriers[imgNdx].srcAccessMask						= VK_ACCESS_TRANSFER_WRITE_BIT;																	// VkAccessFlags			srcAccessMask;
1465 			preAttachmentBarriers[imgNdx].dstAccessMask						= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;	// VkAccessFlags			dstAccessMask;
1466 			preAttachmentBarriers[imgNdx].oldLayout							= m_imageLayout;														// VkImageLayout			oldLayout;
1467 			preAttachmentBarriers[imgNdx].newLayout							= m_imageLayout;														// VkImageLayout			newLayout;
1468 			preAttachmentBarriers[imgNdx].srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;												// deUint32					srcQueueFamilyIndex;
1469 			preAttachmentBarriers[imgNdx].dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;												// deUint32					dstQueueFamilyIndex;
1470 			preAttachmentBarriers[imgNdx].image								= **m_dsImages[imgNdx];													// VkImage					image;
1471 			preAttachmentBarriers[imgNdx].subresourceRange.aspectMask		= getAspectFlags(m_imageFormat);										// VkImageSubresourceRange	subresourceRange;
1472 			preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel		= 0u;
1473 			preAttachmentBarriers[imgNdx].subresourceRange.levelCount		= 1u;
1474 			preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer	= 0u;
1475 			preAttachmentBarriers[imgNdx].subresourceRange.layerCount		= 1u;
1476 		}
1477 
1478 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1479 
1480 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
1481 			0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]);
1482 
1483 		// Do not clear the color attachments as we are using the texture as color attachment.
1484 		m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), 0u, DE_NULL);
1485 
1486 		m_graphicsPipeline.bind(*m_cmdBuffer);
1487 
1488 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
1489 
1490 		const VkDeviceSize vertexBufferOffset = 0;
1491 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1492 
1493 		if (m_pipelineStateMode != PipelineStateMode::STATIC)
1494 			vk.cmdSetAttachmentFeedbackLoopEnableEXT(*m_cmdBuffer, testModeToAspectFlags(m_imageAspectTestMode));
1495 
1496 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
1497 
1498 		m_renderPass.end(vk, *m_cmdBuffer);
1499 		endCommandBuffer(vk, *m_cmdBuffer);
1500 	}
1501 }
1502 
verifyImage(void)1503 tcu::TestStatus AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::verifyImage(void)
1504 {
1505 	const tcu::TextureFormat	tcuFormat		= getSizeCompatibleTcuTextureFormat(m_imageFormat);
1506 	const bool					isDepth			= (!m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)) ||
1507 												   (m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT));
1508 	const bool					isStencil		= (!m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) ||
1509 												   (m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT));
1510 	// ImageSamplingInstance::verifyImage() doesn't support stencil sampling.
1511 	if (!m_useImageAsColorOrDSAttachment && !isStencil)
1512 		return ImageSamplingInstance::verifyImage();
1513 
1514 	const tcu::Vec4	fThreshold (0.005f);
1515 	const tcu::UVec4 uThreshold (0u); // Due to unsigned normalized fixed-point integers conversion to floats and viceversa.
1516 	tcu::UVec2 renderSize = tcu::UVec2({ (unsigned)m_imageSize.x(), (unsigned)m_imageSize.y() });
1517 
1518 	de::MovePtr<tcu::TextureLevel> referenceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(tcuFormat,
1519 																							  m_imageSize.x(),
1520 																							  m_imageSize.y(),
1521 																							  m_imageSize.z()));
1522 
1523 	for (int z = 0; z < m_imageSize.z(); z++)
1524 		for (int y = 0; y < m_imageSize.y(); y++)
1525 			for (int x = 0; x < m_imageSize.x(); x++)
1526 			{
1527 				if (isDepth)
1528 				{
1529 					float depth = 0.0f;
1530 					if (m_interleaveReadWriteComponents)
1531 					{
1532 						int stencil = 1 + m_texture->getLevel(0, 0).getPixStencil(x, y, z);
1533 						depth = static_cast<float>(stencil) / 255.0f;
1534 					}
1535 					else
1536 					{
1537 						if (m_useDifferentAreasSampleWrite && x < m_imageSize.x() / 2)
1538 							depth = m_texture->getLevel(0, 0).getPixDepth(x + (m_imageSize.x() / 2), y, z) + 0.1f;
1539 						else
1540 							depth = m_texture->getLevel(0, 0).getPixDepth(x, y, z);
1541 
1542 						if (!m_useDifferentAreasSampleWrite)
1543 							depth += 0.1f;
1544 					}
1545 
1546 					depth = deFloatClamp(depth, 0.0f, 1.0f);
1547 					referenceTextureLevel->getAccess().setPixDepth(depth, x, y, z);
1548 				}
1549 				if (isStencil)
1550 				{
1551 					int stencil = 0;
1552 					if (m_interleaveReadWriteComponents)
1553 					{
1554 						float depth = m_texture->getLevel(0, 0).getPixDepth(x, y, z) + 0.1f;
1555 						stencil = static_cast<int>(depth * 255.0f);
1556 					}
1557 					else
1558 					{
1559 						if (m_useDifferentAreasSampleWrite && x < m_imageSize.x() / 2)
1560 							stencil = 1 + m_texture->getLevel(0, 0).getPixStencil(x + (m_imageSize.x() / 2), y, z);
1561 						else
1562 							stencil = m_texture->getLevel(0, 0).getPixStencil(x, y, z);
1563 
1564 						if (!m_useDifferentAreasSampleWrite)
1565 							stencil += 1;
1566 
1567 						stencil = deClamp32(stencil, 0, 255);
1568 					}
1569 
1570 					referenceTextureLevel->getAccess().setPixStencil(stencil, x, y, z);
1571 				}
1572 			}
1573 
1574 	for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1575 	{
1576 		if (isDepth)
1577 		{
1578 			// Read back result image
1579 			de::MovePtr<tcu::TextureLevel>			resultTexture			(readDepthAttachment(m_context.getDeviceInterface(),
1580 																				m_context.getDevice(),
1581 																				m_context.getUniversalQueue(),
1582 																				m_context.getUniversalQueueFamilyIndex(),
1583 																				m_context.getDefaultAllocator(),
1584 																				**m_dsImages[imgNdx],
1585 																				m_imageFormat,
1586 																				renderSize,
1587 																				VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1588 
1589 			const tcu::ConstPixelBufferAccess		result	= resultTexture->getAccess();
1590 			const tcu::Sampler::DepthStencilMode	mode				= tcu::Sampler::MODE_DEPTH;
1591 			const tcu::ConstPixelBufferAccess		depthResult			= tcu::getEffectiveDepthStencilAccess(result, mode);
1592 			const tcu::ConstPixelBufferAccess		expectedResult		= tcu::getEffectiveDepthStencilAccess(referenceTextureLevel->getAccess(), mode);
1593 			bool									isIntegerFormat		= isUintFormat(mapTextureFormat(depthResult.getFormat())) || isIntFormat(mapTextureFormat(depthResult.getFormat()));
1594 
1595 			if (!isIntegerFormat)
1596 			{
1597 				if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1598 					return tcu::TestStatus::fail("Failed depth");
1599 			}
1600 			else
1601 			{
1602 				if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, depthResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1603 					return tcu::TestStatus::fail("Failed depth");
1604 			}
1605 		}
1606 
1607 		if (isStencil)
1608 		{
1609 			// Read back result image
1610 			de::MovePtr<tcu::TextureLevel>			resultTexture			(readStencilAttachment(m_context.getDeviceInterface(),
1611 																				m_context.getDevice(),
1612 																				m_context.getUniversalQueue(),
1613 																				m_context.getUniversalQueueFamilyIndex(),
1614 																				m_context.getDefaultAllocator(),
1615 																				**m_dsImages[imgNdx],
1616 																				m_imageFormat,
1617 																				renderSize,
1618 																				VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1619 
1620 			const tcu::ConstPixelBufferAccess		result	= resultTexture->getAccess();
1621 			const tcu::Sampler::DepthStencilMode	mode				= tcu::Sampler::MODE_STENCIL;
1622 			const tcu::ConstPixelBufferAccess		stencilResult		= tcu::getEffectiveDepthStencilAccess(result, mode);
1623 			const tcu::ConstPixelBufferAccess		expectedResult		= tcu::getEffectiveDepthStencilAccess(referenceTextureLevel->getAccess(), mode);
1624 			bool									isIntegerFormat		= isUintFormat(mapTextureFormat(stencilResult.getFormat())) || isIntFormat(mapTextureFormat(stencilResult.getFormat()));
1625 
1626 			if (!isIntegerFormat)
1627 			{
1628 				if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1629 					return tcu::TestStatus::fail("Failed stencil");
1630 			}
1631 			else
1632 			{
1633 				if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", expectedResult, stencilResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1634 					return tcu::TestStatus::fail("Failed stencil");
1635 			}
1636 		}
1637 	}
1638 
1639 	return tcu::TestStatus::pass("Pass");
1640 }
1641 
iterate(void)1642 tcu::TestStatus AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::iterate (void)
1643 {
1644 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1645 	const VkDevice				vkDevice	= m_context.getDevice();
1646 	const VkQueue				queue		= m_context.getUniversalQueue();
1647 
1648 	setup();
1649 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1650 
1651 	return verifyImage();
1652 }
1653 
verifyImage(void)1654 tcu::TestStatus AttachmentFeedbackLoopLayoutImageSamplingInstance::verifyImage(void)
1655 {
1656 	if (!m_useImageAsColorOrDSAttachment)
1657 		return ImageSamplingInstance::verifyImage();
1658 
1659 	const tcu::Vec4	fThreshold (0.01f);
1660 	const tcu::UVec4 uThreshold (1u);
1661 	tcu::UVec2 renderSize = tcu::UVec2({ (unsigned)m_imageSize.x(), (unsigned)m_imageSize.y() });
1662 
1663 	const tcu::TextureFormat	tcuFormat		= getSizeCompatibleTcuTextureFormat(m_imageFormat);
1664 	de::MovePtr<tcu::TextureLevel> referenceTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(tcuFormat,
1665 																												m_imageSize.x(),
1666 																												m_imageSize.y(),
1667 																												m_imageSize.z()));
1668 
1669 	for (int z = 0; z < m_imageSize.z(); z++)
1670 		for (int y = 0; y < m_imageSize.y(); y++)
1671 			for (int x = 0; x < m_imageSize.x(); x++)
1672 			{
1673 				tcu::Vec4 color = tcu::Vec4(1.0f);
1674 
1675 				if (m_useDifferentAreasSampleWrite && (x < m_imageSize.x() / 2))
1676 					color = m_texture->getLevel(0, 0).getPixel(x + (m_imageSize.x() / 2), y, z) + tcu::Vec4(0.1f);
1677 				else
1678 					color = m_texture->getLevel(0, 0).getPixel(x, y, z);
1679 
1680 				if (!m_useDifferentAreasSampleWrite)
1681 					color += tcu::Vec4(0.1f);
1682 
1683 				if (m_interleaveReadWriteComponents)
1684 				{
1685 					tcu::Vec4 sampledColor = m_texture->getLevel(0, 0).getPixel(x, y, z);
1686 					color.x() = color.y();
1687 					color.y() = sampledColor.y();
1688 					color.z() = color.w();
1689 					color.w() = sampledColor.w();
1690 				}
1691 
1692 				color.x() = deFloatClamp(color.x(), 0.0f, 1.0f);
1693 				color.y() = deFloatClamp(color.y(), 0.0f, 1.0f);
1694 				color.z() = deFloatClamp(color.z(), 0.0f, 1.0f);
1695 				color.w() = deFloatClamp(color.w(), 0.0f, 1.0f);
1696 
1697 				referenceTextureLevel->getAccess().setPixel(color, x, y, z);
1698 			}
1699 
1700 	for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1701 	{
1702 		// Read back result image
1703 		de::MovePtr<tcu::TextureLevel>		resultTexture			(readColorAttachment(m_context.getDeviceInterface(),
1704 																						 m_context.getDevice(),
1705 																						 m_context.getUniversalQueue(),
1706 																						 m_context.getUniversalQueueFamilyIndex(),
1707 																						 m_context.getDefaultAllocator(),
1708 																						 **m_colorImages[imgNdx],
1709 																						 m_colorFormat,
1710 																						 renderSize,
1711 																						 vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1712 		const tcu::ConstPixelBufferAccess	result	= resultTexture->getAccess();
1713 		const bool							isIntegerFormat	= isUintFormat(m_imageFormat) || isIntFormat(m_imageFormat);
1714 
1715 		if (!isIntegerFormat)
1716 		{
1717 			if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceTextureLevel->getAccess(), result, fThreshold, tcu::COMPARE_LOG_RESULT))
1718 				return tcu::TestStatus::fail("Failed color");
1719 		}
1720 		else
1721 		{
1722 			if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceTextureLevel->getAccess(), result, uThreshold, tcu::COMPARE_LOG_RESULT))
1723 				return tcu::TestStatus::fail("Failed color");
1724 		}
1725 	}
1726 
1727 	return tcu::TestStatus::pass("Pass");
1728 }
1729 
~AttachmentFeedbackLoopLayoutImageSamplingInstance(void)1730 AttachmentFeedbackLoopLayoutImageSamplingInstance::~AttachmentFeedbackLoopLayoutImageSamplingInstance (void)
1731 {
1732 }
1733 
iterate(void)1734 tcu::TestStatus AttachmentFeedbackLoopLayoutImageSamplingInstance::iterate (void)
1735 {
1736 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1737 	const VkDevice				vkDevice	= m_context.getDevice();
1738 	const VkQueue				queue		= m_context.getUniversalQueue();
1739 
1740 	setup();
1741 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1742 
1743 	return verifyImage();
1744 }
1745 
1746 class AttachmentFeedbackLoopLayoutSamplerTest : public vkt::TestCase {
1747 public:
1748 										AttachmentFeedbackLoopLayoutSamplerTest			(tcu::TestContext&				testContext,
1749 																						 vk::PipelineConstructionType	pipelineConstructionType,
1750 																						 const char*					name,
1751 																						 SamplerViewType				imageViewType,
1752 																						 VkFormat						imageFormat,
1753 																						 int							imageSize,
1754 																						 VkDescriptorType				imageDescriptorType,
1755 																						 float							samplerLod,
1756 																						 TestMode						testMode,
1757 																						 ImageAspectTestMode			imageAspectTestMode,
1758 																						 bool							interleaveReadWriteComponents,
1759 																						 PipelineStateMode				pipelineStateMode,
1760 																						 bool							useMaintenance5);
~AttachmentFeedbackLoopLayoutSamplerTest(void)1761 	virtual								~AttachmentFeedbackLoopLayoutSamplerTest		(void) {}
1762 
1763 	virtual ImageSamplingInstanceParams	getImageSamplingInstanceParams	(SamplerViewType	imageViewType,
1764 																		 VkFormat			imageFormat,
1765 																		 int				imageSize,
1766 																		 VkDescriptorType	imageDescriptorType,
1767 																		 float				samplerLod) const;
1768 
1769 	virtual void						initPrograms					(SourceCollections& sourceCollections) const;
1770 	virtual void						checkSupport					(Context& context) const;
1771 	virtual TestInstance*				createInstance					(Context& context) const;
1772 	virtual tcu::UVec2					getRenderSize					(SamplerViewType viewType) const;
1773 	virtual std::vector<Vertex4Tex4>	createVertices					(void) const;
1774 	virtual VkSamplerCreateInfo			getSamplerCreateInfo			(void) const;
1775 	virtual VkComponentMapping			getComponentMapping				(void) const;
1776 
1777 	static std::string					getGlslSamplerType				(const tcu::TextureFormat& format, SamplerViewType type);
1778 	static tcu::IVec3					getImageSize					(SamplerViewType viewType, int size);
1779 	static int							getArraySize					(SamplerViewType viewType);
1780 
1781 	static std::string					getGlslSampler (const tcu::TextureFormat& format, VkImageViewType type, VkDescriptorType samplingType, int imageCount);
1782 	static std::string					getGlslTextureType (const tcu::TextureFormat& format, VkImageViewType type);
1783 	static std::string					getGlslSamplerDecl (int imageCount);
1784 	static std::string					getGlslTextureDecl (int imageCount);
1785 
1786 protected:
1787 	vk::PipelineConstructionType		m_pipelineConstructionType;
1788 	SamplerViewType						m_imageViewType;
1789 	VkFormat							m_imageFormat;
1790 	int									m_imageSize;
1791 	VkDescriptorType					m_imageDescriptorType;
1792 	float								m_samplerLod;
1793 	TestMode							m_testMode;
1794 	ImageAspectTestMode					m_imageAspectTestMode;
1795 	bool								m_interleaveReadWriteComponents;
1796 	PipelineStateMode					m_pipelineStateMode;
1797 	bool								m_useMaintenance5;
1798 };
1799 
1800 // AttachmentFeedbackLoopLayoutSamplerTest
1801 
AttachmentFeedbackLoopLayoutSamplerTest(tcu::TestContext& testContext, vk::PipelineConstructionType pipelineConstructionType, const char* name, SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, VkDescriptorType imageDescriptorType, float samplerLod, TestMode testMode, ImageAspectTestMode imageAspectTestMode, bool interleaveReadWriteComponents, PipelineStateMode pipelineStateMode, bool useMaintenance5)1802 AttachmentFeedbackLoopLayoutSamplerTest::AttachmentFeedbackLoopLayoutSamplerTest	(tcu::TestContext&				testContext,
1803 																					 vk::PipelineConstructionType	pipelineConstructionType,
1804 																					 const char*					name,
1805 																					 SamplerViewType				imageViewType,
1806 																					 VkFormat						imageFormat,
1807 																					 int							imageSize,
1808 																					 VkDescriptorType				imageDescriptorType,
1809 																					 float							samplerLod,
1810 																					 TestMode						testMode,
1811 																					 ImageAspectTestMode			imageAspectTestMode,
1812 																					 bool							interleaveReadWriteComponents,
1813 																					 PipelineStateMode				pipelineStateMode,
1814 																					 bool							useMaintenance5)
1815 	: vkt::TestCase					(testContext, name)
1816 	, m_pipelineConstructionType	(pipelineConstructionType)
1817 	, m_imageViewType				(imageViewType)
1818 	, m_imageFormat					(imageFormat)
1819 	, m_imageSize					(imageSize)
1820 	, m_imageDescriptorType			(imageDescriptorType)
1821 	, m_samplerLod					(samplerLod)
1822 	, m_testMode					(testMode)
1823 	, m_imageAspectTestMode			(imageAspectTestMode)
1824 	, m_interleaveReadWriteComponents	(interleaveReadWriteComponents)
1825 	, m_pipelineStateMode			(pipelineStateMode)
1826 	, m_useMaintenance5				(useMaintenance5)
1827 {
1828 }
1829 
getImageSamplingInstanceParams(SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, VkDescriptorType imageDescriptorType, float samplerLod) const1830 ImageSamplingInstanceParams AttachmentFeedbackLoopLayoutSamplerTest::getImageSamplingInstanceParams (SamplerViewType	imageViewType,
1831 																									 VkFormat			imageFormat,
1832 																									 int				imageSize,
1833 																									 VkDescriptorType	imageDescriptorType,
1834 																									 float				samplerLod) const
1835 {
1836 	const tcu::UVec2				renderSize			= getRenderSize(imageViewType);
1837 	const std::vector<Vertex4Tex4>	vertices			= createVertices();
1838 	const VkSamplerCreateInfo		samplerParams		= getSamplerCreateInfo();
1839 	const VkComponentMapping		componentMapping	= getComponentMapping();
1840 
1841 	VkImageAspectFlags				imageAspect			= 0u;
1842 	VkPipelineCreateFlags			pipelineCreateFlags = 0u;
1843 
1844 	if (!isCompressedFormat(imageFormat))
1845 	{
1846 		if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR)
1847 		{
1848 			DE_ASSERT(!tcu::hasDepthComponent(mapVkFormat(imageFormat).order) &&
1849 					  !tcu::hasStencilComponent(mapVkFormat(imageFormat).order));
1850 		}
1851 		else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH)
1852 			DE_ASSERT(tcu::hasDepthComponent(mapVkFormat(imageFormat).order));
1853 		else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL)
1854 			DE_ASSERT(tcu::hasStencilComponent(mapVkFormat(imageFormat).order));
1855 
1856 		imageAspect			= testModeToAspectFlags(m_imageAspectTestMode);
1857 		pipelineCreateFlags	= getStaticPipelineCreateFlags(imageAspect, m_pipelineStateMode);
1858 	}
1859 	else
1860 	{
1861 		imageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
1862 	}
1863 
1864 	const VkImageSubresourceRange	subresourceRange	=
1865 	{
1866 		imageAspect,										// VkImageAspectFlags	aspectMask;
1867 		0u,													// deUint32				baseMipLevel;
1868 		1u,													// deUint32				mipLevels;
1869 		0u,													// deUint32				baseArrayLayer;
1870 		(deUint32)getArraySize(imageViewType)				// deUint32				arraySize;
1871 	};
1872 
1873 	return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat,
1874 									   getImageSize(imageViewType, imageSize),
1875 									   getArraySize(imageViewType),
1876 									   componentMapping, subresourceRange,
1877 									   samplerParams, samplerLod, vertices, false,
1878 									   imageDescriptorType, 1u, ALLOCATION_KIND_SUBALLOCATED,
1879 									   vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT,
1880 									   pipelineCreateFlags);
1881 }
1882 
checkSupport(Context& context) const1883 void AttachmentFeedbackLoopLayoutSamplerTest::checkSupport (Context& context) const
1884 {
1885 	const auto&	vki				= context.getInstanceInterface();
1886 	const auto	physicalDevice	= context.getPhysicalDevice();
1887 
1888 	checkPipelineConstructionRequirements(vki, physicalDevice, m_pipelineConstructionType);
1889 
1890 	context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
1891 
1892 	if (m_useMaintenance5)
1893 		context.requireDeviceFunctionality("VK_KHR_maintenance5");
1894 
1895 	if (m_pipelineStateMode != PipelineStateMode::STATIC || isConstructionTypeShaderObject(m_pipelineConstructionType))
1896 		context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_dynamic_state");
1897 
1898 	const auto imgParams = getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType, m_samplerLod);
1899 	checkSupportImageSamplingInstance(context, imgParams);
1900 
1901 	if (m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL) // Image as color or DS attachment.
1902 	{
1903 		VkFormatProperties formatProps;
1904 		vki.getPhysicalDeviceFormatProperties(physicalDevice, imgParams.imageFormat, &formatProps);
1905 
1906 		const auto					attachmentFormatFeature	= isDepthStencilFormat(imgParams.imageFormat)
1907 															? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
1908 															: VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1909 		const VkFormatFeatureFlags	neededFeatures			= attachmentFormatFeature
1910 															| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
1911 															| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
1912 															| VK_FORMAT_FEATURE_TRANSFER_DST_BIT
1913 															;
1914 
1915 		if ((formatProps.optimalTilingFeatures & neededFeatures) != neededFeatures)
1916 		{
1917 			std::ostringstream msg;
1918 			msg << "Format does not support required features: 0x" << std::hex << neededFeatures;
1919 			TCU_THROW(NotSupportedError, msg.str());
1920 		}
1921 
1922 		if ((!m_interleaveReadWriteComponents && m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL) ||
1923 			(m_interleaveReadWriteComponents && m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH))
1924 			context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
1925 	}
1926 }
1927 
getGlslTextureType(const tcu::TextureFormat& format, VkImageViewType type)1928 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureType (const tcu::TextureFormat& format, VkImageViewType type)
1929 {
1930 	std::ostringstream textureType;
1931 
1932 	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1933 		textureType << "u";
1934 	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1935 		textureType << "i";
1936 
1937 	switch (type)
1938 	{
1939 		case VK_IMAGE_VIEW_TYPE_1D:
1940 			textureType << "texture1D";
1941 			break;
1942 
1943 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1944 			textureType << "texture1DArray";
1945 			break;
1946 
1947 		case VK_IMAGE_VIEW_TYPE_2D:
1948 			textureType << "texture2D";
1949 			break;
1950 
1951 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1952 			textureType << "texture2DArray";
1953 			break;
1954 
1955 		case VK_IMAGE_VIEW_TYPE_3D:
1956 			textureType << "texture3D";
1957 			break;
1958 
1959 		case VK_IMAGE_VIEW_TYPE_CUBE:
1960 			textureType << "textureCube";
1961 			break;
1962 
1963 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1964 			textureType << "textureCubeArray";
1965 			break;
1966 
1967 		default:
1968 			DE_FATAL("Unknown image view type");
1969 	}
1970 
1971 	return textureType.str();
1972 }
1973 
getGlslSamplerDecl(int imageCount)1974 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerDecl (int imageCount)
1975 {
1976 	std::ostringstream samplerArray;
1977 	samplerArray << "texSamplers[" << imageCount << "]";
1978 
1979 	return imageCount > 1 ? samplerArray.str() : "texSampler";
1980 }
1981 
getGlslTextureDecl(int imageCount)1982 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureDecl (int imageCount)
1983 {
1984 	std::ostringstream textureArray;
1985 	textureArray << "texImages[" << imageCount << "]";
1986 
1987 	return imageCount > 1 ? textureArray.str() : "texImage";
1988 }
1989 
getGlslSampler(const tcu::TextureFormat& format, VkImageViewType type, VkDescriptorType samplingType, int imageCount)1990 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSampler (const tcu::TextureFormat& format, VkImageViewType type, VkDescriptorType samplingType, int imageCount)
1991 {
1992 	std::string texSampler	= imageCount > 1 ? "texSamplers[i]" : "texSampler";
1993 	std::string texImage	= imageCount > 1 ? "texImages[i]" : "texImage";
1994 
1995 	switch (samplingType)
1996 	{
1997 		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1998 			return getGlslSamplerType(format, type) + "(" + texImage + ", texSampler)";
1999 		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2000 		default:
2001 			return texSampler;
2002 	}
2003 }
2004 
initPrograms(SourceCollections& sourceCollections) const2005 void AttachmentFeedbackLoopLayoutSamplerTest::initPrograms (SourceCollections& sourceCollections) const
2006 {
2007 	std::ostringstream				vertexSrc;
2008 	std::ostringstream				fragmentSrc;
2009 	const char*						texCoordSwizzle	= DE_NULL;
2010 	const VkFormat					vkFormat = m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL ? VK_FORMAT_S8_UINT : m_imageFormat;
2011 	const tcu::TextureFormat		format			= (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(vkFormat))
2012 																						  : mapVkFormat(vkFormat);
2013 	tcu::Vec4						lookupScale;
2014 	tcu::Vec4						lookupBias;
2015 
2016 	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
2017 
2018 	switch (m_imageViewType)
2019 	{
2020 		case VK_IMAGE_VIEW_TYPE_1D:
2021 			texCoordSwizzle = "x";
2022 			break;
2023 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2024 		case VK_IMAGE_VIEW_TYPE_2D:
2025 			texCoordSwizzle = "xy";
2026 			break;
2027 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2028 		case VK_IMAGE_VIEW_TYPE_3D:
2029 		case VK_IMAGE_VIEW_TYPE_CUBE:
2030 			texCoordSwizzle = "xyz";
2031 			break;
2032 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2033 			texCoordSwizzle = "xyzw";
2034 			break;
2035 		default:
2036 			DE_ASSERT(false);
2037 			break;
2038 	}
2039 
2040 	vertexSrc << "#version 440\n"
2041 			  << "layout(location = 0) in vec4 position;\n"
2042 			  << "layout(location = 1) in vec4 texCoords;\n"
2043 			  << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
2044 			  << "out gl_PerVertex {\n"
2045 			  << "	vec4 gl_Position;\n"
2046 			  << "};\n"
2047 			  << "void main (void)\n"
2048 			  << "{\n"
2049 			  << "	gl_Position = position;\n"
2050 			  << "	vtxTexCoords = texCoords;\n"
2051 			  << "}\n";
2052 
2053 	fragmentSrc << "#version 440\n";
2054 
2055 	if ((m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL) ||
2056 		(m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_interleaveReadWriteComponents))
2057 	{
2058 		fragmentSrc << "#extension GL_ARB_shader_stencil_export: require\n";
2059 	}
2060 
2061 	switch (m_imageDescriptorType)
2062 	{
2063 		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2064 			fragmentSrc
2065 				<< "layout(set = 0, binding = 0) uniform highp sampler texSampler;\n"
2066 				<< "layout(set = 0, binding = 1) uniform highp " << getGlslTextureType(format, m_imageViewType) << " " << getGlslTextureDecl(1u) << ";\n";
2067 			break;
2068 		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2069 		default:
2070 			fragmentSrc
2071 				<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " " << getGlslSamplerDecl(1u) << ";\n";
2072 	}
2073 
2074 	if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR || m_testMode == TEST_MODE_READ_ONLY)
2075 		fragmentSrc	<< "layout(location = 0) out highp vec4 fragColor;\n";
2076 
2077 	fragmentSrc	<< "layout(location = 0) in highp vec4 vtxTexCoords;\n"
2078 				<< "void main (void)\n"
2079 				<< "{\n";
2080 
2081 	if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode != TEST_MODE_READ_ONLY)
2082 		fragmentSrc	<< "	uvec4 read_data = ";
2083 	else
2084 		fragmentSrc	<< "	vec4 read_data = ";
2085 
2086 	if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2087 	{
2088 		fragmentSrc << "vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
2089 
2090 		fragmentSrc << "	read_data.x = ";
2091 		if (m_samplerLod > 0.0f)
2092 		{
2093 			DE_ASSERT(m_imageViewType.isNormalized());
2094 			fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ").x";
2095 		}
2096 		else
2097 		{
2098 			if (m_imageViewType.isNormalized())
2099 				fragmentSrc << "texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ").x" << std::fixed;
2100 			else
2101 				fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ", 0).x" << std::fixed;
2102 		}
2103 
2104 		fragmentSrc << " + 0.1f;\n";
2105 	}
2106 	else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode == TEST_MODE_READ_ONLY)
2107 	{
2108 		if (m_samplerLod > 0.0f)
2109 		{
2110 			DE_ASSERT(m_imageViewType.isNormalized());
2111 			fragmentSrc << "vec4(textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ").x / 255.0f, 0.0f, 0.0f, 1.0f)";
2112 		}
2113 		else
2114 		{
2115 			if (m_imageViewType.isNormalized())
2116 				fragmentSrc << "vec4(texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ").x / 255.0f, 0.0f, 0.0f, 1.0f)" << std::fixed;
2117 			else
2118 				fragmentSrc << "vec4(textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ", 0).x / 255.0f, 0.0f, 0.0f, 1.0f)" << std::fixed;
2119 		}
2120 
2121 		fragmentSrc << ";\n";
2122 	}
2123 	else
2124 	{
2125 		if (m_samplerLod > 0.0f)
2126 		{
2127 			DE_ASSERT(m_imageViewType.isNormalized());
2128 			fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ")";
2129 		}
2130 		else
2131 		{
2132 			if (m_imageViewType.isNormalized())
2133 				fragmentSrc << "texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
2134 			else
2135 				fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u) << ", vtxTexCoords." << texCoordSwizzle << ", 0)" << std::fixed;
2136 		}
2137 
2138 		if (m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2139 		{
2140 			if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL)
2141 				fragmentSrc << " + uvec4(1u, 0u, 0u, 0)";
2142 			else
2143 				fragmentSrc << " + vec4(0.1f)";
2144 		}
2145 
2146 		fragmentSrc << ";\n";
2147 	}
2148 
2149 	if (m_interleaveReadWriteComponents)
2150 	{
2151 		if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR)
2152 		{
2153 			fragmentSrc << "	fragColor = vec4(1.0f);\n"
2154 						<< "	fragColor.x = read_data.y;\n"
2155 						<< "	fragColor.z = read_data.w;\n";
2156 		}
2157 		else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH)
2158 		{
2159 			fragmentSrc << "	gl_FragStencilRefARB = int(clamp(read_data.x * 255.0f, 0.0f, 255.0f));\n";
2160 		}
2161 		else
2162 		{
2163 			fragmentSrc << "	gl_FragDepth = clamp(float(read_data.x) / 255.0f, 0.0f, 1.0f);\n";
2164 		}
2165 	}
2166 	else
2167 	{
2168 		if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2169 		{
2170 			fragmentSrc << "	gl_FragDepth = clamp(read_data.x, 0.0f, 1.0f);\n";
2171 		}
2172 		else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2173 		{
2174 			fragmentSrc << "	gl_FragStencilRefARB = int(clamp(read_data.x, 0u, 255u));\n";
2175 		}
2176 		else
2177 		{
2178 			fragmentSrc << "	fragColor = read_data;\n";
2179 		}
2180 	}
2181 
2182 	fragmentSrc	<< "}\n";
2183 
2184 	sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
2185 	sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
2186 }
2187 
createInstance(Context& context) const2188 TestInstance* AttachmentFeedbackLoopLayoutSamplerTest::createInstance (Context& context) const
2189 {
2190 	const bool useImageAsColorOrDSAttachment	= m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL;
2191 	const bool useDifferentAreasSampleWrite		= m_testMode == TEST_MODE_READ_WRITE_DIFFERENT_AREAS;
2192 
2193 	if (m_imageAspectTestMode != IMAGE_ASPECT_TEST_COLOR && useImageAsColorOrDSAttachment)
2194 		return new AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType, m_samplerLod), useImageAsColorOrDSAttachment, useDifferentAreasSampleWrite, m_interleaveReadWriteComponents, m_imageAspectTestMode, m_pipelineStateMode, m_useMaintenance5);
2195 	return new AttachmentFeedbackLoopLayoutImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType, m_samplerLod), useImageAsColorOrDSAttachment, useDifferentAreasSampleWrite, m_interleaveReadWriteComponents, m_imageAspectTestMode, m_pipelineStateMode, m_useMaintenance5);
2196 }
2197 
getRenderSize(SamplerViewType viewType) const2198 tcu::UVec2 AttachmentFeedbackLoopLayoutSamplerTest::getRenderSize (SamplerViewType viewType) const
2199 {
2200 	if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
2201 	{
2202 		return tcu::UVec2(16u, 16u);
2203 	}
2204 	else
2205 	{
2206 		return tcu::UVec2(16u * 3u, 16u * 2u);
2207 	}
2208 }
2209 
createFullscreenQuadArray(vk::VkImageViewType viewType, unsigned arraySize)2210 std::vector<Vertex4Tex4> createFullscreenQuadArray (vk::VkImageViewType viewType, unsigned arraySize)
2211 {
2212 	using tcu::Vec4;
2213 	std::vector<Vertex4Tex4>	verticesArray;
2214 
2215 	const Vertex4Tex4 lowerLeftVertex =
2216 	{
2217 		Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2218 		Vec4(0.0f, 0.0f, 0.0f, 0.0f)
2219 	};
2220 	const Vertex4Tex4 upperLeftVertex =
2221 	{
2222 		Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
2223 		Vec4(0.0f, 1.0f, 0.0f, 0.0f)
2224 	};
2225 	const Vertex4Tex4 lowerRightVertex =
2226 	{
2227 		Vec4(1.0f, -1.0f, 0.0f, 1.0f),
2228 		Vec4(1.0f, 0.0f, 0.0f, 0.0f)
2229 	};
2230 	const Vertex4Tex4 upperRightVertex =
2231 	{
2232 		Vec4(1.0f, 1.0f, 0.0f, 1.0f),
2233 		Vec4(1.0f, 1.0f, 0.0f, 0.0f)
2234 	};
2235 
2236 	for (unsigned arrayNdx = 0; arrayNdx < arraySize; arrayNdx++)
2237 	{
2238 		Vertex4Tex4 vertices[6] =
2239 		{
2240 			lowerLeftVertex,
2241 			upperLeftVertex,
2242 			lowerRightVertex,
2243 
2244 			upperLeftVertex,
2245 			lowerRightVertex,
2246 			upperRightVertex
2247 		};
2248 
2249 		for (int i = 0; i < 6; i++)
2250 		{
2251 			if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2252 			{
2253 				vertices[i].position.y() = (float)arrayNdx;
2254 				vertices[i].texCoord.y() = (float)arrayNdx;
2255 			}
2256 			else
2257 			{
2258 				vertices[i].position.z() = (float)arrayNdx;
2259 				vertices[i].texCoord.z() = (float)arrayNdx;
2260 			}
2261 			verticesArray.push_back(vertices[i]);
2262 		}
2263 	}
2264 
2265 	return verticesArray;
2266 }
2267 
createTestQuadAttachmentFeedbackLoopLayout(vk::VkImageViewType viewType)2268 std::vector<Vertex4Tex4> createTestQuadAttachmentFeedbackLoopLayout (vk::VkImageViewType viewType)
2269 {
2270 	std::vector<Vertex4Tex4> vertices;
2271 
2272 	switch (viewType)
2273 	{
2274 		case vk::VK_IMAGE_VIEW_TYPE_1D:
2275 		case vk::VK_IMAGE_VIEW_TYPE_2D:
2276 			vertices = createFullscreenQuad();
2277 			break;
2278 
2279 		case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2280 			vertices = createFullscreenQuadArray(viewType, 6u);
2281 			break;
2282 
2283 		case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2284 		case vk::VK_IMAGE_VIEW_TYPE_3D:
2285 		case vk::VK_IMAGE_VIEW_TYPE_CUBE:
2286 		case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2287 			vertices = createFullscreenQuadArray(viewType, 6u);
2288 			break;
2289 
2290 		default:
2291 			DE_ASSERT(false);
2292 			break;
2293 	}
2294 
2295 	return vertices;
2296 }
2297 
createVertices(void) const2298 std::vector<Vertex4Tex4> AttachmentFeedbackLoopLayoutSamplerTest::createVertices (void) const
2299 {
2300 	std::vector<Vertex4Tex4> vertices = m_testMode != TEST_MODE_READ_WRITE_DIFFERENT_AREAS ?
2301 		createTestQuadMosaic(m_imageViewType) :
2302 		createTestQuadAttachmentFeedbackLoopLayout(m_imageViewType);
2303 	for (unsigned int i = 0; i < vertices.size(); ++i) {
2304 		if (m_testMode == TEST_MODE_READ_WRITE_DIFFERENT_AREAS)
2305 		{
2306 			vertices[i].texCoord.x() = std::max(vertices[i].texCoord.x(), 0.5f);
2307 			vertices[i].position.x() = std::min(vertices[i].position.x(), 0.0f);
2308 		}
2309 		if (!m_imageViewType.isNormalized()) {
2310 			const float imageSize = static_cast<float>(m_imageSize);
2311 			for (int j = 0; j < tcu::Vec4::SIZE; ++j)
2312 				vertices[i].texCoord[j] *= imageSize;
2313 		}
2314 	}
2315 	return vertices;
2316 }
2317 
getSamplerCreateInfo(void) const2318 VkSamplerCreateInfo AttachmentFeedbackLoopLayoutSamplerTest::getSamplerCreateInfo (void) const
2319 {
2320 	const VkSamplerCreateInfo defaultSamplerParams =
2321 	{
2322 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,										// VkStructureType			sType;
2323 		DE_NULL,																	// const void*				pNext;
2324 		0u,																			// VkSamplerCreateFlags		flags;
2325 		VK_FILTER_NEAREST,															// VkFilter					magFilter;
2326 		VK_FILTER_NEAREST,															// VkFilter					minFilter;
2327 		VK_SAMPLER_MIPMAP_MODE_NEAREST,												// VkSamplerMipmapMode		mipmapMode;
2328 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,										// VkSamplerAddressMode		addressModeU;
2329 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,										// VkSamplerAddressMode		addressModeV;
2330 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,										// VkSamplerAddressMode		addressModeW;
2331 		0.0f,																		// float					mipLodBias;
2332 		VK_FALSE,																	// VkBool32					anisotropyEnable;
2333 		1.0f,																		// float					maxAnisotropy;
2334 		false,																		// VkBool32					compareEnable;
2335 		VK_COMPARE_OP_NEVER,														// VkCompareOp				compareOp;
2336 		0.0f,																		// float					minLod;
2337 		(m_imageViewType.isNormalized() ? 0.25f : 0.0f),							// float					maxLod;
2338 		getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat, false),	// VkBorderColor			borderColor;
2339 		!m_imageViewType.isNormalized(),											// VkBool32					unnormalizedCoordinates;
2340 	};
2341 
2342 	return defaultSamplerParams;
2343 }
2344 
getComponentMapping(void) const2345 VkComponentMapping AttachmentFeedbackLoopLayoutSamplerTest::getComponentMapping (void) const
2346 {
2347 	const VkComponentMapping	componentMapping	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
2348 	return componentMapping;
2349 }
2350 
getGlslSamplerType(const tcu::TextureFormat& format, SamplerViewType type)2351 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type)
2352 {
2353 	std::ostringstream samplerType;
2354 
2355 	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2356 		samplerType << "u";
2357 	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
2358 		samplerType << "i";
2359 
2360 	switch (type)
2361 	{
2362 		case VK_IMAGE_VIEW_TYPE_1D:
2363 			samplerType << "sampler1D";
2364 			break;
2365 
2366 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2367 			samplerType << "sampler1DArray";
2368 			break;
2369 
2370 		case VK_IMAGE_VIEW_TYPE_2D:
2371 			samplerType << "sampler2D";
2372 			break;
2373 
2374 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2375 			samplerType << "sampler2DArray";
2376 			break;
2377 
2378 		case VK_IMAGE_VIEW_TYPE_3D:
2379 			samplerType << "sampler3D";
2380 			break;
2381 
2382 		case VK_IMAGE_VIEW_TYPE_CUBE:
2383 			samplerType << "samplerCube";
2384 			break;
2385 
2386 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2387 			samplerType << "samplerCubeArray";
2388 			break;
2389 
2390 		default:
2391 			DE_FATAL("Unknown image view type");
2392 			break;
2393 	}
2394 
2395 	return samplerType.str();
2396 }
2397 
getImageSize(SamplerViewType viewType, int size)2398 tcu::IVec3 AttachmentFeedbackLoopLayoutSamplerTest::getImageSize (SamplerViewType viewType, int size)
2399 {
2400 	switch (viewType)
2401 	{
2402 		case VK_IMAGE_VIEW_TYPE_1D:
2403 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2404 			return tcu::IVec3(size, 1, 1);
2405 
2406 		case VK_IMAGE_VIEW_TYPE_3D:
2407 			return tcu::IVec3(size, size, 4);
2408 
2409 		default:
2410 			break;
2411 	}
2412 
2413 	return tcu::IVec3(size, size, 1);
2414 }
2415 
getArraySize(SamplerViewType viewType)2416 int AttachmentFeedbackLoopLayoutSamplerTest::getArraySize (SamplerViewType viewType)
2417 {
2418 	switch (viewType)
2419 	{
2420 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2421 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2422 		case VK_IMAGE_VIEW_TYPE_CUBE:
2423 			return 6;
2424 
2425 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2426 			return 36;
2427 
2428 		default:
2429 			break;
2430 	}
2431 
2432 	return 1;
2433 }
2434 } // anonymous
2435 
createAttachmentFeedbackLoopLayoutSamplerTests(tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)2436 tcu::TestCaseGroup* createAttachmentFeedbackLoopLayoutSamplerTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
2437 {
2438 	// TODO: implement layer rendering with a geometry shader to render to arrays, 3D and cube images.
2439 	const struct
2440 	{
2441 		SamplerViewType		type;
2442 		const char*			name;
2443 		bool				readOnly;
2444 	}
2445 	imageViewTypes[] =
2446 	{
2447 		{ VK_IMAGE_VIEW_TYPE_1D,			"1d", false },
2448 		{ { VK_IMAGE_VIEW_TYPE_1D, false },	"1d_unnormalized", false },
2449 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array", true },
2450 		{ VK_IMAGE_VIEW_TYPE_2D,			"2d", false },
2451 		{ { VK_IMAGE_VIEW_TYPE_2D, false },	"2d_unnormalized", false },
2452 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array", true },
2453 		{ VK_IMAGE_VIEW_TYPE_3D,			"3d", true },
2454 		{ VK_IMAGE_VIEW_TYPE_CUBE,			"cube", true },
2455 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array", true }
2456 	};
2457 
2458 	const VkFormat formats[] =
2459 	{
2460 		VK_FORMAT_R8G8B8A8_UNORM,
2461 		VK_FORMAT_D16_UNORM,
2462 		VK_FORMAT_D32_SFLOAT,
2463 		VK_FORMAT_D16_UNORM_S8_UINT,
2464 		VK_FORMAT_D24_UNORM_S8_UINT,
2465 		VK_FORMAT_D32_SFLOAT_S8_UINT,
2466 		VK_FORMAT_S8_UINT
2467 	};
2468 
2469 	de::MovePtr<tcu::TestCaseGroup> samplingTypeTests		(new tcu::TestCaseGroup(testCtx, "sampler"));
2470 
2471 	const struct
2472 	{
2473 		enum TestMode		mode;
2474 		const char*			name;
2475 	}
2476 	testModes[] =
2477 	{
2478 		{ TEST_MODE_READ_ONLY,							"_read" },
2479 		{ TEST_MODE_READ_WRITE_SAME_PIXEL,				"_read_write_same_pixel" },
2480 		{ TEST_MODE_READ_WRITE_DIFFERENT_AREAS,			"_read_write_different_areas" },
2481 	};
2482 
2483 	const char* imageAspectTestModes[] = { "_color", "_depth", "_stencil" };
2484 
2485 	const struct
2486 	{
2487 		VkDescriptorType	type;
2488 		const char*			name;
2489 	}
2490 	imageDescriptorTypes[] =
2491 	{
2492 		{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	"combined_image_sampler" },
2493 		{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				"sampled_image" },
2494 	};
2495 
2496 	const struct
2497 	{
2498 		bool				interleaveReadWriteComponents;
2499 		const char*			name;
2500 	}
2501 	interleaveReadWriteComponentsModes[] =
2502 	{
2503 		{ false,							"" },
2504 		{ true,								"_interleave_read_write_components" },
2505 	};
2506 
2507 	const struct
2508 	{
2509 		const PipelineStateMode	pipelineStateMode;
2510 		const char*				suffix;
2511 	} pipelineStateModes[] =
2512 	{
2513 		{ PipelineStateMode::STATIC,							""						},
2514 		{ PipelineStateMode::DYNAMIC_WITH_ZERO_STATIC,			"_dynamic_zero_static"	},
2515 		{ PipelineStateMode::DYNAMIC_WITH_CONTRADICTORY_STATIC,	"_dynamic_bad_static"	},
2516 	};
2517 
2518 	for (int imageDescriptorTypeNdx = 0; imageDescriptorTypeNdx < DE_LENGTH_OF_ARRAY(imageDescriptorTypes); imageDescriptorTypeNdx++)
2519 	{
2520 		VkDescriptorType					imageDescriptorType		= imageDescriptorTypes[imageDescriptorTypeNdx].type;
2521 		de::MovePtr<tcu::TestCaseGroup>	imageDescriptorTypeGroup	(new tcu::TestCaseGroup(testCtx, imageDescriptorTypes[imageDescriptorTypeNdx].name));
2522 		de::MovePtr<tcu::TestCaseGroup> imageTypeTests		(new tcu::TestCaseGroup(testCtx, "image_type"));
2523 
2524 		for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
2525 		{
2526 			const SamplerViewType			viewType		= imageViewTypes[viewTypeNdx].type;
2527 			de::MovePtr<tcu::TestCaseGroup> viewTypeGroup   (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
2528 			de::MovePtr<tcu::TestCaseGroup>	formatTests		(new tcu::TestCaseGroup(testCtx, "format"));
2529 
2530 			for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2531 			{
2532 				const VkFormat	format			= formats[formatNdx];
2533 				const bool		isCompressed	= isCompressedFormat(format);
2534 				const bool		isDepthStencil	= !isCompressed && tcu::hasDepthComponent(mapVkFormat(format).order) && tcu::hasStencilComponent(mapVkFormat(format).order);
2535 				ImageAspectTestMode	imageAspectTestMode = getImageAspectTestMode(format);
2536 
2537 				if (isCompressed)
2538 				{
2539 					// Do not use compressed formats with 1D and 1D array textures.
2540 					if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2541 						break;
2542 				}
2543 
2544 				for (int testModeNdx = 0; testModeNdx < DE_LENGTH_OF_ARRAY(testModes); testModeNdx++)
2545 				{
2546 					if (imageViewTypes[viewTypeNdx].readOnly && testModes[testModeNdx].mode != TEST_MODE_READ_ONLY)
2547 						continue;
2548 
2549 					for (int restrictColorNdx = 0; restrictColorNdx < DE_LENGTH_OF_ARRAY(interleaveReadWriteComponentsModes); restrictColorNdx++)
2550 					{
2551 						// Limit the interleaveReadWriteComponents test to the ones sampling and writing to the same pixel, to avoid having more tests that are not really adding coverage.
2552 						if (interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents &&
2553 							testModes[testModeNdx].mode != TEST_MODE_READ_WRITE_SAME_PIXEL)
2554 							continue;
2555 
2556 						// If the format is depth-only or stencil-only, do not read one component and write it to the other, as it is missing.
2557 						if (interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents &&
2558 							(tcu::hasDepthComponent(mapVkFormat(format).order) || tcu::hasStencilComponent(mapVkFormat(format).order)) && !isDepthStencil)
2559 							continue;
2560 
2561 						for (const auto& pipelineStateMode : pipelineStateModes)
2562 						{
2563 							std::string name = getFormatCaseName(format) + imageAspectTestModes[imageAspectTestMode] + testModes[testModeNdx].name + interleaveReadWriteComponentsModes[restrictColorNdx].name + pipelineStateMode.suffix;
2564 							formatTests->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(testCtx, pipelineConstructionType, name.c_str(), viewType, format, outputImageSize, imageDescriptorType, 0.0f, testModes[testModeNdx].mode, imageAspectTestMode, interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents, pipelineStateMode.pipelineStateMode, false));
2565 
2566 							if (!isCompressed && isDepthStencil)
2567 							{
2568 								// Image is depth-stencil. Add the stencil case as well.
2569 								std::string stencilTestName = getFormatCaseName(format) + imageAspectTestModes[IMAGE_ASPECT_TEST_STENCIL] + testModes[testModeNdx].name + interleaveReadWriteComponentsModes[restrictColorNdx].name + pipelineStateMode.suffix;
2570 								formatTests->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(testCtx, pipelineConstructionType, stencilTestName.c_str(), viewType, format, outputImageSize, imageDescriptorType, 0.0f, testModes[testModeNdx].mode, IMAGE_ASPECT_TEST_STENCIL, interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents, pipelineStateMode.pipelineStateMode, false));
2571 							}
2572 						}
2573 					}
2574 				}
2575 			}
2576 
2577 			viewTypeGroup->addChild(formatTests.release());
2578 			imageTypeTests->addChild(viewTypeGroup.release());
2579 		}
2580 		imageDescriptorTypeGroup->addChild(imageTypeTests.release());
2581 		samplingTypeTests->addChild(imageDescriptorTypeGroup.release());
2582 	}
2583 
2584 	if (pipelineConstructionType == PipelineConstructionType::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2585 	{
2586 		de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc", ""));
2587 		miscGroup->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(testCtx, pipelineConstructionType, "maintenance5_color_attachment", VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, outputImageSize, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0.0f, TEST_MODE_READ_ONLY, IMAGE_ASPECT_TEST_COLOR, false, PipelineStateMode::STATIC, true));
2588 		miscGroup->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(testCtx, pipelineConstructionType, "maintenance5_ds_attachment", VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM, outputImageSize, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0.0f, TEST_MODE_READ_ONLY, IMAGE_ASPECT_TEST_DEPTH, false, PipelineStateMode::STATIC, true));
2589 		samplingTypeTests->addChild(miscGroup.release());
2590 	}
2591 
2592 	return samplingTypeTests.release();
2593 }
2594 
createAttachmentFeedbackLoopLayoutTests(tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)2595 tcu::TestCaseGroup* createAttachmentFeedbackLoopLayoutTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
2596 {
2597 	de::MovePtr<tcu::TestCaseGroup> attachmentFeedbackLoopLayoutTests(new tcu::TestCaseGroup(testCtx, "attachment_feedback_loop_layout"));
2598 	{
2599 		attachmentFeedbackLoopLayoutTests->addChild(createAttachmentFeedbackLoopLayoutSamplerTests(testCtx, pipelineConstructionType));
2600 	}
2601 
2602 	return attachmentFeedbackLoopLayoutTests.release();
2603 }
2604 
2605 } // pipeline
2606 } // vkt
2607