1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 ARM Ltd.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief VK_EXT_shader_tile_image tests.
23 *//*--------------------------------------------------------------------*/
24
25// Draw overwrapped patches with incremental value. The last value should be the patch count.
26// Decision is made with comparing between simulated value and result value.
27// All multi sample tests run with per sample shading property except MsaaSampleMask test case.
28// There are several variants.
29//  - Color
30//  - Depth
31//  - Stencil
32//  - Msaa
33//  - Formats
34//  - Draw Count
35//  - Patch Count per Draw
36//  - Coherent Mode
37//  ...
38
39#include "vktShaderTileImageTests.hpp"
40#include "deDefs.hpp"
41#include "deSharedPtr.hpp"
42#include "deUniquePtr.hpp"
43#include "draw/vktDrawBufferObjectUtil.hpp"
44#include "tcuCommandLine.hpp"
45#include "tcuImageCompare.hpp"
46#include "tcuResource.hpp"
47#include "tcuStringTemplate.hpp"
48#include "tcuTestLog.hpp"
49#include "tcuTextureUtil.hpp"
50#include "vkBuilderUtil.hpp"
51#include "vkCmdUtil.hpp"
52#include "vkDefs.hpp"
53#include "vkImageUtil.hpp"
54#include "vkMemUtil.hpp"
55#include "vkObjUtil.hpp"
56#include "vkPrograms.hpp"
57#include "vkQueryUtil.hpp"
58#include "vkRef.hpp"
59#include "vkRefUtil.hpp"
60#include "vkTypeUtil.hpp"
61#include "vktRasterizationTests.hpp"
62#include "vktTestCase.hpp"
63
64using namespace vk;
65using de::MovePtr;
66using de::SharedPtr;
67
68namespace vkt
69{
70
71namespace rasterization
72{
73
74namespace
75{
76
77constexpr deUint32 kImageSize			   = 4; // power of 2 for helper test
78constexpr deUint32 kMultiDrawElementCount  = 3;
79constexpr deUint32 kMultiPatchElementCount = 3;
80constexpr deUint32 kMRTCount			   = 2;
81constexpr uint32_t kDerivative0			   = 1; // derivative 0 + offset 1
82constexpr uint32_t kDerivative1			   = 2; // derivative 1 + offset 1
83
84enum class TestType
85{
86	Color,
87	MultiRenderTarget,
88	MultiRenderTargetDynamicIndex,
89	MsaaSampleMask,
90	HelperClassColor,
91	HelperClassDepth,
92	HelperClassStencil,
93	Depth,
94	Stencil
95};
96
97struct TestParam
98{
99	bool				  coherent;
100	TestType			  testType;
101	VkFormat			  colorFormat;
102	VkFormat			  depthStencilFormat;
103	VkSampleCountFlagBits m_sampleCount;
104	bool				  multipleDrawCalls;
105	bool				  multiplePatchesPerDraw;
106	deUint32			  frameBufferSize;
107};
108
109bool isHelperClassTest(TestType testType)
110{
111	const bool helperClass = (testType == TestType::HelperClassColor) || (testType == TestType::HelperClassDepth) ||
112							 (testType == TestType::HelperClassStencil);
113	return helperClass;
114}
115
116deUint32 getSampleCount(VkSampleCountFlagBits sampleCount)
117{
118	deUint32 ret = 0;
119	switch (sampleCount)
120	{
121	case VK_SAMPLE_COUNT_1_BIT:
122		ret = 1;
123		break;
124	case VK_SAMPLE_COUNT_2_BIT:
125		ret = 2;
126		break;
127	case VK_SAMPLE_COUNT_4_BIT:
128		ret = 4;
129		break;
130	case VK_SAMPLE_COUNT_8_BIT:
131		ret = 8;
132		break;
133	case VK_SAMPLE_COUNT_16_BIT:
134		ret = 16;
135		break;
136	case VK_SAMPLE_COUNT_32_BIT:
137		ret = 32;
138		break;
139	case VK_SAMPLE_COUNT_64_BIT:
140		ret = 64;
141		break;
142	default:
143		DE_ASSERT(false);
144	};
145	return ret;
146}
147
148deUint32 getSampleMask(TestType testType)
149{
150	return (testType == TestType::MsaaSampleMask) ? 0xaaaaaaaa : 0;
151}
152
153deUint32 getColorAttachmentCount(TestType testType)
154{
155	switch (testType)
156	{
157	case TestType::MultiRenderTargetDynamicIndex:
158	case TestType::MultiRenderTarget:
159	case TestType::HelperClassColor:
160	case TestType::HelperClassDepth:
161	case TestType::HelperClassStencil:
162		return kMRTCount;
163	default:
164		return 1;
165	}
166	return 1;
167}
168
169deUint32 getVertexCountPerPatch(const TestParam* testParam)
170{
171	return (testParam->testType == TestType::MsaaSampleMask) ? 3 : 6;
172}
173
174deUint32 getPatchesPerDrawCount(bool multiplePatchesPerDraw)
175{
176	return multiplePatchesPerDraw ? kMultiPatchElementCount : 1;
177}
178
179deUint32 getDrawCallCount(const TestParam* testParam)
180{
181	if (isHelperClassTest(testParam->testType))
182	{
183		// helper class use two draw calls, but it is similar to single draw call
184		DE_ASSERT(!testParam->multipleDrawCalls);
185		return 2;
186	}
187
188	return testParam->multipleDrawCalls ? kMultiDrawElementCount : 1;
189}
190
191bool isNormalizedColorFormat(VkFormat format)
192{
193	const tcu::TextureFormat	   colorFormat(mapVkFormat(format));
194	const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
195	const bool normalizedColorFormat = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
196										channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);
197	return normalizedColorFormat;
198}
199
200void addOverhead(std::stringstream& shaderStream)
201{
202	shaderStream << "{\n"
203				 << "	uint overheadLoop = uint(gl_FragCoord.x) * uint(${TOTAL_PATCH_COUNT} + 1);\n"
204				 << "	zero = patchIndex / (${TOTAL_PATCH_COUNT} + 1);\n"
205				 << "	for(uint index = 0u; index < overheadLoop; index++)\n"
206				 << "	{\n"
207				 << "		zero = uint(sin(float(zero)));\n"
208				 << "	}\n"
209				 << "}\n";
210}
211
212void transition2DImage(const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image,
213					   vk::VkImageAspectFlags aspectMask, vk::VkImageLayout oldLayout, vk::VkImageLayout newLayout,
214					   vk::VkAccessFlags srcAccessMask, vk::VkAccessFlags dstAccessMask,
215					   vk::VkPipelineStageFlags srcStageMask, vk::VkPipelineStageFlags dstStageMask)
216{
217	vk::VkImageMemoryBarrier barrier;
218	barrier.sType							= vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
219	barrier.pNext							= DE_NULL;
220	barrier.srcAccessMask					= srcAccessMask;
221	barrier.dstAccessMask					= dstAccessMask;
222	barrier.oldLayout						= oldLayout;
223	barrier.newLayout						= newLayout;
224	barrier.srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;
225	barrier.dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;
226	barrier.image							= image;
227	barrier.subresourceRange.aspectMask		= aspectMask;
228	barrier.subresourceRange.baseMipLevel	= 0;
229	barrier.subresourceRange.levelCount		= 1;
230	barrier.subresourceRange.baseArrayLayer = 0;
231	barrier.subresourceRange.layerCount		= 1;
232
233	vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (vk::VkDependencyFlags)0, 0,
234						  (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1,
235						  &barrier);
236}
237
238class ShaderTileImageTestCase : public TestCase
239{
240public:
241	ShaderTileImageTestCase(tcu::TestContext& context, const std::string& name, const TestParam& testParam);
242	~ShaderTileImageTestCase() override = default;
243	TestInstance* createInstance(Context& context) const override;
244
245protected:
246	void initPrograms(SourceCollections& programCollection) const override;
247	void checkSupport(Context& context) const override;
248
249	void addVS(SourceCollections& programCollection, const std::map<std::string, std::string>& params) const;
250	void addFS(SourceCollections& programCollection, const std::map<std::string, std::string>& params) const;
251	void addCS(SourceCollections& programCollection, const std::map<std::string, std::string>& params) const;
252
253	void getColorTestTypeFS(std::stringstream& fragShader) const;
254	void getHelperClassTestTypeFS(std::stringstream& fragShader) const;
255	void getSampleMaskTypeFS(std::stringstream& fragShader) const;
256	void getDepthTestTypeFS(std::stringstream& fragShader) const;
257	void getStencilTestTypeFS(std::stringstream& fragShader) const;
258
259protected:
260	const TestParam m_testParam;
261};
262
263class ShaderTileImageTestInstance : public TestInstance
264{
265public:
266	ShaderTileImageTestInstance(Context& context, const TestParam* testParam);
267	~ShaderTileImageTestInstance() override = default;
268	tcu::TestStatus iterate() override;
269
270protected:
271	void			 initialize();
272	void			 generateCmdBuffer();
273	void			 generateVertexBuffer();
274	void			 generateAttachments();
275	Move<VkPipeline> generateGraphicsPipeline(bool disableColor0Write, bool disableDepthWrite,
276											  bool disableStencilWrite);
277	void			 generateComputePipeline();
278	void			 rendering();
279	deUint32		 getResultValue(deUint32 fx, deUint32 fy, deUint32 fs, deUint32 renderTargetID) const;
280	deUint32		 simulate(deUint32 fx, deUint32 fy, deUint32 fs, deUint32 renderTargetID) const;
281	tcu::TestStatus	 checkResult() const;
282
283protected:
284	const TestParam* m_testParam;
285
286	const DeviceInterface&	m_vk;
287	SharedPtr<Draw::Buffer> m_vertexBuffer;
288
289	Move<VkCommandPool>				m_cmdPool;
290	Move<VkCommandBuffer>			m_cmdBuffer;
291	Move<vk::VkDescriptorPool>		m_descriptorPool;
292	Move<vk::VkDescriptorSet>		m_descriptorSets[kMRTCount];
293	Move<VkPipelineLayout>			m_graphicsPipelineLayout;
294	Move<VkPipeline>				m_graphicsPipeline;
295	Move<VkPipeline>				m_graphicsPipelineForHelperClass;
296	Move<vk::VkDescriptorSetLayout> m_computeDescriptorSetLayout;
297	Move<VkPipelineLayout>			m_computePipelineLayout;
298	Move<VkPipeline>				m_computePipeline;
299	Move<VkShaderModule>			m_vertexModule;
300	Move<VkShaderModule>			m_fragmentModule;
301	Move<VkImage>					m_imageColor[kMRTCount];
302	MovePtr<Allocation>				m_imageColorAlloc[kMRTCount];
303	deUint32*						m_imageColorBufferHostPtr;
304	Move<VkImageView>				m_imageColorView[kMRTCount];
305	SharedPtr<Draw::Buffer>			m_imageBuffer[kMRTCount];
306	Move<VkImage>					m_imageDepthStencil;
307	MovePtr<Allocation>				m_imageDepthStencilAlloc;
308	Move<VkImageView>				m_imageDepthStencilView;
309};
310
311ShaderTileImageTestCase::ShaderTileImageTestCase(tcu::TestContext& context, const std::string& name, const TestParam& testParam)
312	: TestCase(context, name), m_testParam(testParam)
313{
314}
315
316void ShaderTileImageTestCase::addVS(SourceCollections&						  programCollection,
317									const std::map<std::string, std::string>& params) const
318{
319	std::stringstream vertShader;
320	vertShader << "#version 450 core\n"
321			   << "precision highp float;\n"
322			   << "precision highp int;\n"
323			   << "layout(location = 0) in highp vec2 v_position;\n"
324			   << "layout(location = 0) flat out uint patchIndex;"
325			   << "layout( push_constant ) uniform ConstBlock\n"
326			   << "{\n"
327			   << "	highp uint drawIndex;\n"
328			   << "};\n"
329			   << "void main ()\n"
330			   << "{\n"
331			   << "	uint localPatchIndex = uint(gl_VertexIndex) / ${VERTEX_COUNT_PER_PATCH} + 1;\n" // index from 1
332			   << "	uint patchCountPerDraw = ${PATCH_COUNT_PER_DRAW};\n"
333			   << "	uint globalPatchIndex = drawIndex * patchCountPerDraw + localPatchIndex;\n"
334			   << "	patchIndex = globalPatchIndex;\n"
335			   << "	gl_Position = vec4(v_position, ${INV_TOTAL_PATCH_COUNT} * globalPatchIndex, 1);\n"
336			   << "}\n";
337
338	tcu::StringTemplate vertShaderTpl(vertShader.str());
339	programCollection.glslSources.add("vert") << glu::VertexSource(vertShaderTpl.specialize(params));
340}
341
342void ShaderTileImageTestCase::getColorTestTypeFS(std::stringstream& fragShader) const
343{
344	const deUint32 attachmentCount		   = getColorAttachmentCount(m_testParam.testType);
345	const bool	   mrtDynamicIndexTestType = (m_testParam.testType == TestType::MultiRenderTargetDynamicIndex);
346	const bool	   multiSampleTest		   = (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT);
347
348	const tcu::TextureFormat	   colorFormat(mapVkFormat(m_testParam.colorFormat));
349	const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
350	const bool					   normalizedColorFormat = isNormalizedColorFormat(m_testParam.colorFormat);
351	const tcu::IVec4			   channelBitDepth		 = tcu::getTextureFormatBitDepth(colorFormat);
352
353	fragShader << "#version 450 core\n"
354			   << "#extension GL_EXT_shader_tile_image : require\n"
355			   << "precision highp float;\n"
356			   << "precision highp int;\n"
357			   << "layout( push_constant ) uniform ConstBlock\n"
358			   << "{\n"
359			   << "	highp uint drawIndex;\n"
360			   << "};\n"
361			   << "layout( location = 0 ) flat in uint patchIndex;\n";
362
363	if (!m_testParam.coherent)
364	{
365		fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
366	}
367
368	if (mrtDynamicIndexTestType)
369	{
370		// layout( location = 0 ) tileImageEXT highp attachmentEXT colorIn[0]
371		fragShader << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn[${ATTACHMENT_COUNT}];\n";
372	}
373	else
374	{
375		for (deUint32 i = 0; i < attachmentCount; i++)
376		{
377			// layout( location = 0 ) tileImageEXT highp attachmentEXT colorIn0
378			fragShader << "layout( location = " << i << ") tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn" << i << ";\n";
379		}
380	}
381
382	for (deUint32 i = 0; i < attachmentCount; i++)
383	{
384		// layout( location = 0 ) out highp vec4 out0
385		fragShader << "layout( location = " << i << " ) out highp ${OUTPUT_VECTOR_NAME} out" << i << ";\n";
386	}
387
388	fragShader << "void main()\n"
389			   << "{\n"
390			   << "	uint zero = 0;\n"
391			   << "	uvec2 previous[${ATTACHMENT_COUNT}];\n";
392
393	float amplifier = 1.0f;
394	if (normalizedColorFormat)
395	{
396		amplifier = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) ?
397						static_cast<float>(1 << (channelBitDepth.y() - 1)) : // signed
398						static_cast<float>((1 << channelBitDepth.y()) - 1);	 // unsigned
399
400		// color output precision is less than test case;
401		DE_ASSERT(amplifier > static_cast<float>(kMultiPatchElementCount * kMultiDrawElementCount * attachmentCount +
402												 getSampleCount(m_testParam.m_sampleCount)));
403	}
404
405	for (deUint32 i = 0; i < attachmentCount; i++)
406	{
407		// in0 or colorIn[0]
408		const std::string inputImage =
409			mrtDynamicIndexTestType ? "colorIn[" + std::to_string(i) + "]" : "colorIn" + std::to_string(i);
410
411		// (in0) or (colorIn0, gl_SampleID)
412		const std::string funcParams = multiSampleTest ? "(" + inputImage + ", gl_SampleID)" : "(" + inputImage + ")";
413
414		if (normalizedColorFormat)
415		{
416			// previous[0] = round(colorAttachmentRead(in0) *  amplifier).xy;\n";
417			fragShader << "	previous[" << i << "] = uvec2(round((colorAttachmentReadEXT" << funcParams << " * "
418					   << amplifier << ").xy));\n";
419		}
420		else
421		{
422			// previous[0] *= uvec2(round(colorAttachmentRead(in0).xy));\n";
423			fragShader << "	previous[" << i << "] = uvec2(round((colorAttachmentReadEXT" << funcParams << ").xy));\n";
424		}
425	}
426
427	// add overhead after fetching data
428	addOverhead(fragShader);
429
430	// used only for normalized color format
431	const float invAmplifier = 1.0f / static_cast<float>(amplifier);
432
433	// write output
434	for (deUint32 i = 0; i < attachmentCount; i++)
435	{
436		// if (previous[0].x == 0 && patchIndex == 1)", initial write
437		//  out0.y = float(patchIndex + zero + gl_SampleID +  0);"
438		// else if (previous[0].x == 0 && (previous[0].y + 1) == (patchIndex + gl_SampleID + 0))"
439		//  out0.y = float(previous[0].y + 1);"
440		// else
441		//  out0.y = float(previous[0].y);"
442		//  out0.x = 1;" // error
443		fragShader << "	if (previous[" << i << "].x == 0 && patchIndex == 1)\n"
444				   << "	{\n"
445				   << "		out" << i << ".y = ${OUTPUT_BASIC_TYPE}(patchIndex + zero + gl_SampleID + " << i << ");\n"
446				   << "	}\n"
447				   << "	else if (previous[" << i << "].x == 0 && (previous[" << i
448				   << "].y + 1) == (patchIndex + gl_SampleID + " << i << "))\n"
449				   << "	{\n"
450				   << "		out" << i << ".y = ${OUTPUT_BASIC_TYPE}(previous[" << i << "].y + 1 + zero);\n"
451				   << "	}\n"
452				   << "	else\n"
453				   << "	{\n"
454				   << "		out" << i << ".y = ${OUTPUT_BASIC_TYPE}(previous[" << i << "].y);\n" // for debug purpose
455				   << "		out" << i << ".x = 1;\n"											 // error
456				   << "	}\n";
457
458		if (normalizedColorFormat)
459		{
460			// out0.y *= invAmplifier;
461			fragShader << "		out" << i << ".y *= " << invAmplifier << ";\n";
462		}
463	}
464	fragShader << "}\n";
465}
466
467void ShaderTileImageTestCase::getHelperClassTestTypeFS(std::stringstream& fragShader) const
468{
469	const bool depthHelperClassTest	  = (m_testParam.testType == TestType::HelperClassDepth);
470	const bool stencilHelperClassTest = (m_testParam.testType == TestType::HelperClassStencil);
471
472	DE_ASSERT(getPatchesPerDrawCount(!m_testParam.multiplePatchesPerDraw));
473	DE_ASSERT(getDrawCallCount(&m_testParam) == 2);
474	DE_ASSERT(getColorAttachmentCount(m_testParam.testType) == 2);
475	DE_ASSERT((m_testParam.m_sampleCount == VK_SAMPLE_COUNT_1_BIT));
476	DE_ASSERT(!isNormalizedColorFormat(m_testParam.colorFormat));
477
478	fragShader << "#version 450 core\n"
479			   << "#extension GL_EXT_shader_tile_image : require\n"
480			   << "precision highp float;\n"
481			   << "precision highp int;\n"
482			   << "layout( push_constant ) uniform ConstBlock\n"
483			   << "{\n"
484			   << "	highp uint drawIndex;\n"
485			   << "};\n"
486			   << "layout( location = 0 ) flat in uint patchIndex;\n";
487
488	if (!m_testParam.coherent)
489	{
490		fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
491		if (depthHelperClassTest)
492		{
493			fragShader << "layout( non_coherent_depth_attachment_readEXT ) in;\n";
494		}
495
496		if (stencilHelperClassTest)
497		{
498			fragShader << "layout( non_coherent_stencil_attachment_readEXT ) in;\n";
499		}
500	}
501
502	fragShader << "layout(location = 0) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n";
503	fragShader << "layout(location = 1) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn1;\n";
504
505	fragShader << "layout(location = 0) out highp ${OUTPUT_VECTOR_NAME} out0;\n";
506	fragShader << "layout(location = 1) out highp ${OUTPUT_VECTOR_NAME} out1;\n";
507
508	fragShader << "void main()\n"
509			   << "{\n"
510			   << "	uint zero = 0;\n"
511			   << "	uvec2 previous;\n";
512
513	if (depthHelperClassTest)
514	{
515		fragShader << " uint scalingFactor = ${TOTAL_PATCH_COUNT};\n";
516		fragShader << "	previous.x = uint(round(colorAttachmentReadEXT(colorIn0).x));\n";		// read error status
517		fragShader << "	previous.y = uint(round(depthAttachmentReadEXT() * scalingFactor));\n"; // read depth value
518	}
519	else if (stencilHelperClassTest)
520	{
521		fragShader << "	previous.x = uint(round(colorAttachmentReadEXT(colorIn0).x));\n"; // read error status
522		fragShader << "	previous.y = uint(stencilAttachmentReadEXT());\n";				  // read stencil value
523	}
524	else
525	{
526		fragShader << "	previous = uvec2(round((colorAttachmentReadEXT(colorIn0)).xy));\n";
527	}
528
529	{
530		// draw only one triangle for helperClassTestType, dx or dy should be 0 inside of triangle.
531		// And they should be patchIndex in the diagonal edge of triangle.
532		fragShader << "	uint err = 0;\n"
533				   << "	uint dx = 0;\n"
534				   << "	uint dy = 0;\n"
535				   << "	if (patchIndex != 1)"
536				   << "	{\n"
537				   << "		dx = uint(round(abs(dFdxFine(previous.y))));\n"
538				   << "		dy = uint(round(abs(dFdyFine(previous.y))));\n"
539				   << "		uint err = 0;\n"
540				   << "		if ((dx != 0 && dx != patchIndex - 1) || (dy != 0 && dy != patchIndex - 1))\n"
541				   << "		{\n"
542				   << "			err = 1;\n" // first draw doesn't have error check.
543				   << "		}\n"
544				   << "	}\n";
545	}
546
547	// add overhead after fetching data
548	addOverhead(fragShader);
549
550	// first draw writes to attachment0
551	// second draw reads from attachment0(depth) writes to attachment1
552	{
553		fragShader << "	if (patchIndex == 1 && err != 1)\n"
554				   << "	{\n"
555				   << "		out0.y = ${OUTPUT_BASIC_TYPE}(patchIndex);\n"
556				   << "		out0.x = 0;\n" // error
557				   << "	}\n"
558				   << "	else if (previous.x == 0 && err != 1 && ((previous.y + 1) == patchIndex || previous.y == 0))\n"
559				   << "	{\n"
560				   << "		out1.y = ${OUTPUT_BASIC_TYPE}(max(dx, dy) + 1);\n" // last 1 is to differentiate clear value
561				   << "	}\n"
562				   << "	else\n"
563				   << "	{\n"
564				   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previous.y);\n" // for debug purpose
565				   << "		out0.x = 1;\n"								  // error
566				   << "		out1.y = ${OUTPUT_BASIC_TYPE}(previous.x);\n"
567				   << "		out1.x = 1;\n" // error
568				   << "	}\n";
569	}
570	fragShader << "}\n";
571}
572
573void ShaderTileImageTestCase::getSampleMaskTypeFS(std::stringstream& fragShader) const
574{
575	const deUint32 sampleCount = getSampleCount(m_testParam.m_sampleCount);
576
577	const tcu::TextureFormat	   colorFormat(mapVkFormat(m_testParam.colorFormat));
578	const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
579	const bool					   normalizedColorFormat = isNormalizedColorFormat(m_testParam.colorFormat);
580	const tcu::IVec4			   channelBitDepth		 = tcu::getTextureFormatBitDepth(colorFormat);
581
582	deUint32 amplifier = 1;
583	if (normalizedColorFormat)
584	{
585		amplifier = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) ?
586						(1 << (channelBitDepth.y() - 1)) : // signed
587						((1 << channelBitDepth.y()) - 1);  // unsigned
588	}
589
590	// Samples which is not covered should be 0
591	fragShader << "#version 450 core\n"
592			   << "#extension GL_EXT_shader_tile_image : require\n"
593			   << "precision highp float;\n"
594			   << "precision highp int;\n"
595			   << "layout( push_constant ) uniform ConstBlock\n"
596			   << "{\n"
597			   << "	highp uint drawIndex;\n"
598			   << "};\n";
599	if (!m_testParam.coherent)
600	{
601		fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
602	}
603	fragShader << "layout( location = 0 ) flat in uint patchIndex;\n"
604			   << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n"
605			   << "layout( location = 0 ) out highp ${OUTPUT_VECTOR_NAME} out0;\n"
606			   << "\n"
607			   << "void main()\n"
608			   << "{\n"
609			   << "	uint zero = 0;\n"
610			   << "	uint previous = 0;\n"
611			   << "	bool error = false;\n"
612			   << "	for (int i = 0; i < " << sampleCount << "; ++i)\n"
613			   << "	{\n"
614			   << "		if (((gl_SampleMaskIn[0] >> i) & 0x1) == 0x1)\n"
615			   << "		{\n"
616			   << "			uvec2 previousSample = uvec2(round(colorAttachmentReadEXT"
617			   << "(colorIn0, i) * " << amplifier << ")).xy;\n"
618			   << "			if (previousSample.x != 0)\n"
619			   << "			{\n"
620			   << "				error = true;\n"
621			   << "				break;"
622			   << "			}\n"
623			   << "			if (previous == 0)\n"
624			   << "			{\n"
625			   << "				previous = previousSample.y;\n" // write non zero value to the covered sample
626			   << "			}\n"
627			   << "\n"
628			   << "			if ((patchIndex != 1 && previousSample.y == 0) || previous != previousSample.y)\n"
629			   << "			{\n"
630			   << "				error = true;\n"
631			   << "				break;\n"
632			   << "			}\n"
633			   << "		}\n"
634			   << "	}\n"
635			   << "\n";
636
637	// add overhead after fetching data
638	addOverhead(fragShader);
639
640	// write output
641	fragShader << "if (!error && (previous + 1 == patchIndex))\n"
642			   << "	{\n"
643			   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previous + 1 + zero);\n"
644			   << "	}\n"
645			   << "	else\n"
646			   << "	{\n"
647			   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previous);\n"
648			   << "		out0.x = 1;\n" // error
649			   << "	}\n";
650
651	const float invAmplifier = 1.0f / static_cast<float>(amplifier);
652	if (normalizedColorFormat)
653	{
654		fragShader << "		out0.y *= " << invAmplifier << ";\n";
655	}
656
657	fragShader << "}\n";
658}
659
660void ShaderTileImageTestCase::getDepthTestTypeFS(std::stringstream& fragShader) const
661{
662	const bool		  multiSampleTest = (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT);
663	const std::string depthFuncParams = multiSampleTest ? "(gl_SampleID)" : "()";
664	const std::string colorFuncParams = multiSampleTest ? "(colorIn0, gl_SampleID)" : "(colorIn0)";
665	const deUint32	  sampleCount	  = getSampleCount(m_testParam.m_sampleCount);
666
667	fragShader << "#version 450 core\n"
668			   << "#extension GL_EXT_shader_tile_image : require\n"
669			   << "precision highp float;\n"
670			   << "precision highp int;\n"
671			   << "layout( push_constant ) uniform ConstBlock\n"
672			   << "{\n"
673			   << "	highp uint drawIndex;\n"
674			   << "};\n";
675	if (!m_testParam.coherent)
676	{
677		fragShader << "layout( non_coherent_depth_attachment_readEXT ) in;\n";
678		fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
679	}
680	fragShader << "layout( location = 0 ) flat in uint patchIndex;\n"
681			   << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n"
682			   << "layout( location = 0 ) out highp ${OUTPUT_VECTOR_NAME} out0;\n"
683			   << "\n"
684			   << "void main()\n"
685			   << "{\n"
686			   << "	uint zero = 0;\n"
687			   << " uint scalingFactor = ${TOTAL_PATCH_COUNT};\n";
688	if (multiSampleTest)
689	{
690		// scaling with (patch count + sample count) for multisample case
691		fragShader << " scalingFactor += " << sampleCount << ";\n";
692	}
693	fragShader << "	uint previousDepth = uint(round(depthAttachmentReadEXT" << depthFuncParams
694			   << " * scalingFactor));\n"
695			   << "	${OUTPUT_VECTOR_NAME} previous = ${OUTPUT_VECTOR_NAME}(round(colorAttachmentReadEXT"
696			   << colorFuncParams << "));\n";
697
698	// add overhead after fetching data
699	addOverhead(fragShader);
700
701	// write output
702	fragShader << "	if (previous.x == 0 && patchIndex == 1)\n"
703			   << "	{\n"
704			   << "		out0.y = (1u + zero + gl_SampleID);\n"
705			   << "	}\n"
706			   << "	else if (previous.x == 0 && (previous.y + 1) == (patchIndex + gl_SampleID) && (previousDepth + 1) "
707				  "== (patchIndex + gl_SampleID))\n"
708			   << "	{\n"
709			   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previousDepth + 1 + zero);\n"
710			   << "	}\n"
711			   << "	else\n"
712			   << "	{\n"
713			   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previousDepth);\n" // debug purpose
714			   << "		out0.x = 1;\n"									 // error
715			   << "	}\n";
716
717	if (multiSampleTest)
718	{
719		// Depth value is written without adding SampleID.
720		// Forcely write all fragment depth
721		fragShader << " gl_FragDepth = float(out0.y) / scalingFactor;\n";
722	}
723
724	fragShader << "}\n";
725}
726
727void ShaderTileImageTestCase::getStencilTestTypeFS(std::stringstream& fragShader) const
728{
729	const bool		  multiSampleTest	= (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT);
730	const std::string stencilFuncParams = multiSampleTest ? "(gl_SampleID)" : "()";
731	const std::string colorFuncParams	= multiSampleTest ? "(colorIn0, gl_SampleID)" : "(colorIn0)";
732
733	fragShader << "#version 450 core\n"
734			   << "#extension GL_EXT_shader_tile_image : require\n"
735			   << "precision highp float;\n"
736			   << "precision highp int;\n"
737			   << "layout( push_constant ) uniform ConstBlock\n"
738			   << "{\n"
739			   << "	highp uint drawIndex;\n"
740			   << "};\n";
741	if (!m_testParam.coherent)
742	{
743		fragShader << "layout( non_coherent_stencil_attachment_readEXT ) in;\n";
744		fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
745	}
746	fragShader << "layout( location = 0 ) flat in uint patchIndex;\n"
747			   << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n"
748			   << "layout( location = 0 ) out highp ${OUTPUT_VECTOR_NAME} out0;\n"
749			   << "\n"
750			   << "void main()\n"
751			   << "{\n"
752			   << "	uint zero = 0;\n"
753			   << "	uint previousStencil = uint(round(stencilAttachmentReadEXT" << stencilFuncParams << " ));\n"
754			   << "	${OUTPUT_VECTOR_NAME} previous = ${OUTPUT_VECTOR_NAME}(round(colorAttachmentReadEXT"
755			   << colorFuncParams << "));\n";
756
757	// add overhead after fetching data
758	addOverhead(fragShader);
759
760	// write output
761	fragShader << "	if (previous.x == 0 && (previous.y + 1) == patchIndex && (previousStencil + 1) == patchIndex)\n"
762			   << "	{\n"
763			   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previousStencil + 1 + zero);\n"
764			   << "	}\n"
765			   << "	else\n"
766			   << "	{\n"
767			   << "		out0.y = ${OUTPUT_BASIC_TYPE}(previousStencil);\n" // debug purpose
768			   << "		out0.x = 1;\n"									   // error
769			   << "	}\n"
770			   << "}\n";
771}
772
773void rasterization::ShaderTileImageTestCase::addFS(SourceCollections&						 programCollection,
774												   const std::map<std::string, std::string>& params) const
775{
776	std::stringstream fragShader;
777
778	switch (m_testParam.testType)
779	{
780	case TestType::Color:
781	case TestType::MultiRenderTarget:
782	case TestType::MultiRenderTargetDynamicIndex:
783		getColorTestTypeFS(fragShader);
784		break;
785	case TestType::HelperClassColor:
786	case TestType::HelperClassDepth:
787	case TestType::HelperClassStencil:
788		getHelperClassTestTypeFS(fragShader);
789		break;
790	case TestType::MsaaSampleMask:
791		getSampleMaskTypeFS(fragShader);
792		break;
793	case TestType::Depth:
794		getDepthTestTypeFS(fragShader);
795		break;
796	case TestType::Stencil:
797		getStencilTestTypeFS(fragShader);
798		break;
799	default:
800		DE_ASSERT(true);
801	}
802
803	tcu::StringTemplate fragShaderTpl(fragShader.str());
804	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
805}
806
807// Copy Image to Buffer using Compute Shader for handling multi sample cases
808void ShaderTileImageTestCase::addCS(SourceCollections&						  programCollection,
809									const std::map<std::string, std::string>& params) const
810{
811	std::stringstream compShader;
812
813	const deUint32	  sampleCount = getSampleCount(m_testParam.m_sampleCount);
814	const std::string fsampler	  = sampleCount > 1 ? "texture2DMS" : "texture2D";
815	const std::string usampler	  = sampleCount > 1 ? "utexture2DMS" : "utexture2D";
816	const std::string isampler	  = sampleCount > 1 ? "itexture2DMS" : "itexture2D";
817
818	const tcu::TextureFormat	   colorFormat(mapVkFormat(m_testParam.colorFormat));
819	const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
820	const tcu::IVec4			   channelBitDepth		 = tcu::getTextureFormatBitDepth(colorFormat);
821	const bool					   normalizedColorFormat = isNormalizedColorFormat(m_testParam.colorFormat);
822
823	std::string sampler;
824	switch (channelClass)
825	{
826	case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
827		sampler = usampler;
828		break;
829	case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
830		sampler = isampler;
831		break;
832	default:
833		sampler = fsampler;
834	}
835
836	deUint32 amplifier = 1;
837
838	if (normalizedColorFormat)
839	{
840		amplifier = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) ?
841						(1 << (channelBitDepth.y() - 1)) : // signed
842						((1 << channelBitDepth.y()) - 1);  // unsigned
843	}
844
845	// Compute shader copies color to linear layout in buffer memory
846	compShader << "#version 450 core\n"
847			   << "#extension GL_EXT_samplerless_texture_functions : enable\n"
848			   << "precision highp float;\n"
849			   << "precision highp int;\n"
850			   << "layout(set = 0, binding = 0) uniform " << sampler << " colorTex;\n"
851			   << "layout(set = 0, binding = 1, std430) buffer Block0 { uvec2 values[]; } colorbuf;\n"
852			   << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
853			   << "void main()\n"
854			   << "{\n"
855			   << "	for (uint i = 0u; i < " << sampleCount << "u; ++i) {\n"
856			   << "		uint idx = ((gl_GlobalInvocationID.y * " << m_testParam.frameBufferSize
857			   << "u) + gl_GlobalInvocationID.x) * " << sampleCount << "u + i;\n";
858
859	if (normalizedColorFormat)
860	{
861		compShader << "		colorbuf.values[idx].y = uint(round(texelFetch(colorTex, ivec2(gl_GlobalInvocationID.xy), "
862					  "int(i)).y * "
863				   << amplifier << "));\n";
864		compShader << "		colorbuf.values[idx].x = uint(round(texelFetch(colorTex, ivec2(gl_GlobalInvocationID.xy), "
865					  "int(i)).x));\n";
866	}
867	else
868	{
869		compShader << "		colorbuf.values[idx] = uvec2(round(vec2(texelFetch(colorTex, "
870					  "ivec2(gl_GlobalInvocationID.xy), int(i)).xy)));\n";
871	}
872
873	compShader << "	}\n"
874			   << "}\n";
875
876	tcu::StringTemplate computeShaderTpl(compShader.str());
877	programCollection.glslSources.add("comp") << glu::ComputeSource(computeShaderTpl.specialize(params));
878}
879
880void ShaderTileImageTestCase::initPrograms(SourceCollections& programCollection) const
881{
882	std::map<std::string, std::string> params;
883
884	const deUint32				   drawCount		 = getDrawCallCount(&m_testParam);
885	const deUint32				   patchCountPerDraw = getPatchesPerDrawCount(m_testParam.multiplePatchesPerDraw);
886	const deUint32				   attachmentCount	 = getColorAttachmentCount(m_testParam.testType);
887	const tcu::TextureFormat	   colorFormat(mapVkFormat(m_testParam.colorFormat));
888	const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
889
890	params["VERTEX_COUNT_PER_PATCH"] = std::to_string(getVertexCountPerPatch(&m_testParam));
891	params["PATCH_COUNT_PER_DRAW"]	 = std::to_string(patchCountPerDraw);
892	params["INV_TOTAL_PATCH_COUNT"]	 = std::to_string(1.0f / static_cast<float>(drawCount * patchCountPerDraw));
893	params["TOTAL_PATCH_COUNT"]		 = std::to_string(drawCount * patchCountPerDraw);
894	params["ATTACHMENT_COUNT"]		 = std::to_string(attachmentCount);
895
896	std::string strVecName;
897	std::string strBasicType;
898	std::string strTileImageType;
899
900	switch (channelClass)
901	{
902	case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
903		strVecName		 = "uvec";
904		strTileImageType = "uattachmentEXT";
905		strBasicType	 = "uint";
906		break;
907	case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
908		strVecName		 = "ivec";
909		strTileImageType = "iattachmentEXT";
910		strBasicType	 = "int";
911		break;
912	default:
913		strVecName		 = "vec";
914		strTileImageType = "attachmentEXT";
915		strBasicType	 = "float";
916	}
917	params["OUTPUT_VECTOR_NAME"] = strVecName + std::to_string(tcu::getNumUsedChannels(colorFormat.order));
918	params["OUTPUT_BASIC_TYPE"]	 = strBasicType;
919	params["TILE_IMAGE_TYPE"]	 = strTileImageType;
920
921	addVS(programCollection, params);
922	addFS(programCollection, params);
923	addCS(programCollection, params);
924}
925
926TestInstance* ShaderTileImageTestCase::createInstance(Context& context) const
927{
928	return new ShaderTileImageTestInstance(context, &m_testParam);
929}
930
931void ShaderTileImageTestCase::checkSupport(Context& context) const
932{
933	if (!context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"))
934	{
935		TCU_THROW(NotSupportedError, "VK_KHR_dynamic_rendering not supported");
936	}
937
938	if (!context.requireDeviceFunctionality("VK_EXT_shader_tile_image"))
939	{
940		TCU_THROW(NotSupportedError, "VK_EXT_shader_tile_image not supported");
941	}
942	/* sampleRateShading must be enabled to call fragment shader for all the samples in multisampling */
943	VkPhysicalDeviceShaderTileImageFeaturesEXT shaderTileImageFeature = {};
944	shaderTileImageFeature.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT;
945
946	VkPhysicalDeviceFeatures  features	= {};
947	VkPhysicalDeviceFeatures2 features2 = {};
948	features2.sType						= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
949	features2.pNext						= &shaderTileImageFeature;
950
951	context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
952	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
953
954	if (!shaderTileImageFeature.shaderTileImageColorReadAccess)
955	{
956		TCU_THROW(NotSupportedError, "color read access of VK_EXT_shader_tile_image is not supported");
957	}
958	switch (m_testParam.testType)
959	{
960	case TestType::Depth:
961	case TestType::HelperClassDepth:
962		if (!shaderTileImageFeature.shaderTileImageDepthReadAccess)
963		{
964			TCU_THROW(NotSupportedError, "depth read access of VK_EXT_shader_tile_image is not supported");
965		}
966		break;
967	case TestType::Stencil:
968	case TestType::HelperClassStencil:
969		if (!shaderTileImageFeature.shaderTileImageStencilReadAccess)
970		{
971			TCU_THROW(NotSupportedError, "stencil read access of VK_EXT_shader_tile_image is not supported");
972		}
973		break;
974	case TestType::Color:
975	case TestType::MultiRenderTarget:
976	case TestType::MultiRenderTargetDynamicIndex:
977	case TestType::MsaaSampleMask:
978	case TestType::HelperClassColor:
979		break;
980	default:
981		DE_ASSERT(0);
982	}
983
984	VkPhysicalDeviceVulkan12Properties vulkan12Properties = {};
985	vulkan12Properties.sType							  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
986
987	VkPhysicalDeviceShaderTileImagePropertiesEXT shaderTileImageProperties = {};
988	shaderTileImageProperties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT;
989	shaderTileImageProperties.pNext = &vulkan12Properties;
990
991	VkPhysicalDeviceProperties2 properties = {};
992	properties.sType					   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
993	properties.pNext					   = &shaderTileImageProperties;
994
995	context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
996
997	// shaderTileImageReadSampleFromPixelRateInvocation is a boolean that will be VK_TRUE if reading from samples from a
998	// pixel rate fragment invocation is supported when VkPipelineMultisampleStateCreateInfo::rasterizationSamples > 1.
999	// shaderTileImageReadFromHelperInvocation is a boolean that will be VK_TRUE if reads of tile image data from helper
1000	// fragment invocations result in valid values.
1001	if (!shaderTileImageProperties.shaderTileImageReadSampleFromPixelRateInvocation)
1002	{
1003		if (m_testParam.testType == TestType::MsaaSampleMask)
1004		{
1005			TCU_THROW(NotSupportedError, "multi-samples pixel access of VK_EXT_shader_tile_image is not supported");
1006		}
1007	}
1008
1009	if (!shaderTileImageProperties.shaderTileImageReadFromHelperInvocation)
1010	{
1011		if (isHelperClassTest(m_testParam.testType))
1012		{
1013			TCU_THROW(NotSupportedError, "helper class fragments access of VK_EXT_shader_tile_image is not supported");
1014		}
1015	}
1016
1017	const tcu::TextureFormat	   colorFormat(mapVkFormat(m_testParam.colorFormat));
1018	const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
1019	if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ||
1020		channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1021	{
1022		if ((vulkan12Properties.framebufferIntegerColorSampleCounts & m_testParam.m_sampleCount) == 0 ||
1023			(properties.properties.limits.sampledImageIntegerSampleCounts & m_testParam.m_sampleCount) == 0)
1024		{
1025			TCU_THROW(NotSupportedError, "Sample count not supported");
1026		}
1027	}
1028	else
1029	{
1030		if ((properties.properties.limits.framebufferColorSampleCounts & m_testParam.m_sampleCount) == 0 ||
1031			(properties.properties.limits.sampledImageColorSampleCounts & m_testParam.m_sampleCount) == 0)
1032		{
1033			TCU_THROW(NotSupportedError, "Sample count not supported");
1034		}
1035	}
1036
1037	if (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT && m_testParam.testType != TestType::MsaaSampleMask &&
1038		!features.sampleRateShading)
1039	{
1040		TCU_THROW(NotSupportedError, "sampleRateShading feature not supported");
1041	}
1042
1043	const deUint32 attachmentCount = getColorAttachmentCount(m_testParam.testType);
1044
1045	if (properties.properties.limits.maxFragmentOutputAttachments < attachmentCount ||
1046		properties.properties.limits.maxPerStageDescriptorInputAttachments < attachmentCount)
1047	{
1048		TCU_THROW(NotSupportedError, "attachment number not supported");
1049	}
1050
1051	const InstanceInterface& vki			= context.getInstanceInterface();
1052	VkPhysicalDevice		 physicalDevice = context.getPhysicalDevice();
1053	const VkFormatProperties colorFormatProperties(
1054		getPhysicalDeviceFormatProperties(vki, physicalDevice, m_testParam.colorFormat));
1055	const VkFormatProperties dsFormatProperties(
1056		getPhysicalDeviceFormatProperties(vki, physicalDevice, m_testParam.depthStencilFormat));
1057
1058	if ((colorFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
1059	{
1060		TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
1061	}
1062
1063	if ((dsFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
1064	{
1065		TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
1066	}
1067}
1068
1069ShaderTileImageTestInstance::ShaderTileImageTestInstance(Context& context, const TestParam* testParam)
1070	: TestInstance(context), m_testParam(testParam), m_vk(m_context.getDeviceInterface())
1071{
1072	initialize();
1073}
1074
1075void ShaderTileImageTestInstance::initialize()
1076{
1077	generateCmdBuffer();
1078	generateAttachments();
1079	generateVertexBuffer();
1080	m_graphicsPipeline				 = generateGraphicsPipeline(false, false, false);
1081	m_graphicsPipelineForHelperClass = generateGraphicsPipeline(true, true, true);
1082	generateComputePipeline();
1083}
1084
1085void ShaderTileImageTestInstance::generateComputePipeline()
1086{
1087	const deUint32 attachmentSize = getColorAttachmentCount(m_testParam->testType);
1088	const VkDevice device		  = m_context.getDevice();
1089
1090	const Unique<VkShaderModule> cs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("comp"), 0));
1091
1092	VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
1093
1094	const VkDescriptorSetLayoutBinding bindings[] = {
1095		{
1096			0,								  // binding
1097			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1098			1,								  // descriptorCount
1099			VK_SHADER_STAGE_COMPUTE_BIT,	  // stageFlags
1100			DE_NULL,						  // pImmutableSamplers
1101		},
1102		{
1103			1,								   // binding
1104			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1105			1,								   // descriptorCount
1106			VK_SHADER_STAGE_COMPUTE_BIT,	   // stageFlags
1107			DE_NULL,						   // pImmutableSamplers
1108		},
1109	};
1110
1111	// Create a layout and allocate a descriptor set for it.
1112	const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = {
1113		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1114		DE_NULL,												 // pNext
1115		layoutCreateFlags,										 // flags
1116		sizeof(bindings) / sizeof(bindings[0]),					 // bindingCount
1117		&bindings[0]											 // pBindings
1118	};
1119
1120	m_computeDescriptorSetLayout = vk::createDescriptorSetLayout(m_vk, device, &setLayoutCreateInfo);
1121
1122	const VkPipelineShaderStageCreateInfo csShaderCreateInfo = {
1123		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1124		DE_NULL,
1125		(VkPipelineShaderStageCreateFlags)0,
1126		VK_SHADER_STAGE_COMPUTE_BIT, // stage
1127		*cs,						 // shader
1128		"main",
1129		DE_NULL, // pSpecializationInfo
1130	};
1131
1132	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
1133		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1134		DE_NULL,									   // pNext
1135		(VkPipelineLayoutCreateFlags)0,
1136		1,									 // setLayoutCount
1137		&m_computeDescriptorSetLayout.get(), // pSetLayouts
1138		0,									 // pushConstantRangeCount
1139		DE_NULL,							 // pPushConstantRanges
1140	};
1141
1142	m_computePipelineLayout = createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo, NULL);
1143
1144	const VkComputePipelineCreateInfo pipelineCreateInfo = {
1145		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1146		DE_NULL,
1147		0u,						  // flags
1148		csShaderCreateInfo,		  // cs
1149		*m_computePipelineLayout, // layout
1150		(vk::VkPipeline)0,		  // basePipelineHandle
1151		0u,						  // basePipelineIndex
1152	};
1153
1154	m_computePipeline = createComputePipeline(m_vk, device, DE_NULL, &pipelineCreateInfo, NULL);
1155
1156	VkDescriptorPoolCreateFlags poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1157
1158	vk::DescriptorPoolBuilder poolBuilder;
1159	for (deUint32 i = 0; i < (deInt32)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1160	{
1161		poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount * attachmentSize);
1162	}
1163	m_descriptorPool = poolBuilder.build(m_vk, device, poolCreateFlags, attachmentSize);
1164
1165	for (deUint32 i = 0; i < attachmentSize; ++i)
1166	{
1167		m_descriptorSets[i] = makeDescriptorSet(m_vk, device, *m_descriptorPool, *m_computeDescriptorSetLayout);
1168		VkDescriptorImageInfo  imageInfo;
1169		VkDescriptorBufferInfo bufferInfo;
1170
1171		VkWriteDescriptorSet w = {
1172			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1173			DE_NULL,								// pNext
1174			*m_descriptorSets[i],					// dstSet
1175			(deUint32)0,							// dstBinding
1176			0,										// dstArrayElement
1177			1u,										// descriptorCount
1178			bindings[0].descriptorType,				// descriptorType
1179			&imageInfo,								// pImageInfo
1180			&bufferInfo,							// pBufferInfo
1181			DE_NULL,								// pTexelBufferView
1182		};
1183
1184		imageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageColorView[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1185		w.dstBinding	 = 0;
1186		w.descriptorType = bindings[0].descriptorType;
1187		m_vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1188
1189		bufferInfo		 = makeDescriptorBufferInfo(m_imageBuffer[i]->object(), 0, VK_WHOLE_SIZE);
1190		w.dstBinding	 = 1;
1191		w.descriptorType = bindings[1].descriptorType;
1192		m_vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1193	}
1194}
1195
1196Move<VkPipeline> ShaderTileImageTestInstance::generateGraphicsPipeline(bool disableColor0Write, bool disableDepthWrite,
1197																	   bool disableStencilWrite)
1198{
1199	const VkDevice device = m_context.getDevice();
1200
1201	VkPushConstantRange pushConstant;
1202	pushConstant.offset		= 0;
1203	pushConstant.size		= sizeof(deUint32);
1204	pushConstant.stageFlags = (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
1205
1206	m_graphicsPipelineLayout = makePipelineLayout(m_vk, device, 0, nullptr, 1, &pushConstant);
1207	m_vertexModule			 = createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0u);
1208	m_fragmentModule		 = createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0u);
1209
1210	const VkVertexInputBindingDescription vertexInputBindingDescription = {
1211		0,							 // deUint32 binding;
1212		sizeof(tcu::Vec2),			 // deUint32 strideInBytes;
1213		VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputStepRate stepRate;
1214	};
1215
1216	const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
1217		0u,						 // deUint32 location;
1218		0u,						 // deUint32 binding;
1219		VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1220		0u,						 // deUint32 offsetInBytes;
1221	};
1222
1223	const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1224		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1225		DE_NULL,												   // const void* pNext;
1226		0,														   // VkPipelineVertexInputStateCreateFlags	flags;
1227		1u,														   // deUint32 bindingCount;
1228		&vertexInputBindingDescription,	  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1229		1u,								  // deUint32 attributeCount;
1230		&vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1231	};
1232
1233	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
1234		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1235		DE_NULL,													 // const void* pNext;
1236		(VkPipelineInputAssemblyStateCreateFlags)0,					 // VkPipelineInputAssemblyStateCreateFlags flags;
1237		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,						 // VkPrimitiveTopology topology;
1238		VK_FALSE,													 // VkBool32 primitiveRestartEnable;
1239	};
1240
1241	const VkViewport viewport{
1242		0, 0, static_cast<float>(m_testParam->frameBufferSize), static_cast<float>(m_testParam->frameBufferSize), 0, 1
1243	};
1244	const VkRect2D scissor{ { 0, 0 }, { m_testParam->frameBufferSize, m_testParam->frameBufferSize } };
1245
1246	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = {
1247		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1248		DE_NULL,											   // const void* pNext;
1249		(VkPipelineViewportStateCreateFlags)0,				   // VkPipelineViewportStateCreateFlags flags;
1250		1u,													   // uint32_t viewportCount;
1251		&viewport,											   // const VkViewport* pViewports;
1252		1u,													   // uint32_t scissorCount;
1253		&scissor,											   // const VkRect2D* pScissors;
1254	};
1255
1256	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = {
1257		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1258		DE_NULL,													// const void* pNext;
1259		0u,															// VkPipelineRasterizationStateCreateFlags flags;
1260		VK_FALSE,													// VkBool32 depthClampEnable;
1261		VK_FALSE,													// VkBool32 rasterizerDiscardEnable;
1262		VK_POLYGON_MODE_FILL,										// VkPolygonMode polygonMode;
1263		VK_CULL_MODE_NONE,											// VkCullModeFlags cullMode;
1264		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace frontFace;
1265		VK_FALSE,													// VkBool32 depthBiasEnable;
1266		0.0f,														// float depthBiasConstantFactor;
1267		0.0f,														// float depthBiasClamp;
1268		0.0f,														// float depthBiasSlopeFactor;
1269		1.0f,														// float lineWidth;
1270	};
1271
1272	const VkSampleMask	sampleMask	= getSampleMask(m_testParam->testType);
1273	const VkSampleMask* pSampleMask = (m_testParam->testType == TestType::MsaaSampleMask) ? &sampleMask : DE_NULL;
1274	const bool			sampleShadingEnable = (m_testParam->testType != TestType::MsaaSampleMask);
1275
1276	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
1277		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1278		DE_NULL,												  // const void* pNext;
1279		0u,														  // VkPipelineMultisampleStateCreateFlags flags;
1280		m_testParam->m_sampleCount,								  // VkSampleCountFlagBits rasterizationSamples;
1281		sampleShadingEnable,									  // VkBool32 sampleShadingEnable;
1282		1.0f,													  // float minSampleShading;
1283		pSampleMask,											  // const VkSampleMask* pSampleMask;
1284		VK_FALSE,												  // VkBool32 alphaToCoverageEnable;
1285		VK_FALSE												  // VkBool32 alphaToOneEnable;
1286	};
1287
1288	std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentState(
1289		getColorAttachmentCount(m_testParam->testType),
1290		{
1291			false,												  // VkBool32 blendEnable;
1292			VK_BLEND_FACTOR_ONE,								  // VkBlend srcBlendColor;
1293			VK_BLEND_FACTOR_ONE,								  // VkBlend destBlendColor;
1294			VK_BLEND_OP_ADD,									  // VkBlendOp blendOpColor;
1295			VK_BLEND_FACTOR_ONE,								  // VkBlend srcBlendAlpha;
1296			VK_BLEND_FACTOR_ONE,								  // VkBlend destBlendAlpha;
1297			VK_BLEND_OP_ADD,									  // VkBlendOp blendOpAlpha;
1298			(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT) // VkChannelFlags channelWriteMask;
1299		});
1300
1301	if (disableColor0Write)
1302	{
1303		colorBlendAttachmentState[0].colorWriteMask = 0;
1304	}
1305
1306	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
1307		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1308		DE_NULL,												  // const void* pNext;
1309		/* always needed */
1310		0,											// VkPipelineColorBlendStateCreateFlags flags;
1311		false,										// VkBool32 logicOpEnable;
1312		VK_LOGIC_OP_COPY,							// VkLogicOp logicOp;
1313		(deUint32)colorBlendAttachmentState.size(), // deUint32 attachmentCount;
1314		colorBlendAttachmentState.data(),			// const VkPipelineColorBlendAttachmentState* pAttachments;
1315		{ 0.0f, 0.0f, 0.0f, 0.0f },					// float blendConst[4];
1316	};
1317
1318	VkStencilOpState stencilOpState = {
1319		VK_STENCIL_OP_ZERO,				  // VkStencilOp failOp;
1320		VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp passOp;
1321		VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp depthFailOp;
1322		VK_COMPARE_OP_ALWAYS,			  // VkCompareOp compareOp;
1323		0xff,							  // uint32_t compareMask;
1324		0xff,							  // uint32_t writeMask;
1325		0,								  // uint32_t reference;
1326	};
1327
1328	if (disableStencilWrite)
1329	{
1330		stencilOpState.failOp	   = VK_STENCIL_OP_KEEP;
1331		stencilOpState.passOp	   = VK_STENCIL_OP_KEEP;
1332		stencilOpState.depthFailOp = VK_STENCIL_OP_KEEP;
1333	}
1334
1335	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
1336		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1337		// VkStructureType sType;
1338		DE_NULL, // const void* pNext;
1339		0,
1340		// VkPipelineDepthStencilStateCreateFlags flags;
1341		VK_TRUE,			  // VkBool32 depthTestEnable;
1342		VK_TRUE,			  // VkBool32 depthWriteEnable;
1343		VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
1344		VK_FALSE,			  // VkBool32 depthBoundsTestEnable;
1345		VK_TRUE,			  // VkBool32 stencilTestEnable;
1346		stencilOpState,		  // VkStencilOpState front;
1347		stencilOpState,		  // VkStencilOpState back;
1348		0.0f,				  // float minDepthBounds;
1349		1.0f,				  // float maxDepthBounds;
1350	};
1351
1352	if (disableDepthWrite)
1353	{
1354		pipelineDepthStencilStateInfo.depthWriteEnable = VK_FALSE;
1355	}
1356
1357	std::vector<VkFormat>				   colorsAttachmentFormats(getColorAttachmentCount(m_testParam->testType),
1358																   m_testParam->colorFormat);
1359	const tcu::TextureFormat depthStencilTexFormat = mapVkFormat(m_testParam->depthStencilFormat);
1360	VkFormat depthFormat = tcu::hasDepthComponent(depthStencilTexFormat.order) ? m_testParam->depthStencilFormat : VK_FORMAT_UNDEFINED;
1361	VkFormat stencilFormat = tcu::hasStencilComponent(depthStencilTexFormat.order) ? m_testParam->depthStencilFormat : VK_FORMAT_UNDEFINED;
1362	const VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
1363		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,	// VkStructureType sType;
1364		DE_NULL,												// const void* pNext;
1365		0u,														// deUint32 viewMask;
1366		static_cast<deUint32>(colorsAttachmentFormats.size()),	// deUint32 colorAttachmentCount;
1367		colorsAttachmentFormats.data(),							// const VkFormat* pColorAttachmentFormats;
1368		depthFormat,											// VkFormat depthAttachmentFormat;
1369		stencilFormat,											// VkFormat stencilAttachmentFormat;
1370	};
1371
1372	const VkPipelineShaderStageCreateInfo pShaderStages[] = {
1373		{
1374			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1375			DE_NULL,											 // const void*	 pNext;
1376			(VkPipelineShaderStageCreateFlags)0,				 // VkPipelineShaderStageCreateFlags flags;
1377			VK_SHADER_STAGE_VERTEX_BIT,							 // VkShaderStageFlagBits stage;
1378			*m_vertexModule,									 // VkShaderModule module;
1379			"main",												 // const char* pName;
1380			DE_NULL,											 // const VkSpecializationInfo* pSpecializationInfo;
1381		},
1382		{
1383			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1384			DE_NULL,											 // const void* pNext;
1385			(VkPipelineShaderStageCreateFlags)0,				 // VkPipelineShaderStageCreateFlags flags;
1386			VK_SHADER_STAGE_FRAGMENT_BIT,						 // VkShaderStageFlagBits stage;
1387			*m_fragmentModule,									 // VkShaderModule module;
1388			"main",												 // const char* pName;
1389			DE_NULL,											 // const VkSpecializationInfo* pSpecializationInfo;
1390		},
1391	};
1392
1393	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = {
1394		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1395		&renderingCreateInfo,							 // const void* pNext;
1396		(VkPipelineCreateFlags)0,						 // VkPipelineCreateFlags flags;
1397		2u,												 // deUint32 stageCount;
1398		pShaderStages,									 // const VkPipelineShaderStageCreateInfo* pStages;
1399		&vertexInputStateParams,		 // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1400		&pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1401		DE_NULL,						 // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1402		&pipelineViewportStateInfo,		 // const VkPipelineViewportStateCreateInfo* pViewportState;
1403		&pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1404		&pipelineMultisampleStateInfo,	 // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1405		&pipelineDepthStencilStateInfo,	 // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1406		&pipelineColorBlendStateInfo,	 // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1407		DE_NULL,						 // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1408		*m_graphicsPipelineLayout,		 // VkPipelineLayout layout;
1409		DE_NULL,						 // VkRenderPass renderPass;
1410		0u,								 // deUint32 subpass;
1411		DE_NULL,						 // VkPipeline basePipelineHandle;
1412		0,								 // deInt32 basePipelineIndex;
1413	};
1414
1415	return createGraphicsPipeline(m_vk, device, DE_NULL, &graphicsPipelineInfo);
1416}
1417
1418void ShaderTileImageTestInstance::generateAttachments()
1419{
1420	const VkDevice device	 = m_context.getDevice();
1421	Allocator&	   allocator = m_context.getDefaultAllocator();
1422
1423	auto makeImageCreateInfo = [](const VkFormat format, deUint32 imageSize, VkSampleCountFlagBits sampleCount,
1424								  VkImageUsageFlags usage) -> VkImageCreateInfo
1425	{
1426		const VkImageCreateInfo imageParams = {
1427			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,   // VkStructureType sType;
1428			DE_NULL,							   // const void* pNext;
1429			(VkImageCreateFlags)0,				   // VkImageCreateFlags flags;
1430			VK_IMAGE_TYPE_2D,					   // VkImageType imageType;
1431			format,								   // VkFormat format;
1432			makeExtent3D(imageSize, imageSize, 1), // VkExtent3D extent;
1433			1u,									   // deUint32 mipLevels;
1434			1u,									   // deUint32 arrayLayers;
1435			sampleCount,						   // VkSampleCountFlagBits	samples;
1436			VK_IMAGE_TILING_OPTIMAL,			   // VkImageTiling tiling;
1437			usage,								   // VkImageUsageFlags usage;
1438			VK_SHARING_MODE_EXCLUSIVE,			   // VkSharingMode sharingMode;
1439			0u,									   // deUint32 queueFamilyIndexCount;
1440			DE_NULL,							   // const deUint32* pQueueFamilyIndices;
1441			VK_IMAGE_LAYOUT_UNDEFINED,			   // VkImageLayout initialLayout;
1442		};
1443		return imageParams;
1444	};
1445
1446	// Color Attachment
1447	{
1448		constexpr deUint32		imageBufferPixelSize = sizeof(deUint32) * 2; // always uvec2 type
1449		const VkImageUsageFlags imageUsage =
1450			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1451		const VkDeviceSize imageBufferSize = m_testParam->frameBufferSize * m_testParam->frameBufferSize *
1452											 imageBufferPixelSize * getSampleCount(m_testParam->m_sampleCount);
1453		const VkImageSubresourceRange imageSubresource =
1454			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1455		const VkImageCreateInfo	 imageInfo = makeImageCreateInfo(m_testParam->colorFormat, m_testParam->frameBufferSize,
1456																 m_testParam->m_sampleCount, imageUsage);
1457		const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(
1458			imageBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1459
1460		const deUint32 attachmentCount = getColorAttachmentCount(m_testParam->testType);
1461		for (deUint32 i = 0; i < attachmentCount; ++i)
1462		{
1463			m_imageColor[i]		 = makeImage(m_vk, device, imageInfo);
1464			m_imageColorAlloc[i] = bindImage(m_vk, device, allocator, *m_imageColor[i], MemoryRequirement::Any);
1465			m_imageBuffer[i] =
1466				Draw::Buffer::createAndAlloc(m_vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
1467			m_imageColorView[i] = makeImageView(m_vk, device, *m_imageColor[i], VK_IMAGE_VIEW_TYPE_2D,
1468												m_testParam->colorFormat, imageSubresource);
1469		}
1470
1471		m_imageColorBufferHostPtr = static_cast<deUint32*>(m_imageBuffer[0]->getHostPtr());
1472	}
1473
1474	// depth/stencil attachment.
1475	{
1476		const tcu::TextureFormat depthStencilFormat = mapVkFormat(m_testParam->depthStencilFormat);
1477		const VkImageUsageFlags	 imageUsage =
1478			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1479
1480		VkImageAspectFlags aspect = 0;
1481		if (tcu::hasDepthComponent(depthStencilFormat.order))
1482		{
1483			aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
1484		}
1485		if (tcu::hasStencilComponent(depthStencilFormat.order))
1486		{
1487			aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
1488		}
1489
1490		const VkImageCreateInfo imageInfo = makeImageCreateInfo(
1491			m_testParam->depthStencilFormat, m_testParam->frameBufferSize, m_testParam->m_sampleCount, imageUsage);
1492
1493		const VkImageSubresourceRange imageSubresource = makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u);
1494
1495		m_imageDepthStencil		 = makeImage(m_vk, device, imageInfo);
1496		m_imageDepthStencilAlloc = bindImage(m_vk, device, allocator, *m_imageDepthStencil, MemoryRequirement::Any);
1497		m_imageDepthStencilView	 = makeImageView(m_vk, device, *m_imageDepthStencil, VK_IMAGE_VIEW_TYPE_2D,
1498												 m_testParam->depthStencilFormat, imageSubresource);
1499	}
1500}
1501
1502void ShaderTileImageTestInstance::generateVertexBuffer()
1503{
1504	const deUint32		   drawCount		 = getDrawCallCount(m_testParam);
1505	const deUint32		   patchCountPerDraw = getPatchesPerDrawCount(m_testParam->multiplePatchesPerDraw);
1506	const deUint32		   queueFamilyIndex	 = m_context.getUniversalQueueFamilyIndex();
1507	const VkDevice		   device			 = m_context.getDevice();
1508	Allocator&			   allocator		 = m_context.getDefaultAllocator();
1509	std::vector<tcu::Vec2> vbo;
1510	for (deUint32 patchIndex = 0; patchIndex < (patchCountPerDraw * drawCount); patchIndex++)
1511	{
1512		// _____
1513		// |  /
1514		// | /
1515		// |/
1516		vbo.emplace_back(tcu::Vec2(-1, -1));
1517		vbo.emplace_back(tcu::Vec2(1, 1));
1518		vbo.emplace_back(tcu::Vec2(-1, 1));
1519
1520		if (getVertexCountPerPatch(m_testParam) == 6)
1521		{
1522			if (isHelperClassTest(m_testParam->testType) && patchIndex == 0)
1523			{
1524				// helper class cases render the first patch like follow.
1525				// _____
1526				// |  /
1527				// | /
1528				// |/
1529				// So, 3 of second triangle is dummy.
1530				vbo.emplace_back(tcu::Vec2(-1, -1));
1531				vbo.emplace_back(tcu::Vec2(-1, -1));
1532				vbo.emplace_back(tcu::Vec2(-1, -1));
1533			}
1534			else
1535			{
1536				// Other 6 vertices cases render like follow
1537				// _____
1538				// |  /|
1539				// | / |
1540				// |/__|
1541				vbo.emplace_back(tcu::Vec2(-1, -1));
1542				vbo.emplace_back(tcu::Vec2(1, -1));
1543				vbo.emplace_back(tcu::Vec2(1, 1));
1544			}
1545		}
1546	}
1547
1548	const size_t dataSize = vbo.size() * sizeof(tcu::Vec2);
1549	{
1550		const VkBufferCreateInfo bufferInfo = {
1551			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1552			DE_NULL,							  // const void* pNext;
1553			0u,									  // VkBufferCreateFlags flags;
1554			dataSize,							  // VkDeviceSize size;
1555			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,	  // VkBufferUsageFlags	usage;
1556			VK_SHARING_MODE_EXCLUSIVE,			  // VkSharingMode sharingMode;
1557			1u,									  // deUint32 queueFamilyCount;
1558			&queueFamilyIndex					  // const deUint32* pQueueFamilyIndices;
1559		};
1560		m_vertexBuffer =
1561			Draw::Buffer::createAndAlloc(m_vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
1562	}
1563
1564	/* Load vertices into vertex buffer */
1565	deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), vbo.data(), dataSize);
1566	flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
1567}
1568void ShaderTileImageTestInstance::generateCmdBuffer()
1569{
1570	const VkDevice device = m_context.getDevice();
1571
1572	m_cmdPool	= createCommandPool(m_vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1573									m_context.getUniversalQueueFamilyIndex());
1574	m_cmdBuffer = allocateCommandBuffer(m_vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1575}
1576
1577tcu::TestStatus ShaderTileImageTestInstance::iterate()
1578{
1579	rendering();
1580	return checkResult();
1581}
1582
1583deUint32 ShaderTileImageTestInstance::getResultValue(deUint32 fx, deUint32 fy, deUint32 fs,
1584													 deUint32 renderTargetID) const
1585{
1586	const deUint32* resultData =
1587		static_cast<const deUint32*>(m_imageBuffer[renderTargetID]->getBoundMemory().getHostPtr());
1588	const deUint32 sampleCount = getSampleCount(m_testParam->m_sampleCount);
1589	const deUint32 index	   = (((fy * m_testParam->frameBufferSize) + fx) * sampleCount + fs) * 2; // 2 is for xy
1590	if (resultData[index] != 0)																		  // error
1591	{
1592		return 0xFFFFFFFF;
1593	}
1594
1595	return resultData[index + 1]; // y value
1596}
1597
1598deUint32 ShaderTileImageTestInstance::simulate(deUint32 fx, deUint32 fy, deUint32 fs, deUint32 renderTargetID) const
1599{
1600	const deUint32 totalLayerCount =
1601		getDrawCallCount(m_testParam) * getPatchesPerDrawCount(m_testParam->multiplePatchesPerDraw);
1602
1603	if (m_testParam->testType == TestType::MsaaSampleMask)
1604	{
1605		deUint32 expectedValue = 0;
1606
1607		if (((getSampleMask(m_testParam->testType) >> fs) & 0x1) == 0x1)
1608		{
1609			expectedValue = totalLayerCount + renderTargetID;
1610		}
1611		return expectedValue;
1612	}
1613	if (m_testParam->testType == TestType::Stencil)
1614	{
1615		// stencil test doesn't add fragment sample ID to the output;
1616		const deUint32 expectedValue = totalLayerCount + renderTargetID;
1617		return expectedValue;
1618	}
1619	if (isHelperClassTest(m_testParam->testType))
1620	{
1621		// ________      ________      ________
1622		// 1|1|1|0|      0|0|*|1|      1|1|#|2|
1623		// 1|1|0|0|      0|0|1|*|      1|1|2|#|
1624		// 1|0|0|0|  =>  *|1|0|0|  =>  #|2|1|1|
1625		// 0|0|0|0|      1|*|0|0|      2|#|1|1|
1626		// ________      ________      ________
1627		// raster       max(dx,dy)    result(+1)
1628		// *(#): max(dx, dy) could be 0(1) or 1(2).
1629		if ((fx) == (fy))
1630		{
1631			return kDerivative1; // derivative is 1 because of coverage. (+1) for differentiate clear value
1632		}
1633		else
1634		{
1635			return kDerivative0; // 0, fill all or fill none for quad. (+1) for differentiate clear value
1636		}
1637	}
1638	else
1639	{
1640		const deUint32 expectedValue = totalLayerCount + renderTargetID + fs;
1641		return expectedValue;
1642	}
1643}
1644
1645tcu::TestStatus ShaderTileImageTestInstance::checkResult() const
1646{
1647	const VkDevice device = m_context.getDevice();
1648
1649	qpTestResult   res				   = QP_TEST_RESULT_PASS;
1650	const deUint32 sampleCount		   = getSampleCount(m_testParam->m_sampleCount);
1651	const deUint32 attachmentCount	   = getColorAttachmentCount(m_testParam->testType);
1652	const deUint32 vertexCountPerPatch = getVertexCountPerPatch(m_testParam);
1653	// Loop over all samples in the same fragment
1654
1655	for (deUint32 rt = 0; (res == QP_TEST_RESULT_PASS) && rt < attachmentCount; rt++)
1656	{
1657		// Result of Helper Class test valid only for the rt 1
1658		invalidateAlloc(m_vk, device, m_imageBuffer[rt]->getBoundMemory());
1659
1660		if (rt != 1 && isHelperClassTest(m_testParam->testType))
1661		{
1662			continue;
1663		}
1664
1665		for (deUint32 fy = 0; (res == QP_TEST_RESULT_PASS) && fy < m_testParam->frameBufferSize; ++fy)
1666		{
1667			for (deUint32 fx = 0; (res == QP_TEST_RESULT_PASS) && fx < m_testParam->frameBufferSize; ++fx)
1668			{
1669				for (deUint32 fs = 0; (res == QP_TEST_RESULT_PASS) && fs < sampleCount; ++fs)
1670				{
1671					const deUint32 expectedValue = simulate(fx, fy, fs, rt);
1672					const deUint32 resultValue	 = getResultValue(fx, fy, fs, rt);
1673
1674					if (isHelperClassTest(m_testParam->testType))
1675					{
1676						// ________      ________      ________
1677						// 1|1|1|0|      0|0|*|1|      1|1|#|2|
1678						// 1|1|0|0|      0|0|1|*|      1|1|2|#|
1679						// 1|0|0|0|  =>  *|1|0|0|  =>  #|2|1|1|
1680						// 0|0|0|0|      1|*|0|0|      2|#|1|1|
1681						// ________      ________      ________
1682						// raster       max(dx,dy)    result(+1)
1683						// *(#): max(dx, dy) could be 0(1) or 1(2).
1684						if (expectedValue != resultValue)
1685						{
1686							if (std::abs(static_cast<deInt32>(fx - fy)) != 1 || resultValue != kDerivative1)
1687							{
1688								res = QP_TEST_RESULT_FAIL;
1689								break;
1690							}
1691						}
1692					}
1693					else if (vertexCountPerPatch == 6) // Fill full quad to the framebuffer
1694					{
1695						if (expectedValue != resultValue)
1696						{
1697							res = QP_TEST_RESULT_FAIL;
1698							break;
1699						}
1700					}
1701					else // Fill a triangle to the framebuffer, check half of framebuffer
1702					{
1703						if (fy > fx) // inside of triangle
1704						{
1705							if (expectedValue != resultValue) // not expected value
1706							{
1707								res = QP_TEST_RESULT_FAIL;
1708								break;
1709							}
1710						}
1711						else // outside of filling triangle or triangle edge
1712						{
1713							if (resultValue != 0 && resultValue != expectedValue) // can be not filling
1714							{
1715								res = QP_TEST_RESULT_FAIL;
1716								break;
1717							}
1718						}
1719					}
1720				}
1721			}
1722		}
1723	}
1724
1725	return tcu::TestStatus(res, qpGetTestResultName(res));
1726}
1727
1728void ShaderTileImageTestInstance::rendering()
1729{
1730	const VkDevice device = m_context.getDevice();
1731	const VkQueue  queue  = m_context.getUniversalQueue();
1732
1733	beginCommandBuffer(m_vk, *m_cmdBuffer);
1734
1735	// begin render pass
1736	const VkClearValue clearValue	= {}; // { 0, 0, 0, 0 }
1737	const VkClearValue dsClearValue = {}; // .depth = 0.0f, .stencil = 0
1738	const VkRect2D	   renderArea	= { { 0, 0 }, { m_testParam->frameBufferSize, m_testParam->frameBufferSize } };
1739
1740	const deUint32 colorAttachmentCount = getColorAttachmentCount(m_testParam->testType);
1741
1742	std::vector<VkRenderingAttachmentInfoKHR> colorAttachments;
1743	for (deUint32 colorIndex = 0; colorIndex < colorAttachmentCount; colorIndex++)
1744	{
1745		const VkRenderingAttachmentInfoKHR renderingAtachInfo = {
1746			VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
1747			DE_NULL,										 // const void* pNext;
1748			*m_imageColorView[colorIndex],					 // VkImageView imageView;
1749			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		 // VkImageLayout imageLayout;
1750			VK_RESOLVE_MODE_NONE,							 // VkResolveModeFlagBits resolveMode;
1751			DE_NULL,										 // VkImageView resolveImageView;
1752			VK_IMAGE_LAYOUT_UNDEFINED,						 // VkImageLayout resolveImageLayout;
1753			VK_ATTACHMENT_LOAD_OP_CLEAR,					 // VkAttachmentLoadOp loadOp;
1754			VK_ATTACHMENT_STORE_OP_STORE,					 // VkAttachmentStoreOp storeOp;
1755			clearValue,										 // VkClearValue clearValue;
1756		};
1757
1758		colorAttachments.push_back(renderingAtachInfo);
1759	}
1760
1761	const tcu::TextureFormat depthStencilFormat = mapVkFormat(m_testParam->depthStencilFormat);
1762	const bool				 hasDepth			= tcu::hasDepthComponent(depthStencilFormat.order);
1763	const bool				 hasStencil			= tcu::hasStencilComponent(depthStencilFormat.order);
1764	VkImageLayout			 depthStencilLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1765	VkImageAspectFlags		 depthStencilAspect = 0;
1766	if (hasDepth && hasStencil)
1767	{
1768		depthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1769		depthStencilAspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1770	}
1771	else if (hasDepth)
1772	{
1773		depthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
1774		depthStencilAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
1775	}
1776	else if (hasStencil)
1777	{
1778		depthStencilLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
1779		depthStencilAspect = VK_IMAGE_ASPECT_STENCIL_BIT;
1780	}
1781
1782	const VkRenderingAttachmentInfoKHR depthStencilAttachment = {
1783		VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType			sType;
1784		DE_NULL,										 // const void*				pNext;
1785		*m_imageDepthStencilView,						 // VkImageView				imageView;
1786		depthStencilLayout,								 // VkImageLayout			imageLayout;
1787		VK_RESOLVE_MODE_NONE,							 // VkResolveModeFlagBits	resolveMode;
1788		DE_NULL,										 // VkImageView				resolveImageView;
1789		VK_IMAGE_LAYOUT_UNDEFINED,						 // VkImageLayout			resolveImageLayout;
1790		VK_ATTACHMENT_LOAD_OP_CLEAR,					 // VkAttachmentLoadOp		loadOp;
1791		VK_ATTACHMENT_STORE_OP_STORE,					 // VkAttachmentStoreOp		storeOp;
1792		dsClearValue,									 // VkClearValue				clearValue;
1793	};
1794
1795	const VkRenderingInfoKHR renderingInfo = {
1796		VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,			// VkStructureType sType;
1797		DE_NULL,										// const void* pNext;
1798		0,												// VkRenderingFlagsKHR flags;
1799		renderArea,										// VkRect2D renderArea;
1800		1u,												// deUint32 layerCount;
1801		0u,												// deUint32 viewMask;
1802		static_cast<deUint32>(colorAttachments.size()), // deUint32 colorAttachmentCount;
1803		colorAttachments.data(),						// const VkRenderingAttachmentInfoKHR* pColorAttachments;
1804		hasDepth ? &depthStencilAttachment : DE_NULL,	// const VkRenderingAttachmentInfoKHR* pDepthAttachment;
1805		hasStencil ? &depthStencilAttachment : DE_NULL	// const VkRenderingAttachmentInfoKHR* pStencilAttachment;
1806	};
1807
1808	for (deUint32 colorIndex = 0; colorIndex < colorAttachmentCount; colorIndex++)
1809	{
1810		transition2DImage(m_vk, *m_cmdBuffer, *m_imageColor[colorIndex], VK_IMAGE_ASPECT_COLOR_BIT,
1811						  VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
1812						  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1813						  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1814	}
1815
1816	transition2DImage(m_vk, *m_cmdBuffer, *m_imageDepthStencil, depthStencilAspect, VK_IMAGE_LAYOUT_UNDEFINED,
1817					  depthStencilLayout, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1818					  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1819					  VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1820
1821	m_vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
1822
1823	// vertex input setup
1824	const VkBuffer vertexBuffer = m_vertexBuffer->object();
1825
1826	for (deUint32 drawIndex = 0; drawIndex < getDrawCallCount(m_testParam); drawIndex++)
1827	{
1828		// pipeline setup
1829		if (drawIndex == 1 && isHelperClassTest(m_testParam->testType))
1830		{
1831			m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineForHelperClass);
1832		}
1833		else
1834		{
1835			m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1836		}
1837
1838		const deUint32 vertexCountPerPatch = getVertexCountPerPatch(m_testParam);
1839		const deUint32 vertexCount = vertexCountPerPatch * getPatchesPerDrawCount(m_testParam->multiplePatchesPerDraw);
1840		m_vk.cmdPushConstants(*m_cmdBuffer, *m_graphicsPipelineLayout,
1841							  (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), 0, sizeof(deUint32),
1842							  &drawIndex);
1843
1844		const VkDeviceSize vertexBufferOffset = (vertexCount * drawIndex) * sizeof(tcu::Vec2);
1845		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1846
1847		if (!m_testParam->coherent)
1848		{
1849			VkMemoryBarrier2KHR memoryBarrierForColor = {
1850				VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,				// sType
1851				DE_NULL,											// pNext
1852				VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,// srcStageMask
1853				VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,			// srcAccessMask
1854				VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,// dstStageMask
1855				VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR			// dstAccessMask
1856			};
1857
1858			VkMemoryBarrier2KHR memoryBarrierForDepthStencil = {
1859				VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,				// sType
1860				DE_NULL,											// pNext
1861				VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
1862					VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,	// srcStageMask
1863				VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR, // srcAccessMask
1864				VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
1865					VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT ,	// dstStageMask
1866				VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR	// dstAccessMask
1867			};
1868
1869			VkMemoryBarrier2KHR* memoryBarrier =
1870				(m_testParam->testType == TestType::Depth) || (m_testParam->testType == TestType::Stencil) ?
1871					&memoryBarrierForDepthStencil :
1872					&memoryBarrierForColor;
1873
1874			VkDependencyInfoKHR dependencyInfo{
1875				VK_STRUCTURE_TYPE_DEPENDENCY_INFO, // sType
1876				DE_NULL,						   // pNext
1877				VK_DEPENDENCY_BY_REGION_BIT,	   //dependency flags
1878				1,								   //memory barrier count
1879				memoryBarrier,					   //memory barrier
1880				0,								   // bufferMemoryBarrierCount
1881				DE_NULL,						   // pBufferMemoryBarriers
1882				0,								   // imageMemoryBarrierCount
1883				DE_NULL,						   // pImageMemoryBarriers
1884			};
1885			m_vk.cmdPipelineBarrier2(*m_cmdBuffer, &dependencyInfo);
1886		}
1887
1888		m_vk.cmdDraw(*m_cmdBuffer, vertexCount, 1, 0, 0u);
1889	}
1890	m_vk.cmdEndRendering(*m_cmdBuffer);
1891
1892	for (deUint32 colorIndex = 0; colorIndex < colorAttachmentCount; colorIndex++)
1893	{
1894
1895		transition2DImage(m_vk, *m_cmdBuffer, *m_imageColor[colorIndex], VK_IMAGE_ASPECT_COLOR_BIT,
1896						  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1897						  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1898						  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1899						  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
1900	}
1901
1902	VkMemoryBarrier memBarrier = {
1903		VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
1904		DE_NULL,						  // pNext
1905		0u,								  // srcAccessMask
1906		0u,								  // dstAccessMask
1907	};
1908	memBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1909	memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1910	m_vk.cmdPipelineBarrier(*m_cmdBuffer,
1911							VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1912							VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
1913
1914	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
1915
1916	// Copy color images to buffer memory
1917	for (deUint32 attachmentIndex = 0; attachmentIndex < colorAttachmentCount; attachmentIndex++)
1918	{
1919		m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelineLayout, 0u, 1,
1920								   &*m_descriptorSets[attachmentIndex], 0u, DE_NULL);
1921
1922		m_vk.cmdDispatch(*m_cmdBuffer, m_testParam->frameBufferSize, m_testParam->frameBufferSize, 1);
1923	}
1924	memBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1925	memBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
1926	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 1,
1927							&memBarrier, 0, DE_NULL, 0, DE_NULL);
1928
1929	VK_CHECK(m_vk.endCommandBuffer(*m_cmdBuffer));
1930
1931	submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
1932}
1933
1934std::string formatToName(VkFormat format)
1935{
1936	const std::string formatStr = de::toString(format);
1937	const std::string prefix	= "VK_FORMAT_";
1938
1939	DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
1940
1941	return de::toLower(formatStr.substr(prefix.length()));
1942}
1943
1944void createShaderTileImageTestVariations(tcu::TestContext& testCtx, tcu::TestCaseGroup* gr)
1945{
1946	struct TestTypeParam
1947	{
1948		TestType	value;
1949		const char* name;
1950	};
1951
1952	struct BoolParam
1953	{
1954		bool		value;
1955		const char* name;
1956	};
1957
1958	struct VkSampleCountFlagParam
1959	{
1960		VkSampleCountFlagBits value;
1961		const char*			  name;
1962	};
1963
1964	const std::vector<BoolParam> coherentParams = { { true, "coherent" }, { false, "non_coherent" } };
1965
1966	const std::vector<TestTypeParam> testTypeParams = {
1967		{ TestType::Color, "color" },
1968		{ TestType::MultiRenderTarget, "mrt" },
1969		{ TestType::MultiRenderTargetDynamicIndex, "mrt_dynamic_index" },
1970		{ TestType::MsaaSampleMask, "msaa_sample_mask" },
1971		{ TestType::HelperClassColor, "helper_class_color" },
1972		{ TestType::HelperClassDepth, "helper_class_depth" },
1973		{ TestType::HelperClassStencil, "helper_class_stencil" },
1974		{ TestType::Depth, "depth" },
1975		{ TestType::Stencil, "stencil" },
1976	};
1977
1978	const std::vector<VkSampleCountFlagParam> sampleCountParams = {
1979		{ VK_SAMPLE_COUNT_1_BIT, "samples_1" },	  { VK_SAMPLE_COUNT_2_BIT, "samples_2" },
1980		{ VK_SAMPLE_COUNT_4_BIT, "samples_4" },	  { VK_SAMPLE_COUNT_8_BIT, "samples_8" },
1981		{ VK_SAMPLE_COUNT_16_BIT, "samples_16" }, { VK_SAMPLE_COUNT_32_BIT, "samples_32" },
1982	};
1983
1984	const std::vector<BoolParam> multiDrawsParams = { { false, "single_draw" }, { true, "multi_draws" } };
1985
1986	const std::vector<BoolParam> multiPatchParams = { { false, "single_patch" }, { true, "multi_patches" } };
1987
1988	const std::vector<VkFormat> formats = { VK_FORMAT_R5G6B5_UNORM_PACK16,
1989											VK_FORMAT_R8G8_UNORM,
1990											VK_FORMAT_R8G8_SNORM,
1991											VK_FORMAT_R8G8_UINT,
1992											VK_FORMAT_R8G8_SINT,
1993											VK_FORMAT_R8G8B8A8_UNORM,
1994											VK_FORMAT_R8G8B8A8_SNORM,
1995											VK_FORMAT_R8G8B8A8_UINT,
1996											VK_FORMAT_R8G8B8A8_SINT,
1997											VK_FORMAT_R8G8B8A8_SRGB,
1998											VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1999											VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2000											VK_FORMAT_A8B8G8R8_UINT_PACK32,
2001											VK_FORMAT_A8B8G8R8_SINT_PACK32,
2002											VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2003											VK_FORMAT_B8G8R8A8_UNORM,
2004											VK_FORMAT_B8G8R8A8_SRGB,
2005											VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2006											VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2007											VK_FORMAT_A2B10G10R10_UINT_PACK32,
2008											VK_FORMAT_R16G16_UNORM,
2009											VK_FORMAT_R16G16_SNORM,
2010											VK_FORMAT_R16G16_UINT,
2011											VK_FORMAT_R16G16_SINT,
2012											VK_FORMAT_R16G16_SFLOAT,
2013											VK_FORMAT_R16G16B16A16_UNORM,
2014											VK_FORMAT_R16G16B16A16_SNORM,
2015											VK_FORMAT_R16G16B16A16_UINT,
2016											VK_FORMAT_R16G16B16A16_SINT,
2017											VK_FORMAT_R16G16B16A16_SFLOAT,
2018											VK_FORMAT_R32G32_UINT,
2019											VK_FORMAT_R32G32_SINT,
2020											VK_FORMAT_R32G32_SFLOAT,
2021											VK_FORMAT_R32G32B32A32_UINT,
2022											VK_FORMAT_R32G32B32A32_SINT,
2023											VK_FORMAT_R32G32B32A32_SFLOAT,
2024											VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
2025
2026											VK_FORMAT_D16_UNORM,
2027											VK_FORMAT_X8_D24_UNORM_PACK32,
2028											VK_FORMAT_D32_SFLOAT,
2029											VK_FORMAT_S8_UINT,
2030											VK_FORMAT_D16_UNORM_S8_UINT,
2031											VK_FORMAT_D24_UNORM_S8_UINT,
2032											VK_FORMAT_D32_SFLOAT_S8_UINT };
2033
2034	tcu::TestCaseGroup*				 subGroup = nullptr;
2035	std::vector<tcu::TestCaseGroup*> testGroupStack;
2036	testGroupStack.push_back(gr);
2037
2038	for (const BoolParam& coherentParam : coherentParams)
2039	{
2040		subGroup = (new tcu::TestCaseGroup(testCtx, coherentParam.name));
2041		testGroupStack.back()->addChild(subGroup);
2042		testGroupStack.push_back(subGroup);
2043		for (const TestTypeParam& testTypeParam : testTypeParams)
2044		{
2045			subGroup = new tcu::TestCaseGroup(testCtx, testTypeParam.name);
2046			testGroupStack.back()->addChild(subGroup);
2047			testGroupStack.push_back(subGroup);
2048
2049			for (const VkSampleCountFlagParam& sampleCountParam : sampleCountParams)
2050			{
2051				if (testTypeParam.value == TestType::MsaaSampleMask && sampleCountParam.value == VK_SAMPLE_COUNT_1_BIT)
2052				{
2053					// SampleMask test requires MSAA
2054					continue;
2055				}
2056				if (isHelperClassTest(testTypeParam.value) && sampleCountParam.value != VK_SAMPLE_COUNT_1_BIT)
2057				{
2058					// HelperClass test designed for non msaa case
2059					continue;
2060				}
2061				subGroup = new tcu::TestCaseGroup(testCtx, sampleCountParam.name);
2062				testGroupStack.back()->addChild(subGroup);
2063				testGroupStack.push_back(subGroup);
2064
2065				for (const BoolParam& multiDrawsParam : multiDrawsParams)
2066				{
2067					if (isHelperClassTest(testTypeParam.value) && multiDrawsParam.value)
2068					{
2069						// helper class 2 draws but works like single draw call
2070						continue;
2071					}
2072
2073					subGroup = new tcu::TestCaseGroup(testCtx, multiDrawsParam.name);
2074					testGroupStack.back()->addChild(subGroup);
2075					testGroupStack.push_back(subGroup);
2076
2077					for (const BoolParam& multiPatchParam : multiPatchParams)
2078					{
2079						if (!coherentParam.value && multiPatchParam.value) // cannot guarantee
2080						{
2081							continue;
2082						}
2083						if (isHelperClassTest(testTypeParam.value) && multiPatchParam.value)
2084						{
2085							// helper class works on single patch cases
2086							continue;
2087						}
2088
2089						subGroup = new tcu::TestCaseGroup(testCtx, multiPatchParam.name);
2090						testGroupStack.back()->addChild(subGroup);
2091						testGroupStack.push_back(subGroup);
2092
2093						for (VkFormat format : formats)
2094						{
2095							tcu::TestCaseGroup* curGroup   = testGroupStack.back();
2096							const bool			hasDepth   = tcu::hasDepthComponent(mapVkFormat(format).order);
2097							const bool			hasStencil = tcu::hasStencilComponent(mapVkFormat(format).order);
2098							std::string			name	   = formatToName(format);
2099
2100							TestParam testParam				 = {};
2101							testParam.coherent				 = coherentParam.value;
2102							testParam.testType				 = testTypeParam.value;
2103							testParam.colorFormat			 = VK_FORMAT_R32G32B32A32_UINT;
2104							testParam.depthStencilFormat	 = VK_FORMAT_D32_SFLOAT_S8_UINT;
2105							testParam.m_sampleCount			 = sampleCountParam.value;
2106							testParam.multipleDrawCalls		 = multiDrawsParam.value;
2107							testParam.multiplePatchesPerDraw = multiPatchParam.value;
2108							testParam.frameBufferSize		 = kImageSize;
2109							if (testTypeParam.value == TestType::Depth ||
2110								testTypeParam.value == TestType::HelperClassDepth)
2111							{
2112								if (hasDepth)
2113								{
2114									testParam.depthStencilFormat = format;
2115									curGroup->addChild(new ShaderTileImageTestCase(testCtx, name, testParam));
2116								}
2117							}
2118							else if (testTypeParam.value == TestType::Stencil ||
2119									 testTypeParam.value == TestType::HelperClassStencil)
2120							{
2121								if (hasStencil)
2122								{
2123									testParam.depthStencilFormat = format;
2124									curGroup->addChild(new ShaderTileImageTestCase(testCtx, name, testParam));
2125								}
2126							}
2127							else
2128							{
2129								if (!hasStencil && !hasDepth)
2130								{
2131									if (isHelperClassTest(testTypeParam.value) && isNormalizedColorFormat(format))
2132									{
2133										// reduce helper class test cases and complexities
2134										continue;
2135									}
2136
2137									const deUint32 maxResultValue =
2138										(getDrawCallCount(&testParam) *
2139											 getPatchesPerDrawCount(testParam.multiplePatchesPerDraw) *
2140											 getColorAttachmentCount(testParam.testType) +
2141										 getSampleCount(testParam.m_sampleCount));
2142									const tcu::IVec4 channelBitDepth =
2143										tcu::getTextureFormatBitDepth(mapVkFormat(format));
2144
2145									// color output precision is less than test case.
2146									// ban the overflow problem.
2147									if (static_cast<deUint32>(1 << (channelBitDepth.y() - 1)) > maxResultValue)
2148									{
2149										testParam.colorFormat = format;
2150										curGroup->addChild(new ShaderTileImageTestCase(testCtx, name, testParam));
2151									}
2152								}
2153							}
2154						} // formats
2155						testGroupStack.pop_back();
2156					} // multiPatchParams
2157					testGroupStack.pop_back();
2158				} // multiDrawsParams
2159				testGroupStack.pop_back();
2160			} // sampleCountParams
2161			testGroupStack.pop_back();
2162		} // testTypeParams
2163		testGroupStack.pop_back();
2164	} // coherentParams
2165}
2166} // namespace
2167// anonymous namespace
2168
2169tcu::TestCaseGroup* createShaderTileImageTests(tcu::TestContext& testCtx)
2170{
2171	/* Add the color tests */
2172	tcu::TestCaseGroup* gr = new tcu::TestCaseGroup(testCtx, "shader_tile_image");
2173	createShaderTileImageTestVariations(testCtx, gr);
2174
2175	return gr;
2176}
2177
2178} // namespace rasterization
2179} // namespace vkt
2180