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