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