1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group 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 Vulkan Multi View Render Tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktMultiViewRenderTests.hpp"
25#include "vktMultiViewRenderUtil.hpp"
26#include "vktMultiViewRenderPassUtil.hpp"
27#include "vktCustomInstancesDevices.hpp"
28
29#include "vktTestCase.hpp"
30#include "vkBuilderUtil.hpp"
31#include "vkRefUtil.hpp"
32#include "vkQueryUtil.hpp"
33#include "vkDeviceUtil.hpp"
34#include "vkTypeUtil.hpp"
35#include "vkPrograms.hpp"
36#include "vkPlatform.hpp"
37#include "vkMemUtil.hpp"
38#include "vkImageUtil.hpp"
39#include "vkCmdUtil.hpp"
40#include "vkObjUtil.hpp"
41#include "vkBarrierUtil.hpp"
42
43#include "tcuTestLog.hpp"
44#include "tcuResource.hpp"
45#include "tcuImageCompare.hpp"
46#include "tcuCommandLine.hpp"
47#include "tcuTextureUtil.hpp"
48#include "tcuRGBA.hpp"
49
50#include "deRandom.hpp"
51#include "deMath.h"
52#include "deSharedPtr.hpp"
53#ifdef CTS_USES_VULKANSC
54#include "vkSafetyCriticalUtil.hpp"
55#endif
56
57#include <algorithm>
58#include <bitset>
59
60namespace vkt
61{
62namespace MultiView
63{
64namespace
65{
66
67using namespace vk;
68using de::MovePtr;
69using de::UniquePtr;
70using std::vector;
71using std::map;
72using std::string;
73
74enum TestType
75{
76	TEST_TYPE_VIEW_MASK,
77	TEST_TYPE_VIEW_INDEX_IN_VERTEX,
78	TEST_TYPE_VIEW_INDEX_IN_FRAGMENT,
79	TEST_TYPE_VIEW_INDEX_IN_GEOMETRY,
80	TEST_TYPE_VIEW_INDEX_IN_TESELLATION,
81	TEST_TYPE_INPUT_ATTACHMENTS,
82	TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY,
83	TEST_TYPE_INSTANCED_RENDERING,
84	TEST_TYPE_INPUT_RATE_INSTANCE,
85	TEST_TYPE_DRAW_INDIRECT,
86	TEST_TYPE_DRAW_INDIRECT_INDEXED,
87	TEST_TYPE_DRAW_INDEXED,
88	TEST_TYPE_CLEAR_ATTACHMENTS,
89	TEST_TYPE_SECONDARY_CMD_BUFFER,
90	TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY,
91	TEST_TYPE_POINT_SIZE,
92	TEST_TYPE_MULTISAMPLE,
93	TEST_TYPE_QUERIES,
94	TEST_TYPE_NON_PRECISE_QUERIES,
95	TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY,
96	TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR,
97	TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR,
98	TEST_TYPE_DEPTH,
99	TEST_TYPE_DEPTH_DIFFERENT_RANGES,
100	TEST_TYPE_STENCIL,
101	TEST_TYPE_VIEW_MASK_ITERATION,
102	TEST_TYPE_LAST
103};
104
105enum RenderingType
106{
107	RENDERING_TYPE_RENDERPASS_LEGACY = 0,
108	RENDERING_TYPE_RENDERPASS2,
109	RENDERING_TYPE_DYNAMIC_RENDERING
110};
111
112enum QueryType
113{
114	QUERY_TYPE_GET_QUERY_POOL_RESULTS,
115	QUERY_TYPE_CMD_COPY_QUERY_POOL_RESULTS
116};
117
118struct TestParameters
119{
120	VkExtent3D				extent;
121	vector<deUint32>		viewMasks;
122	TestType				viewIndex;
123	VkSampleCountFlagBits	samples;
124	VkFormat				colorFormat;
125	QueryType				queryType;
126	RenderingType			renderingType;
127
128	bool geometryShaderNeeded (void) const
129	{
130		return ((TEST_TYPE_VIEW_INDEX_IN_GEOMETRY == viewIndex) ||
131				(TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY == viewIndex) ||
132				(TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY == viewIndex));
133	}
134};
135
136const int	TEST_POINT_SIZE_SMALL	= 2;
137const int	TEST_POINT_SIZE_WIDE	= 4;
138
139vk::Move<vk::VkRenderPass> makeRenderPass (const DeviceInterface&		vk,
140										   const VkDevice				device,
141										   const VkFormat				colorFormat,
142										   const vector<deUint32>&		viewMasks,
143										   RenderingType				renderingType,
144										   const VkSampleCountFlagBits	samples = VK_SAMPLE_COUNT_1_BIT,
145										   const VkAttachmentLoadOp		colorLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
146										   const VkFormat				dsFormat = VK_FORMAT_UNDEFINED)
147{
148	switch (renderingType)
149	{
150		case RENDERING_TYPE_RENDERPASS_LEGACY:
151			return MultiView::makeRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, device, colorFormat, viewMasks, samples, colorLoadOp, dsFormat);
152		case RENDERING_TYPE_RENDERPASS2:
153			return MultiView::makeRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, device, colorFormat, viewMasks, samples, colorLoadOp, dsFormat);
154		default:
155			TCU_THROW(InternalError, "Impossible");
156	}
157}
158
159vk::Move<vk::VkRenderPass> makeRenderPassWithAttachments (const DeviceInterface&	vk,
160														  const VkDevice			device,
161														  const VkFormat			colorFormat,
162														  const vector<deUint32>&	viewMasks,
163														  RenderingType				renderingType)
164{
165	switch (renderingType)
166	{
167		case RENDERING_TYPE_RENDERPASS_LEGACY:
168			return MultiView::makeRenderPassWithAttachments<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, device, colorFormat, viewMasks, false);
169		case RENDERING_TYPE_RENDERPASS2:
170			return MultiView::makeRenderPassWithAttachments<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, device, colorFormat, viewMasks, true);
171		default:
172			TCU_THROW(InternalError, "Impossible");
173	}
174}
175
176vk::Move<vk::VkRenderPass> makeRenderPassWithDepth (const DeviceInterface&	vk,
177													const VkDevice			device,
178													const VkFormat			colorFormat,
179													const vector<deUint32>&	viewMasks,
180													const VkFormat			dsFormat,
181													RenderingType			renderingType)
182{
183	switch (renderingType)
184	{
185		case RENDERING_TYPE_RENDERPASS_LEGACY:
186			return MultiView::makeRenderPassWithDepth<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, device, colorFormat, viewMasks, dsFormat);
187		case RENDERING_TYPE_RENDERPASS2:
188			return MultiView::makeRenderPassWithDepth<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, device, colorFormat, viewMasks, dsFormat);
189		default:
190			TCU_THROW(InternalError, "Impossible");
191	}
192}
193
194template<typename RenderpassSubpass>
195void cmdBeginRenderPass (DeviceInterface& vkd, VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassContents contents)
196{
197	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, contents);
198
199	RenderpassSubpass::cmdBeginRenderPass(vkd, cmdBuffer, pRenderPassBegin, &subpassBeginInfo);
200}
201
202void cmdBeginRenderPass (DeviceInterface& vkd, VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassContents contents, RenderingType renderingType)
203{
204	switch (renderingType)
205	{
206		case RENDERING_TYPE_RENDERPASS_LEGACY:	cmdBeginRenderPass<RenderpassSubpass1>(vkd, cmdBuffer, pRenderPassBegin, contents);	break;
207		case RENDERING_TYPE_RENDERPASS2:		cmdBeginRenderPass<RenderpassSubpass2>(vkd, cmdBuffer, pRenderPassBegin, contents);	break;
208		default:								TCU_THROW(InternalError, "Impossible");
209	}
210}
211
212template<typename RenderpassSubpass>
213void cmdNextSubpass (DeviceInterface& vkd, VkCommandBuffer cmdBuffer, const VkSubpassContents contents)
214{
215	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, contents);
216	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
217
218	RenderpassSubpass::cmdNextSubpass(vkd, cmdBuffer, &subpassBeginInfo, &subpassEndInfo);
219}
220
221void cmdNextSubpass (DeviceInterface& vkd, VkCommandBuffer cmdBuffer, const VkSubpassContents contents, RenderingType renderingType)
222{
223	switch (renderingType)
224	{
225		case RENDERING_TYPE_RENDERPASS_LEGACY:	cmdNextSubpass<RenderpassSubpass1>(vkd, cmdBuffer, contents);	break;
226		case RENDERING_TYPE_RENDERPASS2:		cmdNextSubpass<RenderpassSubpass2>(vkd, cmdBuffer, contents);	break;
227		default:								TCU_THROW(InternalError, "Impossible");
228	}
229}
230
231template<typename RenderpassSubpass>
232void cmdEndRenderPass (DeviceInterface& vkd, VkCommandBuffer cmdBuffer)
233{
234	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo	(DE_NULL);
235
236	RenderpassSubpass::cmdEndRenderPass(vkd, cmdBuffer, &subpassEndInfo);
237}
238
239void cmdEndRenderPass (DeviceInterface& vkd, VkCommandBuffer cmdBuffer, RenderingType renderingType)
240{
241	switch (renderingType)
242	{
243		case RENDERING_TYPE_RENDERPASS_LEGACY:	cmdEndRenderPass<RenderpassSubpass1>(vkd, cmdBuffer);	break;
244		case RENDERING_TYPE_RENDERPASS2:		cmdEndRenderPass<RenderpassSubpass2>(vkd, cmdBuffer);	break;
245		default:								TCU_THROW(InternalError, "Impossible");
246	}
247}
248
249class ImageAttachment
250{
251public:
252				ImageAttachment	(VkDevice logicalDevice, DeviceInterface& device, Allocator& allocator, const VkExtent3D extent, VkFormat colorFormat, const VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT);
253	VkImageView	getImageView	(void) const
254	{
255		return *m_imageView;
256	}
257	VkImage		getImage		(void) const
258	{
259		return *m_image;
260	}
261private:
262	Move<VkImage>			m_image;
263	MovePtr<Allocation>		m_allocationImage;
264	Move<VkImageView>		m_imageView;
265};
266
267ImageAttachment::ImageAttachment (VkDevice logicalDevice, DeviceInterface& device, Allocator& allocator, const VkExtent3D extent, VkFormat colorFormat, const VkSampleCountFlagBits samples)
268{
269	const bool						depthStencilFormat			= isDepthStencilFormat(colorFormat);
270	const VkImageAspectFlags		aspectFlags					= depthStencilFormat ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
271	const VkImageSubresourceRange	colorImageSubresourceRange	= makeImageSubresourceRange(aspectFlags, 0u, 1u, 0u, extent.depth);
272	const VkImageUsageFlags			imageUsageFlagsDependent	= depthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
273	const VkImageUsageFlags			imageUsageFlags				= imageUsageFlagsDependent | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
274	const VkImageCreateInfo			colorAttachmentImageInfo	= makeImageCreateInfo(VK_IMAGE_TYPE_2D, extent, colorFormat, imageUsageFlags, samples);
275
276	m_image							= createImage(device, logicalDevice, &colorAttachmentImageInfo);
277	m_allocationImage				= allocator.allocate(getImageMemoryRequirements(device, logicalDevice, *m_image), MemoryRequirement::Any);
278	VK_CHECK(device.bindImageMemory(logicalDevice, *m_image, m_allocationImage->getMemory(), m_allocationImage->getOffset()));
279	m_imageView						= makeImageView(device, logicalDevice, *m_image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, colorFormat, colorImageSubresourceRange);
280}
281
282class MultiViewRenderTestInstance : public TestInstance
283{
284public:
285									MultiViewRenderTestInstance	(Context& context, const TestParameters& parameters);
286									~MultiViewRenderTestInstance();
287protected:
288	typedef de::SharedPtr<Unique<VkPipeline> >		PipelineSp;
289	typedef de::SharedPtr<Unique<VkShaderModule> >	ShaderModuleSP;
290
291	virtual tcu::TestStatus					iterate					(void);
292	virtual void							beforeRenderPass		(void);
293	virtual void							afterRenderPass			(void);
294	virtual void							bindResources			(void) {}
295	virtual void							draw					(const deUint32			subpassCount,
296																	 VkRenderPass			renderPass,
297																	 VkFramebuffer			frameBuffer,
298																	 vector<PipelineSp>&	pipelines);
299	virtual void							createVertexData		(void);
300	virtual MovePtr<tcu::Texture2DArray>	imageData				(void) const;
301	TestParameters							fillMissingParameters	(const TestParameters&	parameters);
302	void									createVertexBuffer		(void);
303	void									createMultiViewDevices	(void);
304	void									createCommandBuffer		(void);
305	void									createSecondaryCommandPool	(void);
306	void									madeShaderModule		(map<VkShaderStageFlagBits,ShaderModuleSP>& shaderModule, vector<VkPipelineShaderStageCreateInfo>& shaderStageParams);
307	Move<VkPipeline>						makeGraphicsPipeline	(const VkRenderPass							renderPass,
308																	 const VkPipelineLayout						pipelineLayout,
309																	 const deUint32								pipelineShaderStageCount,
310																	 const VkPipelineShaderStageCreateInfo*		pipelineShaderStageCreate,
311																	 const deUint32								subpass,
312																	 const VkVertexInputRate					vertexInputRate = VK_VERTEX_INPUT_RATE_VERTEX,
313																	 const bool									useDepthTest = false,
314																	 const bool									useStencilTest = false,
315																	 const float								minDepth = 0.0f,
316																	 const float								maxDepth = 1.0f,
317																	 const VkFormat                                                         dsFormat = VK_FORMAT_UNDEFINED);
318	void									readImage				(VkImage image, const tcu::PixelBufferAccess& dst);
319	bool									checkImage				(tcu::ConstPixelBufferAccess& dst);
320	const tcu::Vec4							getQuarterRefColor		(const deUint32 quarterNdx, const int colorNdx, const int layerNdx, const bool background = true, const deUint32 subpassNdx = 0u) const;
321	void									appendVertex			(const tcu::Vec4& coord, const tcu::Vec4& color);
322	void									setPoint				(const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& pointColor, const int pointSize, const int layerNdx, const deUint32 quarter) const;
323	void									fillTriangle			(const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& color, const int layerNdx, const deUint32 quarter) const;
324	void									fillLayer				(const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& color, const int layerNdx) const;
325	void									fillQuarter				(const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& color, const int layerNdx, const deUint32 quarter, const deUint32 subpassNdx) const;
326#ifndef CTS_USES_VULKANSC
327	void									addRenderingSubpassDependencyIfRequired (deUint32 currentSubpassNdx);
328#endif // CTS_USES_VULKANSC
329
330	const TestParameters			m_parameters;
331	const bool						m_useDynamicRendering;
332	const bool						m_cmdCopyQueryPoolResults;
333	const int						m_seed;
334	const deUint32					m_squareCount;
335
336	Move<VkDevice>					m_logicalDevice;
337#ifndef CTS_USES_VULKANSC
338	de::MovePtr<vk::DeviceDriver>	m_device;
339#else
340	de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> m_device;
341#endif // CTS_USES_VULKANSC
342	MovePtr<Allocator>				m_allocator;
343	deUint32						m_queueFamilyIndex;
344	VkQueue							m_queue;
345	vector<tcu::Vec4>				m_vertexCoord;
346	Move<VkBuffer>					m_vertexCoordBuffer;
347	MovePtr<Allocation>				m_vertexCoordAlloc;
348	vector<tcu::Vec4>				m_vertexColor;
349	Move<VkBuffer>					m_vertexColorBuffer;
350	MovePtr<Allocation>				m_vertexColorAlloc;
351	vector<deUint32>				m_vertexIndices;
352	Move<VkBuffer>					m_vertexIndicesBuffer;
353	MovePtr<Allocation>				m_vertexIndicesAllocation;
354	Move<VkCommandPool>				m_cmdPool;
355	Move<VkCommandBuffer>			m_cmdBuffer;
356	Move<VkCommandPool>				m_cmdPoolSecondary;
357	de::SharedPtr<ImageAttachment>	m_colorAttachment;
358	VkBool32						m_hasMultiDrawIndirect;
359	vector<tcu::Vec4>				m_colorTable;
360};
361
362MultiViewRenderTestInstance::MultiViewRenderTestInstance (Context& context, const TestParameters& parameters)
363	: TestInstance				(context)
364	, m_parameters				(fillMissingParameters(parameters))
365	, m_useDynamicRendering		(parameters.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
366	, m_cmdCopyQueryPoolResults	(parameters.queryType == QUERY_TYPE_CMD_COPY_QUERY_POOL_RESULTS)
367	, m_seed					(context.getTestContext().getCommandLine().getBaseSeed())
368	, m_squareCount				(4u)
369	, m_queueFamilyIndex		(0u)
370{
371	const float v	= 0.75f;
372	const float o	= 0.25f;
373
374	m_colorTable.push_back(tcu::Vec4(v, o, o, 1.0f));
375	m_colorTable.push_back(tcu::Vec4(o, v, o, 1.0f));
376	m_colorTable.push_back(tcu::Vec4(o, o, v, 1.0f));
377	m_colorTable.push_back(tcu::Vec4(o, v, v, 1.0f));
378	m_colorTable.push_back(tcu::Vec4(v, o, v, 1.0f));
379	m_colorTable.push_back(tcu::Vec4(v, v, o, 1.0f));
380	m_colorTable.push_back(tcu::Vec4(o, o, o, 1.0f));
381	m_colorTable.push_back(tcu::Vec4(v, v, v, 1.0f));
382
383	createMultiViewDevices();
384
385	// Color attachment
386	m_colorAttachment = de::SharedPtr<ImageAttachment>(new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat, m_parameters.samples));
387}
388
389MultiViewRenderTestInstance::~MultiViewRenderTestInstance()
390{
391}
392
393tcu::TestStatus MultiViewRenderTestInstance::iterate (void)
394{
395	const deUint32								subpassCount				= static_cast<deUint32>(m_parameters.viewMasks.size());
396	Move<VkRenderPass>							renderPass;
397	Move<VkFramebuffer>							frameBuffer;
398
399	// FrameBuffer & renderPass
400	if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
401	{
402		renderPass	= makeRenderPass (*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_parameters.renderingType);
403		frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(), m_parameters.extent.width, m_parameters.extent.height);
404	}
405
406	// pipelineLayout
407	Unique<VkPipelineLayout>					pipelineLayout				(makePipelineLayout(*m_device, *m_logicalDevice));
408
409	// pipelines
410	map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
411	vector<PipelineSp>							pipelines(subpassCount);
412	const VkVertexInputRate						vertexInputRate				= (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
413
414	{
415		vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
416		madeShaderModule(shaderModule, shaderStageParams);
417		for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
418			pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<deUint32>(shaderStageParams.size()), shaderStageParams.data(), subpassNdx, vertexInputRate))));
419	}
420
421	createCommandBuffer();
422	createVertexData();
423	createVertexBuffer();
424
425	draw(subpassCount, *renderPass, *frameBuffer, pipelines);
426
427	{
428		vector<deUint8>			pixelAccessData	(m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth * mapVkFormat(m_parameters.colorFormat).getPixelSize());
429		tcu::PixelBufferAccess	dst				(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
430
431		readImage(m_colorAttachment->getImage(), dst);
432
433		if (!checkImage(dst))
434			return tcu::TestStatus::fail("Fail");
435	}
436
437	return tcu::TestStatus::pass("Pass");
438}
439
440void MultiViewRenderTestInstance::beforeRenderPass (void)
441{
442	const VkImageSubresourceRange	subresourceRange		=
443	{
444		VK_IMAGE_ASPECT_COLOR_BIT,	//VkImageAspectFlags	aspectMask;
445		0u,							//deUint32				baseMipLevel;
446		1u,							//deUint32				levelCount;
447		0u,							//deUint32				baseArrayLayer;
448		m_parameters.extent.depth,	//deUint32				layerCount;
449	};
450	imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
451		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
452		0, VK_ACCESS_TRANSFER_WRITE_BIT,
453		VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
454
455	const VkClearValue renderPassClearValue = makeClearValueColor(tcu::Vec4(0.0f));
456	m_device->cmdClearColorImage(*m_cmdBuffer, m_colorAttachment->getImage(),  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &renderPassClearValue.color, 1, &subresourceRange);
457
458	imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
459		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
460		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
461		VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
462}
463
464void MultiViewRenderTestInstance::afterRenderPass (void)
465{
466	const VkImageSubresourceRange	subresourceRange		=
467	{
468		VK_IMAGE_ASPECT_COLOR_BIT,	//VkImageAspectFlags	aspectMask;
469		0u,							//deUint32				baseMipLevel;
470		1u,							//deUint32				levelCount;
471		0u,							//deUint32				baseArrayLayer;
472		m_parameters.extent.depth,	//deUint32				layerCount;
473	};
474
475	imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
476		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
477		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
478		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
479}
480
481#ifndef CTS_USES_VULKANSC
482void MultiViewRenderTestInstance::addRenderingSubpassDependencyIfRequired (deUint32 currentSubpassNdx)
483{
484	// Get the combined view mask since the last pipeline barrier.
485	deUint32 viewMask = 0;
486
487	for (deUint32 subpassNdx = 0; subpassNdx < currentSubpassNdx; ++subpassNdx)
488	{
489		if ((viewMask & m_parameters.viewMasks[subpassNdx]) != 0)
490		{
491			viewMask = 0; // This subpass should have a pipeline barrier so reset the view mask.
492		}
493
494		viewMask |= m_parameters.viewMasks[subpassNdx];
495	}
496
497	// Add a pipeline barrier if the view mask for this subpass contains bits used in previous subpasses
498	// since the last pipeline barrier.
499	if ((viewMask & m_parameters.viewMasks[currentSubpassNdx]) != 0)
500	{
501		const VkImageSubresourceRange	subresourceRange		=
502		{
503			VK_IMAGE_ASPECT_COLOR_BIT,	//VkImageAspectFlags	aspectMask;
504			0u,							//deUint32				baseMipLevel;
505			1u,							//deUint32				levelCount;
506			0u,							//deUint32				baseArrayLayer;
507			m_parameters.extent.depth,	//deUint32				layerCount;
508		};
509
510		imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
511			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
512			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
513			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
514	}
515}
516#endif // CTS_USES_VULKANSC
517
518void MultiViewRenderTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
519{
520	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
521	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
522	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
523	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
524	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
525
526	beginCommandBuffer(*m_device, *m_cmdBuffer);
527
528	beforeRenderPass();
529
530	if (!m_useDynamicRendering)
531	{
532		const VkRenderPassBeginInfo renderPassBeginInfo
533		{
534			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
535			DE_NULL,									// const void*			pNext;
536			renderPass,									// VkRenderPass			renderPass;
537			frameBuffer,								// VkFramebuffer		framebuffer;
538			renderArea,									// VkRect2D				renderArea;
539			1u,											// uint32_t				clearValueCount;
540			&renderPassClearValue,						// const VkClearValue*	pClearValues;
541		};
542		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
543	}
544
545	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
546	{
547		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
548
549		if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED)
550			m_device->cmdBindIndexBuffer(*m_cmdBuffer, *m_vertexIndicesBuffer, 0u, VK_INDEX_TYPE_UINT32);
551
552		bindResources();
553
554#ifndef CTS_USES_VULKANSC
555		if (m_useDynamicRendering)
556		{
557			addRenderingSubpassDependencyIfRequired(subpassNdx);
558
559			beginRendering(
560				*m_device,
561				*m_cmdBuffer,
562				m_colorAttachment->getImageView(),
563				renderArea,
564				renderPassClearValue,
565				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
566				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
567				0u,
568				m_parameters.extent.depth,
569				m_parameters.viewMasks[subpassNdx]);
570		}
571#endif // CTS_USES_VULKANSC
572
573		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
574
575		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
576			if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED)
577				m_device->cmdDrawIndexed(*m_cmdBuffer, 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u, 0u);
578			else
579				m_device->cmdDraw(*m_cmdBuffer, 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u);
580
581#ifndef CTS_USES_VULKANSC
582		if (m_useDynamicRendering)
583			endRendering(*m_device, *m_cmdBuffer);
584		else
585#endif // CTS_USES_VULKANSC
586			if (subpassNdx < subpassCount - 1u)
587			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
588	}
589
590	if (!m_useDynamicRendering)
591		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
592
593	afterRenderPass();
594
595	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
596	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
597}
598
599void MultiViewRenderTestInstance::createVertexData (void)
600{
601	tcu::Vec4 color = tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f);
602
603	appendVertex(tcu::Vec4(-1.0f,-1.0f, 1.0f, 1.0f), color);
604	appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
605	appendVertex(tcu::Vec4( 0.0f,-1.0f, 1.0f, 1.0f), color);
606	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
607
608	color = tcu::Vec4(0.3f, 0.0f, 0.2f, 1.0f);
609	appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
610	appendVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), color);
611	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
612	appendVertex(tcu::Vec4( 0.0f, 1.0f, 1.0f, 1.0f), color);
613
614	color = tcu::Vec4(0.4f, 0.2f, 0.3f, 1.0f);
615	appendVertex(tcu::Vec4( 0.0f,-1.0f, 1.0f, 1.0f), color);
616	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
617	appendVertex(tcu::Vec4( 1.0f,-1.0f, 1.0f, 1.0f), color);
618	appendVertex(tcu::Vec4( 1.0f, 0.0f, 1.0f, 1.0f), color);
619
620	color = tcu::Vec4(0.5f, 0.0f, 0.4f, 1.0f);
621	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
622	appendVertex(tcu::Vec4( 0.0f, 1.0f, 1.0f, 1.0f), color);
623	appendVertex(tcu::Vec4( 1.0f, 0.0f, 1.0f, 1.0f), color);
624	appendVertex(tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f), color);
625
626	if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED || m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
627	{
628		const size_t		verticesCount	= m_vertexCoord.size();
629		vector<tcu::Vec4>	vertexColor		(verticesCount);
630		vector<tcu::Vec4>	vertexCoord		(verticesCount);
631
632		m_vertexIndices.clear();
633		m_vertexIndices.reserve(verticesCount);
634		for (deUint32 vertexIdx = 0; vertexIdx < verticesCount; ++vertexIdx)
635			m_vertexIndices.push_back(vertexIdx);
636
637		de::Random(m_seed).shuffle(m_vertexIndices.begin(), m_vertexIndices.end());
638
639		for (deUint32 vertexIdx = 0; vertexIdx < verticesCount; ++vertexIdx)
640			vertexColor[m_vertexIndices[vertexIdx]] = m_vertexColor[vertexIdx];
641		m_vertexColor.assign(vertexColor.begin(), vertexColor.end());
642
643		for (deUint32 vertexIdx = 0; vertexIdx < verticesCount; ++vertexIdx)
644			vertexCoord[m_vertexIndices[vertexIdx]] = m_vertexCoord[vertexIdx];
645		m_vertexCoord.assign(vertexCoord.begin(), vertexCoord.end());
646	}
647}
648
649TestParameters MultiViewRenderTestInstance::fillMissingParameters (const TestParameters& parameters)
650{
651	if (!parameters.viewMasks.empty())
652		return parameters;
653	else
654	{
655		const auto& instanceDriver	= m_context.getInstanceInterface();
656		const auto physicalDevice	= m_context.getPhysicalDevice();
657
658		VkPhysicalDeviceMultiviewProperties multiviewProperties =
659		{
660			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,		// VkStructureType	sType;
661			DE_NULL,													// void*			pNext;
662			0u,															// deUint32			maxMultiviewViewCount;
663			0u															// deUint32			maxMultiviewInstanceIndex;
664		};
665
666		VkPhysicalDeviceProperties2 deviceProperties2;
667		deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
668		deviceProperties2.pNext = &multiviewProperties;
669
670		instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties2);
671
672		TestParameters newParameters = parameters;
673		newParameters.extent.depth = multiviewProperties.maxMultiviewViewCount;
674
675		vector<deUint32> viewMasks(multiviewProperties.maxMultiviewViewCount);
676		for (deUint32 i = 0; i < multiviewProperties.maxMultiviewViewCount; i++)
677			viewMasks[i] = 1 << i;
678		newParameters.viewMasks = viewMasks;
679
680		return newParameters;
681	}
682}
683
684void MultiViewRenderTestInstance::createVertexBuffer (void)
685{
686	DE_ASSERT(m_vertexCoord.size() == m_vertexColor.size());
687	DE_ASSERT(m_vertexCoord.size() != 0);
688
689	const size_t	nonCoherentAtomSize	= static_cast<size_t>(m_context.getDeviceProperties().limits.nonCoherentAtomSize);
690
691	// Upload vertex coordinates
692	{
693		const size_t				dataSize		= static_cast<size_t>(m_vertexCoord.size() * sizeof(m_vertexCoord[0]));
694		const VkDeviceSize			bufferDataSize	= static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
695		const VkBufferCreateInfo	bufferInfo		= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
696
697		m_vertexCoordBuffer	= createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
698		m_vertexCoordAlloc	= m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *m_vertexCoordBuffer), MemoryRequirement::HostVisible);
699
700		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *m_vertexCoordBuffer, m_vertexCoordAlloc->getMemory(), m_vertexCoordAlloc->getOffset()));
701		deMemcpy(m_vertexCoordAlloc->getHostPtr(), m_vertexCoord.data(), static_cast<size_t>(dataSize));
702		flushAlloc(*m_device, *m_logicalDevice, *m_vertexCoordAlloc);
703	}
704
705	// Upload vertex colors
706	{
707		const size_t				dataSize		= static_cast<size_t>(m_vertexColor.size() * sizeof(m_vertexColor[0]));
708		const VkDeviceSize			bufferDataSize	= static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
709		const VkBufferCreateInfo	bufferInfo		= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
710
711		m_vertexColorBuffer	= createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
712		m_vertexColorAlloc	= m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *m_vertexColorBuffer), MemoryRequirement::HostVisible);
713
714		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *m_vertexColorBuffer, m_vertexColorAlloc->getMemory(), m_vertexColorAlloc->getOffset()));
715		deMemcpy(m_vertexColorAlloc->getHostPtr(), m_vertexColor.data(), static_cast<size_t>(dataSize));
716		flushAlloc(*m_device, *m_logicalDevice, *m_vertexColorAlloc);
717	}
718
719	// Upload vertex indices
720	if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED || m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
721	{
722		const size_t				dataSize		= static_cast<size_t>(m_vertexIndices.size() * sizeof(m_vertexIndices[0]));
723		const VkDeviceSize			bufferDataSize	= static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
724		const VkBufferCreateInfo	bufferInfo		= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
725
726		DE_ASSERT(m_vertexIndices.size() == m_vertexCoord.size());
727
728		m_vertexIndicesBuffer		= createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
729		m_vertexIndicesAllocation	= m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *m_vertexIndicesBuffer), MemoryRequirement::HostVisible);
730
731		// Init host buffer data
732		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *m_vertexIndicesBuffer, m_vertexIndicesAllocation->getMemory(), m_vertexIndicesAllocation->getOffset()));
733		deMemcpy(m_vertexIndicesAllocation->getHostPtr(), m_vertexIndices.data(), static_cast<size_t>(dataSize));
734		flushAlloc(*m_device, *m_logicalDevice, *m_vertexIndicesAllocation);
735	}
736	else
737		DE_ASSERT(m_vertexIndices.empty());
738}
739
740void MultiViewRenderTestInstance::createMultiViewDevices (void)
741{
742	const auto&								instanceDriver			= m_context.getInstanceInterface();
743	const VkPhysicalDevice					physicalDevice			= m_context.getPhysicalDevice();
744	const vector<VkQueueFamilyProperties>	queueFamilyProperties	= getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
745
746	for (; m_queueFamilyIndex < queueFamilyProperties.size(); ++m_queueFamilyIndex)
747	{
748		if ((queueFamilyProperties[m_queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
749			break;
750	}
751
752	const float								queuePriorities			= 1.0f;
753	const VkDeviceQueueCreateInfo			queueInfo				=
754	{
755		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,					//VkStructureType			sType;
756		DE_NULL,													//const void*				pNext;
757		(VkDeviceQueueCreateFlags)0u,								//VkDeviceQueueCreateFlags	flags;
758		m_queueFamilyIndex,											//deUint32					queueFamilyIndex;
759		1u,															//deUint32					queueCount;
760		&queuePriorities											//const float*				pQueuePriorities;
761	};
762
763#ifndef CTS_USES_VULKANSC
764	VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures	=
765	{
766		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,	// VkStructureType			sType;
767		DE_NULL,														// void*					pNext;
768		DE_FALSE,														// VkBool32					dynamicRendering
769	};
770#endif // CTS_USES_VULKANSC
771
772	VkPhysicalDeviceMultiviewFeatures		multiviewFeatures		=
773	{
774		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,		// VkStructureType			sType;
775#ifndef CTS_USES_VULKANSC
776		&dynamicRenderingFeatures,									// void*					pNext;
777#else
778		DE_NULL,													// void*					pNext;
779#endif // CTS_USES_VULKANSC
780		DE_FALSE,													// VkBool32					multiview;
781		DE_FALSE,													// VkBool32					multiviewGeometryShader;
782		DE_FALSE,													// VkBool32					multiviewTessellationShader;
783	};
784
785	VkPhysicalDeviceFeatures2				enabledFeatures;
786	enabledFeatures.sType					= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
787	enabledFeatures.pNext					= &multiviewFeatures;
788
789	instanceDriver.getPhysicalDeviceFeatures2(physicalDevice, &enabledFeatures);
790
791	if (!multiviewFeatures.multiview)
792		TCU_THROW(NotSupportedError, "MultiView not supported");
793
794	if (m_parameters.geometryShaderNeeded() && !multiviewFeatures.multiviewGeometryShader)
795		TCU_THROW(NotSupportedError, "Geometry shader is not supported");
796
797	if (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex && !multiviewFeatures.multiviewTessellationShader)
798		TCU_THROW(NotSupportedError, "Tessellation shader is not supported");
799
800	VkPhysicalDeviceMultiviewProperties	multiviewProperties			=
801	{
802		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,		//VkStructureType	sType;
803		DE_NULL,													//void*				pNext;
804		0u,															//deUint32			maxMultiviewViewCount;
805		0u															//deUint32			maxMultiviewInstanceIndex;
806	};
807
808	VkPhysicalDeviceProperties2			propertiesDeviceProperties2;
809	propertiesDeviceProperties2.sType	= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
810	propertiesDeviceProperties2.pNext	= &multiviewProperties;
811
812	instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &propertiesDeviceProperties2);
813
814#ifndef CTS_USES_VULKANSC
815	if (multiviewProperties.maxMultiviewViewCount < 6u)
816		TCU_FAIL("maxMultiviewViewCount below min value");
817#endif // CTS_USES_VULKANSC
818
819	if (multiviewProperties.maxMultiviewInstanceIndex < 134217727u) //134217727u = 2^27 -1
820		TCU_FAIL("maxMultiviewInstanceIndex below min value");
821
822	if (multiviewProperties.maxMultiviewViewCount <m_parameters.extent.depth)
823		TCU_THROW(NotSupportedError, "Limit MaxMultiviewViewCount to small to run this test");
824
825	m_hasMultiDrawIndirect = enabledFeatures.features.multiDrawIndirect;
826
827	{
828		vector<const char*>				deviceExtensions;
829
830		if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_multiview"))
831			deviceExtensions.push_back("VK_KHR_multiview");
832
833		if ((m_parameters.renderingType == RENDERING_TYPE_RENDERPASS2) &&
834			!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_create_renderpass2"))
835			deviceExtensions.push_back("VK_KHR_create_renderpass2");
836		if ((m_parameters.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) &&
837			!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_dynamic_rendering"))
838			deviceExtensions.push_back("VK_KHR_dynamic_rendering");
839
840		if (m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
841			deviceExtensions.push_back("VK_EXT_depth_range_unrestricted");
842
843		void* pNext												= &enabledFeatures;
844#ifdef CTS_USES_VULKANSC
845		VkDeviceObjectReservationCreateInfo memReservationInfo	= m_context.getTestContext().getCommandLine().isSubProcess() ? m_context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
846		memReservationInfo.pNext								= pNext;
847		pNext													= &memReservationInfo;
848
849		VkPhysicalDeviceVulkanSC10Features sc10Features			= createDefaultSC10Features();
850		sc10Features.pNext										= pNext;
851		pNext													= &sc10Features;
852
853		VkPipelineCacheCreateInfo			pcCI;
854		std::vector<VkPipelinePoolSize>		poolSizes;
855		if (m_context.getTestContext().getCommandLine().isSubProcess())
856		{
857			if (m_context.getResourceInterface()->getCacheDataSize() > 0)
858			{
859				pcCI =
860				{
861					VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,			// VkStructureType				sType;
862					DE_NULL,												// const void*					pNext;
863					VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
864						VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
865					m_context.getResourceInterface()->getCacheDataSize(),	// deUintptr					initialDataSize;
866					m_context.getResourceInterface()->getCacheData()		// const void*					pInitialData;
867				};
868				memReservationInfo.pipelineCacheCreateInfoCount		= 1;
869				memReservationInfo.pPipelineCacheCreateInfos		= &pcCI;
870			}
871
872			poolSizes							= m_context.getResourceInterface()->getPipelinePoolSizes();
873			if (!poolSizes.empty())
874			{
875				memReservationInfo.pipelinePoolSizeCount		= deUint32(poolSizes.size());
876				memReservationInfo.pPipelinePoolSizes			= poolSizes.data();
877			}
878		}
879#endif // CTS_USES_VULKANSC
880
881		const VkDeviceCreateInfo		deviceInfo			=
882		{
883			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,							//VkStructureType					sType;
884			pNext,															//const void*						pNext;
885			0u,																//VkDeviceCreateFlags				flags;
886			1u,																//deUint32							queueCreateInfoCount;
887			&queueInfo,														//const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
888			0u,																//deUint32							enabledLayerCount;
889			DE_NULL,														//const char* const*				ppEnabledLayerNames;
890			static_cast<deUint32>(deviceExtensions.size()),					//deUint32							enabledExtensionCount;
891			deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],		//const char* const*				pEnabledExtensionNames;
892			DE_NULL															//const VkPhysicalDeviceFeatures*	pEnabledFeatures;
893		};
894
895		const auto instance = m_context.getInstance();
896
897		m_logicalDevice					= createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
898#ifndef CTS_USES_VULKANSC
899		m_device						= de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance, *m_logicalDevice, m_context.getUsedApiVersion()));
900#else
901		m_device						= de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(m_context.getPlatformInterface(), instance, *m_logicalDevice, m_context.getTestContext().getCommandLine(), m_context.getResourceInterface(), m_context.getDeviceVulkanSC10Properties(), m_context.getDeviceProperties(), m_context.getUsedApiVersion()), vk::DeinitDeviceDeleter(m_context.getResourceInterface().get(), *m_logicalDevice));
902#endif // CTS_USES_VULKANSC
903		m_allocator						= MovePtr<Allocator>(new SimpleAllocator(*m_device, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
904		m_device->getDeviceQueue		(*m_logicalDevice, m_queueFamilyIndex, 0u, &m_queue);
905	}
906}
907
908void MultiViewRenderTestInstance::createCommandBuffer (void)
909{
910	// cmdPool
911	{
912		const VkCommandPoolCreateInfo cmdPoolParams =
913		{
914			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType		sType;
915			DE_NULL,											// const void*			pNext;
916			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCmdPoolCreateFlags	flags;
917			m_queueFamilyIndex,									// deUint32				queueFamilyIndex;
918		};
919		m_cmdPool = createCommandPool(*m_device, *m_logicalDevice, &cmdPoolParams);
920	}
921
922	// cmdBuffer
923	{
924		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
925		{
926			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
927			DE_NULL,											// const void*			pNext;
928			*m_cmdPool,											// VkCommandPool		commandPool;
929			VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
930			1u,													// deUint32				bufferCount;
931		};
932		m_cmdBuffer	= allocateCommandBuffer(*m_device, *m_logicalDevice, &cmdBufferAllocateInfo);
933	}
934}
935
936void MultiViewRenderTestInstance::createSecondaryCommandPool(void)
937{
938	// cmdPool
939	{
940		const VkCommandPoolCreateInfo cmdPoolParams =
941		{
942			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType		sType;
943			DE_NULL,											// const void*			pNext;
944			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCmdPoolCreateFlags	flags;
945			m_queueFamilyIndex,									// deUint32				queueFamilyIndex;
946		};
947		m_cmdPoolSecondary = createCommandPool(*m_device, *m_logicalDevice, &cmdPoolParams);
948	}
949}
950
951void MultiViewRenderTestInstance::madeShaderModule (map<VkShaderStageFlagBits, ShaderModuleSP>& shaderModule, vector<VkPipelineShaderStageCreateInfo>& shaderStageParams)
952{
953	// create shaders modules
954	switch (m_parameters.viewIndex)
955	{
956		case TEST_TYPE_VIEW_MASK:
957		case TEST_TYPE_VIEW_INDEX_IN_VERTEX:
958		case TEST_TYPE_VIEW_INDEX_IN_FRAGMENT:
959		case TEST_TYPE_INSTANCED_RENDERING:
960		case TEST_TYPE_INPUT_RATE_INSTANCE:
961		case TEST_TYPE_DRAW_INDIRECT:
962		case TEST_TYPE_DRAW_INDIRECT_INDEXED:
963		case TEST_TYPE_DRAW_INDEXED:
964		case TEST_TYPE_CLEAR_ATTACHMENTS:
965		case TEST_TYPE_SECONDARY_CMD_BUFFER:
966		case TEST_TYPE_INPUT_ATTACHMENTS:
967		case TEST_TYPE_POINT_SIZE:
968		case TEST_TYPE_MULTISAMPLE:
969		case TEST_TYPE_QUERIES:
970		case TEST_TYPE_NON_PRECISE_QUERIES:
971		case TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY:
972		case TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR:
973		case TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR:
974		case TEST_TYPE_DEPTH:
975		case TEST_TYPE_DEPTH_DIFFERENT_RANGES:
976		case TEST_TYPE_STENCIL:
977			shaderModule[VK_SHADER_STAGE_VERTEX_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("vertex"), 0))));
978			shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("fragment"), 0))));
979			break;
980		case TEST_TYPE_VIEW_INDEX_IN_GEOMETRY:
981		case TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY:
982		case TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY:
983			shaderModule[VK_SHADER_STAGE_VERTEX_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("vertex"), 0))));
984			shaderModule[VK_SHADER_STAGE_GEOMETRY_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("geometry"), 0))));
985			shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("fragment"), 0))));
986			break;
987		case TEST_TYPE_VIEW_INDEX_IN_TESELLATION:
988			shaderModule[VK_SHADER_STAGE_VERTEX_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("vertex"), 0))));
989			shaderModule[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT]		= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("tessellation_control"), 0))));
990			shaderModule[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT]	= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("tessellation_evaluation"), 0))));
991			shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("fragment"), 0))));
992			break;
993		case TEST_TYPE_VIEW_MASK_ITERATION:
994		{
995			const auto	vk12Support	= m_context.contextSupports(vk::ApiVersion(0u, 1u, 2u, 0u));
996			const auto	vertShaderName = vk12Support ? "vert-spv15" : "vert-spv10";
997			shaderModule[VK_SHADER_STAGE_VERTEX_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get(vertShaderName), 0))));
998			shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT]					= (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("view_mask_iteration"), 0))));
999			break;
1000		}
1001		default:
1002			DE_ASSERT(0);
1003		break;
1004	}
1005
1006	VkPipelineShaderStageCreateInfo	pipelineShaderStage	=
1007	{
1008			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
1009			DE_NULL,												// const void*							pNext;
1010			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
1011			(VkShaderStageFlagBits)0,								// VkShaderStageFlagBits				stage;
1012			(VkShaderModule)0,										// VkShaderModule						module;
1013			"main",													// const char*							pName;
1014			(const VkSpecializationInfo*)DE_NULL,					// const VkSpecializationInfo*			pSpecializationInfo;
1015	};
1016
1017	for (map<VkShaderStageFlagBits, ShaderModuleSP>::iterator it=shaderModule.begin(); it!=shaderModule.end(); ++it)
1018	{
1019		pipelineShaderStage.stage	= it->first;
1020		pipelineShaderStage.module	= **it->second;
1021		shaderStageParams.push_back(pipelineShaderStage);
1022	}
1023}
1024
1025Move<VkPipeline> MultiViewRenderTestInstance::makeGraphicsPipeline (const VkRenderPass							renderPass,
1026																	const VkPipelineLayout						pipelineLayout,
1027																	const deUint32								pipelineShaderStageCount,
1028																	const VkPipelineShaderStageCreateInfo*		pipelineShaderStageCreate,
1029																	const deUint32								subpass,
1030																	const VkVertexInputRate						vertexInputRate,
1031																	const bool									useDepthTest,
1032																	const bool									useStencilTest,
1033																	const float									minDepth,
1034																	const float									maxDepth,
1035																	const VkFormat								dsFormat)
1036{
1037	const VkVertexInputBindingDescription			vertexInputBindingDescriptions[]	=
1038	{
1039		{
1040			0u,													// binding;
1041			static_cast<deUint32>(sizeof(m_vertexCoord[0])),	// stride;
1042			vertexInputRate										// inputRate
1043		},
1044		{
1045			1u,													// binding;
1046			static_cast<deUint32>(sizeof(m_vertexColor[0])),	// stride;
1047			vertexInputRate										// inputRate
1048		}
1049	};
1050
1051	const VkVertexInputAttributeDescription			vertexInputAttributeDescriptions[]	=
1052	{
1053		{
1054			0u,											// deUint32	location;
1055			0u,											// deUint32	binding;
1056			VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
1057			0u											// deUint32	offset;
1058		},	// VertexElementData::position
1059		{
1060			1u,											// deUint32	location;
1061			1u,											// deUint32	binding;
1062			VK_FORMAT_R32G32B32A32_SFLOAT,				// VkFormat	format;
1063			0u											// deUint32	offset;
1064		},	// VertexElementData::color
1065	};
1066
1067	const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams				=
1068	{
1069		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1070		NULL,															// const void*								pNext;
1071		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1072		DE_LENGTH_OF_ARRAY(vertexInputBindingDescriptions),				// deUint32									vertexBindingDescriptionCount;
1073		vertexInputBindingDescriptions,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1074		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// deUint32									vertexAttributeDescriptionCount;
1075		vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1076	};
1077
1078	const VkPrimitiveTopology						topology							= (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
1079																						  (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex) ? VK_PRIMITIVE_TOPOLOGY_POINT_LIST :
1080																						  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1081
1082	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams			=
1083	{
1084		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
1085		DE_NULL,														// const void*								pNext;
1086		0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
1087		topology,														// VkPrimitiveTopology						topology;
1088		VK_FALSE,														// VkBool32									primitiveRestartEnable;
1089	};
1090
1091	const VkViewport	viewport	= makeViewport(0.0f, 0.0f, (float)m_parameters.extent.width, (float)m_parameters.extent.height, minDepth, maxDepth);
1092	const VkRect2D		scissor		= makeRect2D(m_parameters.extent);
1093
1094	const VkPipelineViewportStateCreateInfo			viewportStateParams					=
1095	{
1096		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType						sType;
1097		DE_NULL,												// const void*							pNext;
1098		0u,														// VkPipelineViewportStateCreateFlags	flags;
1099		1u,														// deUint32								viewportCount;
1100		&viewport,												// const VkViewport*					pViewports;
1101		1u,														// deUint32								scissorCount;
1102		&scissor												// const VkRect2D*						pScissors;
1103	};
1104
1105	const VkPipelineRasterizationStateCreateInfo	rasterStateParams					=
1106	{
1107		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
1108		DE_NULL,													// const void*								pNext;
1109		0u,															// VkPipelineRasterizationStateCreateFlags	flags;
1110		VK_FALSE,													// VkBool32									depthClampEnable;
1111		VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
1112		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
1113		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
1114		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
1115		VK_FALSE,													// VkBool32									depthBiasEnable;
1116		0.0f,														// float									depthBiasConstantFactor;
1117		0.0f,														// float									depthBiasClamp;
1118		0.0f,														// float									depthBiasSlopeFactor;
1119		1.0f,														// float									lineWidth;
1120	};
1121
1122	const VkSampleCountFlagBits						sampleCountFlagBits					= (TEST_TYPE_MULTISAMPLE == m_parameters.viewIndex) ? VK_SAMPLE_COUNT_4_BIT :
1123																						  VK_SAMPLE_COUNT_1_BIT;
1124	const VkPipelineMultisampleStateCreateInfo		multisampleStateParams				=
1125	{
1126		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
1127		DE_NULL,													// const void*								pNext;
1128		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
1129		sampleCountFlagBits,										// VkSampleCountFlagBits					rasterizationSamples;
1130		VK_FALSE,													// VkBool32									sampleShadingEnable;
1131		0.0f,														// float									minSampleShading;
1132		DE_NULL,													// const VkSampleMask*						pSampleMask;
1133		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
1134		VK_FALSE,													// VkBool32									alphaToOneEnable;
1135	};
1136
1137	VkPipelineDepthStencilStateCreateInfo			depthStencilStateParams				=
1138	{
1139		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
1140		DE_NULL,													// const void*								pNext;
1141		0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
1142		useDepthTest ? VK_TRUE : VK_FALSE,							// VkBool32									depthTestEnable;
1143		useDepthTest ? VK_TRUE : VK_FALSE,							// VkBool32									depthWriteEnable;
1144		VK_COMPARE_OP_LESS_OR_EQUAL,								// VkCompareOp								depthCompareOp;
1145		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
1146		useStencilTest ? VK_TRUE : VK_FALSE,						// VkBool32									stencilTestEnable;
1147		// VkStencilOpState front;
1148		{
1149			VK_STENCIL_OP_KEEP,					// VkStencilOp	failOp;
1150			VK_STENCIL_OP_INCREMENT_AND_CLAMP,	// VkStencilOp	passOp;
1151			VK_STENCIL_OP_KEEP,					// VkStencilOp	depthFailOp;
1152			VK_COMPARE_OP_ALWAYS,				// VkCompareOp	compareOp;
1153			~0u,								// deUint32		compareMask;
1154			~0u,								// deUint32		writeMask;
1155			0u,									// deUint32		reference;
1156		},
1157		// VkStencilOpState back;
1158		{
1159			VK_STENCIL_OP_KEEP,					// VkStencilOp	failOp;
1160			VK_STENCIL_OP_INCREMENT_AND_CLAMP,	// VkStencilOp	passOp;
1161			VK_STENCIL_OP_KEEP,					// VkStencilOp	depthFailOp;
1162			VK_COMPARE_OP_ALWAYS,				// VkCompareOp	compareOp;
1163			~0u,								// deUint32		compareMask;
1164			~0u,								// deUint32		writeMask;
1165			0u,									// deUint32		reference;
1166		},
1167		0.0f,	// float	minDepthBounds;
1168		1.0f,	// float	maxDepthBounds;
1169	};
1170
1171	const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState			=
1172	{
1173		VK_FALSE,								// VkBool32					blendEnable;
1174		VK_BLEND_FACTOR_SRC_ALPHA,				// VkBlendFactor			srcColorBlendFactor;
1175		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,	// VkBlendFactor			dstColorBlendFactor;
1176		VK_BLEND_OP_ADD,						// VkBlendOp				colorBlendOp;
1177		VK_BLEND_FACTOR_ONE,					// VkBlendFactor			srcAlphaBlendFactor;
1178		VK_BLEND_FACTOR_ONE,					// VkBlendFactor			dstAlphaBlendFactor;
1179		VK_BLEND_OP_ADD,						// VkBlendOp				alphaBlendOp;
1180		VK_COLOR_COMPONENT_R_BIT |				// VkColorComponentFlags	colorWriteMask;
1181		VK_COLOR_COMPONENT_G_BIT |
1182		VK_COLOR_COMPONENT_B_BIT |
1183		VK_COLOR_COMPONENT_A_BIT
1184	};
1185
1186	const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams				=
1187	{
1188		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1189		DE_NULL,													// const void*									pNext;
1190		0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1191		VK_FALSE,													// VkBool32										logicOpEnable;
1192		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1193		1u,															// deUint32										attachmentCount;
1194		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1195		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1196	};
1197
1198	VkPipelineTessellationStateCreateInfo			TessellationState					=
1199	{
1200		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	// VkStructureType							sType;
1201		DE_NULL,													// const void*								pNext;
1202		(VkPipelineTessellationStateCreateFlags)0,					// VkPipelineTessellationStateCreateFlags	flags;
1203		4u															// deUint32									patchControlPoints;
1204	};
1205
1206#ifndef CTS_USES_VULKANSC
1207	VkPipelineRenderingCreateInfoKHR				renderingCreateInfo
1208	{
1209		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1210		DE_NULL,
1211		m_parameters.viewMasks[subpass],
1212		1u,
1213		&m_parameters.colorFormat,
1214		dsFormat,
1215		dsFormat
1216	};
1217#else
1218	DE_UNREF(dsFormat);
1219#endif // CTS_USES_VULKANSC
1220
1221	const VkGraphicsPipelineCreateInfo				graphicsPipelineParams
1222	{
1223		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,												// VkStructureType									sType;
1224#ifndef CTS_USES_VULKANSC
1225		(renderPass == 0) ? &renderingCreateInfo : DE_NULL,												// const void*										pNext;
1226#else
1227		DE_NULL,																						// const void*										pNext;
1228#endif // CTS_USES_VULKANSC
1229		(VkPipelineCreateFlags)0u,																		// VkPipelineCreateFlags							flags;
1230		pipelineShaderStageCount,																		// deUint32											stageCount;
1231		pipelineShaderStageCreate,																		// const VkPipelineShaderStageCreateInfo*			pStages;
1232		&vertexInputStateParams,																		// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1233		&inputAssemblyStateParams,																		// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1234		(TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex)? &TessellationState : DE_NULL,	// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1235		&viewportStateParams,																			// const VkPipelineViewportStateCreateInfo*			pViewportState;
1236		&rasterStateParams,																				// const VkPipelineRasterizationStateCreateInfo*	pRasterState;
1237		&multisampleStateParams,																		// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1238		&depthStencilStateParams,																		// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1239		&colorBlendStateParams,																			// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1240		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,												// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1241		pipelineLayout,																					// VkPipelineLayout									layout;
1242		renderPass,																						// VkRenderPass										renderPass;
1243		subpass,																						// deUint32											subpass;
1244		0u,																								// VkPipeline										basePipelineHandle;
1245		0,																								// deInt32											basePipelineIndex;
1246	};
1247
1248	return createGraphicsPipeline(*m_device, *m_logicalDevice, DE_NULL, &graphicsPipelineParams);
1249}
1250
1251void MultiViewRenderTestInstance::readImage (VkImage image, const tcu::PixelBufferAccess& dst)
1252{
1253	Move<VkBuffer>				buffer;
1254	MovePtr<Allocation>			bufferAlloc;
1255	const VkDeviceSize			pixelDataSize	= dst.getWidth() * dst.getHeight() * dst.getDepth() * mapVkFormat(m_parameters.colorFormat).getPixelSize();
1256
1257	// Create destination buffer
1258	{
1259		const VkBufferCreateInfo bufferParams	=
1260		{
1261			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1262			DE_NULL,								// const void*			pNext;
1263			0u,										// VkBufferCreateFlags	flags;
1264			pixelDataSize,							// VkDeviceSize			size;
1265			VK_BUFFER_USAGE_TRANSFER_DST_BIT,		// VkBufferUsageFlags	usage;
1266			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1267			1u,										// deUint32				queueFamilyIndexCount;
1268			&m_queueFamilyIndex,					// const deUint32*		pQueueFamilyIndices;
1269		};
1270
1271		buffer		= createBuffer(*m_device, *m_logicalDevice, &bufferParams);
1272		bufferAlloc	= m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *buffer), MemoryRequirement::HostVisible);
1273		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1274
1275		deMemset(bufferAlloc->getHostPtr(), 0, static_cast<size_t>(pixelDataSize));
1276		flushAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
1277	}
1278
1279	const VkBufferMemoryBarrier	bufferBarrier	=
1280	{
1281		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1282		DE_NULL,									// const void*		pNext;
1283		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
1284		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
1285		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1286		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1287		*buffer,									// VkBuffer			buffer;
1288		0u,											// VkDeviceSize		offset;
1289		pixelDataSize								// VkDeviceSize		size;
1290	};
1291
1292	// Copy image to buffer
1293	const VkImageAspectFlags	aspect			= getAspectFlags(dst.getFormat());
1294	const VkBufferImageCopy		copyRegion		=
1295	{
1296		0u,										// VkDeviceSize				bufferOffset;
1297		(deUint32)dst.getWidth(),				// deUint32					bufferRowLength;
1298		(deUint32)dst.getHeight(),				// deUint32					bufferImageHeight;
1299		{
1300			aspect,								// VkImageAspectFlags		aspect;
1301			0u,									// deUint32					mipLevel;
1302			0u,									// deUint32					baseArrayLayer;
1303			m_parameters.extent.depth,			// deUint32					layerCount;
1304		},										// VkImageSubresourceLayers	imageSubresource;
1305		{ 0, 0, 0 },							// VkOffset3D				imageOffset;
1306		{ m_parameters.extent.width, m_parameters.extent.height, 1u }	// VkExtent3D				imageExtent;
1307	};
1308
1309	beginCommandBuffer (*m_device, *m_cmdBuffer);
1310	{
1311		VkImageSubresourceRange	subresourceRange	=
1312		{
1313			aspect,						// VkImageAspectFlags	aspectMask;
1314			0u,							// deUint32				baseMipLevel;
1315			1u,							// deUint32				mipLevels;
1316			0u,							// deUint32				baseArraySlice;
1317			m_parameters.extent.depth,	// deUint32				arraySize;
1318		};
1319
1320		imageBarrier (*m_device, *m_cmdBuffer, image, subresourceRange,
1321			VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1322			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1323			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
1324
1325		m_device->cmdCopyImageToBuffer(*m_cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, &copyRegion);
1326		m_device->cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0u, DE_NULL);
1327	}
1328	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
1329	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
1330
1331	// Read buffer data
1332	invalidateAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
1333	tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferAlloc->getHostPtr()));
1334}
1335
1336bool MultiViewRenderTestInstance::checkImage (tcu::ConstPixelBufferAccess& renderedFrame)
1337{
1338	const MovePtr<tcu::Texture2DArray>	referenceFrame	= imageData();
1339	const bool							result			= tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
1340															"Result", "Image comparison result", referenceFrame->getLevel(0), renderedFrame, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
1341
1342	if (!result)
1343		for (deUint32 layerNdx = 0u; layerNdx < m_parameters.extent.depth; layerNdx++)
1344		{
1345			tcu::ConstPixelBufferAccess ref (mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, 1u, referenceFrame->getLevel(0).getPixelPtr(0, 0, layerNdx));
1346			tcu::ConstPixelBufferAccess dst (mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, 1u, renderedFrame.getPixelPtr(0 ,0, layerNdx));
1347			tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", ref, dst, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
1348		}
1349
1350	return result;
1351}
1352
1353const tcu::Vec4 MultiViewRenderTestInstance::getQuarterRefColor (const deUint32 quarterNdx, const int colorNdx, const int layerNdx, const bool background, const deUint32 subpassNdx) const
1354{
1355	// this function is used for genrating same colors while rendering and while creating reference
1356
1357	switch (m_parameters.viewIndex)
1358	{
1359		case TEST_TYPE_VIEW_MASK:
1360		case TEST_TYPE_VIEW_MASK_ITERATION:
1361			return m_vertexColor[colorNdx];
1362
1363		case TEST_TYPE_DRAW_INDEXED:
1364			return m_vertexColor[m_vertexIndices[colorNdx]];
1365
1366		case TEST_TYPE_INSTANCED_RENDERING:
1367			return m_vertexColor[0] + tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, static_cast<float>(quarterNdx + 1u) * 0.10f, 0.0);
1368
1369		case TEST_TYPE_INPUT_RATE_INSTANCE:
1370			return m_vertexColor[colorNdx / 4] + tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, static_cast<float>(quarterNdx + 1u) * 0.10f, 0.0);
1371
1372		case TEST_TYPE_DRAW_INDIRECT_INDEXED:
1373			return m_vertexColor[m_vertexIndices[colorNdx]] + tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, 0.0, 0.0);
1374
1375		case TEST_TYPE_VIEW_INDEX_IN_VERTEX:
1376		case TEST_TYPE_VIEW_INDEX_IN_FRAGMENT:
1377		case TEST_TYPE_VIEW_INDEX_IN_GEOMETRY:
1378		case TEST_TYPE_VIEW_INDEX_IN_TESELLATION:
1379		case TEST_TYPE_INPUT_ATTACHMENTS:
1380		case TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY:
1381		case TEST_TYPE_DRAW_INDIRECT:
1382		case TEST_TYPE_CLEAR_ATTACHMENTS:
1383		case TEST_TYPE_SECONDARY_CMD_BUFFER:
1384		case TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY:
1385			return m_vertexColor[colorNdx] + tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, 0.0, 0.0);
1386
1387		case TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR:
1388			if (background)
1389				return m_colorTable[4 + quarterNdx % 4];
1390			else
1391				return m_colorTable[layerNdx % 4];
1392
1393		case TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR:
1394			if (background)
1395				return m_colorTable[4 + quarterNdx % 4];
1396			else
1397				return m_colorTable[0];
1398
1399		case TEST_TYPE_POINT_SIZE:
1400		case TEST_TYPE_MULTISAMPLE:
1401			if (background)
1402				return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
1403			else
1404				return m_vertexColor[colorNdx];
1405
1406		case TEST_TYPE_DEPTH:
1407			if (background)
1408				if (subpassNdx < 4)
1409					return tcu::Vec4(0.66f, 0.0f, 0.0f, 1.0f);
1410				else
1411					return tcu::Vec4(0.33f, 0.0f, 0.0f, 1.0f);
1412			else
1413				return tcu::Vec4(0.99f, 0.0f, 0.0f, 1.0f);
1414
1415		case TEST_TYPE_DEPTH_DIFFERENT_RANGES:
1416			// for quads from partA generate  1.20, 0.90, 0.60,  0.30
1417			// for quads from partB generate  0.55, 0.35, 0.15, -0.05
1418			// depth ranges in views are <0;0.5>, <0;1> or <0.5;1> so
1419			// at least one quad from partA/partB will always be drawn
1420			if (subpassNdx < 4)
1421				return tcu::Vec4(1.2f - 0.3f * static_cast<float>(subpassNdx), 0.0f, 0.0f, 1.0f);
1422			return tcu::Vec4(0.55f - 0.2f * static_cast<float>(subpassNdx % 4), 0.0f, 0.0f, 1.0f);
1423
1424		case TEST_TYPE_STENCIL:
1425			if (background)
1426				return tcu::Vec4(0.33f, 0.0f, 0.0f, 0.0f); // Increment value
1427			else
1428				return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1429
1430		default:
1431			TCU_THROW(InternalError, "Impossible");
1432	}
1433}
1434
1435void MultiViewRenderTestInstance::setPoint (const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& pointColor, const int pointSize, const int layerNdx, const deUint32 quarter) const
1436{
1437	DE_ASSERT(TEST_POINT_SIZE_WIDE > TEST_POINT_SIZE_SMALL);
1438
1439	const int	pointOffset	= 1 + TEST_POINT_SIZE_WIDE / 2 - (pointSize + 1) / 2;
1440	const int	offsetX		= pointOffset + static_cast<int>((quarter == 0u || quarter == 1u) ? 0 : m_parameters.extent.width / 2u);
1441	const int	offsetY		= pointOffset + static_cast<int>((quarter == 0u || quarter == 2u) ? 0 : m_parameters.extent.height / 2u);
1442
1443	for (int y = 0; y < pointSize; ++y)
1444	for (int x = 0; x < pointSize; ++x)
1445		pixelBuffer.setPixel(pointColor, offsetX + x, offsetY + y, layerNdx);
1446}
1447
1448void MultiViewRenderTestInstance::fillTriangle (const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& color, const int layerNdx, const deUint32 quarter) const
1449{
1450	const int		offsetX				= static_cast<int>((quarter == 0u || quarter == 1u) ? 0 : m_parameters.extent.width / 2u);
1451	const int		offsetY				= static_cast<int>((quarter == 0u || quarter == 2u) ? 0 : m_parameters.extent.height / 2u);
1452	const int		maxY				= static_cast<int>(m_parameters.extent.height / 2u);
1453	const tcu::Vec4	multisampledColor	= tcu::Vec4(color[0], color[1], color[2], color[3]) * 0.5f;
1454
1455	for (int y = 0; y < maxY; ++y)
1456	{
1457		for (int x = 0; x < y; ++x)
1458			pixelBuffer.setPixel(color, offsetX + x, offsetY + (maxY - 1) - y, layerNdx);
1459
1460		// Multisampled pixel is on the triangle margin
1461		pixelBuffer.setPixel(multisampledColor, offsetX + y, offsetY + (maxY - 1) - y, layerNdx);
1462	}
1463}
1464
1465void MultiViewRenderTestInstance::fillLayer (const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& color, const int layerNdx) const
1466{
1467	for (deUint32 y = 0u; y < m_parameters.extent.height; ++y)
1468	for (deUint32 x = 0u; x < m_parameters.extent.width; ++x)
1469		pixelBuffer.setPixel(color, x, y, layerNdx);
1470}
1471
1472void MultiViewRenderTestInstance::fillQuarter (const tcu::PixelBufferAccess& pixelBuffer, const tcu::Vec4& color, const int layerNdx, const deUint32 quarter, const deUint32 subpassNdx) const
1473{
1474	const int h		= m_parameters.extent.height;
1475	const int h2	= h / 2;
1476	const int w		= m_parameters.extent.width;
1477	const int w2	= w / 2;
1478	int xStart		= 0;
1479	int xEnd		= 0;
1480	int yStart		= 0;
1481	int yEnd		= 0;
1482
1483	switch (quarter)
1484	{
1485		case 0:	xStart = 0u; xEnd = w2; yStart = 0u; yEnd = h2; break;
1486		case 1:	xStart = 0u; xEnd = w2; yStart = h2; yEnd = h;  break;
1487		case 2:	xStart = w2; xEnd = w;  yStart = 0u; yEnd = h2; break;
1488		case 3:	xStart = w2; xEnd = w;  yStart = h2; yEnd = h;  break;
1489		default: TCU_THROW(InternalError, "Impossible");
1490	}
1491
1492	if (TEST_TYPE_STENCIL == m_parameters.viewIndex ||
1493		TEST_TYPE_DEPTH == m_parameters.viewIndex ||
1494		TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex)
1495	{
1496		if (subpassNdx < 4)
1497		{	// Part A: Horizontal bars near X axis
1498			yStart	= h2 + (yStart - h2) / 2;
1499			yEnd	= h2 + (yEnd - h2) / 2;
1500		}
1501		else
1502		{	// Part B: Vertical bars near Y axis (drawn twice)
1503			xStart	= w2 + (xStart - w2) / 2;
1504			xEnd	= w2 + (xEnd - w2) / 2;
1505		}
1506
1507		// Update pixels in area
1508		if (TEST_TYPE_STENCIL == m_parameters.viewIndex)
1509		{
1510			for (int y = yStart; y < yEnd; ++y)
1511			for (int x = xStart; x < xEnd; ++x)
1512				pixelBuffer.setPixel(pixelBuffer.getPixel(x, y, layerNdx) + color, x, y, layerNdx);
1513		}
1514
1515		if (TEST_TYPE_DEPTH == m_parameters.viewIndex ||
1516			TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex)
1517		{
1518			for (int y = yStart; y < yEnd; ++y)
1519			for (int x = xStart; x < xEnd; ++x)
1520			{
1521				const tcu::Vec4		currentColor	= pixelBuffer.getPixel(x, y, layerNdx);
1522				const tcu::Vec4&	newColor		= (currentColor[0] < color[0]) ? currentColor : color;
1523
1524				pixelBuffer.setPixel(newColor, x, y, layerNdx);
1525			}
1526		}
1527	}
1528	else
1529	{
1530		for (int y = yStart; y < yEnd; ++y)
1531		for (int x = xStart; x < xEnd; ++x)
1532			pixelBuffer.setPixel(color , x, y, layerNdx);
1533	}
1534}
1535
1536MovePtr<tcu::Texture2DArray> MultiViewRenderTestInstance::imageData (void) const
1537{
1538	MovePtr<tcu::Texture2DArray>	referenceFrame	= MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth));
1539	const deUint32					subpassCount	= static_cast<deUint32>(m_parameters.viewMasks.size());
1540	referenceFrame->allocLevel(0);
1541
1542	deMemset (referenceFrame->getLevel(0).getDataPtr(), 0, m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth* mapVkFormat(m_parameters.colorFormat).getPixelSize());
1543
1544	if (TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR == m_parameters.viewIndex || TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR == m_parameters.viewIndex)
1545	{
1546		deUint32	clearedViewMask	= 0;
1547
1548		// Start from last clear command color, which actually takes effect
1549		for (int subpassNdx = static_cast<int>(subpassCount) - 1; subpassNdx >= 0; --subpassNdx)
1550		{
1551			deUint32	subpassToClearViewMask	= m_parameters.viewMasks[subpassNdx] & ~clearedViewMask;
1552
1553			if (subpassToClearViewMask == 0)
1554				continue;
1555
1556			for (deUint32 layerNdx = 0; layerNdx < m_parameters.extent.depth; ++layerNdx)
1557				if ((subpassToClearViewMask & (1 << layerNdx)) != 0 && (clearedViewMask & (1 << layerNdx)) == 0)
1558					fillLayer(referenceFrame->getLevel(0), getQuarterRefColor(0u, 0u, subpassNdx, false), layerNdx);
1559
1560			// These has been cleared. Exclude these layers from upcoming attempts to clear
1561			clearedViewMask |= subpassToClearViewMask;
1562		}
1563	}
1564
1565	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
1566	{
1567		int			layerNdx	= 0;
1568		deUint32	mask		= m_parameters.viewMasks[subpassNdx];
1569
1570		// iterate over image layers
1571		while (mask > 0u)
1572		{
1573			int colorNdx	= 0;
1574
1575			if (mask & 1u)
1576			{
1577				if (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex)
1578				{
1579					struct ColorDataRGBA
1580					{
1581						deUint8	r;
1582						deUint8	g;
1583						deUint8	b;
1584						deUint8	a;
1585					};
1586
1587					ColorDataRGBA	clear		=
1588					{
1589						tcu::floatToU8 (1.0f),
1590						tcu::floatToU8 (0.0f),
1591						tcu::floatToU8 (0.0f),
1592						tcu::floatToU8 (1.0f)
1593					};
1594
1595					ColorDataRGBA*	dataSrc		= (ColorDataRGBA*)referenceFrame->getLevel(0).getPixelPtr(0, 0, layerNdx);
1596					ColorDataRGBA*	dataDes		= dataSrc + 1;
1597					deUint32		copySize	= 1u;
1598					deUint32		layerSize	= m_parameters.extent.width * m_parameters.extent.height - copySize;
1599					deMemcpy(dataSrc, &clear, sizeof(ColorDataRGBA));
1600
1601					while (layerSize > 0)
1602					{
1603						deMemcpy(dataDes, dataSrc, copySize * sizeof(ColorDataRGBA));
1604						dataDes = dataDes + copySize;
1605						layerSize = layerSize - copySize;
1606						copySize = 2u * copySize;
1607						if (copySize >= layerSize)
1608							copySize = layerSize;
1609					}
1610				}
1611
1612				const deUint32 subpassQuarterNdx = subpassNdx % m_squareCount;
1613				if (subpassQuarterNdx == 0u || TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1614				{
1615					const tcu::Vec4 color = getQuarterRefColor(0u, colorNdx, layerNdx, true, subpassNdx);
1616
1617					fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 0u, subpassNdx);
1618				}
1619
1620				colorNdx += 4;
1621				if (subpassQuarterNdx == 1u || subpassCount == 1u || TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1622				{
1623					const tcu::Vec4 color = getQuarterRefColor(1u, colorNdx, layerNdx, true, subpassNdx);
1624
1625					fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 1u, subpassNdx);
1626				}
1627
1628				colorNdx += 4;
1629				if (subpassQuarterNdx == 2u || subpassCount == 1u || TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1630				{
1631					const tcu::Vec4 color = getQuarterRefColor(2u, colorNdx, layerNdx, true, subpassNdx);
1632
1633					fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 2u, subpassNdx);
1634				}
1635
1636				colorNdx += 4;
1637				if (subpassQuarterNdx == 3u || subpassCount == 1u || TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1638				{
1639					const tcu::Vec4 color = getQuarterRefColor(3u, colorNdx, layerNdx, true, subpassNdx);
1640
1641					fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 3u, subpassNdx);
1642				}
1643
1644				if (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex)
1645				{
1646					const tcu::Vec4	color	(0.0f, 0.0f, 1.0f, 1.0f);
1647					const int		maxY	= static_cast<int>(static_cast<float>(m_parameters.extent.height) * 0.75f);
1648					const int		maxX	= static_cast<int>(static_cast<float>(m_parameters.extent.width) * 0.75f);
1649					for (int y = static_cast<int>(m_parameters.extent.height / 4u); y < maxY; ++y)
1650					for (int x = static_cast<int>(m_parameters.extent.width / 4u); x < maxX; ++x)
1651						referenceFrame->getLevel(0).setPixel(color, x, y, layerNdx);
1652				}
1653
1654				if (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)
1655				{
1656					const deUint32	vertexPerPrimitive	= 1u;
1657					const deUint32	unusedQuarterNdx	= 0u;
1658					const int		pointSize			= static_cast<int>(layerNdx == 0u ? TEST_POINT_SIZE_WIDE : TEST_POINT_SIZE_SMALL);
1659
1660					if (subpassCount == 1)
1661						for (deUint32 drawNdx = 0u; drawNdx < m_squareCount; ++drawNdx)
1662							setPoint(referenceFrame->getLevel(0), getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * drawNdx, layerNdx, false), pointSize, layerNdx, drawNdx);
1663					else
1664						setPoint(referenceFrame->getLevel(0), getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * subpassQuarterNdx, layerNdx, false), pointSize, layerNdx, subpassQuarterNdx);
1665				}
1666
1667				if (TEST_TYPE_MULTISAMPLE == m_parameters.viewIndex)
1668				{
1669					const deUint32	vertexPerPrimitive	= 3u;
1670					const deUint32	unusedQuarterNdx	= 0u;
1671
1672					if (subpassCount == 1)
1673						for (deUint32 drawNdx = 0u; drawNdx < m_squareCount; ++drawNdx)
1674							fillTriangle(referenceFrame->getLevel(0), getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * drawNdx, layerNdx, false), layerNdx, drawNdx);
1675					else
1676						fillTriangle(referenceFrame->getLevel(0), getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * subpassQuarterNdx, layerNdx, false), layerNdx, subpassQuarterNdx);
1677				}
1678			}
1679
1680			mask = mask >> 1;
1681			++layerNdx;
1682		}
1683	}
1684	return referenceFrame;
1685}
1686
1687void MultiViewRenderTestInstance::appendVertex (const tcu::Vec4& coord, const tcu::Vec4& color)
1688{
1689	m_vertexCoord.push_back(coord);
1690	m_vertexColor.push_back(color);
1691}
1692
1693class MultiViewAttachmentsTestInstance : public MultiViewRenderTestInstance
1694{
1695public:
1696						MultiViewAttachmentsTestInstance	(Context& context, const TestParameters& parameters);
1697protected:
1698	tcu::TestStatus		iterate								(void) override;
1699	void				beforeRenderPass					(void) override;
1700	void				bindResources						(void) override;
1701	void				setImageData						(VkImage image);
1702	de::SharedPtr<ImageAttachment>	m_inputAttachment;
1703	Move<VkDescriptorPool>			m_descriptorPool;
1704	Move<VkDescriptorSet>			m_descriptorSet;
1705	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
1706	Move<VkPipelineLayout>			m_pipelineLayout;
1707
1708};
1709
1710MultiViewAttachmentsTestInstance::MultiViewAttachmentsTestInstance (Context& context, const TestParameters& parameters)
1711	: MultiViewRenderTestInstance	(context, parameters)
1712{
1713}
1714
1715tcu::TestStatus MultiViewAttachmentsTestInstance::iterate (void)
1716{
1717	const deUint32								subpassCount			= static_cast<deUint32>(m_parameters.viewMasks.size());
1718	Move<VkRenderPass>							renderPass;
1719	Move<VkFramebuffer>							frameBuffer;
1720
1721	// All color attachment
1722	m_colorAttachment	= de::SharedPtr<ImageAttachment>(new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat));
1723	m_inputAttachment	= de::SharedPtr<ImageAttachment>(new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat));
1724
1725	// FrameBuffer & renderPass
1726	if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
1727	{
1728		vector<VkImageView> attachments
1729		{
1730			m_colorAttachment->getImageView(),
1731			m_inputAttachment->getImageView()
1732		};
1733		renderPass	= makeRenderPassWithAttachments(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_parameters.renderingType);
1734		frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, static_cast<deUint32>(attachments.size()), attachments.data(), m_parameters.extent.width, m_parameters.extent.height);
1735	}
1736
1737	// pipelineLayout
1738	m_descriptorSetLayout	= makeDescriptorSetLayout(*m_device, *m_logicalDevice);
1739	m_pipelineLayout		= makePipelineLayout(*m_device, *m_logicalDevice, m_descriptorSetLayout.get());
1740
1741	// pipelines
1742	map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
1743	vector<PipelineSp>							pipelines(subpassCount);
1744
1745	{
1746		vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
1747		madeShaderModule(shaderModule, shaderStageParams);
1748		for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
1749			pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(*renderPass, *m_pipelineLayout, static_cast<deUint32>(shaderStageParams.size()), shaderStageParams.data(), subpassNdx))));
1750	}
1751
1752	createVertexData();
1753	createVertexBuffer();
1754
1755	createCommandBuffer();
1756	setImageData(m_inputAttachment->getImage());
1757	draw(subpassCount, *renderPass, *frameBuffer, pipelines);
1758
1759	{
1760		vector<deUint8>			pixelAccessData	(m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth * mapVkFormat(m_parameters.colorFormat).getPixelSize());
1761		tcu::PixelBufferAccess	dst				(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
1762
1763		readImage (m_colorAttachment->getImage(), dst);
1764		if (!checkImage(dst))
1765			return tcu::TestStatus::fail("Fail");
1766	}
1767
1768	return tcu::TestStatus::pass("Pass");
1769}
1770
1771void MultiViewAttachmentsTestInstance::beforeRenderPass (void)
1772{
1773	const VkDescriptorPoolSize poolSize =
1774	{
1775		vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1776		1u
1777	};
1778
1779	const VkDescriptorPoolCreateInfo createInfo =
1780	{
1781		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1782		DE_NULL,
1783		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1784		1u,
1785		1u,
1786		&poolSize
1787	};
1788
1789	m_descriptorPool = createDescriptorPool(*m_device, *m_logicalDevice, &createInfo);
1790
1791	const VkDescriptorSetAllocateInfo	allocateInfo =
1792	{
1793		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1794		DE_NULL,
1795		*m_descriptorPool,
1796		1u,
1797		&m_descriptorSetLayout.get()
1798	};
1799
1800	m_descriptorSet	= vk::allocateDescriptorSet(*m_device, *m_logicalDevice, &allocateInfo);
1801
1802	const VkDescriptorImageInfo	imageInfo =
1803	{
1804		(VkSampler)0,
1805		m_inputAttachment->getImageView(),
1806		VK_IMAGE_LAYOUT_GENERAL
1807	};
1808
1809	const VkWriteDescriptorSet	write =
1810	{
1811		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	//VkStructureType				sType;
1812		DE_NULL,								//const void*					pNext;
1813		*m_descriptorSet,						//VkDescriptorSet				dstSet;
1814		0u,										//deUint32						dstBinding;
1815		0u,										//deUint32						dstArrayElement;
1816		1u,										//deUint32						descriptorCount;
1817		VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	//VkDescriptorType				descriptorType;
1818		&imageInfo,								//const VkDescriptorImageInfo*	pImageInfo;
1819		DE_NULL,								//const VkDescriptorBufferInfo*	pBufferInfo;
1820		DE_NULL,								//const VkBufferView*			pTexelBufferView;
1821	};
1822
1823	m_device->updateDescriptorSets(*m_logicalDevice, (deUint32)1u, &write, 0u, DE_NULL);
1824
1825	const VkImageSubresourceRange	subresourceRange	=
1826	{
1827		VK_IMAGE_ASPECT_COLOR_BIT,	//VkImageAspectFlags	aspectMask;
1828		0u,							//deUint32				baseMipLevel;
1829		1u,							//deUint32				levelCount;
1830		0u,							//deUint32				baseArrayLayer;
1831		m_parameters.extent.depth,	//deUint32				layerCount;
1832	};
1833
1834	imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
1835		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1836		0, VK_ACCESS_TRANSFER_WRITE_BIT,
1837		VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
1838
1839	const VkClearValue renderPassClearValue = makeClearValueColor(tcu::Vec4(0.0f));
1840	m_device->cmdClearColorImage(*m_cmdBuffer, m_colorAttachment->getImage(),  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &renderPassClearValue.color, 1, &subresourceRange);
1841
1842	imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
1843		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1844		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1845		VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1846}
1847
1848void MultiViewAttachmentsTestInstance::bindResources (void)
1849{
1850	m_device->cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, NULL);
1851}
1852
1853void MultiViewAttachmentsTestInstance::setImageData (VkImage image)
1854{
1855	const MovePtr<tcu::Texture2DArray>		data		= imageData();
1856	Move<VkBuffer>					buffer;
1857	const deUint32					bufferSize	= m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth * tcu::getPixelSize(mapVkFormat(m_parameters.colorFormat));
1858	MovePtr<Allocation>				bufferAlloc;
1859
1860	// Create source buffer
1861	{
1862		const VkBufferCreateInfo		bufferParams			=
1863		{
1864			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1865			DE_NULL,									// const void*			pNext;
1866			0u,											// VkBufferCreateFlags	flags;
1867			bufferSize,									// VkDeviceSize			size;
1868			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
1869			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1870			1u,											// deUint32				queueFamilyIndexCount;
1871			&m_queueFamilyIndex,						// const deUint32*		pQueueFamilyIndices;
1872		};
1873
1874		buffer		= createBuffer(*m_device, *m_logicalDevice, &bufferParams);
1875		bufferAlloc = m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *buffer), MemoryRequirement::HostVisible);
1876		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1877	}
1878
1879	// Barriers for copying buffer to image
1880	const VkBufferMemoryBarrier				preBufferBarrier		=
1881	{
1882		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType	sType;
1883		DE_NULL,										// const void*		pNext;
1884		VK_ACCESS_HOST_WRITE_BIT,						// VkAccessFlags	srcAccessMask;
1885		VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags	dstAccessMask;
1886		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
1887		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
1888		*buffer,										// VkBuffer			buffer;
1889		0u,												// VkDeviceSize		offset;
1890		bufferSize										// VkDeviceSize		size;
1891	};
1892
1893	const VkImageAspectFlags				formatAspect			= getAspectFlags(mapVkFormat(m_parameters.colorFormat));
1894	VkImageSubresourceRange					subresourceRange		=
1895	{												// VkImageSubresourceRange	subresourceRange;
1896		formatAspect,				// VkImageAspectFlags	aspect;
1897		0u,							// deUint32				baseMipLevel;
1898		1u,							// deUint32				mipLevels;
1899		0u,							// deUint32				baseArraySlice;
1900		m_parameters.extent.depth,	// deUint32				arraySize;
1901	};
1902
1903	const VkBufferImageCopy					copyRegion				=
1904	{
1905		0u,															// VkDeviceSize				bufferOffset;
1906		(deUint32)data->getLevel(0).getWidth(),						// deUint32					bufferRowLength;
1907		(deUint32)data->getLevel(0).getHeight(),					// deUint32					bufferImageHeight;
1908		{
1909			VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags		aspect;
1910			0u,														// deUint32					mipLevel;
1911			0u,														// deUint32					baseArrayLayer;
1912			m_parameters.extent.depth,								// deUint32					layerCount;
1913		},															// VkImageSubresourceLayers	imageSubresource;
1914		{ 0, 0, 0 },												// VkOffset3D				imageOffset;
1915		{m_parameters.extent.width, m_parameters.extent.height, 1u}	// VkExtent3D				imageExtent;
1916	};
1917
1918	// Write buffer data
1919	deMemcpy(bufferAlloc->getHostPtr(), data->getLevel(0).getDataPtr(), bufferSize);
1920	flushAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
1921
1922	beginCommandBuffer(*m_device, *m_cmdBuffer);
1923
1924	m_device->cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1925	imageBarrier(*m_device, *m_cmdBuffer, image, subresourceRange,
1926		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1927		0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1928		VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
1929	m_device->cmdCopyBufferToImage(*m_cmdBuffer, *buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1930	imageBarrier(*m_device, *m_cmdBuffer, image, subresourceRange,
1931		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1932		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
1933		VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
1934	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
1935
1936	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
1937}
1938
1939class MultiViewInstancedTestInstance : public MultiViewRenderTestInstance
1940{
1941public:
1942						MultiViewInstancedTestInstance	(Context& context, const TestParameters& parameters);
1943protected:
1944	void				createVertexData				(void);
1945	void				draw							(const deUint32			subpassCount,
1946														 VkRenderPass			renderPass,
1947														 VkFramebuffer			frameBuffer,
1948														 vector<PipelineSp>&	pipelines);
1949};
1950
1951MultiViewInstancedTestInstance::MultiViewInstancedTestInstance (Context& context, const TestParameters& parameters)
1952	: MultiViewRenderTestInstance	(context, parameters)
1953{
1954}
1955
1956void MultiViewInstancedTestInstance::createVertexData (void)
1957{
1958	const tcu::Vec4 color = tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f);
1959
1960	appendVertex(tcu::Vec4(-1.0f,-1.0f, 1.0f, 1.0f), color);
1961	appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
1962	appendVertex(tcu::Vec4( 0.0f,-1.0f, 1.0f, 1.0f), color);
1963	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
1964}
1965
1966void MultiViewInstancedTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
1967{
1968	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
1969	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
1970	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
1971	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
1972	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
1973
1974	beginCommandBuffer(*m_device, *m_cmdBuffer);
1975
1976	beforeRenderPass();
1977
1978	if (!m_useDynamicRendering)
1979	{
1980		const VkRenderPassBeginInfo		renderPassBeginInfo =
1981		{
1982			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
1983			DE_NULL,									// const void*			pNext;
1984			renderPass,									// VkRenderPass			renderPass;
1985			frameBuffer,								// VkFramebuffer		framebuffer;
1986			renderArea,									// VkRect2D				renderArea;
1987			1u,											// uint32_t				clearValueCount;
1988			&renderPassClearValue,						// const VkClearValue*	pClearValues;
1989		};
1990		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
1991	}
1992
1993	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
1994	{
1995		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
1996
1997#ifndef CTS_USES_VULKANSC
1998		if (m_useDynamicRendering)
1999		{
2000			addRenderingSubpassDependencyIfRequired(subpassNdx);
2001
2002			beginRendering(
2003				*m_device,
2004				*m_cmdBuffer,
2005				m_colorAttachment->getImageView(),
2006				renderArea,
2007				renderPassClearValue,
2008				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2009				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2010				0u,
2011				m_parameters.extent.depth,
2012				m_parameters.viewMasks[subpassNdx]);
2013		}
2014#endif // CTS_USES_VULKANSC
2015
2016		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2017
2018		m_device->cmdDraw(*m_cmdBuffer, 4u, drawCountPerSubpass, 0u, subpassNdx % m_squareCount);
2019
2020#ifndef CTS_USES_VULKANSC
2021		if (m_useDynamicRendering)
2022			endRendering(*m_device, *m_cmdBuffer);
2023		else
2024#endif // CTS_USES_VULKANSC
2025			if (subpassNdx < subpassCount - 1u)
2026			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2027	}
2028
2029	if (!m_useDynamicRendering)
2030		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2031
2032	afterRenderPass();
2033
2034	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2035	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2036}
2037
2038class MultiViewInputRateInstanceTestInstance : public MultiViewRenderTestInstance
2039{
2040public:
2041				MultiViewInputRateInstanceTestInstance	(Context& context, const TestParameters& parameters);
2042protected:
2043	void		createVertexData						(void);
2044
2045	void		draw									(const deUint32			subpassCount,
2046														 VkRenderPass			renderPass,
2047														 VkFramebuffer			frameBuffer,
2048														 vector<PipelineSp>&	pipelines);
2049};
2050
2051MultiViewInputRateInstanceTestInstance::MultiViewInputRateInstanceTestInstance (Context& context, const TestParameters& parameters)
2052	: MultiViewRenderTestInstance	(context, parameters)
2053{
2054}
2055
2056void MultiViewInputRateInstanceTestInstance::createVertexData (void)
2057{
2058	appendVertex(tcu::Vec4(-1.0f,-1.0f, 1.0f, 1.0f), tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f));
2059	appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.3f, 0.0f, 0.2f, 1.0f));
2060	appendVertex(tcu::Vec4( 0.0f,-1.0f, 1.0f, 1.0f), tcu::Vec4(0.4f, 0.2f, 0.3f, 1.0f));
2061	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.5f, 0.0f, 0.4f, 1.0f));
2062}
2063
2064void MultiViewInputRateInstanceTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
2065{
2066	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
2067	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
2068	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
2069	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
2070	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
2071
2072	beginCommandBuffer(*m_device, *m_cmdBuffer);
2073
2074	beforeRenderPass();
2075
2076	if (!m_useDynamicRendering)
2077	{
2078		const VkRenderPassBeginInfo		renderPassBeginInfo =
2079		{
2080			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2081			DE_NULL,									// const void*			pNext;
2082			renderPass,									// VkRenderPass			renderPass;
2083			frameBuffer,								// VkFramebuffer		framebuffer;
2084			renderArea,									// VkRect2D				renderArea;
2085			1u,											// uint32_t				clearValueCount;
2086			&renderPassClearValue,						// const VkClearValue*	pClearValues;
2087		};
2088		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2089	}
2090
2091	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2092	{
2093		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
2094
2095#ifndef CTS_USES_VULKANSC
2096		if (m_useDynamicRendering)
2097		{
2098			addRenderingSubpassDependencyIfRequired(subpassNdx);
2099
2100			beginRendering(
2101				*m_device,
2102				*m_cmdBuffer,
2103				m_colorAttachment->getImageView(),
2104				renderArea,
2105				renderPassClearValue,
2106				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2107				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2108				0u,
2109				m_parameters.extent.depth,
2110				m_parameters.viewMasks[subpassNdx]);
2111		}
2112#endif // CTS_USES_VULKANSC
2113
2114		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2115
2116		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2117			m_device->cmdDraw(*m_cmdBuffer, 4u, 4u, 0u, 0u);
2118
2119#ifndef CTS_USES_VULKANSC
2120		if (m_useDynamicRendering)
2121			endRendering(*m_device, *m_cmdBuffer);
2122		else
2123#endif // CTS_USES_VULKANSC
2124			if (subpassNdx < subpassCount - 1u)
2125			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2126	}
2127
2128	if (!m_useDynamicRendering)
2129		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2130
2131	afterRenderPass();
2132
2133	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2134	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2135}
2136
2137class MultiViewDrawIndirectTestInstance : public MultiViewRenderTestInstance
2138{
2139public:
2140				MultiViewDrawIndirectTestInstance	(Context& context, const TestParameters& parameters);
2141protected:
2142
2143	void		draw								(const deUint32			subpassCount,
2144													 VkRenderPass			renderPass,
2145													 VkFramebuffer			frameBuffer,
2146													 vector<PipelineSp>&	pipelines);
2147};
2148
2149MultiViewDrawIndirectTestInstance::MultiViewDrawIndirectTestInstance (Context& context, const TestParameters& parameters)
2150	: MultiViewRenderTestInstance	(context, parameters)
2151{
2152}
2153
2154void MultiViewDrawIndirectTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
2155{
2156	typedef de::SharedPtr<Unique<VkBuffer> >		BufferSP;
2157	typedef de::SharedPtr<UniquePtr<Allocation> >	AllocationSP;
2158
2159	const size_t					nonCoherentAtomSize		= static_cast<size_t>(m_context.getDeviceProperties().limits.nonCoherentAtomSize);
2160	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
2161	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
2162	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
2163	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
2164	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
2165	const deUint32					strideInBuffer			= (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2166															? static_cast<deUint32>(sizeof(vk::VkDrawIndexedIndirectCommand))
2167															: static_cast<deUint32>(sizeof(vk::VkDrawIndirectCommand));
2168	vector< BufferSP >				indirectBuffers			(subpassCount);
2169	vector< AllocationSP >			indirectAllocations		(subpassCount);
2170
2171	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2172	{
2173		vector<VkDrawIndirectCommand>			drawCommands;
2174		vector<VkDrawIndexedIndirectCommand>	drawCommandsIndexed;
2175
2176		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2177		{
2178			if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2179			{
2180				const VkDrawIndexedIndirectCommand	drawCommandIndexed	=
2181				{
2182					4u,												//  deUint32	indexCount;
2183					1u,												//  deUint32	instanceCount;
2184					(drawNdx + subpassNdx % m_squareCount) * 4u,	//  deUint32	firstIndex;
2185					0u,												//  deInt32		vertexOffset;
2186					0u,												//  deUint32	firstInstance;
2187				};
2188
2189				drawCommandsIndexed.push_back(drawCommandIndexed);
2190			}
2191			else
2192			{
2193				const VkDrawIndirectCommand	drawCommand	=
2194				{
2195					4u,												//  deUint32	vertexCount;
2196					1u,												//  deUint32	instanceCount;
2197					(drawNdx + subpassNdx % m_squareCount) * 4u,	//  deUint32	firstVertex;
2198					0u												//  deUint32	firstInstance;
2199				};
2200
2201				drawCommands.push_back(drawCommand);
2202			}
2203		}
2204
2205		const size_t				drawCommandsLength	= (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2206														? drawCommandsIndexed.size()
2207														: drawCommands.size();
2208		const void*					drawCommandsDataPtr	= (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2209														? (void*)&drawCommandsIndexed[0]
2210														: (void*)&drawCommands[0];
2211		const size_t				dataSize			= static_cast<size_t>(drawCommandsLength * strideInBuffer);
2212		const VkDeviceSize			bufferDataSize		= static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
2213		const VkBufferCreateInfo	bufferInfo			= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
2214		Move<VkBuffer>				indirectBuffer		= createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
2215		MovePtr<Allocation>			allocationBuffer	= m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *indirectBuffer),  MemoryRequirement::HostVisible);
2216
2217		DE_ASSERT(drawCommandsLength != 0);
2218
2219		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *indirectBuffer, allocationBuffer->getMemory(), allocationBuffer->getOffset()));
2220
2221		deMemcpy(allocationBuffer->getHostPtr(), drawCommandsDataPtr, static_cast<size_t>(dataSize));
2222
2223		flushAlloc(*m_device, *m_logicalDevice, *allocationBuffer);
2224		indirectBuffers[subpassNdx] = (BufferSP(new Unique<VkBuffer>(indirectBuffer)));
2225		indirectAllocations[subpassNdx] = (AllocationSP(new UniquePtr<Allocation>(allocationBuffer)));
2226	}
2227
2228	beginCommandBuffer(*m_device, *m_cmdBuffer);
2229
2230	beforeRenderPass();
2231
2232	if (!m_useDynamicRendering)
2233	{
2234		const VkRenderPassBeginInfo renderPassBeginInfo
2235		{
2236			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2237			DE_NULL,									// const void*			pNext;
2238			renderPass,									// VkRenderPass			renderPass;
2239			frameBuffer,								// VkFramebuffer		framebuffer;
2240			renderArea,									// VkRect2D				renderArea;
2241			1u,											// uint32_t				clearValueCount;
2242			&renderPassClearValue,						// const VkClearValue*	pClearValues;
2243		};
2244		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2245	}
2246
2247	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2248	{
2249		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
2250
2251		if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2252			m_device->cmdBindIndexBuffer(*m_cmdBuffer, *m_vertexIndicesBuffer, 0u, VK_INDEX_TYPE_UINT32);
2253
2254#ifndef CTS_USES_VULKANSC
2255		if (m_useDynamicRendering)
2256		{
2257			addRenderingSubpassDependencyIfRequired(subpassNdx);
2258
2259			beginRendering(
2260				*m_device,
2261				*m_cmdBuffer,
2262				m_colorAttachment->getImageView(),
2263				renderArea,
2264				renderPassClearValue,
2265				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2266				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2267				0u,
2268				m_parameters.extent.depth,
2269				m_parameters.viewMasks[subpassNdx]);
2270		}
2271#endif // CTS_USES_VULKANSC
2272
2273		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2274
2275		if (m_hasMultiDrawIndirect)
2276		{
2277			if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2278				m_device->cmdDrawIndexedIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], 0u, drawCountPerSubpass, strideInBuffer);
2279			else
2280				m_device->cmdDrawIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], 0u, drawCountPerSubpass, strideInBuffer);
2281		}
2282		else
2283		{
2284			for (deUint32 drawNdx = 0; drawNdx < drawCountPerSubpass; drawNdx++)
2285			{
2286				if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2287					m_device->cmdDrawIndexedIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], drawNdx * strideInBuffer, 1, strideInBuffer);
2288				else
2289					m_device->cmdDrawIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], drawNdx * strideInBuffer, 1, strideInBuffer);
2290			}
2291		}
2292
2293#ifndef CTS_USES_VULKANSC
2294		if (m_useDynamicRendering)
2295			endRendering(*m_device, *m_cmdBuffer);
2296		else
2297#endif // CTS_USES_VULKANSC
2298			if (subpassNdx < subpassCount - 1u)
2299			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2300	}
2301
2302	if (!m_useDynamicRendering)
2303		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2304
2305	afterRenderPass();
2306
2307	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2308	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2309}
2310
2311class MultiViewClearAttachmentsTestInstance : public MultiViewRenderTestInstance
2312{
2313public:
2314				MultiViewClearAttachmentsTestInstance	(Context& context, const TestParameters& parameters);
2315protected:
2316	void		draw									(const deUint32			subpassCount,
2317														 VkRenderPass			renderPass,
2318														 VkFramebuffer			frameBuffer,
2319														 vector<PipelineSp>&	pipelines);
2320};
2321
2322MultiViewClearAttachmentsTestInstance::MultiViewClearAttachmentsTestInstance (Context& context, const TestParameters& parameters)
2323	: MultiViewRenderTestInstance	(context, parameters)
2324{
2325}
2326
2327void MultiViewClearAttachmentsTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
2328{
2329	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
2330	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
2331	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
2332	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
2333	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
2334
2335	beginCommandBuffer(*m_device, *m_cmdBuffer);
2336
2337	beforeRenderPass();
2338
2339	if (!m_useDynamicRendering)
2340	{
2341		const VkRenderPassBeginInfo renderPassBeginInfo
2342		{
2343			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2344			DE_NULL,									// const void*			pNext;
2345			renderPass,									// VkRenderPass			renderPass;
2346			frameBuffer,								// VkFramebuffer		framebuffer;
2347			renderArea,									// VkRect2D				renderArea;
2348			1u,											// uint32_t				clearValueCount;
2349			&renderPassClearValue,						// const VkClearValue*	pClearValues;
2350		};
2351		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2352	}
2353
2354	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2355	{
2356		VkClearAttachment	clearAttachment	=
2357		{
2358			VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags	aspectMask
2359			0u,														// deUint32				colorAttachment
2360			makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f))	// VkClearValue			clearValue
2361		};
2362
2363		const VkOffset2D	offset[2]		=
2364		{
2365			{0, 0},
2366			{static_cast<deInt32>(static_cast<float>(m_parameters.extent.width) * 0.25f), static_cast<deInt32>(static_cast<float>(m_parameters.extent.height) * 0.25f)}
2367		};
2368
2369		const VkExtent2D	extent[2]		=
2370		{
2371			{m_parameters.extent.width, m_parameters.extent.height},
2372			{static_cast<deUint32>(static_cast<float>(m_parameters.extent.width) * 0.5f), static_cast<deUint32>(static_cast<float>(m_parameters.extent.height) * 0.5f)}
2373		};
2374
2375		const VkRect2D		rect2D[2]		=
2376		{
2377			{offset[0], extent[0]},
2378			{offset[1], extent[1]}
2379		};
2380
2381		VkClearRect			clearRect		=
2382		{
2383			rect2D[0],	// VkRect2D	rect
2384			0u,			// deUint32	baseArrayLayer
2385			1u,			// deUint32	layerCount
2386		};
2387
2388#ifndef CTS_USES_VULKANSC
2389		if (m_useDynamicRendering)
2390		{
2391			addRenderingSubpassDependencyIfRequired(subpassNdx);
2392
2393			beginRendering(
2394				*m_device,
2395				*m_cmdBuffer,
2396				m_colorAttachment->getImageView(),
2397				renderArea,
2398				renderPassClearValue,
2399				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2400				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2401				0u,
2402				m_parameters.extent.depth,
2403				m_parameters.viewMasks[subpassNdx]);
2404		}
2405#endif // CTS_USES_VULKANSC
2406
2407		m_device->cmdClearAttachments(*m_cmdBuffer, 1u, &clearAttachment, 1u, &clearRect);
2408		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
2409		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2410
2411		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2412			m_device->cmdDraw(*m_cmdBuffer, 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u);
2413
2414		clearRect.rect = rect2D[1];
2415		clearAttachment.clearValue = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
2416		m_device->cmdClearAttachments(*m_cmdBuffer, 1u, &clearAttachment, 1u, &clearRect);
2417
2418#ifndef CTS_USES_VULKANSC
2419		if (m_useDynamicRendering)
2420			endRendering(*m_device, *m_cmdBuffer);
2421		else
2422#endif // CTS_USES_VULKANSC
2423			if (subpassNdx < subpassCount - 1u)
2424			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2425	}
2426
2427	if (!m_useDynamicRendering)
2428		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2429
2430	afterRenderPass();
2431
2432	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2433	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2434}
2435
2436class MultiViewSecondaryCommandBufferTestInstance : public MultiViewRenderTestInstance
2437{
2438public:
2439				MultiViewSecondaryCommandBufferTestInstance	(Context& context, const TestParameters& parameters);
2440protected:
2441	void		draw										(const deUint32			subpassCount,
2442															 VkRenderPass			renderPass,
2443															 VkFramebuffer			frameBuffer,
2444															 vector<PipelineSp>&	pipelines);
2445};
2446
2447MultiViewSecondaryCommandBufferTestInstance::MultiViewSecondaryCommandBufferTestInstance (Context& context, const TestParameters& parameters)
2448	: MultiViewRenderTestInstance	(context, parameters)
2449{
2450}
2451
2452void MultiViewSecondaryCommandBufferTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
2453{
2454	typedef de::SharedPtr<Unique<VkCommandBuffer> >	VkCommandBufferSp;
2455
2456	createSecondaryCommandPool();
2457
2458	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
2459	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
2460	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
2461	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
2462	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
2463
2464	beginCommandBuffer(*m_device, *m_cmdBuffer);
2465
2466	beforeRenderPass();
2467
2468	const VkRenderPassBeginInfo renderPassBeginInfo
2469	{
2470		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2471		DE_NULL,									// const void*			pNext;
2472		renderPass,									// VkRenderPass			renderPass;
2473		frameBuffer,								// VkFramebuffer		framebuffer;
2474		renderArea,									// VkRect2D				renderArea;
2475		1u,											// uint32_t				clearValueCount;
2476		&renderPassClearValue,						// const VkClearValue*	pClearValues;
2477	};
2478	if (!m_useDynamicRendering)
2479		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, m_parameters.renderingType);
2480
2481	//Create secondary buffer
2482	const VkCommandBufferAllocateInfo	cmdBufferAllocateInfo	=
2483	{
2484		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
2485		DE_NULL,										// const void*				pNext;
2486		*m_cmdPoolSecondary,							// VkCommandPool			commandPool;
2487		VK_COMMAND_BUFFER_LEVEL_SECONDARY,				// VkCommandBufferLevel		level;
2488		1u,												// deUint32					bufferCount;
2489	};
2490	vector<VkCommandBufferSp>	cmdBufferSecondary;
2491
2492	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2493	{
2494		cmdBufferSecondary.push_back(VkCommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(*m_device, *m_logicalDevice, &cmdBufferAllocateInfo))));
2495
2496#ifndef CTS_USES_VULKANSC
2497		const VkCommandBufferInheritanceRenderingInfoKHR secCmdBufInheritRenderingInfo
2498		{
2499			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,	// VkStructureType							sType;
2500			DE_NULL,															// const void*								pNext;
2501			0u,																	// VkRenderingFlagsKHR						flags;
2502			m_parameters.viewMasks[subpassNdx],									// uint32_t									viewMask;
2503			1u,																	// uint32_t									colorAttachmentCount;
2504			&m_parameters.colorFormat,											// const VkFormat*							pColorAttachmentFormats;
2505			VK_FORMAT_UNDEFINED,												// VkFormat									depthAttachmentFormat;
2506			VK_FORMAT_UNDEFINED,												// VkFormat									stencilAttachmentFormat;
2507			m_parameters.samples												// VkSampleCountFlagBits					rasterizationSamples;
2508		};
2509#endif // CTS_USES_VULKANSC
2510
2511		const VkCommandBufferInheritanceInfo secCmdBufInheritInfo
2512		{
2513			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,					// VkStructureType							sType;
2514#ifndef CTS_USES_VULKANSC
2515			m_useDynamicRendering ? &secCmdBufInheritRenderingInfo : DE_NULL,	// const void*								pNext;
2516#else
2517			DE_NULL,															// const void*								pNext;
2518#endif // CTS_USES_VULKANSC
2519			renderPass,															// VkRenderPass								renderPass;
2520			subpassNdx,															// deUint32									subpass;
2521			frameBuffer,														// VkFramebuffer							framebuffer;
2522			VK_FALSE,															// VkBool32									occlusionQueryEnable;
2523			(VkQueryControlFlags)0u,											// VkQueryControlFlags						queryFlags;
2524			(VkQueryPipelineStatisticFlags)0u,									// VkQueryPipelineStatisticFlags			pipelineStatistics;
2525		};
2526
2527		const VkCommandBufferBeginInfo info
2528		{
2529			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,						// VkStructureType							sType;
2530			DE_NULL,															// const void*								pNext;
2531			VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,					// VkCommandBufferUsageFlags				flags;
2532			&secCmdBufInheritInfo,												// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
2533		};
2534
2535		VK_CHECK(m_device->beginCommandBuffer(cmdBufferSecondary.back().get()->get(), &info));
2536
2537		m_device->cmdBindVertexBuffers(cmdBufferSecondary.back().get()->get(), 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
2538		m_device->cmdBindPipeline(cmdBufferSecondary.back().get()->get(), VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2539
2540#ifndef CTS_USES_VULKANSC
2541		if (m_useDynamicRendering)
2542		{
2543			addRenderingSubpassDependencyIfRequired(subpassNdx);
2544
2545			beginRendering(
2546				*m_device,
2547				*m_cmdBuffer,
2548				m_colorAttachment->getImageView(),
2549				renderArea,
2550				renderPassClearValue,
2551				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2552				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2553				VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR,
2554				m_parameters.extent.depth,
2555				m_parameters.viewMasks[subpassNdx]);
2556		}
2557#endif // CTS_USES_VULKANSC
2558
2559		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2560			m_device->cmdDraw(cmdBufferSecondary.back().get()->get(), 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u);
2561
2562		VK_CHECK(m_device->endCommandBuffer(cmdBufferSecondary.back().get()->get()));
2563
2564		m_device->cmdExecuteCommands(*m_cmdBuffer, 1u, &cmdBufferSecondary.back().get()->get());
2565#ifndef CTS_USES_VULKANSC
2566		if (m_useDynamicRendering)
2567			endRendering(*m_device, *m_cmdBuffer);
2568		else
2569#endif // CTS_USES_VULKANSC
2570			if (subpassNdx < subpassCount - 1u)
2571			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, m_parameters.renderingType);
2572	}
2573
2574	if (!m_useDynamicRendering)
2575		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2576
2577	afterRenderPass();
2578
2579	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2580	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2581}
2582
2583class MultiViewPointSizeTestInstance : public MultiViewRenderTestInstance
2584{
2585public:
2586				MultiViewPointSizeTestInstance	(Context& context, const TestParameters& parameters);
2587protected:
2588	void		validatePointSize				(const VkPhysicalDeviceLimits& limits, const deUint32 pointSize);
2589	void		createVertexData				(void);
2590	void		draw							(const deUint32			subpassCount,
2591												 VkRenderPass			renderPass,
2592												 VkFramebuffer			frameBuffer,
2593												 vector<PipelineSp>&	pipelines);
2594};
2595
2596MultiViewPointSizeTestInstance::MultiViewPointSizeTestInstance (Context& context, const TestParameters& parameters)
2597	: MultiViewRenderTestInstance	(context, parameters)
2598{
2599	const auto&						vki					= m_context.getInstanceInterface();
2600	const auto						physDevice			= m_context.getPhysicalDevice();
2601	const VkPhysicalDeviceLimits	limits				= getPhysicalDeviceProperties(vki, physDevice).limits;
2602
2603	validatePointSize(limits, static_cast<deUint32>(TEST_POINT_SIZE_WIDE));
2604	validatePointSize(limits, static_cast<deUint32>(TEST_POINT_SIZE_SMALL));
2605}
2606
2607void MultiViewPointSizeTestInstance::validatePointSize (const VkPhysicalDeviceLimits& limits, const deUint32 pointSize)
2608{
2609	const float	testPointSizeFloat	= static_cast<float>(pointSize);
2610	float		granuleCount		= 0.0f;
2611
2612	if (!de::inRange(testPointSizeFloat, limits.pointSizeRange[0], limits.pointSizeRange[1]))
2613		TCU_THROW(NotSupportedError, "Required point size is outside of the the limits range");
2614
2615	granuleCount = static_cast<float>(deCeilFloatToInt32((testPointSizeFloat - limits.pointSizeRange[0]) / limits.pointSizeGranularity));
2616
2617	if (limits.pointSizeRange[0] + granuleCount * limits.pointSizeGranularity != testPointSizeFloat)
2618		TCU_THROW(NotSupportedError, "Granuliraty does not allow to get required point size");
2619
2620	DE_ASSERT(pointSize + 1 <= m_parameters.extent.width / 2);
2621	DE_ASSERT(pointSize + 1 <= m_parameters.extent.height / 2);
2622}
2623
2624void MultiViewPointSizeTestInstance::createVertexData (void)
2625{
2626	const float		pixelStepX	= 2.0f / static_cast<float>(m_parameters.extent.width);
2627	const float		pixelStepY	= 2.0f / static_cast<float>(m_parameters.extent.height);
2628	const int		pointMargin	= 1 + TEST_POINT_SIZE_WIDE / 2;
2629
2630	appendVertex(tcu::Vec4(-1.0f + pointMargin * pixelStepX,-1.0f + pointMargin * pixelStepY, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
2631	appendVertex(tcu::Vec4(-1.0f + pointMargin * pixelStepX, 0.0f + pointMargin * pixelStepY, 1.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
2632	appendVertex(tcu::Vec4( 0.0f + pointMargin * pixelStepX,-1.0f + pointMargin * pixelStepY, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
2633	appendVertex(tcu::Vec4( 0.0f + pointMargin * pixelStepX, 0.0f + pointMargin * pixelStepY, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.5f, 0.3f, 1.0f));
2634}
2635
2636void MultiViewPointSizeTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
2637{
2638	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
2639	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
2640	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
2641	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
2642	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
2643
2644	beginCommandBuffer(*m_device, *m_cmdBuffer);
2645
2646	beforeRenderPass();
2647
2648	if (!m_useDynamicRendering)
2649	{
2650		const VkRenderPassBeginInfo renderPassBeginInfo
2651		{
2652			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2653			DE_NULL,									// const void*			pNext;
2654			renderPass,									// VkRenderPass			renderPass;
2655			frameBuffer,								// VkFramebuffer		framebuffer;
2656			renderArea,									// VkRect2D				renderArea;
2657			1u,											// uint32_t				clearValueCount;
2658			&renderPassClearValue,						// const VkClearValue*	pClearValues;
2659		};
2660		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2661	}
2662
2663	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2664	{
2665		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
2666
2667		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2668
2669#ifndef CTS_USES_VULKANSC
2670		if (m_useDynamicRendering)
2671		{
2672			addRenderingSubpassDependencyIfRequired(subpassNdx);
2673
2674			beginRendering(
2675				*m_device,
2676				*m_cmdBuffer,
2677				m_colorAttachment->getImageView(),
2678				renderArea,
2679				renderPassClearValue,
2680				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2681				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2682				0u,
2683				m_parameters.extent.depth,
2684				m_parameters.viewMasks[subpassNdx]);
2685		}
2686#endif // CTS_USES_VULKANSC
2687
2688		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2689			m_device->cmdDraw(*m_cmdBuffer, 1u, 1u, drawNdx + subpassNdx % m_squareCount, 0u);
2690
2691#ifndef CTS_USES_VULKANSC
2692		if (m_useDynamicRendering)
2693			endRendering(*m_device, *m_cmdBuffer);
2694		else
2695#endif // CTS_USES_VULKANSC
2696			if (subpassNdx < subpassCount - 1u)
2697			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2698	}
2699
2700	if (!m_useDynamicRendering)
2701		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2702
2703	afterRenderPass();
2704
2705	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2706	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2707}
2708
2709class MultiViewMultsampleTestInstance : public MultiViewRenderTestInstance
2710{
2711public:
2712					MultiViewMultsampleTestInstance	(Context& context, const TestParameters& parameters);
2713protected:
2714	tcu::TestStatus	iterate							(void);
2715	void			createVertexData				(void);
2716
2717	void			draw							(const deUint32			subpassCount,
2718													 VkRenderPass			renderPass,
2719													 VkFramebuffer			frameBuffer,
2720													 vector<PipelineSp>&	pipelines);
2721	void			afterRenderPass					(void);
2722private:
2723	de::SharedPtr<ImageAttachment>	m_resolveAttachment;
2724};
2725
2726MultiViewMultsampleTestInstance::MultiViewMultsampleTestInstance (Context& context, const TestParameters& parameters)
2727	: MultiViewRenderTestInstance	(context, parameters)
2728{
2729	// Color attachment
2730	m_resolveAttachment = de::SharedPtr<ImageAttachment>(new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat, VK_SAMPLE_COUNT_1_BIT));
2731}
2732
2733tcu::TestStatus MultiViewMultsampleTestInstance::iterate (void)
2734{
2735	const deUint32								subpassCount				= static_cast<deUint32>(m_parameters.viewMasks.size());
2736	Move<VkRenderPass>							renderPass;
2737	Move<VkFramebuffer>							frameBuffer;
2738
2739	// FrameBuffer & renderPass
2740	if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
2741	{
2742		renderPass	= makeRenderPass (*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_parameters.renderingType, VK_SAMPLE_COUNT_4_BIT);
2743		frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(), m_parameters.extent.width, m_parameters.extent.height);
2744	}
2745
2746	// pipelineLayout
2747	Unique<VkPipelineLayout>					pipelineLayout				(makePipelineLayout(*m_device, *m_logicalDevice));
2748
2749	// pipelines
2750	map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
2751	vector<PipelineSp>							pipelines(subpassCount);
2752	const VkVertexInputRate						vertexInputRate				= (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2753
2754	{
2755		vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
2756		madeShaderModule(shaderModule, shaderStageParams);
2757		for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
2758			pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<deUint32>(shaderStageParams.size()), shaderStageParams.data(), subpassNdx, vertexInputRate))));
2759	}
2760
2761	createCommandBuffer();
2762	createVertexData();
2763	createVertexBuffer();
2764
2765	draw(subpassCount, *renderPass, *frameBuffer, pipelines);
2766
2767	{
2768		vector<deUint8>			pixelAccessData	(m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth * mapVkFormat(m_parameters.colorFormat).getPixelSize());
2769		tcu::PixelBufferAccess	dst				(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
2770
2771		readImage(m_resolveAttachment->getImage(), dst);
2772
2773		if (!checkImage(dst))
2774			return tcu::TestStatus::fail("Fail");
2775	}
2776
2777	return tcu::TestStatus::pass("Pass");
2778}
2779
2780void MultiViewMultsampleTestInstance::createVertexData (void)
2781{
2782	tcu::Vec4	color	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2783
2784	color	= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2785	appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
2786	appendVertex(tcu::Vec4(-1.0f,-1.0f, 1.0f, 1.0f), color);
2787	appendVertex(tcu::Vec4( 0.0f,-1.0f, 1.0f, 1.0f), color);
2788
2789	color	= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2790	appendVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), color);
2791	appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
2792	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
2793
2794	color	= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2795	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
2796	appendVertex(tcu::Vec4( 0.0f,-1.0f, 1.0f, 1.0f), color);
2797	appendVertex(tcu::Vec4( 1.0f,-1.0f, 1.0f, 1.0f), color);
2798
2799	color	= tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
2800	appendVertex(tcu::Vec4( 0.0f, 1.0f, 1.0f, 1.0f), color);
2801	appendVertex(tcu::Vec4( 0.0f, 0.0f, 1.0f, 1.0f), color);
2802	appendVertex(tcu::Vec4( 1.0f, 0.0f, 1.0f, 1.0f), color);
2803}
2804
2805void MultiViewMultsampleTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
2806{
2807	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
2808	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
2809	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
2810	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
2811	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
2812	const deUint32					vertexPerPrimitive		= 3u;
2813	const VkImageSubresourceLayers	subresourceLayer		=
2814	{
2815		VK_IMAGE_ASPECT_COLOR_BIT,	//  VkImageAspectFlags	aspectMask;
2816		0u,							//  deUint32			mipLevel;
2817		0u,							//  deUint32			baseArrayLayer;
2818		m_parameters.extent.depth,	//  deUint32			layerCount;
2819	};
2820	const VkImageResolve			imageResolveRegion		=
2821	{
2822		subresourceLayer,															//  VkImageSubresourceLayers	srcSubresource;
2823		makeOffset3D(0, 0, 0),														//  VkOffset3D					srcOffset;
2824		subresourceLayer,															//  VkImageSubresourceLayers	dstSubresource;
2825		makeOffset3D(0, 0, 0),														//  VkOffset3D					dstOffset;
2826		makeExtent3D(m_parameters.extent.width, m_parameters.extent.height, 1u),	//  VkExtent3D					extent;
2827	};
2828
2829	beginCommandBuffer(*m_device, *m_cmdBuffer);
2830
2831	beforeRenderPass();
2832
2833	if (!m_useDynamicRendering)
2834	{
2835		const VkRenderPassBeginInfo renderPassBeginInfo
2836		{
2837			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
2838			DE_NULL,									// const void*			pNext;
2839			renderPass,									// VkRenderPass			renderPass;
2840			frameBuffer,								// VkFramebuffer		framebuffer;
2841			renderArea,									// VkRect2D				renderArea;
2842			1u,											// uint32_t				clearValueCount;
2843			&renderPassClearValue,						// const VkClearValue*	pClearValues;
2844		};
2845		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2846	}
2847
2848	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2849	{
2850		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
2851
2852		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2853
2854#ifndef CTS_USES_VULKANSC
2855		if (m_useDynamicRendering)
2856		{
2857			addRenderingSubpassDependencyIfRequired(subpassNdx);
2858
2859			beginRendering(
2860				*m_device,
2861				*m_cmdBuffer,
2862				m_colorAttachment->getImageView(),
2863				renderArea,
2864				renderPassClearValue,
2865				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2866				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2867				0u,
2868				m_parameters.extent.depth,
2869				m_parameters.viewMasks[subpassNdx]);
2870		}
2871#endif // CTS_USES_VULKANSC
2872
2873		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2874			m_device->cmdDraw(*m_cmdBuffer, vertexPerPrimitive, 1u, (drawNdx + subpassNdx % m_squareCount) * vertexPerPrimitive, 0u);
2875
2876#ifndef CTS_USES_VULKANSC
2877		if (m_useDynamicRendering)
2878			endRendering(*m_device, *m_cmdBuffer);
2879		else
2880#endif // CTS_USES_VULKANSC
2881			if (subpassNdx < subpassCount - 1u)
2882			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2883	}
2884
2885	if (!m_useDynamicRendering)
2886		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2887
2888	afterRenderPass();
2889
2890	m_device->cmdResolveImage(*m_cmdBuffer, m_colorAttachment->getImage(), VK_IMAGE_LAYOUT_GENERAL, m_resolveAttachment->getImage(), VK_IMAGE_LAYOUT_GENERAL, 1u, &imageResolveRegion);
2891
2892	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2893	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2894}
2895
2896void MultiViewMultsampleTestInstance::afterRenderPass (void)
2897{
2898	const VkImageSubresourceRange	subresourceRange		=
2899	{
2900		VK_IMAGE_ASPECT_COLOR_BIT,	//  VkImageAspectFlags	aspectMask;
2901		0u,							//  deUint32			baseMipLevel;
2902		1u,							//  deUint32			levelCount;
2903		0u,							//  deUint32			baseArrayLayer;
2904		m_parameters.extent.depth,	//  deUint32			layerCount;
2905	};
2906
2907	imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
2908		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2909		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2910		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
2911
2912	imageBarrier(*m_device, *m_cmdBuffer, m_resolveAttachment->getImage(), subresourceRange,
2913		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2914		0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2915		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
2916}
2917
2918class MultiViewQueriesTestInstance : public MultiViewRenderTestInstance
2919{
2920public:
2921						MultiViewQueriesTestInstance	(Context& context, const TestParameters& parameters);
2922protected:
2923	tcu::TestStatus		iterate							(void);
2924	void				createVertexData				(void);
2925
2926	void				draw							(const deUint32			subpassCount,
2927														 VkRenderPass			renderPass,
2928														 VkFramebuffer			frameBuffer,
2929														 vector<PipelineSp>&	pipelines);
2930	deUint32			getUsedViewsCount				(const deUint32			viewMaskIndex);
2931	deUint32			getQueryCountersNumber			();
2932private:
2933	const deUint32				m_verticesPerPrimitive;
2934	const VkQueryControlFlags	m_occlusionQueryFlags;
2935	deUint64					m_timestampMask;
2936	vector<deUint64>			m_timestampStartValues;
2937	vector<deUint64>			m_timestampEndValues;
2938	vector<uint64_t>			m_timestampStartAvailabilityValues;
2939	vector<uint64_t>			m_timestampEndAvailabilityValues;
2940	vector<deBool>				m_counterSeriesStart;
2941	vector<deBool>				m_counterSeriesEnd;
2942	vector<deUint64>			m_occlusionValues;
2943	vector<deUint64>			m_occlusionExpectedValues;
2944	vector<uint64_t>			m_occlusionAvailabilityValues;
2945	deUint32					m_occlusionObjectsOffset;
2946	vector<deUint64>			m_occlusionObjectPixelsCount;
2947};
2948
2949MultiViewQueriesTestInstance::MultiViewQueriesTestInstance (Context& context, const TestParameters& parameters)
2950	: MultiViewRenderTestInstance	(context, parameters)
2951	, m_verticesPerPrimitive		(4u)
2952	, m_occlusionQueryFlags			((parameters.viewIndex == TEST_TYPE_QUERIES) * VK_QUERY_CONTROL_PRECISE_BIT)
2953	, m_occlusionObjectsOffset		(0)
2954{
2955	// Generate the timestamp mask
2956	const auto&	vki				= m_context.getInstanceInterface();
2957	const auto	physicalDevice	= m_context.getPhysicalDevice();
2958
2959	const std::vector<VkQueueFamilyProperties>	queueProperties	= vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
2960
2961	if(queueProperties[0].timestampValidBits == 0)
2962		TCU_THROW(NotSupportedError, "Device does not support timestamp.");
2963
2964	m_timestampMask = 0xFFFFFFFFFFFFFFFFull >> (64 - queueProperties[0].timestampValidBits);
2965}
2966
2967void verifyAvailabilityBits (const std::vector<uint64_t>& bits, const char* setName)
2968{
2969	constexpr auto invalidValue = uint64_t{0};
2970	for (size_t i = 0u; i < bits.size(); ++i)
2971	{
2972		if (bits[i] == invalidValue)
2973			TCU_FAIL(setName + std::string(" availability bit ") + de::toString(i) + " is " + de::toString(invalidValue));
2974	}
2975}
2976
2977tcu::TestStatus MultiViewQueriesTestInstance::iterate (void)
2978{
2979	const deUint32								subpassCount			= static_cast<deUint32>(m_parameters.viewMasks.size());
2980	Move<VkRenderPass>							renderPass;
2981	Move<VkFramebuffer>							frameBuffer;
2982	Unique<VkPipelineLayout>					pipelineLayout			(makePipelineLayout(*m_device, *m_logicalDevice));
2983	vector<PipelineSp>							pipelines				(subpassCount);
2984	deUint64									occlusionValue			= 0;
2985	deUint64									occlusionExpectedValue	= 0;
2986	map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
2987
2988	if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
2989	{
2990		renderPass	= makeRenderPass (*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_parameters.renderingType);
2991		frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(), m_parameters.extent.width, m_parameters.extent.height);
2992	}
2993
2994	{
2995		vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
2996
2997		madeShaderModule(shaderModule, shaderStageParams);
2998		for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
2999			pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<deUint32>(shaderStageParams.size()), shaderStageParams.data(), subpassNdx))));
3000	}
3001
3002	createCommandBuffer();
3003	createVertexData();
3004	createVertexBuffer();
3005
3006	draw(subpassCount, *renderPass, *frameBuffer, pipelines);
3007
3008	DE_ASSERT(!m_occlusionValues.empty());
3009	DE_ASSERT(m_occlusionValues.size() == m_occlusionExpectedValues.size());
3010	DE_ASSERT(m_occlusionValues.size() == m_counterSeriesEnd.size());
3011	for (size_t ndx = 0; ndx < m_counterSeriesEnd.size(); ++ndx)
3012	{
3013		occlusionValue			+= m_occlusionValues[ndx];
3014		occlusionExpectedValue	+= m_occlusionExpectedValues[ndx];
3015
3016		if (m_counterSeriesEnd[ndx])
3017		{
3018			if (m_parameters.viewIndex == TEST_TYPE_QUERIES)
3019			{
3020				if (occlusionExpectedValue != occlusionValue)
3021					return tcu::TestStatus::fail("occlusion, result:" + de::toString(occlusionValue) + ", expected:" + de::toString(occlusionExpectedValue));
3022			}
3023			else // verify non precise occlusion query
3024			{
3025				if (occlusionValue == 0)
3026					return tcu::TestStatus::fail("occlusion, result: 0, expected non zero value");
3027			}
3028		}
3029	}
3030	verifyAvailabilityBits(m_occlusionAvailabilityValues, "occlusion");
3031
3032	DE_ASSERT(!m_timestampStartValues.empty());
3033	DE_ASSERT(m_timestampStartValues.size() == m_timestampEndValues.size());
3034	DE_ASSERT(m_timestampStartValues.size() == m_counterSeriesStart.size());
3035	for (size_t ndx = 0; ndx < m_timestampStartValues.size(); ++ndx)
3036	{
3037		if (m_counterSeriesStart[ndx])
3038		{
3039			if (m_timestampEndValues[ndx] > 0 && m_timestampEndValues[ndx] >= m_timestampStartValues[ndx])
3040				continue;
3041		}
3042		else
3043		{
3044			if (m_timestampEndValues[ndx] > 0 && m_timestampEndValues[ndx] >= m_timestampStartValues[ndx])
3045				continue;
3046
3047			if (m_timestampEndValues[ndx] == 0 && m_timestampStartValues[ndx] == 0)
3048				continue;
3049		}
3050
3051		return tcu::TestStatus::fail("timestamp");
3052	}
3053	verifyAvailabilityBits(m_timestampStartAvailabilityValues, "timestamp start");
3054	verifyAvailabilityBits(m_timestampEndAvailabilityValues, "timestamp end");
3055
3056	return tcu::TestStatus::pass("Pass");
3057}
3058
3059void MultiViewQueriesTestInstance::createVertexData (void)
3060{
3061	tcu::Vec4 color = tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f);
3062
3063	appendVertex(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), color);
3064	appendVertex(tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f), color);
3065	appendVertex(tcu::Vec4( 0.0f,-1.0f, 0.0f, 1.0f), color);
3066	appendVertex(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), color);
3067
3068	color = tcu::Vec4(0.3f, 0.0f, 0.2f, 1.0f);
3069	appendVertex(tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f), color);
3070	appendVertex(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), color);
3071	appendVertex(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), color);
3072	appendVertex(tcu::Vec4( 0.0f, 1.0f, 0.0f, 1.0f), color);
3073
3074	color = tcu::Vec4(0.4f, 0.2f, 0.3f, 1.0f);
3075	appendVertex(tcu::Vec4( 0.0f,-1.0f, 0.0f, 1.0f), color);
3076	appendVertex(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), color);
3077	appendVertex(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), color);
3078	appendVertex(tcu::Vec4( 1.0f, 0.0f, 0.0f, 1.0f), color);
3079
3080	color = tcu::Vec4(0.5f, 0.0f, 0.4f, 1.0f);
3081	appendVertex(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), color);
3082	appendVertex(tcu::Vec4( 0.0f, 1.0f, 0.0f, 1.0f), color);
3083	appendVertex(tcu::Vec4( 1.0f, 0.0f, 0.0f, 1.0f), color);
3084	appendVertex(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), color);
3085
3086	// Create occluded square objects as zoom out of main
3087	const deUint32	mainObjectsVerticesCount		= static_cast<deUint32>(m_vertexCoord.size());
3088	const deUint32	mainObjectsCount				= mainObjectsVerticesCount / m_verticesPerPrimitive;
3089	const deUint32	occlusionObjectMultiplierX[]	= { 1, 2, 2, 1 };
3090	const deUint32	occlusionObjectMultiplierY[]	= { 1, 1, 3, 3 };
3091	const deUint32	occlusionObjectDivisor			= 4u;
3092	const float		occlusionObjectDivisorFloat		= static_cast<float>(occlusionObjectDivisor);
3093
3094	DE_ASSERT(0 == m_parameters.extent.width  % (2 * occlusionObjectDivisor));
3095	DE_ASSERT(0 == m_parameters.extent.height % (2 * occlusionObjectDivisor));
3096	DE_ASSERT(DE_LENGTH_OF_ARRAY(occlusionObjectMultiplierX) == mainObjectsCount);
3097	DE_ASSERT(DE_LENGTH_OF_ARRAY(occlusionObjectMultiplierY) == mainObjectsCount);
3098
3099	for (size_t objectNdx = 0; objectNdx < mainObjectsCount; ++objectNdx)
3100	{
3101		const size_t	objectStart			= objectNdx * m_verticesPerPrimitive;
3102		const float		xRatio				= static_cast<float>(occlusionObjectMultiplierX[objectNdx]) / occlusionObjectDivisorFloat;
3103		const float		yRatio				= static_cast<float>(occlusionObjectMultiplierY[objectNdx]) / occlusionObjectDivisorFloat;
3104		const double	areaRatio			= static_cast<double>(xRatio) * static_cast<double>(yRatio);
3105		const deUint64	occludedPixelsCount	= static_cast<deUint64>(areaRatio * (m_parameters.extent.width / 2) * (m_parameters.extent.height / 2));
3106
3107		m_occlusionObjectPixelsCount.push_back(occludedPixelsCount);
3108
3109		for (size_t vertexNdx = 0; vertexNdx < m_verticesPerPrimitive; ++vertexNdx)
3110		{
3111			const float		occludedObjectVertexXCoord	= m_vertexCoord[objectStart + vertexNdx][0] * xRatio;
3112			const float		occludedObjectVertexYCoord	= m_vertexCoord[objectStart + vertexNdx][1] * yRatio;
3113			const tcu::Vec4	occludedObjectVertexCoord	= tcu::Vec4(occludedObjectVertexXCoord, occludedObjectVertexYCoord, 1.0f, 1.0f);
3114
3115			appendVertex(occludedObjectVertexCoord, m_vertexColor[objectStart + vertexNdx]);
3116		}
3117	}
3118
3119	m_occlusionObjectsOffset = mainObjectsVerticesCount;
3120}
3121
3122// Extract single values or pairs of consecutive values from src and store them in dst1 and dst2.
3123// If ds2 is not null, src is processed as containing pairs of values.
3124// The first value will be stored in ds1 and the second one in dst2.
3125void unpackValues (const std::vector<uint64_t>& src, std::vector<uint64_t>* dst1, std::vector<uint64_t>* dst2)
3126{
3127	if (!dst2)
3128	{
3129		std::copy(begin(src), end(src), begin(*dst1));
3130		return;
3131	}
3132
3133	constexpr size_t sz0 = 0;
3134	constexpr size_t sz1 = 1;
3135	constexpr size_t sz2 = 2;
3136
3137	DE_UNREF(sz0); // For release builds.
3138	DE_ASSERT(src.size() % sz2 == sz0);
3139
3140	for (size_t i = 0; i < src.size(); i += sz2)
3141	{
3142		const auto j = i / sz2;
3143		dst1->at(j) = src.at(i);
3144		dst2->at(j) = src.at(i + sz1);
3145	}
3146}
3147
3148void MultiViewQueriesTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
3149{
3150	const VkRect2D				renderArea						= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
3151	const VkClearValue			renderPassClearValue			= makeClearValueColor(tcu::Vec4(0.0f));
3152	const VkBuffer				vertexBuffers[]					= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
3153	const VkDeviceSize			vertexBufferOffsets[]			= {                   0u,                   0u };
3154	const deUint32				drawCountPerSubpass				= (subpassCount == 1) ? m_squareCount : 1u;
3155	const deUint32				queryCountersNumber				= (subpassCount == 1) ? m_squareCount * getUsedViewsCount(0) : getQueryCountersNumber();
3156
3157	const VkQueryPoolCreateInfo	occlusionQueryPoolCreateInfo	=
3158	{
3159		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	//  VkStructureType					sType;
3160		DE_NULL,									//  const void*						pNext;
3161		(VkQueryPoolCreateFlags)0,					//  VkQueryPoolCreateFlags			flags;
3162		VK_QUERY_TYPE_OCCLUSION,					//  VkQueryType						queryType;
3163		queryCountersNumber,						//  deUint32						queryCount;
3164		0u,											//  VkQueryPipelineStatisticFlags	pipelineStatistics;
3165	};
3166	const VkQueryPoolCreateInfo	timestampQueryPoolCreateInfo	=
3167	{
3168		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	//  VkStructureType					sType;
3169		DE_NULL,									//  const void*						pNext;
3170		(VkQueryPoolCreateFlags)0,					//  VkQueryPoolCreateFlags			flags;
3171		VK_QUERY_TYPE_TIMESTAMP,					//  VkQueryType						queryType;
3172		queryCountersNumber,						//  deUint32						queryCount;
3173		0u,											//  VkQueryPipelineStatisticFlags	pipelineStatistics;
3174	};
3175	const Unique<VkQueryPool>	occlusionQueryPool				(createQueryPool(*m_device, *m_logicalDevice, &occlusionQueryPoolCreateInfo));
3176	const Unique<VkQueryPool>	timestampStartQueryPool			(createQueryPool(*m_device, *m_logicalDevice, &timestampQueryPoolCreateInfo));
3177	const Unique<VkQueryPool>	timestampEndQueryPool			(createQueryPool(*m_device, *m_logicalDevice, &timestampQueryPoolCreateInfo));
3178	deUint32					queryStartIndex					= 0;
3179
3180	const bool					withAvailability				= (m_parameters.viewIndex == TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY);
3181	const uint32_t				valuesPerQuery					= (withAvailability ? 2u : 1u);
3182	const uint32_t				valuesNumber					= queryCountersNumber * valuesPerQuery;
3183	const auto					queryStride						= static_cast<VkDeviceSize>(sizeof(uint64_t) * valuesPerQuery);
3184	const auto					extraFlag						= (withAvailability ? VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : static_cast<VkQueryResultFlagBits>(0));
3185	const auto					queryFlags						= (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT | extraFlag);
3186
3187	vk::BufferWithMemory		queryBuffer						(m_context.getDeviceInterface(), *m_logicalDevice, *m_allocator, makeBufferCreateInfo(valuesNumber * sizeof(uint64_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible);
3188
3189	beginCommandBuffer(*m_device, *m_cmdBuffer);
3190
3191	beforeRenderPass();
3192
3193	// Query pools must be reset before use
3194	m_device->cmdResetQueryPool(*m_cmdBuffer, *occlusionQueryPool, queryStartIndex, queryCountersNumber);
3195	m_device->cmdResetQueryPool(*m_cmdBuffer, *timestampStartQueryPool, queryStartIndex, queryCountersNumber);
3196	m_device->cmdResetQueryPool(*m_cmdBuffer, *timestampEndQueryPool, queryStartIndex, queryCountersNumber);
3197
3198	if (!m_useDynamicRendering)
3199	{
3200		const VkRenderPassBeginInfo	renderPassBeginInfo
3201		{
3202			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	//  VkStructureType		sType;
3203			DE_NULL,									//  const void*			pNext;
3204			renderPass,									//  VkRenderPass		renderPass;
3205			frameBuffer,								//  VkFramebuffer		framebuffer;
3206			renderArea,									//  VkRect2D			renderArea;
3207			1u,											//  uint32_t			clearValueCount;
3208			&renderPassClearValue,						//  const VkClearValue*	pClearValues;
3209		};
3210		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
3211	}
3212
3213	m_occlusionExpectedValues.reserve(queryCountersNumber);
3214	m_counterSeriesStart.reserve(queryCountersNumber);
3215	m_counterSeriesEnd.reserve(queryCountersNumber);
3216
3217	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
3218	{
3219		deUint32	queryCountersToUse	= getUsedViewsCount(subpassNdx);
3220
3221		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
3222		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
3223
3224#ifndef CTS_USES_VULKANSC
3225		if (m_useDynamicRendering)
3226		{
3227			addRenderingSubpassDependencyIfRequired(subpassNdx);
3228
3229			beginRendering(
3230				*m_device,
3231				*m_cmdBuffer,
3232				m_colorAttachment->getImageView(),
3233				renderArea,
3234				renderPassClearValue,
3235				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3236				(subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
3237				0u,
3238				m_parameters.extent.depth,
3239				m_parameters.viewMasks[subpassNdx]);
3240		}
3241#endif // CTS_USES_VULKANSC
3242
3243		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
3244		{
3245			const deUint32 primitiveNumber	= drawNdx + subpassNdx % m_squareCount;
3246			const deUint32 firstVertex		= primitiveNumber * m_verticesPerPrimitive;
3247
3248			m_device->cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, *timestampStartQueryPool, queryStartIndex);
3249			{
3250				m_device->cmdDraw(*m_cmdBuffer, m_verticesPerPrimitive, 1u, firstVertex, 0u);
3251
3252				// Render occluded object
3253				m_device->cmdBeginQuery(*m_cmdBuffer, *occlusionQueryPool, queryStartIndex, m_occlusionQueryFlags);
3254				m_device->cmdDraw(*m_cmdBuffer, m_verticesPerPrimitive, 1u, m_occlusionObjectsOffset + firstVertex, 0u);
3255				m_device->cmdEndQuery(*m_cmdBuffer, *occlusionQueryPool, queryStartIndex);
3256
3257				for (deUint32 viewMaskNdx = 0; viewMaskNdx < queryCountersToUse; ++viewMaskNdx)
3258				{
3259					m_occlusionExpectedValues.push_back(m_occlusionObjectPixelsCount[primitiveNumber]);
3260					m_counterSeriesStart.push_back(viewMaskNdx == 0);
3261					m_counterSeriesEnd.push_back(viewMaskNdx + 1 == queryCountersToUse);
3262				}
3263			}
3264			m_device->cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, *timestampEndQueryPool, queryStartIndex);
3265
3266			queryStartIndex += queryCountersToUse;
3267		}
3268
3269#ifndef CTS_USES_VULKANSC
3270		if (m_useDynamicRendering)
3271			endRendering(*m_device, *m_cmdBuffer);
3272		else
3273#endif // CTS_USES_VULKANSC
3274			if (subpassNdx < subpassCount - 1u)
3275			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
3276	}
3277
3278	DE_ASSERT(queryStartIndex == queryCountersNumber);
3279
3280	if (!m_useDynamicRendering)
3281		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
3282
3283	afterRenderPass();
3284
3285	if (m_cmdCopyQueryPoolResults)
3286		m_device->cmdCopyQueryPoolResults(*m_cmdBuffer, *occlusionQueryPool, 0u, queryCountersNumber, *queryBuffer, 0u, queryStride, queryFlags);
3287
3288	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3289	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3290
3291	// These vectors will temporarily hold results.
3292	std::vector<uint64_t>	occlusionQueryResultsBuffer			(valuesNumber, 0u);
3293	std::vector<uint64_t>	timestampStartQueryResultsBuffer	(valuesNumber, 0u);
3294	std::vector<uint64_t>	timestampEndQueryResultsBuffer		(valuesNumber, 0u);
3295
3296	m_occlusionValues.resize(queryCountersNumber);
3297	m_timestampStartValues.resize(queryCountersNumber);
3298	m_timestampEndValues.resize(queryCountersNumber);
3299
3300	if (withAvailability)
3301	{
3302		m_occlusionAvailabilityValues.resize(queryCountersNumber);
3303		m_timestampStartAvailabilityValues.resize(queryCountersNumber);
3304		m_timestampEndAvailabilityValues.resize(queryCountersNumber);
3305	}
3306
3307	if (m_cmdCopyQueryPoolResults)
3308	{
3309		memcpy(occlusionQueryResultsBuffer.data(), queryBuffer.getAllocation().getHostPtr(), de::dataSize(occlusionQueryResultsBuffer));
3310		memcpy(timestampStartQueryResultsBuffer.data(), queryBuffer.getAllocation().getHostPtr(), de::dataSize(timestampStartQueryResultsBuffer));
3311		memcpy(timestampEndQueryResultsBuffer.data(), queryBuffer.getAllocation().getHostPtr(), de::dataSize(timestampEndQueryResultsBuffer));
3312	}
3313	else
3314	{
3315		m_device->getQueryPoolResults(*m_logicalDevice, *occlusionQueryPool, 0u, queryCountersNumber, de::dataSize(occlusionQueryResultsBuffer), de::dataOrNull(occlusionQueryResultsBuffer), queryStride, queryFlags);
3316		m_device->getQueryPoolResults(*m_logicalDevice, *timestampStartQueryPool, 0u, queryCountersNumber, de::dataSize(timestampStartQueryResultsBuffer), de::dataOrNull(timestampStartQueryResultsBuffer), queryStride, queryFlags);
3317		m_device->getQueryPoolResults(*m_logicalDevice, *timestampEndQueryPool, 0u, queryCountersNumber, de::dataSize(timestampEndQueryResultsBuffer), de::dataOrNull(timestampEndQueryResultsBuffer), queryStride, queryFlags);
3318	}
3319
3320	unpackValues(occlusionQueryResultsBuffer, &m_occlusionValues, (withAvailability ? &m_occlusionAvailabilityValues : nullptr));
3321	unpackValues(timestampStartQueryResultsBuffer, &m_timestampStartValues, (withAvailability ? &m_timestampStartAvailabilityValues : nullptr));
3322	unpackValues(timestampEndQueryResultsBuffer, &m_timestampEndValues, (withAvailability ? &m_timestampEndAvailabilityValues : nullptr));
3323
3324	for (deUint32 ndx = 0; ndx < m_timestampStartValues.size(); ++ndx)
3325		m_timestampStartValues[ndx] &= m_timestampMask;
3326
3327	for (deUint32 ndx = 0; ndx < m_timestampEndValues.size(); ++ndx)
3328		m_timestampEndValues[ndx] &= m_timestampMask;
3329}
3330
3331deUint32 MultiViewQueriesTestInstance::getUsedViewsCount (const deUint32 viewMaskIndex)
3332{
3333	deUint32 result = 0;
3334
3335	for (deUint32 viewMask = m_parameters.viewMasks[viewMaskIndex]; viewMask != 0; viewMask >>= 1)
3336		if ((viewMask & 1) != 0)
3337			result++;
3338
3339	return result;
3340}
3341
3342deUint32 MultiViewQueriesTestInstance::getQueryCountersNumber ()
3343{
3344	deUint32 result = 0;
3345
3346	for (deUint32 i = 0; i < m_parameters.viewMasks.size(); ++i)
3347		result += getUsedViewsCount(i);
3348
3349	return result;
3350}
3351
3352class MultiViewReadbackTestInstance : public MultiViewRenderTestInstance
3353{
3354public:
3355						MultiViewReadbackTestInstance	(Context& context, const TestParameters& parameters);
3356protected:
3357	tcu::TestStatus		iterate							(void);
3358	void				drawClears						(const deUint32				subpassCount,
3359														 VkRenderPass				renderPass,
3360														 VkFramebuffer				frameBuffer,
3361														 vector<PipelineSp>&		pipelines,
3362														 const bool					clearPass);
3363	void				clear							(const VkCommandBuffer		commandBuffer,
3364														 const VkRect2D&			clearRect2D,
3365														 const tcu::Vec4&			clearColor);
3366private:
3367	vector<VkRect2D>	m_quarters;
3368};
3369
3370MultiViewReadbackTestInstance::MultiViewReadbackTestInstance (Context& context, const TestParameters& parameters)
3371	: MultiViewRenderTestInstance	(context, parameters)
3372{
3373	const deUint32 halfWidth	= m_parameters.extent.width / 2;
3374	const deUint32 halfHeight	= m_parameters.extent.height / 2;
3375
3376	for (deInt32 x = 0; x < 2; ++x)
3377	for (deInt32 y = 0; y < 2; ++y)
3378	{
3379		const deInt32	offsetX	= static_cast<deInt32>(halfWidth) * x;
3380		const deInt32	offsetY	= static_cast<deInt32>(halfHeight) * y;
3381		const VkRect2D	area	= { { offsetX, offsetY}, {halfWidth, halfHeight} };
3382
3383		m_quarters.push_back(area);
3384	}
3385}
3386
3387tcu::TestStatus MultiViewReadbackTestInstance::iterate (void)
3388{
3389	const deUint32	subpassCount	= static_cast<deUint32>(m_parameters.viewMasks.size());
3390
3391	createCommandBuffer();
3392
3393	for (deUint32 pass = 0; pass < 2; ++pass)
3394	{
3395		const bool									fullClearPass	= (pass == 0);
3396		const VkAttachmentLoadOp					loadOp			= (!fullClearPass) ? VK_ATTACHMENT_LOAD_OP_LOAD :
3397																	  (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR) ? VK_ATTACHMENT_LOAD_OP_CLEAR :
3398																	  (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE :
3399																	  VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3400		Move<VkRenderPass>							renderPass;
3401		Move<VkFramebuffer>							frameBuffer;
3402		Unique<VkPipelineLayout>					pipelineLayout	(makePipelineLayout(*m_device, *m_logicalDevice));
3403		vector<PipelineSp>							pipelines		(subpassCount);
3404		map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
3405
3406		if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3407		{
3408			renderPass	= makeRenderPass (*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_parameters.renderingType, VK_SAMPLE_COUNT_1_BIT, loadOp);
3409			frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(), m_parameters.extent.width, m_parameters.extent.height);
3410		}
3411
3412		{
3413			vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
3414			madeShaderModule(shaderModule, shaderStageParams);
3415			for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
3416				pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<deUint32>(shaderStageParams.size()), shaderStageParams.data(), subpassNdx))));
3417		}
3418
3419		drawClears(subpassCount, *renderPass, *frameBuffer, pipelines, fullClearPass);
3420	}
3421
3422	{
3423		vector<deUint8>			pixelAccessData	(m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth * mapVkFormat(m_parameters.colorFormat).getPixelSize());
3424		tcu::PixelBufferAccess	dst				(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
3425
3426		readImage(m_colorAttachment->getImage(), dst);
3427
3428		if (!checkImage(dst))
3429			return tcu::TestStatus::fail("Fail");
3430	}
3431
3432	return tcu::TestStatus::pass("Pass");
3433}
3434
3435void MultiViewReadbackTestInstance::drawClears (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines, const bool clearPass)
3436{
3437	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
3438	const VkClearValue				renderPassClearValue	= makeClearValueColor(m_colorTable[0]);
3439	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
3440	const bool						withClearColor			= (clearPass && m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR);
3441
3442	beginCommandBuffer(*m_device, *m_cmdBuffer);
3443
3444	if (clearPass)
3445		beforeRenderPass();
3446
3447	if (!m_useDynamicRendering)
3448	{
3449		const VkRenderPassBeginInfo renderPassBeginInfo
3450		{
3451			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			//  VkStructureType		sType;
3452			DE_NULL,											//  const void*			pNext;
3453			renderPass,											//  VkRenderPass		renderPass;
3454			frameBuffer,										//  VkFramebuffer		framebuffer;
3455			renderArea,											//  VkRect2D			renderArea;
3456			withClearColor ? 1u : 0u,							//  uint32_t			clearValueCount;
3457			withClearColor ? &renderPassClearValue : DE_NULL,	//  const VkClearValue*	pClearValues;
3458		};
3459		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
3460	}
3461
3462	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
3463	{
3464		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
3465
3466#ifndef CTS_USES_VULKANSC
3467		if (m_useDynamicRendering)
3468		{
3469			addRenderingSubpassDependencyIfRequired(subpassNdx);
3470
3471			VkAttachmentLoadOp loadOperation = VK_ATTACHMENT_LOAD_OP_LOAD;
3472			if (clearPass)
3473			{
3474				if (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR)
3475					loadOperation = VK_ATTACHMENT_LOAD_OP_CLEAR;
3476				else if (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR)
3477					loadOperation = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3478				else
3479					loadOperation = VK_ATTACHMENT_LOAD_OP_MAX_ENUM;
3480			}
3481
3482			beginRendering(
3483				*m_device,
3484				*m_cmdBuffer,
3485				m_colorAttachment->getImageView(),
3486				renderArea,
3487				renderPassClearValue,
3488				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3489				loadOperation,
3490				0u,
3491				m_parameters.extent.depth,
3492				m_parameters.viewMasks[subpassNdx]);
3493		}
3494#endif // CTS_USES_VULKANSC
3495
3496		if (clearPass)
3497		{
3498			if (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR)
3499				clear(*m_cmdBuffer, renderArea, m_colorTable[subpassNdx % 4]);
3500		}
3501		else
3502		{
3503			for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
3504			{
3505				const deUint32 primitiveNumber	= drawNdx + subpassNdx % m_squareCount;
3506
3507				clear(*m_cmdBuffer, m_quarters[primitiveNumber], m_colorTable[4 + primitiveNumber]);
3508			}
3509		}
3510
3511#ifndef CTS_USES_VULKANSC
3512		if (m_useDynamicRendering)
3513			endRendering(*m_device, *m_cmdBuffer);
3514		else
3515#endif // CTS_USES_VULKANSC
3516			if (subpassNdx < subpassCount - 1u)
3517			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
3518	}
3519
3520	if (!m_useDynamicRendering)
3521		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
3522
3523	if (!clearPass)
3524		afterRenderPass();
3525
3526	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3527	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3528}
3529
3530void MultiViewReadbackTestInstance::clear (const VkCommandBuffer commandBuffer, const VkRect2D& clearRect2D, const tcu::Vec4& clearColor)
3531{
3532	const VkClearRect		clearRect		=
3533	{
3534		clearRect2D,						//  VkRect2D	rect
3535		0u,									//  deUint32	baseArrayLayer
3536		1u,									//  deUint32	layerCount
3537	};
3538	const VkClearAttachment	clearAttachment	=
3539	{
3540		VK_IMAGE_ASPECT_COLOR_BIT,			//  VkImageAspectFlags	aspectMask
3541		0u,									//  deUint32			colorAttachment
3542		makeClearValueColor(clearColor)		//  VkClearValue		clearValue
3543	};
3544
3545	m_device->cmdClearAttachments(commandBuffer, 1u, &clearAttachment, 1u, &clearRect);
3546}
3547
3548class MultiViewDepthStencilTestInstance : public MultiViewRenderTestInstance
3549{
3550public:
3551									MultiViewDepthStencilTestInstance	(Context& context, const TestParameters& parameters);
3552protected:
3553	tcu::TestStatus					iterate								(void) override;
3554	void							createVertexData					(void) override;
3555
3556	void							draw								(const deUint32					subpassCount,
3557																		 VkRenderPass					renderPass,
3558																		 VkFramebuffer					frameBuffer,
3559																		 vector<PipelineSp>&			pipelines) override;
3560	void							beforeRenderPass							(void) override;
3561	void							afterRenderPass							(void) override;
3562	vector<VkImageView>				makeAttachmentsVector				(void);
3563	MovePtr<tcu::Texture2DArray>	imageData							(void) const override;
3564	void							readImage							(VkImage						image,
3565																		 const tcu::PixelBufferAccess&	dst);
3566	vector<tcu::Vec2>				getDepthRanges						(void) const;
3567
3568private:
3569	VkFormat						m_dsFormat;
3570	de::SharedPtr<ImageAttachment>	m_dsAttachment;
3571	bool							m_depthTest;
3572	bool							m_stencilTest;
3573};
3574
3575MultiViewDepthStencilTestInstance::MultiViewDepthStencilTestInstance (Context& context, const TestParameters& parameters)
3576	: MultiViewRenderTestInstance	(context, parameters)
3577	, m_dsFormat					(VK_FORMAT_UNDEFINED)
3578	, m_depthTest					(m_parameters.viewIndex == TEST_TYPE_DEPTH ||
3579									 m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
3580	, m_stencilTest					(m_parameters.viewIndex == TEST_TYPE_STENCIL)
3581{
3582	const VkFormat formats[] = { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };
3583
3584	for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(formats); ++ndx)
3585	{
3586		const VkFormat				format				= formats[ndx];
3587		const auto&					vki					= m_context.getInstanceInterface();
3588		const auto					physicalDevice		= m_context.getPhysicalDevice();
3589		const VkFormatProperties	formatProperties	= getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
3590
3591		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
3592		{
3593			m_dsFormat = format;
3594
3595			break;
3596		}
3597	}
3598
3599	if (m_dsFormat == VK_FORMAT_UNDEFINED)
3600		TCU_FAIL("Supported depth/stencil format not found, that violates specification");
3601
3602	// Depth/stencil attachment
3603	m_dsAttachment = de::SharedPtr<ImageAttachment>(new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_dsFormat));
3604}
3605
3606vector<VkImageView>	MultiViewDepthStencilTestInstance::makeAttachmentsVector (void)
3607{
3608	vector<VkImageView> attachments;
3609
3610	attachments.push_back(m_colorAttachment->getImageView());
3611	attachments.push_back(m_dsAttachment->getImageView());
3612
3613	return attachments;
3614}
3615
3616MovePtr<tcu::Texture2DArray> MultiViewDepthStencilTestInstance::imageData(void) const
3617{
3618	MovePtr<tcu::Texture2DArray>	referenceFrame		= MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth));
3619	const deUint32					subpassCount		= static_cast<deUint32>(m_parameters.viewMasks.size());
3620	const vector<tcu::Vec2>			depthRanges			= getDepthRanges();
3621
3622	referenceFrame->allocLevel(0);
3623	deMemset(referenceFrame->getLevel(0).getDataPtr(), 0, m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth* mapVkFormat(m_parameters.colorFormat).getPixelSize());
3624
3625	for (deUint32 layerNdx = 0; layerNdx < m_parameters.extent.depth; ++layerNdx)
3626		fillLayer(referenceFrame->getLevel(0), getQuarterRefColor(0u, 0u, 0u, false), layerNdx);
3627
3628	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
3629	{
3630		int					layerNdx			= 0;
3631		deUint32			mask				= m_parameters.viewMasks[subpassNdx];
3632		const tcu::Vec2&	depthRange			= depthRanges[subpassNdx];
3633		const float			depthMin			= depthRange[0];
3634		const float			depthMax			= depthRange[1];
3635
3636		// iterate over image layers
3637		while (mask > 0u)
3638		{
3639			if (mask & 1u)
3640			{
3641				const deUint32	subpassQuarterNdx	= subpassNdx % m_squareCount;
3642				const int		colorNdx			= subpassQuarterNdx * 4;
3643				tcu::Vec4		color				= getQuarterRefColor(subpassQuarterNdx, colorNdx, layerNdx, true, subpassNdx);
3644
3645				if (m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
3646				{
3647					// quads with depth out of range should be cliiped
3648					// to simplify code we are drawing them with background color
3649					if ((color.x() < 0.0f) || (color.x() > 1.0f))
3650						color.x() = 1.0f;
3651					else
3652					{
3653						const float depthClamped = de::clamp(color.x(), 0.0f, 1.0f);
3654						color.x() = depthClamped * depthMax + (1.0f - depthClamped) * depthMin;
3655					}
3656				}
3657
3658				fillQuarter(referenceFrame->getLevel(0), color, layerNdx, subpassQuarterNdx, subpassNdx);
3659			}
3660
3661			mask = mask >> 1;
3662			++layerNdx;
3663		}
3664	}
3665	return referenceFrame;
3666}
3667
3668void MultiViewDepthStencilTestInstance::readImage (VkImage image, const tcu::PixelBufferAccess& dst)
3669{
3670	const VkFormat				bufferFormat	= m_depthTest ? getDepthBufferFormat(m_dsFormat) :
3671												  m_stencilTest ? getStencilBufferFormat(m_dsFormat) :
3672												  VK_FORMAT_UNDEFINED;
3673	const deUint32				imagePixelSize	= static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(bufferFormat)));
3674	const VkDeviceSize			pixelDataSize	= dst.getWidth() * dst.getHeight() * dst.getDepth() * imagePixelSize;
3675	const tcu::TextureFormat	tcuBufferFormat	= mapVkFormat(bufferFormat);
3676	Move<VkBuffer>				buffer;
3677	MovePtr<Allocation>			bufferAlloc;
3678
3679	// Create destination buffer
3680	{
3681		const VkBufferCreateInfo bufferParams	=
3682		{
3683			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
3684			DE_NULL,								// const void*			pNext;
3685			0u,										// VkBufferCreateFlags	flags;
3686			pixelDataSize,							// VkDeviceSize			size;
3687			VK_BUFFER_USAGE_TRANSFER_DST_BIT,		// VkBufferUsageFlags	usage;
3688			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
3689			1u,										// deUint32				queueFamilyIndexCount;
3690			&m_queueFamilyIndex,					// const deUint32*		pQueueFamilyIndices;
3691		};
3692
3693		buffer		= createBuffer(*m_device, *m_logicalDevice, &bufferParams);
3694		bufferAlloc	= m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *buffer), MemoryRequirement::HostVisible);
3695		VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
3696
3697		deMemset(bufferAlloc->getHostPtr(), 0xCC, static_cast<size_t>(pixelDataSize));
3698		flushAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
3699	}
3700
3701	const VkBufferMemoryBarrier	bufferBarrier	=
3702	{
3703		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
3704		DE_NULL,									// const void*		pNext;
3705		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
3706		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
3707		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
3708		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
3709		*buffer,									// VkBuffer			buffer;
3710		0u,											// VkDeviceSize		offset;
3711		pixelDataSize								// VkDeviceSize		size;
3712	};
3713
3714	// Copy image to buffer
3715	const VkImageAspectFlags	aspect			= m_depthTest ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT) :
3716												  m_stencilTest ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_STENCIL_BIT) :
3717												  static_cast<VkImageAspectFlags>(0u);
3718	const VkBufferImageCopy		copyRegion		=
3719	{
3720		0u,											// VkDeviceSize				bufferOffset;
3721		(deUint32)dst.getWidth(),					// deUint32					bufferRowLength;
3722		(deUint32)dst.getHeight(),					// deUint32					bufferImageHeight;
3723		{
3724			aspect,									// VkImageAspectFlags		aspect;
3725			0u,										// deUint32					mipLevel;
3726			0u,										// deUint32					baseArrayLayer;
3727			m_parameters.extent.depth,				// deUint32					layerCount;
3728		},											// VkImageSubresourceLayers	imageSubresource;
3729		{ 0, 0, 0 },								// VkOffset3D				imageOffset;
3730		{											// VkExtent3D				imageExtent;
3731			m_parameters.extent.width,
3732			m_parameters.extent.height,
3733			1u
3734		}
3735	};
3736
3737	beginCommandBuffer (*m_device, *m_cmdBuffer);
3738	{
3739		m_device->cmdCopyImageToBuffer(*m_cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, &copyRegion);
3740		m_device->cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0u, DE_NULL);
3741	}
3742	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3743	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3744
3745	// Read buffer data
3746	invalidateAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
3747
3748	if (m_depthTest)
3749	{
3750		// Translate depth into color space
3751		tcu::ConstPixelBufferAccess	pixelBuffer	(tcuBufferFormat, dst.getSize(), bufferAlloc->getHostPtr());
3752
3753		for (int z = 0; z < pixelBuffer.getDepth(); z++)
3754		for (int y = 0; y < pixelBuffer.getHeight(); y++)
3755		for (int x = 0; x < pixelBuffer.getWidth(); x++)
3756		{
3757			const float		depth	= pixelBuffer.getPixDepth(x, y, z);
3758			const tcu::Vec4	color	= tcu::Vec4(depth, 0.0f, 0.0f, 1.0f);
3759
3760			dst.setPixel(color, x, y, z);
3761		}
3762	}
3763
3764	if (m_stencilTest)
3765	{
3766		// Translate stencil into color space
3767		tcu::ConstPixelBufferAccess	pixelBuffer	(tcuBufferFormat, dst.getSize(), bufferAlloc->getHostPtr());
3768		const tcu::Vec4				baseColor		= getQuarterRefColor(0u, 0u, 0u, false);
3769		const tcu::Vec4				colorStep		= getQuarterRefColor(0u, 0u, 0u, true);
3770		const tcu::Vec4				colorMap[4]		=
3771		{
3772			baseColor,
3773			tcu::Vec4(1.0f * colorStep[0], 0.0f, 0.0f, 1.0),
3774			tcu::Vec4(2.0f * colorStep[0], 0.0f, 0.0f, 1.0),
3775			tcu::Vec4(3.0f * colorStep[0], 0.0f, 0.0f, 1.0),
3776		};
3777		const tcu::Vec4				invalidColor	= tcu::Vec4(0.0f);
3778
3779		for (int z = 0; z < pixelBuffer.getDepth(); z++)
3780		for (int y = 0; y < pixelBuffer.getHeight(); y++)
3781		for (int x = 0; x < pixelBuffer.getWidth(); x++)
3782		{
3783			const int			stencilInt	= pixelBuffer.getPixStencil(x, y, z);
3784			const tcu::Vec4&	color		= de::inRange(stencilInt, 0, DE_LENGTH_OF_ARRAY(colorMap)) ? colorMap[stencilInt] : invalidColor;
3785
3786			dst.setPixel(color, x, y, z);
3787		}
3788	}
3789}
3790
3791tcu::TestStatus MultiViewDepthStencilTestInstance::iterate (void)
3792{
3793	const deUint32								subpassCount	= static_cast<deUint32>(m_parameters.viewMasks.size());
3794	Move<VkRenderPass>							renderPass;
3795	vector<VkImageView>							attachments		(makeAttachmentsVector());
3796	Move<VkFramebuffer>							frameBuffer;
3797	Unique<VkPipelineLayout>					pipelineLayout	(makePipelineLayout(*m_device, *m_logicalDevice));
3798	vector<PipelineSp>							pipelines		(subpassCount);
3799	const vector<tcu::Vec2>						depthRanges		(getDepthRanges());
3800	map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
3801
3802	if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3803	{
3804		renderPass	= makeRenderPassWithDepth(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_dsFormat, m_parameters.renderingType);
3805		frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, static_cast<deUint32>(attachments.size()), attachments.data(), m_parameters.extent.width, m_parameters.extent.height, 1u);
3806	}
3807
3808	if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3809	{
3810		renderPass	= makeRenderPassWithDepth(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks, m_dsFormat, m_parameters.renderingType);
3811		frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, static_cast<deUint32>(attachments.size()), attachments.data(), m_parameters.extent.width, m_parameters.extent.height, 1u);
3812	}
3813
3814	{
3815		vector<VkPipelineShaderStageCreateInfo>	shaderStageParams;
3816		madeShaderModule(shaderModule, shaderStageParams);
3817		for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
3818		{
3819			const tcu::Vec2& depthRange = depthRanges[subpassNdx];
3820			const float depthMin		= depthRange[0];
3821			const float depthMax		= depthRange[1];
3822
3823			pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(
3824				*renderPass, *pipelineLayout, static_cast<deUint32>(shaderStageParams.size()), shaderStageParams.data(),
3825				subpassNdx, VK_VERTEX_INPUT_RATE_VERTEX, m_depthTest, m_stencilTest, depthMin, depthMax, m_dsFormat))));
3826		}
3827	}
3828
3829	createCommandBuffer();
3830	createVertexData();
3831	createVertexBuffer();
3832
3833	draw(subpassCount, *renderPass, *frameBuffer, pipelines);
3834
3835	{
3836		vector<deUint8>			pixelAccessData	(m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth * mapVkFormat(m_parameters.colorFormat).getPixelSize());
3837		tcu::PixelBufferAccess	dst				(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width, m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
3838
3839		readImage(m_dsAttachment->getImage(), dst);
3840
3841		if (!checkImage(dst))
3842			return tcu::TestStatus::fail("Fail");
3843	}
3844
3845	return tcu::TestStatus::pass("Pass");
3846}
3847
3848void MultiViewDepthStencilTestInstance::createVertexData (void)
3849{
3850/*
3851	partA - draw vertical quads, marked with 1
3852
3853	ViewMasks
3854	0011
3855	0110
3856	1100
3857	1001
3858
3859	Layer3  Layer2  Layer1  Layer0
3860	  ^       ^       ^       ^
3861	00|10   00|10   01|00   01|00
3862	00|10   00|10   01|00   01|00
3863	--+-->  --+-->  --+-->  --+-->
3864	00|10   01|00   01|00   00|10
3865	00|10   01|00   01|00   00|10
3866
3867
3868	partB - draw horizontal quads, marked with 2
3869
3870	ViewMasks
3871	0110
3872	1100
3873	1001
3874	0011
3875
3876	Layer3  Layer2  Layer1  Layer0
3877	  ^       ^       ^       ^
3878	00|00   00|00   00|00   00|00
3879	00|22   22|00   22|00   00|22
3880	--+-->  --+-->  --+-->  --+-->
3881	22|00   22|00   00|22   00|22
3882	00|00   00|00   00|00   00|00
3883
3884
3885	Final - after drawing quads from partA and partB (3 marks where quads overlap)
3886
3887	Layer3  Layer2  Layer1  Layer0
3888	  ^       ^       ^       ^
3889	00|10   00|10   01|00   01|00
3890	00|32   22|10   23|00   01|22
3891	--+-->  --+-->  --+-->  --+-->
3892	22|10   23|00   01|22   00|32
3893	00|10   01|00   01|00   00|10
3894*/
3895	tcu::Vec4	color	(0.0f, 0.0f, 0.0f, 1.0f); // is not essential in this test
3896	float		depth	(getQuarterRefColor(0u, 0u, 0u, true, 0u)[0]);
3897
3898	// part A - four horizontal quads
3899	appendVertex(tcu::Vec4(-1.0f,-0.5f, depth, 1.0f), color);		// when testing TEST_TYPE_DEPTH_DIFFERENT_RANGES
3900	appendVertex(tcu::Vec4(-1.0f, 0.0f, depth, 1.0f), color);		// this quad will have depth 1.2
3901	appendVertex(tcu::Vec4( 0.0f,-0.5f, depth, 1.0f), color);		// and will be clipped in all views
3902	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3903
3904	depth = getQuarterRefColor(0u, 0u, 0u, true, 1u)[0];
3905	appendVertex(tcu::Vec4(-1.0f, 0.0f, depth, 1.0f), color);
3906	appendVertex(tcu::Vec4(-1.0f, 0.5f, depth, 1.0f), color);
3907	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3908	appendVertex(tcu::Vec4( 0.0f, 0.5f, depth, 1.0f), color);
3909
3910	depth = getQuarterRefColor(0u, 0u, 0u, true, 2u)[0];
3911	appendVertex(tcu::Vec4( 0.0f,-0.5f, depth, 1.0f), color);
3912	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3913	appendVertex(tcu::Vec4( 1.0f,-0.5f, depth, 1.0f), color);
3914	appendVertex(tcu::Vec4( 1.0f, 0.0f, depth, 1.0f), color);
3915
3916	depth = getQuarterRefColor(0u, 0u, 0u, true, 3u)[0];
3917	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3918	appendVertex(tcu::Vec4( 0.0f, 0.5f, depth, 1.0f), color);
3919	appendVertex(tcu::Vec4( 1.0f, 0.0f, depth, 1.0f), color);
3920	appendVertex(tcu::Vec4( 1.0f, 0.5f, depth, 1.0f), color);
3921
3922	// part B - four vertical quads
3923	depth = getQuarterRefColor(0u, 0u, 0u, true, 4u)[0];
3924	appendVertex(tcu::Vec4(-0.5f,-1.0f, depth, 1.0f), color);
3925	appendVertex(tcu::Vec4(-0.5f, 0.0f, depth, 1.0f), color);
3926	appendVertex(tcu::Vec4( 0.0f,-1.0f, depth, 1.0f), color);
3927	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3928
3929	depth = getQuarterRefColor(0u, 0u, 0u, true, 5u)[0];
3930	appendVertex(tcu::Vec4(-0.5f, 0.0f, depth, 1.0f), color);
3931	appendVertex(tcu::Vec4(-0.5f, 1.0f, depth, 1.0f), color);
3932	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3933	appendVertex(tcu::Vec4( 0.0f, 1.0f, depth, 1.0f), color);
3934
3935	depth = getQuarterRefColor(0u, 0u, 0u, true, 6u)[0];
3936	appendVertex(tcu::Vec4( 0.0f,-1.0f, depth, 1.0f), color);
3937	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);
3938	appendVertex(tcu::Vec4( 0.5f,-1.0f, depth, 1.0f), color);
3939	appendVertex(tcu::Vec4( 0.5f, 0.0f, depth, 1.0f), color);
3940
3941	depth = getQuarterRefColor(0u, 0u, 0u, true, 7u)[0];			// when testing TEST_TYPE_DEPTH_DIFFERENT_RANGES
3942	appendVertex(tcu::Vec4( 0.0f, 0.0f, depth, 1.0f), color);		// this quad will have depth -0.05
3943	appendVertex(tcu::Vec4( 0.0f, 1.0f, depth, 1.0f), color);		// and will be clipped in all views
3944	appendVertex(tcu::Vec4( 0.5f, 0.0f, depth, 1.0f), color);
3945	appendVertex(tcu::Vec4( 0.5f, 1.0f, depth, 1.0f), color);
3946}
3947
3948vector<tcu::Vec2> MultiViewDepthStencilTestInstance::getDepthRanges(void) const
3949{
3950	if (TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex)
3951	{
3952		DE_ASSERT(m_parameters.viewMasks.size() == 12);
3953		return
3954		{
3955			// ranges used when four quads from part A are drawn
3956			{0.0f, 1.0f},
3957			{0.5f, 1.0f},
3958			{0.0f, 0.5f},
3959			{0.0f, 1.0f},
3960
3961			// ranges used when four quads from part B are drawn
3962			{0.0f, 0.5f},
3963			{0.0f, 1.0f},
3964			{0.5f, 1.0f},
3965			{0.0f, 0.5f},
3966
3967			// ranges used when part B is drawn once again
3968			{0.5f, 1.0f},
3969			{0.0f, 0.5f},
3970			{0.0f, 0.5f},
3971			{0.0f, 1.0f},
3972		};
3973	}
3974
3975	// by defaul use <0; 1> range for all subpasses
3976	return { m_parameters.viewMasks.size(), tcu::Vec2(0.0f, 1.0f) };
3977}
3978
3979void MultiViewDepthStencilTestInstance::draw (const deUint32 subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer, vector<PipelineSp>& pipelines)
3980{
3981	const VkRect2D					renderArea				= { { 0, 0 }, { m_parameters.extent.width, m_parameters.extent.height } };
3982	const VkClearValue				renderPassClearValue	= makeClearValueColor(tcu::Vec4(0.0f));
3983	const VkBuffer					vertexBuffers[]			= { *m_vertexCoordBuffer, *m_vertexColorBuffer };
3984	const VkDeviceSize				vertexBufferOffsets[]	= {                   0u,                   0u };
3985	const deUint32					drawCountPerSubpass		= (subpassCount == 1) ? m_squareCount : 1u;
3986	const deUint32					vertexPerPrimitive		= 4u;
3987
3988	beginCommandBuffer(*m_device, *m_cmdBuffer);
3989
3990	beforeRenderPass();
3991
3992	if (!m_useDynamicRendering)
3993	{
3994		const VkRenderPassBeginInfo renderPassBeginInfo
3995		{
3996			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
3997			DE_NULL,									// const void*			pNext;
3998			renderPass,									// VkRenderPass			renderPass;
3999			frameBuffer,								// VkFramebuffer		framebuffer;
4000			renderArea,									// VkRect2D				renderArea;
4001			1u,											// uint32_t				clearValueCount;
4002			&renderPassClearValue,						// const VkClearValue*	pClearValues;
4003		};
4004		cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
4005	}
4006
4007	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
4008	{
4009		deUint32 firstVertexOffset = (subpassNdx < 4) ? 0u : m_squareCount * vertexPerPrimitive;
4010
4011		m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
4012		m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
4013
4014#ifndef CTS_USES_VULKANSC
4015		if (m_useDynamicRendering)
4016		{
4017			addRenderingSubpassDependencyIfRequired(subpassNdx);
4018
4019			VkRenderingAttachmentInfoKHR colorAttachment
4020			{
4021				vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
4022				DE_NULL,												// const void*							pNext;
4023				m_colorAttachment->getImageView(),						// VkImageView							imageView;
4024				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout						imageLayout;
4025				VK_RESOLVE_MODE_NONE,									// VkResolveModeFlagBits				resolveMode;
4026				DE_NULL,												// VkImageView							resolveImageView;
4027				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout						resolveImageLayout;
4028				VK_ATTACHMENT_LOAD_OP_LOAD,								// VkAttachmentLoadOp					loadOp;
4029				vk::VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
4030				renderPassClearValue									// VkClearValue							clearValue;
4031			};
4032
4033			VkRenderingAttachmentInfoKHR dsAttachment
4034			{
4035				VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,		// VkStructureType						sType;
4036				DE_NULL,												// const void*							pNext;
4037				m_dsAttachment->getImageView(),							// VkImageView							imageView;
4038				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// VkImageLayout						imageLayout;
4039				VK_RESOLVE_MODE_NONE,									// VkResolveModeFlagBits				resolveMode;
4040				DE_NULL,												// VkImageView							resolveImageView;
4041				VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout						resolveImageLayout;
4042				VK_ATTACHMENT_LOAD_OP_LOAD,								// VkAttachmentLoadOp					loadOp;
4043				VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp					storeOp;
4044				makeClearValueDepthStencil(0.0f, 0)						// VkClearValue							clearValue;
4045			};
4046
4047			vk::VkRenderingInfoKHR renderingInfo
4048			{
4049				vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
4050				DE_NULL,
4051				0u,														// VkRenderingFlagsKHR					flags;
4052				renderArea,												// VkRect2D								renderArea;
4053				m_parameters.extent.depth,								// deUint32								layerCount;
4054				m_parameters.viewMasks[subpassNdx],						// deUint32								viewMask;
4055				1u,														// deUint32								colorAttachmentCount;
4056				&colorAttachment,										// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
4057				(m_depthTest ? &dsAttachment : DE_NULL),				// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
4058				(m_stencilTest ? &dsAttachment : DE_NULL),				// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
4059			};
4060
4061			m_device->cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
4062		}
4063#endif // CTS_USES_VULKANSC
4064
4065		for (deUint32 drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
4066			m_device->cmdDraw(*m_cmdBuffer, vertexPerPrimitive, 1u, firstVertexOffset + (drawNdx + subpassNdx % m_squareCount) * vertexPerPrimitive, 0u);
4067
4068#ifndef CTS_USES_VULKANSC
4069		if (m_useDynamicRendering)
4070			endRendering(*m_device, *m_cmdBuffer);
4071		else
4072#endif // CTS_USES_VULKANSC
4073			if (subpassNdx < subpassCount - 1u)
4074			cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
4075	}
4076
4077	if (!m_useDynamicRendering)
4078		cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
4079
4080	afterRenderPass();
4081
4082	VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
4083	submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
4084}
4085
4086void MultiViewDepthStencilTestInstance::beforeRenderPass (void)
4087{
4088	MultiViewRenderTestInstance::beforeRenderPass();
4089
4090	const VkImageSubresourceRange	subresourceRange		=
4091	{
4092		VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,	//VkImageAspectFlags	aspectMask;
4093		0u,															//deUint32				baseMipLevel;
4094		1u,															//deUint32				levelCount;
4095		0u,															//deUint32				baseArrayLayer;
4096		m_parameters.extent.depth,									//deUint32				layerCount;
4097	};
4098	imageBarrier(*m_device, *m_cmdBuffer, m_dsAttachment->getImage(), subresourceRange,
4099		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4100		0, VK_ACCESS_TRANSFER_WRITE_BIT,
4101		VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4102
4103	const tcu::Vec4		baseColor	= getQuarterRefColor(0u, 0u, 0u, false);
4104	const float			clearDepth	= baseColor[0];
4105	const VkClearValue	clearValue	= makeClearValueDepthStencil(clearDepth, 0);
4106
4107	m_device->cmdClearDepthStencilImage(*m_cmdBuffer, m_dsAttachment->getImage(),  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.depthStencil, 1, &subresourceRange);
4108
4109	imageBarrier(*m_device, *m_cmdBuffer, m_dsAttachment->getImage(), subresourceRange,
4110		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4111		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
4112		VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
4113}
4114
4115void MultiViewDepthStencilTestInstance::afterRenderPass (void)
4116{
4117	MultiViewRenderTestInstance::afterRenderPass();
4118
4119	const VkImageSubresourceRange	dsSubresourceRange		=
4120	{
4121		VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,	//  VkImageAspectFlags	aspectMask;
4122		0u,															//  deUint32			baseMipLevel;
4123		1u,															//  deUint32			levelCount;
4124		0u,															//  deUint32			baseArrayLayer;
4125		m_parameters.extent.depth,									//  deUint32			layerCount;
4126	};
4127
4128	imageBarrier(*m_device, *m_cmdBuffer, m_dsAttachment->getImage(), dsSubresourceRange,
4129		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4130		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
4131		VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4132}
4133
4134class MultiViewMaskIterationTestInstance : public MultiViewRenderTestInstance
4135{
4136public:
4137	MultiViewMaskIterationTestInstance	(Context& context, const TestParameters& parameters);
4138protected:
4139	void								beforeRender	(const VkCommandBuffer cmdBuffer);
4140	void								afterRender		(const VkCommandBuffer cmdBuffer);
4141	tcu::TestStatus						iterate			(void) override;
4142
4143	using ImageWithBufferPtr = std::unique_ptr<ImageWithBuffer>;
4144	ImageWithBufferPtr					m_colorImage;
4145	tcu::IVec3							m_dim;
4146	uint32_t							m_layerCount;
4147	VkImageSubresourceRange				m_colorSRR;
4148	VkClearValue						m_clearValue;
4149};
4150
4151MultiViewMaskIterationTestInstance::MultiViewMaskIterationTestInstance (Context& context, const TestParameters& parameters)
4152	: MultiViewRenderTestInstance	(context, parameters)
4153{
4154	m_dim					=	tcu::IVec3(m_parameters.extent.width, m_parameters.extent.height, 1);
4155	m_layerCount			=	m_parameters.extent.depth;
4156	const auto	colorUsage	=	(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
4157	m_colorSRR				=	makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount);
4158	m_colorImage			=	ImageWithBufferPtr (new ImageWithBuffer(*m_device, *m_logicalDevice, *m_allocator, makeExtent3D(m_dim), m_parameters.colorFormat, colorUsage, VK_IMAGE_TYPE_2D, m_colorSRR, m_layerCount));
4159	m_clearValue			=	makeClearValueColor(tcu::Vec4(0));
4160}
4161
4162
4163void MultiViewMaskIterationTestInstance::beforeRender (const VkCommandBuffer cmdBuffer)
4164{
4165	imageBarrier(*m_device, cmdBuffer, m_colorImage->getImage(), m_colorSRR,
4166		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4167		0, VK_ACCESS_TRANSFER_WRITE_BIT,
4168		VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4169
4170
4171	m_device->cmdClearColorImage(cmdBuffer, m_colorImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_clearValue.color, 1u, &m_colorSRR);
4172
4173	imageBarrier(*m_device, cmdBuffer, m_colorImage->getImage(), m_colorSRR,
4174		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4175		VK_ACCESS_TRANSFER_WRITE_BIT, (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
4176		VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
4177}
4178
4179void MultiViewMaskIterationTestInstance::afterRender (const VkCommandBuffer cmdBuffer)
4180{
4181	imageBarrier(*m_device, cmdBuffer, m_colorImage->getImage(), m_colorSRR,
4182		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4183		(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), VK_ACCESS_TRANSFER_READ_BIT,
4184		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4185}
4186
4187tcu::TestStatus MultiViewMaskIterationTestInstance::iterate (void)
4188{
4189	bool			failure			=	false;
4190	const deUint32	subpassCount	=	static_cast<deUint32>(m_parameters.viewMasks.size());
4191	const auto		fbExtent		=	makeExtent3D(m_dim);
4192	const auto		colorSRL		=	makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_layerCount);
4193
4194	map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
4195	vector<VkPipelineShaderStageCreateInfo>		shaderStageParams;
4196	madeShaderModule(shaderModule, shaderStageParams);
4197	const VkShaderModule vertexShaderModule = shaderModule[VK_SHADER_STAGE_VERTEX_BIT]->get();
4198	const VkShaderModule fragShaderModule	= shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT]->get();
4199
4200	const std::vector<VkViewport>	viewports	(1u, makeViewport(fbExtent));
4201	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(fbExtent));
4202	const auto pipelineLayout		= makePipelineLayout(*m_device, *m_logicalDevice, VK_NULL_HANDLE);
4203
4204	const auto colorBlendAttState	= makePipelineColorBlendAttachmentState(VK_FALSE, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT));
4205
4206	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo	= initVulkanStructure();
4207
4208#ifndef CTS_USES_VULKANSC
4209	VkRenderingAttachmentInfoKHR renderingAttInfo =
4210	{
4211		VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,//	VkStructureType			sType;
4212		nullptr,										//	const void*				pNext;
4213		m_colorImage->getImageView(),					//	VkImageView				imageView;
4214		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout			imageLayout;
4215		VK_RESOLVE_MODE_NONE,							//	VkResolveModeFlagBits	resolveMode;
4216		VK_NULL_HANDLE,									//	VkImageView				resolveImageView;
4217		VK_IMAGE_LAYOUT_UNDEFINED,						//	VkImageLayout			resolveImageLayout;
4218		VK_ATTACHMENT_LOAD_OP_LOAD,						//	VkAttachmentLoadOp		loadOp;
4219		VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp		storeOp;
4220		m_clearValue,									//	VkClearValue			clearValue;
4221	};
4222#endif
4223
4224	for (deUint32 subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
4225	{
4226		const auto			layerMask	= m_parameters.viewMasks[subpassNdx];
4227		Move<VkRenderPass>	renderPass;
4228		Move<VkFramebuffer>	frameBuffer;
4229
4230		// FrameBuffer & renderPass
4231		if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
4232		{
4233			const std::vector<deUint32> layerMasks (1u, layerMask);
4234			renderPass	= makeRenderPass (*m_device, *m_logicalDevice, m_parameters.colorFormat, layerMasks, m_parameters.renderingType);
4235			frameBuffer	= makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorImage->getImageView(), fbExtent.width, fbExtent.height);
4236		}
4237#ifndef CTS_USES_VULKANSC
4238		const VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo =
4239		{
4240			VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,	//	VkStructureType	sType;
4241			nullptr,												//	const void*		pNext;
4242			layerMask,												//	uint32_t		viewMask;
4243			1u,														//	uint32_t		colorAttachmentCount;
4244			&m_parameters.colorFormat,								//	const VkFormat*	pColorAttachmentFormats;
4245			VK_FORMAT_UNDEFINED,									//	VkFormat		depthAttachmentFormat;
4246			VK_FORMAT_UNDEFINED,									//	VkFormat		stencilAttachmentFormat;
4247		};
4248#endif // CTS_USES_VULKANSC
4249		const std::vector<VkPipelineColorBlendAttachmentState> colorBlendStateVec (1u, colorBlendAttState);
4250
4251		const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
4252		{
4253			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
4254			nullptr,													//	const void*									pNext;
4255			0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
4256			VK_FALSE,													//	VkBool32									logicOpEnable;
4257			VK_LOGIC_OP_CLEAR,											//	VkLogicOp									logicOp;
4258			de::sizeU32(colorBlendStateVec),							//	uint32_t									attachmentCount;
4259			de::dataOrNull(colorBlendStateVec),							//	const VkPipelineColorBlendAttachmentState*	pAttachments;
4260			{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
4261		};
4262
4263		const auto pipeline = vk::makeGraphicsPipeline(*m_device, *m_logicalDevice, pipelineLayout.get(),
4264			vertexShaderModule, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, fragShaderModule,
4265			*renderPass, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
4266			&vertexInputStateCreateInfo, nullptr, nullptr, nullptr, &colorBlendStateCreateInfo, nullptr,
4267#ifndef CTS_USES_VULKANSC
4268			(*renderPass == 0) ? &pipelineRenderingCreateInfo : VK_NULL_HANDLE
4269#else
4270			VK_NULL_HANDLE
4271#endif // CTS_USES_VULKANSC
4272			);
4273
4274		CommandPoolWithBuffer cmd (*m_device, *m_logicalDevice, m_queueFamilyIndex);
4275		const auto cmdBuffer = cmd.cmdBuffer.get();
4276
4277		beginCommandBuffer(*m_device, cmdBuffer);
4278
4279		beforeRender(cmdBuffer);
4280
4281		if (!m_useDynamicRendering)
4282		{
4283			const VkRect2D				renderArea				= { { 0, 0 }, { fbExtent.width, fbExtent.height } };
4284			const VkRenderPassBeginInfo	renderPassBeginInfo
4285			{
4286				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
4287				DE_NULL,									// const void*			pNext;
4288				*renderPass,								// VkRenderPass			renderPass;
4289				*frameBuffer,								// VkFramebuffer		framebuffer;
4290				renderArea,									// VkRect2D				renderArea;
4291				1u,											// uint32_t				clearValueCount;
4292				&m_clearValue,								// const VkClearValue*	pClearValues;
4293			};
4294			cmdBeginRenderPass(*m_device, cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
4295		}
4296#ifndef CTS_USES_VULKANSC
4297		else
4298		{
4299			const VkRenderingInfoKHR renderingInfo =
4300			{
4301				VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,				//	VkStructureType						sType;
4302				nullptr,											//	const void*							pNext;
4303				0,													//	VkRenderingFlags					flags;
4304				scissors.at(0u),									//	VkRect2D							renderArea;
4305				m_layerCount,										//	uint32_t							m_layerCount;
4306				layerMask,											//	uint32_t							viewMask;
4307				1u,													//	uint32_t							colorAttachmentCount;
4308				&renderingAttInfo,									//	const VkRenderingAttachmentInfo*	pColorAttachments;
4309				DE_NULL,											//	const VkRenderingAttachmentInfo*	pDepthAttachment;
4310				DE_NULL,											//	const VkRenderingAttachmentInfo*	pStencilAttachment;
4311			};
4312
4313			m_device->cmdBeginRendering(cmdBuffer, &renderingInfo);
4314		}
4315#endif // CTS_USES_VULKANSC
4316
4317		m_device->cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
4318
4319		m_device->cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
4320
4321
4322		if (!m_useDynamicRendering)
4323			cmdEndRenderPass(*m_device, cmdBuffer, m_parameters.renderingType);
4324#ifndef CTS_USES_VULKANSC
4325		else
4326			m_device->cmdEndRendering(cmdBuffer);
4327#endif // CTS_USES_VULKANSC
4328
4329		afterRender(cmdBuffer);
4330
4331		// Copy all image contents to their verification buffers
4332		const auto copyRegion = makeBufferImageCopy(fbExtent, colorSRL);
4333		m_device->cmdCopyImageToBuffer(cmdBuffer, m_colorImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_colorImage->getBuffer(), 1u, &copyRegion);
4334
4335		// Global barrier to synchronize verification buffers to host reads.
4336		{
4337			const auto transfer2HostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
4338			cmdPipelineMemoryBarrier(*m_device, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2HostBarrier);
4339		}
4340
4341		endCommandBuffer(*m_device, cmdBuffer);
4342		submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, cmdBuffer);
4343
4344		// Invalidate all allocations.
4345		invalidateAlloc(*m_device, *m_logicalDevice, m_colorImage->getBufferAllocation());
4346
4347		// Verify all layers in all images.
4348		const auto colorTcuFormat = mapVkFormat(m_parameters.colorFormat);
4349		const auto colorPixelSize = tcu::getPixelSize(colorTcuFormat);
4350		const auto colorLayerSize = static_cast<size_t>(m_dim.x() * m_dim.y() * m_dim.z() * colorPixelSize);
4351
4352		const tcu::UVec4	threshold	(0u, 0u, 0u, 0u); // We expect exact results.
4353		auto&				log			= m_context.getTestContext().getLog();
4354
4355		const auto	dataPtr		= reinterpret_cast<const char*>(m_colorImage->getBufferAllocation().getHostPtr());
4356
4357		for (uint32_t layerIdx = 0u; layerIdx < m_layerCount; ++layerIdx)
4358		{
4359			const bool							layerWritten	=	((layerMask & (1 << layerIdx)) != 0u);
4360			const auto							layerDataPtr	=	dataPtr + colorLayerSize * layerIdx;
4361			const tcu::ConstPixelBufferAccess	layerAccess			(colorTcuFormat, m_dim, layerDataPtr);
4362			const tcu::UVec4					expectedColor	=	(layerWritten
4363																	? tcu::UVec4(layerIdx, 255u, 0, 255u) // Needs to match frag shader.
4364																	: tcu::UVec4(0u, 0u, 0u, 0u));
4365			const std::string					logImgName		=	"ColorAttachment" + std::to_string(0) + "-Subpass" + std::to_string(subpassNdx) + "-Layer" + std::to_string(layerIdx);
4366			tcu::TextureLevel					refLevel			(colorTcuFormat, m_dim.x(), m_dim.y(), m_dim.z());
4367			tcu::PixelBufferAccess				refAccess		=	refLevel.getAccess();
4368
4369			tcu::clear(refAccess, expectedColor);
4370
4371			if (!tcu::intThresholdCompare(log, logImgName.c_str(), "", refAccess, layerAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
4372				failure = true;
4373		}
4374	}
4375
4376	if (failure)
4377		return tcu::TestStatus::fail("Invalid value found in verification buffers; check log for details");
4378
4379	return tcu::TestStatus::pass("Pass");
4380}
4381
4382class MultiViewRenderTestsCase : public vkt::TestCase
4383{
4384public:
4385	MultiViewRenderTestsCase (tcu::TestContext &context, const char *name, const TestParameters& parameters)
4386		: TestCase			(context, name)
4387		, m_parameters		(parameters)
4388	{
4389		DE_ASSERT(m_parameters.extent.width == m_parameters.extent.height);
4390	}
4391private:
4392	const TestParameters	m_parameters;
4393
4394	vkt::TestInstance*	createInstance		(vkt::Context& context) const
4395	{
4396		if (TEST_TYPE_INPUT_ATTACHMENTS == m_parameters.viewIndex ||
4397			TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY == m_parameters.viewIndex)
4398			return new MultiViewAttachmentsTestInstance(context, m_parameters);
4399
4400		if (TEST_TYPE_INSTANCED_RENDERING == m_parameters.viewIndex)
4401			return new MultiViewInstancedTestInstance(context, m_parameters);
4402
4403		if (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
4404			return new MultiViewInputRateInstanceTestInstance(context, m_parameters);
4405
4406		if (TEST_TYPE_DRAW_INDIRECT == m_parameters.viewIndex ||
4407			TEST_TYPE_DRAW_INDIRECT_INDEXED == m_parameters.viewIndex)
4408			return new MultiViewDrawIndirectTestInstance(context, m_parameters);
4409
4410		if (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex)
4411			return new MultiViewClearAttachmentsTestInstance(context, m_parameters);
4412
4413		if (TEST_TYPE_SECONDARY_CMD_BUFFER == m_parameters.viewIndex ||
4414			TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY == m_parameters.viewIndex)
4415			return new MultiViewSecondaryCommandBufferTestInstance(context, m_parameters);
4416
4417		if (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)
4418			return new MultiViewPointSizeTestInstance(context, m_parameters);
4419
4420		if (TEST_TYPE_MULTISAMPLE == m_parameters.viewIndex)
4421			return new MultiViewMultsampleTestInstance(context, m_parameters);
4422
4423		if (TEST_TYPE_QUERIES == m_parameters.viewIndex ||
4424			TEST_TYPE_NON_PRECISE_QUERIES == m_parameters.viewIndex ||
4425			TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY == m_parameters.viewIndex)
4426			return new MultiViewQueriesTestInstance(context, m_parameters);
4427
4428		if (TEST_TYPE_VIEW_MASK == m_parameters.viewIndex ||
4429			TEST_TYPE_VIEW_INDEX_IN_VERTEX == m_parameters.viewIndex ||
4430			TEST_TYPE_VIEW_INDEX_IN_FRAGMENT == m_parameters.viewIndex ||
4431			TEST_TYPE_VIEW_INDEX_IN_GEOMETRY == m_parameters.viewIndex ||
4432			TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex ||
4433			TEST_TYPE_DRAW_INDEXED == m_parameters.viewIndex)
4434			return new MultiViewRenderTestInstance(context, m_parameters);
4435		if (TEST_TYPE_VIEW_MASK_ITERATION == m_parameters.viewIndex)
4436			return new MultiViewMaskIterationTestInstance(context, m_parameters);
4437		if (TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR == m_parameters.viewIndex ||
4438			TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR == m_parameters.viewIndex)
4439			return new MultiViewReadbackTestInstance(context, m_parameters);
4440
4441		if (TEST_TYPE_DEPTH == m_parameters.viewIndex ||
4442			TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex ||
4443			TEST_TYPE_STENCIL == m_parameters.viewIndex)
4444			return new MultiViewDepthStencilTestInstance(context, m_parameters);
4445
4446		TCU_THROW(InternalError, "Unknown test type");
4447	}
4448
4449	virtual void		checkSupport		(Context& context) const
4450	{
4451		if (m_parameters.geometryShaderNeeded())
4452			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
4453
4454		if (m_parameters.renderingType == RENDERING_TYPE_RENDERPASS2)
4455			context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
4456
4457		if (m_parameters.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
4458			context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
4459
4460		context.requireDeviceFunctionality("VK_KHR_multiview");
4461
4462		if (m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
4463			context.requireDeviceFunctionality("VK_EXT_depth_range_unrestricted");
4464		if (m_parameters.viewIndex == TEST_TYPE_QUERIES)
4465			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_OCCLUSION_QUERY_PRECISE);
4466
4467#ifdef CTS_USES_VULKANSC
4468		const InstanceInterface&			instance			= context.getInstanceInterface();
4469		const VkPhysicalDevice				physicalDevice		= context.getPhysicalDevice();
4470		VkPhysicalDeviceMultiviewProperties	multiviewProperties =
4471		{
4472			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,		//VkStructureType	sType;
4473			DE_NULL,													//void*				pNext;
4474			0u,															//deUint32			maxMultiviewViewCount;
4475			0u															//deUint32			maxMultiviewInstanceIndex;
4476		};
4477
4478		VkPhysicalDeviceProperties2			propertiesDeviceProperties2;
4479		propertiesDeviceProperties2.sType						= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4480		propertiesDeviceProperties2.pNext						= &multiviewProperties;
4481
4482		instance.getPhysicalDeviceProperties2(physicalDevice, &propertiesDeviceProperties2);
4483
4484		if (multiviewProperties.maxMultiviewViewCount < m_parameters.viewMasks.size())
4485			TCU_THROW(NotSupportedError, "maxMultiviewViewCount is less than required by test");
4486#endif // CTS_USES_VULKANSC
4487	}
4488
4489	void				initPrograms		(SourceCollections& programCollection) const
4490	{
4491		// Create vertex shader
4492		if (TEST_TYPE_INSTANCED_RENDERING == m_parameters.viewIndex)
4493		{
4494			std::ostringstream source;
4495			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4496					<< "#extension GL_EXT_multiview : enable\n"
4497					<< "layout(location = 0) in highp vec4 in_position;\n"
4498					<< "layout(location = 1) in vec4 in_color;\n"
4499					<< "layout(location = 0) out vec4 out_color;\n"
4500					<< "void main (void)\n"
4501					<< "{\n"
4502					<< "	int modInstance = gl_InstanceIndex % 4;\n"
4503					<< "	int instance    = gl_InstanceIndex + 1;\n"
4504					<< "	gl_Position = in_position;\n"
4505					<< "	if (modInstance == 1)\n"
4506					<< "		gl_Position = in_position + vec4(0.0f, 1.0f, 0.0f, 0.0f);\n"
4507					<< "	if (modInstance == 2)\n"
4508					<< "		gl_Position = in_position + vec4(1.0f, 0.0f, 0.0f, 0.0f);\n"
4509					<< "	if (modInstance == 3)\n"
4510					<< "		gl_Position =  in_position + vec4(1.0f, 1.0f, 0.0f, 0.0f);\n"
4511					<< "	out_color = in_color + vec4(0.0f, gl_ViewIndex * 0.10f, instance * 0.10f, 0.0f);\n"
4512					<< "}\n";
4513			programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4514		}
4515		else if (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
4516		{
4517			std::ostringstream source;
4518			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4519					<< "#extension GL_EXT_multiview : enable\n"
4520					<< "layout(location = 0) in highp vec4 in_position;\n"
4521					<< "layout(location = 1) in vec4 in_color;\n"
4522					<< "layout(location = 0) out vec4 out_color;\n"
4523					<< "void main (void)\n"
4524					<< "{\n"
4525					<< "	int instance = gl_InstanceIndex + 1;\n"
4526					<< "	gl_Position = in_position;\n"
4527					<< "	if (gl_VertexIndex == 1)\n"
4528					<< "		gl_Position.y += 1.0f;\n"
4529					<< "	else if (gl_VertexIndex == 2)\n"
4530					<< "		gl_Position.x += 1.0f;\n"
4531					<< "	else if (gl_VertexIndex == 3)\n"
4532					<< "	{\n"
4533					<< "		gl_Position.x += 1.0f;\n"
4534					<< "		gl_Position.y += 1.0f;\n"
4535					<< "	}\n"
4536					<< "	out_color = in_color + vec4(0.0f, gl_ViewIndex * 0.10f, instance * 0.10f, 0.0f);\n"
4537					<< "}\n";
4538			programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4539		}
4540		else if (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)
4541		{
4542			std::ostringstream source;
4543			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4544					<< "#extension GL_EXT_multiview : enable\n"
4545					<< "layout(location = 0) in highp vec4 in_position;\n"
4546					<< "layout(location = 1) in highp vec4 in_color;\n"
4547					<< "layout(location = 0) out vec4 out_color;\n"
4548					<< "void main (void)\n"
4549					<< "{\n"
4550					<< "	gl_Position = in_position;\n"
4551					<< "	if (gl_ViewIndex == 0)\n"
4552					<< "		gl_PointSize = " << de::floatToString(static_cast<float>(TEST_POINT_SIZE_WIDE), 1) << "f;\n"
4553					<< "	else\n"
4554					<< "		gl_PointSize = " << de::floatToString(static_cast<float>(TEST_POINT_SIZE_SMALL), 1) << "f;\n"
4555					<< "	out_color = in_color;\n"
4556					<< "}\n";
4557			programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4558		}
4559		else if (TEST_TYPE_VIEW_MASK_ITERATION == m_parameters.viewIndex)
4560		{
4561			std::ostringstream source;
4562			source
4563				<< "#version 460\n"
4564				<< "#extension GL_ARB_shader_viewport_layer_array : enable\n"
4565				<< "vec2 positions[3] = vec2[](\n"
4566				<< "    vec2(-1.0, -1.0),\n"
4567				<< "    vec2(-1.0,  3.0),\n"
4568				<< "    vec2( 3.0, -1.0)\n"
4569				<< ");\n"
4570				<< "void main() {\n"
4571				<< "    gl_Position = vec4(positions[gl_VertexIndex % 3], 1.0, 1.0);\n"
4572				<< "}\n"
4573				;
4574			{
4575				const auto						src			= source.str();
4576				const vk::ShaderBuildOptions	spv15Opts	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, false);
4577
4578				programCollection.glslSources.add("vert-spv10") << glu::VertexSource(src);
4579				programCollection.glslSources.add("vert-spv15") << glu::VertexSource(src) << spv15Opts;
4580			}
4581		}
4582		else
4583		{
4584			const bool generateColor	=  (TEST_TYPE_VIEW_INDEX_IN_VERTEX == m_parameters.viewIndex)
4585										|| (TEST_TYPE_DRAW_INDIRECT == m_parameters.viewIndex)
4586										|| (TEST_TYPE_DRAW_INDIRECT_INDEXED == m_parameters.viewIndex)
4587										|| (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex);
4588			std::ostringstream source;
4589			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4590					<< "#extension GL_EXT_multiview : enable\n"
4591					<< "layout(location = 0) in highp vec4 in_position;\n"
4592					<< "layout(location = 1) in vec4 in_color;\n"
4593					<< "layout(location = 0) out vec4 out_color;\n"
4594					<< "void main (void)\n"
4595					<< "{\n"
4596					<< "	gl_Position = in_position;\n";
4597				if (generateColor)
4598					source << "	out_color = in_color + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n";
4599				else
4600					source << "	out_color = in_color;\n";
4601			source	<< "}\n";
4602			programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4603		}
4604
4605		if (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex)
4606		{// Tessellation control & evaluation
4607			std::ostringstream source_tc;
4608			source_tc	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4609						<< "#extension GL_EXT_multiview : enable\n"
4610						<< "#extension GL_EXT_tessellation_shader : require\n"
4611						<< "layout(vertices = 4) out;\n"
4612						<< "layout(location = 0) in vec4 in_color[];\n"
4613						<< "layout(location = 0) out vec4 out_color[];\n"
4614						<< "\n"
4615						<< "void main (void)\n"
4616						<< "{\n"
4617						<< "	if ( gl_InvocationID == 0 )\n"
4618						<< "	{\n"
4619						<< "		gl_TessLevelInner[0] = 4.0f;\n"
4620						<< "		gl_TessLevelInner[1] = 4.0f;\n"
4621						<< "		gl_TessLevelOuter[0] = 4.0f;\n"
4622						<< "		gl_TessLevelOuter[1] = 4.0f;\n"
4623						<< "		gl_TessLevelOuter[2] = 4.0f;\n"
4624						<< "		gl_TessLevelOuter[3] = 4.0f;\n"
4625						<< "	}\n"
4626						<< "	out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
4627						<< "	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
4628						<< "}\n";
4629			programCollection.glslSources.add("tessellation_control") << glu::TessellationControlSource(source_tc.str());
4630
4631			std::ostringstream source_te;
4632			source_te	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4633						<< "#extension GL_EXT_multiview : enable\n"
4634						<< "#extension GL_EXT_tessellation_shader : require\n"
4635						<< "layout( quads, equal_spacing, ccw ) in;\n"
4636						<< "layout(location = 0) in vec4 in_color[];\n"
4637						<< "layout(location = 0) out vec4 out_color;\n"
4638						<< "void main (void)\n"
4639						<< "{\n"
4640						<< "	const float u = gl_TessCoord.x;\n"
4641						<< "	const float v = gl_TessCoord.y;\n"
4642						<< "	const float w = gl_TessCoord.z;\n"
4643						<< "	gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position +(1 - u) * v * gl_in[1].gl_Position + u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n"
4644						<< "	out_color = in_color[0]+ vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4645						<< "}\n";
4646			programCollection.glslSources.add("tessellation_evaluation") << glu::TessellationEvaluationSource(source_te.str());
4647		}
4648
4649		if (m_parameters.geometryShaderNeeded())
4650		{// Geometry Shader
4651			std::ostringstream	source;
4652			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4653					<< "#extension GL_EXT_multiview : enable\n"
4654					<< "layout(triangles) in;\n"
4655					<< "layout(triangle_strip, max_vertices = 16) out;\n"
4656					<< "layout(location = 0) in vec4 in_color[];\n"
4657					<< "layout(location = 0) out vec4 out_color;\n"
4658					<< "void main (void)\n"
4659					<< "{\n"
4660					<< "	out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4661					<< "	gl_Position = gl_in[0].gl_Position;\n"
4662					<< "	EmitVertex();\n"
4663					<< "	out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4664					<< "	gl_Position = gl_in[1].gl_Position;\n"
4665					<< "	EmitVertex();\n"
4666					<< "	out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4667					<< "	gl_Position = gl_in[2].gl_Position;\n"
4668					<< "	EmitVertex();\n"
4669					<< "	out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4670					<< "	gl_Position = vec4(gl_in[2].gl_Position.x, gl_in[1].gl_Position.y, 1.0, 1.0);\n"
4671					<< "	EmitVertex();\n"
4672					<< "	EndPrimitive();\n"
4673					<< "}\n";
4674			programCollection.glslSources.add("geometry") << glu::GeometrySource(source.str());
4675		}
4676
4677		if (TEST_TYPE_INPUT_ATTACHMENTS == m_parameters.viewIndex)
4678		{// Create fragment shader read/write attachment
4679			std::ostringstream source;
4680			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4681					<< "#extension GL_EXT_multiview : enable\n"
4682					<< "layout(location = 0) in vec4 in_color;\n"
4683					<< "layout(location = 0) out vec4 out_color;\n"
4684					<< "layout(input_attachment_index = 0, set=0, binding=0) uniform highp subpassInput in_color_attachment;\n"
4685					<< "void main()\n"
4686					<<"{\n"
4687					<< "	out_color = vec4(subpassLoad(in_color_attachment));\n"
4688					<< "}\n";
4689			programCollection.glslSources.add("fragment") << glu::FragmentSource(source.str());
4690		}
4691		else if (TEST_TYPE_VIEW_MASK_ITERATION == m_parameters.viewIndex)
4692		{
4693			std::ostringstream source;
4694			source	<< "#version 460\n"
4695					<< "#extension " << "GL_EXT_multiview" << " : enable\n"
4696					<< "layout (location=" << 0 << ") out uvec4 color;\n"
4697					<< "void main (void) {\n"
4698					<< "    const uint layerIndex = uint(gl_ViewIndex);\n"
4699					<< "    color = uvec4(layerIndex, 255, " << 0 << ", 255);\n"
4700					<< "}\n"
4701					;
4702			programCollection.glslSources.add("view_mask_iteration") << glu::FragmentSource(source.str());
4703		}
4704		else
4705		{// Create fragment shader
4706			std::ostringstream source;
4707			source	<< glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450)<<"\n"
4708					<< "#extension GL_EXT_multiview : enable\n"
4709					<< "layout(location = 0) in vec4 in_color;\n"
4710					<< "layout(location = 0) out vec4 out_color;\n"
4711					<< "void main()\n"
4712					<<"{\n";
4713				if (TEST_TYPE_VIEW_INDEX_IN_FRAGMENT == m_parameters.viewIndex ||
4714					TEST_TYPE_SECONDARY_CMD_BUFFER == m_parameters.viewIndex)
4715					source << "	out_color = in_color + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n";
4716				else
4717					source << "	out_color = in_color;\n";
4718			source	<< "}\n";
4719			programCollection.glslSources.add("fragment") << glu::FragmentSource(source.str());
4720		}
4721	}
4722};
4723} //anonymous
4724
4725static std::string createViewMasksName(const std::vector<deUint32>& viewMasks)
4726{
4727	std::ostringstream		masks;
4728
4729	for (size_t ndx = 0u; ndx < viewMasks.size(); ++ndx)
4730	{
4731		masks << viewMasks[ndx];
4732		if (viewMasks.size() - 1 != ndx)
4733			masks << "_";
4734	}
4735
4736	return masks.str();
4737}
4738
4739static std::vector<deUint32> tripleDepthStencilMasks(std::vector<deUint32>& baseMasks)
4740{
4741	std::vector<deUint32> tripledMasks(baseMasks);
4742	std::vector<deUint32> partBMasks;
4743
4744	// a,b,c,d  =>  b,c,d,a
4745	partBMasks.insert(partBMasks.end(), baseMasks.begin() + 1, baseMasks.end());
4746	partBMasks.push_back(baseMasks[0]);
4747
4748	tripledMasks.insert(tripledMasks.end(), partBMasks.begin(), partBMasks.end());
4749	tripledMasks.insert(tripledMasks.end(), partBMasks.begin(), partBMasks.end());
4750
4751	return tripledMasks;
4752}
4753
4754void multiViewRenderCreateTests (tcu::TestCaseGroup* group)
4755{
4756	const deUint32				testCaseCount				= 7u;
4757	const string				shaderName[TEST_TYPE_LAST]	=
4758	{
4759		"masks",
4760		"vertex_shader",
4761		"fragment_shader",
4762		"geometry_shader",
4763		"tessellation_shader",
4764		"input_attachments",
4765		"input_attachments_geometry",
4766		"instanced",
4767		"input_instance",
4768		"draw_indirect",
4769		"draw_indirect_indexed",
4770		"draw_indexed",
4771		"clear_attachments",
4772		"secondary_cmd_buffer",
4773		"secondary_cmd_buffer_geometry",
4774		"point_size",
4775		"multisample",
4776		"queries",
4777		"non_precise_queries",
4778		"non_precise_queries_with_availability",
4779		"readback_implicit_clear",
4780		"readback_explicit_clear",
4781		"depth",
4782		"depth_different_ranges",
4783		"stencil",
4784		"view_mask_iteration",
4785	};
4786	const VkExtent3D			extent3D[testCaseCount]		=
4787	{
4788		{16u,	16u,	4u},
4789		{64u,	64u,	8u},
4790		{128u,	128u,	4u},
4791		{32u,	32u,	5u},
4792		{64u,	64u,	6u},
4793		{32u,	32u,	4u},
4794		{16u,	16u,	10u},
4795	};
4796	vector<deUint32>			viewMasks[testCaseCount];
4797
4798	viewMasks[0].push_back(15u);	//1111
4799
4800	viewMasks[1].push_back(8u);		//1000
4801
4802	viewMasks[2].push_back(1u);		//0001
4803	viewMasks[2].push_back(2u);		//0010
4804	viewMasks[2].push_back(4u);		//0100
4805	viewMasks[2].push_back(8u);		//1000
4806
4807	viewMasks[3].push_back(15u);	//1111
4808	viewMasks[3].push_back(15u);	//1111
4809	viewMasks[3].push_back(15u);	//1111
4810	viewMasks[3].push_back(15u);	//1111
4811
4812	viewMasks[4].push_back(8u);		//1000
4813	viewMasks[4].push_back(1u);		//0001
4814	viewMasks[4].push_back(1u);		//0001
4815	viewMasks[4].push_back(8u);		//1000
4816
4817	viewMasks[5].push_back(5u);		//0101
4818	viewMasks[5].push_back(10u);	//1010
4819	viewMasks[5].push_back(5u);		//0101
4820	viewMasks[5].push_back(10u);	//1010
4821
4822	const deUint32 minSupportedMultiviewViewCount	= 6u;
4823	const deUint32 maxViewMask						= (1u << minSupportedMultiviewViewCount) - 1u;
4824
4825	for (deUint32 mask = 1u; mask <= maxViewMask; mask = mask << 1u)
4826		viewMasks[testCaseCount - 1].push_back(mask);
4827
4828	vector<deUint32>			depthStencilMasks;
4829
4830	depthStencilMasks.push_back(3u);	// 0011
4831	depthStencilMasks.push_back(6u);	// 0110
4832	depthStencilMasks.push_back(12u);	// 1100
4833	depthStencilMasks.push_back(9u);	// 1001
4834
4835#ifndef CTS_USES_VULKANSC
4836	int numberOfRenderingTypes = 3;
4837#else
4838	int numberOfRenderingTypes = 2;
4839#endif // CTS_USES_VULKANSC
4840
4841	for (int renderPassTypeNdx = 0; renderPassTypeNdx < numberOfRenderingTypes; ++renderPassTypeNdx)
4842	{
4843		RenderingType				renderPassType	(RENDERING_TYPE_RENDERPASS_LEGACY);
4844		MovePtr<tcu::TestCaseGroup>	targetGroup		(DE_NULL);
4845		tcu::TestCaseGroup*			targetGroupPtr	(group);
4846
4847		if (renderPassTypeNdx == 1)
4848		{
4849			renderPassType	= RENDERING_TYPE_RENDERPASS2;
4850			targetGroup		= MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(group->getTestContext(), "renderpass2"));
4851			targetGroupPtr	= targetGroup.get();
4852		}
4853		else if (renderPassTypeNdx == 2)
4854		{
4855			renderPassType	= RENDERING_TYPE_DYNAMIC_RENDERING;
4856			targetGroup		= MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(group->getTestContext(), "dynamic_rendering"));
4857			targetGroupPtr	= targetGroup.get();
4858		}
4859
4860		tcu::TestContext&			testCtx				(targetGroupPtr->getTestContext());
4861		// ViewIndex rendering tests.
4862		MovePtr<tcu::TestCaseGroup>	groupViewIndex		(new tcu::TestCaseGroup(testCtx, "index"));
4863
4864		for (int testTypeNdx = TEST_TYPE_VIEW_MASK; testTypeNdx < TEST_TYPE_LAST; ++testTypeNdx)
4865		{
4866			MovePtr<tcu::TestCaseGroup>	groupShader			(new tcu::TestCaseGroup(testCtx, shaderName[testTypeNdx].c_str()));
4867			const TestType				testType			= static_cast<TestType>(testTypeNdx);
4868			const VkSampleCountFlagBits	sampleCountFlags	= (testType == TEST_TYPE_MULTISAMPLE) ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT;
4869			VkFormat				colorFormat;
4870
4871			if (testType == TEST_TYPE_MULTISAMPLE)
4872				colorFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
4873			else if (testType == TEST_TYPE_VIEW_MASK_ITERATION)
4874				colorFormat = VK_FORMAT_R8G8B8A8_UINT;
4875			else
4876				colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
4877
4878			// subpassLoad can't be used with dynamic rendering
4879			if ((testTypeNdx == TEST_TYPE_INPUT_ATTACHMENTS) && (renderPassType == RENDERING_TYPE_DYNAMIC_RENDERING))
4880				continue;
4881
4882			if (testTypeNdx == TEST_TYPE_VIEW_MASK_ITERATION)
4883			{
4884				for (deUint32 testCaseNdx = 0u; testCaseNdx < testCaseCount; ++testCaseNdx)
4885				{
4886					const TestParameters	parameters	=	{ extent3D[testCaseNdx], viewMasks[testCaseNdx], testType, sampleCountFlags, colorFormat, QUERY_TYPE_GET_QUERY_POOL_RESULTS, renderPassType };
4887					const std::string		testName	=	createViewMasksName(parameters.viewMasks);
4888
4889					groupShader->addChild(new MultiViewRenderTestsCase(testCtx, testName.c_str(), parameters));
4890				}
4891			}
4892			else
4893			{
4894				for (int queryTypeNdx = 0; queryTypeNdx < 2; ++queryTypeNdx)
4895				{
4896					const std::string queryTestName = queryTypeNdx == 0 ? "get_query_pool_results" : "cmd_copy_query_pool_results";
4897					const auto queryType = queryTypeNdx == 0 ? QUERY_TYPE_GET_QUERY_POOL_RESULTS : QUERY_TYPE_CMD_COPY_QUERY_POOL_RESULTS;
4898					MovePtr<tcu::TestCaseGroup>	queryTypeGroup(new tcu::TestCaseGroup(testCtx, queryTestName.c_str()));
4899
4900					if (testTypeNdx == TEST_TYPE_DEPTH ||
4901						testTypeNdx == TEST_TYPE_DEPTH_DIFFERENT_RANGES ||
4902						testTypeNdx == TEST_TYPE_STENCIL)
4903					{
4904						const VkExtent3D		dsTestExtent3D	= { 64u, 64u, 4u };
4905						const TestParameters	parameters		= { dsTestExtent3D, tripleDepthStencilMasks(depthStencilMasks), testType, sampleCountFlags, colorFormat, queryType, renderPassType };
4906						const std::string		testName		= createViewMasksName(parameters.viewMasks);
4907
4908						queryTypeGroup->addChild(new MultiViewRenderTestsCase(testCtx, testName.c_str(), parameters));
4909					}
4910					else
4911					{
4912						for (deUint32 testCaseNdx = 0u; testCaseNdx < testCaseCount; ++testCaseNdx)
4913						{
4914							const TestParameters	parameters	=	{ extent3D[testCaseNdx], viewMasks[testCaseNdx], testType, sampleCountFlags, colorFormat, queryType, renderPassType };
4915							const std::string		testName	=	createViewMasksName(parameters.viewMasks);
4916
4917							queryTypeGroup->addChild(new MultiViewRenderTestsCase(testCtx, testName.c_str(), parameters));
4918						}
4919
4920						// maxMultiviewViewCount case
4921						{
4922							const VkExtent3D		incompleteExtent3D	= { 16u, 16u, 0u };
4923							const vector<deUint32>	unusedMasks;
4924							const TestParameters	parameters			= { incompleteExtent3D, unusedMasks, testType, sampleCountFlags, colorFormat, queryType, renderPassType };
4925
4926							queryTypeGroup->addChild(new MultiViewRenderTestsCase(testCtx, "max_multi_view_view_count", parameters));
4927						}
4928					}
4929					groupShader->addChild(queryTypeGroup.release());
4930				}
4931			}
4932
4933			switch (testType)
4934			{
4935				case TEST_TYPE_VIEW_MASK:
4936				case TEST_TYPE_INPUT_ATTACHMENTS:
4937				case TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY:
4938				case TEST_TYPE_INSTANCED_RENDERING:
4939				case TEST_TYPE_INPUT_RATE_INSTANCE:
4940				case TEST_TYPE_DRAW_INDIRECT:
4941				case TEST_TYPE_DRAW_INDIRECT_INDEXED:
4942				case TEST_TYPE_DRAW_INDEXED:
4943				case TEST_TYPE_CLEAR_ATTACHMENTS:
4944				case TEST_TYPE_SECONDARY_CMD_BUFFER:
4945				case TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY:
4946				case TEST_TYPE_POINT_SIZE:
4947				case TEST_TYPE_MULTISAMPLE:
4948				case TEST_TYPE_QUERIES:
4949				case TEST_TYPE_NON_PRECISE_QUERIES:
4950				case TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY:
4951				case TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR:
4952				case TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR:
4953				case TEST_TYPE_DEPTH:
4954				case TEST_TYPE_DEPTH_DIFFERENT_RANGES:
4955				case TEST_TYPE_STENCIL:
4956				case TEST_TYPE_VIEW_MASK_ITERATION:
4957					targetGroupPtr->addChild(groupShader.release());
4958					break;
4959				case TEST_TYPE_VIEW_INDEX_IN_VERTEX:
4960				case TEST_TYPE_VIEW_INDEX_IN_FRAGMENT:
4961				case TEST_TYPE_VIEW_INDEX_IN_GEOMETRY:
4962				case TEST_TYPE_VIEW_INDEX_IN_TESELLATION:
4963					groupViewIndex->addChild(groupShader.release());
4964					break;
4965				default:
4966					DE_ASSERT(0);
4967					break;
4968			}
4969		}
4970
4971		targetGroupPtr->addChild(groupViewIndex.release());
4972
4973		if (renderPassType != RENDERING_TYPE_RENDERPASS_LEGACY)
4974			group->addChild(targetGroup.release());
4975	}
4976}
4977
4978} //MultiView
4979} //vkt
4980