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
61namespace vkt
62{
63namespace pipeline
64{
65
66using namespace vk;
67using de::MovePtr;
68
69namespace
70{
71
72enum 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
80enum ImageAspectTestMode
81{
82	IMAGE_ASPECT_TEST_COLOR = 0,
83	IMAGE_ASPECT_TEST_DEPTH = 1,
84	IMAGE_ASPECT_TEST_STENCIL = 2,
85};
86
87VkImageAspectFlagBits 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
101enum 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
108VkPipelineCreateFlags 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
121VkPipelineCreateFlags 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
138const int outputImageSize = 256;
139
140ImageAspectTestMode 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
151class SamplerViewType {
152public:
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
160	operator vk::VkImageViewType () const
161	{
162		return m_viewType;
163	}
164
165	bool isNormalized () const
166	{
167		return m_normalized;
168	}
169
170private:
171	vk::VkImageViewType m_viewType;
172	bool				m_normalized;
173};
174
175de::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
205de::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
235static 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
254template<typename TcuFormatType>
255static 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
309VkImageAspectFlags 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
321VkImageAspectFlags getAspectFlags (VkFormat format)
322{
323	if (isCompressedFormat(format))
324		return VK_IMAGE_ASPECT_COLOR_BIT;
325	else
326		return getAspectFlags(mapVkFormat(format));
327}
328
329tcu::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
338std::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
347class AttachmentFeedbackLoopLayoutImageSamplingInstance : public ImageSamplingInstance
348{
349public:
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
363protected:
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
376class AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance : public AttachmentFeedbackLoopLayoutImageSamplingInstance
377{
378public:
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
392protected:
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
403AttachmentFeedbackLoopLayoutImageSamplingInstance::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
422void 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
969AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::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
982AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance (void)
983{
984}
985
986void 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
1503tcu::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
1642tcu::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
1654tcu::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
1730AttachmentFeedbackLoopLayoutImageSamplingInstance::~AttachmentFeedbackLoopLayoutImageSamplingInstance (void)
1731{
1732}
1733
1734tcu::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
1746class AttachmentFeedbackLoopLayoutSamplerTest : public vkt::TestCase {
1747public:
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);
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
1786protected:
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
1802AttachmentFeedbackLoopLayoutSamplerTest::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
1830ImageSamplingInstanceParams 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
1883void 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
1928std::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
1974std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerDecl (int imageCount)
1975{
1976	std::ostringstream samplerArray;
1977	samplerArray << "texSamplers[" << imageCount << "]";
1978
1979	return imageCount > 1 ? samplerArray.str() : "texSampler";
1980}
1981
1982std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureDecl (int imageCount)
1983{
1984	std::ostringstream textureArray;
1985	textureArray << "texImages[" << imageCount << "]";
1986
1987	return imageCount > 1 ? textureArray.str() : "texImage";
1988}
1989
1990std::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
2005void 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
2188TestInstance* 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
2198tcu::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
2210std::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
2268std::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
2298std::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
2318VkSamplerCreateInfo 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
2345VkComponentMapping 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
2351std::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
2398tcu::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
2416int 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
2436tcu::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
2595tcu::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