1/*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief RenderPass tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktRenderPassTests.hpp"
25
26#include "vktTestCaseUtil.hpp"
27
28#include "vkDefs.hpp"
29#include "vkDeviceUtil.hpp"
30#include "vkImageUtil.hpp"
31#include "vkMemUtil.hpp"
32#include "vkPlatform.hpp"
33#include "vkPrograms.hpp"
34#include "vkQueryUtil.hpp"
35#include "vkRef.hpp"
36#include "vkRefUtil.hpp"
37#include "vkStrUtil.hpp"
38#include "vkTypeUtil.hpp"
39
40#include "tcuTestLog.hpp"
41#include "tcuResultCollector.hpp"
42#include "tcuFormatUtil.hpp"
43#include "tcuTextureUtil.hpp"
44#include "tcuFloat.hpp"
45#include "tcuMaybe.hpp"
46#include "tcuVectorUtil.hpp"
47
48#include "deUniquePtr.hpp"
49#include "deSharedPtr.hpp"
50#include "deStringUtil.hpp"
51#include "deSTLUtil.hpp"
52#include "deRandom.hpp"
53
54#include <limits>
55
56using namespace vk;
57
58using tcu::Maybe;
59using tcu::nothing;
60using tcu::just;
61using tcu::TestLog;
62using tcu::Vec2;
63using tcu::IVec2;
64using tcu::UVec2;
65using tcu::IVec4;
66using tcu::UVec4;
67using tcu::Vec4;
68using tcu::BVec4;
69using tcu::ConstPixelBufferAccess;
70using tcu::PixelBufferAccess;
71
72using de::UniquePtr;
73
74using std::vector;
75using std::string;
76
77namespace vkt
78{
79namespace
80{
81enum
82{
83	STENCIL_VALUE = 84u,
84	// Limit integer values that are representable as floats
85	MAX_INTEGER_VALUE = ((1u<<22u)-1u)
86};
87
88// Utility functions using flattened structs
89Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, VkFenceCreateFlags flags)
90{
91	const VkFenceCreateInfo pCreateInfo =
92	{
93		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
94		DE_NULL,
95
96		flags
97	};
98	return createFence(vk, device, &pCreateInfo);
99}
100
101Move<VkFramebuffer> createFramebuffer (const DeviceInterface&	vk,
102									   VkDevice					device,
103									   VkFramebufferCreateFlags	pCreateInfo_flags,
104									   VkRenderPass				pCreateInfo_renderPass,
105									   deUint32					pCreateInfo_attachmentCount,
106									   const VkImageView*		pCreateInfo_pAttachments,
107									   deUint32					pCreateInfo_width,
108									   deUint32					pCreateInfo_height,
109									   deUint32					pCreateInfo_layers)
110{
111	const VkFramebufferCreateInfo pCreateInfo =
112	{
113		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
114		DE_NULL,
115		pCreateInfo_flags,
116		pCreateInfo_renderPass,
117		pCreateInfo_attachmentCount,
118		pCreateInfo_pAttachments,
119		pCreateInfo_width,
120		pCreateInfo_height,
121		pCreateInfo_layers,
122	};
123	return createFramebuffer(vk, device, &pCreateInfo);
124}
125
126Move<VkImage> createImage (const DeviceInterface&	vk,
127						   VkDevice					device,
128						   VkImageCreateFlags		pCreateInfo_flags,
129						   VkImageType				pCreateInfo_imageType,
130						   VkFormat					pCreateInfo_format,
131						   VkExtent3D				pCreateInfo_extent,
132						   deUint32					pCreateInfo_mipLevels,
133						   deUint32					pCreateInfo_arrayLayers,
134						   VkSampleCountFlagBits	pCreateInfo_samples,
135						   VkImageTiling			pCreateInfo_tiling,
136						   VkImageUsageFlags		pCreateInfo_usage,
137						   VkSharingMode			pCreateInfo_sharingMode,
138						   deUint32					pCreateInfo_queueFamilyCount,
139						   const deUint32*			pCreateInfo_pQueueFamilyIndices,
140						   VkImageLayout			pCreateInfo_initialLayout)
141{
142	const VkImageCreateInfo pCreateInfo =
143	{
144		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
145		DE_NULL,
146		pCreateInfo_flags,
147		pCreateInfo_imageType,
148		pCreateInfo_format,
149		pCreateInfo_extent,
150		pCreateInfo_mipLevels,
151		pCreateInfo_arrayLayers,
152		pCreateInfo_samples,
153		pCreateInfo_tiling,
154		pCreateInfo_usage,
155		pCreateInfo_sharingMode,
156		pCreateInfo_queueFamilyCount,
157		pCreateInfo_pQueueFamilyIndices,
158		pCreateInfo_initialLayout
159	};
160	return createImage(vk, device, &pCreateInfo);
161}
162
163void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
164{
165	VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
166}
167
168void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
169{
170	VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
171}
172
173Move<VkImageView> createImageView (const DeviceInterface&	vk,
174									VkDevice				device,
175									VkImageViewCreateFlags	pCreateInfo_flags,
176									VkImage					pCreateInfo_image,
177									VkImageViewType			pCreateInfo_viewType,
178									VkFormat				pCreateInfo_format,
179									VkComponentMapping		pCreateInfo_components,
180									VkImageSubresourceRange	pCreateInfo_subresourceRange)
181{
182	const VkImageViewCreateInfo pCreateInfo =
183	{
184		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
185		DE_NULL,
186		pCreateInfo_flags,
187		pCreateInfo_image,
188		pCreateInfo_viewType,
189		pCreateInfo_format,
190		pCreateInfo_components,
191		pCreateInfo_subresourceRange,
192	};
193	return createImageView(vk, device, &pCreateInfo);
194}
195
196Move<VkBuffer> createBuffer (const DeviceInterface&	vk,
197							 VkDevice				device,
198							 VkBufferCreateFlags	pCreateInfo_flags,
199							 VkDeviceSize			pCreateInfo_size,
200							 VkBufferUsageFlags		pCreateInfo_usage,
201							 VkSharingMode			pCreateInfo_sharingMode,
202							 deUint32				pCreateInfo_queueFamilyCount,
203							 const deUint32*		pCreateInfo_pQueueFamilyIndices)
204{
205	const VkBufferCreateInfo pCreateInfo =
206	{
207		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
208		DE_NULL,
209		pCreateInfo_flags,
210		pCreateInfo_size,
211		pCreateInfo_usage,
212		pCreateInfo_sharingMode,
213		pCreateInfo_queueFamilyCount,
214		pCreateInfo_pQueueFamilyIndices,
215	};
216	return createBuffer(vk, device, &pCreateInfo);
217}
218
219Move<VkCommandPool> createCommandPool (const DeviceInterface&	vk,
220									   VkDevice					device,
221									   VkCommandPoolCreateFlags	pCreateInfo_flags,
222									   deUint32					pCreateInfo_queueFamilyIndex)
223{
224	const VkCommandPoolCreateInfo pCreateInfo =
225	{
226		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
227		DE_NULL,
228		pCreateInfo_flags,
229		pCreateInfo_queueFamilyIndex,
230	};
231	return createCommandPool(vk, device, &pCreateInfo);
232}
233
234void cmdBeginRenderPass (const DeviceInterface&	vk,
235						 VkCommandBuffer		cmdBuffer,
236						 VkRenderPass			pRenderPassBegin_renderPass,
237						 VkFramebuffer			pRenderPassBegin_framebuffer,
238						 VkRect2D				pRenderPassBegin_renderArea,
239						 deUint32				pRenderPassBegin_clearValueCount,
240						 const VkClearValue*	pRenderPassBegin_pAttachmentClearValues,
241						 VkSubpassContents		contents)
242{
243	const VkRenderPassBeginInfo pRenderPassBegin =
244	{
245		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
246		DE_NULL,
247		pRenderPassBegin_renderPass,
248		pRenderPassBegin_framebuffer,
249		pRenderPassBegin_renderArea,
250		pRenderPassBegin_clearValueCount,
251		pRenderPassBegin_pAttachmentClearValues,
252	};
253	vk.cmdBeginRenderPass(cmdBuffer, &pRenderPassBegin, contents);
254}
255
256Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface&	vk,
257											 VkDevice				device,
258											 VkCommandPool			pCreateInfo_commandPool,
259											 VkCommandBufferLevel	pCreateInfo_level)
260{
261	const VkCommandBufferAllocateInfo pAllocateInfo =
262	{
263		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
264		DE_NULL,
265		pCreateInfo_commandPool,
266		pCreateInfo_level,
267		1u,												// bufferCount
268	};
269	return allocateCommandBuffer(vk, device, &pAllocateInfo);
270}
271
272void beginCommandBuffer (const DeviceInterface&			vk,
273						 VkCommandBuffer				cmdBuffer,
274						 VkCommandBufferUsageFlags		pBeginInfo_flags,
275						 VkRenderPass					pInheritanceInfo_renderPass,
276						 deUint32						pInheritanceInfo_subpass,
277						 VkFramebuffer					pInheritanceInfo_framebuffer,
278						 VkBool32						pInheritanceInfo_occlusionQueryEnable,
279						 VkQueryControlFlags			pInheritanceInfo_queryFlags,
280						 VkQueryPipelineStatisticFlags	pInheritanceInfo_pipelineStatistics)
281{
282	const VkCommandBufferInheritanceInfo	pInheritanceInfo	=
283	{
284		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
285		DE_NULL,
286		pInheritanceInfo_renderPass,
287		pInheritanceInfo_subpass,
288		pInheritanceInfo_framebuffer,
289		pInheritanceInfo_occlusionQueryEnable,
290		pInheritanceInfo_queryFlags,
291		pInheritanceInfo_pipelineStatistics,
292	};
293	const VkCommandBufferBeginInfo			pBeginInfo			=
294	{
295		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
296		DE_NULL,
297		pBeginInfo_flags,
298		&pInheritanceInfo,
299	};
300	VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo));
301}
302
303void endCommandBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
304{
305	VK_CHECK(vk.endCommandBuffer(cmdBuffer));
306}
307
308void queueSubmit (const DeviceInterface& vk, VkQueue queue, deUint32 cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence)
309{
310	const VkSubmitInfo submitInfo =
311	{
312		VK_STRUCTURE_TYPE_SUBMIT_INFO,
313		DE_NULL,
314		0u,								// waitSemaphoreCount
315		(const VkSemaphore*)DE_NULL,	// pWaitSemaphores
316		(const VkPipelineStageFlags*)DE_NULL,
317		cmdBufferCount,					// commandBufferCount
318		pCmdBuffers,
319		0u,								// signalSemaphoreCount
320		(const VkSemaphore*)DE_NULL,	// pSignalSemaphores
321	};
322	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
323}
324
325void waitForFences (const DeviceInterface& vk, VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout)
326{
327	VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout));
328}
329
330VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
331{
332	const tcu::TextureFormat format = mapVkFormat(vkFormat);
333
334	DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
335
336	switch (format.order)
337	{
338		case tcu::TextureFormat::DS:
339			return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
340
341		case tcu::TextureFormat::D:
342			return VK_IMAGE_ASPECT_DEPTH_BIT;
343
344		case tcu::TextureFormat::S:
345			return VK_IMAGE_ASPECT_STENCIL_BIT;
346
347		default:
348			return VK_IMAGE_ASPECT_COLOR_BIT;
349	}
350}
351
352VkAccessFlags getAllMemoryReadFlags (void)
353{
354	return VK_ACCESS_TRANSFER_READ_BIT
355		   | VK_ACCESS_UNIFORM_READ_BIT
356		   | VK_ACCESS_HOST_READ_BIT
357		   | VK_ACCESS_INDEX_READ_BIT
358		   | VK_ACCESS_SHADER_READ_BIT
359		   | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
360		   | VK_ACCESS_INDIRECT_COMMAND_READ_BIT
361		   | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
362		   | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
363		   | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
364}
365
366VkAccessFlags getAllMemoryWriteFlags (void)
367{
368	return VK_ACCESS_TRANSFER_WRITE_BIT
369		   | VK_ACCESS_HOST_WRITE_BIT
370		   | VK_ACCESS_SHADER_WRITE_BIT
371		   | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
372		   | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
373}
374
375VkAccessFlags getMemoryFlagsForLayout (const VkImageLayout layout)
376{
377	switch (layout)
378	{
379		case VK_IMAGE_LAYOUT_GENERAL:							return getAllMemoryReadFlags() | getAllMemoryWriteFlags();
380		case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:			return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
381		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:	return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
382		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:	return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
383		case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:			return VK_ACCESS_SHADER_READ_BIT;
384		case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:				return VK_ACCESS_TRANSFER_READ_BIT;
385		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:				return VK_ACCESS_TRANSFER_WRITE_BIT;
386
387		default:
388			return (VkAccessFlags)0;
389	}
390}
391
392VkPipelineStageFlags getAllPipelineStageFlags (void)
393{
394	return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
395		   | VK_PIPELINE_STAGE_TRANSFER_BIT
396		   | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
397		   | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
398		   | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
399		   | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
400		   | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
401		   | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
402		   | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
403		   | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
404		   | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
405		   | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
406		   | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
407}
408
409class AttachmentReference
410{
411public:
412					AttachmentReference		(deUint32		attachment,
413											 VkImageLayout	layout)
414		: m_attachment	(attachment)
415		, m_layout		(layout)
416	{
417	}
418
419	deUint32		getAttachment			(void) const { return m_attachment;	}
420	VkImageLayout	getImageLayout			(void) const { return m_layout;		}
421
422private:
423	deUint32		m_attachment;
424	VkImageLayout	m_layout;
425};
426
427class Subpass
428{
429public:
430										Subpass						(VkPipelineBindPoint				pipelineBindPoint,
431																	 VkSubpassDescriptionFlags			flags,
432																	 const vector<AttachmentReference>&	inputAttachments,
433																	 const vector<AttachmentReference>&	colorAttachments,
434																	 const vector<AttachmentReference>&	resolveAttachments,
435																	 AttachmentReference				depthStencilAttachment,
436																	 const vector<AttachmentReference>&	preserveAttachments)
437		: m_pipelineBindPoint		(pipelineBindPoint)
438		, m_flags					(flags)
439		, m_inputAttachments		(inputAttachments)
440		, m_colorAttachments		(colorAttachments)
441		, m_resolveAttachments		(resolveAttachments)
442		, m_depthStencilAttachment	(depthStencilAttachment)
443		, m_preserveAttachments		(preserveAttachments)
444	{
445	}
446
447	VkPipelineBindPoint					getPipelineBindPoint		(void) const { return m_pipelineBindPoint;		}
448	VkSubpassDescriptionFlags			getFlags					(void) const { return m_flags;					}
449	const vector<AttachmentReference>&	getInputAttachments			(void) const { return m_inputAttachments;		}
450	const vector<AttachmentReference>&	getColorAttachments			(void) const { return m_colorAttachments;		}
451	const vector<AttachmentReference>&	getResolveAttachments		(void) const { return m_resolveAttachments;		}
452	const AttachmentReference&			getDepthStencilAttachment	(void) const { return m_depthStencilAttachment;	}
453	const vector<AttachmentReference>&	getPreserveAttachments		(void) const { return m_preserveAttachments;	}
454
455private:
456	VkPipelineBindPoint					m_pipelineBindPoint;
457	VkSubpassDescriptionFlags			m_flags;
458
459	vector<AttachmentReference>			m_inputAttachments;
460	vector<AttachmentReference>			m_colorAttachments;
461	vector<AttachmentReference>			m_resolveAttachments;
462	AttachmentReference					m_depthStencilAttachment;
463
464	vector<AttachmentReference>			m_preserveAttachments;
465};
466
467class SubpassDependency
468{
469public:
470							SubpassDependency	(deUint32				srcPass,
471												 deUint32				dstPass,
472
473												 VkPipelineStageFlags	srcStageMask,
474												 VkPipelineStageFlags	dstStageMask,
475
476												 VkAccessFlags			outputMask,
477												 VkAccessFlags			inputMask,
478
479												 VkDependencyFlags		flags)
480		: m_srcPass			(srcPass)
481		, m_dstPass			(dstPass)
482
483		, m_srcStageMask	(srcStageMask)
484		, m_dstStageMask	(dstStageMask)
485
486		, m_outputMask		(outputMask)
487		, m_inputMask		(inputMask)
488		, m_flags			(flags)
489	{
490	}
491
492	deUint32				getSrcPass			(void) const { return m_srcPass;		}
493	deUint32				getDstPass			(void) const { return m_dstPass;		}
494
495	VkPipelineStageFlags	getSrcStageMask		(void) const { return m_srcStageMask;	}
496	VkPipelineStageFlags	getDstStageMask		(void) const { return m_dstStageMask;	}
497
498	VkAccessFlags			getOutputMask		(void) const { return m_outputMask;		}
499	VkAccessFlags			getInputMask		(void) const { return m_inputMask;		}
500
501	VkDependencyFlags		getFlags			(void) const { return m_flags;		}
502
503private:
504	deUint32				m_srcPass;
505	deUint32				m_dstPass;
506
507	VkPipelineStageFlags	m_srcStageMask;
508	VkPipelineStageFlags	m_dstStageMask;
509
510	VkAccessFlags			m_outputMask;
511	VkAccessFlags			m_inputMask;
512	VkDependencyFlags		m_flags;
513};
514
515class Attachment
516{
517public:
518						Attachment			(VkFormat				format,
519											 VkSampleCountFlagBits	samples,
520
521											 VkAttachmentLoadOp		loadOp,
522											 VkAttachmentStoreOp	storeOp,
523
524											 VkAttachmentLoadOp		stencilLoadOp,
525											 VkAttachmentStoreOp	stencilStoreOp,
526
527											 VkImageLayout			initialLayout,
528											 VkImageLayout			finalLayout)
529		: m_format			(format)
530		, m_samples			(samples)
531
532		, m_loadOp			(loadOp)
533		, m_storeOp			(storeOp)
534
535		, m_stencilLoadOp	(stencilLoadOp)
536		, m_stencilStoreOp	(stencilStoreOp)
537
538		, m_initialLayout	(initialLayout)
539		, m_finalLayout		(finalLayout)
540	{
541	}
542
543	VkFormat				getFormat			(void) const { return m_format;			}
544	VkSampleCountFlagBits	getSamples			(void) const { return m_samples;		}
545
546	VkAttachmentLoadOp		getLoadOp			(void) const { return m_loadOp;			}
547	VkAttachmentStoreOp		getStoreOp			(void) const { return m_storeOp;		}
548
549
550	VkAttachmentLoadOp		getStencilLoadOp	(void) const { return m_stencilLoadOp;	}
551	VkAttachmentStoreOp		getStencilStoreOp	(void) const { return m_stencilStoreOp;	}
552
553	VkImageLayout			getInitialLayout	(void) const { return m_initialLayout;	}
554	VkImageLayout			getFinalLayout		(void) const { return m_finalLayout;	}
555
556private:
557	VkFormat				m_format;
558	VkSampleCountFlagBits	m_samples;
559
560	VkAttachmentLoadOp		m_loadOp;
561	VkAttachmentStoreOp		m_storeOp;
562
563	VkAttachmentLoadOp		m_stencilLoadOp;
564	VkAttachmentStoreOp		m_stencilStoreOp;
565
566	VkImageLayout			m_initialLayout;
567	VkImageLayout			m_finalLayout;
568};
569
570class RenderPass
571{
572public:
573										RenderPass		(const vector<Attachment>&			attachments,
574														 const vector<Subpass>&				subpasses,
575														 const vector<SubpassDependency>&	dependencies)
576		: m_attachments		(attachments)
577		, m_subpasses		(subpasses)
578		, m_dependencies	(dependencies)
579	{
580	}
581
582	const vector<Attachment>&			getAttachments	(void) const { return m_attachments;	}
583	const vector<Subpass>&				getSubpasses	(void) const { return m_subpasses;		}
584	const vector<SubpassDependency>&	getDependencies	(void) const { return m_dependencies;	}
585
586private:
587	const vector<Attachment>			m_attachments;
588	const vector<Subpass>				m_subpasses;
589	const vector<SubpassDependency>		m_dependencies;
590};
591
592struct TestConfig
593{
594	enum RenderTypes
595	{
596		RENDERTYPES_NONE	= 0,
597		RENDERTYPES_CLEAR	= (1<<1),
598		RENDERTYPES_DRAW	= (1<<2)
599	};
600
601	enum CommandBufferTypes
602	{
603		COMMANDBUFFERTYPES_INLINE		= (1<<0),
604		COMMANDBUFFERTYPES_SECONDARY	= (1<<1)
605	};
606
607	enum ImageMemory
608	{
609		IMAGEMEMORY_STRICT		= (1<<0),
610		IMAGEMEMORY_LAZY		= (1<<1)
611	};
612
613	TestConfig (const RenderPass&	renderPass_,
614				RenderTypes			renderTypes_,
615				CommandBufferTypes	commandBufferTypes_,
616				ImageMemory			imageMemory_,
617				const UVec2&		targetSize_,
618				const UVec2&		renderPos_,
619				const UVec2&		renderSize_,
620				deUint32			seed_)
621		: renderPass			(renderPass_)
622		, renderTypes			(renderTypes_)
623		, commandBufferTypes	(commandBufferTypes_)
624		, imageMemory			(imageMemory_)
625		, targetSize			(targetSize_)
626		, renderPos				(renderPos_)
627		, renderSize			(renderSize_)
628		, seed					(seed_)
629	{
630	}
631
632	RenderPass			renderPass;
633	RenderTypes			renderTypes;
634	CommandBufferTypes	commandBufferTypes;
635	ImageMemory			imageMemory;
636	UVec2				targetSize;
637	UVec2				renderPos;
638	UVec2				renderSize;
639	deUint32			seed;
640};
641
642TestConfig::RenderTypes operator| (TestConfig::RenderTypes a, TestConfig::RenderTypes b)
643{
644	return (TestConfig::RenderTypes)(((deUint32)a) | ((deUint32)b));
645}
646
647TestConfig::CommandBufferTypes operator| (TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
648{
649	return (TestConfig::CommandBufferTypes)(((deUint32)a) | ((deUint32)b));
650}
651
652TestConfig::ImageMemory operator| (TestConfig::ImageMemory a, TestConfig::ImageMemory b)
653{
654	return (TestConfig::ImageMemory)(((deUint32)a) | ((deUint32)b));
655}
656
657void logRenderPassInfo (TestLog&			log,
658						const RenderPass&	renderPass)
659{
660	const tcu::ScopedLogSection section (log, "RenderPass", "RenderPass");
661
662	{
663		const tcu::ScopedLogSection	attachmentsSection	(log, "Attachments", "Attachments");
664		const vector<Attachment>&	attachments			= renderPass.getAttachments();
665
666		for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
667		{
668			const tcu::ScopedLogSection	attachmentSection	(log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
669			const Attachment&			attachment			= attachments[attachmentNdx];
670
671			log << TestLog::Message << "Format: " << attachment.getFormat() << TestLog::EndMessage;
672			log << TestLog::Message << "Samples: " << attachment.getSamples() << TestLog::EndMessage;
673
674			log << TestLog::Message << "LoadOp: " << attachment.getLoadOp() << TestLog::EndMessage;
675			log << TestLog::Message << "StoreOp: " << attachment.getStoreOp() << TestLog::EndMessage;
676
677			log << TestLog::Message << "StencilLoadOp: " << attachment.getStencilLoadOp() << TestLog::EndMessage;
678			log << TestLog::Message << "StencilStoreOp: " << attachment.getStencilStoreOp() << TestLog::EndMessage;
679
680			log << TestLog::Message << "InitialLayout: " << attachment.getInitialLayout() << TestLog::EndMessage;
681			log << TestLog::Message << "FinalLayout: " << attachment.getFinalLayout() << TestLog::EndMessage;
682		}
683	}
684
685	{
686		const tcu::ScopedLogSection	subpassesSection	(log, "Subpasses", "Subpasses");
687		const vector<Subpass>&		subpasses			= renderPass.getSubpasses();
688
689		for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
690		{
691			const tcu::ScopedLogSection			subpassSection		(log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
692			const Subpass&						subpass				= subpasses[subpassNdx];
693
694			const vector<AttachmentReference>&	inputAttachments	= subpass.getInputAttachments();
695			const vector<AttachmentReference>&	colorAttachments	= subpass.getColorAttachments();
696			const vector<AttachmentReference>&	resolveAttachments	= subpass.getResolveAttachments();
697			const vector<AttachmentReference>&	preserveAttachments	= subpass.getPreserveAttachments();
698
699			if (!inputAttachments.empty())
700			{
701				const tcu::ScopedLogSection		inputAttachmentsSection	(log, "Inputs", "Inputs");
702
703				for (size_t inputNdx = 0; inputNdx < inputAttachments.size(); inputNdx++)
704				{
705					const tcu::ScopedLogSection		inputAttachmentSection	(log, "Input" + de::toString(inputNdx), "Input " + de::toString(inputNdx));
706					const AttachmentReference&		inputAttachment			= inputAttachments[inputNdx];
707
708					log << TestLog::Message << "Attachment: " << inputAttachment.getAttachment() << TestLog::EndMessage;
709					log << TestLog::Message << "Layout: " << inputAttachment.getImageLayout() << TestLog::EndMessage;
710				}
711			}
712
713			if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
714			{
715				const tcu::ScopedLogSection		depthStencilAttachmentSection	(log, "DepthStencil", "DepthStencil");
716				const AttachmentReference&		depthStencilAttachment			= subpass.getDepthStencilAttachment();
717
718				log << TestLog::Message << "Attachment: " << depthStencilAttachment.getAttachment() << TestLog::EndMessage;
719				log << TestLog::Message << "Layout: " << depthStencilAttachment.getImageLayout() << TestLog::EndMessage;
720			}
721
722			if (!colorAttachments.empty())
723			{
724				const tcu::ScopedLogSection		colorAttachmentsSection	(log, "Colors", "Colors");
725
726				for (size_t colorNdx = 0; colorNdx < colorAttachments.size(); colorNdx++)
727				{
728					const tcu::ScopedLogSection		colorAttachmentSection	(log, "Color" + de::toString(colorNdx), "Color " + de::toString(colorNdx));
729					const AttachmentReference&		colorAttachment			= colorAttachments[colorNdx];
730
731					log << TestLog::Message << "Attachment: " << colorAttachment.getAttachment() << TestLog::EndMessage;
732					log << TestLog::Message << "Layout: " << colorAttachment.getImageLayout() << TestLog::EndMessage;
733				}
734			}
735
736			if (!resolveAttachments.empty())
737			{
738				const tcu::ScopedLogSection		resolveAttachmentsSection	(log, "Resolves", "Resolves");
739
740				for (size_t resolveNdx = 0; resolveNdx < resolveAttachments.size(); resolveNdx++)
741				{
742					const tcu::ScopedLogSection		resolveAttachmentSection	(log, "Resolve" + de::toString(resolveNdx), "Resolve " + de::toString(resolveNdx));
743					const AttachmentReference&		resolveAttachment			= resolveAttachments[resolveNdx];
744
745					log << TestLog::Message << "Attachment: " << resolveAttachment.getAttachment() << TestLog::EndMessage;
746					log << TestLog::Message << "Layout: " << resolveAttachment.getImageLayout() << TestLog::EndMessage;
747				}
748			}
749
750			if (!preserveAttachments.empty())
751			{
752				const tcu::ScopedLogSection		preserveAttachmentsSection	(log, "Preserves", "Preserves");
753
754				for (size_t preserveNdx = 0; preserveNdx < preserveAttachments.size(); preserveNdx++)
755				{
756					const tcu::ScopedLogSection		preserveAttachmentSection	(log, "Preserve" + de::toString(preserveNdx), "Preserve " + de::toString(preserveNdx));
757					const AttachmentReference&		preserveAttachment			= preserveAttachments[preserveNdx];
758
759					log << TestLog::Message << "Attachment: " << preserveAttachment.getAttachment() << TestLog::EndMessage;
760					log << TestLog::Message << "Layout: " << preserveAttachment.getImageLayout() << TestLog::EndMessage;
761				}
762			}
763		}
764
765	}
766
767	if (!renderPass.getDependencies().empty())
768	{
769		const tcu::ScopedLogSection	dependenciesSection	(log, "Dependencies", "Dependencies");
770
771		for (size_t depNdx = 0; depNdx < renderPass.getDependencies().size(); depNdx++)
772		{
773			const tcu::ScopedLogSection	dependencySection	(log, "Dependency" + de::toString(depNdx), "Dependency " + de::toString(depNdx));
774			const SubpassDependency&	dep					= renderPass.getDependencies()[depNdx];
775
776			log << TestLog::Message << "Source: " << dep.getSrcPass() << TestLog::EndMessage;
777			log << TestLog::Message << "Destination: " << dep.getDstPass() << TestLog::EndMessage;
778
779			log << TestLog::Message << "Source Stage Mask: " << dep.getSrcStageMask() << TestLog::EndMessage;
780			log << TestLog::Message << "Destination Stage Mask: " << dep.getDstStageMask() << TestLog::EndMessage;
781
782			log << TestLog::Message << "Input Mask: " << dep.getInputMask() << TestLog::EndMessage;
783			log << TestLog::Message << "Output Mask: " << dep.getOutputMask() << TestLog::EndMessage;
784			log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags()) << TestLog::EndMessage;
785		}
786	}
787}
788
789std::string clearColorToString (VkFormat vkFormat, VkClearColorValue value)
790{
791	const tcu::TextureFormat		format			= mapVkFormat(vkFormat);
792	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
793	const tcu::BVec4				channelMask		= tcu::getTextureFormatChannelMask(format);
794
795	std::ostringstream				stream;
796
797	stream << "(";
798
799	switch (channelClass)
800	{
801		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
802			for (int i = 0; i < 4; i++)
803			{
804				if (i > 0)
805					stream << ", ";
806
807				if (channelMask[i])
808					stream << value.int32[i];
809				else
810					stream << "Undef";
811			}
812			break;
813
814		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
815			for (int i = 0; i < 4; i++)
816			{
817				if (i > 0)
818					stream << ", ";
819
820				if (channelMask[i])
821					stream << value.uint32[i];
822				else
823					stream << "Undef";
824			}
825			break;
826
827		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
828		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
829		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
830			for (int i = 0; i < 4; i++)
831			{
832				if (i > 0)
833					stream << ", ";
834
835				if (channelMask[i])
836					stream << value.float32[i];
837				else
838					stream << "Undef";
839			}
840			break;
841
842		default:
843			DE_FATAL("Unknown channel class");
844	}
845
846	stream << ")";
847
848	return stream.str();
849}
850
851std::string clearValueToString (VkFormat vkFormat, VkClearValue value)
852{
853	const tcu::TextureFormat	format	= mapVkFormat(vkFormat);
854
855	if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
856	{
857		std::ostringstream stream;
858
859		stream << "(";
860
861		if (tcu::hasStencilComponent(format.order))
862			stream << "stencil: " << value.depthStencil.stencil;
863
864		if (tcu::hasStencilComponent(format.order) && tcu::hasDepthComponent(format.order))
865			stream << ", ";
866
867		if (tcu::hasDepthComponent(format.order))
868			stream << "depth: " << value.depthStencil.depth;
869
870		stream << ")";
871
872		return stream.str();
873	}
874	else
875		return clearColorToString(vkFormat, value.color);
876}
877
878VkClearColorValue randomColorClearValue (const Attachment& attachment, de::Random& rng)
879{
880	const float						clearNan		= tcu::Float32::nan().asFloat();
881	const tcu::TextureFormat		format			= mapVkFormat(attachment.getFormat());
882	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
883	const tcu::BVec4				channelMask		= tcu::getTextureFormatChannelMask(format);
884	VkClearColorValue				clearColor;
885
886	switch (channelClass)
887	{
888		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
889		{
890			const tcu::IVec4 valueMin = tcu::getFormatMinIntValue(format);
891			const tcu::IVec4 valueMax = tcu::getFormatMaxIntValue(format);
892
893			for (int ndx = 0; ndx < 4; ndx++)
894			{
895				if (!channelMask[ndx])
896					clearColor.int32[ndx] = std::numeric_limits<deInt32>::min();
897				else
898					clearColor.uint32[ndx] = rng.getInt(valueMin[ndx], valueMax[ndx]);
899			}
900			break;
901		}
902
903		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
904		{
905			const UVec4 valueMax = tcu::getFormatMaxUintValue(format);
906
907			for (int ndx = 0; ndx < 4; ndx++)
908			{
909				if (!channelMask[ndx])
910					clearColor.uint32[ndx] = std::numeric_limits<deUint32>::max();
911				else
912					clearColor.uint32[ndx] = rng.getUint32() % valueMax[ndx];
913			}
914			break;
915		}
916
917		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
918		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
919		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
920		{
921			const tcu::TextureFormatInfo	formatInfo		= tcu::getTextureFormatInfo(format);
922
923			for (int ndx = 0; ndx < 4; ndx++)
924			{
925				if (!channelMask[ndx])
926					clearColor.float32[ndx] = clearNan;
927				else
928					clearColor.float32[ndx] = formatInfo.valueMin[ndx] + rng.getFloat() * (formatInfo.valueMax[ndx] - formatInfo.valueMin[ndx]);
929			}
930			break;
931		}
932
933		default:
934			DE_FATAL("Unknown channel class");
935	}
936
937	return clearColor;
938}
939
940VkAttachmentDescription createAttachmentDescription (const Attachment& attachment)
941{
942	const VkAttachmentDescription attachmentDescription =
943	{
944		0,											// flags
945
946		attachment.getFormat(),						// format
947		attachment.getSamples(),					// samples
948
949		attachment.getLoadOp(),						// loadOp
950		attachment.getStoreOp(),					// storeOp
951
952		attachment.getStencilLoadOp(),				// stencilLoadOp
953		attachment.getStencilStoreOp(),				// stencilStoreOp
954
955		attachment.getInitialLayout(),				// initialLayout
956		attachment.getFinalLayout(),				// finalLayout
957	};
958
959	return attachmentDescription;
960}
961
962VkAttachmentReference createAttachmentReference (const AttachmentReference& referenceInfo)
963{
964	const VkAttachmentReference reference =
965	{
966		referenceInfo.getAttachment(),	// attachment;
967		referenceInfo.getImageLayout()	// layout;
968	};
969
970	return reference;
971}
972
973VkSubpassDescription createSubpassDescription (const Subpass&					subpass,
974											   vector<VkAttachmentReference>*	attachmentReferenceLists,
975											   vector<deUint32>*				preserveAttachmentReferences)
976{
977	vector<VkAttachmentReference>&	inputAttachmentReferences			= attachmentReferenceLists[0];
978	vector<VkAttachmentReference>&	colorAttachmentReferences			= attachmentReferenceLists[1];
979	vector<VkAttachmentReference>&	resolveAttachmentReferences			= attachmentReferenceLists[2];
980	vector<VkAttachmentReference>&	depthStencilAttachmentReferences	= attachmentReferenceLists[3];
981
982	for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
983		colorAttachmentReferences.push_back(createAttachmentReference(subpass.getColorAttachments()[attachmentNdx]));
984
985	for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
986		inputAttachmentReferences.push_back(createAttachmentReference(subpass.getInputAttachments()[attachmentNdx]));
987
988	for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
989		resolveAttachmentReferences.push_back(createAttachmentReference(subpass.getResolveAttachments()[attachmentNdx]));
990
991	depthStencilAttachmentReferences.push_back(createAttachmentReference(subpass.getDepthStencilAttachment()));
992
993	for (size_t attachmentNdx = 0; attachmentNdx < subpass.getPreserveAttachments().size(); attachmentNdx++)
994		preserveAttachmentReferences->push_back(subpass.getPreserveAttachments()[attachmentNdx].getAttachment());
995
996	DE_ASSERT(resolveAttachmentReferences.empty() || colorAttachmentReferences.size() == resolveAttachmentReferences.size());
997
998	{
999		const VkSubpassDescription subpassDescription =
1000		{
1001			subpass.getFlags(),																		// flags;
1002			subpass.getPipelineBindPoint(),															// pipelineBindPoint;
1003
1004			(deUint32)inputAttachmentReferences.size(),												// inputCount;
1005			inputAttachmentReferences.empty() ? DE_NULL : &inputAttachmentReferences[0],			// inputAttachments;
1006
1007			(deUint32)colorAttachmentReferences.size(),												// colorCount;
1008			colorAttachmentReferences.empty() ? DE_NULL :  &colorAttachmentReferences[0],			// colorAttachments;
1009			resolveAttachmentReferences.empty() ? DE_NULL : &resolveAttachmentReferences[0],		// resolveAttachments;
1010
1011			&depthStencilAttachmentReferences[0],													// pDepthStencilAttachment;
1012			(deUint32)preserveAttachmentReferences->size(),											// preserveCount;
1013			preserveAttachmentReferences->empty() ? DE_NULL : &(*preserveAttachmentReferences)[0]	// preserveAttachments;
1014		};
1015
1016		return subpassDescription;
1017	}
1018}
1019
1020VkSubpassDependency createSubpassDependency	(const SubpassDependency& dependencyInfo)
1021{
1022	const VkSubpassDependency dependency =
1023	{
1024		dependencyInfo.getSrcPass(),			// srcSubpass;
1025		dependencyInfo.getDstPass(),			// destSubpass;
1026
1027		dependencyInfo.getSrcStageMask(),		// srcStageMask;
1028		dependencyInfo.getDstStageMask(),		// destStageMask;
1029
1030		dependencyInfo.getOutputMask(),			// outputMask;
1031		dependencyInfo.getInputMask(),			// inputMask;
1032
1033		dependencyInfo.getFlags()				// dependencyFlags;
1034	};
1035
1036	return dependency;
1037}
1038
1039Move<VkRenderPass> createRenderPass (const DeviceInterface&	vk,
1040									 VkDevice				device,
1041									 const RenderPass&		renderPassInfo)
1042{
1043	const size_t							perSubpassAttachmentReferenceLists = 4;
1044	vector<VkAttachmentDescription>			attachments;
1045	vector<VkSubpassDescription>			subpasses;
1046	vector<VkSubpassDependency>				dependencies;
1047	vector<vector<VkAttachmentReference> >	attachmentReferenceLists(renderPassInfo.getSubpasses().size() * perSubpassAttachmentReferenceLists);
1048	vector<vector<deUint32> >				preserveAttachments(renderPassInfo.getSubpasses().size());
1049
1050	for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
1051		attachments.push_back(createAttachmentDescription(renderPassInfo.getAttachments()[attachmentNdx]));
1052
1053	for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
1054		subpasses.push_back(createSubpassDescription(renderPassInfo.getSubpasses()[subpassNdx], &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists]), &preserveAttachments[subpassNdx]));
1055
1056	for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++)
1057		dependencies.push_back(createSubpassDependency(renderPassInfo.getDependencies()[depNdx]));
1058
1059	{
1060		const VkRenderPassCreateInfo	createInfo	=
1061		{
1062			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1063			DE_NULL,
1064			(VkRenderPassCreateFlags)0u,
1065			(deUint32)attachments.size(),
1066			(attachments.empty() ? DE_NULL : &attachments[0]),
1067			(deUint32)subpasses.size(),
1068			(subpasses.empty() ? DE_NULL : &subpasses[0]),
1069			(deUint32)dependencies.size(),
1070			(dependencies.empty() ? DE_NULL : &dependencies[0])
1071		};
1072
1073		return createRenderPass(vk, device, &createInfo);
1074	}
1075}
1076
1077Move<VkFramebuffer> createFramebuffer (const DeviceInterface&		vk,
1078									   VkDevice						device,
1079									   VkRenderPass					renderPass,
1080									   const UVec2&					size,
1081									   const vector<VkImageView>&	attachments)
1082{
1083	return createFramebuffer(vk, device, 0u, renderPass, (deUint32)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], size.x(), size.y(), 1u);
1084}
1085
1086Move<VkImage> createAttachmentImage (const DeviceInterface&	vk,
1087									 VkDevice				device,
1088									 deUint32				queueIndex,
1089									 const UVec2&			size,
1090									 VkFormat				format,
1091									 VkSampleCountFlagBits	samples,
1092									 VkImageUsageFlags		usageFlags,
1093									 VkImageLayout			layout)
1094{
1095	const VkExtent3D size_					= { size.x(), size.y(), 1u };
1096	VkImageUsageFlags targetUsageFlags		= 0;
1097	const tcu::TextureFormat textureFormat	= mapVkFormat(format);
1098
1099	if (tcu::hasDepthComponent(textureFormat.order) || tcu::hasStencilComponent(textureFormat.order))
1100	{
1101		targetUsageFlags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1102	}
1103	else
1104	{
1105		targetUsageFlags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1106	}
1107
1108	return createImage(vk, device,
1109					   (VkImageCreateFlags)0,
1110					   VK_IMAGE_TYPE_2D,
1111					   format,
1112					   size_,
1113					   1u /* mipLevels */,
1114					   1u /* arraySize */,
1115					   samples,
1116					   VK_IMAGE_TILING_OPTIMAL,
1117					   usageFlags | targetUsageFlags,
1118					   VK_SHARING_MODE_EXCLUSIVE,
1119					   1,
1120					   &queueIndex,
1121					   layout);
1122}
1123
1124de::MovePtr<Allocation> createImageMemory (const DeviceInterface&	vk,
1125										   VkDevice					device,
1126										   Allocator&				allocator,
1127										   VkImage					image,
1128										   bool						lazy)
1129{
1130	de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any));
1131	bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
1132	return allocation;
1133}
1134
1135Move<VkImageView> createImageAttachmentView (const DeviceInterface&	vk,
1136											 VkDevice				device,
1137											 VkImage				image,
1138											 VkFormat				format,
1139											 VkImageAspectFlags		aspect)
1140{
1141	const VkImageSubresourceRange range =
1142	{
1143		aspect,
1144		0,
1145		1,
1146		0,
1147		1
1148	};
1149
1150	return createImageView(vk, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
1151}
1152
1153VkClearValue randomClearValue (const Attachment& attachment, de::Random& rng)
1154{
1155	const float					clearNan	= tcu::Float32::nan().asFloat();
1156	const tcu::TextureFormat	format		= mapVkFormat(attachment.getFormat());
1157
1158	if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
1159	{
1160		VkClearValue clearValue;
1161
1162		clearValue.depthStencil.depth	= clearNan;
1163		clearValue.depthStencil.stencil	= 255;
1164
1165		if (tcu::hasStencilComponent(format.order))
1166			clearValue.depthStencil.stencil	= rng.getInt(0, 255);
1167
1168		if (tcu::hasDepthComponent(format.order))
1169			clearValue.depthStencil.depth	= rng.getFloat();
1170
1171		return clearValue;
1172	}
1173	else
1174	{
1175		VkClearValue clearValue;
1176
1177		clearValue.color = randomColorClearValue(attachment, rng);
1178
1179		return clearValue;
1180	}
1181}
1182
1183class AttachmentResources
1184{
1185public:
1186	AttachmentResources (const DeviceInterface&		vk,
1187						 VkDevice					device,
1188						 Allocator&					allocator,
1189						 deUint32					queueIndex,
1190						 const UVec2&				size,
1191						 const Attachment&			attachmentInfo,
1192						 VkImageUsageFlags			usageFlags)
1193		: m_image			(createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(), attachmentInfo.getSamples(), usageFlags, VK_IMAGE_LAYOUT_UNDEFINED))
1194		, m_imageMemory		(createImageMemory(vk, device, allocator, *m_image, ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0)))
1195		, m_attachmentView	(createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), getImageAspectFlags(attachmentInfo.getFormat())))
1196	{
1197		if ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) == 0)
1198		{
1199			const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
1200
1201			if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1202			{
1203				const tcu::TextureFormat	depthFormat		= getDepthCopyFormat(attachmentInfo.getFormat());
1204				const tcu::TextureFormat	stencilFormat	= getStencilCopyFormat(attachmentInfo.getFormat());
1205
1206				m_bufferSize			= size.x() * size.y() * depthFormat.getPixelSize();
1207				m_secondaryBufferSize	= size.x() * size.y() * stencilFormat.getPixelSize();
1208
1209				m_buffer				= createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1210				m_bufferMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
1211
1212				bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1213
1214				m_secondaryBuffer		= createBuffer(vk, device, 0, m_secondaryBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1215				m_secondaryBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, device, *m_secondaryBuffer), MemoryRequirement::HostVisible);
1216
1217				bindBufferMemory(vk, device, *m_secondaryBuffer, m_secondaryBufferMemory->getMemory(), m_secondaryBufferMemory->getOffset());
1218			}
1219			else
1220			{
1221				m_bufferSize	= size.x() * size.y() * format.getPixelSize();
1222
1223				m_buffer		= createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1224				m_bufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
1225
1226				bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1227			}
1228		}
1229	}
1230
1231	~AttachmentResources (void)
1232	{
1233	}
1234
1235	VkImageView getAttachmentView (void) const
1236	{
1237		return *m_attachmentView;
1238	}
1239
1240	VkImage getImage (void) const
1241	{
1242		return *m_image;
1243	}
1244
1245	VkBuffer getBuffer (void) const
1246	{
1247		DE_ASSERT(*m_buffer != DE_NULL);
1248		return *m_buffer;
1249	}
1250
1251	VkDeviceSize getBufferSize (void) const
1252	{
1253		DE_ASSERT(*m_buffer != DE_NULL);
1254		return m_bufferSize;
1255	}
1256
1257	const Allocation& getResultMemory (void) const
1258	{
1259		DE_ASSERT(m_bufferMemory);
1260		return *m_bufferMemory;
1261	}
1262
1263	VkBuffer getSecondaryBuffer (void) const
1264	{
1265		DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1266		return *m_secondaryBuffer;
1267	}
1268
1269	VkDeviceSize getSecondaryBufferSize (void) const
1270	{
1271		DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1272		return m_secondaryBufferSize;
1273	}
1274
1275	const Allocation& getSecondaryResultMemory (void) const
1276	{
1277		DE_ASSERT(m_secondaryBufferMemory);
1278		return *m_secondaryBufferMemory;
1279	}
1280
1281private:
1282	const Unique<VkImage>			m_image;
1283	const UniquePtr<Allocation>		m_imageMemory;
1284	const Unique<VkImageView>		m_attachmentView;
1285
1286	Move<VkBuffer>					m_buffer;
1287	VkDeviceSize					m_bufferSize;
1288	de::MovePtr<Allocation>			m_bufferMemory;
1289
1290	Move<VkBuffer>					m_secondaryBuffer;
1291	VkDeviceSize					m_secondaryBufferSize;
1292	de::MovePtr<Allocation>			m_secondaryBufferMemory;
1293};
1294
1295void uploadBufferData (const DeviceInterface&	vk,
1296					   VkDevice					device,
1297					   const Allocation&		memory,
1298					   size_t					size,
1299					   const void*				data)
1300{
1301	const VkMappedMemoryRange range =
1302	{
1303		VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// sType;
1304		DE_NULL,								// pNext;
1305		memory.getMemory(),						// mem;
1306		memory.getOffset(),						// offset;
1307		(VkDeviceSize)size						// size;
1308	};
1309	void* const ptr = memory.getHostPtr();
1310
1311	deMemcpy(ptr, data, size);
1312	VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range));
1313}
1314
1315VkImageAspectFlagBits getPrimaryImageAspect (tcu::TextureFormat::ChannelOrder order)
1316{
1317	DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
1318
1319	switch (order)
1320	{
1321		case tcu::TextureFormat::D:
1322		case tcu::TextureFormat::DS:
1323			return VK_IMAGE_ASPECT_DEPTH_BIT;
1324
1325		case tcu::TextureFormat::S:
1326			return VK_IMAGE_ASPECT_STENCIL_BIT;
1327
1328		default:
1329			return VK_IMAGE_ASPECT_COLOR_BIT;
1330	}
1331}
1332
1333class RenderQuad
1334{
1335public:
1336	RenderQuad (const Vec4& posA, const Vec4& posB)
1337		: m_vertices(6)
1338	{
1339		m_vertices[0] = posA;
1340		m_vertices[1] = Vec4(posA[0], posB[1], posA[2], posA[3]);
1341		m_vertices[2] = posB;
1342
1343		m_vertices[3] = posB;
1344		m_vertices[4] = Vec4(posB[0], posA[1], posB[2], posA[3]);
1345		m_vertices[5] = posA;
1346	}
1347
1348	const Vec4&		getCornerA			(void) const
1349	{
1350		return m_vertices[0];
1351	}
1352
1353	const Vec4&		getCornerB			(void) const
1354	{
1355		return m_vertices[2];
1356	}
1357
1358	const void*		getVertexPointer	(void) const
1359	{
1360		return &m_vertices[0];
1361	}
1362
1363	size_t			getVertexDataSize	(void) const
1364	{
1365		return sizeof(Vec4) * m_vertices.size();
1366	}
1367
1368private:
1369	vector<Vec4>	m_vertices;
1370};
1371
1372class ColorClear
1373{
1374public:
1375	ColorClear	(const UVec2&				offset,
1376				 const UVec2&				size,
1377				 const VkClearColorValue&	color)
1378		: m_offset	(offset)
1379		, m_size	(size)
1380		, m_color	(color)
1381	{
1382	}
1383
1384	const UVec2&				getOffset		(void) const { return m_offset;		}
1385	const UVec2&				getSize			(void) const { return m_size;		}
1386	const VkClearColorValue&	getColor		(void) const { return m_color;		}
1387
1388private:
1389	UVec2				m_offset;
1390	UVec2				m_size;
1391	VkClearColorValue	m_color;
1392};
1393
1394class DepthStencilClear
1395{
1396public:
1397	DepthStencilClear	(const UVec2&				offset,
1398						 const UVec2&				size,
1399						 float						depth,
1400						 deUint32					stencil)
1401		: m_offset	(offset)
1402		, m_size	(size)
1403		, m_depth	(depth)
1404		, m_stencil	(stencil)
1405	{
1406	}
1407
1408	const UVec2&		getOffset		(void) const { return m_offset;		}
1409	const UVec2&		getSize			(void) const { return m_size;		}
1410	float				getDepth		(void) const { return m_depth;		}
1411	deUint32			getStencil		(void) const { return m_stencil;	}
1412
1413private:
1414	UVec2				m_offset;
1415	UVec2				m_size;
1416
1417	float				m_depth;
1418	deUint32			m_stencil;
1419};
1420
1421class SubpassRenderInfo
1422{
1423public:
1424	SubpassRenderInfo	(const RenderPass&					renderPass,
1425						 deUint32							subpassIndex,
1426
1427						 bool								isSecondary_,
1428
1429						 const UVec2&						viewportOffset,
1430						 const UVec2&						viewportSize,
1431
1432						 const Maybe<RenderQuad>&			renderQuad,
1433						 const vector<ColorClear>&			colorClears,
1434						 const Maybe<DepthStencilClear>&	depthStencilClear)
1435		: m_viewportOffset		(viewportOffset)
1436		, m_viewportSize		(viewportSize)
1437		, m_subpassIndex		(subpassIndex)
1438		, m_isSecondary			(isSecondary_)
1439		, m_flags				(renderPass.getSubpasses()[subpassIndex].getFlags())
1440		, m_renderQuad			(renderQuad)
1441		, m_colorClears			(colorClears)
1442		, m_depthStencilClear	(depthStencilClear)
1443		, m_colorAttachments	(renderPass.getSubpasses()[subpassIndex].getColorAttachments())
1444	{
1445		for (deUint32 attachmentNdx = 0; attachmentNdx < (deUint32)m_colorAttachments.size(); attachmentNdx++)
1446			m_colorAttachmentInfo.push_back(renderPass.getAttachments()[m_colorAttachments[attachmentNdx].getAttachment()]);
1447
1448		if (renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
1449		{
1450			m_depthStencilAttachment		= tcu::just(renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment());
1451			m_depthStencilAttachmentInfo	= tcu::just(renderPass.getAttachments()[renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment()]);
1452		}
1453	}
1454
1455	const UVec2&						getViewportOffset				(void) const { return m_viewportOffset;		}
1456	const UVec2&						getViewportSize					(void) const { return m_viewportSize;		}
1457
1458	deUint32							getSubpassIndex					(void) const { return m_subpassIndex;		}
1459	bool								isSecondary						(void) const { return m_isSecondary;		}
1460
1461	const Maybe<RenderQuad>&			getRenderQuad					(void) const { return m_renderQuad;			}
1462	const vector<ColorClear>&			getColorClears					(void) const { return m_colorClears;		}
1463	const Maybe<DepthStencilClear>&		getDepthStencilClear			(void) const { return m_depthStencilClear;	}
1464
1465	deUint32							getColorAttachmentCount			(void) const { return (deUint32)m_colorAttachments.size(); }
1466	VkImageLayout						getColorAttachmentLayout		(deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getImageLayout(); }
1467	deUint32							getColorAttachmentIndex			(deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getAttachment(); }
1468	const Attachment&					getColorAttachment				(deUint32 attachmentNdx) const { return m_colorAttachmentInfo[attachmentNdx]; }
1469	Maybe<VkImageLayout>				getDepthStencilAttachmentLayout	(void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::nothing<VkImageLayout>(); }
1470	Maybe<deUint32>						getDepthStencilAttachmentIndex	(void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::nothing<deUint32>(); };
1471	const Maybe<Attachment>&			getDepthStencilAttachment		(void) const { return m_depthStencilAttachmentInfo; }
1472	VkSubpassDescriptionFlags			getSubpassFlags					(void) const { return m_flags; }
1473private:
1474	UVec2								m_viewportOffset;
1475	UVec2								m_viewportSize;
1476
1477	deUint32							m_subpassIndex;
1478	bool								m_isSecondary;
1479	VkSubpassDescriptionFlags			m_flags;
1480
1481	Maybe<RenderQuad>					m_renderQuad;
1482	vector<ColorClear>					m_colorClears;
1483	Maybe<DepthStencilClear>			m_depthStencilClear;
1484
1485	vector<AttachmentReference>			m_colorAttachments;
1486	vector<Attachment>					m_colorAttachmentInfo;
1487
1488	Maybe<AttachmentReference>			m_depthStencilAttachment;
1489	Maybe<Attachment>					m_depthStencilAttachmentInfo;
1490};
1491
1492Move<VkPipeline> createSubpassPipeline (const DeviceInterface&		vk,
1493										VkDevice					device,
1494										VkRenderPass				renderPass,
1495										VkShaderModule				vertexShaderModule,
1496										VkShaderModule				fragmentShaderModule,
1497										VkPipelineLayout			pipelineLayout,
1498										const SubpassRenderInfo&	renderInfo)
1499{
1500	const VkSpecializationInfo emptyShaderSpecializations =
1501	{
1502		0u,			// mapEntryCount
1503		DE_NULL,	// pMap
1504		0u,			// dataSize
1505		DE_NULL,	// pData
1506	};
1507
1508	Maybe<VkSampleCountFlagBits>				rasterSamples;
1509	vector<VkPipelineColorBlendAttachmentState>	attachmentBlendStates;
1510
1511	for (deUint32 attachmentNdx = 0; attachmentNdx < renderInfo.getColorAttachmentCount(); attachmentNdx++)
1512	{
1513		const Attachment&			attachment		= renderInfo.getColorAttachment(attachmentNdx);
1514
1515		DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
1516
1517		rasterSamples = attachment.getSamples();
1518
1519		{
1520			const VkPipelineColorBlendAttachmentState	attachmentBlendState =
1521			{
1522				VK_FALSE,																								// blendEnable
1523				VK_BLEND_FACTOR_SRC_ALPHA,																				// srcBlendColor
1524				VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,																	// destBlendColor
1525				VK_BLEND_OP_ADD,																						// blendOpColor
1526				VK_BLEND_FACTOR_ONE,																					// srcBlendAlpha
1527				VK_BLEND_FACTOR_ONE,																					// destBlendAlpha
1528				VK_BLEND_OP_ADD,																						// blendOpAlpha
1529				VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT,	// channelWriteMask
1530			};
1531
1532			attachmentBlendStates.push_back(attachmentBlendState);
1533		}
1534	}
1535
1536	if (renderInfo.getDepthStencilAttachment())
1537	{
1538		const Attachment& attachment = *renderInfo.getDepthStencilAttachment();
1539
1540		DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
1541		rasterSamples = attachment.getSamples();
1542	}
1543
1544	// If there are no attachment use single sample
1545	if (!rasterSamples)
1546		rasterSamples = VK_SAMPLE_COUNT_1_BIT;
1547
1548	const VkPipelineShaderStageCreateInfo shaderStages[2] =
1549	{
1550		{
1551			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
1552			DE_NULL,												// pNext
1553			(VkPipelineShaderStageCreateFlags)0u,
1554			VK_SHADER_STAGE_VERTEX_BIT,								// stage
1555			vertexShaderModule,										// shader
1556			"main",
1557			&emptyShaderSpecializations
1558		},
1559		{
1560			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
1561			DE_NULL,												// pNext
1562			(VkPipelineShaderStageCreateFlags)0u,
1563			VK_SHADER_STAGE_FRAGMENT_BIT,							// stage
1564			fragmentShaderModule,									// shader
1565			"main",
1566			&emptyShaderSpecializations
1567		}
1568	};
1569	const VkVertexInputBindingDescription vertexBinding =
1570	{
1571		0u,															// binding
1572		(deUint32)sizeof(tcu::Vec4),								// strideInBytes
1573		VK_VERTEX_INPUT_RATE_VERTEX,								// stepRate
1574	};
1575	const VkVertexInputAttributeDescription vertexAttrib =
1576	{
1577		0u,															// location
1578		0u,															// binding
1579		VK_FORMAT_R32G32B32A32_SFLOAT,								// format
1580		0u,															// offsetInBytes
1581	};
1582	const VkPipelineVertexInputStateCreateInfo vertexInputState =
1583	{
1584		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	sType
1585		DE_NULL,													//	pNext
1586		(VkPipelineVertexInputStateCreateFlags)0u,
1587		1u,															//	bindingCount
1588		&vertexBinding,												//	pVertexBindingDescriptions
1589		1u,															//	attributeCount
1590		&vertexAttrib,												//	pVertexAttributeDescriptions
1591	};
1592	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
1593	{
1594		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// sType
1595		DE_NULL,														// pNext
1596		(VkPipelineInputAssemblyStateCreateFlags)0u,
1597		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// topology
1598		VK_FALSE,														// primitiveRestartEnable
1599	};
1600	const VkViewport viewport =
1601	{
1602		(float)renderInfo.getViewportOffset().x(),	(float)renderInfo.getViewportOffset().y(),
1603		(float)renderInfo.getViewportSize().x(),	(float)renderInfo.getViewportSize().y(),
1604		0.0f, 1.0f
1605	};
1606	const VkRect2D scissor =
1607	{
1608		{ (deInt32)renderInfo.getViewportOffset().x(),	(deInt32)renderInfo.getViewportOffset().y() },
1609		{ renderInfo.getViewportSize().x(),				renderInfo.getViewportSize().y() }
1610	};
1611	const VkPipelineViewportStateCreateInfo viewportState =
1612	{
1613		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1614		DE_NULL,
1615		(VkPipelineViewportStateCreateFlags)0u,
1616		1u,
1617		&viewport,
1618		1u,
1619		&scissor
1620	};
1621	const VkPipelineRasterizationStateCreateInfo rasterState =
1622	{
1623		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// sType
1624		DE_NULL,														// pNext
1625		(VkPipelineRasterizationStateCreateFlags)0u,
1626		VK_TRUE,														// depthClipEnable
1627		VK_FALSE,														// rasterizerDiscardEnable
1628		VK_POLYGON_MODE_FILL,											// fillMode
1629		VK_CULL_MODE_NONE,												// cullMode
1630		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// frontFace
1631		VK_FALSE,														// depthBiasEnable
1632		0.0f,															// depthBias
1633		0.0f,															// depthBiasClamp
1634		0.0f,															// slopeScaledDepthBias
1635		1.0f															// lineWidth
1636	};
1637	const VkPipelineMultisampleStateCreateInfo multisampleState =
1638	{
1639		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// sType
1640		DE_NULL,														// pNext
1641		(VkPipelineMultisampleStateCreateFlags)0u,
1642		*rasterSamples,													// rasterSamples
1643		VK_FALSE,														// sampleShadingEnable
1644		0.0f,															// minSampleShading
1645		DE_NULL,														// pSampleMask
1646		VK_FALSE,														// alphaToCoverageEnable
1647		VK_FALSE,														// alphaToOneEnable
1648	};
1649	const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1650	{
1651		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// sType
1652		DE_NULL,													// pNext
1653		(VkPipelineDepthStencilStateCreateFlags)0u,
1654		VK_TRUE,													// depthTestEnable
1655		VK_TRUE,													// depthWriteEnable
1656		VK_COMPARE_OP_ALWAYS,										// depthCompareOp
1657		VK_FALSE,													// depthBoundsEnable
1658		VK_TRUE,													// stencilTestEnable
1659		{
1660			VK_STENCIL_OP_REPLACE,									// stencilFailOp
1661			VK_STENCIL_OP_REPLACE,									// stencilPassOp
1662			VK_STENCIL_OP_REPLACE,									// stencilDepthFailOp
1663			VK_COMPARE_OP_ALWAYS,									// stencilCompareOp
1664			~0u,													// stencilCompareMask
1665			~0u,													// stencilWriteMask
1666			STENCIL_VALUE											// stencilReference
1667		},															// front
1668		{
1669			VK_STENCIL_OP_REPLACE,									// stencilFailOp
1670			VK_STENCIL_OP_REPLACE,									// stencilPassOp
1671			VK_STENCIL_OP_REPLACE,									// stencilDepthFailOp
1672			VK_COMPARE_OP_ALWAYS,									// stencilCompareOp
1673			~0u,													// stencilCompareMask
1674			~0u,													// stencilWriteMask
1675			STENCIL_VALUE											// stencilReference
1676		},															// back
1677
1678		0.0f,														// minDepthBounds;
1679		1.0f														// maxDepthBounds;
1680	};
1681	const VkPipelineColorBlendStateCreateInfo blendState =
1682	{
1683		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,			// sType
1684		DE_NULL,															// pNext
1685		(VkPipelineColorBlendStateCreateFlags)0u,
1686		VK_FALSE,															// logicOpEnable
1687		VK_LOGIC_OP_COPY,													// logicOp
1688		(deUint32)attachmentBlendStates.size(),								// attachmentCount
1689		attachmentBlendStates.empty() ? DE_NULL : &attachmentBlendStates[0],// pAttachments
1690		{ 0.0f, 0.0f, 0.0f, 0.0f }											// blendConst
1691	};
1692	const VkGraphicsPipelineCreateInfo createInfo =
1693	{
1694		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		// sType
1695		DE_NULL,												// pNext
1696		(VkPipelineCreateFlags)0u,
1697
1698		2,														// stageCount
1699		shaderStages,											// pStages
1700
1701		&vertexInputState,										// pVertexInputState
1702		&inputAssemblyState,									// pInputAssemblyState
1703		DE_NULL,												// pTessellationState
1704		&viewportState,											// pViewportState
1705		&rasterState,											// pRasterState
1706		&multisampleState,										// pMultisampleState
1707		&depthStencilState,										// pDepthStencilState
1708		&blendState,											// pColorBlendState
1709		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,		// pDynamicState
1710		pipelineLayout,											// layout
1711
1712		renderPass,												// renderPass
1713		renderInfo.getSubpassIndex(),							// subpass
1714		DE_NULL,												// basePipelineHandle
1715		0u														// basePipelineIndex
1716	};
1717
1718	return createGraphicsPipeline(vk, device, DE_NULL, &createInfo);
1719}
1720
1721class SubpassRenderer
1722{
1723public:
1724	SubpassRenderer (Context&					context,
1725					 const DeviceInterface&		vk,
1726					 VkDevice					device,
1727					 Allocator&					allocator,
1728					 VkRenderPass				renderPass,
1729					 VkFramebuffer				framebuffer,
1730					 VkCommandPool				commandBufferPool,
1731					 deUint32					queueFamilyIndex,
1732					 const SubpassRenderInfo&	renderInfo)
1733		: m_renderInfo	(renderInfo)
1734	{
1735		const deUint32 subpassIndex = renderInfo.getSubpassIndex();
1736
1737		if (renderInfo.getRenderQuad())
1738		{
1739			const RenderQuad&					renderQuad				= *renderInfo.getRenderQuad();
1740			const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
1741			{
1742				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// sType;
1743				DE_NULL,										// pNext;
1744				(vk::VkPipelineLayoutCreateFlags)0,
1745				0u,												// descriptorSetCount;
1746				DE_NULL,										// pSetLayouts;
1747				0u,												// pushConstantRangeCount;
1748				DE_NULL,										// pPushConstantRanges;
1749			};
1750
1751			m_vertexShaderModule	= createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-vert"), 0u);
1752			m_fragmentShaderModule	= createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-frag"), 0u);
1753			m_pipelineLayout		= createPipelineLayout(vk, device, &pipelineLayoutParams);
1754			m_pipeline				= createSubpassPipeline(vk, device, renderPass, *m_vertexShaderModule, *m_fragmentShaderModule, *m_pipelineLayout, m_renderInfo);
1755
1756			m_vertexBuffer			= createBuffer(vk, device, 0u, (VkDeviceSize)renderQuad.getVertexDataSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex);
1757			m_vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible);
1758
1759			bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset());
1760			uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(), renderQuad.getVertexPointer());
1761		}
1762
1763		if (renderInfo.isSecondary())
1764		{
1765			m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1766
1767			beginCommandBuffer(vk, *m_commandBuffer, vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, renderPass, subpassIndex, framebuffer, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
1768			pushRenderCommands(vk, *m_commandBuffer);
1769			endCommandBuffer(vk, *m_commandBuffer);
1770		}
1771	}
1772
1773	bool isSecondary (void) const
1774	{
1775		return m_commandBuffer;
1776	}
1777
1778	VkCommandBuffer getCommandBuffer (void) const
1779	{
1780		DE_ASSERT(isSecondary());
1781		return *m_commandBuffer;
1782	}
1783
1784	void pushRenderCommands (const DeviceInterface&		vk,
1785							 VkCommandBuffer			commandBuffer)
1786	{
1787		if (!m_renderInfo.getColorClears().empty())
1788		{
1789			const vector<ColorClear>&	colorClears	(m_renderInfo.getColorClears());
1790
1791			for (deUint32 attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
1792			{
1793				const ColorClear&		colorClear	= colorClears[attachmentNdx];
1794				const VkClearAttachment	attachment	=
1795				{
1796					VK_IMAGE_ASPECT_COLOR_BIT,
1797					attachmentNdx,
1798					makeClearValue(colorClear.getColor()),
1799				};
1800				const VkClearRect		rect		=
1801				{
1802					{
1803						{ (deInt32)colorClear.getOffset().x(),	(deInt32)colorClear.getOffset().y()	},
1804						{ colorClear.getSize().x(),				colorClear.getSize().y()			}
1805					},					// rect
1806					0u,					// baseArrayLayer
1807					1u,					// layerCount
1808				};
1809
1810				vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
1811			}
1812		}
1813
1814		if (m_renderInfo.getDepthStencilClear())
1815		{
1816			const DepthStencilClear&		depthStencilClear	= *m_renderInfo.getDepthStencilClear();
1817			const deUint32					attachmentNdx		= m_renderInfo.getColorAttachmentCount();
1818			tcu::TextureFormat				format				= mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
1819			const VkClearAttachment			attachment			=
1820			{
1821				(VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
1822					| (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
1823				attachmentNdx,
1824				makeClearValueDepthStencil(depthStencilClear.getDepth(), depthStencilClear.getStencil())
1825			};
1826			const VkClearRect				rect				=
1827			{
1828				{
1829					{ (deInt32)depthStencilClear.getOffset().x(),	(deInt32)depthStencilClear.getOffset().y()	},
1830					{ depthStencilClear.getSize().x(),				depthStencilClear.getSize().y()				}
1831				},							// rect
1832				0u,							// baseArrayLayer
1833				1u,							// layerCount
1834			};
1835
1836			vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
1837		}
1838
1839		if (m_renderInfo.getRenderQuad())
1840		{
1841			const VkDeviceSize	offset			= 0;
1842			const VkBuffer		vertexBuffer	= *m_vertexBuffer;
1843
1844			vk.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1845			vk.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer, &offset);
1846			vk.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
1847		}
1848	}
1849
1850private:
1851	const SubpassRenderInfo				m_renderInfo;
1852	Move<VkCommandBuffer>				m_commandBuffer;
1853	Move<VkPipeline>					m_pipeline;
1854	Move<VkPipelineLayout>				m_pipelineLayout;
1855
1856	Move<VkShaderModule>				m_vertexShaderModule;
1857
1858	Move<VkShaderModule>				m_fragmentShaderModule;
1859
1860	Move<VkBuffer>						m_vertexBuffer;
1861	de::MovePtr<Allocation>				m_vertexBufferMemory;
1862};
1863
1864void pushImageInitializationCommands (const DeviceInterface&								vk,
1865									  VkCommandBuffer										commandBuffer,
1866									  const vector<Attachment>&								attachmentInfo,
1867									  const vector<de::SharedPtr<AttachmentResources> >&	attachmentResources,
1868									  deUint32												queueIndex,
1869									  const vector<Maybe<VkClearValue> >&					clearValues)
1870{
1871	{
1872		vector<VkImageMemoryBarrier>	initializeLayouts;
1873
1874		for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1875		{
1876			if (!clearValues[attachmentNdx])
1877				continue;
1878
1879			const VkImageMemoryBarrier barrier =
1880			{
1881				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,							// sType;
1882				DE_NULL,														// pNext;
1883
1884				(VkAccessFlags)0,												// srcAccessMask
1885				getAllMemoryReadFlags() | VK_ACCESS_TRANSFER_WRITE_BIT,			// dstAccessMask
1886
1887				VK_IMAGE_LAYOUT_UNDEFINED,										// oldLayout
1888				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,							// newLayout;
1889
1890				queueIndex,														// srcQueueFamilyIndex;
1891				queueIndex,														// destQueueFamilyIndex;
1892
1893				attachmentResources[attachmentNdx]->getImage(),					// image;
1894				{																// subresourceRange;
1895					getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()),		// aspect;
1896					0,																	// baseMipLevel;
1897					1,																	// mipLevels;
1898					0,																	// baseArraySlice;
1899					1																	// arraySize;
1900				}
1901			};
1902
1903			initializeLayouts.push_back(barrier);
1904		}
1905
1906		if (!initializeLayouts.empty())
1907			vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1908								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1909								  0, (const VkMemoryBarrier*)DE_NULL,
1910								  0, (const VkBufferMemoryBarrier*)DE_NULL,
1911								  (deUint32)initializeLayouts.size(), &initializeLayouts[0]);
1912	}
1913
1914	for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1915	{
1916		if (!clearValues[attachmentNdx])
1917			continue;
1918
1919		const tcu::TextureFormat format = mapVkFormat(attachmentInfo[attachmentNdx].getFormat());
1920
1921		if (hasStencilComponent(format.order) || hasDepthComponent(format.order))
1922		{
1923			const float						clearNan		= tcu::Float32::nan().asFloat();
1924			const float						clearDepth		= hasDepthComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.depth : clearNan;
1925			const deUint32					clearStencil	= hasStencilComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.stencil : ~0u;
1926			const VkClearDepthStencilValue	depthStencil	=
1927			{
1928				clearDepth,
1929				clearStencil
1930			};
1931			const VkImageSubresourceRange range =
1932			{
1933				(VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
1934									 | (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
1935				0,
1936				1,
1937				0,
1938				1
1939			};
1940
1941			vk.cmdClearDepthStencilImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencil, 1, &range);
1942		}
1943		else
1944		{
1945			const VkImageSubresourceRange	range		=
1946			{
1947				VK_IMAGE_ASPECT_COLOR_BIT,				// aspectMask;
1948				0,										// baseMipLevel;
1949				1,										// mipLevels;
1950				0,										// baseArrayLayer;
1951				1										// layerCount;
1952			};
1953			const VkClearColorValue			clearColor	= clearValues[attachmentNdx]->color;
1954
1955			vk.cmdClearColorImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
1956		}
1957	}
1958
1959	{
1960		vector<VkImageMemoryBarrier>	renderPassLayouts;
1961
1962		for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1963		{
1964			const VkImageLayout			oldLayout = clearValues[attachmentNdx] ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
1965			const VkImageMemoryBarrier	barrier   =
1966			{
1967				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// sType;
1968				DE_NULL,												// pNext;
1969
1970				(oldLayout != VK_IMAGE_LAYOUT_UNDEFINED ? getAllMemoryWriteFlags() : (VkAccessFlags)0),					// srcAccessMask
1971				getAllMemoryReadFlags() | getMemoryFlagsForLayout(attachmentInfo[attachmentNdx].getInitialLayout()),	// dstAccessMask
1972
1973				oldLayout,												// oldLayout
1974				attachmentInfo[attachmentNdx].getInitialLayout(),		// newLayout;
1975
1976				queueIndex,												// srcQueueFamilyIndex;
1977				queueIndex,												// destQueueFamilyIndex;
1978
1979				attachmentResources[attachmentNdx]->getImage(),			// image;
1980				{														// subresourceRange;
1981					getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()),		// aspect;
1982					0,																	// baseMipLevel;
1983					1,																	// mipLevels;
1984					0,																	// baseArraySlice;
1985					1																	// arraySize;
1986				}
1987			};
1988
1989			renderPassLayouts.push_back(barrier);
1990		}
1991
1992		if (!renderPassLayouts.empty())
1993			vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1994								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1995								  0, (const VkMemoryBarrier*)DE_NULL,
1996								  0, (const VkBufferMemoryBarrier*)DE_NULL,
1997								  (deUint32)renderPassLayouts.size(), &renderPassLayouts[0]);
1998	}
1999}
2000
2001void pushRenderPassCommands (const DeviceInterface&								vk,
2002							 VkCommandBuffer									commandBuffer,
2003							 VkRenderPass										renderPass,
2004							 VkFramebuffer										framebuffer,
2005							 const vector<de::SharedPtr<SubpassRenderer> >&		subpassRenderers,
2006							 const UVec2&										renderPos,
2007							 const UVec2&										renderSize,
2008							 const vector<Maybe<VkClearValue> >&				renderPassClearValues,
2009							 TestConfig::RenderTypes							render)
2010{
2011	const float				clearNan				= tcu::Float32::nan().asFloat();
2012	vector<VkClearValue>	attachmentClearValues;
2013
2014	for (size_t attachmentNdx = 0; attachmentNdx < renderPassClearValues.size(); attachmentNdx++)
2015	{
2016		if (renderPassClearValues[attachmentNdx])
2017			attachmentClearValues.push_back(*renderPassClearValues[attachmentNdx]);
2018		else
2019			attachmentClearValues.push_back(makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan));
2020	}
2021
2022	{
2023		const VkRect2D renderArea =
2024		{
2025			{ (deInt32)renderPos.x(),	(deInt32)renderPos.y()	},
2026			{ renderSize.x(),			renderSize.y()			}
2027		};
2028
2029		for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
2030		{
2031			const VkSubpassContents	contents = subpassRenderers[subpassNdx]->isSecondary() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE;
2032
2033			if (subpassNdx == 0)
2034				cmdBeginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (deUint32)attachmentClearValues.size(), attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0], contents);
2035			else
2036				vk.cmdNextSubpass(commandBuffer, contents);
2037
2038			if (render)
2039			{
2040				if (contents == VK_SUBPASS_CONTENTS_INLINE)
2041				{
2042					subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer);
2043				}
2044				else if (contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
2045				{
2046					const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
2047					vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
2048				}
2049				else
2050					DE_FATAL("Invalid contents");
2051			}
2052		}
2053
2054		vk.cmdEndRenderPass(commandBuffer);
2055	}
2056}
2057
2058void pushReadImagesToBuffers (const DeviceInterface&								vk,
2059							  VkCommandBuffer										commandBuffer,
2060							  deUint32												queueIndex,
2061
2062							  const vector<de::SharedPtr<AttachmentResources> >&	attachmentResources,
2063							  const vector<Attachment>&								attachmentInfo,
2064							  const vector<bool>&									isLazy,
2065
2066							  const UVec2&											targetSize)
2067{
2068	{
2069		vector<VkImageMemoryBarrier>	imageBarriers;
2070
2071		for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2072		{
2073			if (isLazy[attachmentNdx])
2074				continue;
2075
2076			const VkImageLayout			oldLayout	= attachmentInfo[attachmentNdx].getFinalLayout();
2077			const VkImageMemoryBarrier	barrier		=
2078			{
2079				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,							// sType
2080				DE_NULL,														// pNext
2081
2082				getAllMemoryWriteFlags() | getMemoryFlagsForLayout(oldLayout),	// srcAccessMask
2083				getAllMemoryReadFlags(),										// dstAccessMask
2084
2085				oldLayout,														// oldLayout
2086				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,							// newLayout
2087
2088				queueIndex,														// srcQueueFamilyIndex
2089				queueIndex,														// destQueueFamilyIndex
2090
2091				attachmentResources[attachmentNdx]->getImage(),					// image
2092				{																// subresourceRange
2093					getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()),		// aspect;
2094					0,																	// baseMipLevel
2095					1,																	// mipLevels
2096					0,																	// baseArraySlice
2097					1																	// arraySize
2098				}
2099			};
2100
2101			imageBarriers.push_back(barrier);
2102		}
2103
2104		if (!imageBarriers.empty())
2105			vk.cmdPipelineBarrier(commandBuffer,
2106								  getAllPipelineStageFlags(),
2107								  getAllPipelineStageFlags(),
2108								  (VkDependencyFlags)0,
2109								  0, (const VkMemoryBarrier*)DE_NULL,
2110								  0, (const VkBufferMemoryBarrier*)DE_NULL,
2111								  (deUint32)imageBarriers.size(), &imageBarriers[0]);
2112	}
2113
2114	for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2115	{
2116		if (isLazy[attachmentNdx])
2117			continue;
2118
2119		const tcu::TextureFormat::ChannelOrder	order	= mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
2120		const VkBufferImageCopy					rect	=
2121		{
2122			0, // bufferOffset
2123			0, // bufferRowLength
2124			0, // bufferImageHeight
2125			{							// imageSubresource
2126				getPrimaryImageAspect(mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order),	// aspect
2127				0,						// mipLevel
2128				0,						// arraySlice
2129				1						// arraySize
2130			},
2131			{ 0, 0, 0 },				// imageOffset
2132			{ targetSize.x(), targetSize.y(), 1u }		// imageExtent
2133		};
2134
2135		vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(), 1, &rect);
2136
2137		if (tcu::TextureFormat::DS == order)
2138		{
2139			const VkBufferImageCopy stencilRect =
2140			{
2141				0, // bufferOffset
2142				0, // bufferRowLength
2143				0, // bufferImageHeight
2144				{									// imageSubresource
2145					VK_IMAGE_ASPECT_STENCIL_BIT,	// aspect
2146					0,								// mipLevel
2147					0,								// arraySlice
2148					1						// arraySize
2149				},
2150				{ 0, 0, 0 },				// imageOffset
2151				{ targetSize.x(), targetSize.y(), 1u }		// imageExtent
2152			};
2153
2154			vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect);
2155		}
2156	}
2157
2158	{
2159		vector<VkBufferMemoryBarrier>	bufferBarriers;
2160
2161		for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2162		{
2163			if (isLazy[attachmentNdx])
2164				continue;
2165
2166			const tcu::TextureFormat::ChannelOrder	order			= mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
2167			const VkBufferMemoryBarrier				bufferBarrier	=
2168			{
2169				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2170				DE_NULL,
2171
2172				getAllMemoryWriteFlags(),
2173				getAllMemoryReadFlags(),
2174
2175				queueIndex,
2176				queueIndex,
2177
2178				attachmentResources[attachmentNdx]->getBuffer(),
2179				0,
2180				attachmentResources[attachmentNdx]->getBufferSize()
2181			};
2182
2183			bufferBarriers.push_back(bufferBarrier);
2184
2185			if (tcu::TextureFormat::DS == order)
2186			{
2187				const VkBufferMemoryBarrier secondaryBufferBarrier =
2188				{
2189					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2190					DE_NULL,
2191
2192					getAllMemoryWriteFlags(),
2193					getAllMemoryReadFlags(),
2194
2195					queueIndex,
2196					queueIndex,
2197
2198					attachmentResources[attachmentNdx]->getSecondaryBuffer(),
2199					0,
2200					attachmentResources[attachmentNdx]->getSecondaryBufferSize()
2201				};
2202
2203				bufferBarriers.push_back(secondaryBufferBarrier);
2204			}
2205		}
2206
2207		if (!bufferBarriers.empty())
2208			vk.cmdPipelineBarrier(commandBuffer,
2209								  getAllPipelineStageFlags(),
2210								  getAllPipelineStageFlags(),
2211								  (VkDependencyFlags)0,
2212								  0, (const VkMemoryBarrier*)DE_NULL,
2213								  (deUint32)bufferBarriers.size(), &bufferBarriers[0],
2214								  0, (const VkImageMemoryBarrier*)DE_NULL);
2215	}
2216}
2217
2218void clear (const PixelBufferAccess& access, const VkClearValue& value)
2219{
2220	const tcu::TextureFormat&	format	= access.getFormat();
2221
2222	if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2223	{
2224		if (tcu::hasDepthComponent(format.order))
2225			tcu::clearDepth(access, value.depthStencil.depth);
2226
2227		if (tcu::hasStencilComponent(format.order))
2228			tcu::clearStencil(access, value.depthStencil.stencil);
2229	}
2230	else
2231	{
2232		if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT
2233				|| tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
2234				|| tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
2235		{
2236			const tcu::Vec4		color	(value.color.float32[0],
2237										 value.color.float32[1],
2238										 value.color.float32[2],
2239										 value.color.float32[3]);
2240
2241			if (tcu::isSRGB(format))
2242				tcu::clear(access, tcu::linearToSRGB(color));
2243			else
2244				tcu::clear(access, color);
2245		}
2246		else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2247		{
2248			const tcu::UVec4	color	(value.color.uint32[0],
2249										 value.color.uint32[1],
2250										 value.color.uint32[2],
2251										 value.color.uint32[3]);
2252
2253			tcu::clear(access, color);
2254		}
2255		else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
2256		{
2257			const tcu::IVec4	color	(value.color.int32[0],
2258										 value.color.int32[1],
2259										 value.color.int32[2],
2260										 value.color.int32[3]);
2261
2262			tcu::clear(access, color);
2263		}
2264		else
2265			DE_FATAL("Unknown channel class");
2266	}
2267}
2268
2269Vec4 computeUvs (const IVec2& posA, const IVec2& posB, const IVec2& pos)
2270{
2271	const float u = de::clamp((float)(pos.x() - posA.x()) / (float)(posB.x() - posA.x()), 0.0f, 1.0f);
2272	const float v = de::clamp((float)(pos.y() - posA.y()) / (float)(posB.y() - posA.y()), 0.0f, 1.0f);
2273
2274	return Vec4(u, v, u * v, (u + v) / 2.0f);
2275}
2276
2277void renderReferenceImages (vector<tcu::TextureLevel>&			referenceAttachments,
2278							const RenderPass&					renderPassInfo,
2279							const UVec2&						targetSize,
2280							const vector<Maybe<VkClearValue> >&	imageClearValues,
2281							const vector<Maybe<VkClearValue> >&	renderPassClearValues,
2282							const vector<SubpassRenderInfo>&	subpassRenderInfo,
2283							const UVec2&						renderPos,
2284							const UVec2&						renderSize)
2285{
2286	const vector<Subpass>&	subpasses		= renderPassInfo.getSubpasses();
2287	vector<bool>			attachmentUsed	(renderPassInfo.getAttachments().size(), false);
2288
2289	referenceAttachments.resize(renderPassInfo.getAttachments().size());
2290
2291	for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
2292	{
2293		const Attachment				attachment					= renderPassInfo.getAttachments()[attachmentNdx];
2294		const tcu::TextureFormat		format						= mapVkFormat(attachment.getFormat());
2295		const tcu::TextureFormatInfo	textureInfo					= tcu::getTextureFormatInfo(format);
2296		tcu::TextureLevel&				reference					= referenceAttachments[attachmentNdx];
2297		const bool						isDepthOrStencilAttachment	= hasDepthComponent(format.order) || hasStencilComponent(format.order);
2298
2299		reference = tcu::TextureLevel(format, targetSize.x(), targetSize.y());
2300
2301		if (imageClearValues[attachmentNdx])
2302			clear(reference.getAccess(), *imageClearValues[attachmentNdx]);
2303		else
2304		{
2305			// Fill with grid if image contentst are undefined before renderpass
2306			if (isDepthOrStencilAttachment)
2307			{
2308				if (tcu::hasDepthComponent(format.order))
2309					tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), 2, textureInfo.valueMin, textureInfo.valueMax);
2310
2311				if (tcu::hasStencilComponent(format.order))
2312					tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), 2, textureInfo.valueMin, textureInfo.valueMax);
2313			}
2314			else
2315				tcu::fillWithGrid(reference.getAccess(), 2, textureInfo.valueMin, textureInfo.valueMax);
2316		}
2317	}
2318
2319	for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
2320	{
2321		const Subpass&						subpass				= subpasses[subpassNdx];
2322		const SubpassRenderInfo&			renderInfo			= subpassRenderInfo[subpassNdx];
2323		const vector<AttachmentReference>&	colorAttachments	= subpass.getColorAttachments();
2324
2325		// Apply load op if attachment was used for the first time
2326		for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++)
2327		{
2328			const deUint32 attachmentIndex = colorAttachments[attachmentNdx].getAttachment();
2329
2330			if (!attachmentUsed[attachmentIndex])
2331			{
2332				const Attachment&	attachment	= renderPassInfo.getAttachments()[attachmentIndex];
2333				tcu::TextureLevel&	reference	= referenceAttachments[attachmentIndex];
2334
2335				DE_ASSERT(!tcu::hasDepthComponent(reference.getFormat().order));
2336				DE_ASSERT(!tcu::hasStencilComponent(reference.getFormat().order));
2337
2338				if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2339					clear(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2340				else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2341				{
2342					const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2343
2344					tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2345				}
2346
2347				attachmentUsed[attachmentIndex] = true;
2348			}
2349		}
2350
2351		// Apply load op to depth/stencil attachment if it was used for the first time
2352		if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED && !attachmentUsed[subpass.getDepthStencilAttachment().getAttachment()])
2353		{
2354			const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
2355
2356			// Apply load op if attachment was used for the first time
2357			if (!attachmentUsed[attachmentIndex])
2358			{
2359				const Attachment&	attachment	= renderPassInfo.getAttachments()[attachmentIndex];
2360				tcu::TextureLevel&	reference		= referenceAttachments[attachmentIndex];
2361
2362				if (tcu::hasDepthComponent(reference.getFormat().order))
2363				{
2364					if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2365						clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2366					else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2367					{
2368						const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2369
2370						tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2371					}
2372				}
2373
2374				if (tcu::hasStencilComponent(reference.getFormat().order))
2375				{
2376					if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2377						clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2378					else if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2379					{
2380						const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2381
2382						tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2383					}
2384				}
2385			}
2386
2387			attachmentUsed[attachmentIndex] = true;
2388		}
2389
2390		for (size_t colorClearNdx = 0; colorClearNdx < renderInfo.getColorClears().size(); colorClearNdx++)
2391		{
2392			const ColorClear&	colorClear	= renderInfo.getColorClears()[colorClearNdx];
2393			const UVec2			offset		= colorClear.getOffset();
2394			const UVec2			size		= colorClear.getSize();
2395			tcu::TextureLevel&	reference	= referenceAttachments[subpass.getColorAttachments()[colorClearNdx].getAttachment()];
2396			VkClearValue		value;
2397
2398			value.color = colorClear.getColor();
2399
2400			clear(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), value);
2401		}
2402
2403		if (renderInfo.getDepthStencilClear())
2404		{
2405			const DepthStencilClear&	dsClear		= *renderInfo.getDepthStencilClear();
2406			const UVec2					offset		= dsClear.getOffset();
2407			const UVec2					size		= dsClear.getSize();
2408			tcu::TextureLevel&			reference	= referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
2409
2410			if (tcu::hasDepthComponent(reference.getFormat().order))
2411				clearDepth(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getDepth());
2412
2413			if (tcu::hasStencilComponent(reference.getFormat().order))
2414				clearStencil(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getStencil());
2415		}
2416
2417		if (renderInfo.getRenderQuad())
2418		{
2419			const RenderQuad&	renderQuad	= *renderInfo.getRenderQuad();
2420			const Vec4			posA		= renderQuad.getCornerA();
2421			const Vec4			posB		= renderQuad.getCornerB();
2422			const Vec2			origin		= Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
2423			const Vec2			p			= Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
2424			const IVec2			posAI		((deInt32)(origin.x() + (p.x() * posA.x())),
2425											 (deInt32)(origin.y() + (p.y() * posA.y())));
2426			const IVec2			posBI		((deInt32)(origin.x() + (p.x() * posB.x())),
2427											 (deInt32)(origin.y() + (p.y() * posB.y())));
2428
2429			for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++)
2430			{
2431				const Attachment				attachment			= renderPassInfo.getAttachments()[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
2432				const tcu::TextureFormatInfo	textureInfo			= tcu::getTextureFormatInfo(mapVkFormat(attachment.getFormat()));
2433				tcu::TextureLevel&				referenceTexture	= referenceAttachments[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
2434				const bool						srgb				= tcu::isSRGB(referenceTexture.getFormat());
2435				const PixelBufferAccess	reference			= referenceTexture.getAccess();
2436				const float						clampMin			= (float)(-MAX_INTEGER_VALUE);
2437				const float						clampMax			= (float)(MAX_INTEGER_VALUE);
2438				const Vec4						valueMax			(de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
2439																	 de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
2440																	 de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
2441																	 de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
2442
2443				const Vec4						valueMin			(de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
2444																	 de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
2445																	 de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
2446																	 de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
2447
2448				DE_ASSERT(posAI.x() < posBI.x());
2449				DE_ASSERT(posAI.y() < posBI.y());
2450
2451				for (int y = posAI.y(); y <= (int)posBI.y(); y++)
2452				for (int x = posAI.x(); x <= (int)posBI.x(); x++)
2453				{
2454					const Vec4	uvs		= computeUvs(posAI, posBI, IVec2(x, y));
2455					const Vec4	color	= valueMax * uvs + valueMin * (Vec4(1.0f) - uvs);
2456
2457					if (srgb)
2458						reference.setPixel(tcu::linearToSRGB(color), x, y);
2459					else
2460						reference.setPixel(color, x, y);
2461				}
2462			}
2463
2464			if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
2465			{
2466				tcu::TextureLevel&				referenceTexture	= referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
2467				const PixelBufferAccess	reference			= referenceTexture.getAccess();
2468
2469				DE_ASSERT(posAI.x() < posBI.x());
2470				DE_ASSERT(posAI.y() < posBI.y());
2471
2472				for (int y = posAI.y(); y <= (int)posBI.y(); y++)
2473				for (int x = posAI.x(); x <= (int)posBI.x(); x++)
2474				{
2475					const Vec4 uvs = computeUvs(posAI, posBI, IVec2(x, y));
2476
2477					if (tcu::hasDepthComponent(reference.getFormat().order))
2478						reference.setPixDepth(uvs.x(), x, y);
2479
2480					if (tcu::hasStencilComponent(reference.getFormat().order))
2481						reference.setPixStencil(STENCIL_VALUE, x, y);
2482				}
2483			}
2484		}
2485	}
2486
2487	// Mark all attachments that were used but not stored as undefined
2488	for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
2489	{
2490		const Attachment				attachment	= renderPassInfo.getAttachments()[attachmentNdx];
2491		const tcu::TextureFormat		format		= mapVkFormat(attachment.getFormat());
2492		const tcu::TextureFormatInfo	textureInfo	= tcu::getTextureFormatInfo(format);
2493		tcu::TextureLevel&				reference	= referenceAttachments[attachmentNdx];
2494
2495		if (attachmentUsed[attachmentNdx] && renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
2496			tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2497	}
2498}
2499
2500Maybe<deUint32> findColorAttachment (const Subpass&				subpass,
2501									 deUint32					attachmentIndex)
2502{
2503	for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpass.getColorAttachments().size(); colorAttachmentNdx++)
2504	{
2505		if (subpass.getColorAttachments()[colorAttachmentNdx].getAttachment() == attachmentIndex)
2506			return tcu::just((deUint32)colorAttachmentNdx);
2507	}
2508
2509	return tcu::nothing<deUint32>();
2510}
2511
2512int calcFloatDiff (float a, float b)
2513{
2514	const deUint32		au		= tcu::Float32(a).bits();
2515	const deUint32		bu		= tcu::Float32(b).bits();
2516
2517	const bool			asign	= (au & (0x1u << 31u)) != 0u;
2518	const bool			bsign	= (bu & (0x1u << 31u)) != 0u;
2519
2520	const deUint32		avalue	= (au & ((0x1u << 31u) - 1u));
2521	const deUint32		bvalue	= (bu & ((0x1u << 31u) - 1u));
2522
2523	if (asign != bsign)
2524		return avalue + bvalue + 1u;
2525	else if (avalue < bvalue)
2526		return bvalue - avalue;
2527	else
2528		return avalue - bvalue;
2529}
2530
2531bool comparePixelToDepthClearValue (const ConstPixelBufferAccess&	access,
2532									int								x,
2533									int								y,
2534									float							ref)
2535{
2536	const tcu::TextureFormat		format			= tcu::getEffectiveDepthStencilTextureFormat(access.getFormat(), tcu::Sampler::MODE_DEPTH);
2537	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
2538
2539	switch (channelClass)
2540	{
2541		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2542		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2543		{
2544			const int	bitDepth	= tcu::getTextureFormatBitDepth(format).x();
2545			const float	depth		= access.getPixDepth(x, y);
2546			const float	threshold	= 2.0f / (float)((1 << bitDepth) - 1);
2547
2548			return deFloatAbs(depth - ref) <= threshold;
2549		}
2550
2551		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2552		{
2553			const float	depth			= access.getPixDepth(x, y);
2554			const int	mantissaBits	= tcu::getTextureFormatMantissaBitDepth(format).x();
2555			const int	threshold		= 10 * 1 << (23 - mantissaBits);
2556
2557			DE_ASSERT(mantissaBits <= 23);
2558
2559			return calcFloatDiff(depth, ref) <= threshold;
2560		}
2561
2562		default:
2563			DE_FATAL("Invalid channel class");
2564			return false;
2565	}
2566}
2567
2568bool comparePixelToStencilClearValue (const ConstPixelBufferAccess&	access,
2569									  int							x,
2570									  int							y,
2571									  deUint32						ref)
2572{
2573	const deUint32 stencil = access.getPixStencil(x, y);
2574
2575	return stencil == ref;
2576}
2577
2578bool comparePixelToColorClearValue (const ConstPixelBufferAccess&	access,
2579									int								x,
2580									int								y,
2581									const VkClearColorValue&		ref)
2582{
2583	const tcu::TextureFormat		format			= access.getFormat();
2584	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
2585	const BVec4						channelMask		= tcu::getTextureFormatChannelMask(format);
2586
2587	switch (channelClass)
2588	{
2589		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2590		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2591		{
2592			const IVec4	bitDepth	(tcu::getTextureFormatBitDepth(format));
2593			const Vec4	resColor	(access.getPixel(x, y));
2594			const Vec4	refColor	(ref.float32[0],
2595									 ref.float32[1],
2596									 ref.float32[2],
2597									 ref.float32[3]);
2598			const Vec4	threshold	(bitDepth[0] > 0 ? 20.0f / (float)((1 << bitDepth[0]) - 1) : 1.0f,
2599									 bitDepth[1] > 0 ? 20.0f / (float)((1 << bitDepth[1]) - 1) : 1.0f,
2600									 bitDepth[2] > 0 ? 20.0f / (float)((1 << bitDepth[2]) - 1) : 1.0f,
2601									 bitDepth[3] > 0 ? 20.0f / (float)((1 << bitDepth[3]) - 1) : 1.0f);
2602
2603			if (tcu::isSRGB(access.getFormat()))
2604				return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, tcu::linearToSRGB(refColor)), threshold), channelMask), channelMask));
2605			else
2606				return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2607		}
2608
2609		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2610		{
2611			const UVec4	resColor	(access.getPixelUint(x, y));
2612			const UVec4	refColor	(ref.uint32[0],
2613									 ref.uint32[1],
2614									 ref.uint32[2],
2615									 ref.uint32[3]);
2616			const UVec4	threshold	(1);
2617
2618			return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2619		}
2620
2621		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2622		{
2623			const IVec4	resColor	(access.getPixelInt(x, y));
2624			const IVec4	refColor	(ref.int32[0],
2625									 ref.int32[1],
2626									 ref.int32[2],
2627									 ref.int32[3]);
2628			const IVec4	threshold	(1);
2629
2630			return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2631		}
2632
2633		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2634		{
2635			const Vec4	resColor		(access.getPixel(x, y));
2636			const Vec4	refColor		(ref.float32[0],
2637										 ref.float32[1],
2638										 ref.float32[2],
2639										 ref.float32[3]);
2640			const IVec4	mantissaBits	(tcu::getTextureFormatMantissaBitDepth(format));
2641			const IVec4	threshold		(10 * IVec4(1) << (23 - mantissaBits));
2642
2643			DE_ASSERT(tcu::allEqual(greaterThanEqual(threshold, IVec4(0)), BVec4(true)));
2644
2645			for (int ndx = 0; ndx < 4; ndx++)
2646			{
2647				if (calcFloatDiff(resColor[ndx], refColor[ndx]) > threshold[ndx] && channelMask[ndx])
2648					return false;
2649			}
2650
2651			return true;
2652		}
2653
2654		default:
2655			DE_FATAL("Invalid channel class");
2656			return false;
2657	}
2658}
2659
2660class PixelStatus
2661{
2662public:
2663	enum Status
2664	{
2665		STATUS_UNDEFINED	= 0,
2666		STATUS_OK			= 1,
2667		STATUS_FAIL			= 2,
2668
2669		STATUS_LAST
2670	};
2671
2672			PixelStatus			(Status color, Status depth, Status stencil)
2673				: m_status	((deUint8)((color << COLOR_OFFSET)
2674					| (depth << DEPTH_OFFSET)
2675					| (stencil << STENCIL_OFFSET)))
2676	{
2677	}
2678
2679	Status	getColorStatus		(void) const { return (Status)((m_status & COLOR_MASK) >> COLOR_OFFSET); }
2680	Status	getDepthStatus		(void) const { return (Status)((m_status & DEPTH_MASK) >> DEPTH_OFFSET); }
2681	Status	getStencilStatus	(void) const { return (Status)((m_status & STENCIL_MASK) >> STENCIL_OFFSET); }
2682
2683	void	setColorStatus		(Status status)
2684	{
2685		DE_ASSERT(getColorStatus() == STATUS_UNDEFINED);
2686		m_status |= (deUint8)(status << COLOR_OFFSET);
2687	}
2688
2689	void	setDepthStatus		(Status status)
2690	{
2691		DE_ASSERT(getDepthStatus() == STATUS_UNDEFINED);
2692		m_status |= (deUint8)(status << DEPTH_OFFSET);
2693	}
2694
2695	void	setStencilStatus	(Status status)
2696	{
2697		DE_ASSERT(getStencilStatus() == STATUS_UNDEFINED);
2698		m_status |= (deUint8)(status << STENCIL_OFFSET);
2699	}
2700
2701private:
2702	enum
2703	{
2704		COLOR_OFFSET	= 0,
2705		DEPTH_OFFSET	= 2,
2706		STENCIL_OFFSET	= 4,
2707
2708		COLOR_MASK		= (3<<COLOR_OFFSET),
2709		DEPTH_MASK		= (3<<DEPTH_OFFSET),
2710		STENCIL_MASK	= (3<<STENCIL_OFFSET),
2711	};
2712	deUint8	m_status;
2713};
2714
2715void checkDepthRenderQuad (const ConstPixelBufferAccess&	result,
2716						   const IVec2&						posA,
2717						   const IVec2&						posB,
2718						   vector<PixelStatus>&				status)
2719{
2720	for (int y = posA.y(); y <= posB.y(); y++)
2721	for (int x = posA.x(); x <= posB.x(); x++)
2722	{
2723		PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2724
2725		if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
2726		{
2727			const Vec4	minUvs		= computeUvs(posA, posB, IVec2(x-1, y-1));
2728			const Vec4	maxUvs		= computeUvs(posA, posB, IVec2(x+1, y+1));
2729			const bool	softCheck	= std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2730									|| std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2731			const float	resDepth	= result.getPixDepth(x, y);
2732
2733			if (resDepth >= minUvs.x() && resDepth <= maxUvs.x())
2734				pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
2735			else if (!softCheck)
2736				pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
2737		}
2738	}
2739}
2740
2741void checkStencilRenderQuad (const ConstPixelBufferAccess&		result,
2742							 const IVec2&						posA,
2743							 const IVec2&						posB,
2744							 vector<PixelStatus>&				status)
2745{
2746	for (int y = posA.y(); y <= posB.y(); y++)
2747	for (int x = posA.x(); x <= posB.x(); x++)
2748	{
2749		PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2750
2751		if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
2752		{
2753			const bool	softCheck	= std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2754									|| std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2755
2756			if (result.getPixStencil(x, y) == STENCIL_VALUE)
2757				pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
2758			else if (!softCheck)
2759				pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
2760		}
2761	}
2762}
2763
2764void checkColorRenderQuad (const ConstPixelBufferAccess&	result,
2765						   const IVec2&						posA,
2766						   const IVec2&						posB,
2767						   vector<PixelStatus>&				status)
2768{
2769	const tcu::TextureFormat&		format				= result.getFormat();
2770	const bool						srgb				= tcu::isSRGB(format);
2771	const tcu::TextureChannelClass	channelClass		= tcu::getTextureChannelClass(format.type);
2772	const tcu::TextureFormatInfo	textureInfo			= tcu::getTextureFormatInfo(format);
2773	const float						clampMin			= (float)(-MAX_INTEGER_VALUE);
2774	const float						clampMax			= (float)(MAX_INTEGER_VALUE);
2775	const Vec4						valueMax			(de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
2776														 de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
2777														 de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
2778														 de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
2779
2780	const Vec4						valueMin			(de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
2781														 de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
2782														 de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
2783														 de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
2784	const BVec4						channelMask			= tcu::getTextureFormatChannelMask(format);
2785
2786	IVec4						formatBitDepths = tcu::getTextureFormatBitDepth(format);
2787	Vec4						threshold = Vec4(1.0f) / Vec4((float)(1 << formatBitDepths.x()),
2788																(float)(1 << formatBitDepths.y()),
2789																(float)(1 << formatBitDepths.z()),
2790																(float)(1 << formatBitDepths.w()));
2791
2792	switch (channelClass)
2793	{
2794		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2795		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2796		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2797		{
2798			for (int y = posA.y(); y <= posB.y(); y++)
2799			for (int x = posA.x(); x <= posB.x(); x++)
2800			{
2801				PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2802
2803				if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2804				{
2805					const Vec4	minDiff		= Vec4(1.0f) / (IVec4(1) << tcu::getTextureFormatMantissaBitDepth(format)).cast<float>();
2806					const Vec4	minUvs		= computeUvs(posA, posB, IVec2(x-1, y-1));
2807					const Vec4	maxUvs		= computeUvs(posA, posB, IVec2(x+1, y+1));
2808					const bool	softCheck	= std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2809											|| std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2810
2811					const Vec4	resColor	(result.getPixel(x, y));
2812
2813					Vec4	minRefColor	= srgb ? tcu::linearToSRGB(valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs))
2814											 : valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs) - threshold;
2815					Vec4	maxRefColor	= srgb ? tcu::linearToSRGB(valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs))
2816											 : valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs) + threshold;
2817
2818					// Take into account rounding and quantization
2819					if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
2820					{
2821						minRefColor = tcu::min(minRefColor * (Vec4(1.0f) - minDiff), minRefColor * (Vec4(1.0f) + minDiff));
2822						maxRefColor = tcu::max(maxRefColor * (Vec4(1.0f) - minDiff), maxRefColor * (Vec4(1.0f) + minDiff));
2823					}
2824					else
2825					{
2826						minRefColor = minRefColor - minDiff;
2827						maxRefColor = maxRefColor + minDiff;
2828					}
2829
2830					DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2831					DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2832					DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2833					DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2834
2835					if (tcu::anyNotEqual(tcu::logicalAnd(
2836											tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2837															lessThanEqual(resColor, maxRefColor)),
2838											channelMask), channelMask))
2839					{
2840						if (!softCheck)
2841							pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2842					}
2843					else
2844						pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2845				}
2846			}
2847
2848			break;
2849		}
2850
2851		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2852		{
2853			for (int y = posA.y(); y <= posB.y(); y++)
2854			for (int x = posA.x(); x <= posB.x(); x++)
2855			{
2856				PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2857
2858				if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2859				{
2860					const Vec4	minUvs			= computeUvs(posA, posB, IVec2(x-1, y-1));
2861					const Vec4	maxUvs			= computeUvs(posA, posB, IVec2(x+1, y+1));
2862					const bool	softCheck		= std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2863												|| std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2864
2865					const UVec4	resColor		(result.getPixelUint(x, y));
2866
2867					const Vec4	minRefColorF	= valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
2868					const Vec4	maxRefColorF	= valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
2869
2870					const UVec4	minRefColor		(minRefColorF.asUint());
2871					const UVec4	maxRefColor		(maxRefColorF.asUint());
2872
2873					DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2874					DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2875					DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2876					DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2877
2878					if (tcu::anyNotEqual(tcu::logicalAnd(
2879											tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2880															lessThanEqual(resColor, maxRefColor)),
2881											channelMask), channelMask))
2882					{
2883						if (!softCheck)
2884							pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2885					}
2886					else
2887						pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2888				}
2889			}
2890
2891			break;
2892		}
2893
2894		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2895		{
2896			for (int y = posA.y(); y <= posB.y(); y++)
2897			for (int x = posA.x(); x <= posB.x(); x++)
2898			{
2899				PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2900
2901				if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2902				{
2903					const Vec4	minUvs			= computeUvs(posA, posB, IVec2(x-1, y-1));
2904					const Vec4	maxUvs			= computeUvs(posA, posB, IVec2(x+1, y+1));
2905					const bool	softCheck		= std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2906												|| std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2907
2908					const IVec4	resColor		(result.getPixelInt(x, y));
2909
2910					const Vec4	minRefColorF	= valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
2911					const Vec4	maxRefColorF	= valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
2912
2913					const IVec4	minRefColor		(minRefColorF.asInt());
2914					const IVec4	maxRefColor		(maxRefColorF.asInt());
2915
2916					DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2917					DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2918					DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2919					DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2920
2921					if (tcu::anyNotEqual(tcu::logicalAnd(
2922											tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2923															lessThanEqual(resColor, maxRefColor)),
2924											channelMask), channelMask))
2925					{
2926						if (!softCheck)
2927							pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2928					}
2929					else
2930						pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2931				}
2932			}
2933
2934			break;
2935		}
2936
2937		default:
2938			DE_FATAL("Invalid channel class");
2939	}
2940}
2941
2942void checkColorClear (const ConstPixelBufferAccess&	result,
2943					  const UVec2&					offset,
2944					  const UVec2&					size,
2945					  vector<PixelStatus>&			status,
2946					  const VkClearColorValue&		color)
2947{
2948	DE_ASSERT(offset.x() + size.x() <= (deUint32)result.getWidth());
2949	DE_ASSERT(offset.y() + size.y() <= (deUint32)result.getHeight());
2950
2951	DE_ASSERT(result.getWidth() * result.getHeight() == (int)status.size());
2952
2953	for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2954	for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2955	{
2956		PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2957
2958		DE_ASSERT(x + y * result.getWidth() < (int)status.size());
2959
2960		if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2961		{
2962			if (comparePixelToColorClearValue(result, x, y, color))
2963				pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2964			else
2965				pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2966		}
2967	}
2968}
2969
2970void checkDepthClear (const ConstPixelBufferAccess&	result,
2971					  const UVec2&					offset,
2972					  const UVec2&					size,
2973					  vector<PixelStatus>&			status,
2974					  float							depth)
2975{
2976	for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2977	for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2978	{
2979		PixelStatus&	pixelStatus	= status[x + y * result.getWidth()];
2980
2981		if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
2982		{
2983			if (comparePixelToDepthClearValue(result, x, y, depth))
2984				pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
2985			else
2986				pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
2987		}
2988	}
2989}
2990
2991void checkStencilClear (const ConstPixelBufferAccess&	result,
2992						const UVec2&					offset,
2993						const UVec2&					size,
2994						vector<PixelStatus>&			status,
2995						deUint32						stencil)
2996{
2997	for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2998	for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2999	{
3000		PixelStatus&	pixelStatus	= status[x + y * result.getWidth()];
3001
3002		if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
3003		{
3004			if (comparePixelToStencilClearValue(result, x, y, stencil))
3005				pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3006			else
3007				pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
3008		}
3009	}
3010}
3011
3012bool verifyAttachment (const ConstPixelBufferAccess&		result,
3013					   const Maybe<ConstPixelBufferAccess>&	secondaryResult,
3014					   const RenderPass&					renderPassInfo,
3015					   const Maybe<VkClearValue>&			renderPassClearValue,
3016					   const Maybe<VkClearValue>&			imageClearValue,
3017					   const vector<Subpass>&				subpasses,
3018					   const vector<SubpassRenderInfo>&		subpassRenderInfo,
3019					   const PixelBufferAccess&				errorImage,
3020					   deUint32								attachmentIndex,
3021					   const UVec2&							renderPos,
3022					   const UVec2&							renderSize)
3023{
3024	const tcu::TextureFormat&		format				= result.getFormat();
3025	const bool						hasDepth			= tcu::hasDepthComponent(format.order);
3026	const bool						hasStencil			= tcu::hasStencilComponent(format.order);
3027	const bool						isColorFormat		= !hasDepth && !hasStencil;
3028	const PixelStatus				initialStatus		(isColorFormat ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
3029														 hasDepth ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
3030														 hasStencil ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK);
3031
3032	bool							attachmentIsUsed	= false;
3033	vector<PixelStatus>				status				(result.getWidth() * result.getHeight(), initialStatus);
3034	tcu::clear(errorImage, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
3035
3036	// Check if attachment is used
3037	for (int subpassNdx = 0; subpassNdx < (int)subpasses.size(); subpassNdx++)
3038	{
3039		const Subpass&			subpass			= subpasses[subpassNdx];
3040		const Maybe<deUint32>	attachmentNdx	= findColorAttachment(subpass, attachmentIndex);
3041
3042		if (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex)
3043			attachmentIsUsed = true;
3044	}
3045
3046	// Set all pixels that have undefined values to OK
3047	if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3048							|| (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)))
3049	{
3050		for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
3051		for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
3052		{
3053			PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3054
3055			if (isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3056				pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
3057			else
3058			{
3059				if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3060					pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
3061
3062				if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3063					pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3064			}
3065		}
3066	}
3067
3068	// Check renderpass rendering results
3069	if (renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE
3070		|| (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE))
3071	{
3072		// Check subpass rendering results
3073		for (int subpassNdx = (int)subpasses.size() - 1; subpassNdx >= 0; subpassNdx--)
3074		{
3075			const Subpass&				subpass			= subpasses[subpassNdx];
3076			const SubpassRenderInfo&	renderInfo		= subpassRenderInfo[subpassNdx];
3077			const Maybe<deUint32>		attachmentNdx	= findColorAttachment(subpass, attachmentIndex);
3078
3079			// Check rendered quad
3080			if (renderInfo.getRenderQuad() && (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex))
3081			{
3082				const RenderQuad&	renderQuad	= *renderInfo.getRenderQuad();
3083				const Vec4			posA		= renderQuad.getCornerA();
3084				const Vec4			posB		= renderQuad.getCornerB();
3085				const Vec2			origin		= Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
3086				const Vec2			p			= Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
3087				const IVec2			posAI		((deInt32)(origin.x() + (p.x() * posA.x())),
3088												 (deInt32)(origin.y() + (p.y() * posA.y())));
3089				const IVec2			posBI		((deInt32)(origin.x() + (p.x() * posB.x())),
3090												 (deInt32)(origin.y() + (p.y() * posB.y())));
3091
3092				if (isColorFormat)
3093					checkColorRenderQuad(result, posAI, posBI, status);
3094				else
3095				{
3096					if (hasDepth)
3097						checkDepthRenderQuad(result, posAI, posBI, status);
3098
3099					if (hasDepth && hasStencil)
3100						checkStencilRenderQuad(*secondaryResult, posAI, posBI, status);
3101					else if (hasStencil)
3102						checkStencilRenderQuad(result, posAI, posBI, status);
3103				}
3104			}
3105
3106			// Check color attachment clears
3107			if (attachmentNdx && !renderInfo.getColorClears().empty())
3108			{
3109				const ColorClear& clear = renderInfo.getColorClears()[*attachmentNdx];
3110
3111				checkColorClear(result, clear.getOffset(), clear.getSize(), status, clear.getColor());
3112			}
3113
3114			// Check depth/stencil attachment clears
3115			if (subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex && renderInfo.getDepthStencilClear())
3116			{
3117				const DepthStencilClear clear = *renderInfo.getDepthStencilClear();
3118
3119				if (hasDepth)
3120					checkDepthClear(result, clear.getOffset(), clear.getSize(), status, clear.getDepth());
3121
3122				if (hasDepth && hasStencil)
3123					checkStencilClear(*secondaryResult, clear.getOffset(), clear.getSize(), status, clear.getStencil());
3124				else if (hasStencil)
3125					checkStencilClear(result, clear.getOffset(), clear.getSize(), status, clear.getStencil());
3126			}
3127		}
3128
3129		// Check renderpas clear results
3130		if (attachmentIsUsed && renderPassClearValue)
3131		{
3132			if (isColorFormat)
3133			{
3134				if (renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3135					checkColorClear(result, renderPos, renderSize, status, renderPassClearValue->color);
3136			}
3137			else
3138			{
3139				if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3140					checkDepthClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.depth);
3141
3142				if (hasDepth && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3143					checkStencilClear(*secondaryResult, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
3144				else if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3145					checkStencilClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
3146			}
3147		}
3148	}
3149
3150	// Set all pixels that have undefined values fater renderpass to OK
3151	if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3152							|| (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)))
3153	{
3154		for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
3155		for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
3156		{
3157			PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3158
3159			if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED
3160				&& isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3161				pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
3162			else
3163			{
3164				if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED
3165					&& hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3166					pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
3167
3168				if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED
3169					&& hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3170					pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3171			}
3172		}
3173	}
3174
3175	if (imageClearValue)
3176	{
3177		if (isColorFormat)
3178			checkColorClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->color);
3179		else
3180		{
3181			if (hasDepth)
3182				checkDepthClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.depth);
3183
3184			if (hasDepth && hasStencil)
3185				checkStencilClear(*secondaryResult, UVec2(0, 0), UVec2(secondaryResult->getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
3186			else if (hasStencil)
3187				checkStencilClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
3188		}
3189	}
3190
3191	{
3192		bool isOk = true;
3193
3194		for(int y = 0; y < result.getHeight(); y++)
3195		for(int x = 0; x < result.getWidth(); x++)
3196		{
3197			const PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3198
3199			if (isColorFormat)
3200			{
3201				if (pixelStatus.getColorStatus() != PixelStatus::STATUS_OK)
3202				{
3203					if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
3204						errorImage.setPixel(Vec4(1.0f, 1.0f, 0.0f, 1.0f), x, y);
3205					else if (pixelStatus.getColorStatus() == PixelStatus::STATUS_FAIL)
3206						errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3207
3208					isOk = false;
3209				}
3210			}
3211			else
3212			{
3213				if (hasDepth && pixelStatus.getDepthStatus() != PixelStatus::STATUS_OK)
3214				{
3215					errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3216					isOk = false;
3217				}
3218
3219				if (hasStencil && pixelStatus.getStencilStatus() != PixelStatus::STATUS_OK)
3220				{
3221					errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3222					isOk = false;
3223				}
3224			}
3225		}
3226
3227		return isOk;
3228	}
3229}
3230
3231bool logAndVerifyImages (TestLog&											log,
3232						 const DeviceInterface&								vk,
3233						 VkDevice											device,
3234						 const vector<de::SharedPtr<AttachmentResources> >&	attachmentResources,
3235						 const vector<bool>&								attachmentIsLazy,
3236						 const RenderPass&									renderPassInfo,
3237						 const vector<Maybe<VkClearValue> >&				renderPassClearValues,
3238						 const vector<Maybe<VkClearValue> >&				imageClearValues,
3239						 const vector<SubpassRenderInfo>&					subpassRenderInfo,
3240						 const UVec2&										targetSize,
3241						 const TestConfig&									config)
3242{
3243	vector<tcu::TextureLevel>	referenceAttachments;
3244	bool						isOk					= true;
3245
3246	log << TestLog::Message << "Reference images fill undefined pixels with grid pattern." << TestLog::EndMessage;
3247
3248	renderReferenceImages(referenceAttachments, renderPassInfo, targetSize, imageClearValues, renderPassClearValues, subpassRenderInfo, config.renderPos, config.renderSize);
3249
3250	for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3251	{
3252		if (!attachmentIsLazy[attachmentNdx])
3253		{
3254			const Attachment			attachment		= renderPassInfo.getAttachments()[attachmentNdx];
3255			const tcu::TextureFormat	format			= mapVkFormat(attachment.getFormat());
3256
3257			if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
3258			{
3259				const tcu::TextureFormat	depthFormat		= getDepthCopyFormat(attachment.getFormat());
3260				const VkDeviceSize			depthBufferSize	= targetSize.x() * targetSize.y() * depthFormat.getPixelSize();
3261				void* const					depthPtr		= attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
3262
3263				const tcu::TextureFormat	stencilFormat		= getStencilCopyFormat(attachment.getFormat());
3264				const VkDeviceSize			stencilBufferSize	= targetSize.x() * targetSize.y() * stencilFormat.getPixelSize();
3265				void* const					stencilPtr			= attachmentResources[attachmentNdx]->getSecondaryResultMemory().getHostPtr();
3266
3267				const VkMappedMemoryRange	ranges[] =
3268				{
3269					{
3270						VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,								// sType;
3271						DE_NULL,															// pNext;
3272						attachmentResources[attachmentNdx]->getResultMemory().getMemory(),	// mem;
3273						attachmentResources[attachmentNdx]->getResultMemory().getOffset(),	// offset;
3274						depthBufferSize														// size;
3275					},
3276					{
3277						VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,										// sType;
3278						DE_NULL,																	// pNext;
3279						attachmentResources[attachmentNdx]->getSecondaryResultMemory().getMemory(),	// mem;
3280						attachmentResources[attachmentNdx]->getSecondaryResultMemory().getOffset(),	// offset;
3281						stencilBufferSize															// size;
3282					}
3283				};
3284				VK_CHECK(vk.invalidateMappedMemoryRanges(device, 2u, ranges));
3285
3286				{
3287					const ConstPixelBufferAccess	depthAccess		(depthFormat, targetSize.x(), targetSize.y(), 1, depthPtr);
3288					const ConstPixelBufferAccess	stencilAccess	(stencilFormat, targetSize.x(), targetSize.y(), 1, stencilPtr);
3289					tcu::TextureLevel				errorImage		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
3290
3291					log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Depth", "Attachment " + de::toString(attachmentNdx) + " Depth", depthAccess);
3292					log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Stencil", "Attachment " + de::toString(attachmentNdx) + " Stencil", stencilAccess);
3293
3294					log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
3295
3296					if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
3297						&& !verifyAttachment(depthAccess, tcu::just(stencilAccess), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
3298					{
3299						log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
3300						isOk = false;
3301					}
3302				}
3303			}
3304			else
3305			{
3306				const VkDeviceSize			bufferSize	= targetSize.x() * targetSize.y() * format.getPixelSize();
3307				void* const					ptr			= attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
3308
3309				const VkMappedMemoryRange	range	=
3310				{
3311					VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,								// sType;
3312					DE_NULL,															// pNext;
3313					attachmentResources[attachmentNdx]->getResultMemory().getMemory(),	// mem;
3314					attachmentResources[attachmentNdx]->getResultMemory().getOffset(),	// offset;
3315					bufferSize															// size;
3316				};
3317				VK_CHECK(vk.invalidateMappedMemoryRanges(device, 1u, &range));
3318
3319				{
3320					const ConstPixelBufferAccess	access		(format, targetSize.x(), targetSize.y(), 1, ptr);
3321					tcu::TextureLevel				errorImage	(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
3322
3323					log << TestLog::Image("Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx), access);
3324					log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
3325
3326					if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
3327						&& !verifyAttachment(access, tcu::nothing<ConstPixelBufferAccess>(), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
3328					{
3329						log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
3330						isOk = false;
3331					}
3332				}
3333			}
3334		}
3335	}
3336
3337	return isOk;
3338}
3339
3340std::string getAttachmentType (VkFormat vkFormat)
3341{
3342	const tcu::TextureFormat		format			= mapVkFormat(vkFormat);
3343	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
3344
3345	switch (channelClass)
3346	{
3347		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
3348			return "ivec4";
3349
3350		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
3351			return "uvec4";
3352
3353		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
3354		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
3355		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
3356			return "vec4";
3357
3358		default:
3359			DE_FATAL("Unknown channel class");
3360			return "";
3361	}
3362}
3363
3364void createTestShaders (SourceCollections& dst, TestConfig config)
3365{
3366	if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
3367	{
3368		const vector<Subpass>&	subpasses	= config.renderPass.getSubpasses();
3369
3370		for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3371		{
3372			const Subpass&		subpass		= subpasses[subpassNdx];
3373			std::ostringstream	vertexShader;
3374			std::ostringstream	fragmentShader;
3375
3376			vertexShader << "#version 310 es\n"
3377						 << "layout(location = 0) in highp vec4 a_position;\n"
3378						 << "layout(location = 0) out highp vec2 v_color;\n"
3379						 << "void main (void) {\n"
3380						 << "\thighp float a = 0.5 + a_position.x;\n"
3381						 << "\thighp float b = 0.5 + a_position.y;\n"
3382						 << "\tv_color = vec2(a, b);\n"
3383						 << "\tgl_Position = a_position;\n"
3384						 << "}\n";
3385
3386			fragmentShader << "#version 310 es\n"
3387						   << "layout(location = 0) in highp vec2 v_color;\n";
3388
3389			for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
3390			{
3391				const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3392				fragmentShader << "layout(location = " << attachmentNdx << ") out highp " << attachmentType << " o_color" << attachmentNdx << ";\n";
3393			}
3394
3395			fragmentShader	<< "void main (void) {\n"
3396							<< "\thighp vec4 scale = vec4(v_color.x, v_color.y, v_color.x * v_color.y, (v_color.x + v_color.y) / 2.0);\n";
3397
3398			for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
3399			{
3400				const tcu::TextureFormat		format			= mapVkFormat(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3401				const tcu::TextureFormatInfo	formatInfo		= tcu::getTextureFormatInfo(format);
3402				const float						clampMin		= (float)(-MAX_INTEGER_VALUE);
3403				const float						clampMax		= (float)(MAX_INTEGER_VALUE);
3404				const Vec4						valueMax		(de::clamp(formatInfo.valueMax[0], clampMin, clampMax),
3405																 de::clamp(formatInfo.valueMax[1], clampMin, clampMax),
3406																 de::clamp(formatInfo.valueMax[2], clampMin, clampMax),
3407																 de::clamp(formatInfo.valueMax[3], clampMin, clampMax));
3408
3409				const Vec4						valueMin		(de::clamp(formatInfo.valueMin[0], clampMin, clampMax),
3410																 de::clamp(formatInfo.valueMin[1], clampMin, clampMax),
3411																 de::clamp(formatInfo.valueMin[2], clampMin, clampMax),
3412																 de::clamp(formatInfo.valueMin[3], clampMin, clampMax));
3413				const std::string				attachmentType	= getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3414
3415				fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "(vec4" << valueMin << " + vec4" << (valueMax - valueMin)  << " * scale);\n";
3416			}
3417
3418			fragmentShader << "}\n";
3419
3420			dst.glslSources.add(de::toString(subpassNdx) + "-vert") << glu::VertexSource(vertexShader.str());
3421			dst.glslSources.add(de::toString(subpassNdx) + "-frag") << glu::FragmentSource(fragmentShader.str());
3422		}
3423	}
3424}
3425
3426void initializeAttachmentIsLazy (vector<bool>& attachmentIsLazy, const vector<Attachment>& attachments, TestConfig::ImageMemory imageMemory)
3427{
3428	bool lastAttachmentWasLazy = false;
3429
3430	for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3431	{
3432		if (attachments[attachmentNdx].getLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
3433			&& attachments[attachmentNdx].getStoreOp() != VK_ATTACHMENT_STORE_OP_STORE
3434			&& attachments[attachmentNdx].getStencilLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
3435			&& attachments[attachmentNdx].getStencilStoreOp() != VK_ATTACHMENT_STORE_OP_STORE)
3436		{
3437			if (imageMemory == TestConfig::IMAGEMEMORY_LAZY || (imageMemory & TestConfig::IMAGEMEMORY_LAZY && !lastAttachmentWasLazy))
3438			{
3439				attachmentIsLazy.push_back(true);
3440				lastAttachmentWasLazy = true;
3441			}
3442			else if (imageMemory & TestConfig::IMAGEMEMORY_STRICT)
3443			{
3444				attachmentIsLazy.push_back(false);
3445				lastAttachmentWasLazy = false;
3446			}
3447			else
3448				DE_FATAL("Unknown imageMemory");
3449		}
3450		else
3451			attachmentIsLazy.push_back(false);
3452	}
3453}
3454
3455enum AttachmentRefType
3456{
3457	ATTACHMENTREFTYPE_COLOR,
3458	ATTACHMENTREFTYPE_DEPTH_STENCIL,
3459	ATTACHMENTREFTYPE_INPUT,
3460	ATTACHMENTREFTYPE_RESOLVE,
3461};
3462
3463VkImageUsageFlags getImageUsageFromLayout(VkImageLayout layout)
3464{
3465	switch (layout)
3466	{
3467		case VK_IMAGE_LAYOUT_GENERAL:
3468		case VK_IMAGE_LAYOUT_PREINITIALIZED:
3469			return 0;
3470		case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
3471			return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
3472		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
3473		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
3474			return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
3475		case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
3476			return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3477		case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
3478			return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3479		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
3480			return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3481		default:
3482			DE_FATAL("Unexpected image layout");
3483			return 0;
3484	}
3485}
3486
3487void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags>& attachmentImageUsage, AttachmentRefType refType, size_t count, const AttachmentReference* references)
3488{
3489	for (size_t referenceNdx = 0; referenceNdx < count; ++referenceNdx)
3490	{
3491		const deUint32 attachment = references[referenceNdx].getAttachment();
3492
3493		if (attachment != VK_ATTACHMENT_UNUSED)
3494		{
3495			VkImageUsageFlags usage;
3496
3497			switch (refType)
3498			{
3499				case ATTACHMENTREFTYPE_COLOR:
3500				case ATTACHMENTREFTYPE_RESOLVE:
3501					usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
3502					break;
3503				case ATTACHMENTREFTYPE_DEPTH_STENCIL:
3504					usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
3505					break;
3506				case ATTACHMENTREFTYPE_INPUT:
3507					usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
3508					break;
3509				default:
3510					DE_FATAL("Unexpected attachment reference type");
3511					usage = 0;
3512					break;
3513			}
3514
3515			attachmentImageUsage[attachment] |= usage;
3516		}
3517	}
3518}
3519
3520void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags>& attachmentImageUsage, AttachmentRefType refType, const vector<AttachmentReference>& references)
3521{
3522	if (!references.empty())
3523	{
3524		getImageUsageFromAttachmentReferences(attachmentImageUsage, refType, references.size(), &references[0]);
3525	}
3526}
3527
3528void initializeAttachmentImageUsage (Context &context, vector<VkImageUsageFlags>& attachmentImageUsage, const RenderPass& renderPassInfo, const vector<bool>& attachmentIsLazy, const vector<Maybe<VkClearValue> >& clearValues)
3529{
3530	attachmentImageUsage.resize(renderPassInfo.getAttachments().size(), VkImageUsageFlags(0));
3531
3532	for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); ++subpassNdx)
3533	{
3534		const Subpass& subpass = renderPassInfo.getSubpasses()[subpassNdx];
3535
3536		getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_COLOR, subpass.getColorAttachments());
3537		getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_DEPTH_STENCIL, 1, &subpass.getDepthStencilAttachment());
3538		getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_INPUT, subpass.getInputAttachments());
3539		getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_RESOLVE, subpass.getResolveAttachments());
3540	}
3541
3542	for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3543	{
3544		const Attachment& attachment = renderPassInfo.getAttachments()[attachmentNdx];
3545
3546		const VkFormatProperties		formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), attachment.getFormat());
3547		const VkFormatFeatureFlags		supportedFeatures = formatProperties.optimalTilingFeatures;
3548
3549		if ((supportedFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0)
3550			attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_SAMPLED_BIT;
3551
3552		if ((supportedFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0)
3553			attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_STORAGE_BIT;
3554
3555		attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getInitialLayout());
3556		attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getFinalLayout());
3557
3558		if (!attachmentIsLazy[attachmentNdx])
3559		{
3560			if (clearValues[attachmentNdx])
3561				attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3562
3563			attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3564		}
3565	}
3566}
3567
3568void initializeSubpassIsSecondary (vector<bool>& subpassIsSecondary, const vector<Subpass>& subpasses, TestConfig::CommandBufferTypes commandBuffer)
3569{
3570	bool lastSubpassWasSecondary = false;
3571
3572	for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3573	{
3574		if (commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary))
3575		{
3576			subpassIsSecondary.push_back(true);
3577			lastSubpassWasSecondary = true;
3578		}
3579		else if (commandBuffer & TestConfig::COMMANDBUFFERTYPES_INLINE)
3580		{
3581			subpassIsSecondary.push_back(false);
3582			lastSubpassWasSecondary = false;
3583		}
3584		else
3585			DE_FATAL("Unknown commandBuffer");
3586	}
3587}
3588
3589void initializeImageClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments, const vector<bool>& isLazy)
3590{
3591	for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3592	{
3593		if (!isLazy[attachmentNdx])
3594			clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
3595		else
3596			clearValues.push_back(nothing<VkClearValue>());
3597	}
3598}
3599
3600void initializeRenderPassClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments)
3601{
3602	for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3603	{
3604		if (attachments[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR
3605			|| attachments[attachmentNdx].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3606		{
3607			clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
3608		}
3609		else
3610			clearValues.push_back(nothing<VkClearValue>());
3611	}
3612}
3613
3614void initializeSubpassClearValues (de::Random& rng, vector<vector<VkClearColorValue> >& clearValues, const RenderPass& renderPass)
3615{
3616	clearValues.resize(renderPass.getSubpasses().size());
3617
3618	for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
3619	{
3620		const Subpass&						subpass				= renderPass.getSubpasses()[subpassNdx];
3621		const vector<AttachmentReference>&	colorAttachments	= subpass.getColorAttachments();
3622
3623		clearValues[subpassNdx].resize(colorAttachments.size());
3624
3625		for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
3626		{
3627			const AttachmentReference&	attachmentRef	= colorAttachments[attachmentRefNdx];
3628			const Attachment&			attachment		= renderPass.getAttachments()[attachmentRef.getAttachment()];
3629
3630			clearValues[subpassNdx][attachmentRefNdx] = randomColorClearValue(attachment, rng);
3631		}
3632	}
3633}
3634
3635void logSubpassRenderInfo (TestLog&					log,
3636						   const SubpassRenderInfo&	info)
3637{
3638	log << TestLog::Message << "Viewport, offset: " << info.getViewportOffset() << ", size: " << info.getViewportSize() << TestLog::EndMessage;
3639
3640	if (info.isSecondary())
3641		log << TestLog::Message << "Subpass uses secondary command buffers" << TestLog::EndMessage;
3642	else
3643		log << TestLog::Message << "Subpass uses inlined commands" << TestLog::EndMessage;
3644
3645	for (deUint32 attachmentNdx = 0; attachmentNdx < info.getColorClears().size(); attachmentNdx++)
3646	{
3647		const ColorClear&	colorClear	= info.getColorClears()[attachmentNdx];
3648
3649		log << TestLog::Message << "Clearing color attachment " << attachmentNdx
3650			<< ". Offset: " << colorClear.getOffset()
3651			<< ", Size: " << colorClear.getSize()
3652			<< ", Color: " << clearColorToString(info.getColorAttachment(attachmentNdx).getFormat(), colorClear.getColor()) << TestLog::EndMessage;
3653	}
3654
3655	if (info.getDepthStencilClear())
3656	{
3657		const DepthStencilClear&	depthStencilClear	= *info.getDepthStencilClear();
3658
3659		log << TestLog::Message << "Clearing depth stencil attachment"
3660			<< ". Offset: " << depthStencilClear.getOffset()
3661			<< ", Size: " << depthStencilClear.getSize()
3662			<< ", Depth: " << depthStencilClear.getDepth()
3663			<< ", Stencil: " << depthStencilClear.getStencil() << TestLog::EndMessage;
3664	}
3665
3666	if (info.getRenderQuad())
3667	{
3668		const RenderQuad&	renderQuad	= *info.getRenderQuad();
3669
3670		log << TestLog::Message << "Rendering gradient quad to " << renderQuad.getCornerA() << " -> " << renderQuad.getCornerB() << TestLog::EndMessage;
3671	}
3672}
3673
3674void logTestCaseInfo (TestLog&									log,
3675					  const TestConfig&							config,
3676					  const vector<bool>&						attachmentIsLazy,
3677					  const vector<Maybe<VkClearValue> >&		imageClearValues,
3678					  const vector<Maybe<VkClearValue> >&		renderPassClearValues,
3679					  const vector<SubpassRenderInfo>&			subpassRenderInfo)
3680{
3681	const RenderPass&	renderPass	= config.renderPass;
3682
3683	logRenderPassInfo(log, renderPass);
3684
3685	DE_ASSERT(attachmentIsLazy.size() == renderPass.getAttachments().size());
3686	DE_ASSERT(imageClearValues.size() == renderPass.getAttachments().size());
3687	DE_ASSERT(renderPassClearValues.size() == renderPass.getAttachments().size());
3688
3689	log << TestLog::Message << "TargetSize: " << config.targetSize << TestLog::EndMessage;
3690	log << TestLog::Message << "Render area, Offset: " << config.renderPos << ", Size: " << config.renderSize << TestLog::EndMessage;
3691
3692	for (size_t attachmentNdx = 0; attachmentNdx < attachmentIsLazy.size(); attachmentNdx++)
3693	{
3694		const tcu::ScopedLogSection	section	(log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
3695
3696		if (attachmentIsLazy[attachmentNdx])
3697			log << TestLog::Message << "Is lazy." << TestLog::EndMessage;
3698
3699		if (imageClearValues[attachmentNdx])
3700			log << TestLog::Message << "Image is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *imageClearValues[attachmentNdx]) << " before rendering." << TestLog::EndMessage;
3701
3702		if (renderPass.getAttachments()[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR && renderPassClearValues[attachmentNdx])
3703			log << TestLog::Message << "Attachment is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *renderPassClearValues[attachmentNdx]) << " in the beginning of the render pass." << TestLog::EndMessage;
3704	}
3705
3706	for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
3707	{
3708		const tcu::ScopedLogSection section (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
3709
3710		logSubpassRenderInfo(log, subpassRenderInfo[subpassNdx]);
3711	}
3712}
3713
3714void initializeSubpassRenderInfo (vector<SubpassRenderInfo>& renderInfos, de::Random& rng, const RenderPass& renderPass, const TestConfig& config)
3715{
3716	const TestConfig::CommandBufferTypes	commandBuffer			= config.commandBufferTypes;
3717	const vector<Subpass>&					subpasses				= renderPass.getSubpasses();
3718	bool									lastSubpassWasSecondary	= false;
3719
3720	for (deUint32 subpassNdx = 0; subpassNdx < (deUint32)subpasses.size(); subpassNdx++)
3721	{
3722		const Subpass&				subpass				= subpasses[subpassNdx];
3723		const bool					subpassIsSecondary	= commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY
3724														|| (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary) ? true : false;
3725		const UVec2					viewportSize		((config.renderSize * UVec2(2)) / UVec2(3));
3726		const UVec2					viewportOffset		(config.renderPos.x() + (subpassNdx % 2) * (config.renderSize.x() / 3),
3727														 config.renderPos.y() + ((subpassNdx / 2) % 2) * (config.renderSize.y() / 3));
3728
3729		vector<ColorClear>			colorClears;
3730		Maybe<DepthStencilClear>	depthStencilClear;
3731		Maybe<RenderQuad>			renderQuad;
3732
3733		lastSubpassWasSecondary		= subpassIsSecondary;
3734
3735		if (config.renderTypes & TestConfig::RENDERTYPES_CLEAR)
3736		{
3737			const vector<AttachmentReference>&	colorAttachments	= subpass.getColorAttachments();
3738
3739			for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
3740			{
3741				const AttachmentReference&	attachmentRef	= colorAttachments[attachmentRefNdx];
3742				const Attachment&			attachment		= renderPass.getAttachments()[attachmentRef.getAttachment()];
3743				const UVec2					size			((viewportSize * UVec2(2)) / UVec2(3));
3744				const UVec2					offset			(viewportOffset.x() + ((deUint32)attachmentRefNdx % 2u) * (viewportSize.x() / 3u),
3745															 viewportOffset.y() + (((deUint32)attachmentRefNdx / 2u) % 2u) * (viewportSize.y() / 3u));
3746				const VkClearColorValue		color			= randomColorClearValue(attachment, rng);
3747
3748				colorClears.push_back(ColorClear(offset, size, color));
3749			}
3750
3751			if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
3752			{
3753				const Attachment&	attachment		= renderPass.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()];
3754				const UVec2			size			((viewportSize * UVec2(2)) / UVec2(3));
3755				const UVec2			offset			(viewportOffset.x() + ((deUint32)colorAttachments.size() % 2u) * (viewportSize.x() / 3u),
3756													 viewportOffset.y() + (((deUint32)colorAttachments.size() / 2u) % 2u) * (viewportSize.y() / 3u));
3757				const VkClearValue	value			= randomClearValue(attachment, rng);
3758
3759				depthStencilClear = tcu::just(DepthStencilClear(offset, size, value.depthStencil.depth, value.depthStencil.stencil));
3760			}
3761		}
3762
3763		if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
3764		{
3765			// (-0.5,-0.5) - (0.5,0.5) rounded to pixel edges
3766			const float x = (float)(viewportSize.x() / 4) / (float)(viewportSize.x() / 2);
3767			const float y = (float)(viewportSize.y() / 4) / (float)(viewportSize.y() / 2);
3768			renderQuad = tcu::just(RenderQuad(tcu::Vec4(-x, -y, 0.0f, 1.0f), tcu::Vec4(x, y, 1.0f, 1.0f)));
3769		}
3770
3771		renderInfos.push_back(SubpassRenderInfo(renderPass, subpassNdx, subpassIsSecondary, viewportOffset, viewportSize, renderQuad, colorClears, depthStencilClear));
3772	}
3773}
3774
3775void checkTextureFormatSupport (TestLog&					log,
3776								const InstanceInterface&	vk,
3777								VkPhysicalDevice			device,
3778								const vector<Attachment>&	attachments)
3779{
3780	bool supported = true;
3781
3782	for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3783	{
3784		const Attachment&			attachment					= attachments[attachmentNdx];
3785		const tcu::TextureFormat	format						= mapVkFormat(attachment.getFormat());
3786		const bool					isDepthOrStencilAttachment	= hasDepthComponent(format.order) || hasStencilComponent(format.order);
3787		const VkFormatFeatureFlags	flags						= isDepthOrStencilAttachment? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
3788		VkFormatProperties			properties;
3789
3790		vk.getPhysicalDeviceFormatProperties(device, attachment.getFormat(), &properties);
3791
3792		if ((properties.optimalTilingFeatures & flags) != flags)
3793		{
3794			supported = false;
3795			log << TestLog::Message << "Format: " << attachment.getFormat() << " not supported as " << (isDepthOrStencilAttachment ? "depth stencil attachment" : "color attachment") << TestLog::EndMessage;
3796		}
3797	}
3798
3799	if (!supported)
3800		TCU_THROW(NotSupportedError, "Format not supported");
3801}
3802
3803tcu::TestStatus renderPassTest (Context& context, TestConfig config)
3804{
3805	const UVec2							targetSize			= config.targetSize;
3806	const UVec2							renderPos			= config.renderPos;
3807	const UVec2							renderSize			= config.renderSize;
3808	const RenderPass&					renderPassInfo		= config.renderPass;
3809
3810	TestLog&							log					= context.getTestContext().getLog();
3811	de::Random							rng					(config.seed);
3812
3813	vector<bool>						attachmentIsLazy;
3814	vector<VkImageUsageFlags>			attachmentImageUsage;
3815	vector<Maybe<VkClearValue> >		imageClearValues;
3816	vector<Maybe<VkClearValue> >		renderPassClearValues;
3817
3818	vector<bool>						subpassIsSecondary;
3819	vector<SubpassRenderInfo>			subpassRenderInfo;
3820	vector<vector<VkClearColorValue> >	subpassColorClearValues;
3821
3822	initializeAttachmentIsLazy(attachmentIsLazy, renderPassInfo.getAttachments(), config.imageMemory);
3823	initializeImageClearValues(rng, imageClearValues, renderPassInfo.getAttachments(), attachmentIsLazy);
3824	initializeAttachmentImageUsage(context, attachmentImageUsage, renderPassInfo, attachmentIsLazy, imageClearValues);
3825	initializeRenderPassClearValues(rng, renderPassClearValues, renderPassInfo.getAttachments());
3826
3827	initializeSubpassIsSecondary(subpassIsSecondary, renderPassInfo.getSubpasses(), config.commandBufferTypes);
3828	initializeSubpassClearValues(rng, subpassColorClearValues, renderPassInfo);
3829	initializeSubpassRenderInfo(subpassRenderInfo, rng, renderPassInfo, config);
3830
3831	logTestCaseInfo(log, config, attachmentIsLazy, imageClearValues, renderPassClearValues, subpassRenderInfo);
3832
3833	checkTextureFormatSupport(log, context.getInstanceInterface(), context.getPhysicalDevice(), config.renderPass.getAttachments());
3834
3835	{
3836		const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3837
3838		log << TestLog::Message << "Max color attachments: " << properties.limits.maxColorAttachments << TestLog::EndMessage;
3839
3840		for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
3841		{
3842			 if (renderPassInfo.getSubpasses()[subpassNdx].getColorAttachments().size() > (size_t)properties.limits.maxColorAttachments)
3843				 TCU_THROW(NotSupportedError, "Subpass uses more than maxColorAttachments.");
3844		}
3845	}
3846
3847	{
3848		const VkDevice								device								= context.getDevice();
3849		const DeviceInterface&						vk									= context.getDeviceInterface();
3850		const VkQueue								queue								= context.getUniversalQueue();
3851		const deUint32								queueIndex							= context.getUniversalQueueFamilyIndex();
3852		Allocator&									allocator							= context.getDefaultAllocator();
3853
3854		const Unique<VkRenderPass>					renderPass							(createRenderPass(vk, device, renderPassInfo));
3855		const Unique<VkCommandPool>					commandBufferPool					(createCommandPool(vk, device, queueIndex, 0));
3856		const Unique<VkCommandBuffer>				initializeImagesCommandBuffer		(allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3857		const Unique<VkCommandBuffer>				renderCommandBuffer					(allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3858		const Unique<VkCommandBuffer>				readImagesToBuffersCommandBuffer	(allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3859
3860		vector<de::SharedPtr<AttachmentResources> >	attachmentResources;
3861		vector<de::SharedPtr<SubpassRenderer> >		subpassRenderers;
3862		vector<VkImageView>							attachmentViews;
3863
3864		for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3865		{
3866			const Attachment&	attachmentInfo	= renderPassInfo.getAttachments()[attachmentNdx];
3867
3868			attachmentResources.push_back(de::SharedPtr<AttachmentResources>(new AttachmentResources(vk, device, allocator, queueIndex, targetSize, attachmentInfo, attachmentImageUsage[attachmentNdx])));
3869			attachmentViews.push_back(attachmentResources[attachmentNdx]->getAttachmentView());
3870		}
3871
3872		beginCommandBuffer(vk, *initializeImagesCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3873		pushImageInitializationCommands(vk, *initializeImagesCommandBuffer, renderPassInfo.getAttachments(), attachmentResources, queueIndex, imageClearValues);
3874		endCommandBuffer(vk, *initializeImagesCommandBuffer);
3875
3876		{
3877			const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, device, *renderPass, targetSize, attachmentViews));
3878
3879			for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
3880				subpassRenderers.push_back(de::SharedPtr<SubpassRenderer>(new SubpassRenderer(context, vk, device, allocator, *renderPass, *framebuffer, *commandBufferPool, queueIndex, subpassRenderInfo[subpassNdx])));
3881
3882			beginCommandBuffer(vk, *renderCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3883			pushRenderPassCommands(vk, *renderCommandBuffer, *renderPass, *framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, config.renderTypes);
3884			endCommandBuffer(vk, *renderCommandBuffer);
3885
3886			beginCommandBuffer(vk, *readImagesToBuffersCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3887			pushReadImagesToBuffers(vk, *readImagesToBuffersCommandBuffer, queueIndex, attachmentResources, renderPassInfo.getAttachments(), attachmentIsLazy, targetSize);
3888			endCommandBuffer(vk, *readImagesToBuffersCommandBuffer);
3889			{
3890				const VkCommandBuffer commandBuffers[] =
3891				{
3892					*initializeImagesCommandBuffer,
3893					*renderCommandBuffer,
3894					*readImagesToBuffersCommandBuffer
3895				};
3896				const Unique<VkFence>	fence		(createFence(vk, device, 0u));
3897
3898				queueSubmit(vk, queue, DE_LENGTH_OF_ARRAY(commandBuffers), commandBuffers, *fence);
3899				waitForFences(vk, device, 1, &fence.get(), VK_TRUE, ~0ull);
3900			}
3901		}
3902
3903		if (logAndVerifyImages(log, vk, device, attachmentResources, attachmentIsLazy, renderPassInfo, renderPassClearValues, imageClearValues, subpassRenderInfo, targetSize, config))
3904			return tcu::TestStatus::pass("Pass");
3905		else
3906			return tcu::TestStatus::fail("Result verification failed");
3907	}
3908}
3909
3910static const VkFormat s_coreColorFormats[] =
3911{
3912	VK_FORMAT_R5G6B5_UNORM_PACK16,
3913	VK_FORMAT_R8_UNORM,
3914	VK_FORMAT_R8_SNORM,
3915	VK_FORMAT_R8_UINT,
3916	VK_FORMAT_R8_SINT,
3917	VK_FORMAT_R8G8_UNORM,
3918	VK_FORMAT_R8G8_SNORM,
3919	VK_FORMAT_R8G8_UINT,
3920	VK_FORMAT_R8G8_SINT,
3921	VK_FORMAT_R8G8B8A8_UNORM,
3922	VK_FORMAT_R8G8B8A8_SNORM,
3923	VK_FORMAT_R8G8B8A8_UINT,
3924	VK_FORMAT_R8G8B8A8_SINT,
3925	VK_FORMAT_R8G8B8A8_SRGB,
3926	VK_FORMAT_A8B8G8R8_UNORM_PACK32,
3927	VK_FORMAT_A8B8G8R8_SNORM_PACK32,
3928	VK_FORMAT_A8B8G8R8_UINT_PACK32,
3929	VK_FORMAT_A8B8G8R8_SINT_PACK32,
3930	VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3931	VK_FORMAT_B8G8R8A8_UNORM,
3932	VK_FORMAT_B8G8R8A8_SRGB,
3933	VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3934	VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3935	VK_FORMAT_A2B10G10R10_UINT_PACK32,
3936	VK_FORMAT_R16_UNORM,
3937	VK_FORMAT_R16_SNORM,
3938	VK_FORMAT_R16_UINT,
3939	VK_FORMAT_R16_SINT,
3940	VK_FORMAT_R16_SFLOAT,
3941	VK_FORMAT_R16G16_UNORM,
3942	VK_FORMAT_R16G16_SNORM,
3943	VK_FORMAT_R16G16_UINT,
3944	VK_FORMAT_R16G16_SINT,
3945	VK_FORMAT_R16G16_SFLOAT,
3946	VK_FORMAT_R16G16B16A16_UNORM,
3947	VK_FORMAT_R16G16B16A16_SNORM,
3948	VK_FORMAT_R16G16B16A16_UINT,
3949	VK_FORMAT_R16G16B16A16_SINT,
3950	VK_FORMAT_R16G16B16A16_SFLOAT,
3951	VK_FORMAT_R32_UINT,
3952	VK_FORMAT_R32_SINT,
3953	VK_FORMAT_R32_SFLOAT,
3954	VK_FORMAT_R32G32_UINT,
3955	VK_FORMAT_R32G32_SINT,
3956	VK_FORMAT_R32G32_SFLOAT,
3957	VK_FORMAT_R32G32B32A32_UINT,
3958	VK_FORMAT_R32G32B32A32_SINT,
3959	VK_FORMAT_R32G32B32A32_SFLOAT
3960};
3961
3962static const VkFormat s_coreDepthStencilFormats[] =
3963{
3964	VK_FORMAT_D16_UNORM,
3965
3966	VK_FORMAT_X8_D24_UNORM_PACK32,
3967	VK_FORMAT_D32_SFLOAT,
3968
3969	VK_FORMAT_D24_UNORM_S8_UINT,
3970	VK_FORMAT_D32_SFLOAT_S8_UINT
3971};
3972
3973de::MovePtr<tcu::TestCaseGroup> createAttachmentTestCaseGroup (tcu::TestContext& testCtx)
3974{
3975	const deUint32 attachmentCounts[] = { 1, 3, 4, 8 };
3976	const VkAttachmentLoadOp loadOps[] =
3977	{
3978		VK_ATTACHMENT_LOAD_OP_LOAD,
3979		VK_ATTACHMENT_LOAD_OP_CLEAR,
3980		VK_ATTACHMENT_LOAD_OP_DONT_CARE
3981	};
3982
3983	const VkAttachmentStoreOp storeOps[] =
3984	{
3985		VK_ATTACHMENT_STORE_OP_STORE,
3986		VK_ATTACHMENT_STORE_OP_DONT_CARE
3987	};
3988
3989	const VkImageLayout initialAndFinalColorLayouts[] =
3990	{
3991		VK_IMAGE_LAYOUT_GENERAL,
3992		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3993		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
3994		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3995		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
3996	};
3997
3998	const VkImageLayout initialAndFinalDepthStencilLayouts[] =
3999	{
4000		VK_IMAGE_LAYOUT_GENERAL,
4001		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4002		VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
4003		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
4004		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4005		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
4006	};
4007
4008	const VkImageLayout subpassLayouts[] =
4009	{
4010		VK_IMAGE_LAYOUT_GENERAL,
4011		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
4012	};
4013
4014	const VkImageLayout depthStencilLayouts[] =
4015	{
4016		VK_IMAGE_LAYOUT_GENERAL,
4017		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
4018	};
4019
4020	const TestConfig::RenderTypes renderCommands[] =
4021	{
4022		TestConfig::RENDERTYPES_NONE,
4023		TestConfig::RENDERTYPES_CLEAR,
4024		TestConfig::RENDERTYPES_DRAW,
4025		TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
4026	};
4027
4028	const TestConfig::CommandBufferTypes commandBuffers[] =
4029	{
4030		TestConfig::COMMANDBUFFERTYPES_INLINE,
4031		TestConfig::COMMANDBUFFERTYPES_SECONDARY,
4032		TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
4033	};
4034
4035	const TestConfig::ImageMemory imageMemories[] =
4036	{
4037		TestConfig::IMAGEMEMORY_STRICT,
4038		TestConfig::IMAGEMEMORY_LAZY,
4039		TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
4040	};
4041
4042	const UVec2 targetSizes[] =
4043	{
4044		UVec2(64, 64),
4045		UVec2(63, 65)
4046	};
4047
4048	const UVec2 renderPositions[] =
4049	{
4050		UVec2(0, 0),
4051		UVec2(3, 17)
4052	};
4053
4054	const UVec2 renderSizes[] =
4055	{
4056		UVec2(32, 32),
4057		UVec2(60, 47)
4058	};
4059
4060	de::Random rng (1433774382u);
4061	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "attachment", "Attachment format and count tests with load and store ops and image layouts"));
4062
4063	for (size_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++)
4064	{
4065		const deUint32					attachmentCount			= attachmentCounts[attachmentCountNdx];
4066		const deUint32					testCaseCount			= (attachmentCount == 1 ? 100 : 200);
4067		de::MovePtr<tcu::TestCaseGroup>	attachmentCountGroup	(new tcu::TestCaseGroup(testCtx, de::toString(attachmentCount).c_str(), de::toString(attachmentCount).c_str()));
4068
4069		for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
4070		{
4071			const bool					useDepthStencil		= rng.getBool();
4072			VkImageLayout				depthStencilLayout	= VK_IMAGE_LAYOUT_GENERAL;
4073			vector<Attachment>			attachments;
4074			vector<AttachmentReference>	colorAttachmentReferences;
4075
4076			for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
4077			{
4078				const VkSampleCountFlagBits	sampleCount		= VK_SAMPLE_COUNT_1_BIT;
4079				const VkFormat				format			= rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
4080				const VkAttachmentLoadOp	loadOp			= rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4081				const VkAttachmentStoreOp	storeOp			= rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4082
4083				const VkImageLayout			initialLayout	= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4084				const VkImageLayout			finalizeLayout	= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4085				const VkImageLayout			subpassLayout	= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4086
4087				const VkAttachmentLoadOp	stencilLoadOp	= rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4088				const VkAttachmentStoreOp	stencilStoreOp	= rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4089
4090				attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4091				colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4092			}
4093
4094			if (useDepthStencil)
4095			{
4096				const VkSampleCountFlagBits	sampleCount			= VK_SAMPLE_COUNT_1_BIT;
4097				const VkFormat				format				= rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats), DE_ARRAY_END(s_coreDepthStencilFormats));
4098				const VkAttachmentLoadOp	loadOp				= rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4099				const VkAttachmentStoreOp	storeOp				= rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4100
4101				const VkImageLayout			initialLayout		= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
4102				const VkImageLayout			finalizeLayout		= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
4103
4104				const VkAttachmentLoadOp	stencilLoadOp		= rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4105				const VkAttachmentStoreOp	stencilStoreOp		= rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4106
4107				depthStencilLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(depthStencilLayouts), DE_ARRAY_END(depthStencilLayouts));
4108				attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4109			}
4110
4111			{
4112				const TestConfig::RenderTypes			render			= rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
4113				const TestConfig::CommandBufferTypes	commandBuffer	= rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
4114				const TestConfig::ImageMemory			imageMemory		= rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
4115				const vector<Subpass>					subpasses		(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference((useDepthStencil ? (deUint32)(attachments.size() - 1) : VK_ATTACHMENT_UNUSED), depthStencilLayout), vector<AttachmentReference>()));
4116				const vector<SubpassDependency>			deps;
4117
4118				const string							testCaseName	= de::toString(attachmentCountNdx * testCaseCount + testCaseNdx);
4119				const RenderPass						renderPass		(attachments, subpasses, deps);
4120				const UVec2								targetSize		= rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
4121				const UVec2								renderPos		= rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
4122				const UVec2								renderSize		= rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
4123
4124				addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 1293809));
4125			}
4126		}
4127
4128		group->addChild(attachmentCountGroup.release());
4129	}
4130
4131	return group;
4132}
4133
4134de::MovePtr<tcu::TestCaseGroup> createAttachmentAllocationTestGroup (tcu::TestContext& testCtx)
4135{
4136	const deUint32 attachmentCounts[] = { 4, 8 };
4137	const VkAttachmentLoadOp loadOps[] =
4138	{
4139		VK_ATTACHMENT_LOAD_OP_LOAD,
4140		VK_ATTACHMENT_LOAD_OP_CLEAR,
4141		VK_ATTACHMENT_LOAD_OP_DONT_CARE
4142	};
4143
4144	const VkAttachmentStoreOp storeOps[] =
4145	{
4146		VK_ATTACHMENT_STORE_OP_STORE,
4147		VK_ATTACHMENT_STORE_OP_DONT_CARE
4148	};
4149
4150	const VkImageLayout initialAndFinalColorLayouts[] =
4151	{
4152		VK_IMAGE_LAYOUT_GENERAL,
4153		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4154		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
4155		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4156		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
4157	};
4158
4159	const VkImageLayout subpassLayouts[] =
4160	{
4161		VK_IMAGE_LAYOUT_GENERAL,
4162		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4163	};
4164
4165	enum AllocationType
4166	{
4167		// Each pass uses one more attachmen than previous one
4168		ALLOCATIONTYPE_GROW,
4169		// Each pass uses one less attachment than previous one
4170		ALLOCATIONTYPE_SHRINK,
4171		// Each pass drops one attachment and picks up new one
4172		ALLOCATIONTYPE_ROLL,
4173		// Start by growing and end by shrinking
4174		ALLOCATIONTYPE_GROW_SHRINK
4175	};
4176
4177	const AllocationType allocationTypes[] =
4178	{
4179		ALLOCATIONTYPE_GROW,
4180		ALLOCATIONTYPE_SHRINK,
4181		ALLOCATIONTYPE_ROLL,
4182		ALLOCATIONTYPE_GROW_SHRINK
4183	};
4184
4185	const char* const allocationTypeStr[] =
4186	{
4187		"grow",
4188		"shrink",
4189		"roll",
4190		"grow_shrink"
4191	};
4192
4193	const TestConfig::RenderTypes renderCommands[] =
4194	{
4195		TestConfig::RENDERTYPES_NONE,
4196		TestConfig::RENDERTYPES_CLEAR,
4197		TestConfig::RENDERTYPES_DRAW,
4198		TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
4199	};
4200
4201	const TestConfig::CommandBufferTypes commandBuffers[] =
4202	{
4203		TestConfig::COMMANDBUFFERTYPES_INLINE,
4204		TestConfig::COMMANDBUFFERTYPES_SECONDARY,
4205		TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
4206	};
4207
4208	const TestConfig::ImageMemory imageMemories[] =
4209	{
4210		TestConfig::IMAGEMEMORY_STRICT,
4211		TestConfig::IMAGEMEMORY_LAZY,
4212		TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
4213	};
4214
4215	const UVec2 targetSizes[] =
4216	{
4217		UVec2(64, 64),
4218		UVec2(63, 65)
4219	};
4220
4221	const UVec2 renderPositions[] =
4222	{
4223		UVec2(0, 0),
4224		UVec2(3, 17)
4225	};
4226
4227	const UVec2 renderSizes[] =
4228	{
4229		UVec2(32, 32),
4230		UVec2(60, 47)
4231	};
4232
4233	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "attachment_allocation", "Attachment allocation tests"));
4234	de::Random						rng		(3700649827u);
4235
4236	for (size_t allocationTypeNdx = 0; allocationTypeNdx < DE_LENGTH_OF_ARRAY(allocationTypes); allocationTypeNdx++)
4237	{
4238		const AllocationType			allocationType		= allocationTypes[allocationTypeNdx];
4239		const size_t					testCaseCount		= 100;
4240		de::MovePtr<tcu::TestCaseGroup>	allocationTypeGroup	(new tcu::TestCaseGroup(testCtx, allocationTypeStr[allocationTypeNdx], allocationTypeStr[allocationTypeNdx]));
4241
4242		for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
4243		{
4244			const deUint32		attachmentCount	= rng.choose<deUint32>(DE_ARRAY_BEGIN(attachmentCounts), DE_ARRAY_END(attachmentCounts));
4245			vector<Attachment>	attachments;
4246			vector<Subpass>		subpasses;
4247
4248			for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
4249			{
4250				const VkSampleCountFlagBits	sampleCount		= VK_SAMPLE_COUNT_1_BIT;
4251				const VkFormat				format			= rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
4252				const VkAttachmentLoadOp	loadOp			= rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4253				const VkAttachmentStoreOp	storeOp			= rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4254
4255				const VkImageLayout			initialLayout	= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4256				const VkImageLayout			finalizeLayout	= rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
4257
4258				const VkAttachmentLoadOp	stencilLoadOp	= rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4259				const VkAttachmentStoreOp	stencilStoreOp	= rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4260
4261				attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4262			}
4263
4264			if (allocationType == ALLOCATIONTYPE_GROW)
4265			{
4266				for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4267				{
4268					vector<AttachmentReference>	colorAttachmentReferences;
4269
4270					for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
4271					{
4272						const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4273
4274						colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4275					}
4276
4277					subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4278				}
4279			}
4280			else if (allocationType == ALLOCATIONTYPE_SHRINK)
4281			{
4282				for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4283				{
4284					vector<AttachmentReference>	colorAttachmentReferences;
4285
4286					for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
4287					{
4288						const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4289
4290						colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4291					}
4292
4293					subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4294				}
4295			}
4296			else if (allocationType == ALLOCATIONTYPE_ROLL)
4297			{
4298				for (size_t subpassNdx = 0; subpassNdx < attachmentCount / 2; subpassNdx++)
4299				{
4300					vector<AttachmentReference>	colorAttachmentReferences;
4301
4302					for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount / 2; attachmentNdx++)
4303					{
4304						const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4305
4306						colorAttachmentReferences.push_back(AttachmentReference((deUint32)(subpassNdx + attachmentNdx), subpassLayout));
4307					}
4308
4309					subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4310				}
4311			}
4312			else if (allocationType == ALLOCATIONTYPE_GROW_SHRINK)
4313			{
4314				for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4315				{
4316					vector<AttachmentReference>	colorAttachmentReferences;
4317
4318					for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
4319					{
4320						const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4321
4322						colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4323					}
4324
4325					subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4326				}
4327
4328				for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4329				{
4330					vector<AttachmentReference>	colorAttachmentReferences;
4331
4332					for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
4333					{
4334						const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4335
4336						colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4337					}
4338
4339					subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4340				}
4341			}
4342			else
4343				DE_FATAL("Unknown allocation type");
4344
4345			{
4346				const TestConfig::RenderTypes			render			= rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
4347				const TestConfig::CommandBufferTypes	commandBuffer	= rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
4348				const TestConfig::ImageMemory			imageMemory		= rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
4349
4350				const string							testCaseName	= de::toString(testCaseNdx);
4351				const UVec2								targetSize		= rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
4352				const UVec2								renderPos		= rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
4353				const UVec2								renderSize		= rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
4354
4355				vector<SubpassDependency>				deps;
4356
4357				for (size_t subpassNdx = 0; subpassNdx < subpasses.size() - 1; subpassNdx++)
4358				{
4359					const bool byRegion				= rng.getBool();
4360					deps.push_back(SubpassDependency((deUint32)subpassNdx, (deUint32)subpassNdx + 1,
4361													 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
4362														| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
4363														| VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
4364														| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
4365
4366													 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
4367														| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
4368														| VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
4369														| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
4370
4371													 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
4372													 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // \todo [pyry] Correct?
4373
4374													 byRegion ? (VkBool32)VK_TRUE : (VkBool32)VK_FALSE));
4375				}
4376
4377				const RenderPass					renderPass		(attachments, subpasses, deps);
4378
4379				addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 80329));
4380			}
4381		}
4382
4383		group->addChild(allocationTypeGroup.release());
4384	}
4385
4386	return group;
4387}
4388
4389de::MovePtr<tcu::TestCaseGroup> createSimpleTestGroup (tcu::TestContext& testCtx)
4390{
4391	const UVec2						targetSize	(64, 64);
4392	const UVec2						renderPos	(0, 0);
4393	const UVec2						renderSize	(64, 64);
4394	de::MovePtr<tcu::TestCaseGroup>	group		(new tcu::TestCaseGroup(testCtx, "simple", "Simple basic render pass tests"));
4395
4396	// color
4397	{
4398		const RenderPass	renderPass	(vector<Attachment>(1, Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4399																		  VK_SAMPLE_COUNT_1_BIT,
4400																		  VK_ATTACHMENT_LOAD_OP_CLEAR,
4401																		  VK_ATTACHMENT_STORE_OP_STORE,
4402																		  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4403																		  VK_ATTACHMENT_STORE_OP_DONT_CARE,
4404																		  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4405																		  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4406										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4407																	0u,
4408																	vector<AttachmentReference>(),
4409																	vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4410																	vector<AttachmentReference>(),
4411																	AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
4412																	vector<AttachmentReference>())),
4413										 vector<SubpassDependency>());
4414
4415		addFunctionCaseWithPrograms<TestConfig>(group.get(), "color", "Single color attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4416	}
4417
4418	// depth
4419	{
4420		const RenderPass	renderPass	(vector<Attachment>(1, Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
4421																		  VK_SAMPLE_COUNT_1_BIT,
4422																		  VK_ATTACHMENT_LOAD_OP_CLEAR,
4423																		  VK_ATTACHMENT_STORE_OP_STORE,
4424																		  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4425																		  VK_ATTACHMENT_STORE_OP_DONT_CARE,
4426																		  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4427																		  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4428										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4429																	0u,
4430																	vector<AttachmentReference>(),
4431																	vector<AttachmentReference>(),
4432																	vector<AttachmentReference>(),
4433																	AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4434																	vector<AttachmentReference>())),
4435										 vector<SubpassDependency>());
4436
4437		addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth", "Single depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4438	}
4439
4440	// stencil
4441	{
4442		const RenderPass	renderPass	(vector<Attachment>(1, Attachment(VK_FORMAT_S8_UINT,
4443																		  VK_SAMPLE_COUNT_1_BIT,
4444																		  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4445																		  VK_ATTACHMENT_STORE_OP_DONT_CARE,
4446																		  VK_ATTACHMENT_LOAD_OP_CLEAR,
4447																		  VK_ATTACHMENT_STORE_OP_STORE,
4448																		  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4449																		  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4450										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4451																	0u,
4452																	vector<AttachmentReference>(),
4453																	vector<AttachmentReference>(),
4454																	vector<AttachmentReference>(),
4455																	AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4456																	vector<AttachmentReference>())),
4457										 vector<SubpassDependency>());
4458
4459		addFunctionCaseWithPrograms<TestConfig>(group.get(), "stencil", "Single stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4460	}
4461
4462	// depth_stencil
4463	{
4464		const RenderPass	renderPass	(vector<Attachment>(1, Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
4465																		  VK_SAMPLE_COUNT_1_BIT,
4466																		  VK_ATTACHMENT_LOAD_OP_CLEAR,
4467																		  VK_ATTACHMENT_STORE_OP_STORE,
4468																		  VK_ATTACHMENT_LOAD_OP_CLEAR,
4469																		  VK_ATTACHMENT_STORE_OP_STORE,
4470																		  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4471																		  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4472										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4473																	0u,
4474																	vector<AttachmentReference>(),
4475																	vector<AttachmentReference>(),
4476																	vector<AttachmentReference>(),
4477																	AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4478																	vector<AttachmentReference>())),
4479										 vector<SubpassDependency>());
4480
4481		addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth_stencil", "Single depth stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4482	}
4483
4484	// color_depth
4485	{
4486		const Attachment	attachments[] =
4487		{
4488			Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4489					   VK_SAMPLE_COUNT_1_BIT,
4490					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4491					   VK_ATTACHMENT_STORE_OP_STORE,
4492					   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4493					   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4494					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4495					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4496			Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
4497					   VK_SAMPLE_COUNT_1_BIT,
4498					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4499					   VK_ATTACHMENT_STORE_OP_STORE,
4500					   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4501					   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4502					   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4503					   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4504		};
4505
4506		const RenderPass	renderPass	(vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4507										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4508																	0u,
4509																	vector<AttachmentReference>(),
4510																	vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4511																	vector<AttachmentReference>(),
4512																	AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4513																	vector<AttachmentReference>())),
4514										 vector<SubpassDependency>());
4515
4516		addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth", "Color and depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4517	}
4518
4519	// color_stencil
4520	{
4521		const Attachment	attachments[] =
4522		{
4523			Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4524					   VK_SAMPLE_COUNT_1_BIT,
4525					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4526					   VK_ATTACHMENT_STORE_OP_STORE,
4527					   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4528					   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4529					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4530					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4531			Attachment(VK_FORMAT_S8_UINT,
4532					   VK_SAMPLE_COUNT_1_BIT,
4533					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4534					   VK_ATTACHMENT_STORE_OP_STORE,
4535					   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4536					   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4537					   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4538					   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4539		};
4540
4541		const RenderPass	renderPass	(vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4542										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4543																	0u,
4544																	vector<AttachmentReference>(),
4545																	vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4546																	vector<AttachmentReference>(),
4547																	AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4548																	vector<AttachmentReference>())),
4549										 vector<SubpassDependency>());
4550
4551
4552		addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_stencil", "Color and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4553	}
4554
4555	// color_depth_stencil
4556	{
4557		const Attachment	attachments[] =
4558		{
4559			Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4560					   VK_SAMPLE_COUNT_1_BIT,
4561					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4562					   VK_ATTACHMENT_STORE_OP_STORE,
4563					   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4564					   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4565					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4566					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4567			Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
4568					   VK_SAMPLE_COUNT_1_BIT,
4569					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4570					   VK_ATTACHMENT_STORE_OP_STORE,
4571					   VK_ATTACHMENT_LOAD_OP_CLEAR,
4572					   VK_ATTACHMENT_STORE_OP_STORE,
4573					   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4574					   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4575		};
4576
4577		const RenderPass	renderPass	(vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4578										 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4579																	0u,
4580																	vector<AttachmentReference>(),
4581																	vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4582																	vector<AttachmentReference>(),
4583																	AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4584																	vector<AttachmentReference>())),
4585										 vector<SubpassDependency>());
4586
4587		addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth_stencil", "Color, depth and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4588	}
4589
4590	return group;
4591}
4592
4593std::string formatToName (VkFormat format)
4594{
4595	const std::string	formatStr	= de::toString(format);
4596	const std::string	prefix		= "VK_FORMAT_";
4597
4598	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
4599
4600	return de::toLower(formatStr.substr(prefix.length()));
4601}
4602
4603de::MovePtr<tcu::TestCaseGroup> createFormatTestGroup(tcu::TestContext& testCtx)
4604{
4605	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(testCtx, "formats", "Tests for different image formats."));
4606
4607	const UVec2 targetSize	(64, 64);
4608	const UVec2 renderPos	(0, 0);
4609	const UVec2 renderSize	(64, 64);
4610
4611	const struct
4612	{
4613		const char* const			str;
4614		const VkAttachmentLoadOp	op;
4615	} loadOps[] =
4616	{
4617		{ "clear",		VK_ATTACHMENT_LOAD_OP_CLEAR		},
4618		{ "load",		VK_ATTACHMENT_LOAD_OP_LOAD		},
4619		{ "dont_care",	VK_ATTACHMENT_LOAD_OP_DONT_CARE	}
4620	};
4621
4622	const struct
4623	{
4624		 const char* const				str;
4625		 const TestConfig::RenderTypes	types;
4626	} renderTypes[] =
4627	{
4628		{ "clear",		TestConfig::RENDERTYPES_CLEAR								},
4629		{ "draw",		TestConfig::RENDERTYPES_DRAW								},
4630		{ "clear_draw",	TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW	}
4631	};
4632
4633	// Color formats
4634	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreColorFormats); formatNdx++)
4635	{
4636		const VkFormat					format		= s_coreColorFormats[formatNdx];
4637		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatToName(format).c_str(), de::toString(format).c_str()));
4638
4639		for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
4640		{
4641			const VkAttachmentLoadOp		loadOp	= loadOps[loadOpNdx].op;
4642			de::MovePtr<tcu::TestCaseGroup>	loadOpGroup	(new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
4643
4644			for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
4645			{
4646				const RenderPass	renderPass	(vector<Attachment>(1, Attachment(format,
4647																				  VK_SAMPLE_COUNT_1_BIT,
4648																				  loadOp,
4649																				  VK_ATTACHMENT_STORE_OP_STORE,
4650																				  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4651																				  VK_ATTACHMENT_STORE_OP_DONT_CARE,
4652																				  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4653																				  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4654												 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4655																			0u,
4656																			vector<AttachmentReference>(),
4657																			vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4658																			vector<AttachmentReference>(),
4659																			AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
4660																			vector<AttachmentReference>())),
4661												 vector<SubpassDependency>());
4662
4663				addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4664			}
4665
4666			formatGroup->addChild(loadOpGroup.release());
4667		}
4668
4669		group->addChild(formatGroup.release());
4670	}
4671
4672	// Depth stencil formats
4673	for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreDepthStencilFormats); formatNdx++)
4674	{
4675		const VkFormat					vkFormat		= s_coreDepthStencilFormats[formatNdx];
4676		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, formatToName(vkFormat).c_str(), de::toString(vkFormat).c_str()));
4677
4678		for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
4679		{
4680			const VkAttachmentLoadOp		loadOp	= loadOps[loadOpNdx].op;
4681			de::MovePtr<tcu::TestCaseGroup>	loadOpGroup	(new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
4682
4683			for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
4684			{
4685				const tcu::TextureFormat	format				= mapVkFormat(vkFormat);
4686				const bool					isStencilAttachment	= hasStencilComponent(format.order);
4687				const bool					isDepthAttachment	= hasDepthComponent(format.order);
4688				const RenderPass			renderPass			(vector<Attachment>(1, Attachment(vkFormat,
4689																				  VK_SAMPLE_COUNT_1_BIT,
4690																				  isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4691																				  isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE,
4692																				  isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4693																				  isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :VK_ATTACHMENT_STORE_OP_DONT_CARE,
4694																				  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4695																				  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4696												 vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4697																			0u,
4698																			vector<AttachmentReference>(),
4699																			vector<AttachmentReference>(),
4700																			vector<AttachmentReference>(),
4701																			AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4702																			vector<AttachmentReference>())),
4703												 vector<SubpassDependency>());
4704
4705				addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4706			}
4707
4708			formatGroup->addChild(loadOpGroup.release());
4709		}
4710
4711		group->addChild(formatGroup.release());
4712	}
4713
4714	return group;
4715}
4716
4717} // anonymous
4718
4719tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx)
4720{
4721	de::MovePtr<tcu::TestCaseGroup>	renderpassTests	(new tcu::TestCaseGroup(testCtx, "renderpass", "RenderPass Tests"));
4722
4723	renderpassTests->addChild(createSimpleTestGroup(testCtx).release());
4724	renderpassTests->addChild(createFormatTestGroup(testCtx).release());
4725	renderpassTests->addChild(createAttachmentTestCaseGroup(testCtx).release());
4726	renderpassTests->addChild(createAttachmentAllocationTestGroup(testCtx).release());
4727
4728	return renderpassTests.release();
4729}
4730
4731} // vkt
4732