• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group Inc.
6  * Copyright (c) 2018-2020 NVIDIA Corporation
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 Tests for VK_KHR_fragment_shading_rate
23  * The test renders 9*9 triangles, where each triangle has one of the valid
24  * fragment sizes ({1,2,4},{1,2,4}) (clamped to implementation limits) for
25  * each of the pipeline shading rate and the primitive shading rate. The
26  * fragment shader does an atomic add to a memory location to get a unique
27  * identifier for the fragment, and outputs the primitive ID, atomic counter,
28  * fragment size, and some other info the the color output. Then a compute
29  * shader copies this to buffer memory, and the host verifies several
30  * properties of the output. For example, if a sample has a particular
31  * primitive ID and atomic value, then all other samples in the tile with
32  * the same primitive ID should have the same atomic value.
33  *//*--------------------------------------------------------------------*/
34 
35 #include "vktFragmentShadingRateBasic.hpp"
36 
37 #include "vkBufferWithMemory.hpp"
38 #include "vkImageWithMemory.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkBuilderUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkImageUtil.hpp"
45 
46 #include "vktTestGroupUtil.hpp"
47 #include "vktTestCase.hpp"
48 
49 #include "deDefs.h"
50 #include "deMath.h"
51 #include "deRandom.h"
52 #include "deSharedPtr.hpp"
53 #include "deString.h"
54 
55 #include "tcuTestCase.hpp"
56 #include "tcuTestLog.hpp"
57 
58 #include <string>
59 #include <sstream>
60 
61 namespace vkt
62 {
63 namespace FragmentShadingRate
64 {
65 namespace
66 {
67 using namespace vk;
68 using namespace std;
69 
70 #define NUM_TRIANGLES (9*9)
71 
72 enum class AttachmentUsage
73 {
74 	NO_ATTACHMENT = 0,
75 	NO_ATTACHMENT_PTR,
76 	WITH_ATTACHMENT,
77 };
78 
79 struct CaseDef
80 {
81 	deInt32 seed;
82 	VkExtent2D framebufferDim;
83 	VkSampleCountFlagBits samples;
84 	VkFragmentShadingRateCombinerOpKHR combinerOp[2];
85 	AttachmentUsage attachmentUsage;
86 	bool shaderWritesRate;
87 	bool geometryShader;
88 	bool useDynamicState;
89 	bool useDynamicRendering;
90 	bool useApiSampleMask;
91 	bool useSampleMaskIn;
92 	bool conservativeEnable;
93 	VkConservativeRasterizationModeEXT conservativeMode;
94 	bool useDepthStencil; // == fragDepth || fragStencil
95 	bool fragDepth;
96 	bool fragStencil;
97 	bool multiViewport;
98 	bool colorLayered;
99 	bool srLayered; // colorLayered must also be true
100 	deUint32 numColorLayers;
101 	bool multiView;
102 	bool interlock;
103 	bool sampleLocations;
104 	bool sampleShadingEnable;
105 	bool sampleShadingInput;
106 	bool sampleMaskTest;
107 
useAttachmentvkt::FragmentShadingRate::__anon238d709f0111::CaseDef108 	bool useAttachment () const
109 	{
110 		return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT);
111 	}
112 };
113 
114 class FSRTestInstance : public TestInstance
115 {
116 public:
117 						FSRTestInstance		(Context& context, const CaseDef& data);
118 						~FSRTestInstance	(void);
119 	tcu::TestStatus		iterate				(void);
120 
121 private:
122 	// Test parameters
123 	CaseDef				m_data;
124 
125 	// Cache simulated combiner operations, to avoid recomputing per-sample
126 	deInt32				m_simulateValueCount;
127 	vector<deInt32>		m_simulateCache;
128 	// Cache mapping of primitive ID to pipeline/primitive shading rate
129 	vector<deInt32>		m_primIDToPrimitiveShadingRate;
130 	vector<deInt32>		m_primIDToPipelineShadingRate;
131 	deUint32			m_supportedFragmentShadingRateCount;
132 	vector<VkPhysicalDeviceFragmentShadingRateKHR>	m_supportedFragmentShadingRates;
133 	VkPhysicalDeviceFragmentShadingRatePropertiesKHR	m_shadingRateProperties;
134 
135 	deInt32				PrimIDToPrimitiveShadingRate	(deInt32 primID);
136 	deInt32				PrimIDToPipelineShadingRate		(deInt32 primID);
137 	VkExtent2D			SanitizeExtent		(VkExtent2D ext) const;
138 	deInt32				SanitizeRate		(deInt32 rate) const;
139 	deInt32				ShadingRateExtentToClampedMask	(VkExtent2D ext, bool allowSwap) const;
140 	deInt32				ShadingRateExtentToEnum	(VkExtent2D ext) const;
141 	VkExtent2D			ShadingRateEnumToExtent	(deInt32 rate) const;
142 	deInt32				Simulate			(deInt32 rate0, deInt32 rate1, deInt32 rate2);
143 	VkExtent2D			Combine				(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const;
144 	bool				Force1x1			() const;
145 };
146 
FSRTestInstance(Context & context,const CaseDef & data)147 FSRTestInstance::FSRTestInstance (Context& context, const CaseDef& data)
148 	: vkt::TestInstance		(context)
149 	, m_data				(data)
150 	, m_simulateValueCount	(((4 * 4) | 4) + 1)
151 	, m_simulateCache		(m_simulateValueCount*m_simulateValueCount*m_simulateValueCount, ~0)
152 	, m_primIDToPrimitiveShadingRate(NUM_TRIANGLES, ~0)
153 	, m_primIDToPipelineShadingRate(NUM_TRIANGLES, ~0)
154 {
155 	m_supportedFragmentShadingRateCount = 0;
156 	m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, DE_NULL);
157 
158 	if (m_supportedFragmentShadingRateCount < 3)
159 		TCU_THROW(TestError, "*pFragmentShadingRateCount too small");
160 
161 	m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount);
162 	for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
163 	{
164 		m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
165 		m_supportedFragmentShadingRates[i].pNext = nullptr;
166 	}
167 	m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]);
168 
169 	m_shadingRateProperties = m_context.getFragmentShadingRateProperties();
170 }
171 
~FSRTestInstance(void)172 FSRTestInstance::~FSRTestInstance (void)
173 {
174 }
175 
176 class FSRTestCase : public TestCase
177 {
178 	public:
179 								FSRTestCase		(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
180 								~FSRTestCase	(void);
181 	virtual	void				initPrograms	(SourceCollections& programCollection) const;
182 	virtual TestInstance*		createInstance	(Context& context) const;
183 	virtual void				checkSupport	(Context& context) const;
184 
185 private:
186 	CaseDef						m_data;
187 };
188 
FSRTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)189 FSRTestCase::FSRTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
190 	: vkt::TestCase	(context, name, desc)
191 	, m_data		(data)
192 {
193 }
194 
~FSRTestCase(void)195 FSRTestCase::~FSRTestCase	(void)
196 {
197 }
198 
Force1x1() const199 bool FSRTestInstance::Force1x1() const
200 {
201 	if (m_data.useApiSampleMask && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
202 		return true;
203 
204 	if (m_data.useSampleMaskIn && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderSampleMask)
205 		return true;
206 
207 	if (m_data.conservativeEnable && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithConservativeRasterization)
208 		return true;
209 
210 	if (m_data.useDepthStencil && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderDepthStencilWrites)
211 		return true;
212 
213 	if (m_data.interlock && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithFragmentShaderInterlock)
214 		return true;
215 
216 	if (m_data.sampleLocations && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithCustomSampleLocations)
217 		return true;
218 
219 	if (m_data.sampleShadingEnable || m_data.sampleShadingInput)
220 		return true;
221 
222 	return false;
223 }
224 
225 static VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
226 								   VK_IMAGE_USAGE_SAMPLED_BIT |
227 								   VK_IMAGE_USAGE_TRANSFER_DST_BIT |
228 								   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
229 
checkSupport(Context & context) const230 void FSRTestCase::checkSupport(Context& context) const
231 {
232 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
233 
234 	if (m_data.useDynamicRendering)
235 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
236 
237 	if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
238 		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
239 
240 	if (m_data.shaderWritesRate &&
241 		!context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate)
242 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
243 
244 	if (!context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate &&
245 		m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
246 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
247 
248 	if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
249 		m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
250 		TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
251 
252 	VkImageFormatProperties imageProperties;
253 	VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), VK_FORMAT_R32G32B32A32_UINT, VK_IMAGE_TYPE_2D,
254 																							VK_IMAGE_TILING_OPTIMAL, cbUsage, 0, &imageProperties);
255 
256 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
257 		TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32B32A32_UINT not supported");
258 
259 	if (!(imageProperties.sampleCounts & m_data.samples))
260 		TCU_THROW(NotSupportedError, "color buffer sample count not supported");
261 
262 	if (m_data.numColorLayers > imageProperties.maxArrayLayers)
263 		TCU_THROW(NotSupportedError, "color buffer layers not supported");
264 
265 	if (m_data.useAttachment() && !context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
266 		TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
267 
268 	if (!context.getFragmentShadingRateProperties().fragmentShadingRateNonTrivialCombinerOps &&
269 		((m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR && m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
270 		 (m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR && m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
271 		TCU_THROW(NotSupportedError, "fragmentShadingRateNonTrivialCombinerOps not supported");
272 
273 	if (m_data.conservativeEnable)
274 	{
275 		context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
276 		if (m_data.conservativeMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT &&
277 			!context.getConservativeRasterizationPropertiesEXT().primitiveUnderestimation)
278 			TCU_THROW(NotSupportedError, "primitiveUnderestimation not supported");
279 	}
280 
281 	if (m_data.fragStencil)
282 		context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
283 
284 	if (m_data.multiViewport &&
285 		!context.getFragmentShadingRateProperties().primitiveFragmentShadingRateWithMultipleViewports)
286 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateWithMultipleViewports not supported");
287 
288 	if (m_data.srLayered &&
289 		!context.getFragmentShadingRateProperties().layeredShadingRateAttachments)
290 		TCU_THROW(NotSupportedError, "layeredShadingRateAttachments not supported");
291 
292 	if ((m_data.multiViewport || m_data.colorLayered) &&
293 		!m_data.geometryShader)
294 		context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
295 
296 	if (m_data.multiView && m_data.geometryShader &&
297 		!context.getMultiviewFeatures().multiviewGeometryShader)
298 		TCU_THROW(NotSupportedError, "multiviewGeometryShader not supported");
299 
300 	if (m_data.interlock &&
301 		!context.getFragmentShaderInterlockFeaturesEXT().fragmentShaderPixelInterlock)
302 		TCU_THROW(NotSupportedError, "fragmentShaderPixelInterlock not supported");
303 
304 	if (m_data.sampleLocations)
305 	{
306 		context.requireDeviceFunctionality("VK_EXT_sample_locations");
307 		if (!(m_data.samples & context.getSampleLocationsPropertiesEXT().sampleLocationSampleCounts))
308 			TCU_THROW(NotSupportedError, "samples not supported in sampleLocationSampleCounts");
309 	}
310 
311 	if (m_data.sampleMaskTest && !context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
312 		TCU_THROW(NotSupportedError, "fragmentShadingRateWithSampleMask not supported");
313 }
314 
315 // Error codes writted by the fragment shader
316 enum
317 {
318 	ERROR_NONE = 0,
319 	ERROR_FRAGCOORD_CENTER = 1,
320 	ERROR_VTG_READBACK = 2,
321 	ERROR_FRAGCOORD_DERIV = 3,
322 	ERROR_FRAGCOORD_IMPLICIT_DERIV = 4,
323 };
324 
initPrograms(SourceCollections & programCollection) const325 void FSRTestCase::initPrograms (SourceCollections& programCollection) const
326 {
327 	std::stringstream vss;
328 
329 	vss <<
330 		"#version 450 core\n"
331 		"#extension GL_EXT_fragment_shading_rate : enable\n"
332 		"#extension GL_ARB_shader_viewport_layer_array : enable\n"
333 		"layout(push_constant) uniform PC {\n"
334 		"	int shadingRate;\n"
335 		"} pc;\n"
336 		"layout(location = 0) in vec2 pos;\n"
337 		"layout(location = 0) out int instanceIndex;\n"
338 		"layout(location = 1) out int readbackok;\n"
339 		"layout(location = 2) out float zero;\n"
340 		"out gl_PerVertex\n"
341 		"{\n"
342 		"   vec4 gl_Position;\n"
343 		"};\n"
344 		"void main()\n"
345 		"{\n"
346 		"  gl_Position = vec4(pos, 0, 1);\n"
347 		"  instanceIndex = gl_InstanceIndex;\n"
348 		"  readbackok = 1;\n"
349 		"  zero = 0;\n";
350 
351 	if (m_data.shaderWritesRate)
352 	{
353 		vss << "  gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
354 
355 		// Verify that we can read from the output variable
356 		vss << "  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
357 
358 		if (!m_data.geometryShader)
359 		{
360 			if (m_data.multiViewport)
361 				vss << "  gl_ViewportIndex = instanceIndex & 1;\n";
362 			if (m_data.colorLayered)
363 				vss << "  gl_Layer = (instanceIndex & 2) >> 1;\n";
364 		}
365 	}
366 
367 	vss << "}\n";
368 
369 	programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
370 
371 	if (m_data.geometryShader)
372 	{
373 		std::string writeShadingRate = "";
374 		if (m_data.shaderWritesRate)
375 		{
376 			writeShadingRate =
377 				"  gl_PrimitiveShadingRateEXT = pc.shadingRate;\n"
378 				"  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
379 
380 			if (m_data.multiViewport)
381 				writeShadingRate += "  gl_ViewportIndex = inInstanceIndex[0] & 1;\n";
382 
383 			if (m_data.colorLayered)
384 				writeShadingRate += "  gl_Layer = (inInstanceIndex[0] & 2) >> 1;\n";
385 		}
386 
387 		std::stringstream gss;
388 		gss <<
389 			"#version 450 core\n"
390 			"#extension GL_EXT_fragment_shading_rate : enable\n"
391 			"\n"
392 			"layout(push_constant) uniform PC {\n"
393 			"	int shadingRate;\n"
394 			"} pc;\n"
395 			"\n"
396 			"in gl_PerVertex\n"
397 			"{\n"
398 			"   vec4 gl_Position;\n"
399 			"} gl_in[3];\n"
400 			"\n"
401 			"layout(location = 0) in int inInstanceIndex[];\n"
402 			"layout(location = 0) out int outInstanceIndex;\n"
403 			"layout(location = 1) out int readbackok;\n"
404 			"layout(location = 2) out float zero;\n"
405 			"layout(triangles) in;\n"
406 			"layout(triangle_strip, max_vertices=3) out;\n"
407 			"\n"
408 			"out gl_PerVertex {\n"
409 			"   vec4 gl_Position;\n"
410 			"};\n"
411 			"\n"
412 			"void main(void)\n"
413 			"{\n"
414 			"   gl_Position = gl_in[0].gl_Position;\n"
415 			"   outInstanceIndex = inInstanceIndex[0];\n"
416 			"   readbackok  = 1;\n"
417 			"   zero = 0;\n"
418 			<< writeShadingRate <<
419 			"   EmitVertex();"
420 			"\n"
421 			"   gl_Position = gl_in[1].gl_Position;\n"
422 			"   outInstanceIndex = inInstanceIndex[1];\n"
423 			"   readbackok = 1;\n"
424 			"   zero = 0;\n"
425 			<< writeShadingRate <<
426 			"   EmitVertex();"
427 			"\n"
428 			"   gl_Position = gl_in[2].gl_Position;\n"
429 			"   outInstanceIndex = inInstanceIndex[2];\n"
430 			"   readbackok = 1;\n"
431 			"   zero = 0;\n"
432 			<< writeShadingRate <<
433 			"   EmitVertex();"
434 			"}\n";
435 
436 		programCollection.glslSources.add("geom") << glu::GeometrySource(gss.str());
437 	}
438 
439 	std::stringstream fss;
440 
441 	fss <<
442 		"#version 450 core\n"
443 		"#extension GL_EXT_fragment_shading_rate : enable\n"
444 		"#extension GL_ARB_shader_stencil_export : enable\n"
445 		"#extension GL_ARB_fragment_shader_interlock : enable\n"
446 		"layout(location = 0) out uvec4 col0;\n"
447 		"layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
448 		"layout(set = 0, binding = 3) uniform usampler2D tex;\n"
449 		"layout(location = 0) flat in int instanceIndex;\n"
450 		"layout(location = 1) flat in int readbackok;\n"
451 		"layout(location = 2) " << (m_data.sampleShadingInput ? "sample " : "") << "in float zero;\n";
452 
453 	if (m_data.interlock)
454 		fss << "layout(pixel_interlock_ordered) in;\n";
455 
456 	fss <<
457 		"void main()\n"
458 		"{\n";
459 
460 	if (m_data.interlock)
461 		fss << "  beginInvocationInterlockARB();\n";
462 
463 	fss <<
464 		// X component gets shading rate enum
465 		"  col0.x = gl_ShadingRateEXT;\n"
466 		"  col0.y = 0;\n"
467 		// Z component gets packed primitiveID | atomic value
468 		"  col0.z = (instanceIndex << 24) | ((atomicAdd(buf.counter, 1) + 1) & 0x00FFFFFFu);\n"
469 		"  ivec2 fragCoordXY = ivec2(gl_FragCoord.xy);\n"
470 		"  ivec2 fragSize = ivec2(1<<((gl_ShadingRateEXT/4)&3), 1<<(gl_ShadingRateEXT&3));\n"
471 		// W component gets error code
472 		"  col0.w = uint(zero)" << (m_data.sampleShadingInput ? " * gl_SampleID" : "") << ";\n"
473 		"  if (((fragCoordXY - fragSize / 2) % fragSize) != ivec2(0,0))\n"
474 		"    col0.w = " << ERROR_FRAGCOORD_CENTER << ";\n";
475 
476 	if (m_data.shaderWritesRate)
477 	{
478 		fss <<
479 			"  if (readbackok != 1)\n"
480 			"    col0.w = " << ERROR_VTG_READBACK << ";\n";
481 	}
482 
483 	// When sample shading, gl_FragCoord is more likely to give bad derivatives,
484 	// e.g. due to a partially covered quad having some pixels center sample and
485 	// some sample at a sample location.
486 	if (!m_data.sampleShadingEnable && !m_data.sampleShadingInput)
487 	{
488 		fss << "  if (dFdx(gl_FragCoord.xy) != ivec2(fragSize.x, 0) || dFdy(gl_FragCoord.xy) != ivec2(0, fragSize.y))\n"
489 			   "    col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (int(dFdx(gl_FragCoord.xy)) << 14) | (int(dFdx(gl_FragCoord.xy)) << 8) | " << ERROR_FRAGCOORD_DERIV << ";\n";
490 
491 		fss << "  uint implicitDerivX = texture(tex, vec2(gl_FragCoord.x / textureSize(tex, 0).x, 0)).x;\n"
492 			   "  uint implicitDerivY = texture(tex, vec2(0, gl_FragCoord.y / textureSize(tex, 0).y)).x;\n"
493 			   "  if (implicitDerivX != fragSize.x || implicitDerivY != fragSize.y)\n"
494 			   "    col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (implicitDerivY << 14) | (implicitDerivX << 8) | " << ERROR_FRAGCOORD_IMPLICIT_DERIV << ";\n";
495 	}
496 	// Y component gets sample mask value
497 	if (m_data.useSampleMaskIn)
498 		fss << "  col0.y = gl_SampleMaskIn[0];\n";
499 
500 	if (m_data.fragDepth)
501 		fss << "  gl_FragDepth = float(instanceIndex) / float(" << NUM_TRIANGLES << ");\n";
502 
503 	if (m_data.fragStencil)
504 		fss << "  gl_FragStencilRefARB = instanceIndex;\n";
505 
506 	if (m_data.interlock)
507 		fss << "  endInvocationInterlockARB();\n";
508 
509 	fss <<
510 		"}\n";
511 
512 	programCollection.glslSources.add("frag") << glu::FragmentSource(fss.str());
513 
514 	std::stringstream css;
515 
516 	std::string fsampType = m_data.samples > 1 ?  "texture2DMSArray" :  "texture2DArray";
517 	std::string usampType = m_data.samples > 1 ? "utexture2DMSArray" : "utexture2DArray";
518 
519 	// Compute shader copies color/depth/stencil to linear layout in buffer memory
520 	css <<
521 		"#version 450 core\n"
522 		"#extension GL_EXT_samplerless_texture_functions : enable\n"
523 		"layout(set = 0, binding = 1) uniform " << usampType << " colorTex;\n"
524 		"layout(set = 0, binding = 2, std430) buffer Block0 { uvec4 b[]; } colorbuf;\n"
525 		"layout(set = 0, binding = 4, std430) buffer Block1 { float b[]; } depthbuf;\n"
526 		"layout(set = 0, binding = 5, std430) buffer Block2 { uint b[]; } stencilbuf;\n"
527 		"layout(set = 0, binding = 6) uniform " << fsampType << " depthTex;\n"
528 		"layout(set = 0, binding = 7) uniform " << usampType << " stencilTex;\n"
529 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
530 		"void main()\n"
531 		"{\n"
532 		"   for (int i = 0; i < " << m_data.samples << "; ++i) {\n"
533 		"      uint idx = ((gl_GlobalInvocationID.z * " << m_data.framebufferDim.height << " + gl_GlobalInvocationID.y) * " << m_data.framebufferDim.width << " + gl_GlobalInvocationID.x) * " << m_data.samples << " + i;\n"
534 		"      colorbuf.b[idx] = texelFetch(colorTex, ivec3(gl_GlobalInvocationID.xyz), i);\n";
535 
536 	if (m_data.fragDepth)
537 		css << "      depthbuf.b[idx] = texelFetch(depthTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
538 
539 	if (m_data.fragStencil)
540 		css << "      stencilbuf.b[idx] = texelFetch(stencilTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
541 
542 	css <<
543 		"   }\n"
544 		"}\n";
545 
546 	programCollection.glslSources.add("comp") << glu::ComputeSource(css.str());
547 }
548 
createInstance(Context & context) const549 TestInstance* FSRTestCase::createInstance (Context& context) const
550 {
551 	return new FSRTestInstance(context, m_data);
552 }
553 
ShadingRateExtentToEnum(VkExtent2D ext) const554 deInt32 FSRTestInstance::ShadingRateExtentToEnum(VkExtent2D ext) const
555 {
556 	ext.width = deCtz32(ext.width);
557 	ext.height = deCtz32(ext.height);
558 
559 	return (ext.width << 2) | ext.height;
560 }
561 
ShadingRateEnumToExtent(deInt32 rate) const562 VkExtent2D FSRTestInstance::ShadingRateEnumToExtent(deInt32 rate) const
563 {
564 	VkExtent2D ret;
565 	ret.width = 1 << ((rate/4) & 3);
566 	ret.height = 1 << (rate & 3);
567 
568 	return ret;
569 }
570 
Combine(VkExtent2D ext0,VkExtent2D ext1,VkFragmentShadingRateCombinerOpKHR comb) const571 VkExtent2D FSRTestInstance::Combine(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const
572 {
573 	VkExtent2D ret;
574 	switch (comb)
575 	{
576 	default:
577 		DE_ASSERT(0);
578 		// fallthrough
579 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR:
580 		return ext0;
581 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR:
582 		return ext1;
583 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR:
584 		ret = { de::min(ext0.width, ext1.width), de::min(ext0.height, ext1.height) };
585 		return ret;
586 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR:
587 		ret = { de::max(ext0.width, ext1.width), de::max(ext0.height, ext1.height) };
588 		return ret;
589 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR:
590 		ret = { ext0.width * ext1.width, ext0.height * ext1.height };
591 		if (!m_shadingRateProperties.fragmentShadingRateStrictMultiplyCombiner)
592 		{
593 			if (ext0.width == 1 && ext1.width == 1)
594 				ret.width = 2;
595 			if (ext0.height == 1 && ext1.height == 1)
596 				ret.height = 2;
597 		}
598 		return ret;
599 	}
600 }
601 
Simulate(deInt32 rate0,deInt32 rate1,deInt32 rate2)602 deInt32 FSRTestInstance::Simulate(deInt32 rate0, deInt32 rate1, deInt32 rate2)
603 {
604 	deInt32 &cachedRate = m_simulateCache[(rate2*m_simulateValueCount + rate1)*m_simulateValueCount + rate0];
605 	if (cachedRate != ~0)
606 		return cachedRate;
607 
608 	VkExtent2D extent0 = ShadingRateEnumToExtent(rate0);
609 	VkExtent2D extent1 = ShadingRateEnumToExtent(rate1);
610 	VkExtent2D extent2 = ShadingRateEnumToExtent(rate2);
611 
612 	deInt32 finalMask = 0;
613 	// Simulate once for implementations that don't allow swapping rate xy,
614 	// and once for those that do. Any of those results is allowed.
615 	for (deUint32 allowSwap = 0; allowSwap <= 1; ++allowSwap)
616 	{
617 		// Combine rate 0 and 1, get a mask of possible clamped rates
618 		VkExtent2D intermed = Combine(extent0, extent1, m_data.combinerOp[0]);
619 		deInt32 intermedMask = ShadingRateExtentToClampedMask(intermed, allowSwap == 1);
620 
621 		// For each clamped rate, combine that with rate 2 and accumulate the possible clamped rates
622 		for (int i = 0; i < 16; ++i)
623 		{
624 			if (intermedMask & (1<<i))
625 			{
626 				VkExtent2D final = Combine(ShadingRateEnumToExtent(i), extent2, m_data.combinerOp[1]);
627 				finalMask |= ShadingRateExtentToClampedMask(final, allowSwap == 1);
628 			}
629 		}
630 		{
631 			// unclamped intermediate value is also permitted
632 			VkExtent2D final = Combine(intermed, extent2, m_data.combinerOp[1]);
633 			finalMask |= ShadingRateExtentToClampedMask(final, allowSwap == 1);
634 		}
635 	}
636 
637 	if (Force1x1())
638 		finalMask = 0x1;
639 
640 	cachedRate = finalMask;
641 	return finalMask;
642 }
643 
644 // If a rate is not valid (<=4x4), clamp it to something valid.
645 // This is only used for "inputs" to the system, not to mimic
646 // how the implementation internally clamps intermediate values.
SanitizeExtent(VkExtent2D ext) const647 VkExtent2D FSRTestInstance::SanitizeExtent(VkExtent2D ext) const
648 {
649 	DE_ASSERT(ext.width > 0 && ext.height > 0);
650 
651 	ext.width = de::min(ext.width, 4u);
652 	ext.height = de::min(ext.height, 4u);
653 
654 	return ext;
655 }
656 
657 // Map an extent to a mask of all modes smaller than or equal to it in either dimension
ShadingRateExtentToClampedMask(VkExtent2D ext,bool allowSwap) const658 deInt32 FSRTestInstance::ShadingRateExtentToClampedMask(VkExtent2D ext, bool allowSwap) const
659 {
660 	deUint32 desiredSize = ext.width * ext.height;
661 
662 	deInt32 mask = 0;
663 
664 	while (desiredSize > 0)
665 	{
666 		// First, find modes that maximize the area
667 		for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
668 		{
669 			const VkPhysicalDeviceFragmentShadingRateKHR &supportedRate = m_supportedFragmentShadingRates[i];
670 			if ((supportedRate.sampleCounts & m_data.samples) &&
671 				supportedRate.fragmentSize.width * supportedRate.fragmentSize.height == desiredSize &&
672 				((supportedRate.fragmentSize.width  <= ext.width && supportedRate.fragmentSize.height <= ext.height) ||
673 				 (supportedRate.fragmentSize.height <= ext.width && supportedRate.fragmentSize.width  <= ext.height && allowSwap)))
674 			{
675 				mask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
676 			}
677 		}
678 		if (mask)
679 		{
680 			// Amongst the modes that maximize the area, pick the ones that
681 			// minimize the aspect ratio. Prefer ratio of 1, then 2, then 4.
682 			// 1x1 = 0, 2x2 = 5, 4x4 = 10
683 			static const deUint32 aspectMaskRatio1 = 0x421;
684 			// 2x1 = 4, 1x2 = 1, 4x2 = 9, 2x4 = 6
685 			static const deUint32 aspectMaskRatio2 = 0x252;
686 			// 4x1 = 8, 1x4 = 2,
687 			static const deUint32 aspectMaskRatio4 = 0x104;
688 
689 			if (mask & aspectMaskRatio1)
690 			{
691 				mask &= aspectMaskRatio1;
692 				break;
693 			}
694 			if (mask & aspectMaskRatio2)
695 			{
696 				mask &= aspectMaskRatio2;
697 				break;
698 			}
699 			if (mask & aspectMaskRatio4)
700 			{
701 				mask &= aspectMaskRatio4;
702 				break;
703 			}
704 			DE_ASSERT(0);
705 		}
706 		desiredSize /= 2;
707 	}
708 
709 	return mask;
710 }
711 
712 
SanitizeRate(deInt32 rate) const713 deInt32 FSRTestInstance::SanitizeRate(deInt32 rate) const
714 {
715 	VkExtent2D extent = ShadingRateEnumToExtent(rate);
716 
717 	extent = SanitizeExtent(extent);
718 
719 	return ShadingRateExtentToEnum(extent);
720 }
721 
722 // Map primID % 9 to primitive shading rate
PrimIDToPrimitiveShadingRate(deInt32 primID)723 deInt32 FSRTestInstance::PrimIDToPrimitiveShadingRate(deInt32 primID)
724 {
725 	deInt32 &cachedRate = m_primIDToPrimitiveShadingRate[primID];
726 	if (cachedRate != ~0)
727 		return cachedRate;
728 
729 	VkExtent2D extent;
730 	extent.width = 1 << (primID % 3);
731 	extent.height = 1 << ((primID/3) % 3);
732 
733 	cachedRate = ShadingRateExtentToEnum(extent);
734 	return cachedRate;
735 }
736 
737 // Map primID / 9 to pipeline shading rate
PrimIDToPipelineShadingRate(deInt32 primID)738 deInt32 FSRTestInstance::PrimIDToPipelineShadingRate(deInt32 primID)
739 {
740 	deInt32 &cachedRate = m_primIDToPipelineShadingRate[primID];
741 	if (cachedRate != ~0)
742 		return cachedRate;
743 
744 	primID /= 9;
745 	VkExtent2D extent;
746 	extent.width = 1 << (primID % 3);
747 	extent.height = 1 << ((primID/3) % 3);
748 
749 	cachedRate = ShadingRateExtentToEnum(extent);
750 	return cachedRate;
751 }
752 
CreateCachedBuffer(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkBufferCreateInfo & bufferCreateInfo)753 static de::MovePtr<BufferWithMemory> CreateCachedBuffer(const vk::DeviceInterface&		vk,
754 														const vk::VkDevice				device,
755 														vk::Allocator&					allocator,
756 														const vk::VkBufferCreateInfo&	bufferCreateInfo)
757 {
758 	try
759 	{
760 		return de::MovePtr<BufferWithMemory>(new BufferWithMemory(
761 			vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Cached));
762 	}
763 	catch (const tcu::NotSupportedError&)
764 	{
765 		return de::MovePtr<BufferWithMemory>(new BufferWithMemory(
766 			vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
767 	}
768 }
769 
iterate(void)770 tcu::TestStatus FSRTestInstance::iterate (void)
771 {
772 	const DeviceInterface&	vk						= m_context.getDeviceInterface();
773 	const VkDevice			device					= m_context.getDevice();
774 	tcu::TestLog&			log						= m_context.getTestContext().getLog();
775 	Allocator&				allocator				= m_context.getDefaultAllocator();
776 	VkFlags					allShaderStages			= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
777 	VkFlags					allPipelineStages		= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
778 													  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
779 													  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
780 													  VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
781 													  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
782 													  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
783 													  VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV;
784 	const VkFormat			cbFormat				= VK_FORMAT_R32G32B32A32_UINT;
785 	const VkFormat			dsFormat				= VK_FORMAT_D32_SFLOAT_S8_UINT;
786 
787 	if (m_data.geometryShader)
788 	{
789 		allShaderStages	|= VK_SHADER_STAGE_GEOMETRY_BIT;
790 		allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
791 	}
792 
793 	deRandom rnd;
794 	deRandom_init(&rnd, m_data.seed);
795 
796 	qpTestResult res = QP_TEST_RESULT_PASS;
797 	deUint32 numUnexpected1x1Samples = 0;
798 	deUint32 numTotalSamples = 0;
799 
800 	enum AttachmentModes
801 	{
802 		ATTACHMENT_MODE_DEFAULT = 0,
803 		ATTACHMENT_MODE_LAYOUT_OPTIMAL,
804 		ATTACHMENT_MODE_IMAGELESS,
805 		ATTACHMENT_MODE_2DARRAY,
806 		ATTACHMENT_MODE_TILING_LINEAR,
807 
808 		ATTACHMENT_MODE_COUNT,
809 	};
810 
811 	deUint32 numSRLayers = m_data.srLayered ? 2u : 1u;
812 
813 	VkExtent2D minFragmentShadingRateAttachmentTexelSize = {1, 1};
814 	VkExtent2D maxFragmentShadingRateAttachmentTexelSize = {1, 1};
815 	deUint32 maxFragmentShadingRateAttachmentTexelSizeAspectRatio = 1;
816 	if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
817 	{
818 		minFragmentShadingRateAttachmentTexelSize = m_context.getFragmentShadingRateProperties().minFragmentShadingRateAttachmentTexelSize;
819 		maxFragmentShadingRateAttachmentTexelSize = m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSize;
820 		maxFragmentShadingRateAttachmentTexelSizeAspectRatio = m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
821 	}
822 
823 	VkDeviceSize atomicBufferSize = sizeof(deUint32);
824 
825 	de::MovePtr<BufferWithMemory> atomicBuffer;
826 	atomicBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
827 		vk, device, allocator, makeBufferCreateInfo(atomicBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
828 
829 	deUint32 *abuf = (deUint32 *)atomicBuffer->getAllocation().getHostPtr();
830 
831 	// NUM_TRIANGLES triangles, 3 vertices, 2 components of float position
832 	VkDeviceSize vertexBufferSize = NUM_TRIANGLES * 3 * 2 * sizeof(float);
833 
834 	de::MovePtr<BufferWithMemory> vertexBuffer;
835 	vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
836 		vk, device, allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
837 
838 	float *vbuf = (float *)vertexBuffer->getAllocation().getHostPtr();
839 	for (deInt32 i = 0; i < (deInt32)(vertexBufferSize / sizeof(float)); ++i)
840 	{
841 		vbuf[i] = deRandom_getFloat(&rnd)*2.0f - 1.0f;
842 	}
843 	flushAlloc(vk, device, vertexBuffer->getAllocation());
844 
845 	VkDeviceSize colorOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples * 4 * sizeof(deUint32) * m_data.numColorLayers;
846 	de::MovePtr<BufferWithMemory> colorOutputBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
847 
848 	VkDeviceSize depthOutputBufferSize = 0, stencilOutputBufferSize = 0;
849 	de::MovePtr<BufferWithMemory> depthOutputBuffer, stencilOutputBuffer;
850 	if (m_data.useDepthStencil)
851 	{
852 		depthOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples * sizeof(float) * m_data.numColorLayers;
853 		depthOutputBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(depthOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
854 
855 		stencilOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples * sizeof(deUint32) * m_data.numColorLayers;
856 		stencilOutputBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(stencilOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
857 	}
858 
859 	deUint32 minSRTexelWidth = minFragmentShadingRateAttachmentTexelSize.width;
860 	deUint32 minSRTexelHeight = minFragmentShadingRateAttachmentTexelSize.height;
861 	deUint32 maxSRWidth = (m_data.framebufferDim.width + minSRTexelWidth - 1) / minSRTexelWidth;
862 	deUint32 maxSRHeight = (m_data.framebufferDim.height + minSRTexelHeight - 1) / minSRTexelHeight;
863 
864 	// max size over all formats
865 	VkDeviceSize srFillBufferSize = numSRLayers * maxSRWidth * maxSRHeight * 32/*4 component 64-bit*/;
866 	de::MovePtr<BufferWithMemory> srFillBuffer;
867 	deUint8 *fillPtr = DE_NULL;
868 	if (m_data.useAttachment())
869 	{
870 		srFillBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(srFillBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
871 		fillPtr = (deUint8 *)srFillBuffer->getAllocation().getHostPtr();
872 	}
873 
874 	de::MovePtr<ImageWithMemory> cbImage;
875 	Move<VkImageView> cbImageView;
876 	{
877 		const VkImageCreateInfo			imageCreateInfo			=
878 		{
879 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
880 			DE_NULL,								// const void*				pNext;
881 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
882 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
883 			cbFormat,								// VkFormat					format;
884 			{
885 				m_data.framebufferDim.width,		// deUint32	width;
886 				m_data.framebufferDim.height,		// deUint32	height;
887 				1u									// deUint32	depth;
888 			},										// VkExtent3D				extent;
889 			1u,										// deUint32					mipLevels;
890 			m_data.numColorLayers,					// deUint32					arrayLayers;
891 			m_data.samples,							// VkSampleCountFlagBits	samples;
892 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
893 			cbUsage,								// VkImageUsageFlags		usage;
894 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
895 			0u,										// deUint32					queueFamilyIndexCount;
896 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
897 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
898 		};
899 		cbImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
900 			vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
901 
902 		VkImageViewCreateInfo		imageViewCreateInfo		=
903 		{
904 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
905 			DE_NULL,									// const void*				pNext;
906 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
907 			**cbImage,									// VkImage					image;
908 			VK_IMAGE_VIEW_TYPE_2D_ARRAY,				// VkImageViewType			viewType;
909 			cbFormat,									// VkFormat					format;
910 			{
911 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
912 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
913 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
914 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
915 			},											// VkComponentMapping		 components;
916 			{
917 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
918 				0u,										// deUint32				baseMipLevel;
919 				1u,										// deUint32				levelCount;
920 				0u,										// deUint32				baseArrayLayer;
921 				m_data.numColorLayers					// deUint32				layerCount;
922 			}											// VkImageSubresourceRange	subresourceRange;
923 		};
924 		cbImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
925 	}
926 
927 	de::MovePtr<ImageWithMemory> dsImage;
928 	Move<VkImageView> dsImageView, dImageView, sImageView;
929 	VkImageUsageFlags dsUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
930 								VK_IMAGE_USAGE_SAMPLED_BIT |
931 								VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
932 								VK_IMAGE_USAGE_TRANSFER_DST_BIT;
933 	if (m_data.useDepthStencil)
934 	{
935 		const VkImageCreateInfo			imageCreateInfo			=
936 		{
937 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
938 			DE_NULL,								// const void*				pNext;
939 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
940 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
941 			dsFormat,								// VkFormat					format;
942 			{
943 				m_data.framebufferDim.width,		// deUint32	width;
944 				m_data.framebufferDim.height,		// deUint32	height;
945 				1u									// deUint32	depth;
946 			},										// VkExtent3D				extent;
947 			1u,										// deUint32					mipLevels;
948 			m_data.numColorLayers,					// deUint32					arrayLayers;
949 			m_data.samples,							// VkSampleCountFlagBits	samples;
950 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
951 			dsUsage,								// VkImageUsageFlags		usage;
952 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
953 			0u,										// deUint32					queueFamilyIndexCount;
954 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
955 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
956 		};
957 		dsImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
958 			vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
959 
960 		VkImageViewCreateInfo		imageViewCreateInfo		=
961 		{
962 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
963 			DE_NULL,									// const void*				pNext;
964 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
965 			**dsImage,									// VkImage					image;
966 			VK_IMAGE_VIEW_TYPE_2D_ARRAY,				// VkImageViewType			viewType;
967 			dsFormat,									// VkFormat					format;
968 			{
969 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
970 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
971 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
972 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
973 			},											// VkComponentMapping		 components;
974 			{
975 				VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,	// VkImageAspectFlags	aspectMask;
976 				0u,										// deUint32				baseMipLevel;
977 				1u,										// deUint32				levelCount;
978 				0u,										// deUint32				baseArrayLayer;
979 				m_data.numColorLayers					// deUint32				layerCount;
980 			}											// VkImageSubresourceRange	subresourceRange;
981 		};
982 		dsImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
983 		imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
984 		dImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
985 		imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
986 		sImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
987 	}
988 
989 	// Image used to test implicit derivative calculations.
990 	// Filled with a value of 1<<lod.
991 	de::MovePtr<ImageWithMemory> derivImage;
992 	Move<VkImageView> derivImageView;
993 	VkImageUsageFlags derivUsage = VK_IMAGE_USAGE_SAMPLED_BIT |
994 								   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
995 	deUint32 derivNumLevels;
996 	{
997 		deUint32 maxDim = de::max(m_context.getFragmentShadingRateProperties().maxFragmentSize.width, m_context.getFragmentShadingRateProperties().maxFragmentSize.height);
998 		derivNumLevels = 1 + deCtz32(maxDim);
999 		const VkImageCreateInfo			imageCreateInfo			=
1000 		{
1001 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1002 			DE_NULL,								// const void*				pNext;
1003 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1004 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1005 			VK_FORMAT_R32_UINT,						// VkFormat					format;
1006 			{
1007 				m_context.getFragmentShadingRateProperties().maxFragmentSize.width,		// deUint32	width;
1008 				m_context.getFragmentShadingRateProperties().maxFragmentSize.height,	// deUint32	height;
1009 				1u									// deUint32	depth;
1010 			},										// VkExtent3D				extent;
1011 			derivNumLevels,							// deUint32					mipLevels;
1012 			1u,										// deUint32					arrayLayers;
1013 			VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1014 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1015 			derivUsage,								// VkImageUsageFlags		usage;
1016 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1017 			0u,										// deUint32					queueFamilyIndexCount;
1018 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1019 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1020 		};
1021 		derivImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1022 			vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1023 
1024 		VkImageViewCreateInfo		imageViewCreateInfo		=
1025 		{
1026 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1027 			DE_NULL,									// const void*				pNext;
1028 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1029 			**derivImage,								// VkImage					image;
1030 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
1031 			VK_FORMAT_R32_UINT,							// VkFormat					format;
1032 			{
1033 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1034 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1035 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1036 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1037 			},											// VkComponentMapping		 components;
1038 			{
1039 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
1040 				0u,										// deUint32				baseMipLevel;
1041 				derivNumLevels,							// deUint32				levelCount;
1042 				0u,										// deUint32				baseArrayLayer;
1043 				1u										// deUint32				layerCount;
1044 			}											// VkImageSubresourceRange	subresourceRange;
1045 		};
1046 		derivImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1047 	}
1048 
1049 	// sampler used with derivImage
1050 	const struct VkSamplerCreateInfo		samplerInfo	=
1051 	{
1052 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// sType
1053 		DE_NULL,									// pNext
1054 		0u,											// flags
1055 		VK_FILTER_NEAREST,							// magFilter
1056 		VK_FILTER_NEAREST,							// minFilter
1057 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
1058 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
1059 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
1060 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
1061 		0.0f,										// mipLodBias
1062 		VK_FALSE,									// anisotropyEnable
1063 		1.0f,										// maxAnisotropy
1064 		DE_FALSE,									// compareEnable
1065 		VK_COMPARE_OP_ALWAYS,						// compareOp
1066 		0.0f,										// minLod
1067 		(float)derivNumLevels,						// maxLod
1068 		VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,		// borderColor
1069 		VK_FALSE,									// unnormalizedCoords
1070 	};
1071 
1072 	Move<VkSampler>			sampler	= createSampler(vk, device, &samplerInfo);
1073 
1074 	Move<vk::VkDescriptorSetLayout>	descriptorSetLayout;
1075 	VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
1076 
1077 	const VkDescriptorSetLayoutBinding bindings[] =
1078 	{
1079 		{
1080 			0u,										// binding
1081 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1082 			1u,										// descriptorCount
1083 			allShaderStages,						// stageFlags
1084 			DE_NULL,								// pImmutableSamplers
1085 		},
1086 		{
1087 			1u,										// binding
1088 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		// descriptorType
1089 			1u,										// descriptorCount
1090 			allShaderStages,						// stageFlags
1091 			DE_NULL,								// pImmutableSamplers
1092 		},
1093 		{
1094 			2u,										// binding
1095 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1096 			1u,										// descriptorCount
1097 			allShaderStages,						// stageFlags
1098 			DE_NULL,								// pImmutableSamplers
1099 		},
1100 		{
1101 			3u,										// binding
1102 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	// descriptorType
1103 			1u,										// descriptorCount
1104 			allShaderStages,						// stageFlags
1105 			DE_NULL,								// pImmutableSamplers
1106 		},
1107 		{
1108 			4u,										// binding
1109 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1110 			1u,										// descriptorCount
1111 			allShaderStages,						// stageFlags
1112 			DE_NULL,								// pImmutableSamplers
1113 		},
1114 		{
1115 			5u,										// binding
1116 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1117 			1u,										// descriptorCount
1118 			allShaderStages,						// stageFlags
1119 			DE_NULL,								// pImmutableSamplers
1120 		},
1121 		{
1122 			6u,										// binding
1123 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		// descriptorType
1124 			1u,										// descriptorCount
1125 			allShaderStages,						// stageFlags
1126 			DE_NULL,								// pImmutableSamplers
1127 		},
1128 		{
1129 			7u,										// binding
1130 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		// descriptorType
1131 			1u,										// descriptorCount
1132 			allShaderStages,						// stageFlags
1133 			DE_NULL,								// pImmutableSamplers
1134 		},
1135 	};
1136 
1137 	// Create a layout and allocate a descriptor set for it.
1138 	const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
1139 	{
1140 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
1141 		DE_NULL,													// pNext
1142 		layoutCreateFlags,											// flags
1143 		sizeof(bindings)/sizeof(bindings[0]),						// bindingCount
1144 		&bindings[0]												// pBindings
1145 	};
1146 
1147 	descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
1148 
1149 	const VkPushConstantRange				pushConstantRange				=
1150 	{
1151 		allShaderStages,											// VkShaderStageFlags					stageFlags;
1152 		0u,															// deUint32								offset;
1153 		sizeof(deInt32)												// deUint32								size;
1154 	};
1155 
1156 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1157 	{
1158 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
1159 		DE_NULL,													// pNext
1160 		(VkPipelineLayoutCreateFlags)0,
1161 		1,															// setLayoutCount
1162 		&descriptorSetLayout.get(),									// pSetLayouts
1163 		1u,															// pushConstantRangeCount
1164 		&pushConstantRange,											// pPushConstantRanges
1165 	};
1166 
1167 	Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1168 
1169 	const Unique<VkShaderModule>	cs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
1170 
1171 	const VkPipelineShaderStageCreateInfo	csShaderCreateInfo =
1172 	{
1173 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1174 		DE_NULL,
1175 		(VkPipelineShaderStageCreateFlags)0,
1176 		VK_SHADER_STAGE_COMPUTE_BIT,								// stage
1177 		*cs,														// shader
1178 		"main",
1179 		DE_NULL,													// pSpecializationInfo
1180 	};
1181 
1182 	const VkComputePipelineCreateInfo		pipelineCreateInfo =
1183 	{
1184 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1185 		DE_NULL,
1186 		0u,															// flags
1187 		csShaderCreateInfo,											// cs
1188 		*pipelineLayout,											// layout
1189 		(vk::VkPipeline)0,											// basePipelineHandle
1190 		0u,															// basePipelineIndex
1191 	};
1192 	Move<VkPipeline> computePipeline = createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo, NULL);
1193 
1194 	for (deUint32 modeIdx = 0; modeIdx < ATTACHMENT_MODE_COUNT; ++modeIdx)
1195 	{
1196 		// If we're not using an attachment, don't test all the different attachment modes
1197 		if (modeIdx != ATTACHMENT_MODE_DEFAULT && !m_data.useAttachment())
1198 			continue;
1199 
1200 		// Consider all uint formats possible
1201 		static const VkFormat srFillFormats[] =
1202 		{
1203 			VK_FORMAT_R8_UINT,
1204 			VK_FORMAT_R8G8_UINT,
1205 			VK_FORMAT_R8G8B8_UINT,
1206 			VK_FORMAT_R8G8B8A8_UINT,
1207 			VK_FORMAT_R16_UINT,
1208 			VK_FORMAT_R16G16_UINT,
1209 			VK_FORMAT_R16G16B16_UINT,
1210 			VK_FORMAT_R16G16B16A16_UINT,
1211 			VK_FORMAT_R32_UINT,
1212 			VK_FORMAT_R32G32_UINT,
1213 			VK_FORMAT_R32G32B32_UINT,
1214 			VK_FORMAT_R32G32B32A32_UINT,
1215 			VK_FORMAT_R64_UINT,
1216 			VK_FORMAT_R64G64_UINT,
1217 			VK_FORMAT_R64G64B64_UINT,
1218 			VK_FORMAT_R64G64B64A64_UINT,
1219 		};
1220 		// Only test all formats in the default mode
1221 		deUint32 numFillFormats = modeIdx == ATTACHMENT_MODE_DEFAULT ? (deUint32)(sizeof(srFillFormats)/sizeof(srFillFormats[0])) : 1u;
1222 
1223 		// Iterate over all supported tile sizes and formats
1224 		for (deUint32 srTexelWidth  = minFragmentShadingRateAttachmentTexelSize.width;
1225 					  srTexelWidth <= maxFragmentShadingRateAttachmentTexelSize.width;
1226 					  srTexelWidth *= 2)
1227 		for (deUint32 srTexelHeight  = minFragmentShadingRateAttachmentTexelSize.height;
1228 					  srTexelHeight <= maxFragmentShadingRateAttachmentTexelSize.height;
1229 					  srTexelHeight *= 2)
1230 		for (deUint32 formatIdx = 0; formatIdx < numFillFormats; ++formatIdx)
1231 		{
1232 
1233 			deUint32 aspectRatio = (srTexelHeight > srTexelWidth) ? (srTexelHeight / srTexelWidth) : (srTexelWidth / srTexelHeight);
1234 			if (aspectRatio > maxFragmentShadingRateAttachmentTexelSizeAspectRatio)
1235 				continue;
1236 
1237 			// Go through the loop only once when not using an attachment
1238 			if (!m_data.useAttachment() &&
1239 				(srTexelWidth != minFragmentShadingRateAttachmentTexelSize.width ||
1240 				 srTexelHeight != minFragmentShadingRateAttachmentTexelSize.height ||
1241 				 formatIdx != 0))
1242 				 continue;
1243 
1244 			bool imagelessFB = modeIdx == ATTACHMENT_MODE_IMAGELESS;
1245 
1246 			deUint32 srWidth = (m_data.framebufferDim.width + srTexelWidth - 1) / srTexelWidth;
1247 			deUint32 srHeight = (m_data.framebufferDim.height + srTexelHeight - 1) / srTexelHeight;
1248 
1249 			VkFormat srFormat = srFillFormats[formatIdx];
1250 			deUint32 srFillBpp = tcu::getPixelSize(mapVkFormat(srFormat));
1251 
1252 			VkImageLayout srLayout = modeIdx == ATTACHMENT_MODE_LAYOUT_OPTIMAL ? VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR : VK_IMAGE_LAYOUT_GENERAL;
1253 			VkImageViewType srViewType = modeIdx == ATTACHMENT_MODE_2DARRAY ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
1254 			VkImageTiling srTiling = (modeIdx == ATTACHMENT_MODE_TILING_LINEAR) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1255 
1256 			VkFormatProperties srFormatProperties;
1257 			m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), srFormat, &srFormatProperties);
1258 			VkFormatFeatureFlags srFormatFeatures = srTiling == VK_IMAGE_TILING_LINEAR ? srFormatProperties.linearTilingFeatures : srFormatProperties.optimalTilingFeatures;
1259 
1260 			if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
1261 				!(srFormatFeatures & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
1262 			{
1263 				if (srFormat == VK_FORMAT_R8_UINT && srTiling == VK_IMAGE_TILING_OPTIMAL)
1264 				{
1265 					log << tcu::TestLog::Message << "VK_FORMAT_R8_UINT/VK_IMAGE_TILING_OPTIMAL don't support VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR" << tcu::TestLog::EndMessage;
1266 					res = QP_TEST_RESULT_FAIL;
1267 				}
1268 				continue;
1269 			}
1270 
1271 			Move<vk::VkDescriptorPool>		descriptorPool;
1272 			Move<vk::VkDescriptorSet>		descriptorSet;
1273 			VkDescriptorPoolCreateFlags poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1274 
1275 			vk::DescriptorPoolBuilder poolBuilder;
1276 			for (deInt32 i = 0; i < (deInt32)(sizeof(bindings)/sizeof(bindings[0])); ++i)
1277 				poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1278 
1279 			descriptorPool = poolBuilder.build(vk, device, poolCreateFlags, 1u);
1280 			descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1281 
1282 			de::MovePtr<ImageWithMemory> srImage;
1283 			Move<VkImageView> srImageView;
1284 			VkImageUsageFlags srUsage = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1285 										VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1286 										VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1287 
1288 			if (m_data.useAttachment())
1289 			{
1290 				const VkImageCreateInfo			imageCreateInfo			=
1291 				{
1292 					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1293 					DE_NULL,								// const void*				pNext;
1294 					(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1295 					VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1296 					srFormat,								// VkFormat					format;
1297 					{
1298 						srWidth,							// deUint32	width;
1299 						srHeight,							// deUint32	height;
1300 						1u									// deUint32	depth;
1301 					},										// VkExtent3D				extent;
1302 					1u,										// deUint32					mipLevels;
1303 					numSRLayers,							// deUint32					arrayLayers;
1304 					VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1305 					srTiling,								// VkImageTiling			tiling;
1306 					srUsage,								// VkImageUsageFlags		usage;
1307 					VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1308 					0u,										// deUint32					queueFamilyIndexCount;
1309 					DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1310 					VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1311 				};
1312 				srImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1313 					vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1314 
1315 				VkImageViewCreateInfo		imageViewCreateInfo		=
1316 				{
1317 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1318 					DE_NULL,									// const void*				pNext;
1319 					(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1320 					**srImage,									// VkImage					image;
1321 					srViewType,									// VkImageViewType			viewType;
1322 					srFormat,									// VkFormat					format;
1323 					{
1324 						VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1325 						VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1326 						VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1327 						VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1328 					},											// VkComponentMapping		 components;
1329 					{
1330 						VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
1331 						0u,										// deUint32				baseMipLevel;
1332 						1u,										// deUint32				levelCount;
1333 						0u,										// deUint32				baseArrayLayer;
1334 						srViewType == VK_IMAGE_VIEW_TYPE_2D ?
1335 						1 : numSRLayers,						// deUint32				layerCount;
1336 					}											// VkImageSubresourceRange	subresourceRange;
1337 				};
1338 				srImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1339 			}
1340 
1341 			VkDescriptorImageInfo imageInfo;
1342 			VkDescriptorBufferInfo bufferInfo;
1343 
1344 			VkWriteDescriptorSet w =
1345 			{
1346 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
1347 				DE_NULL,														// pNext
1348 				*descriptorSet,													// dstSet
1349 				(deUint32)0,													// dstBinding
1350 				0,																// dstArrayElement
1351 				1u,																// descriptorCount
1352 				bindings[0].descriptorType,										// descriptorType
1353 				&imageInfo,														// pImageInfo
1354 				&bufferInfo,													// pBufferInfo
1355 				DE_NULL,														// pTexelBufferView
1356 			};
1357 
1358 			abuf[0] = 0;
1359 			flushAlloc(vk, device, atomicBuffer->getAllocation());
1360 
1361 			bufferInfo = makeDescriptorBufferInfo(**atomicBuffer, 0, atomicBufferSize);
1362 			w.dstBinding = 0;
1363 			w.descriptorType = bindings[0].descriptorType;
1364 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1365 
1366 			imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImageView, VK_IMAGE_LAYOUT_GENERAL);
1367 			w.dstBinding = 1;
1368 			w.descriptorType = bindings[1].descriptorType;
1369 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1370 
1371 			bufferInfo = makeDescriptorBufferInfo(**colorOutputBuffer, 0, colorOutputBufferSize);
1372 			w.dstBinding = 2;
1373 			w.descriptorType = bindings[2].descriptorType;
1374 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1375 
1376 			imageInfo = makeDescriptorImageInfo(*sampler, *derivImageView, VK_IMAGE_LAYOUT_GENERAL);
1377 			w.dstBinding = 3;
1378 			w.descriptorType = bindings[3].descriptorType;
1379 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1380 
1381 			if (m_data.useDepthStencil)
1382 			{
1383 				bufferInfo = makeDescriptorBufferInfo(**depthOutputBuffer, 0, depthOutputBufferSize);
1384 				w.dstBinding = 4;
1385 				w.descriptorType = bindings[4].descriptorType;
1386 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1387 
1388 				bufferInfo = makeDescriptorBufferInfo(**stencilOutputBuffer, 0, stencilOutputBufferSize);
1389 				w.dstBinding = 5;
1390 				w.descriptorType = bindings[5].descriptorType;
1391 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1392 
1393 				imageInfo = makeDescriptorImageInfo(DE_NULL, *dImageView, VK_IMAGE_LAYOUT_GENERAL);
1394 				w.dstBinding = 6;
1395 				w.descriptorType = bindings[6].descriptorType;
1396 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1397 
1398 				imageInfo = makeDescriptorImageInfo(DE_NULL, *sImageView, VK_IMAGE_LAYOUT_GENERAL);
1399 				w.dstBinding = 7;
1400 				w.descriptorType = bindings[7].descriptorType;
1401 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1402 			}
1403 
1404 			Move<VkRenderPass> renderPass;
1405 			Move<VkFramebuffer> framebuffer;
1406 
1407 			std::vector<VkImageView> attachments;
1408 			attachments.push_back(*cbImageView);
1409 			deUint32 dsAttachmentIdx = 0, srAttachmentIdx = 0;
1410 			if (m_data.useAttachment())
1411 			{
1412 				srAttachmentIdx = (deUint32)attachments.size();
1413 				attachments.push_back(*srImageView);
1414 			}
1415 			if (m_data.useDepthStencil)
1416 			{
1417 				dsAttachmentIdx = (deUint32)attachments.size();
1418 				attachments.push_back(*dsImageView);
1419 			}
1420 
1421 			if (!m_data.useDynamicRendering)
1422 			{
1423 				const vk::VkAttachmentReference2 colorAttachmentReference
1424 				{
1425 					VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,					// sType
1426 					DE_NULL,													// pNext
1427 					0,															// attachment
1428 					vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
1429 					0,															// aspectMask
1430 				};
1431 
1432 				const vk::VkAttachmentReference2 fragmentShadingRateAttachment =
1433 				{
1434 					VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,					// sType
1435 					DE_NULL,													// pNext
1436 					srAttachmentIdx,											// attachment
1437 					srLayout,													// layout
1438 					0,															// aspectMask
1439 				};
1440 
1441 				const vk::VkAttachmentReference2 depthAttachmentReference =
1442 				{
1443 					VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,					// sType
1444 					DE_NULL,													// pNext
1445 					dsAttachmentIdx,											// attachment
1446 					vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
1447 					0,															// aspectMask
1448 				};
1449 
1450 				const bool										noAttachmentPtr				= (m_data.attachmentUsage == AttachmentUsage::NO_ATTACHMENT_PTR);
1451 				const VkFragmentShadingRateAttachmentInfoKHR	shadingRateAttachmentInfo	=
1452 				{
1453 					VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,							// VkStructureType				  sType;
1454 					DE_NULL,																				// const void*					  pNext;
1455 					(noAttachmentPtr ? nullptr : &fragmentShadingRateAttachment),							// const VkAttachmentReference2*	pFragmentShadingRateAttachment;
1456 					{ srTexelWidth, srTexelHeight },														// VkExtent2D					   shadingRateAttachmentTexelSize;
1457 				};
1458 
1459 				const bool						useAttachmentInfo	= (m_data.attachmentUsage != AttachmentUsage::NO_ATTACHMENT);
1460 				const VkSubpassDescription2		subpassDesc			=
1461 				{
1462 					VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,						// sType
1463 					(useAttachmentInfo ? &shadingRateAttachmentInfo : nullptr),		// pNext;
1464 					(vk::VkSubpassDescriptionFlags)0,								// flags
1465 					vk::VK_PIPELINE_BIND_POINT_GRAPHICS,							// pipelineBindPoint
1466 					m_data.multiView ? 0x3 : 0u,									// viewMask
1467 					0u,																// inputCount
1468 					DE_NULL,														// pInputAttachments
1469 					1,																// colorCount
1470 					&colorAttachmentReference,										// pColorAttachments
1471 					DE_NULL,														// pResolveAttachments
1472 					m_data.useDepthStencil ? &depthAttachmentReference : DE_NULL,	// depthStencilAttachment
1473 					0u,																// preserveCount
1474 					DE_NULL,														// pPreserveAttachments
1475 				};
1476 
1477 				std::vector<VkAttachmentDescription2> attachmentDescriptions
1478 				{
1479 					{
1480 						VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType sType;
1481 						DE_NULL,									// const void* pNext;
1482 						(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
1483 						VK_FORMAT_R32G32B32A32_UINT,				// VkFormat							format;
1484 						m_data.samples,								// VkSampleCountFlagBits			samples;
1485 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
1486 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
1487 						VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
1488 						VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
1489 						VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
1490 						VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
1491 					}
1492 				};
1493 				if (m_data.useAttachment())
1494 					attachmentDescriptions.push_back(
1495 					{
1496 						VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType sType;
1497 						DE_NULL,									// const void* pNext;
1498 						(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
1499 						srFormat,									// VkFormat							format;
1500 						VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
1501 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
1502 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
1503 						VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
1504 						VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
1505 						srLayout,									// VkImageLayout					initialLayout;
1506 						srLayout									// VkImageLayout					finalLayout;
1507 					}
1508 					);
1509 
1510 				if (m_data.useDepthStencil)
1511 					attachmentDescriptions.push_back(
1512 					{
1513 						VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType sType;
1514 						DE_NULL,									// const void* pNext;
1515 						(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
1516 						VK_FORMAT_D32_SFLOAT_S8_UINT,				// VkFormat							format;
1517 						m_data.samples,								// VkSampleCountFlagBits			samples;
1518 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
1519 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
1520 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				stencilLoadOp;
1521 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				stencilStoreOp;
1522 						VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
1523 						VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
1524 					}
1525 					);
1526 
1527 				const VkRenderPassCreateInfo2	renderPassParams	=
1528 				{
1529 					VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,			// sType
1530 					DE_NULL,												// pNext
1531 					(vk::VkRenderPassCreateFlags)0,
1532 					(deUint32)attachmentDescriptions.size(),				// attachmentCount
1533 					&attachmentDescriptions[0],								// pAttachments
1534 					1u,														// subpassCount
1535 					&subpassDesc,											// pSubpasses
1536 					0u,														// dependencyCount
1537 					DE_NULL,												// pDependencies
1538 					0u,														// correlatedViewMaskCount
1539 					DE_NULL,												// pCorrelatedViewMasks
1540 				};
1541 
1542 				renderPass = createRenderPass2(vk, device, &renderPassParams);
1543 
1544 				std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo;
1545 				framebufferAttachmentImageInfo.push_back(
1546 					{
1547 						VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		//  VkStructureType		sType;
1548 						DE_NULL,													//  const void*			pNext;
1549 						(VkImageCreateFlags)0u,										//  VkImageCreateFlags	flags;
1550 						cbUsage,													//  VkImageUsageFlags	usage;
1551 						m_data.framebufferDim.width,								//  deUint32			width;
1552 						m_data.framebufferDim.height,								//  deUint32			height;
1553 						m_data.numColorLayers,										//  deUint32			layerCount;
1554 						0u,															//  deUint32			viewFormatCount;
1555 						DE_NULL														//  const VkFormat*		pViewFormats;
1556 					}
1557 				);
1558 				if (m_data.useAttachment())
1559 					framebufferAttachmentImageInfo.push_back(
1560 					{
1561 						VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		//  VkStructureType		sType;
1562 						DE_NULL,													//  const void*			pNext;
1563 						(VkImageCreateFlags)0u,										//  VkImageCreateFlags	flags;
1564 						srUsage,													//  VkImageUsageFlags	usage;
1565 						srWidth,													//  deUint32			width;
1566 						srHeight,													//  deUint32			height;
1567 						numSRLayers,												//  deUint32			layerCount;
1568 						0u,															//  deUint32			viewFormatCount;
1569 						DE_NULL														//  const VkFormat*		pViewFormats;
1570 					}
1571 					);
1572 
1573 				if (m_data.useDepthStencil)
1574 					framebufferAttachmentImageInfo.push_back(
1575 					{
1576 						VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		//  VkStructureType		sType;
1577 						DE_NULL,													//  const void*			pNext;
1578 						(VkImageCreateFlags)0u,										//  VkImageCreateFlags	flags;
1579 						dsUsage,													//  VkImageUsageFlags	usage;
1580 						m_data.framebufferDim.width,								//  deUint32			width;
1581 						m_data.framebufferDim.height,								//  deUint32			height;
1582 						m_data.numColorLayers,										//  deUint32			layerCount;
1583 						0u,															//  deUint32			viewFormatCount;
1584 						DE_NULL														//  const VkFormat*		pViewFormats;
1585 					}
1586 					);
1587 
1588 				const VkFramebufferAttachmentsCreateInfo				framebufferAttachmentsCreateInfo	=
1589 				{
1590 					VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO,		//  VkStructureType								sType;
1591 					DE_NULL,													//  const void*									pNext;
1592 					(deUint32)framebufferAttachmentImageInfo.size(),			//  deUint32									attachmentImageInfoCount;
1593 					&framebufferAttachmentImageInfo[0]							//  const VkFramebufferAttachmentImageInfo*		pAttachmentImageInfos;
1594 				};
1595 
1596 				const vk::VkFramebufferCreateInfo	framebufferParams	=
1597 				{
1598 					vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// sType
1599 					imagelessFB ? &framebufferAttachmentsCreateInfo : DE_NULL,				// pNext
1600 					(vk::VkFramebufferCreateFlags)(imagelessFB ? VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT : 0),
1601 					*renderPass,									// renderPass
1602 					(deUint32)attachments.size(),					// attachmentCount
1603 					imagelessFB ? DE_NULL : &attachments[0],		// pAttachments
1604 					m_data.framebufferDim.width,					// width
1605 					m_data.framebufferDim.height,					// height
1606 					m_data.multiView ? 1 : m_data.numColorLayers,	// layers
1607 				};
1608 
1609 				framebuffer = createFramebuffer(vk, device, &framebufferParams);
1610 			}
1611 
1612 			const VkVertexInputBindingDescription		vertexBinding =
1613 			{
1614 				0u,							// deUint32				binding;
1615 				sizeof(float) * 2,			// deUint32				stride;
1616 				VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
1617 			};
1618 			const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
1619 			{
1620 				0u,							// deUint32	location;
1621 				0u,							// deUint32	binding;
1622 				VK_FORMAT_R32G32_SFLOAT,	// VkFormat	format;
1623 				0u							// deUint32	offset;
1624 			};
1625 
1626 			const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
1627 			{
1628 				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
1629 				DE_NULL,													// const void*								pNext;
1630 				(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
1631 				1u,															// deUint32									vertexBindingDescriptionCount;
1632 				&vertexBinding,												// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1633 				1u,															// deUint32									vertexAttributeDescriptionCount;
1634 				&vertexInputAttributeDescription							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1635 			};
1636 
1637 			const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateCreateInfo	=
1638 			{
1639 				VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
1640 				DE_NULL,														// const void*								pNext;
1641 				(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
1642 				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
1643 				VK_FALSE														// VkBool32									primitiveRestartEnable;
1644 			};
1645 
1646 			const VkPipelineRasterizationConservativeStateCreateInfoEXT consRastState =
1647 			{
1648 				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,	// VkStructureType										   sType;
1649 				DE_NULL,																		// const void*											   pNext;
1650 				(VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,						// VkPipelineRasterizationConservativeStateCreateFlagsEXT	flags;
1651 				m_data.conservativeMode,														// VkConservativeRasterizationModeEXT						conservativeRasterizationMode;
1652 				0.0f,																			// float													 extraPrimitiveOverestimationSize;
1653 			};
1654 
1655 			const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
1656 			{
1657 				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
1658 				m_data.conservativeEnable ? &consRastState : DE_NULL,			// const void*								pNext;
1659 				(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
1660 				VK_FALSE,														// VkBool32									depthClampEnable;
1661 				VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
1662 				VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
1663 				VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
1664 				VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace								frontFace;
1665 				VK_FALSE,														// VkBool32									depthBiasEnable;
1666 				0.0f,															// float									depthBiasConstantFactor;
1667 				0.0f,															// float									depthBiasClamp;
1668 				0.0f,															// float									depthBiasSlopeFactor;
1669 				1.0f															// float									lineWidth;
1670 			};
1671 
1672 			// Kill some bits from each AA mode
1673 			const VkSampleMask	sampleMask	= m_data.sampleMaskTest ? 0x9 : 0x7D56;
1674 			const VkSampleMask*	pSampleMask = m_data.useApiSampleMask ? &sampleMask : DE_NULL;
1675 
1676 			// All samples at pixel center. We'll validate that pixels are fully covered or uncovered.
1677 			std::vector<VkSampleLocationEXT> sampleLocations(m_data.samples, { 0.5f, 0.5f });
1678 			const VkSampleLocationsInfoEXT sampleLocationsInfo =
1679 			{
1680 				VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,	// VkStructureType				sType;
1681 				DE_NULL,										// const void*					pNext;
1682 				(VkSampleCountFlagBits)m_data.samples,			// VkSampleCountFlagBits		sampleLocationsPerPixel;
1683 				{ 1, 1 },										// VkExtent2D					sampleLocationGridSize;
1684 				(deUint32)m_data.samples,						// uint32_t						sampleLocationsCount;
1685 				&sampleLocations[0],							// const VkSampleLocationEXT*	pSampleLocations;
1686 			};
1687 
1688 			const VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo =
1689 			{
1690 				VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,	// VkStructureType			sType;
1691 				DE_NULL,															// const void*				pNext;
1692 				VK_TRUE,															// VkBool32					sampleLocationsEnable;
1693 				sampleLocationsInfo,												// VkSampleLocationsInfoEXT	sampleLocationsInfo;
1694 			};
1695 
1696 			const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo =
1697 			{
1698 				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
1699 				m_data.sampleLocations ? &pipelineSampleLocationsCreateInfo : DE_NULL,	// const void*					pNext
1700 				0u,															// VkPipelineMultisampleStateCreateFlags	flags
1701 				(VkSampleCountFlagBits)m_data.samples,						// VkSampleCountFlagBits					rasterizationSamples
1702 				(VkBool32)m_data.sampleShadingEnable,						// VkBool32									sampleShadingEnable
1703 				1.0f,														// float									minSampleShading
1704 				pSampleMask,												// const VkSampleMask*						pSampleMask
1705 				VK_FALSE,													// VkBool32									alphaToCoverageEnable
1706 				VK_FALSE													// VkBool32									alphaToOneEnable
1707 			};
1708 
1709 			std::vector<VkViewport> viewports;
1710 			std::vector<VkRect2D> scissors;
1711 			if (m_data.multiViewport)
1712 			{
1713 				// Split the viewport into left and right halves
1714 				int x0 = 0, x1 = m_data.framebufferDim.width/2, x2 = m_data.framebufferDim.width;
1715 
1716 				viewports.push_back(makeViewport((float)x0, 0, (float)(x1-x0), (float)m_data.framebufferDim.height, 0.0f, 1.0f));
1717 				scissors.push_back(makeRect2D(x0, 0, x1-x0, m_data.framebufferDim.height));
1718 
1719 				viewports.push_back(makeViewport((float)x1, 0, (float)(x2-x1), (float)m_data.framebufferDim.height, 0.0f, 1.0f));
1720 				scissors.push_back(makeRect2D(x1, 0, x2-x1, m_data.framebufferDim.height));
1721 			}
1722 			else
1723 			{
1724 				viewports.push_back(makeViewport(m_data.framebufferDim.width, m_data.framebufferDim.height));
1725 				scissors.push_back(makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height));
1726 			}
1727 
1728 			const VkPipelineViewportStateCreateInfo			viewportStateCreateInfo				=
1729 			{
1730 				VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// VkStructureType							sType
1731 				DE_NULL,													// const void*								pNext
1732 				(VkPipelineViewportStateCreateFlags)0,						// VkPipelineViewportStateCreateFlags		flags
1733 				(deUint32)viewports.size(),									// deUint32									viewportCount
1734 				&viewports[0],												// const VkViewport*						pViewports
1735 				(deUint32)scissors.size(),									// deUint32									scissorCount
1736 				&scissors[0]												// const VkRect2D*							pScissors
1737 			};
1738 
1739 			Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1740 			Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1741 			Move<VkShaderModule> geomShader;
1742 			if (m_data.geometryShader)
1743 				geomShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0);
1744 
1745 			deUint32 numStages = m_data.geometryShader ? 3 : 2u;
1746 
1747 			const VkPipelineShaderStageCreateInfo	shaderCreateInfo[3] =
1748 			{
1749 				{
1750 					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1751 					DE_NULL,
1752 					(VkPipelineShaderStageCreateFlags)0,
1753 					VK_SHADER_STAGE_VERTEX_BIT,									// stage
1754 					*vertShader,												// shader
1755 					"main",
1756 					DE_NULL,													// pSpecializationInfo
1757 				},
1758 				{
1759 					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1760 					DE_NULL,
1761 					(VkPipelineShaderStageCreateFlags)0,
1762 					VK_SHADER_STAGE_FRAGMENT_BIT,								// stage
1763 					*fragShader,												// shader
1764 					"main",
1765 					DE_NULL,													// pSpecializationInfo
1766 				},
1767 				{
1768 					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1769 					DE_NULL,
1770 					(VkPipelineShaderStageCreateFlags)0,
1771 					VK_SHADER_STAGE_GEOMETRY_BIT,								// stage
1772 					*geomShader,												// shader
1773 					"main",
1774 					DE_NULL,													// pSpecializationInfo
1775 				}
1776 			};
1777 
1778 			const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState		=
1779 			{
1780 				VK_FALSE,				// VkBool32					 blendEnable;
1781 				VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcColorBlendFactor;
1782 				VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
1783 				VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
1784 				VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			srcAlphaBlendFactor;
1785 				VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
1786 				VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
1787 				0xf						// VkColorComponentFlags	colorWriteMask;
1788 			};
1789 
1790 			const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo		=
1791 			{
1792 				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1793 				DE_NULL,													// const void*									pNext;
1794 				0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1795 				VK_FALSE,													// VkBool32										logicOpEnable;
1796 				VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1797 				1u,															// deUint32										attachmentCount;
1798 				&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1799 				{ 1.0f, 1.0f, 1.0f, 1.0f }									// float										blendConstants[4];
1800 			};
1801 
1802 			const deUint32 fragSizeWH = m_data.sampleMaskTest ? 2 : 0;
1803 
1804 			VkPipelineRenderingCreateInfoKHR renderingCreateInfo
1805 			{
1806 				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1807 				DE_NULL,
1808 				m_data.multiView ? 0x3 : 0u,
1809 				1u,
1810 				&cbFormat,
1811 				m_data.useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED,
1812 				m_data.useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED
1813 			};
1814 
1815 			VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo =
1816 			{
1817 				VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,	// VkStructureType						sType;
1818 				m_data.useDynamicRendering ? &renderingCreateInfo : DE_NULL,			// const void*							pNext;
1819 				{ fragSizeWH, fragSizeWH },												// VkExtent2D							fragmentSize;
1820 				{ m_data.combinerOp[0], m_data.combinerOp[1] },							// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
1821 			};
1822 
1823 			VkDynamicState dynamicState = VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR;
1824 			const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
1825 			{
1826 				VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType						sType;
1827 				DE_NULL,													// const void*							pNext;
1828 				(VkPipelineDynamicStateCreateFlags)0,						// VkPipelineDynamicStateCreateFlags	flags;
1829 				m_data.useDynamicState ? 1u : 0u,							// uint32_t								dynamicStateCount;
1830 				&dynamicState,												// const VkDynamicState*				pDynamicStates;
1831 			};
1832 
1833 			// Enable depth/stencil writes, always passing
1834 			VkPipelineDepthStencilStateCreateInfo		depthStencilStateParams				=
1835 			{
1836 				VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
1837 				DE_NULL,													// const void*								pNext;
1838 				0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
1839 				VK_TRUE,													// VkBool32									depthTestEnable;
1840 				VK_TRUE,													// VkBool32									depthWriteEnable;
1841 				VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
1842 				VK_FALSE,													// VkBool32									depthBoundsTestEnable;
1843 				VK_TRUE,													// VkBool32									stencilTestEnable;
1844 				// VkStencilOpState	front;
1845 				{
1846 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
1847 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
1848 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
1849 					VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
1850 					0u,						// deUint32		compareMask;
1851 					0xFFu,					// deUint32		writeMask;
1852 					0xFFu,					// deUint32		reference;
1853 				},
1854 				// VkStencilOpState	back;
1855 				{
1856 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
1857 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
1858 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
1859 					VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
1860 					0u,						// deUint32		compareMask;
1861 					0xFFu,					// deUint32		writeMask;
1862 					0xFFu,					// deUint32		reference;
1863 				},
1864 				0.0f,						// float			minDepthBounds;
1865 				0.0f,						// float			maxDepthBounds;
1866 			};
1867 
1868 			const VkGraphicsPipelineCreateInfo				graphicsPipelineCreateInfo		=
1869 			{
1870 				VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1871 				&shadingRateStateCreateInfo,						// const void*										pNext;
1872 				(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
1873 				numStages,											// deUint32											stageCount;
1874 				&shaderCreateInfo[0],								// const VkPipelineShaderStageCreateInfo*			pStages;
1875 				&vertexInputStateCreateInfo,						// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1876 				&inputAssemblyStateCreateInfo,						// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1877 				DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1878 				&viewportStateCreateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
1879 				&rasterizationStateCreateInfo,						// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
1880 				&multisampleStateCreateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1881 				&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1882 				&colorBlendStateCreateInfo,							// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1883 				&dynamicStateCreateInfo,							// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1884 				pipelineLayout.get(),								// VkPipelineLayout									layout;
1885 				renderPass.get(),									// VkRenderPass										renderPass;
1886 				0u,													// deUint32											subpass;
1887 				DE_NULL,											// VkPipeline										basePipelineHandle;
1888 				0													// int												basePipelineIndex;
1889 			};
1890 
1891 			VkImageMemoryBarrier imageBarrier =
1892 			{
1893 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
1894 				DE_NULL,											// const void*			pNext
1895 				0u,													// VkAccessFlags		srcAccessMask
1896 				VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		dstAccessMask
1897 				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout		oldLayout
1898 				VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		newLayout
1899 				VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
1900 				VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
1901 				**cbImage,											// VkImage				image
1902 				{
1903 					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
1904 					0u,										// uint32_t				baseMipLevel
1905 					VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
1906 					0u,										// uint32_t				baseArray
1907 					VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
1908 				}
1909 			};
1910 
1911 			const VkQueue					queue					= m_context.getUniversalQueue();
1912 			Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
1913 			Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1914 			VkClearValue					clearColor				= makeClearValueColorU32(0, 0, 0, 0);
1915 			VkClearValue					clearDepthStencil		= makeClearValueDepthStencil(0.0, 0);
1916 
1917 			beginCommandBuffer(vk, *cmdBuffer, 0u);
1918 
1919 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1920 									(VkDependencyFlags)0,
1921 									0, (const VkMemoryBarrier*)DE_NULL,
1922 									0, (const VkBufferMemoryBarrier*)DE_NULL,
1923 									1, &imageBarrier);
1924 
1925 			imageBarrier.image = **derivImage;
1926 			imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1927 
1928 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1929 									(VkDependencyFlags)0,
1930 									0, (const VkMemoryBarrier*)DE_NULL,
1931 									0, (const VkBufferMemoryBarrier*)DE_NULL,
1932 									1, &imageBarrier);
1933 
1934 			// Clear level to 1<<level
1935 			for (deUint32 i = 0; i < derivNumLevels; ++i)
1936 			{
1937 				VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, i, 1u, 0u, 1u);
1938 				VkClearValue clearLevelColor = makeClearValueColorU32(1<<i,0,0,0);
1939 				vk.cmdClearColorImage(*cmdBuffer, **derivImage, VK_IMAGE_LAYOUT_GENERAL, &clearLevelColor.color, 1, &range);
1940 			}
1941 
1942 			// Clear color buffer to transparent black
1943 			{
1944 				VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
1945 				vk.cmdClearColorImage(*cmdBuffer, **cbImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1946 			}
1947 
1948 			// Clear depth and stencil
1949 			if (m_data.useDepthStencil)
1950 			{
1951 				VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
1952 				VkImageMemoryBarrier dsBarrier = imageBarrier;
1953 				dsBarrier.image = **dsImage;
1954 				dsBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1955 				dsBarrier.subresourceRange = range;
1956 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1957 										0u, // dependencyFlags
1958 										0u, nullptr,
1959 										0u, nullptr,
1960 										1u, &dsBarrier);
1961 				vk.cmdClearDepthStencilImage(*cmdBuffer, **dsImage, VK_IMAGE_LAYOUT_GENERAL, &clearDepthStencil.depthStencil, 1, &range);
1962 			}
1963 
1964 			// Initialize shading rate image with varying values
1965 			if (m_data.useAttachment())
1966 			{
1967 				imageBarrier.image = **srImage;
1968 				imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1969 
1970 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1971 										(VkDependencyFlags)0,
1972 										0, (const VkMemoryBarrier*)DE_NULL,
1973 										0, (const VkBufferMemoryBarrier*)DE_NULL,
1974 										1, &imageBarrier);
1975 
1976 				deMemset(fillPtr, 0, (size_t)srFillBufferSize);
1977 				for (deUint32 layer = 0; layer < numSRLayers; ++layer)
1978 				{
1979 					for (deUint32 x = 0; x < srWidth; ++x)
1980 					{
1981 						for (deUint32 y = 0; y < srHeight; ++y)
1982 						{
1983 							deUint32 idx = (layer*srHeight + y)*srWidth + x;
1984 							deUint8 val = (deUint8)SanitizeRate(idx & 0xF);
1985 							// actual shading rate is always in the LSBs of the first byte of a texel
1986 							fillPtr[srFillBpp*idx] = val;
1987 						}
1988 					}
1989 				}
1990 				flushAlloc(vk, device, srFillBuffer->getAllocation());
1991 
1992 				const VkBufferImageCopy				copyRegion							=
1993 				{
1994 					0u,																	// VkDeviceSize			bufferOffset;
1995 					0u,																	// deUint32				bufferRowLength;
1996 					0u,																	// deUint32				bufferImageHeight;
1997 					{
1998 						VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags	aspect;
1999 						0u,																// deUint32				mipLevel;
2000 						0u,																// deUint32				baseArrayLayer;
2001 						numSRLayers,													// deUint32				layerCount;
2002 					},																	// VkImageSubresourceLayers imageSubresource;
2003 					{ 0, 0, 0 },														// VkOffset3D			imageOffset;
2004 					{ srWidth, srHeight, 1 },											// VkExtent3D			imageExtent;
2005 				};
2006 
2007 				vk.cmdCopyBufferToImage(*cmdBuffer, **srFillBuffer, **srImage, VK_IMAGE_LAYOUT_GENERAL, 1, &copyRegion);
2008 
2009 				imageBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
2010 				imageBarrier.newLayout = srLayout;
2011 
2012 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2013 										(VkDependencyFlags)0,
2014 										0, (const VkMemoryBarrier*)DE_NULL,
2015 										0, (const VkBufferMemoryBarrier*)DE_NULL,
2016 										1, &imageBarrier);
2017 			}
2018 
2019 			VkMemoryBarrier					memBarrier =
2020 			{
2021 				VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// sType
2022 				DE_NULL,							// pNext
2023 				0u,									// srcAccessMask
2024 				0u,									// dstAccessMask
2025 			};
2026 
2027 			memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
2028 			memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
2029 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, allPipelineStages,
2030 				0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2031 
2032 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
2033 
2034 			vector<Move<VkPipeline>> pipelines;
2035 
2036 			// If using dynamic state, create a single graphics pipeline and bind it
2037 			if (m_data.useDynamicState)
2038 			{
2039 				pipelines.push_back(createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo));
2040 				vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[0]);
2041 			}
2042 
2043 			VkRect2D renderArea = makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
2044 			if (m_data.useDynamicRendering)
2045 			{
2046 				VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo
2047 				{
2048 					VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,	// VkStructureType		sType;
2049 					DE_NULL,																// const void*			pNext;
2050 					*srImageView,															// VkImageView			imageView;
2051 					srLayout,																// VkImageLayout		imageLayout;
2052 					{ srTexelWidth, srTexelHeight }											// VkExtent2D			shadingRateAttachmentTexelSize;
2053 				};
2054 
2055 				VkRenderingAttachmentInfoKHR colorAttachment
2056 				{
2057 					vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,					// VkStructureType						sType;
2058 					DE_NULL,																// const void*							pNext;
2059 					*cbImageView,															// VkImageView							imageView;
2060 					VK_IMAGE_LAYOUT_GENERAL,												// VkImageLayout						imageLayout;
2061 					VK_RESOLVE_MODE_NONE,													// VkResolveModeFlagBits				resolveMode;
2062 					DE_NULL,																// VkImageView							resolveImageView;
2063 					VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout						resolveImageLayout;
2064 					VK_ATTACHMENT_LOAD_OP_LOAD,												// VkAttachmentLoadOp					loadOp;
2065 					VK_ATTACHMENT_STORE_OP_STORE,											// VkAttachmentStoreOp					storeOp;
2066 					clearColor																// VkClearValue							clearValue;
2067 				};
2068 
2069 				std::vector<VkRenderingAttachmentInfoKHR> depthStencilAttachments(2,
2070 				{
2071 					VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,						// VkStructureType						sType;
2072 					DE_NULL,																// const void*							pNext;
2073 					*dsImageView,															// VkImageView							imageView;
2074 					VK_IMAGE_LAYOUT_GENERAL,												// VkImageLayout						imageLayout;
2075 					VK_RESOLVE_MODE_NONE,													// VkResolveModeFlagBits				resolveMode;
2076 					DE_NULL,																// VkImageView							resolveImageView;
2077 					VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout						resolveImageLayout;
2078 					VK_ATTACHMENT_LOAD_OP_LOAD,												// VkAttachmentLoadOp					loadOp;
2079 					VK_ATTACHMENT_STORE_OP_STORE,											// VkAttachmentStoreOp					storeOp;
2080 					clearDepthStencil														// VkClearValue							clearValue;
2081 				});
2082 
2083 				vk::VkRenderingInfoKHR renderingInfo
2084 				{
2085 					vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
2086 					m_data.useAttachment() ? &shadingRateAttachmentInfo : DE_NULL,
2087 					0,																		// VkRenderingFlagsKHR					flags;
2088 					renderArea,																// VkRect2D								renderArea;
2089 					m_data.multiView ? 1 : m_data.numColorLayers,							// deUint32								layerCount;
2090 					m_data.multiView ? 0x3 : 0u,											// deUint32								viewMask;
2091 					1u,																		// deUint32								colorAttachmentCount;
2092 					&colorAttachment,														// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
2093 					m_data.useDepthStencil ? &depthStencilAttachments[0] : DE_NULL,			// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
2094 					m_data.useDepthStencil ? &depthStencilAttachments[1] : DE_NULL,			// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
2095 				};
2096 
2097 				vk.cmdBeginRenderingKHR(*cmdBuffer, &renderingInfo);
2098 			}
2099 			else
2100 			{
2101 				const VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo
2102 				{
2103 					VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO,		//  VkStructureType		sType;
2104 					DE_NULL,													//  const void*			pNext;
2105 					(deUint32)attachments.size(),								//  deUint32			attachmentCount;
2106 					&attachments[0]												//  const VkImageView*	pAttachments;
2107 				};
2108 
2109 				beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea,
2110 								0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, imagelessFB ? &renderPassAttachmentBeginInfo : DE_NULL);
2111 			}
2112 
2113 			for (deInt32 i = 0; i < NUM_TRIANGLES; ++i)
2114 			{
2115 				// Bind vertex attributes pointing to the next triangle
2116 				VkDeviceSize vertexBufferOffset = i*3*2*sizeof(float);
2117 				VkBuffer vb = **vertexBuffer;
2118 				vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
2119 
2120 				// Put primitive shading rate in a push constant
2121 				deInt32 shadingRatePC = PrimIDToPrimitiveShadingRate(i);
2122 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, allShaderStages, 0, sizeof(shadingRatePC), &shadingRatePC);
2123 
2124 				if (m_data.useDynamicState)
2125 				{
2126 					VkExtent2D fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
2127 					vk.cmdSetFragmentShadingRateKHR(*cmdBuffer, &fragmentSize, m_data.combinerOp);
2128 				}
2129 				else
2130 				{
2131 					// Create a new pipeline with the desired pipeline shading rate
2132 					shadingRateStateCreateInfo.fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
2133 					pipelines.push_back(createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo));
2134 					vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines.back());
2135 				}
2136 
2137 				// Draw one triangle, with "primitive ID" in gl_InstanceIndex
2138 				vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, i);
2139 			}
2140 
2141 			if (m_data.useDynamicRendering)
2142 				endRendering(vk, *cmdBuffer);
2143 			else
2144 				endRenderPass(vk, *cmdBuffer);
2145 
2146 			memBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
2147 			memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
2148 			vk.cmdPipelineBarrier(*cmdBuffer, allPipelineStages, allPipelineStages,
2149 				0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2150 
2151 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1, &*descriptorSet, 0u, DE_NULL);
2152 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
2153 
2154 			// Copy color/depth/stencil buffers to buffer memory
2155 			vk.cmdDispatch(*cmdBuffer, m_data.framebufferDim.width, m_data.framebufferDim.height, m_data.numColorLayers);
2156 
2157 			memBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2158 			memBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2159 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2160 				0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2161 
2162 			endCommandBuffer(vk, *cmdBuffer);
2163 
2164 			submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2165 
2166 			deUint32 *colorptr = (deUint32 *)colorOutputBuffer->getAllocation().getHostPtr();
2167 			invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
2168 
2169 			invalidateAlloc(vk, device, atomicBuffer->getAllocation());
2170 
2171 			float *depthptr = DE_NULL;
2172 			deUint32 *stencilptr = DE_NULL;
2173 
2174 			if (m_data.useDepthStencil)
2175 			{
2176 				depthptr = (float *)depthOutputBuffer->getAllocation().getHostPtr();
2177 				invalidateAlloc(vk, device, depthOutputBuffer->getAllocation());
2178 
2179 				stencilptr = (deUint32 *)stencilOutputBuffer->getAllocation().getHostPtr();
2180 				invalidateAlloc(vk, device, stencilOutputBuffer->getAllocation());
2181 			}
2182 
2183 			// Loop over all samples and validate the output
2184 			for (deUint32 layer = 0; layer < m_data.numColorLayers && res == QP_TEST_RESULT_PASS; ++layer)
2185 			{
2186 				for (deUint32 y = 0; y < m_data.framebufferDim.height && res == QP_TEST_RESULT_PASS; ++y)
2187 				{
2188 					for (deUint32 x = 0; x < m_data.framebufferDim.width && res == QP_TEST_RESULT_PASS; ++x)
2189 					{
2190 						for (deInt32 s = 0; s < m_data.samples && res == QP_TEST_RESULT_PASS; ++s)
2191 						{
2192 							deUint32 *sample = &colorptr[4*(((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s)];
2193 
2194 							// If testing the rasterizer sample mask, if this sample is not set in the
2195 							// mask then it shouldn't have written anything.
2196 							if (m_data.useApiSampleMask && !(sampleMask & (1 << s)) && sample[2] != 0)
2197 							{
2198 								log << tcu::TestLog::Message << std::hex << "sample written despite pSampleMask (" << x << "," << y << ",sample " << s << ")" << tcu::TestLog::EndMessage;
2199 								res = QP_TEST_RESULT_FAIL;
2200 								continue;
2201 							}
2202 
2203 							// The same isn't covered by any primitives, skip it
2204 							if (sample[2] == 0)
2205 								continue;
2206 
2207 							// skip samples that have the same value as sample zero - it would be redundant to check them.
2208 							if (s > 0)
2209 							{
2210 								deUint32 *sample0 = &colorptr[4*(((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + 0)];
2211 								bool same = deMemCmp(sample, sample0, 16) == 0;
2212 
2213 								if (m_data.fragDepth)
2214 								{
2215 									float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2216 									float *dsample0 = &depthptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + 0];
2217 									same = same && (*dsample == *dsample0);
2218 								}
2219 
2220 								if (m_data.fragStencil)
2221 								{
2222 									deUint32 *ssample = &stencilptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2223 									deUint32 *ssample0 = &stencilptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + 0];
2224 									same = same && (*ssample == *ssample0);
2225 								}
2226 
2227 								if (same)
2228 									continue;
2229 							}
2230 
2231 							// Fragment shader writes error codes to .w component.
2232 							// All nonzero values are unconditionally failures
2233 							if (sample[3] != 0)
2234 							{
2235 								if (sample[3] == ERROR_FRAGCOORD_CENTER)
2236 									log << tcu::TestLog::Message << std::hex << "fragcoord test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2237 								else if (sample[3] == ERROR_VTG_READBACK)
2238 									log << tcu::TestLog::Message << std::hex << "vs/gs output readback test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2239 								else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_DERIV)
2240 									log << tcu::TestLog::Message << std::hex << "fragcoord derivative test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")="
2241 																				"(0x" << ((sample[3] >>  8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F) << "), expected="
2242 																				"(0x" << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F) << ")" << tcu::TestLog::EndMessage;
2243 								else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_IMPLICIT_DERIV)
2244 									log << tcu::TestLog::Message << std::hex << "implicit derivative test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")="
2245 																				"(0x" << ((sample[3] >>  8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F) << "), expected="
2246 																				"(0x" << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F) << ")" << tcu::TestLog::EndMessage;
2247 								else
2248 									log << tcu::TestLog::Message << std::hex << "w coord unknown test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2249 								res = QP_TEST_RESULT_FAIL;
2250 								continue;
2251 							}
2252 
2253 							// x component of sample
2254 							deUint32 rate = sample[0];
2255 							// fragment size
2256 							deUint32 pixelsX = 1 << ((rate/4)&3);
2257 							deUint32 pixelsY = 1 << (rate&3);
2258 
2259 							// Fragment region
2260 							deUint32 fragMinX = x & ~(pixelsX-1);
2261 							deUint32 fragMinY = y & ~(pixelsY-1);
2262 							deUint32 fragMaxX = fragMinX + pixelsX;
2263 							deUint32 fragMaxY = fragMinY + pixelsY;
2264 
2265 							// Clamp to FB dimension for odd sizes
2266 							if (fragMaxX > m_data.framebufferDim.width)
2267 								fragMaxX = m_data.framebufferDim.width;
2268 							if (fragMaxY > m_data.framebufferDim.height)
2269 								fragMaxY = m_data.framebufferDim.height;
2270 
2271 							// z component of sample
2272 							deUint32 primID = sample[2] >> 24;
2273 							deUint32 atomVal = sample[2] & 0xFFFFFF;
2274 
2275 							// Compute pipeline and primitive rate from primitive ID, and attachment
2276 							// rate from the x/y coordinate
2277 							deInt32 pipelineRate = PrimIDToPipelineShadingRate(primID);
2278 							deInt32 primitiveRate = m_data.shaderWritesRate ? PrimIDToPrimitiveShadingRate(primID) : 0;
2279 
2280 							deInt32 attachmentLayer = (m_data.srLayered && modeIdx == ATTACHMENT_MODE_2DARRAY) ? layer : 0;
2281 							deInt32 attachmentRate = m_data.useAttachment() ? fillPtr[srFillBpp*((attachmentLayer * srHeight + (y / srTexelHeight)) * srWidth + (x / srTexelWidth))] : 0;
2282 
2283 							// Get mask of allowed shading rates
2284 							deInt32 expectedMasks = Simulate(pipelineRate, primitiveRate, attachmentRate);
2285 
2286 							if (!(expectedMasks & (1 << rate)))
2287 							{
2288 								log << tcu::TestLog::Message << std::hex << "unexpected shading rate. failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ") "
2289 																			"result rate 0x" << rate << " mask of expected rates 0x" << expectedMasks <<
2290 																			" pipelineRate=0x" << pipelineRate << " primitiveRate=0x" << primitiveRate << " attachmentRate =0x" << attachmentRate << tcu::TestLog::EndMessage;
2291 								res = QP_TEST_RESULT_FAIL;
2292 								continue;
2293 							}
2294 							// Check that not all fragments are downgraded to 1x1
2295 							if (rate == 0 && expectedMasks != 1)
2296 								numUnexpected1x1Samples++;
2297 							numTotalSamples++;
2298 
2299 							// Check that gl_FragDepth = primID / NUM_TRIANGLES
2300 							if (m_data.fragDepth)
2301 							{
2302 								float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2303 								float expected = (float)primID / NUM_TRIANGLES;
2304 								if (fabs(*dsample - expected) > 0.01)
2305 								{
2306 									log << tcu::TestLog::Message << std::hex << "depth write failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")=" << *dsample << " expected " << expected << tcu::TestLog::EndMessage;
2307 									res = QP_TEST_RESULT_FAIL;
2308 									continue;
2309 								}
2310 							}
2311 
2312 							// Check that stencil value = primID
2313 							if (m_data.fragStencil)
2314 							{
2315 								deUint32 *ssample = &stencilptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2316 								if (*ssample != primID)
2317 								{
2318 									log << tcu::TestLog::Message << std::hex << "stencil write failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")=" << *ssample << " expected " << primID << tcu::TestLog::EndMessage;
2319 									res = QP_TEST_RESULT_FAIL;
2320 									continue;
2321 								}
2322 							}
2323 
2324 							// Check that primitives are in the right viewport/scissor
2325 							if (m_data.multiViewport)
2326 							{
2327 								VkRect2D *scissor = &scissors[primID & 1];
2328 								if ((int)x < scissor->offset.x || (int)x >= (int)(scissor->offset.x + scissor->extent.width) ||
2329 									(int)y < scissor->offset.y || (int)y >= (int)(scissor->offset.y + scissor->extent.height))
2330 								{
2331 									log << tcu::TestLog::Message << std::hex << "primitive found outside of expected viewport (0x" << x << ",0x" << y << ",sample 0x" << s << ") primID=" << primID << tcu::TestLog::EndMessage;
2332 									res = QP_TEST_RESULT_FAIL;
2333 									continue;
2334 								}
2335 							}
2336 
2337 							// Check that primitives are in the right layer
2338 							if (m_data.colorLayered)
2339 							{
2340 								if (layer != ((primID & 2)>>1))
2341 								{
2342 									log << tcu::TestLog::Message << std::hex << "primitive found in wrong layer (0x" << x << ",0x" << y << ",sample 0x" << s << ") primID=" << primID << " layer=" << layer << tcu::TestLog::EndMessage;
2343 									res = QP_TEST_RESULT_FAIL;
2344 									continue;
2345 								}
2346 							}
2347 
2348 							// Check that multiview broadcasts the same primitive to both layers
2349 							if (m_data.multiView)
2350 							{
2351 								deUint32 otherLayer = layer^1;
2352 								deUint32 *othersample = &colorptr[4*(((otherLayer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s)];
2353 								deUint32 otherPrimID = othersample[2] >> 24;
2354 								if (primID != otherPrimID)
2355 								{
2356 									log << tcu::TestLog::Message << std::hex << "multiview primitive mismatch (0x" << x << ",0x" << y << ",sample 0x" << s << ") primID=" << primID << "  otherPrimID=" << otherPrimID << tcu::TestLog::EndMessage;
2357 									res = QP_TEST_RESULT_FAIL;
2358 									continue;
2359 								}
2360 							}
2361 
2362 							// Loop over all samples in the same fragment
2363 							for (deUint32 fx = fragMinX; fx < fragMaxX; ++fx)
2364 							{
2365 								for (deUint32 fy = fragMinY; fy < fragMaxY; ++fy)
2366 								{
2367 									for (deInt32 fs = 0; fs < m_data.samples; ++fs)
2368 									{
2369 										deUint32 *fsample = &colorptr[4*(((layer * m_data.framebufferDim.height + fy) * m_data.framebufferDim.width + fx)*m_data.samples + fs)];
2370 										deUint32 frate = fsample[0];
2371 										deUint32 fprimID = fsample[2] >> 24;
2372 										deUint32 fatomVal = fsample[2] & 0xFFFFFF;
2373 
2374 										// If we write out the sample mask value, check that the samples in the
2375 										// mask must not be uncovered, and that samples not in the mask must not
2376 										// be covered by this primitive
2377 										if (m_data.useSampleMaskIn)
2378 										{
2379 											int p = pixelsX * pixelsY - ((fx - fragMinX) + pixelsX * (fy - fragMinY)) - 1;
2380 											int sampleIdx = fs + m_data.samples * p;
2381 
2382 											if ((sample[1] & (1 << sampleIdx)) && fsample[2] == 0)
2383 											{
2384 												log << tcu::TestLog::Message << std::hex << "sample set in sampleMask but not written (0x" << fx << ",0x" << fy << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2385 												res = QP_TEST_RESULT_FAIL;
2386 												continue;
2387 											}
2388 											if (!(sample[1] & (1 << sampleIdx)) && fsample[2] != 0 && fprimID == primID)
2389 											{
2390 												log << tcu::TestLog::Message << std::hex << "sample not set in sampleMask but written with same primID (0x" << fx << ",0x" << fy << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2391 												res = QP_TEST_RESULT_FAIL;
2392 												continue;
2393 											}
2394 										}
2395 
2396 										// If conservative raster is enabled, or custom sample locations all at the center, check that
2397 										// samples in the same pixel must be covered.
2398 										if (m_data.conservativeEnable ||
2399 											(m_data.sampleLocations && m_context.getFragmentShadingRateProperties().fragmentShadingRateWithCustomSampleLocations))
2400 										{
2401 											// If it's in the same pixel, expect it to be fully covered.
2402 											if (fx == x && fy == y && fsample[2] == 0)
2403 											{
2404 												log << tcu::TestLog::Message << std::hex << "pixel not fully covered (0x" << fx << ",0x" << fy << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2405 												res = QP_TEST_RESULT_FAIL;
2406 												continue;
2407 											}
2408 										}
2409 
2410 										if (fsample[2] == 0)
2411 											continue;
2412 
2413 										// If the primitive matches this sample, then it must have the same rate and
2414 										// atomic value
2415 										if (fprimID == primID)
2416 										{
2417 											if (rate != frate || (atomVal != fatomVal && !(m_data.sampleShadingEnable || m_data.sampleShadingInput)))
2418 											{
2419 												log << tcu::TestLog::Message << std::hex << "failed pixel (0x" << x << ",0x" << y << ",sample " << s << ")=0x" << ((primID<<24)|atomVal) <<
2420 																							" compared to (0x" << fx << ",0x" << fy << ",sample " << fs << ")=0x" << ((fprimID<<24)|fatomVal) <<
2421 																							" pipelineRate=0x" << pipelineRate << " primitiveRate=0x" << primitiveRate << " attachmentRate =0x" << attachmentRate <<
2422 																							tcu::TestLog::EndMessage;
2423 												res = QP_TEST_RESULT_FAIL;
2424 											}
2425 										}
2426 									}
2427 								}
2428 							}
2429 						}
2430 					}
2431 				}
2432 			}
2433 			if (res == QP_TEST_RESULT_FAIL)
2434 				break;
2435 		}
2436 	}
2437 	// All samples were coerced to 1x1, unexpected
2438 	if (res == QP_TEST_RESULT_PASS &&
2439 		numTotalSamples != 0 &&
2440 		numUnexpected1x1Samples == numTotalSamples &&
2441 		numTotalSamples > 16)
2442 	{
2443 		log << tcu::TestLog::Message << std::hex << "Quality warning - all fragments used 1x1" << tcu::TestLog::EndMessage;
2444 		res = QP_TEST_RESULT_QUALITY_WARNING;
2445 	}
2446 
2447 	return tcu::TestStatus(res, qpGetTestResultName(res));
2448 }
2449 
2450 }	// anonymous
2451 
createBasicTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,bool useDynamicRendering)2452 void createBasicTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup, bool useDynamicRendering)
2453 {
2454 	typedef struct
2455 	{
2456 		deUint32				count;
2457 		const char*				name;
2458 		const char*				description;
2459 	} TestGroupCase;
2460 
2461 	typedef struct
2462 	{
2463 		VkExtent2D				count;
2464 		const char*				name;
2465 		const char*				description;
2466 	} TestGroupCase2D;
2467 
2468 	typedef struct
2469 	{
2470 		AttachmentUsage			usage;
2471 		const char*				name;
2472 		const char*				description;
2473 	} TestGroupUsageCase;
2474 
2475 	TestGroupCase groupCases[] =
2476 	{
2477 		{ 0,	"basic",				"basic tests"					},
2478 		{ 1,	"apisamplemask",		"use pSampleMask"				},
2479 		{ 2,	"samplemaskin",			"use gl_SampleMaskIn"			},
2480 		{ 3,	"conservativeunder",	"conservative underestimation"	},
2481 		{ 4,	"conservativeover",		"conservative overestimation"	},
2482 		{ 5,	"fragdepth",			"depth shader output"			},
2483 		{ 6,	"fragstencil",			"stencil shader output"			},
2484 		{ 7,	"multiviewport",		"multiple viewports and gl_ViewportIndex"	},
2485 		{ 8,	"colorlayered",			"multiple layer color, single layer shading rate"	},
2486 		{ 9,	"srlayered",			"multiple layer color, multiple layers shading rate"	},
2487 		{ 10,	"multiview",			"multiview"	},
2488 		{ 11,	"multiviewsrlayered",	"multiview and multilayer shading rate"	},
2489 		{ 12,	"interlock",			"fragment shader interlock"	},
2490 		{ 13,	"samplelocations",		"custom sample locations"	},
2491 		{ 14,	"sampleshadingenable",	"enable sample shading in createinfo"	},
2492 		{ 15,	"sampleshadinginput",	"enable sample shading by using gl_SampleID"	},
2493 	};
2494 
2495 	TestGroupCase dynCases[] =
2496 	{
2497 		{ 1,	"dynamic",	"uses dynamic shading rate state"	},
2498 		{ 0,	"static",	"uses static shading rate state"	},
2499 	};
2500 
2501 	TestGroupUsageCase attCases[] =
2502 	{
2503 		{ AttachmentUsage::NO_ATTACHMENT,		"noattachment",		"no shading rate attachment"			},
2504 		{ AttachmentUsage::WITH_ATTACHMENT,		"attachment",		"has shading rate attachment"			},
2505 		{ AttachmentUsage::NO_ATTACHMENT_PTR,	"noattachmentptr",	"no shading rate attachment pointer"	},
2506 	};
2507 
2508 	TestGroupCase shdCases[] =
2509 	{
2510 		{ 0,	"noshaderrate",	"shader doesn't write rate"	},
2511 		{ 1,	"shaderrate",	"shader writes rate"	},
2512 	};
2513 
2514 	TestGroupCase combCases[] =
2515 	{
2516 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,	"keep",		"keep"	},
2517 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR,	"replace",	"replace"	},
2518 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR,		"min",		"min"	},
2519 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR,		"max",		"max"	},
2520 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR,		"mul",		"mul"	},
2521 	};
2522 
2523 	TestGroupCase2D extentCases[] =
2524 	{
2525 		{ {1,   1},		"1x1",		"1x1"		},
2526 		{ {4,   4},		"4x4",		"4x4"		},
2527 		{ {33,  35},	"33x35",	"33x35"		},
2528 		{ {151, 431},	"151x431",	"151x431"	},
2529 		{ {256, 256},	"256x256",	"256x256"	},
2530 	};
2531 
2532 	TestGroupCase sampCases[] =
2533 	{
2534 		{ VK_SAMPLE_COUNT_1_BIT,	"samples1",		"1 raster sample"	},
2535 		{ VK_SAMPLE_COUNT_2_BIT,	"samples2",		"2 raster samples"	},
2536 		{ VK_SAMPLE_COUNT_4_BIT,	"samples4",		"4 raster samples"	},
2537 		{ VK_SAMPLE_COUNT_8_BIT,	"samples8",		"8 raster samples"	},
2538 		{ VK_SAMPLE_COUNT_16_BIT,	"samples16",	"16 raster samples"	},
2539 	};
2540 
2541 	TestGroupCase geomCases[] =
2542 	{
2543 		{ 0,	"vs",	"vertex shader only"	},
2544 		{ 1,	"gs",	"vertex and geometry shader"	},
2545 	};
2546 
2547 	deInt32 seed = 0;
2548 
2549 	for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groupCases); groupNdx++)
2550 	{
2551 		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, groupCases[groupNdx].name, groupCases[groupNdx].description));
2552 		for (int dynNdx = 0; dynNdx < DE_LENGTH_OF_ARRAY(dynCases); dynNdx++)
2553 		{
2554 			de::MovePtr<tcu::TestCaseGroup> dynGroup(new tcu::TestCaseGroup(testCtx, dynCases[dynNdx].name, dynCases[dynNdx].description));
2555 			for (int attNdx = 0; attNdx < DE_LENGTH_OF_ARRAY(attCases); attNdx++)
2556 			{
2557 				if (useDynamicRendering && attCases[attNdx].usage == AttachmentUsage::NO_ATTACHMENT_PTR)
2558 					continue;
2559 
2560 				de::MovePtr<tcu::TestCaseGroup> attGroup(new tcu::TestCaseGroup(testCtx, attCases[attNdx].name, attCases[attNdx].description));
2561 				for (int shdNdx = 0; shdNdx < DE_LENGTH_OF_ARRAY(shdCases); shdNdx++)
2562 				{
2563 					de::MovePtr<tcu::TestCaseGroup> shdGroup(new tcu::TestCaseGroup(testCtx, shdCases[shdNdx].name, shdCases[shdNdx].description));
2564 					for (int cmb0Ndx = 0; cmb0Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb0Ndx++)
2565 					{
2566 						de::MovePtr<tcu::TestCaseGroup> cmb0Group(new tcu::TestCaseGroup(testCtx, combCases[cmb0Ndx].name, combCases[cmb0Ndx].description));
2567 						for (int cmb1Ndx = 0; cmb1Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb1Ndx++)
2568 						{
2569 							de::MovePtr<tcu::TestCaseGroup> cmb1Group(new tcu::TestCaseGroup(testCtx, combCases[cmb1Ndx].name, combCases[cmb1Ndx].description));
2570 							for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
2571 							{
2572 								de::MovePtr<tcu::TestCaseGroup> extGroup(new tcu::TestCaseGroup(testCtx, extentCases[extNdx].name, extentCases[extNdx].description));
2573 								for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
2574 								{
2575 									de::MovePtr<tcu::TestCaseGroup> sampGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name, sampCases[sampNdx].description));
2576 									for (int geomNdx = 0; geomNdx < DE_LENGTH_OF_ARRAY(geomCases); geomNdx++)
2577 									{
2578 										bool useApiSampleMask = groupNdx == 1;
2579 										bool useSampleMaskIn = groupNdx == 2;
2580 										bool consRast = groupNdx == 3 || groupNdx == 4;
2581 										bool fragDepth = groupNdx == 5;
2582 										bool fragStencil = groupNdx == 6;
2583 										bool multiViewport = groupNdx == 7;
2584 										bool colorLayered = groupNdx == 8 || groupNdx == 9;
2585 										bool srLayered = groupNdx == 9 || groupNdx == 11;
2586 										bool multiView = groupNdx == 10 || groupNdx == 11;
2587 										bool interlock = groupNdx == 12;
2588 										bool sampleLocations = groupNdx == 13;
2589 										bool sampleShadingEnable = groupNdx == 14;
2590 										bool sampleShadingInput = groupNdx == 15;
2591 										VkConservativeRasterizationModeEXT conservativeMode = (groupNdx == 3) ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT : VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
2592 										deUint32 numColorLayers = (colorLayered || multiView) ? 2u : 1u;
2593 
2594 										// Don't bother with geometry shader if we're not testing shader writes
2595 										if (geomCases[geomNdx].count && !shdCases[shdNdx].count)
2596 											continue;
2597 
2598 										// reduce number of tests
2599 										if ((groupNdx != 0) &&
2600 											(!dynCases[dynNdx].count ||
2601 											 !(combCases[cmb0Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR || combCases[cmb0Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
2602 											 !(combCases[cmb1Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR || combCases[cmb1Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
2603 											continue;
2604 
2605 										// Don't bother with geometry shader if we're testing conservative raster, sample mask, depth/stencil
2606 										if (geomCases[geomNdx].count && (useApiSampleMask || useSampleMaskIn || consRast || fragDepth || fragStencil))
2607 											continue;
2608 
2609 										// Don't bother with geometry shader if we're testing non-dynamic state
2610 										if (geomCases[geomNdx].count && !dynCases[dynNdx].count)
2611 											continue;
2612 
2613 										// Only test multiViewport/layered with shaderWritesRate
2614 										if ((multiViewport || colorLayered) && !shdCases[shdNdx].count)
2615 											continue;
2616 
2617 										// Can't test layered shading rate attachment without an attachment
2618 										if (srLayered && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
2619 											continue;
2620 
2621 										CaseDef c =
2622 										{
2623 											seed++,													// deInt32 seed;
2624 											extentCases[extNdx].count,								// VkExtent2D framebufferDim;
2625 											(VkSampleCountFlagBits)sampCases[sampNdx].count,		// VkSampleCountFlagBits samples;
2626 											{
2627 												(VkFragmentShadingRateCombinerOpKHR)combCases[cmb0Ndx].count,
2628 												(VkFragmentShadingRateCombinerOpKHR)combCases[cmb1Ndx].count
2629 											},														// VkFragmentShadingRateCombinerOpKHR combinerOp[2];
2630 											attCases[attNdx].usage,									// AttachmentUsage attachmentUsage;
2631 											(bool)shdCases[shdNdx].count,							// bool shaderWritesRate;
2632 											(bool)geomCases[geomNdx].count,							// bool geometryShader;
2633 											(bool)dynCases[dynNdx].count,							// bool useDynamicState;
2634 											useDynamicRendering,									// bool useDynamicRendering;
2635 											useApiSampleMask,										// bool useApiSampleMask;
2636 											useSampleMaskIn,										// bool useSampleMaskIn;
2637 											consRast,												// bool conservativeEnable;
2638 											conservativeMode,										// VkConservativeRasterizationModeEXT conservativeMode;
2639 											fragDepth || fragStencil,								// bool useDepthStencil;
2640 											fragDepth,												// bool fragDepth;
2641 											fragStencil,											// bool fragStencil;
2642 											multiViewport,											// bool multiViewport;
2643 											colorLayered,											// bool colorLayered;
2644 											srLayered,												// bool srLayered;
2645 											numColorLayers,											// deUint32 numColorLayers;
2646 											multiView,												// bool multiView;
2647 											interlock,												// bool interlock;
2648 											sampleLocations,										// bool sampleLocations;
2649 											sampleShadingEnable,									// bool sampleShadingEnable;
2650 											sampleShadingInput,										// bool sampleShadingInput;
2651 											false,													// bool sampleMaskTest;
2652 										};
2653 
2654 										sampGroup->addChild(new FSRTestCase(testCtx, geomCases[geomNdx].name, geomCases[geomNdx].description, c));
2655 									}
2656 									extGroup->addChild(sampGroup.release());
2657 								}
2658 								cmb1Group->addChild(extGroup.release());
2659 							}
2660 							cmb0Group->addChild(cmb1Group.release());
2661 						}
2662 						shdGroup->addChild(cmb0Group.release());
2663 					}
2664 					attGroup->addChild(shdGroup.release());
2665 				}
2666 				dynGroup->addChild(attGroup.release());
2667 			}
2668 			group->addChild(dynGroup.release());
2669 		}
2670 		parentGroup->addChild(group.release());
2671 	}
2672 
2673 	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc_tests", "Single tests that don't need to be part of above test matrix"));
2674 	group->addChild(new FSRTestCase(testCtx, "sample_mask_test", "", {
2675 		123,													// deInt32 seed;
2676 		{32,  33},												// VkExtent2D framebufferDim;
2677 		VK_SAMPLE_COUNT_4_BIT,									// VkSampleCountFlagBits samples;
2678 		{
2679 			VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
2680 			VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR
2681 		},														// VkFragmentShadingRateCombinerOpKHR combinerOp[2];
2682 		AttachmentUsage::NO_ATTACHMENT,							// AttachmentUsage attachmentUsage;
2683 		true,													// bool shaderWritesRate;
2684 		false,													// bool geometryShader;
2685 		false,													// bool useDynamicState;
2686 		false,													// bool useDynamicRendering;
2687 		true,													// bool useApiSampleMask;
2688 		false,													// bool useSampleMaskIn;
2689 		false,													// bool conservativeEnable;
2690 		VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,	// VkConservativeRasterizationModeEXT conservativeMode;
2691 		false,													// bool useDepthStencil;
2692 		false,													// bool fragDepth;
2693 		false,													// bool fragStencil;
2694 		false,													// bool multiViewport;
2695 		false,													// bool colorLayered;
2696 		false,													// bool srLayered;
2697 		1u,														// deUint32 numColorLayers;
2698 		false,													// bool multiView;
2699 		false,													// bool interlock;
2700 		false,													// bool sampleLocations;
2701 		false,													// bool sampleShadingEnable;
2702 		false,													// bool sampleShadingInput;
2703 		true,													// bool sampleMaskTest;
2704 	}));
2705 
2706 	parentGroup->addChild(group.release());
2707 }
2708 
2709 }	// FragmentShadingRage
2710 }	// vkt
2711