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