• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
60 using namespace vk;
61 
62 using tcu::BVec4;
63 using tcu::IVec2;
64 using tcu::IVec4;
65 using tcu::UVec2;
66 using tcu::UVec4;
67 using tcu::Vec2;
68 using tcu::Vec4;
69 
70 using tcu::Maybe;
71 using tcu::just;
72 using tcu::nothing;
73 
74 using tcu::ConstPixelBufferAccess;
75 using tcu::PixelBufferAccess;
76 
77 using tcu::TestLog;
78 
79 using de::UniquePtr;
80 
81 using std::pair;
82 using std::set;
83 using std::string;
84 using std::vector;
85 
86 namespace vkt
87 {
88 namespace
89 {
90 enum BoolOp
91 {
92 	BOOLOP_AND,
93 	BOOLOP_OR,
94 	BOOLOP_EQ,
95 	BOOLOP_NEQ
96 };
97 
boolOpToString(BoolOp op)98 const 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 
performBoolOp(BoolOp op,bool a,bool b)120 bool 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 
boolOpFromIndex(size_t index)142 BoolOp 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
createFence(const DeviceInterface & vk,VkDevice device,VkFenceCreateFlags flags)156 Move<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 
createFramebuffer(const DeviceInterface & vk,VkDevice device,VkFramebufferCreateFlags pCreateInfo_flags,VkRenderPass pCreateInfo_renderPass,deUint32 pCreateInfo_attachmentCount,const VkImageView * pCreateInfo_pAttachments,deUint32 pCreateInfo_width,deUint32 pCreateInfo_height,deUint32 pCreateInfo_layers)168 Move<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 
createImage(const DeviceInterface & vk,VkDevice device,VkImageCreateFlags pCreateInfo_flags,VkImageType pCreateInfo_imageType,VkFormat pCreateInfo_format,VkExtent3D pCreateInfo_extent,deUint32 pCreateInfo_mipLevels,deUint32 pCreateInfo_arrayLayers,VkSampleCountFlagBits pCreateInfo_samples,VkImageTiling pCreateInfo_tiling,VkImageUsageFlags pCreateInfo_usage,VkSharingMode pCreateInfo_sharingMode,deUint32 pCreateInfo_queueFamilyCount,const deUint32 * pCreateInfo_pQueueFamilyIndices,VkImageLayout pCreateInfo_initialLayout)193 Move<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 
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)230 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
231 {
232 	VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
233 }
234 
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)235 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
236 {
237 	VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
238 }
239 
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags pCreateInfo_flags,VkImage pCreateInfo_image,VkImageViewType pCreateInfo_viewType,VkFormat pCreateInfo_format,VkComponentMapping pCreateInfo_components,VkImageSubresourceRange pCreateInfo_subresourceRange)240 Move<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 
createBuffer(const DeviceInterface & vk,VkDevice device,VkBufferCreateFlags pCreateInfo_flags,VkDeviceSize pCreateInfo_size,VkBufferUsageFlags pCreateInfo_usage,VkSharingMode pCreateInfo_sharingMode,deUint32 pCreateInfo_queueFamilyCount,const deUint32 * pCreateInfo_pQueueFamilyIndices)263 Move<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 
createCommandPool(const DeviceInterface & vk,VkDevice device,VkCommandPoolCreateFlags pCreateInfo_flags,deUint32 pCreateInfo_queueFamilyIndex)286 Move<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 
cmdBeginRenderPass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkRenderPass pRenderPassBegin_renderPass,VkFramebuffer pRenderPassBegin_framebuffer,VkRect2D pRenderPassBegin_renderArea,deUint32 pRenderPassBegin_clearValueCount,const VkClearValue * pRenderPassBegin_pAttachmentClearValues,VkSubpassContents contents)301 void 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 
allocateCommandBuffer(const DeviceInterface & vk,VkDevice device,VkCommandPool pCreateInfo_commandPool,VkCommandBufferLevel pCreateInfo_level)323 Move<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 
beginCommandBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkCommandBufferUsageFlags pBeginInfo_flags,VkRenderPass pInheritanceInfo_renderPass,deUint32 pInheritanceInfo_subpass,VkFramebuffer pInheritanceInfo_framebuffer,VkBool32 pInheritanceInfo_occlusionQueryEnable,VkQueryControlFlags pInheritanceInfo_queryFlags,VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics)339 void 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 
endCommandBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)370 void endCommandBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
371 {
372 	VK_CHECK(vk.endCommandBuffer(cmdBuffer));
373 }
374 
queueSubmit(const DeviceInterface & vk,VkQueue queue,deUint32 cmdBufferCount,const VkCommandBuffer * pCmdBuffers,VkFence fence)375 void 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 
waitForFences(const DeviceInterface & vk,VkDevice device,deUint32 fenceCount,const VkFence * pFences,VkBool32 waitAll,deUint64 timeout)392 void 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 
getImageAspectFlags(VkFormat vkFormat)397 VkImageAspectFlags 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 
getAllMemoryReadFlags(void)419 VkAccessFlags 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 
getAllMemoryWriteFlags(void)433 VkAccessFlags 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 
getMemoryFlagsForLayout(const VkImageLayout layout)442 VkAccessFlags 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 
getAllPipelineStageFlags(void)459 VkPipelineStageFlags 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 
476 class AttachmentReference
477 {
478 public:
AttachmentReference(deUint32 attachment,VkImageLayout layout)479 					AttachmentReference		(deUint32		attachment,
480 											 VkImageLayout	layout)
481 		: m_attachment	(attachment)
482 		, m_layout		(layout)
483 	{
484 	}
485 
getAttachment(void) const486 	deUint32		getAttachment			(void) const { return m_attachment;	}
getImageLayout(void) const487 	VkImageLayout	getImageLayout			(void) const { return m_layout;		}
488 
489 private:
490 	deUint32		m_attachment;
491 	VkImageLayout	m_layout;
492 };
493 
494 class Subpass
495 {
496 public:
Subpass(VkPipelineBindPoint pipelineBindPoint,VkSubpassDescriptionFlags flags,const vector<AttachmentReference> & inputAttachments,const vector<AttachmentReference> & colorAttachments,const vector<AttachmentReference> & resolveAttachments,AttachmentReference depthStencilAttachment,const vector<deUint32> & preserveAttachments)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 
getPipelineBindPoint(void) const514 	VkPipelineBindPoint					getPipelineBindPoint		(void) const { return m_pipelineBindPoint;		}
getFlags(void) const515 	VkSubpassDescriptionFlags			getFlags					(void) const { return m_flags;					}
getInputAttachments(void) const516 	const vector<AttachmentReference>&	getInputAttachments			(void) const { return m_inputAttachments;		}
getColorAttachments(void) const517 	const vector<AttachmentReference>&	getColorAttachments			(void) const { return m_colorAttachments;		}
getResolveAttachments(void) const518 	const vector<AttachmentReference>&	getResolveAttachments		(void) const { return m_resolveAttachments;		}
getDepthStencilAttachment(void) const519 	const AttachmentReference&			getDepthStencilAttachment	(void) const { return m_depthStencilAttachment;	}
getPreserveAttachments(void) const520 	const vector<deUint32>&				getPreserveAttachments		(void) const { return m_preserveAttachments;	}
521 
522 private:
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 
534 class SubpassDependency
535 {
536 public:
SubpassDependency(deUint32 srcPass,deUint32 dstPass,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags outputMask,VkAccessFlags inputMask,VkDependencyFlags flags)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 
getSrcPass(void) const559 	deUint32				getSrcPass			(void) const { return m_srcPass;		}
getDstPass(void) const560 	deUint32				getDstPass			(void) const { return m_dstPass;		}
561 
getSrcStageMask(void) const562 	VkPipelineStageFlags	getSrcStageMask		(void) const { return m_srcStageMask;	}
getDstStageMask(void) const563 	VkPipelineStageFlags	getDstStageMask		(void) const { return m_dstStageMask;	}
564 
getOutputMask(void) const565 	VkAccessFlags			getOutputMask		(void) const { return m_outputMask;		}
getInputMask(void) const566 	VkAccessFlags			getInputMask		(void) const { return m_inputMask;		}
567 
getFlags(void) const568 	VkDependencyFlags		getFlags			(void) const { return m_flags;		}
569 
570 private:
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 
582 class Attachment
583 {
584 public:
Attachment(VkFormat format,VkSampleCountFlagBits samples,VkAttachmentLoadOp loadOp,VkAttachmentStoreOp storeOp,VkAttachmentLoadOp stencilLoadOp,VkAttachmentStoreOp stencilStoreOp,VkImageLayout initialLayout,VkImageLayout finalLayout)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 
getFormat(void) const610 	VkFormat				getFormat			(void) const { return m_format;			}
getSamples(void) const611 	VkSampleCountFlagBits	getSamples			(void) const { return m_samples;		}
612 
getLoadOp(void) const613 	VkAttachmentLoadOp		getLoadOp			(void) const { return m_loadOp;			}
getStoreOp(void) const614 	VkAttachmentStoreOp		getStoreOp			(void) const { return m_storeOp;		}
615 
616 
getStencilLoadOp(void) const617 	VkAttachmentLoadOp		getStencilLoadOp	(void) const { return m_stencilLoadOp;	}
getStencilStoreOp(void) const618 	VkAttachmentStoreOp		getStencilStoreOp	(void) const { return m_stencilStoreOp;	}
619 
getInitialLayout(void) const620 	VkImageLayout			getInitialLayout	(void) const { return m_initialLayout;	}
getFinalLayout(void) const621 	VkImageLayout			getFinalLayout		(void) const { return m_finalLayout;	}
622 
623 private:
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 
637 class RenderPass
638 {
639 public:
RenderPass(const vector<Attachment> & attachments,const vector<Subpass> & subpasses,const vector<SubpassDependency> & dependencies)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 
getAttachments(void) const649 	const vector<Attachment>&			getAttachments	(void) const { return m_attachments;	}
getSubpasses(void) const650 	const vector<Subpass>&				getSubpasses	(void) const { return m_subpasses;		}
getDependencies(void) const651 	const vector<SubpassDependency>&	getDependencies	(void) const { return m_dependencies;	}
652 
653 private:
654 	const vector<Attachment>			m_attachments;
655 	const vector<Subpass>				m_subpasses;
656 	const vector<SubpassDependency>		m_dependencies;
657 };
658 
659 struct 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 
TestConfigvkt::__anon30da2d3d0111::TestConfig680 						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 
operator |(TestConfig::RenderTypes a,TestConfig::RenderTypes b)709 TestConfig::RenderTypes operator| (TestConfig::RenderTypes a, TestConfig::RenderTypes b)
710 {
711 	return (TestConfig::RenderTypes)(((deUint32)a) | ((deUint32)b));
712 }
713 
operator |(TestConfig::CommandBufferTypes a,TestConfig::CommandBufferTypes b)714 TestConfig::CommandBufferTypes operator| (TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
715 {
716 	return (TestConfig::CommandBufferTypes)(((deUint32)a) | ((deUint32)b));
717 }
718 
operator |(TestConfig::ImageMemory a,TestConfig::ImageMemory b)719 TestConfig::ImageMemory operator| (TestConfig::ImageMemory a, TestConfig::ImageMemory b)
720 {
721 	return (TestConfig::ImageMemory)(((deUint32)a) | ((deUint32)b));
722 }
723 
logRenderPassInfo(TestLog & log,const RenderPass & renderPass)724 void 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 
clearColorToString(VkFormat vkFormat,VkClearColorValue value)855 std::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 
clearValueToString(VkFormat vkFormat,VkClearValue value)917 std::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 
randomColorClearValue(const Attachment & attachment,de::Random & rng)944 VkClearColorValue 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 
createAttachmentDescription(const Attachment & attachment)999 VkAttachmentDescription 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 
createAttachmentReference(const AttachmentReference & referenceInfo)1021 VkAttachmentReference 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 
createSubpassDescription(const Subpass & subpass,vector<VkAttachmentReference> * attachmentReferenceLists,vector<deUint32> * preserveAttachmentReferences)1032 VkSubpassDescription 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 
createSubpassDependency(const SubpassDependency & dependencyInfo)1079 VkSubpassDependency 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 
createRenderPass(const DeviceInterface & vk,VkDevice device,const RenderPass & renderPassInfo)1098 Move<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 
createFramebuffer(const DeviceInterface & vk,VkDevice device,VkRenderPass renderPass,const UVec2 & size,const vector<VkImageView> & attachments)1136 Move<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 
createAttachmentImage(const DeviceInterface & vk,VkDevice device,deUint32 queueIndex,const UVec2 & size,VkFormat format,VkSampleCountFlagBits samples,VkImageUsageFlags usageFlags,VkImageLayout layout)1145 Move<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 
createImageMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image,bool lazy)1184 de::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 
createImageAttachmentView(const DeviceInterface & vk,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)1195 Move<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 
randomClearValue(const Attachment & attachment,de::Random & rng)1213 VkClearValue 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 
1247 class AttachmentResources
1248 {
1249 public:
AttachmentResources(const DeviceInterface & vk,VkDevice device,Allocator & allocator,deUint32 queueIndex,const UVec2 & size,const Attachment & attachmentInfo,VkImageUsageFlags usageFlags)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 
getInputAttachmentViews(void) const1307 	const pair<VkImageView, VkImageView>& getInputAttachmentViews (void) const
1308 	{
1309 		return m_inputAttachmentViews;
1310 	}
1311 
~AttachmentResources(void)1312 	~AttachmentResources (void)
1313 	{
1314 	}
1315 
getAttachmentView(void) const1316 	VkImageView getAttachmentView (void) const
1317 	{
1318 		return *m_attachmentView;
1319 	}
1320 
getImage(void) const1321 	VkImage getImage (void) const
1322 	{
1323 		return *m_image;
1324 	}
1325 
getBuffer(void) const1326 	VkBuffer getBuffer (void) const
1327 	{
1328 		DE_ASSERT(*m_buffer != DE_NULL);
1329 		return *m_buffer;
1330 	}
1331 
getBufferSize(void) const1332 	VkDeviceSize getBufferSize (void) const
1333 	{
1334 		DE_ASSERT(*m_buffer != DE_NULL);
1335 		return m_bufferSize;
1336 	}
1337 
getResultMemory(void) const1338 	const Allocation& getResultMemory (void) const
1339 	{
1340 		DE_ASSERT(m_bufferMemory);
1341 		return *m_bufferMemory;
1342 	}
1343 
getSecondaryBuffer(void) const1344 	VkBuffer getSecondaryBuffer (void) const
1345 	{
1346 		DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1347 		return *m_secondaryBuffer;
1348 	}
1349 
getSecondaryBufferSize(void) const1350 	VkDeviceSize getSecondaryBufferSize (void) const
1351 	{
1352 		DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1353 		return m_secondaryBufferSize;
1354 	}
1355 
getSecondaryResultMemory(void) const1356 	const Allocation& getSecondaryResultMemory (void) const
1357 	{
1358 		DE_ASSERT(m_secondaryBufferMemory);
1359 		return *m_secondaryBufferMemory;
1360 	}
1361 
1362 private:
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 
uploadBufferData(const DeviceInterface & vk,VkDevice device,const Allocation & memory,size_t size,const void * data)1380 void 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 
getPrimaryImageAspect(tcu::TextureFormat::ChannelOrder order)1400 VkImageAspectFlagBits 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 
1418 class RenderQuad
1419 {
1420 public:
RenderQuad(const Vec2 & posA,const Vec2 & posB)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 
getCornerA(void) const1433 	const Vec2&		getCornerA			(void) const
1434 	{
1435 		return m_vertices[0];
1436 	}
1437 
getCornerB(void) const1438 	const Vec2&		getCornerB			(void) const
1439 	{
1440 		return m_vertices[2];
1441 	}
1442 
getVertexPointer(void) const1443 	const void*		getVertexPointer	(void) const
1444 	{
1445 		return &m_vertices[0];
1446 	}
1447 
getVertexDataSize(void) const1448 	size_t			getVertexDataSize	(void) const
1449 	{
1450 		return sizeof(Vec2) * m_vertices.size();
1451 	}
1452 
1453 private:
1454 	vector<Vec2>	m_vertices;
1455 };
1456 
1457 class ColorClear
1458 {
1459 public:
ColorClear(const UVec2 & offset,const UVec2 & size,const VkClearColorValue & color)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 
getOffset(void) const1469 	const UVec2&				getOffset	(void) const { return m_offset;	}
getSize(void) const1470 	const UVec2&				getSize		(void) const { return m_size;	}
getColor(void) const1471 	const VkClearColorValue&	getColor	(void) const { return m_color;	}
1472 
1473 private:
1474 	UVec2						m_offset;
1475 	UVec2						m_size;
1476 	VkClearColorValue			m_color;
1477 };
1478 
1479 class DepthStencilClear
1480 {
1481 public:
DepthStencilClear(const UVec2 & offset,const UVec2 & size,float depth,deUint32 stencil)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 
getOffset(void) const1493 	const UVec2&	getOffset			(void) const { return m_offset;		}
getSize(void) const1494 	const UVec2&	getSize				(void) const { return m_size;		}
getDepth(void) const1495 	float			getDepth			(void) const { return m_depth;		}
getStencil(void) const1496 	deUint32		getStencil			(void) const { return m_stencil;	}
1497 
1498 private:
1499 	const UVec2		m_offset;
1500 	const UVec2		m_size;
1501 
1502 	const float		m_depth;
1503 	const deUint32	m_stencil;
1504 };
1505 
1506 class SubpassRenderInfo
1507 {
1508 public:
SubpassRenderInfo(const RenderPass & renderPass,deUint32 subpassIndex,bool isSecondary_,const UVec2 & viewportOffset,const UVec2 & viewportSize,const Maybe<RenderQuad> & renderQuad,const vector<ColorClear> & colorClears,const Maybe<DepthStencilClear> & depthStencilClear)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 
getViewportOffset(void) const1541 	const UVec2&					getViewportOffset				(void) const { return m_viewportOffset;		}
getViewportSize(void) const1542 	const UVec2&					getViewportSize					(void) const { return m_viewportSize;		}
1543 
getSubpassIndex(void) const1544 	deUint32						getSubpassIndex					(void) const { return m_subpassIndex;		}
isSecondary(void) const1545 	bool							isSecondary						(void) const { return m_isSecondary;		}
1546 
getRenderQuad(void) const1547 	const Maybe<RenderQuad>&		getRenderQuad					(void) const { return m_renderQuad;			}
getColorClears(void) const1548 	const vector<ColorClear>&		getColorClears					(void) const { return m_colorClears;		}
getDepthStencilClear(void) const1549 	const Maybe<DepthStencilClear>&	getDepthStencilClear			(void) const { return m_depthStencilClear;	}
1550 
getInputAttachmentCount(void) const1551 	deUint32						getInputAttachmentCount			(void) const { return (deUint32)m_inputAttachments.size(); }
getInputAttachmentIndex(deUint32 attachmentNdx) const1552 	deUint32						getInputAttachmentIndex			(deUint32 attachmentNdx) const { return m_inputAttachments[attachmentNdx].getAttachment(); }
getInputAttachmentLayout(deUint32 attachmentNdx) const1553 	VkImageLayout					getInputAttachmentLayout		(deUint32 attachmentNdx) const { return m_inputAttachments[attachmentNdx].getImageLayout(); }
1554 
getColorAttachmentCount(void) const1555 	deUint32						getColorAttachmentCount			(void) const { return (deUint32)m_colorAttachments.size(); }
getColorAttachmentLayout(deUint32 attachmentNdx) const1556 	VkImageLayout					getColorAttachmentLayout		(deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getImageLayout(); }
getColorAttachmentIndex(deUint32 attachmentNdx) const1557 	deUint32						getColorAttachmentIndex			(deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getAttachment(); }
getColorAttachment(deUint32 attachmentNdx) const1558 	const Attachment&				getColorAttachment				(deUint32 attachmentNdx) const { return m_colorAttachmentInfo[attachmentNdx]; }
getDepthStencilAttachmentLayout(void) const1559 	Maybe<VkImageLayout>			getDepthStencilAttachmentLayout	(void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::nothing<VkImageLayout>(); }
getDepthStencilAttachmentIndex(void) const1560 	Maybe<deUint32>					getDepthStencilAttachmentIndex	(void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::nothing<deUint32>(); };
getDepthStencilAttachment(void) const1561 	const Maybe<Attachment>&		getDepthStencilAttachment		(void) const { return m_depthStencilAttachmentInfo; }
getSubpassFlags(void) const1562 	VkSubpassDescriptionFlags		getSubpassFlags					(void) const { return m_flags; }
1563 
1564 private:
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 
createSubpassPipeline(const DeviceInterface & vk,VkDevice device,VkRenderPass renderPass,VkShaderModule vertexShaderModule,VkShaderModule fragmentShaderModule,VkPipelineLayout pipelineLayout,const SubpassRenderInfo & renderInfo)1585 Move<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 
1815 class SubpassRenderer
1816 {
1817 public:
SubpassRenderer(Context & context,const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkRenderPass renderPass,VkFramebuffer framebuffer,VkCommandPool commandBufferPool,deUint32 queueFamilyIndex,const vector<VkImage> & attachmentImages,const vector<pair<VkImageView,VkImageView>> & attachmentViews,const SubpassRenderInfo & renderInfo,const vector<Attachment> & attachmentInfos)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 
isSecondary(void) const2066 	bool isSecondary (void) const
2067 	{
2068 		return m_commandBuffer;
2069 	}
2070 
getCommandBuffer(void) const2071 	VkCommandBuffer getCommandBuffer (void) const
2072 	{
2073 		DE_ASSERT(isSecondary());
2074 		return *m_commandBuffer;
2075 	}
2076 
pushRenderCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer)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 
2231 private:
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 
pushImageInitializationCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const vector<Attachment> & attachmentInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,deUint32 queueIndex,const vector<Maybe<VkClearValue>> & clearValues)2249 void 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 
pushRenderPassCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,VkRenderPass renderPass,VkFramebuffer framebuffer,const vector<de::SharedPtr<SubpassRenderer>> & subpassRenderers,const UVec2 & renderPos,const UVec2 & renderSize,const vector<Maybe<VkClearValue>> & renderPassClearValues,TestConfig::RenderTypes render)2386 void 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 
pushReadImagesToBuffers(const DeviceInterface & vk,VkCommandBuffer commandBuffer,deUint32 queueIndex,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<Attachment> & attachmentInfo,const vector<bool> & isLazy,const UVec2 & targetSize)2443 void 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 
2603 class PixelValue
2604 {
2605 public:
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 
2615 private:
2616 	deUint16	m_status;
2617 };
2618 
PixelValue(const Maybe<bool> & x,const Maybe<bool> & y,const Maybe<bool> & z,const Maybe<bool> & w)2619 PixelValue::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 
setUndefined(size_t ndx)2641 void 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 
setValue(size_t ndx,bool value)2650 void 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 
getValue(size_t ndx) const2665 Maybe<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 
clearReferenceValues(vector<PixelValue> & values,const UVec2 & targetSize,const UVec2 & offset,const UVec2 & size,const BVec4 & mask,const PixelValue & value)2678 void 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 
markUndefined(vector<PixelValue> & values,const BVec4 & mask,const UVec2 & targetSize,const UVec2 & offset,const UVec2 & size)2705 void 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 
clearValueToPixelValue(const VkClearValue & value,const tcu::TextureFormat & format)2724 PixelValue 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 
renderReferenceValues(vector<vector<PixelValue>> & referenceAttachments,const RenderPass & renderPassInfo,const UVec2 & targetSize,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo,const UVec2 & renderPos,const UVec2 & renderSize)2816 void 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 
renderReferenceImagesFromValues(vector<tcu::TextureLevel> & referenceImages,const vector<vector<PixelValue>> & referenceValues,const UVec2 & targetSize,const RenderPass & renderPassInfo)3156 void 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 
verifyColorAttachment(const vector<PixelValue> & reference,const ConstPixelBufferAccess & result,const PixelBufferAccess & errorImage)3241 bool 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 
verifyDepthAttachment(const vector<PixelValue> & reference,const ConstPixelBufferAccess & result,const PixelBufferAccess & errorImage)3286 bool 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 
verifyStencilAttachment(const vector<PixelValue> & reference,const ConstPixelBufferAccess & result,const PixelBufferAccess & errorImage)3328 bool 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 
logAndVerifyImages(TestLog & log,const DeviceInterface & vk,VkDevice device,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<bool> & attachmentIsLazy,const RenderPass & renderPassInfo,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo,const UVec2 & targetSize,const TestConfig & config)3370 bool 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 
getInputAttachmentType(VkFormat vkFormat)3520 std::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 
getAttachmentType(VkFormat vkFormat)3544 std::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 
createTestShaders(SourceCollections & dst,TestConfig config)3568 void 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 
initializeAttachmentIsLazy(vector<bool> & attachmentIsLazy,const vector<Attachment> & attachments,TestConfig::ImageMemory imageMemory)3811 void 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 
3840 enum AttachmentRefType
3841 {
3842 	ATTACHMENTREFTYPE_COLOR,
3843 	ATTACHMENTREFTYPE_DEPTH_STENCIL,
3844 	ATTACHMENTREFTYPE_INPUT,
3845 	ATTACHMENTREFTYPE_RESOLVE,
3846 };
3847 
getImageUsageFromLayout(VkImageLayout layout)3848 VkImageUsageFlags 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 
getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> & attachmentImageUsage,AttachmentRefType refType,size_t count,const AttachmentReference * references)3878 void 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 
getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> & attachmentImageUsage,AttachmentRefType refType,const vector<AttachmentReference> & references)3914 void 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 
initializeAttachmentImageUsage(Context & context,vector<VkImageUsageFlags> & attachmentImageUsage,const RenderPass & renderPassInfo,const vector<bool> & attachmentIsLazy,const vector<Maybe<VkClearValue>> & clearValues)3922 void 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 
initializeSubpassIsSecondary(vector<bool> & subpassIsSecondary,const vector<Subpass> & subpasses,TestConfig::CommandBufferTypes commandBuffer)3961 void 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 
initializeImageClearValues(de::Random & rng,vector<Maybe<VkClearValue>> & clearValues,const vector<Attachment> & attachments,const vector<bool> & isLazy)3982 void 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 
initializeRenderPassClearValues(de::Random & rng,vector<Maybe<VkClearValue>> & clearValues,const vector<Attachment> & attachments)3993 void 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 
initializeSubpassClearValues(de::Random & rng,vector<vector<VkClearColorValue>> & clearValues,const RenderPass & renderPass)4007 void 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 
logSubpassRenderInfo(TestLog & log,const SubpassRenderInfo & info)4028 void 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 
logTestCaseInfo(TestLog & log,const TestConfig & config,const vector<bool> & attachmentIsLazy,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo)4067 void 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 
roundToViewport(float x,deUint32 offset,deUint32 size)4107 float 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 
initializeSubpassRenderInfo(vector<SubpassRenderInfo> & renderInfos,de::Random & rng,const RenderPass & renderPass,const TestConfig & config)4116 void 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 
checkTextureFormatSupport(TestLog & log,const InstanceInterface & vk,VkPhysicalDevice device,const vector<Attachment> & attachments)4183 void 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 
renderPassTest(Context & context,TestConfig config)4211 tcu::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 
4323 static 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 
4375 static 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 
addAttachmentTests(tcu::TestCaseGroup * group)4386 void 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 
4545 template<typename T>
chooseRandom(de::Random & rng,const set<T> & values)4546 T 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 
addAttachmentAllocationTests(tcu::TestCaseGroup * group)4557 void 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 
addSimpleTests(tcu::TestCaseGroup * group)5124 void 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 
formatToName(VkFormat format)5325 std::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 
addFormatTests(tcu::TestCaseGroup * group)5335 void 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 
createRenderPassTests(tcu::TestContext & testCtx)5709 tcu::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