• 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 #include "vkStrUtil.hpp"
46 
47 #include "vktTestGroupUtil.hpp"
48 #include "vktTestCase.hpp"
49 
50 #include "deDefs.h"
51 #include "deMath.h"
52 #include "deRandom.h"
53 #include "deSharedPtr.hpp"
54 #include "deString.h"
55 
56 #include "tcuTestCase.hpp"
57 #include "tcuTestLog.hpp"
58 
59 #include <set>
60 #include <string>
61 #include <sstream>
62 #include <vector>
63 #include <algorithm>
64 #include <iterator>
65 
66 namespace vkt
67 {
68 namespace FragmentShadingRate
69 {
70 namespace
71 {
72 using namespace vk;
73 using namespace std;
74 
75 #define NUM_TRIANGLES (9*9)
76 
77 enum class AttachmentUsage
78 {
79 	NO_ATTACHMENT = 0,
80 	NO_ATTACHMENT_PTR,
81 	WITH_ATTACHMENT,
82 	WITH_ATTACHMENT_WITHOUT_IMAGEVIEW, // No imageview at VkRenderingFragmentShadingRateAttachmentInfoKHR.
83 };
84 
85 struct CaseDef
86 {
87 	SharedGroupParams groupParams;
88 	deInt32 seed;
89 	VkExtent2D framebufferDim;
90 	VkSampleCountFlagBits samples;
91 	VkFragmentShadingRateCombinerOpKHR combinerOp[2];
92 	AttachmentUsage attachmentUsage;
93 	bool shaderWritesRate;
94 	bool geometryShader;
95 	bool meshShader;
96 	bool useDynamicState;
97 	bool useApiSampleMask;
98 	bool useSampleMaskIn;
99 	bool conservativeEnable;
100 	VkConservativeRasterizationModeEXT conservativeMode;
101 	bool useDepthStencil; // == fragDepth || fragStencil
102 	bool fragDepth;
103 	bool fragStencil;
104 	bool multiViewport;
105 	bool colorLayered;
106 	bool srLayered; // colorLayered must also be true
107 	deUint32 numColorLayers;
108 	bool multiView;
109 	bool correlationMask;
110 	bool interlock;
111 	bool sampleLocations;
112 	bool sampleShadingEnable;
113 	bool sampleShadingInput;
114 	bool sampleMaskTest;
115 	bool earlyAndLateTest;
116 	bool garbageAttachment;
117 
useAttachmentvkt::FragmentShadingRate::__anon9bcbc2440111::CaseDef118 	bool useAttachment () const
119 	{
120 		return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT);
121 	}
122 
useAttachmentWithoutImageViewvkt::FragmentShadingRate::__anon9bcbc2440111::CaseDef123 	bool useAttachmentWithoutImageView () const
124 	{
125 		return (attachmentUsage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW);
126 	}
127 };
128 
129 class FSRTestInstance : public TestInstance
130 {
131 public:
132 						FSRTestInstance				(Context& context, const CaseDef& data);
133 						~FSRTestInstance			(void);
134 	tcu::TestStatus		iterate						(void);
135 
136 private:
137 	// Test parameters
138 	CaseDef				m_data;
139 
140 	// Cache simulated combiner operations, to avoid recomputing per-sample
141 	deInt32				m_simulateValueCount;
142 	vector<deInt32>		m_simulateCache;
143 	// Cache mapping of primitive ID to pipeline/primitive shading rate
144 	vector<deInt32>		m_primIDToPrimitiveShadingRate;
145 	vector<deInt32>		m_primIDToPipelineShadingRate;
146 	deUint32			m_supportedFragmentShadingRateCount;
147 	vector<VkPhysicalDeviceFragmentShadingRateKHR>	m_supportedFragmentShadingRates;
148 	VkPhysicalDeviceFragmentShadingRatePropertiesKHR	m_shadingRateProperties;
149 
150 protected:
151 
152 	void				preRenderCommands				(VkCommandBuffer									cmdBuffer,
153 														 ImageWithMemory*									cbImage,
154 														 ImageWithMemory*									dsImage,
155 														 ImageWithMemory*									derivImage,
156 														 deUint32											derivNumLevels,
157 														 ImageWithMemory*									srImage,
158 														 VkImageLayout										srLayout,
159 														 BufferWithMemory*									srFillBuffer,
160 														 deUint32											numSRLayers,
161 														 deUint32											srWidth,
162 														 deUint32											srHeight,
163 														 deUint32											srFillBpp,
164 														 const VkClearValue&								clearColor,
165 														 const VkClearValue&								clearDepthStencil);
166 	void				beginLegacyRender				(VkCommandBuffer									cmdBuffer,
167 														 VkRenderPass										renderPass,
168 														 VkFramebuffer										framebuffer,
169 														 VkImageView										srImageView,
170 														 VkImageView										cbImageView,
171 														 VkImageView										dsImageView,
172 														 bool												imagelessFB) const;
173 	void				drawCommands					(VkCommandBuffer									cmdBuffer,
174 														 std::vector<GraphicsPipelineWrapper>&				pipelines,
175 														 const std::vector<VkViewport>&						viewports,
176 														 const std::vector<VkRect2D>&						scissors,
177 														 const VkPipelineLayout								pipelineLayout,
178 														 const VkRenderPass									renderPass,
179 														 const VkPipelineVertexInputStateCreateInfo*		vertexInputState,
180 														 const VkPipelineDynamicStateCreateInfo*			dynamicState,
181 														 const VkPipelineRasterizationStateCreateInfo*		rasterizationState,
182 														 const VkPipelineDepthStencilStateCreateInfo*		depthStencilState,
183 														 const VkPipelineMultisampleStateCreateInfo*		multisampleState,
184 														 VkPipelineFragmentShadingRateStateCreateInfoKHR*	shadingRateState,
185 														 PipelineRenderingCreateInfoWrapper					dynamicRenderingState,
186 														 const VkShaderModule								vertShader,
187 														 const VkShaderModule								geomShader,
188 														 const VkShaderModule								meshShader,
189 														 const VkShaderModule								fragShader,
190 														 const std::vector<VkDescriptorSet>&				descriptorSet,
191 														 VkBuffer											vertexBuffer,
192 														 const uint32_t										pushConstantSize);
193 #ifndef CTS_USES_VULKANSC
194 	void				beginSecondaryCmdBuffer			(VkCommandBuffer									cmdBuffer,
195 														 VkFormat											cbFormat,
196 														 VkFormat											dsFormat,
197 														 VkRenderingFlagsKHR								renderingFlags = 0u) const;
198 	void				beginDynamicRender				(VkCommandBuffer									cmdBuffer,
199 														 VkImageView										srImageView,
200 														 VkImageLayout										srImageLayout,
201 														 const VkExtent2D&									srTexelSize,
202 														 VkImageView										cbImageView,
203 														 VkImageView										dsImageView,
204 														 const VkClearValue&								clearColor,
205 														 const VkClearValue&								clearDepthStencil,
206 														 VkRenderingFlagsKHR								renderingFlags = 0u) const;
207 #endif // CTS_USES_VULKANSC
208 
209 	deInt32				PrimIDToPrimitiveShadingRate	(deInt32 primID);
210 	deInt32				PrimIDToPipelineShadingRate		(deInt32 primID);
211 	VkExtent2D			SanitizeExtent					(VkExtent2D ext) const;
212 	deInt32				SanitizeRate					(deInt32 rate) const;
213 	deInt32				ShadingRateExtentToClampedMask	(VkExtent2D ext) const;
214 	deInt32				ShadingRateExtentToEnum			(VkExtent2D ext) const;
215 	VkExtent2D			ShadingRateEnumToExtent			(deInt32 rate) const;
216 	deInt32				Simulate						(deInt32 rate0, deInt32 rate1, deInt32 rate2);
217 	VkExtent2D			Combine							(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const;
218 	deInt32				CombineMasks					(deInt32 rateMask0, deInt32 rateMask1, VkFragmentShadingRateCombinerOpKHR comb, bool allowUnclampedResult) const;
219 	bool				Force1x1						() const;
220 };
221 
FSRTestInstance(Context & context,const CaseDef & data)222 FSRTestInstance::FSRTestInstance (Context& context, const CaseDef& data)
223 	: vkt::TestInstance		(context)
224 	, m_data				(data)
225 	, m_simulateValueCount	(((4 * 4) | 4) + 1)
226 	, m_simulateCache		(m_simulateValueCount*m_simulateValueCount*m_simulateValueCount, ~0)
227 	, m_primIDToPrimitiveShadingRate(NUM_TRIANGLES, ~0)
228 	, m_primIDToPipelineShadingRate(NUM_TRIANGLES, ~0)
229 {
230 	m_supportedFragmentShadingRateCount = 0;
231 	m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, DE_NULL);
232 
233 	if (m_supportedFragmentShadingRateCount < 3)
234 		TCU_THROW(TestError, "*pFragmentShadingRateCount too small");
235 
236 	m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount);
237 	for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
238 	{
239 		m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
240 		m_supportedFragmentShadingRates[i].pNext = nullptr;
241 	}
242 	m_context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(m_context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]);
243 
244 	m_shadingRateProperties = m_context.getFragmentShadingRateProperties();
245 }
246 
~FSRTestInstance(void)247 FSRTestInstance::~FSRTestInstance (void)
248 {
249 }
250 
251 class FSRTestCase : public TestCase
252 {
253 	public:
254 								FSRTestCase		(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
255 								~FSRTestCase	(void);
256 	virtual	void				initPrograms	(SourceCollections& programCollection) const;
257 	virtual TestInstance*		createInstance	(Context& context) const;
258 	virtual void				checkSupport	(Context& context) const;
259 
260 private:
261 	CaseDef						m_data;
262 };
263 
FSRTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)264 FSRTestCase::FSRTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
265 	: vkt::TestCase	(context, name, desc)
266 	, m_data		(data)
267 {
268 }
269 
~FSRTestCase(void)270 FSRTestCase::~FSRTestCase	(void)
271 {
272 }
273 
Force1x1() const274 bool FSRTestInstance::Force1x1() const
275 {
276 	if (m_data.useApiSampleMask && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
277 		return true;
278 
279 	if (m_data.useSampleMaskIn && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderSampleMask)
280 		return true;
281 
282 	if (m_data.conservativeEnable && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithConservativeRasterization)
283 		return true;
284 
285 	if (m_data.useDepthStencil && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithShaderDepthStencilWrites)
286 		return true;
287 
288 	if (m_data.interlock && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithFragmentShaderInterlock)
289 		return true;
290 
291 	if (m_data.sampleLocations && !m_context.getFragmentShadingRateProperties().fragmentShadingRateWithCustomSampleLocations)
292 		return true;
293 
294 	if (m_data.sampleShadingEnable || m_data.sampleShadingInput)
295 		return true;
296 
297 	return false;
298 }
299 
300 static VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
301 								   VK_IMAGE_USAGE_SAMPLED_BIT |
302 								   VK_IMAGE_USAGE_TRANSFER_DST_BIT |
303 								   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
304 
305 static VkImageUsageFlags dsUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
306 								   VK_IMAGE_USAGE_SAMPLED_BIT |
307 								   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
308 								   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
309 
310 
checkSupport(Context & context) const311 void FSRTestCase::checkSupport(Context& context) const
312 {
313 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
314 
315 	if (m_data.groupParams->useDynamicRendering)
316 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
317 
318 	if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
319 		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
320 
321 	if (m_data.shaderWritesRate &&
322 		!context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate)
323 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
324 
325 	if (!context.getFragmentShadingRateFeatures().primitiveFragmentShadingRate &&
326 		m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
327 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
328 
329 	if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
330 		m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
331 		TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
332 
333 	const auto&		vki			= context.getInstanceInterface();
334 	const auto		physDev		= context.getPhysicalDevice();
335 
336 	VkImageFormatProperties	imageProperties;
337 	VkResult				result			= vki.getPhysicalDeviceImageFormatProperties(physDev, VK_FORMAT_R32G32B32A32_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, cbUsage, 0, &imageProperties);
338 
339 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
340 		TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32B32A32_UINT not supported");
341 
342 	if (m_data.geometryShader)
343 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
344 
345 	if (!(imageProperties.sampleCounts & m_data.samples))
346 		TCU_THROW(NotSupportedError, "color buffer sample count not supported");
347 
348 	if (m_data.numColorLayers > imageProperties.maxArrayLayers)
349 		TCU_THROW(NotSupportedError, "color buffer layers not supported");
350 
351 	if (m_data.useAttachment() && !context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
352 		TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
353 
354 	if (!context.getFragmentShadingRateProperties().fragmentShadingRateNonTrivialCombinerOps &&
355 		((m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR && m_data.combinerOp[0] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
356 		 (m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR && m_data.combinerOp[1] != VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
357 		TCU_THROW(NotSupportedError, "fragmentShadingRateNonTrivialCombinerOps not supported");
358 
359 	if (m_data.conservativeEnable)
360 	{
361 		context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
362 		if (m_data.conservativeMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT &&
363 			!context.getConservativeRasterizationPropertiesEXT().primitiveUnderestimation)
364 			TCU_THROW(NotSupportedError, "primitiveUnderestimation not supported");
365 	}
366 
367 	if (m_data.fragStencil)
368 		context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
369 
370 	if (m_data.multiViewport &&
371 		!context.getFragmentShadingRateProperties().primitiveFragmentShadingRateWithMultipleViewports)
372 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateWithMultipleViewports not supported");
373 
374 	if (m_data.srLayered &&
375 		!context.getFragmentShadingRateProperties().layeredShadingRateAttachments)
376 		TCU_THROW(NotSupportedError, "layeredShadingRateAttachments not supported");
377 
378 	if ((m_data.multiViewport || m_data.colorLayered) &&
379 		!m_data.geometryShader)
380 		context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
381 
382 	if (m_data.multiView && m_data.geometryShader &&
383 		!context.getMultiviewFeatures().multiviewGeometryShader)
384 		TCU_THROW(NotSupportedError, "multiviewGeometryShader not supported");
385 
386 	if (m_data.interlock &&
387 		!context.getFragmentShaderInterlockFeaturesEXT().fragmentShaderPixelInterlock)
388 		TCU_THROW(NotSupportedError, "fragmentShaderPixelInterlock not supported");
389 
390 	if (m_data.sampleLocations)
391 	{
392 		context.requireDeviceFunctionality("VK_EXT_sample_locations");
393 		if (!(m_data.samples & context.getSampleLocationsPropertiesEXT().sampleLocationSampleCounts))
394 			TCU_THROW(NotSupportedError, "samples not supported in sampleLocationSampleCounts");
395 	}
396 
397 	if (m_data.sampleMaskTest && !context.getFragmentShadingRateProperties().fragmentShadingRateWithSampleMask)
398 		TCU_THROW(NotSupportedError, "fragmentShadingRateWithSampleMask not supported");
399 
400 #ifndef CTS_USES_VULKANSC
401 	if (m_data.meshShader)
402 	{
403 		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
404 		const auto& meshFeatures = context.getMeshShaderFeaturesEXT();
405 
406 		if (m_data.shaderWritesRate && !meshFeatures.primitiveFragmentShadingRateMeshShader)
407 			TCU_THROW(NotSupportedError, "primitiveFragmentShadingRateMeshShader not supported");
408 
409 		if (m_data.multiView && !meshFeatures.multiviewMeshShader)
410 			TCU_THROW(NotSupportedError, "multiviewMeshShader not supported");
411 	}
412 
413 	checkPipelineLibraryRequirements(vki, physDev, m_data.groupParams->pipelineConstructionType);
414 
415 	if (m_data.earlyAndLateTest)
416 	{
417 		context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
418 		if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
419 			TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
420 	}
421 #endif
422 }
423 
424 // Error codes writted by the fragment shader
425 enum
426 {
427 	ERROR_NONE = 0,
428 	ERROR_FRAGCOORD_CENTER = 1,
429 	ERROR_VTG_READBACK = 2,
430 	ERROR_FRAGCOORD_DERIV = 3,
431 	ERROR_FRAGCOORD_IMPLICIT_DERIV = 4,
432 };
433 
initPrograms(SourceCollections & programCollection) const434 void FSRTestCase::initPrograms (SourceCollections& programCollection) const
435 {
436 	if (!m_data.meshShader)
437 	{
438 		std::stringstream vss;
439 
440 		vss <<
441 			"#version 450 core\n"
442 			"#extension GL_EXT_fragment_shading_rate : enable\n"
443 			"#extension GL_ARB_shader_viewport_layer_array : enable\n"
444 			"layout(push_constant) uniform PC {\n"
445 			"	int shadingRate;\n"
446 			"} pc;\n"
447 			"layout(location = 0) in vec2 pos;\n"
448 			"layout(location = 0) out int instanceIndex;\n"
449 			"layout(location = 1) out int readbackok;\n"
450 			"layout(location = 2) out float zero;\n"
451 			"out gl_PerVertex\n"
452 			"{\n"
453 			"   vec4 gl_Position;\n"
454 			"};\n"
455 			"void main()\n"
456 			"{\n"
457 			"  gl_Position = vec4(pos, 0, 1);\n"
458 			"  instanceIndex = gl_InstanceIndex;\n"
459 			"  readbackok = 1;\n"
460 			"  zero = 0;\n";
461 
462 		if (m_data.shaderWritesRate)
463 		{
464 			vss << "  gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
465 
466 			// Verify that we can read from the output variable
467 			vss << "  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
468 
469 			if (!m_data.geometryShader)
470 			{
471 				if (m_data.multiViewport)
472 					vss << "  gl_ViewportIndex = instanceIndex & 1;\n";
473 				if (m_data.colorLayered)
474 					vss << "  gl_Layer = ((instanceIndex & 2) >> 1);\n";
475 			}
476 		}
477 
478 		vss << "}\n";
479 
480 		programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
481 		programCollection.glslSources.add("vert_1_2") << glu::VertexSource(vss.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, true);
482 
483 		if (m_data.geometryShader)
484 		{
485 			std::string writeShadingRate = "";
486 			if (m_data.shaderWritesRate)
487 			{
488 				writeShadingRate =
489 					"  gl_PrimitiveShadingRateEXT = pc.shadingRate;\n"
490 					"  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
491 
492 				if (m_data.multiViewport)
493 					writeShadingRate += "  gl_ViewportIndex = inInstanceIndex[0] & 1;\n";
494 
495 				if (m_data.colorLayered)
496 					writeShadingRate += "  gl_Layer = (inInstanceIndex[0] & 2) >> 1;\n";
497 			}
498 
499 			std::stringstream gss;
500 			gss <<
501 				"#version 450 core\n"
502 				"#extension GL_EXT_fragment_shading_rate : enable\n"
503 				"\n"
504 				"layout(push_constant) uniform PC {\n"
505 				"	int shadingRate;\n"
506 				"} pc;\n"
507 				"\n"
508 				"in gl_PerVertex\n"
509 				"{\n"
510 				"   vec4 gl_Position;\n"
511 				"} gl_in[3];\n"
512 				"\n"
513 				"layout(location = 0) in int inInstanceIndex[];\n"
514 				"layout(location = 0) out int outInstanceIndex;\n"
515 				"layout(location = 1) out int readbackok;\n"
516 				"layout(location = 2) out float zero;\n"
517 				"layout(triangles) in;\n"
518 				"layout(triangle_strip, max_vertices=3) out;\n"
519 				"\n"
520 				"out gl_PerVertex {\n"
521 				"   vec4 gl_Position;\n"
522 				"};\n"
523 				"\n"
524 				"void main(void)\n"
525 				"{\n"
526 				"   gl_Position = gl_in[0].gl_Position;\n"
527 				"   outInstanceIndex = inInstanceIndex[0];\n"
528 				"   readbackok  = 1;\n"
529 				"   zero = 0;\n"
530 				<< writeShadingRate <<
531 				"   EmitVertex();"
532 				"\n"
533 				"   gl_Position = gl_in[1].gl_Position;\n"
534 				"   outInstanceIndex = inInstanceIndex[1];\n"
535 				"   readbackok = 1;\n"
536 				"   zero = 0;\n"
537 				<< writeShadingRate <<
538 				"   EmitVertex();"
539 				"\n"
540 				"   gl_Position = gl_in[2].gl_Position;\n"
541 				"   outInstanceIndex = inInstanceIndex[2];\n"
542 				"   readbackok = 1;\n"
543 				"   zero = 0;\n"
544 				<< writeShadingRate <<
545 				"   EmitVertex();"
546 				"}\n";
547 
548 			programCollection.glslSources.add("geom") << glu::GeometrySource(gss.str());
549 		}
550 	}
551 	else
552 	{
553 		std::stringstream mss;
554 
555 		mss <<
556 			"#version 450 core\n"
557 			"#extension GL_EXT_mesh_shader : enable\n"
558 			"layout(local_size_x=3) in;\n"
559 			"layout(triangles) out;\n"
560 			"layout(max_vertices=3, max_primitives=1) out;\n"
561 			"layout(push_constant, std430) uniform PC {\n"
562 			"  int shadingRate;\n"
563 			"  uint instanceIndex;\n"
564 			"} pc;\n"
565 			"layout(set=1, binding=0, std430) readonly buffer PosBuffer {\n"
566 			"  vec2 vertexPositions[];\n"
567 			"} pb;\n"
568 			"layout(location = 0) flat out int instanceIndex[];\n"
569 			"layout(location = 1) flat out int readbackok[];\n"
570 			"layout(location = 2) out float zero[];\n";
571 
572 		if (m_data.shaderWritesRate)
573 		{
574 			mss <<
575 				"perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
576 				<< (m_data.colorLayered ? "  int gl_Layer;\n" : "")
577 				<< (m_data.multiViewport ? "  int gl_ViewportIndex;\n" : "") <<
578 				"  int gl_PrimitiveShadingRateEXT;\n"
579 				"} gl_MeshPrimitivesEXT[];\n";
580 		}
581 
582 		mss <<
583 			"void main()\n"
584 			"{\n"
585 			"  SetMeshOutputsEXT(3u, 1u);\n"
586 			"  const uint vertexIdx = (pc.instanceIndex * 3u + gl_LocalInvocationIndex);\n"
587 			"  gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(pb.vertexPositions[vertexIdx], 0, 1);\n"
588 			"  if (gl_LocalInvocationIndex == 0) {\n"
589 			"    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
590 			"  }\n"
591 			"  instanceIndex[gl_LocalInvocationIndex] = int(pc.instanceIndex);\n"
592 			"  readbackok[gl_LocalInvocationIndex] = 1;\n"
593 			"  zero[gl_LocalInvocationIndex] = 0;\n";
594 
595 		if (m_data.shaderWritesRate)
596 		{
597 			mss << "  gl_MeshPrimitivesEXT[0].gl_PrimitiveShadingRateEXT = pc.shadingRate;\n";
598 
599 			// gl_MeshPerPrimitiveEXT is write-only in mesh shaders, so we cannot verify the readback operation.
600 			//mss << "  if (gl_PrimitiveShadingRateEXT != pc.shadingRate) readbackok = 0;\n";
601 
602 			if (m_data.multiViewport)
603 				mss << "  gl_MeshPrimitivesEXT[0].gl_ViewportIndex = int(pc.instanceIndex & 1);\n";
604 			if (m_data.colorLayered)
605 				mss << "  gl_MeshPrimitivesEXT[0].gl_Layer = int((pc.instanceIndex & 2) >> 1);\n";
606 		}
607 
608 		mss << "}\n";
609 
610 		const ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
611 		programCollection.glslSources.add("mesh") << glu::MeshSource(mss.str()) << buildOptions;
612 	}
613 
614 	std::stringstream fss;
615 
616 	fss <<
617 		"#version 450 core\n"
618 		"#extension GL_EXT_fragment_shading_rate : enable\n"
619 		"#extension GL_ARB_shader_stencil_export : enable\n"
620 		"#extension GL_ARB_fragment_shader_interlock : enable\n";
621 
622 	if (m_data.earlyAndLateTest)
623 		fss << "#extension GL_AMD_shader_early_and_late_fragment_tests : enable\n";
624 
625 	fss << "layout(location = 0) out uvec4 col0;\n"
626 		"layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
627 		"layout(set = 0, binding = 3) uniform usampler2D tex;\n"
628 		"layout(location = 0) flat in int instanceIndex;\n"
629 		"layout(location = 1) flat in int readbackok;\n"
630 		"layout(location = 2) " << (m_data.sampleShadingInput ? "sample " : "") << "in float zero;\n";
631 
632 	if (m_data.earlyAndLateTest)
633 		fss << "layout(early_and_late_fragment_tests_amd) in;\n";
634 
635 	if (m_data.fragDepth && m_data.earlyAndLateTest)
636 		fss << "layout(depth_less) out float gl_FragDepth;\n";
637 
638 	if (m_data.fragStencil && m_data.earlyAndLateTest)
639 		fss << "layout(stencil_ref_less_front_amd) out int gl_FragStencilRefARB;\n";
640 
641 	if (m_data.interlock)
642 		fss << "layout(pixel_interlock_ordered) in;\n";
643 
644 	fss <<
645 		"void main()\n"
646 		"{\n";
647 
648 	if (m_data.interlock)
649 		fss << "  beginInvocationInterlockARB();\n";
650 
651 	fss <<
652 		// X component gets shading rate enum
653 		"  col0.x = gl_ShadingRateEXT;\n"
654 		"  col0.y = 0;\n"
655 		// Z component gets packed primitiveID | atomic value
656 		"  col0.z = (instanceIndex << 24) | ((atomicAdd(buf.counter, 1) + 1) & 0x00FFFFFFu);\n"
657 		"  ivec2 fragCoordXY = ivec2(gl_FragCoord.xy);\n"
658 		"  ivec2 fragSize = ivec2(1<<((gl_ShadingRateEXT/4)&3), 1<<(gl_ShadingRateEXT&3));\n"
659 		// W component gets error code
660 		"  col0.w = uint(zero)" << (m_data.sampleShadingInput ? " * gl_SampleID" : "") << ";\n"
661 		"  if (((fragCoordXY - fragSize / 2) % fragSize) != ivec2(0,0))\n"
662 		"    col0.w = " << ERROR_FRAGCOORD_CENTER << ";\n";
663 
664 	if (m_data.shaderWritesRate)
665 	{
666 		fss <<
667 			"  if (readbackok != 1)\n"
668 			"    col0.w = " << ERROR_VTG_READBACK << ";\n";
669 	}
670 
671 	// When sample shading, gl_FragCoord is more likely to give bad derivatives,
672 	// e.g. due to a partially covered quad having some pixels center sample and
673 	// some sample at a sample location.
674 	if (!m_data.sampleShadingEnable && !m_data.sampleShadingInput)
675 	{
676 		fss << "  if (dFdx(gl_FragCoord.xy) != ivec2(fragSize.x, 0) || dFdy(gl_FragCoord.xy) != ivec2(0, fragSize.y))\n"
677 			   "    col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (int(dFdx(gl_FragCoord.xy)) << 14) | (int(dFdx(gl_FragCoord.xy)) << 8) | " << ERROR_FRAGCOORD_DERIV << ";\n";
678 
679 		fss << "  uint implicitDerivX = texture(tex, vec2(gl_FragCoord.x / textureSize(tex, 0).x, 0)).x;\n"
680 			   "  uint implicitDerivY = texture(tex, vec2(0, gl_FragCoord.y / textureSize(tex, 0).y)).x;\n"
681 			   "  if (implicitDerivX != fragSize.x || implicitDerivY != fragSize.y)\n"
682 			   "    col0.w = (fragSize.y << 26) | (fragSize.x << 20) | (implicitDerivY << 14) | (implicitDerivX << 8) | " << ERROR_FRAGCOORD_IMPLICIT_DERIV << ";\n";
683 	}
684 	// Y component gets sample mask value
685 	if (m_data.useSampleMaskIn)
686 		fss << "  col0.y = gl_SampleMaskIn[0];\n";
687 
688 	if (m_data.fragDepth)
689 		fss << "  gl_FragDepth = float(instanceIndex) / float(" << NUM_TRIANGLES << ");\n";
690 
691 	if (m_data.fragStencil)
692 		fss << "  gl_FragStencilRefARB = instanceIndex;\n";
693 
694 	if (m_data.interlock)
695 		fss << "  endInvocationInterlockARB();\n";
696 
697 	fss <<
698 		"}\n";
699 
700 	programCollection.glslSources.add("frag") << glu::FragmentSource(fss.str());
701 
702 	std::stringstream css;
703 
704 	std::string fsampType = m_data.samples > 1 ?  "texture2DMSArray" :  "texture2DArray";
705 	std::string usampType = m_data.samples > 1 ? "utexture2DMSArray" : "utexture2DArray";
706 
707 	// Compute shader copies color/depth/stencil to linear layout in buffer memory
708 	css <<
709 		"#version 450 core\n"
710 		"#extension GL_EXT_samplerless_texture_functions : enable\n"
711 		"layout(set = 0, binding = 1) uniform " << usampType << " colorTex;\n"
712 		"layout(set = 0, binding = 2, std430) buffer Block0 { uvec4 b[]; } colorbuf;\n"
713 		"layout(set = 0, binding = 4, std430) buffer Block1 { float b[]; } depthbuf;\n"
714 		"layout(set = 0, binding = 5, std430) buffer Block2 { uint b[]; } stencilbuf;\n"
715 		"layout(set = 0, binding = 6) uniform " << fsampType << " depthTex;\n"
716 		"layout(set = 0, binding = 7) uniform " << usampType << " stencilTex;\n"
717 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
718 		"void main()\n"
719 		"{\n"
720 		"   for (int i = 0; i < " << m_data.samples << "; ++i) {\n"
721 		"      uint idx = ((gl_GlobalInvocationID.z * " << m_data.framebufferDim.height << " + gl_GlobalInvocationID.y) * " << m_data.framebufferDim.width << " + gl_GlobalInvocationID.x) * " << m_data.samples << " + i;\n"
722 		"      colorbuf.b[idx] = texelFetch(colorTex, ivec3(gl_GlobalInvocationID.xyz), i);\n";
723 
724 	if (m_data.fragDepth)
725 		css << "      depthbuf.b[idx] = texelFetch(depthTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
726 
727 	if (m_data.fragStencil)
728 		css << "      stencilbuf.b[idx] = texelFetch(stencilTex, ivec3(gl_GlobalInvocationID.xyz), i).x;\n";
729 
730 	css <<
731 		"   }\n"
732 		"}\n";
733 
734 	programCollection.glslSources.add("comp") << glu::ComputeSource(css.str());
735 }
736 
createInstance(Context & context) const737 TestInstance* FSRTestCase::createInstance (Context& context) const
738 {
739 	return new FSRTestInstance(context, m_data);
740 }
741 
ShadingRateExtentToEnum(VkExtent2D ext) const742 deInt32 FSRTestInstance::ShadingRateExtentToEnum(VkExtent2D ext) const
743 {
744 	ext.width = deCtz32(ext.width);
745 	ext.height = deCtz32(ext.height);
746 
747 	return (ext.width << 2) | ext.height;
748 }
749 
ShadingRateEnumToExtent(deInt32 rate) const750 VkExtent2D FSRTestInstance::ShadingRateEnumToExtent(deInt32 rate) const
751 {
752 	VkExtent2D ret;
753 	ret.width = 1 << ((rate/4) & 3);
754 	ret.height = 1 << (rate & 3);
755 
756 	return ret;
757 }
758 
Combine(VkExtent2D ext0,VkExtent2D ext1,VkFragmentShadingRateCombinerOpKHR comb) const759 VkExtent2D FSRTestInstance::Combine(VkExtent2D ext0, VkExtent2D ext1, VkFragmentShadingRateCombinerOpKHR comb) const
760 {
761 	VkExtent2D ret;
762 	switch (comb)
763 	{
764 	default:
765 		DE_ASSERT(0);
766 		// fallthrough
767 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR:
768 		return ext0;
769 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR:
770 		return ext1;
771 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR:
772 		ret = { de::min(ext0.width, ext1.width), de::min(ext0.height, ext1.height) };
773 		return ret;
774 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR:
775 		ret = { de::max(ext0.width, ext1.width), de::max(ext0.height, ext1.height) };
776 		return ret;
777 	case VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR:
778 		ret = { ext0.width * ext1.width, ext0.height * ext1.height };
779 		if (!m_shadingRateProperties.fragmentShadingRateStrictMultiplyCombiner)
780 		{
781 			if (ext0.width == 1 && ext1.width == 1)
782 				ret.width = 2;
783 			if (ext0.height == 1 && ext1.height == 1)
784 				ret.height = 2;
785 		}
786 		return ret;
787 	}
788 }
789 
CombineMasks(deInt32 rateMask0,deInt32 rateMask1,VkFragmentShadingRateCombinerOpKHR comb,bool allowUnclampedResult) const790 deInt32 FSRTestInstance::CombineMasks(deInt32 rateMask0, deInt32 rateMask1, VkFragmentShadingRateCombinerOpKHR comb, bool allowUnclampedResult) const
791 {
792 	deInt32 combinedMask = 0;
793 
794 	for (int i = 0; i < 16; i++)
795 	{
796 		if (rateMask0 & (1 << i))
797 		{
798 			VkExtent2D rate0 = ShadingRateEnumToExtent(i);
799 
800 			for (int j = 0; j < 16; j++)
801 			{
802 				if (rateMask1 & (1 << j))
803 				{
804 					VkExtent2D	combinerResult	= Combine(rate0, ShadingRateEnumToExtent(j), comb);
805 					deInt32		clampedResult	= ShadingRateExtentToClampedMask(combinerResult);
806 
807 					if (allowUnclampedResult)
808 					{
809 						combinedMask |= 1 << ShadingRateExtentToEnum(combinerResult);
810 					}
811 
812 					combinedMask |= clampedResult;
813 				}
814 			}
815 		}
816 	}
817 
818 	return combinedMask;
819 }
820 
Simulate(deInt32 rate0,deInt32 rate1,deInt32 rate2)821 deInt32 FSRTestInstance::Simulate(deInt32 rate0, deInt32 rate1, deInt32 rate2)
822 {
823 	deInt32 &cachedRate = m_simulateCache[(rate2*m_simulateValueCount + rate1)*m_simulateValueCount + rate0];
824 	if (cachedRate != ~0)
825 		return cachedRate;
826 
827 	const VkExtent2D extent0 = ShadingRateEnumToExtent(rate0);
828 	const VkExtent2D extent1 = ShadingRateEnumToExtent(rate1);
829 	const VkExtent2D extent2 = ShadingRateEnumToExtent(rate2);
830 
831 	deInt32 finalMask = 0;
832 
833 	// Clamped and unclamped inputs.
834 	const deInt32 extentMask0 = ShadingRateExtentToClampedMask(extent0) | (1 << rate0);
835 	const deInt32 extentMask1 = ShadingRateExtentToClampedMask(extent1) | (1 << rate1);
836 	const deInt32 extentMask2 = ShadingRateExtentToClampedMask(extent2) | (1 << rate2);
837 
838 	// Combine rate 0 and 1, get a mask of possible clamped rates
839 	deInt32 intermedMask = CombineMasks(extentMask0, extentMask1, m_data.combinerOp[0], true /* allowUnclampedResult */);
840 
841 	// For each clamped rate, combine that with rate 2 and accumulate the possible clamped rates
842 	for (int i = 0; i < 16; ++i)
843 	{
844 		if (intermedMask & (1<<i))
845 		{
846 			finalMask |= CombineMasks(intermedMask , extentMask2, m_data.combinerOp[1], false /* allowUnclampedResult */);
847 		}
848 	}
849 
850 	if (Force1x1())
851 		finalMask = 0x1;
852 
853 	cachedRate = finalMask;
854 	return finalMask;
855 }
856 
857 // If a rate is not valid (<=4x4), clamp it to something valid.
858 // This is only used for "inputs" to the system, not to mimic
859 // how the implementation internally clamps intermediate values.
SanitizeExtent(VkExtent2D ext) const860 VkExtent2D FSRTestInstance::SanitizeExtent(VkExtent2D ext) const
861 {
862 	DE_ASSERT(ext.width > 0 && ext.height > 0);
863 
864 	ext.width = de::min(ext.width, 4u);
865 	ext.height = de::min(ext.height, 4u);
866 
867 	return ext;
868 }
869 
870 // Map an extent to a mask of all modes smaller than or equal to it in either dimension
ShadingRateExtentToClampedMask(VkExtent2D ext) const871 deInt32 FSRTestInstance::ShadingRateExtentToClampedMask(VkExtent2D ext) const
872 {
873 	const deUint32	shadingRateBit		= (1 << ShadingRateExtentToEnum(ext));
874 	deUint32		desiredSize			= ext.width * ext.height;
875 	deInt32			mask				= 0;
876 	deInt32			swappedSizesMask	= 0;
877 
878 	while (desiredSize > 0)
879 	{
880 		// First, find modes that maximize the area
881 		for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
882 		{
883 			const VkPhysicalDeviceFragmentShadingRateKHR &supportedRate = m_supportedFragmentShadingRates[i];
884 			if ((supportedRate.sampleCounts & m_data.samples) &&
885 				supportedRate.fragmentSize.width * supportedRate.fragmentSize.height == desiredSize)
886 			{
887 				if (supportedRate.fragmentSize.width  <= ext.width && supportedRate.fragmentSize.height <= ext.height)
888 				{
889 					mask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
890 				}
891 				else if (supportedRate.fragmentSize.height <= ext.width && supportedRate.fragmentSize.width  <= ext.height)
892 				{
893 					swappedSizesMask |= 1 << ShadingRateExtentToEnum(supportedRate.fragmentSize);
894 				}
895 			}
896 		}
897 		if (mask)
898 		{
899 			// Amongst the modes that maximize the area, pick the ones that
900 			// minimize the aspect ratio. Prefer ratio of 1, then 2, then 4.
901 			// 1x1 = 0, 2x2 = 5, 4x4 = 10
902 			static const deUint32 aspectMaskRatio1 = 0x421;
903 			// 2x1 = 4, 1x2 = 1, 4x2 = 9, 2x4 = 6
904 			static const deUint32 aspectMaskRatio2 = 0x252;
905 			// 4x1 = 8, 1x4 = 2,
906 			static const deUint32 aspectMaskRatio4 = 0x104;
907 
908 			if (mask & aspectMaskRatio1)
909 			{
910 				mask &= aspectMaskRatio1;
911 				break;
912 			}
913 			if (mask & aspectMaskRatio2)
914 			{
915 				mask &= aspectMaskRatio2;
916 				break;
917 			}
918 			if (mask & aspectMaskRatio4)
919 			{
920 				mask &= aspectMaskRatio4;
921 				break;
922 			}
923 			DE_ASSERT(0);
924 		}
925 		desiredSize /= 2;
926 	}
927 
928 	// Optionally include the sizes with swapped width and height.
929 	mask |= swappedSizesMask;
930 
931 	if (mask & shadingRateBit)
932 	{
933 		// The given shading rate is valid. Don't clamp it.
934 		return shadingRateBit;
935 	}
936 
937 	// Return alternative shading rates.
938 	return mask;
939 }
940 
941 
SanitizeRate(deInt32 rate) const942 deInt32 FSRTestInstance::SanitizeRate(deInt32 rate) const
943 {
944 	VkExtent2D extent = ShadingRateEnumToExtent(rate);
945 
946 	extent = SanitizeExtent(extent);
947 
948 	return ShadingRateExtentToEnum(extent);
949 }
950 
951 // Map primID % 9 to primitive shading rate
PrimIDToPrimitiveShadingRate(deInt32 primID)952 deInt32 FSRTestInstance::PrimIDToPrimitiveShadingRate(deInt32 primID)
953 {
954 	deInt32 &cachedRate = m_primIDToPrimitiveShadingRate[primID];
955 	if (cachedRate != ~0)
956 		return cachedRate;
957 
958 	VkExtent2D extent;
959 	extent.width = 1 << (primID % 3);
960 	extent.height = 1 << ((primID/3) % 3);
961 
962 	cachedRate = ShadingRateExtentToEnum(extent);
963 	return cachedRate;
964 }
965 
966 // Map primID / 9 to pipeline shading rate
PrimIDToPipelineShadingRate(deInt32 primID)967 deInt32 FSRTestInstance::PrimIDToPipelineShadingRate(deInt32 primID)
968 {
969 	deInt32 &cachedRate = m_primIDToPipelineShadingRate[primID];
970 	if (cachedRate != ~0)
971 		return cachedRate;
972 
973 	primID /= 9;
974 	VkExtent2D extent;
975 	extent.width = 1 << (primID % 3);
976 	extent.height = 1 << ((primID/3) % 3);
977 
978 	cachedRate = ShadingRateExtentToEnum(extent);
979 	return cachedRate;
980 }
981 
CreateCachedBuffer(const vk::DeviceInterface & vk,const vk::VkDevice device,vk::Allocator & allocator,const vk::VkBufferCreateInfo & bufferCreateInfo)982 static de::MovePtr<BufferWithMemory> CreateCachedBuffer(const vk::DeviceInterface&		vk,
983 														const vk::VkDevice				device,
984 														vk::Allocator&					allocator,
985 														const vk::VkBufferCreateInfo&	bufferCreateInfo)
986 {
987 	try
988 	{
989 		return de::MovePtr<BufferWithMemory>(new BufferWithMemory(
990 			vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Cached));
991 	}
992 	catch (const tcu::NotSupportedError&)
993 	{
994 		return de::MovePtr<BufferWithMemory>(new BufferWithMemory(
995 			vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
996 	}
997 }
998 
iterate(void)999 tcu::TestStatus FSRTestInstance::iterate (void)
1000 {
1001 	const DeviceInterface&	vk						= m_context.getDeviceInterface();
1002 	const VkDevice			device					= m_context.getDevice();
1003 	tcu::TestLog&			log						= m_context.getTestContext().getLog();
1004 	Allocator&				allocator				= m_context.getDefaultAllocator();
1005 	VkFlags					allShaderStages			= VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
1006 	VkFlags					allPipelineStages		= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
1007 													  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1008 													  VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1009 													  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
1010 													  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
1011 													  VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1012 	const VkFormat			cbFormat				= VK_FORMAT_R32G32B32A32_UINT;
1013 	VkFormat				dsFormat				= VK_FORMAT_UNDEFINED;
1014 	const auto				vertBufferUsage			= (m_data.meshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1015 
1016 	if (m_data.meshShader)
1017 	{
1018 #ifndef CTS_USES_VULKANSC
1019 		allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
1020 		allPipelineStages |= VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT;
1021 #else
1022 		DE_ASSERT(false);
1023 #endif // CTS_USES_VULKANSC
1024 	}
1025 	else
1026 	{
1027 		allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
1028 		allPipelineStages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
1029 
1030 		if (m_data.geometryShader)
1031 		{
1032 			allShaderStages	|= VK_SHADER_STAGE_GEOMETRY_BIT;
1033 			allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
1034 		}
1035 	}
1036 
1037 	if (m_data.useDepthStencil)
1038 	{
1039 		VkFormatProperties formatProps;
1040 		m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), VK_FORMAT_D32_SFLOAT_S8_UINT, &formatProps);
1041 		if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
1042 		{
1043 			dsFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
1044 		}
1045 		else
1046 		{
1047 			dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1048 		}
1049 	}
1050 
1051 	deRandom rnd;
1052 	deRandom_init(&rnd, m_data.seed);
1053 
1054 	qpTestResult res = QP_TEST_RESULT_PASS;
1055 	deUint32 numUnexpected1x1Samples = 0;
1056 	deUint32 numTotalSamples = 0;
1057 
1058 	enum AttachmentModes
1059 	{
1060 		ATTACHMENT_MODE_DEFAULT = 0,
1061 		ATTACHMENT_MODE_LAYOUT_OPTIMAL,
1062 		ATTACHMENT_MODE_IMAGELESS,
1063 		ATTACHMENT_MODE_2DARRAY,
1064 		ATTACHMENT_MODE_TILING_LINEAR,
1065 
1066 		ATTACHMENT_MODE_COUNT,
1067 	};
1068 
1069 	deUint32 numSRLayers = m_data.srLayered ? 2u : 1u;
1070 
1071 	VkExtent2D minFragmentShadingRateAttachmentTexelSize = {1, 1};
1072 	VkExtent2D maxFragmentShadingRateAttachmentTexelSize = {1, 1};
1073 	deUint32 maxFragmentShadingRateAttachmentTexelSizeAspectRatio = 1;
1074 	if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
1075 	{
1076 		minFragmentShadingRateAttachmentTexelSize = m_context.getFragmentShadingRateProperties().minFragmentShadingRateAttachmentTexelSize;
1077 		maxFragmentShadingRateAttachmentTexelSize = m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSize;
1078 		maxFragmentShadingRateAttachmentTexelSizeAspectRatio = m_context.getFragmentShadingRateProperties().maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
1079 	}
1080 
1081 	VkDeviceSize atomicBufferSize = sizeof(deUint32);
1082 
1083 	de::MovePtr<BufferWithMemory> atomicBuffer;
1084 	atomicBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1085 		vk, device, allocator, makeBufferCreateInfo(atomicBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
1086 
1087 	deUint32 *abuf = (deUint32 *)atomicBuffer->getAllocation().getHostPtr();
1088 
1089 	// NUM_TRIANGLES triangles, 3 vertices, 2 components of float position
1090 	VkDeviceSize vertexBufferSize = NUM_TRIANGLES * 3 * 2 * sizeof(float);
1091 
1092 	de::MovePtr<BufferWithMemory> vertexBuffer;
1093 	vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1094 		vk, device, allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vertBufferUsage), MemoryRequirement::HostVisible | MemoryRequirement::Coherent));
1095 
1096 	float *vbuf = (float *)vertexBuffer->getAllocation().getHostPtr();
1097 	for (deInt32 i = 0; i < (deInt32)(vertexBufferSize / sizeof(float)); ++i)
1098 	{
1099 		vbuf[i] = deRandom_getFloat(&rnd)*2.0f - 1.0f;
1100 	}
1101 	flushAlloc(vk, device, vertexBuffer->getAllocation());
1102 
1103 	VkDeviceSize colorOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples * 4 * sizeof(deUint32) * m_data.numColorLayers;
1104 	de::MovePtr<BufferWithMemory> colorOutputBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1105 
1106 	VkDeviceSize depthOutputBufferSize = 0, stencilOutputBufferSize = 0;
1107 	de::MovePtr<BufferWithMemory> depthOutputBuffer, stencilOutputBuffer;
1108 	if (m_data.useDepthStencil)
1109 	{
1110 		depthOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples * sizeof(float) * m_data.numColorLayers;
1111 		depthOutputBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(depthOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1112 
1113 		stencilOutputBufferSize = m_data.framebufferDim.width * m_data.framebufferDim.height * m_data.samples * sizeof(deUint32) * m_data.numColorLayers;
1114 		stencilOutputBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(stencilOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1115 	}
1116 
1117 	deUint32 minSRTexelWidth = minFragmentShadingRateAttachmentTexelSize.width;
1118 	deUint32 minSRTexelHeight = minFragmentShadingRateAttachmentTexelSize.height;
1119 	deUint32 maxSRWidth = (m_data.framebufferDim.width + minSRTexelWidth - 1) / minSRTexelWidth;
1120 	deUint32 maxSRHeight = (m_data.framebufferDim.height + minSRTexelHeight - 1) / minSRTexelHeight;
1121 
1122 	// max size over all formats
1123 	VkDeviceSize srFillBufferSize = numSRLayers * maxSRWidth * maxSRHeight * 32/*4 component 64-bit*/;
1124 	de::MovePtr<BufferWithMemory> srFillBuffer;
1125 	deUint8 *fillPtr = DE_NULL;
1126 	if (m_data.useAttachment())
1127 	{
1128 		srFillBuffer = CreateCachedBuffer(vk, device, allocator, makeBufferCreateInfo(srFillBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
1129 		fillPtr = (deUint8 *)srFillBuffer->getAllocation().getHostPtr();
1130 	}
1131 
1132 	de::MovePtr<ImageWithMemory> cbImage;
1133 	Move<VkImageView> cbImageView;
1134 	{
1135 		const VkImageCreateInfo			imageCreateInfo			=
1136 		{
1137 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1138 			DE_NULL,								// const void*				pNext;
1139 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1140 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1141 			cbFormat,								// VkFormat					format;
1142 			{
1143 				m_data.framebufferDim.width,		// deUint32	width;
1144 				m_data.framebufferDim.height,		// deUint32	height;
1145 				1u									// deUint32	depth;
1146 			},										// VkExtent3D				extent;
1147 			1u,										// deUint32					mipLevels;
1148 			m_data.numColorLayers,					// deUint32					arrayLayers;
1149 			m_data.samples,							// VkSampleCountFlagBits	samples;
1150 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1151 			cbUsage,								// VkImageUsageFlags		usage;
1152 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1153 			0u,										// deUint32					queueFamilyIndexCount;
1154 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1155 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1156 		};
1157 		cbImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1158 			vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1159 
1160 		VkImageViewCreateInfo		imageViewCreateInfo		=
1161 		{
1162 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1163 			DE_NULL,									// const void*				pNext;
1164 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1165 			**cbImage,									// VkImage					image;
1166 			VK_IMAGE_VIEW_TYPE_2D_ARRAY,				// VkImageViewType			viewType;
1167 			cbFormat,									// VkFormat					format;
1168 			{
1169 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1170 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1171 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1172 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1173 			},											// VkComponentMapping		 components;
1174 			{
1175 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
1176 				0u,										// deUint32				baseMipLevel;
1177 				1u,										// deUint32				levelCount;
1178 				0u,										// deUint32				baseArrayLayer;
1179 				m_data.numColorLayers					// deUint32				layerCount;
1180 			}											// VkImageSubresourceRange	subresourceRange;
1181 		};
1182 		cbImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1183 	}
1184 
1185 	de::MovePtr<ImageWithMemory> dsImage;
1186 	Move<VkImageView> dsImageView, dImageView, sImageView;
1187 
1188 	if (m_data.useDepthStencil)
1189 	{
1190 		const VkImageCreateInfo			imageCreateInfo			=
1191 		{
1192 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1193 			DE_NULL,								// const void*				pNext;
1194 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1195 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1196 			dsFormat,								// VkFormat					format;
1197 			{
1198 				m_data.framebufferDim.width,		// deUint32	width;
1199 				m_data.framebufferDim.height,		// deUint32	height;
1200 				1u									// deUint32	depth;
1201 			},										// VkExtent3D				extent;
1202 			1u,										// deUint32					mipLevels;
1203 			m_data.numColorLayers,					// deUint32					arrayLayers;
1204 			m_data.samples,							// VkSampleCountFlagBits	samples;
1205 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1206 			dsUsage,								// VkImageUsageFlags		usage;
1207 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1208 			0u,										// deUint32					queueFamilyIndexCount;
1209 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1210 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1211 		};
1212 		dsImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1213 			vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1214 
1215 		VkImageViewCreateInfo		imageViewCreateInfo		=
1216 		{
1217 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1218 			DE_NULL,									// const void*				pNext;
1219 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1220 			**dsImage,									// VkImage					image;
1221 			VK_IMAGE_VIEW_TYPE_2D_ARRAY,				// VkImageViewType			viewType;
1222 			dsFormat,									// VkFormat					format;
1223 			{
1224 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1225 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1226 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1227 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1228 			},											// VkComponentMapping		 components;
1229 			{
1230 				VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,	// VkImageAspectFlags	aspectMask;
1231 				0u,										// deUint32				baseMipLevel;
1232 				1u,										// deUint32				levelCount;
1233 				0u,										// deUint32				baseArrayLayer;
1234 				m_data.numColorLayers					// deUint32				layerCount;
1235 			}											// VkImageSubresourceRange	subresourceRange;
1236 		};
1237 		dsImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1238 		imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1239 		dImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1240 		imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1241 		sImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1242 	}
1243 
1244 	// Image used to test implicit derivative calculations.
1245 	// Filled with a value of 1<<lod.
1246 	de::MovePtr<ImageWithMemory> derivImage;
1247 	Move<VkImageView> derivImageView;
1248 	VkImageUsageFlags derivUsage = VK_IMAGE_USAGE_SAMPLED_BIT |
1249 								   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1250 	deUint32 derivNumLevels;
1251 	{
1252 		deUint32 maxDim = de::max(m_context.getFragmentShadingRateProperties().maxFragmentSize.width, m_context.getFragmentShadingRateProperties().maxFragmentSize.height);
1253 		derivNumLevels = 1 + deCtz32(maxDim);
1254 		const VkImageCreateInfo			imageCreateInfo			=
1255 		{
1256 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1257 			DE_NULL,								// const void*				pNext;
1258 			(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1259 			VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1260 			VK_FORMAT_R32_UINT,						// VkFormat					format;
1261 			{
1262 				m_context.getFragmentShadingRateProperties().maxFragmentSize.width,		// deUint32	width;
1263 				m_context.getFragmentShadingRateProperties().maxFragmentSize.height,	// deUint32	height;
1264 				1u									// deUint32	depth;
1265 			},										// VkExtent3D				extent;
1266 			derivNumLevels,							// deUint32					mipLevels;
1267 			1u,										// deUint32					arrayLayers;
1268 			VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1269 			VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1270 			derivUsage,								// VkImageUsageFlags		usage;
1271 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1272 			0u,										// deUint32					queueFamilyIndexCount;
1273 			DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1274 			VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1275 		};
1276 		derivImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1277 			vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1278 
1279 		VkImageViewCreateInfo		imageViewCreateInfo		=
1280 		{
1281 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1282 			DE_NULL,									// const void*				pNext;
1283 			(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1284 			**derivImage,								// VkImage					image;
1285 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
1286 			VK_FORMAT_R32_UINT,							// VkFormat					format;
1287 			{
1288 				VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1289 				VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1290 				VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1291 				VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1292 			},											// VkComponentMapping		 components;
1293 			{
1294 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
1295 				0u,										// deUint32				baseMipLevel;
1296 				derivNumLevels,							// deUint32				levelCount;
1297 				0u,										// deUint32				baseArrayLayer;
1298 				1u										// deUint32				layerCount;
1299 			}											// VkImageSubresourceRange	subresourceRange;
1300 		};
1301 		derivImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1302 	}
1303 
1304 	// sampler used with derivImage
1305 	const struct VkSamplerCreateInfo		samplerInfo	=
1306 	{
1307 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// sType
1308 		DE_NULL,									// pNext
1309 		0u,											// flags
1310 		VK_FILTER_NEAREST,							// magFilter
1311 		VK_FILTER_NEAREST,							// minFilter
1312 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
1313 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
1314 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
1315 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
1316 		0.0f,										// mipLodBias
1317 		VK_FALSE,									// anisotropyEnable
1318 		1.0f,										// maxAnisotropy
1319 		DE_FALSE,									// compareEnable
1320 		VK_COMPARE_OP_ALWAYS,						// compareOp
1321 		0.0f,										// minLod
1322 		(float)derivNumLevels,						// maxLod
1323 		VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,		// borderColor
1324 		VK_FALSE,									// unnormalizedCoords
1325 	};
1326 
1327 	Move<VkSampler>			sampler	= createSampler(vk, device, &samplerInfo);
1328 
1329 	std::vector<Move<vk::VkDescriptorSetLayout>> descriptorSetLayouts;
1330 	const VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
1331 
1332 	const VkDescriptorSetLayoutBinding bindings[] =
1333 	{
1334 		{
1335 			0u,										// binding
1336 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1337 			1u,										// descriptorCount
1338 			allShaderStages,						// stageFlags
1339 			DE_NULL,								// pImmutableSamplers
1340 		},
1341 		{
1342 			1u,										// binding
1343 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		// descriptorType
1344 			1u,										// descriptorCount
1345 			allShaderStages,						// stageFlags
1346 			DE_NULL,								// pImmutableSamplers
1347 		},
1348 		{
1349 			2u,										// binding
1350 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1351 			1u,										// descriptorCount
1352 			allShaderStages,						// stageFlags
1353 			DE_NULL,								// pImmutableSamplers
1354 		},
1355 		{
1356 			3u,										// binding
1357 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	// descriptorType
1358 			1u,										// descriptorCount
1359 			allShaderStages,						// stageFlags
1360 			DE_NULL,								// pImmutableSamplers
1361 		},
1362 		{
1363 			4u,										// binding
1364 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1365 			1u,										// descriptorCount
1366 			allShaderStages,						// stageFlags
1367 			DE_NULL,								// pImmutableSamplers
1368 		},
1369 		{
1370 			5u,										// binding
1371 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1372 			1u,										// descriptorCount
1373 			allShaderStages,						// stageFlags
1374 			DE_NULL,								// pImmutableSamplers
1375 		},
1376 		{
1377 			6u,										// binding
1378 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		// descriptorType
1379 			1u,										// descriptorCount
1380 			allShaderStages,						// stageFlags
1381 			DE_NULL,								// pImmutableSamplers
1382 		},
1383 		{
1384 			7u,										// binding
1385 			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		// descriptorType
1386 			1u,										// descriptorCount
1387 			allShaderStages,						// stageFlags
1388 			DE_NULL,								// pImmutableSamplers
1389 		},
1390 	};
1391 
1392 	// Create a layout and allocate a descriptor set for it.
1393 	const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
1394 	{
1395 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
1396 		DE_NULL,													// pNext
1397 		layoutCreateFlags,											// flags
1398 		static_cast<uint32_t>(de::arrayLength(bindings)),			// bindingCount
1399 		&bindings[0]												// pBindings
1400 	};
1401 
1402 	descriptorSetLayouts.push_back(vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo));
1403 
1404 	// Mesh shaders use set 1 binding 0 as the vertex buffer.
1405 	if (m_data.meshShader)
1406 	{
1407 #ifndef CTS_USES_VULKANSC
1408 		const VkDescriptorSetLayoutBinding extraBinding =
1409 		{
1410 			0u,										// binding
1411 			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,		// descriptorType
1412 			1u,										// descriptorCount
1413 			VK_SHADER_STAGE_MESH_BIT_EXT,			// stageFlags
1414 			DE_NULL,								// pImmutableSamplers
1415 		};
1416 
1417 		const VkDescriptorSetLayoutCreateInfo extraSetLayoutCreateInfo =
1418 		{
1419 			vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
1420 			DE_NULL,													// pNext
1421 			layoutCreateFlags,											// flags
1422 			1u,															// bindingCount
1423 			&extraBinding,												// pBindings
1424 		};
1425 
1426 		descriptorSetLayouts.push_back(vk::createDescriptorSetLayout(vk, device, &extraSetLayoutCreateInfo));
1427 #else
1428 		DE_ASSERT(false);
1429 #endif // CTS_USES_VULKANSC
1430 	}
1431 
1432 	const uint32_t							numConstants					= (m_data.meshShader ? 2u : 1u);
1433 	const uint32_t							pushConstantSize				= (static_cast<uint32_t>(sizeof(deInt32)) * numConstants);
1434 	const VkPushConstantRange				pushConstantRange				=
1435 	{
1436 		allShaderStages,	// VkShaderStageFlags					stageFlags;
1437 		0u,					// deUint32								offset;
1438 		pushConstantSize,	// deUint32								size;
1439 	};
1440 
1441 	std::vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw;
1442 	descriptorSetLayoutsRaw.reserve(descriptorSetLayouts.size());
1443 
1444 	std::transform(begin(descriptorSetLayouts), end(descriptorSetLayouts), std::back_inserter(descriptorSetLayoutsRaw),
1445 		[](const Move<VkDescriptorSetLayout>& elem) { return elem.get(); });
1446 
1447 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1448 	{
1449 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
1450 		DE_NULL,													// pNext
1451 		(VkPipelineLayoutCreateFlags)0,
1452 		static_cast<uint32_t>(descriptorSetLayoutsRaw.size()),		// setLayoutCount
1453 		de::dataOrNull(descriptorSetLayoutsRaw),					// pSetLayouts
1454 		1u,															// pushConstantRangeCount
1455 		&pushConstantRange,											// pPushConstantRanges
1456 	};
1457 
1458 	Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1459 
1460 	const Unique<VkShaderModule>	cs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
1461 
1462 	const VkPipelineShaderStageCreateInfo	csShaderCreateInfo =
1463 	{
1464 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1465 		DE_NULL,
1466 		(VkPipelineShaderStageCreateFlags)0,
1467 		VK_SHADER_STAGE_COMPUTE_BIT,								// stage
1468 		*cs,														// shader
1469 		"main",
1470 		DE_NULL,													// pSpecializationInfo
1471 	};
1472 
1473 	const VkComputePipelineCreateInfo		pipelineCreateInfo =
1474 	{
1475 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1476 		DE_NULL,
1477 		0u,															// flags
1478 		csShaderCreateInfo,											// cs
1479 		*pipelineLayout,											// layout
1480 		(vk::VkPipeline)0,											// basePipelineHandle
1481 		0u,															// basePipelineIndex
1482 	};
1483 	Move<VkPipeline> computePipeline = createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo, NULL);
1484 
1485 	for (deUint32 modeIdx = 0; modeIdx < ATTACHMENT_MODE_COUNT; ++modeIdx)
1486 	{
1487 		// If we're not using an attachment, don't test all the different attachment modes
1488 		if (modeIdx != ATTACHMENT_MODE_DEFAULT && !m_data.useAttachment())
1489 			continue;
1490 
1491 		// Consider all uint formats possible
1492 		static const VkFormat srFillFormats[] =
1493 		{
1494 			VK_FORMAT_R8_UINT,
1495 			VK_FORMAT_R8G8_UINT,
1496 			VK_FORMAT_R8G8B8_UINT,
1497 			VK_FORMAT_R8G8B8A8_UINT,
1498 			VK_FORMAT_R16_UINT,
1499 			VK_FORMAT_R16G16_UINT,
1500 			VK_FORMAT_R16G16B16_UINT,
1501 			VK_FORMAT_R16G16B16A16_UINT,
1502 			VK_FORMAT_R32_UINT,
1503 			VK_FORMAT_R32G32_UINT,
1504 			VK_FORMAT_R32G32B32_UINT,
1505 			VK_FORMAT_R32G32B32A32_UINT,
1506 			VK_FORMAT_R64_UINT,
1507 			VK_FORMAT_R64G64_UINT,
1508 			VK_FORMAT_R64G64B64_UINT,
1509 			VK_FORMAT_R64G64B64A64_UINT,
1510 		};
1511 		// Only test all formats in the default mode
1512 		deUint32 numFillFormats = modeIdx == ATTACHMENT_MODE_DEFAULT ? (deUint32)(sizeof(srFillFormats)/sizeof(srFillFormats[0])) : 1u;
1513 
1514 		// Iterate over all supported tile sizes and formats
1515 		for (deUint32 srTexelWidth  = minFragmentShadingRateAttachmentTexelSize.width;
1516 					  srTexelWidth <= maxFragmentShadingRateAttachmentTexelSize.width;
1517 					  srTexelWidth *= 2)
1518 		for (deUint32 srTexelHeight  = minFragmentShadingRateAttachmentTexelSize.height;
1519 					  srTexelHeight <= maxFragmentShadingRateAttachmentTexelSize.height;
1520 					  srTexelHeight *= 2)
1521 		for (deUint32 formatIdx = 0; formatIdx < numFillFormats; ++formatIdx)
1522 		{
1523 			deUint32 aspectRatio = (srTexelHeight > srTexelWidth) ? (srTexelHeight / srTexelWidth) : (srTexelWidth / srTexelHeight);
1524 			if (aspectRatio > maxFragmentShadingRateAttachmentTexelSizeAspectRatio)
1525 				continue;
1526 
1527 			// Go through the loop only once when not using an attachment
1528 			if (!m_data.useAttachment() &&
1529 				(srTexelWidth != minFragmentShadingRateAttachmentTexelSize.width ||
1530 				 srTexelHeight != minFragmentShadingRateAttachmentTexelSize.height ||
1531 				 formatIdx != 0))
1532 				 continue;
1533 
1534 			bool imagelessFB = modeIdx == ATTACHMENT_MODE_IMAGELESS;
1535 
1536 			deUint32 srWidth = (m_data.framebufferDim.width + srTexelWidth - 1) / srTexelWidth;
1537 			deUint32 srHeight = (m_data.framebufferDim.height + srTexelHeight - 1) / srTexelHeight;
1538 
1539 			VkFormat srFormat = srFillFormats[formatIdx];
1540 			deUint32 srFillBpp = tcu::getPixelSize(mapVkFormat(srFormat));
1541 
1542 			VkImageLayout	srLayout	= modeIdx == ATTACHMENT_MODE_LAYOUT_OPTIMAL ? VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR : VK_IMAGE_LAYOUT_GENERAL;
1543 			VkImageViewType srViewType	= modeIdx == ATTACHMENT_MODE_2DARRAY ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
1544 			VkImageTiling	srTiling	= (modeIdx == ATTACHMENT_MODE_TILING_LINEAR) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1545 
1546 			VkFormatProperties srFormatProperties;
1547 			m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), srFormat, &srFormatProperties);
1548 			VkFormatFeatureFlags srFormatFeatures = srTiling == VK_IMAGE_TILING_LINEAR ? srFormatProperties.linearTilingFeatures : srFormatProperties.optimalTilingFeatures;
1549 
1550 			if (m_context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate &&
1551 				!(srFormatFeatures & VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
1552 			{
1553 				if (srFormat == VK_FORMAT_R8_UINT && srTiling == VK_IMAGE_TILING_OPTIMAL)
1554 				{
1555 					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;
1556 					res = QP_TEST_RESULT_FAIL;
1557 				}
1558 				continue;
1559 			}
1560 
1561 			Move<vk::VkDescriptorPool>					descriptorPool;
1562 			std::vector<Move<vk::VkDescriptorSet>>		descriptorSets;
1563 			VkDescriptorPoolCreateFlags					poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1564 
1565 			vk::DescriptorPoolBuilder poolBuilder;
1566 			for (deInt32 i = 0; i < (deInt32)(sizeof(bindings)/sizeof(bindings[0])); ++i)
1567 				poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1568 			if (m_data.meshShader)
1569 				poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1570 
1571 			descriptorPool = poolBuilder.build(vk, device, poolCreateFlags, static_cast<uint32_t>(descriptorSetLayouts.size()));
1572 			for (const auto& setLayout : descriptorSetLayouts)
1573 				descriptorSets.push_back(makeDescriptorSet(vk, device, *descriptorPool, *setLayout));
1574 
1575 			const auto mainDescriptorSet = descriptorSets.front().get();
1576 
1577 			de::MovePtr<ImageWithMemory> srImage;
1578 			Move<VkImageView> srImageView;
1579 			VkImageUsageFlags srUsage = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1580 										VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1581 										VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1582 
1583 			if (m_data.useAttachment())
1584 			{
1585 				const VkImageCreateInfo			imageCreateInfo			=
1586 				{
1587 					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1588 					DE_NULL,								// const void*				pNext;
1589 					(VkImageCreateFlags)0u,					// VkImageCreateFlags		flags;
1590 					VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1591 					srFormat,								// VkFormat					format;
1592 					{
1593 						srWidth,							// deUint32	width;
1594 						srHeight,							// deUint32	height;
1595 						1u									// deUint32	depth;
1596 					},										// VkExtent3D				extent;
1597 					1u,										// deUint32					mipLevels;
1598 					numSRLayers,							// deUint32					arrayLayers;
1599 					VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1600 					srTiling,								// VkImageTiling			tiling;
1601 					srUsage,								// VkImageUsageFlags		usage;
1602 					VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1603 					0u,										// deUint32					queueFamilyIndexCount;
1604 					DE_NULL,								// const deUint32*			pQueueFamilyIndices;
1605 					VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout;
1606 				};
1607 				srImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
1608 					vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1609 
1610 				VkImageViewCreateInfo		imageViewCreateInfo		=
1611 				{
1612 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1613 					DE_NULL,									// const void*				pNext;
1614 					(VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
1615 					**srImage,									// VkImage					image;
1616 					srViewType,									// VkImageViewType			viewType;
1617 					srFormat,									// VkFormat					format;
1618 					{
1619 						VK_COMPONENT_SWIZZLE_R,					// VkComponentSwizzle	r;
1620 						VK_COMPONENT_SWIZZLE_G,					// VkComponentSwizzle	g;
1621 						VK_COMPONENT_SWIZZLE_B,					// VkComponentSwizzle	b;
1622 						VK_COMPONENT_SWIZZLE_A					// VkComponentSwizzle	a;
1623 					},											// VkComponentMapping		 components;
1624 					{
1625 						VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
1626 						0u,										// deUint32				baseMipLevel;
1627 						1u,										// deUint32				levelCount;
1628 						0u,										// deUint32				baseArrayLayer;
1629 						srViewType == VK_IMAGE_VIEW_TYPE_2D ?
1630 						1 : numSRLayers,						// deUint32				layerCount;
1631 					}											// VkImageSubresourceRange	subresourceRange;
1632 				};
1633 				srImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
1634 			}
1635 
1636 			VkDescriptorImageInfo imageInfo;
1637 			VkDescriptorBufferInfo bufferInfo;
1638 
1639 			VkWriteDescriptorSet w =
1640 			{
1641 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
1642 				DE_NULL,														// pNext
1643 				descriptorSets.front().get(),									// dstSet
1644 				(deUint32)0,													// dstBinding
1645 				0,																// dstArrayElement
1646 				1u,																// descriptorCount
1647 				bindings[0].descriptorType,										// descriptorType
1648 				&imageInfo,														// pImageInfo
1649 				&bufferInfo,													// pBufferInfo
1650 				DE_NULL,														// pTexelBufferView
1651 			};
1652 
1653 			abuf[0] = 0;
1654 			flushAlloc(vk, device, atomicBuffer->getAllocation());
1655 
1656 			bufferInfo = makeDescriptorBufferInfo(**atomicBuffer, 0, atomicBufferSize);
1657 			w.dstBinding = 0;
1658 			w.descriptorType = bindings[0].descriptorType;
1659 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1660 
1661 			imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImageView, VK_IMAGE_LAYOUT_GENERAL);
1662 			w.dstBinding = 1;
1663 			w.descriptorType = bindings[1].descriptorType;
1664 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1665 
1666 			bufferInfo = makeDescriptorBufferInfo(**colorOutputBuffer, 0, colorOutputBufferSize);
1667 			w.dstBinding = 2;
1668 			w.descriptorType = bindings[2].descriptorType;
1669 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1670 
1671 			imageInfo = makeDescriptorImageInfo(*sampler, *derivImageView, VK_IMAGE_LAYOUT_GENERAL);
1672 			w.dstBinding = 3;
1673 			w.descriptorType = bindings[3].descriptorType;
1674 			vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1675 
1676 			if (m_data.useDepthStencil)
1677 			{
1678 				bufferInfo = makeDescriptorBufferInfo(**depthOutputBuffer, 0, depthOutputBufferSize);
1679 				w.dstBinding = 4;
1680 				w.descriptorType = bindings[4].descriptorType;
1681 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1682 
1683 				bufferInfo = makeDescriptorBufferInfo(**stencilOutputBuffer, 0, stencilOutputBufferSize);
1684 				w.dstBinding = 5;
1685 				w.descriptorType = bindings[5].descriptorType;
1686 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1687 
1688 				imageInfo = makeDescriptorImageInfo(DE_NULL, *dImageView, VK_IMAGE_LAYOUT_GENERAL);
1689 				w.dstBinding = 6;
1690 				w.descriptorType = bindings[6].descriptorType;
1691 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1692 
1693 				imageInfo = makeDescriptorImageInfo(DE_NULL, *sImageView, VK_IMAGE_LAYOUT_GENERAL);
1694 				w.dstBinding = 7;
1695 				w.descriptorType = bindings[7].descriptorType;
1696 				vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1697 			}
1698 
1699 			// Update vertex buffer descriptor.
1700 			if (m_data.meshShader)
1701 			{
1702 				const auto					extraBufferInfo	= makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
1703 				const VkWriteDescriptorSet	extraWrite		=
1704 				{
1705 					VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
1706 					DE_NULL,														// pNext
1707 					descriptorSets.back().get(),									// dstSet
1708 					(deUint32)0,													// dstBinding
1709 					0,																// dstArrayElement
1710 					1u,																// descriptorCount
1711 					VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,								// descriptorType
1712 					nullptr,														// pImageInfo
1713 					&extraBufferInfo,												// pBufferInfo
1714 					DE_NULL,														// pTexelBufferView
1715 				};
1716 
1717 				vk.updateDescriptorSets(device, 1u, &extraWrite, 0u, nullptr);
1718 			}
1719 
1720 			Move<VkRenderPass> renderPass;
1721 			Move<VkFramebuffer> framebuffer;
1722 
1723 			std::vector<VkImageView> attachments;
1724 			attachments.push_back(*cbImageView);
1725 			deUint32 dsAttachmentIdx = 0, srAttachmentIdx = 0;
1726 			if (m_data.useAttachment())
1727 			{
1728 				srAttachmentIdx = (deUint32)attachments.size();
1729 				attachments.push_back(*srImageView);
1730 			}
1731 			if (m_data.useDepthStencil)
1732 			{
1733 				dsAttachmentIdx = (deUint32)attachments.size();
1734 				attachments.push_back(*dsImageView);
1735 			}
1736 
1737 			if (!m_data.groupParams->useDynamicRendering)
1738 			{
1739 				const vk::VkAttachmentReference2 colorAttachmentReference
1740 				{
1741 					VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,					// sType
1742 					DE_NULL,													// pNext
1743 					0,															// attachment
1744 					vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
1745 					0,															// aspectMask
1746 				};
1747 
1748 				const vk::VkAttachmentReference2 fragmentShadingRateAttachment =
1749 				{
1750 					VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,					// sType
1751 					DE_NULL,													// pNext
1752 					srAttachmentIdx,											// attachment
1753 					srLayout,													// layout
1754 					0,															// aspectMask
1755 				};
1756 
1757 				const vk::VkAttachmentReference2 depthAttachmentReference =
1758 				{
1759 					VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,					// sType
1760 					DE_NULL,													// pNext
1761 					dsAttachmentIdx,											// attachment
1762 					vk::VK_IMAGE_LAYOUT_GENERAL,								// layout
1763 					0,															// aspectMask
1764 				};
1765 
1766 				const bool										noAttachmentPtr				= (m_data.attachmentUsage == AttachmentUsage::NO_ATTACHMENT_PTR);
1767 				const VkFragmentShadingRateAttachmentInfoKHR	shadingRateAttachmentInfo	=
1768 				{
1769 					VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,							// VkStructureType				  sType;
1770 					DE_NULL,																				// const void*					  pNext;
1771 					(noAttachmentPtr ? nullptr : &fragmentShadingRateAttachment),							// const VkAttachmentReference2*	pFragmentShadingRateAttachment;
1772 					{ srTexelWidth, srTexelHeight },														// VkExtent2D					   shadingRateAttachmentTexelSize;
1773 				};
1774 
1775 				const bool						useAttachmentInfo	= (m_data.attachmentUsage != AttachmentUsage::NO_ATTACHMENT);
1776 				const VkSubpassDescription2		subpassDesc			=
1777 				{
1778 					VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,						// sType
1779 					(useAttachmentInfo ? &shadingRateAttachmentInfo : nullptr),		// pNext;
1780 					(vk::VkSubpassDescriptionFlags)0,								// flags
1781 					vk::VK_PIPELINE_BIND_POINT_GRAPHICS,							// pipelineBindPoint
1782 					m_data.multiView ? 0x3 : 0u,									// viewMask
1783 					0u,																// inputCount
1784 					DE_NULL,														// pInputAttachments
1785 					1,																// colorCount
1786 					&colorAttachmentReference,										// pColorAttachments
1787 					DE_NULL,														// pResolveAttachments
1788 					m_data.useDepthStencil ? &depthAttachmentReference : DE_NULL,	// depthStencilAttachment
1789 					0u,																// preserveCount
1790 					DE_NULL,														// pPreserveAttachments
1791 				};
1792 
1793 				std::vector<VkAttachmentDescription2> attachmentDescriptions
1794 				{
1795 					{
1796 						VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType sType;
1797 						DE_NULL,									// const void* pNext;
1798 						(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
1799 						cbFormat,					// VkFormat							format;
1800 						m_data.samples,								// VkSampleCountFlagBits			samples;
1801 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
1802 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
1803 						VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
1804 						VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
1805 						VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
1806 						VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
1807 					}
1808 				};
1809 				if (m_data.useAttachment())
1810 					attachmentDescriptions.push_back(
1811 					{
1812 						VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType sType;
1813 						DE_NULL,									// const void* pNext;
1814 						(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
1815 						srFormat,									// VkFormat							format;
1816 						VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
1817 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
1818 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
1819 						VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
1820 						VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
1821 						srLayout,									// VkImageLayout					initialLayout;
1822 						srLayout									// VkImageLayout					finalLayout;
1823 					}
1824 					);
1825 
1826 				if (m_data.useDepthStencil)
1827 					attachmentDescriptions.push_back(
1828 					{
1829 						VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,	// VkStructureType sType;
1830 						DE_NULL,									// const void* pNext;
1831 						(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
1832 						dsFormat,									// VkFormat							format;
1833 						m_data.samples,								// VkSampleCountFlagBits			samples;
1834 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp;
1835 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
1836 						VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				stencilLoadOp;
1837 						VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				stencilStoreOp;
1838 						VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout					initialLayout;
1839 						VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					finalLayout;
1840 					}
1841 					);
1842 
1843 				const deUint32					correlatedViewMask = 0x3;
1844 				const VkRenderPassCreateInfo2	renderPassParams	=
1845 				{
1846 					VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,			// sType
1847 					DE_NULL,												// pNext
1848 					(vk::VkRenderPassCreateFlags)0,
1849 					(deUint32)attachmentDescriptions.size(),				// attachmentCount
1850 					&attachmentDescriptions[0],								// pAttachments
1851 					1u,														// subpassCount
1852 					&subpassDesc,											// pSubpasses
1853 					0u,														// dependencyCount
1854 					DE_NULL,												// pDependencies
1855 					m_data.correlationMask,									// correlatedViewMaskCount
1856 					m_data.correlationMask ? &correlatedViewMask : DE_NULL	// pCorrelatedViewMasks
1857 				};
1858 
1859 				renderPass = createRenderPass2(vk, device, &renderPassParams);
1860 
1861 				std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo;
1862 				framebufferAttachmentImageInfo.push_back(
1863 					{
1864 						VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		//  VkStructureType		sType;
1865 						DE_NULL,													//  const void*			pNext;
1866 						(VkImageCreateFlags)0u,										//  VkImageCreateFlags	flags;
1867 						cbUsage,													//  VkImageUsageFlags	usage;
1868 						m_data.framebufferDim.width,								//  deUint32			width;
1869 						m_data.framebufferDim.height,								//  deUint32			height;
1870 						m_data.numColorLayers,										//  deUint32			layerCount;
1871 						1u,															//  deUint32			viewFormatCount;
1872 						&cbFormat													//  const VkFormat*		pViewFormats;
1873 					}
1874 				);
1875 				if (m_data.useAttachment())
1876 					framebufferAttachmentImageInfo.push_back(
1877 					{
1878 						VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		//  VkStructureType		sType;
1879 						DE_NULL,													//  const void*			pNext;
1880 						(VkImageCreateFlags)0u,										//  VkImageCreateFlags	flags;
1881 						srUsage,													//  VkImageUsageFlags	usage;
1882 						srWidth,													//  deUint32			width;
1883 						srHeight,													//  deUint32			height;
1884 						srViewType == VK_IMAGE_VIEW_TYPE_2D ? 1 : numSRLayers,		//  deUint32			layerCount;
1885 						1u,															//  deUint32			viewFormatCount;
1886 						&srFormat													//  const VkFormat*		pViewFormats;
1887 					}
1888 					);
1889 
1890 				if (m_data.useDepthStencil)
1891 					framebufferAttachmentImageInfo.push_back(
1892 					{
1893 						VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,		//  VkStructureType		sType;
1894 						DE_NULL,													//  const void*			pNext;
1895 						(VkImageCreateFlags)0u,										//  VkImageCreateFlags	flags;
1896 						dsUsage,													//  VkImageUsageFlags	usage;
1897 						m_data.framebufferDim.width,								//  deUint32			width;
1898 						m_data.framebufferDim.height,								//  deUint32			height;
1899 						m_data.numColorLayers,										//  deUint32			layerCount;
1900 						1u,															//  deUint32			viewFormatCount;
1901 						&dsFormat													//  const VkFormat*		pViewFormats;
1902 					}
1903 					);
1904 
1905 				const VkFramebufferAttachmentsCreateInfo				framebufferAttachmentsCreateInfo	=
1906 				{
1907 					VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO,		//  VkStructureType								sType;
1908 					DE_NULL,													//  const void*									pNext;
1909 					(deUint32)framebufferAttachmentImageInfo.size(),			//  deUint32									attachmentImageInfoCount;
1910 					&framebufferAttachmentImageInfo[0]							//  const VkFramebufferAttachmentImageInfo*		pAttachmentImageInfos;
1911 				};
1912 
1913 				const vk::VkFramebufferCreateInfo	framebufferParams	=
1914 				{
1915 					vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// sType
1916 					imagelessFB ? &framebufferAttachmentsCreateInfo : DE_NULL,				// pNext
1917 					(vk::VkFramebufferCreateFlags)(imagelessFB ? VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT : 0),
1918 					*renderPass,									// renderPass
1919 					(deUint32)attachments.size(),					// attachmentCount
1920 					imagelessFB ? DE_NULL : &attachments[0],		// pAttachments
1921 					m_data.framebufferDim.width,					// width
1922 					m_data.framebufferDim.height,					// height
1923 					m_data.multiView ? 1 : m_data.numColorLayers,	// layers
1924 				};
1925 
1926 				framebuffer = createFramebuffer(vk, device, &framebufferParams);
1927 			}
1928 
1929 			const VkVertexInputBindingDescription		vertexBinding =
1930 			{
1931 				0u,							// deUint32				binding;
1932 				sizeof(float) * 2,			// deUint32				stride;
1933 				VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
1934 			};
1935 			const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
1936 			{
1937 				0u,							// deUint32	location;
1938 				0u,							// deUint32	binding;
1939 				VK_FORMAT_R32G32_SFLOAT,	// VkFormat	format;
1940 				0u							// deUint32	offset;
1941 			};
1942 
1943 			const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
1944 			{
1945 				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
1946 				DE_NULL,													// const void*								pNext;
1947 				(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
1948 				1u,															// deUint32									vertexBindingDescriptionCount;
1949 				&vertexBinding,												// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1950 				1u,															// deUint32									vertexAttributeDescriptionCount;
1951 				&vertexInputAttributeDescription							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1952 			};
1953 
1954 			const VkPipelineRasterizationConservativeStateCreateInfoEXT consRastState =
1955 			{
1956 				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,	// VkStructureType										   sType;
1957 				DE_NULL,																		// const void*											   pNext;
1958 				(VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,						// VkPipelineRasterizationConservativeStateCreateFlagsEXT	flags;
1959 				m_data.conservativeMode,														// VkConservativeRasterizationModeEXT						conservativeRasterizationMode;
1960 				0.0f,																			// float													 extraPrimitiveOverestimationSize;
1961 			};
1962 
1963 			const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
1964 			{
1965 				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
1966 				m_data.conservativeEnable ? &consRastState : DE_NULL,			// const void*								pNext;
1967 				(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags	flags;
1968 				VK_FALSE,														// VkBool32									depthClampEnable;
1969 				VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
1970 				VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
1971 				VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
1972 				VK_FRONT_FACE_CLOCKWISE,										// VkFrontFace								frontFace;
1973 				VK_FALSE,														// VkBool32									depthBiasEnable;
1974 				0.0f,															// float									depthBiasConstantFactor;
1975 				0.0f,															// float									depthBiasClamp;
1976 				0.0f,															// float									depthBiasSlopeFactor;
1977 				1.0f															// float									lineWidth;
1978 			};
1979 
1980 			// Kill some bits from each AA mode
1981 			const VkSampleMask	sampleMask	= m_data.sampleMaskTest ? 0x9 : 0x7D56;
1982 			const VkSampleMask*	pSampleMask = m_data.useApiSampleMask ? &sampleMask : DE_NULL;
1983 
1984 			// All samples at pixel center. We'll validate that pixels are fully covered or uncovered.
1985 			std::vector<VkSampleLocationEXT> sampleLocations(m_data.samples, { 0.5f, 0.5f });
1986 			const VkSampleLocationsInfoEXT sampleLocationsInfo =
1987 			{
1988 				VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,	// VkStructureType				sType;
1989 				DE_NULL,										// const void*					pNext;
1990 				(VkSampleCountFlagBits)m_data.samples,			// VkSampleCountFlagBits		sampleLocationsPerPixel;
1991 				{ 1, 1 },										// VkExtent2D					sampleLocationGridSize;
1992 				(deUint32)m_data.samples,						// uint32_t						sampleLocationsCount;
1993 				&sampleLocations[0],							// const VkSampleLocationEXT*	pSampleLocations;
1994 			};
1995 
1996 			const VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo =
1997 			{
1998 				VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT,	// VkStructureType			sType;
1999 				DE_NULL,															// const void*				pNext;
2000 				VK_TRUE,															// VkBool32					sampleLocationsEnable;
2001 				sampleLocationsInfo,												// VkSampleLocationsInfoEXT	sampleLocationsInfo;
2002 			};
2003 
2004 			const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo =
2005 			{
2006 				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
2007 				m_data.sampleLocations ? &pipelineSampleLocationsCreateInfo : DE_NULL,	// const void*					pNext
2008 				0u,															// VkPipelineMultisampleStateCreateFlags	flags
2009 				(VkSampleCountFlagBits)m_data.samples,						// VkSampleCountFlagBits					rasterizationSamples
2010 				(VkBool32)m_data.sampleShadingEnable,						// VkBool32									sampleShadingEnable
2011 				1.0f,														// float									minSampleShading
2012 				pSampleMask,												// const VkSampleMask*						pSampleMask
2013 				VK_FALSE,													// VkBool32									alphaToCoverageEnable
2014 				VK_FALSE													// VkBool32									alphaToOneEnable
2015 			};
2016 
2017 			std::vector<VkViewport> viewports;
2018 			std::vector<VkRect2D> scissors;
2019 			if (m_data.multiViewport)
2020 			{
2021 				// Split the viewport into left and right halves
2022 				int x0 = 0, x1 = m_data.framebufferDim.width/2, x2 = m_data.framebufferDim.width;
2023 
2024 				viewports.push_back(makeViewport((float)x0, 0, std::max((float)(x1 - x0), 1.0f), (float)m_data.framebufferDim.height, 0.0f, 1.0f));
2025 				scissors.push_back(makeRect2D(x0, 0, x1 - x0, m_data.framebufferDim.height));
2026 
2027 				viewports.push_back(makeViewport((float)x1, 0, std::max((float)(x2 - x1), 1.0f), (float)m_data.framebufferDim.height, 0.0f, 1.0f));
2028 				scissors.push_back(makeRect2D(x1, 0, x2 - x1, m_data.framebufferDim.height));
2029 			}
2030 			else
2031 			{
2032 				viewports.push_back(makeViewport(m_data.framebufferDim.width, m_data.framebufferDim.height));
2033 				scissors.push_back(makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height));
2034 			}
2035 
2036 			const auto& binaries = m_context.getBinaryCollection();
2037 			Move<VkShaderModule> fragShader = createShaderModule(vk, device, binaries.get("frag"), 0);
2038 			Move<VkShaderModule> vertShader;
2039 			Move<VkShaderModule> geomShader;
2040 			Move<VkShaderModule> meshShader;
2041 
2042 			if (m_data.meshShader)
2043 			{
2044 				meshShader = createShaderModule(vk, device, binaries.get("mesh"), 0);
2045 			}
2046 			else
2047 			{
2048 				if (m_context.contextSupports(VK_API_VERSION_1_2))
2049 					vertShader = createShaderModule(vk, device, binaries.get("vert_1_2"), 0);
2050 				else
2051 					vertShader = createShaderModule(vk, device, binaries.get("vert"), 0);
2052 
2053 				if (m_data.geometryShader)
2054 					geomShader = createShaderModule(vk, device, binaries.get("geom"), 0);
2055 			}
2056 
2057 			const deUint32 fragSizeWH = m_data.sampleMaskTest ? 2 : 1;
2058 
2059 			PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
2060 #ifndef CTS_USES_VULKANSC
2061 			VkPipelineRenderingCreateInfoKHR renderingCreateInfo
2062 			{
2063 				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
2064 				DE_NULL,
2065 				m_data.multiView ? 0x3 : 0u,
2066 				1u,
2067 				&cbFormat,
2068 				dsFormat,
2069 				dsFormat
2070 			};
2071 			renderingCreateInfoWrapper.ptr = m_data.groupParams->useDynamicRendering ? &renderingCreateInfo : DE_NULL;
2072 #endif // CTS_USES_VULKANSC
2073 
2074 			VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo
2075 			{
2076 				VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,	// VkStructureType						sType;
2077 				renderingCreateInfoWrapper.ptr,											// const void*							pNext;
2078 				{ fragSizeWH, fragSizeWH },												// VkExtent2D							fragmentSize;
2079 				{ m_data.combinerOp[0], m_data.combinerOp[1] },							// VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
2080 			};
2081 
2082 			VkDynamicState dynamicState = VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR;
2083 			const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo
2084 			{
2085 				VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,		// VkStructureType						sType;
2086 				DE_NULL,													// const void*							pNext;
2087 				(VkPipelineDynamicStateCreateFlags)0,						// VkPipelineDynamicStateCreateFlags	flags;
2088 				m_data.useDynamicState ? 1u : 0u,							// uint32_t								dynamicStateCount;
2089 				&dynamicState,												// const VkDynamicState*				pDynamicStates;
2090 			};
2091 
2092 			// Enable depth/stencil writes, always passing
2093 			VkPipelineDepthStencilStateCreateInfo		depthStencilStateParams
2094 			{
2095 				VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
2096 				DE_NULL,													// const void*								pNext;
2097 				0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
2098 				VK_TRUE,													// VkBool32									depthTestEnable;
2099 				VK_TRUE,													// VkBool32									depthWriteEnable;
2100 				VK_COMPARE_OP_ALWAYS,										// VkCompareOp								depthCompareOp;
2101 				VK_FALSE,													// VkBool32									depthBoundsTestEnable;
2102 				VK_TRUE,													// VkBool32									stencilTestEnable;
2103 				// VkStencilOpState	front;
2104 				{
2105 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
2106 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
2107 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
2108 					VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
2109 					0u,						// deUint32		compareMask;
2110 					0xFFu,					// deUint32		writeMask;
2111 					0xFFu,					// deUint32		reference;
2112 				},
2113 				// VkStencilOpState	back;
2114 				{
2115 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	failOp;
2116 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp;
2117 					VK_STENCIL_OP_REPLACE,	// VkStencilOp	depthFailOp;
2118 					VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp;
2119 					0u,						// deUint32		compareMask;
2120 					0xFFu,					// deUint32		writeMask;
2121 					0xFFu,					// deUint32		reference;
2122 				},
2123 				0.0f,						// float			minDepthBounds;
2124 				0.0f,						// float			maxDepthBounds;
2125 			};
2126 
2127 			const VkQueue				queue				= m_context.getUniversalQueue();
2128 			Move<VkCommandPool>			cmdPool				= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
2129 			Move<VkCommandBuffer>		cmdBuffer			= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2130 			Move<VkCommandBuffer>		secCmdBuffer;
2131 			VkClearValue				clearColor			= makeClearValueColorU32(0, 0, 0, 0);
2132 			VkClearValue				clearDepthStencil	= makeClearValueDepthStencil(0.0, 0);
2133 
2134 			std::vector<GraphicsPipelineWrapper> pipelines;
2135 			pipelines.reserve(m_data.useDynamicState ? 1u : NUM_TRIANGLES);
2136 
2137 			std::vector<VkDescriptorSet> descriptorSetsRaw;
2138 
2139 			descriptorSetsRaw.reserve(descriptorSets.size());
2140 
2141 			std::transform(begin(descriptorSets), end(descriptorSets), std::back_inserter(descriptorSetsRaw),
2142 				[](const Move<VkDescriptorSet>& elem) { return elem.get(); });
2143 
2144 #ifndef CTS_USES_VULKANSC
2145 			const VkExtent2D srTexelSize { srTexelWidth, srTexelHeight };
2146 			if (m_data.groupParams->useSecondaryCmdBuffer)
2147 			{
2148 				secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2149 
2150 				// record secondary command buffer
2151 				if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2152 				{
2153 					beginSecondaryCmdBuffer(*secCmdBuffer, cbFormat, dsFormat, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
2154 					beginDynamicRender(*secCmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView, *dsImageView,
2155 									   clearColor, clearDepthStencil);
2156 				}
2157 				else
2158 					beginSecondaryCmdBuffer(*secCmdBuffer, cbFormat, dsFormat);
2159 
2160 				drawCommands(*secCmdBuffer, pipelines, viewports, scissors, *pipelineLayout, *renderPass,
2161 							 &vertexInputStateCreateInfo, &dynamicStateCreateInfo, &rasterizationStateCreateInfo,
2162 							 &depthStencilStateParams, &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2163 							 renderingCreateInfoWrapper, *vertShader, *geomShader, *meshShader, *fragShader, descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2164 
2165 				if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2166 					endRendering(vk, *secCmdBuffer);
2167 
2168 				endCommandBuffer(vk, *secCmdBuffer);
2169 
2170 				// record primary command buffer
2171 				beginCommandBuffer(vk, *cmdBuffer, 0u);
2172 
2173 				preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), derivImage.get(), derivNumLevels, srImage.get(), srLayout,
2174 								  srFillBuffer.get(), numSRLayers, srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2175 				if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2176 					beginDynamicRender(*cmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView, *dsImageView,
2177 									   clearColor, clearDepthStencil, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR);
2178 
2179 				vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
2180 
2181 				if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2182 					endRendering(vk, *cmdBuffer);
2183 			}
2184 			else if (m_data.groupParams->useDynamicRendering)
2185 			{
2186 				beginCommandBuffer(vk, *cmdBuffer);
2187 				preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), derivImage.get(), derivNumLevels, srImage.get(), srLayout,
2188 								  srFillBuffer.get(), numSRLayers, srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2189 				beginDynamicRender(*cmdBuffer, *srImageView, srLayout, srTexelSize, *cbImageView, *dsImageView, clearColor, clearDepthStencil);
2190 				drawCommands(*cmdBuffer, pipelines, viewports, scissors, *pipelineLayout, *renderPass,
2191 							 &vertexInputStateCreateInfo, &dynamicStateCreateInfo, &rasterizationStateCreateInfo,
2192 							 &depthStencilStateParams, &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2193 							 renderingCreateInfoWrapper, *vertShader, *geomShader, *meshShader, *fragShader, descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2194 				endRendering(vk, *cmdBuffer);
2195 			}
2196 #endif // CTS_USES_VULKANSC
2197 
2198 			if (!m_data.groupParams->useDynamicRendering)
2199 			{
2200 				beginCommandBuffer(vk, *cmdBuffer);
2201 				preRenderCommands(*cmdBuffer, cbImage.get(), dsImage.get(), derivImage.get(), derivNumLevels, srImage.get(), srLayout,
2202 								  srFillBuffer.get(), numSRLayers, srWidth, srHeight, srFillBpp, clearColor, clearDepthStencil);
2203 				beginLegacyRender(*cmdBuffer, *renderPass, *framebuffer, *srImageView, *cbImageView, *dsImageView, imagelessFB);
2204 				drawCommands(*cmdBuffer, pipelines, viewports, scissors, *pipelineLayout, *renderPass,
2205 							 &vertexInputStateCreateInfo, &dynamicStateCreateInfo, &rasterizationStateCreateInfo,
2206 							 &depthStencilStateParams, &multisampleStateCreateInfo, &shadingRateStateCreateInfo,
2207 							 renderingCreateInfoWrapper, *vertShader, *geomShader, *meshShader, *fragShader, descriptorSetsRaw, **vertexBuffer, pushConstantSize);
2208 				endRenderPass(vk, *cmdBuffer);
2209 			}
2210 
2211 			VkMemoryBarrier memBarrier
2212 			{
2213 				VK_STRUCTURE_TYPE_MEMORY_BARRIER,
2214 				DE_NULL,
2215 				VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
2216 				VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
2217 			};
2218 			vk.cmdPipelineBarrier(*cmdBuffer, allPipelineStages, allPipelineStages, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2219 
2220 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1, &mainDescriptorSet, 0u, DE_NULL);
2221 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
2222 
2223 			// Copy color/depth/stencil buffers to buffer memory
2224 			vk.cmdDispatch(*cmdBuffer, m_data.framebufferDim.width, m_data.framebufferDim.height, m_data.numColorLayers);
2225 
2226 			memBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
2227 			memBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2228 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2229 				0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2230 
2231 			endCommandBuffer(vk, *cmdBuffer);
2232 
2233 			submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2234 
2235 			deUint32 *colorptr = (deUint32 *)colorOutputBuffer->getAllocation().getHostPtr();
2236 			invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
2237 
2238 			invalidateAlloc(vk, device, atomicBuffer->getAllocation());
2239 
2240 			float *depthptr = DE_NULL;
2241 			deUint32 *stencilptr = DE_NULL;
2242 
2243 			if (m_data.useDepthStencil)
2244 			{
2245 				depthptr = (float *)depthOutputBuffer->getAllocation().getHostPtr();
2246 				invalidateAlloc(vk, device, depthOutputBuffer->getAllocation());
2247 
2248 				stencilptr = (deUint32 *)stencilOutputBuffer->getAllocation().getHostPtr();
2249 				invalidateAlloc(vk, device, stencilOutputBuffer->getAllocation());
2250 			}
2251 
2252 			// Loop over all samples and validate the output
2253 			for (deUint32 layer = 0; layer < m_data.numColorLayers && res == QP_TEST_RESULT_PASS; ++layer)
2254 			{
2255 				for (deUint32 y = 0; y < m_data.framebufferDim.height && res == QP_TEST_RESULT_PASS; ++y)
2256 				{
2257 					for (deUint32 x = 0; x < m_data.framebufferDim.width && res == QP_TEST_RESULT_PASS; ++x)
2258 					{
2259 						for (deInt32 s = 0; s < m_data.samples && res == QP_TEST_RESULT_PASS; ++s)
2260 						{
2261 							deUint32 *sample = &colorptr[4*(((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s)];
2262 
2263 							// If testing the rasterizer sample mask, if this sample is not set in the
2264 							// mask then it shouldn't have written anything.
2265 							if (m_data.useApiSampleMask && !(sampleMask & (1 << s)) && sample[2] != 0)
2266 							{
2267 								log << tcu::TestLog::Message << std::hex << "sample written despite pSampleMask (" << x << "," << y << ",sample " << s << ")" << tcu::TestLog::EndMessage;
2268 								res = QP_TEST_RESULT_FAIL;
2269 								continue;
2270 							}
2271 
2272 							// The same isn't covered by any primitives, skip it
2273 							if (sample[2] == 0)
2274 								continue;
2275 
2276 							// skip samples that have the same value as sample zero - it would be redundant to check them.
2277 							if (s > 0)
2278 							{
2279 								deUint32 *sample0 = &colorptr[4*(((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + 0)];
2280 								bool same = deMemCmp(sample, sample0, 16) == 0;
2281 
2282 								if (m_data.fragDepth)
2283 								{
2284 									float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2285 									float *dsample0 = &depthptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + 0];
2286 									same = same && (*dsample == *dsample0);
2287 								}
2288 
2289 								if (m_data.fragStencil)
2290 								{
2291 									deUint32 *ssample = &stencilptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2292 									deUint32 *ssample0 = &stencilptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + 0];
2293 									same = same && (*ssample == *ssample0);
2294 								}
2295 
2296 								if (same)
2297 									continue;
2298 							}
2299 
2300 							// Fragment shader writes error codes to .w component.
2301 							// All nonzero values are unconditionally failures
2302 							if (sample[3] != 0)
2303 							{
2304 								if (sample[3] == ERROR_FRAGCOORD_CENTER)
2305 									log << tcu::TestLog::Message << std::hex << "fragcoord test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2306 								else if (sample[3] == ERROR_VTG_READBACK)
2307 									log << tcu::TestLog::Message << std::hex << "vs/gs output readback test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2308 								else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_DERIV)
2309 									log << tcu::TestLog::Message << std::hex << "fragcoord derivative test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")="
2310 																				"(0x" << ((sample[3] >>  8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F) << "), expected="
2311 																				"(0x" << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F) << ")" << tcu::TestLog::EndMessage;
2312 								else if ((sample[3] & 0xFF) == ERROR_FRAGCOORD_IMPLICIT_DERIV)
2313 									log << tcu::TestLog::Message << std::hex << "implicit derivative test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")="
2314 																				"(0x" << ((sample[3] >>  8) & 0x3F) << ",0x" << ((sample[3] >> 14) & 0x3F) << "), expected="
2315 																				"(0x" << ((sample[3] >> 20) & 0x3F) << ",0x" << ((sample[3] >> 26) & 0x3F) << ")" << tcu::TestLog::EndMessage;
2316 								else
2317 									log << tcu::TestLog::Message << std::hex << "w coord unknown test failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")" << tcu::TestLog::EndMessage;
2318 								res = QP_TEST_RESULT_FAIL;
2319 								continue;
2320 							}
2321 
2322 							// x component of sample
2323 							deUint32 rate = sample[0];
2324 							// fragment size
2325 							deUint32 pixelsX = 1 << ((rate/4)&3);
2326 							deUint32 pixelsY = 1 << (rate&3);
2327 
2328 							// Fragment region
2329 							deUint32 fragMinX = x & ~(pixelsX-1);
2330 							deUint32 fragMinY = y & ~(pixelsY-1);
2331 							deUint32 fragMaxX = fragMinX + pixelsX;
2332 							deUint32 fragMaxY = fragMinY + pixelsY;
2333 
2334 							// Clamp to FB dimension for odd sizes
2335 							if (fragMaxX > m_data.framebufferDim.width)
2336 								fragMaxX = m_data.framebufferDim.width;
2337 							if (fragMaxY > m_data.framebufferDim.height)
2338 								fragMaxY = m_data.framebufferDim.height;
2339 
2340 							// z component of sample
2341 							deUint32 primID = sample[2] >> 24;
2342 							deUint32 atomVal = sample[2] & 0xFFFFFF;
2343 
2344 							// Compute pipeline and primitive rate from primitive ID, and attachment
2345 							// rate from the x/y coordinate
2346 							deInt32 pipelineRate = PrimIDToPipelineShadingRate(primID);
2347 							deInt32 primitiveRate = m_data.shaderWritesRate ? PrimIDToPrimitiveShadingRate(primID) : 0;
2348 
2349 							deInt32 attachmentLayer = (m_data.srLayered && modeIdx == ATTACHMENT_MODE_2DARRAY) ? layer : 0;
2350 							deInt32 attachmentRate = m_data.useAttachment() ? fillPtr[srFillBpp*((attachmentLayer * srHeight + (y / srTexelHeight)) * srWidth + (x / srTexelWidth))] : 0;
2351 
2352 							// Get mask of allowed shading rates
2353 							deInt32 expectedMasks = Simulate(pipelineRate, primitiveRate, attachmentRate);
2354 
2355 							if (!(expectedMasks & (1 << rate)))
2356 							{
2357 								log << tcu::TestLog::Message << std::hex << "unexpected shading rate. failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ") "
2358 																			"result rate 0x" << rate << " mask of expected rates 0x" << expectedMasks <<
2359 																			" pipelineRate=0x" << pipelineRate << " primitiveRate=0x" << primitiveRate << " attachmentRate =0x" << attachmentRate << tcu::TestLog::EndMessage;
2360 								res = QP_TEST_RESULT_FAIL;
2361 								continue;
2362 							}
2363 							// Check that not all fragments are downgraded to 1x1
2364 							if (rate == 0 && expectedMasks != 1)
2365 								numUnexpected1x1Samples++;
2366 							numTotalSamples++;
2367 
2368 							// Check that gl_FragDepth = primID / NUM_TRIANGLES
2369 							if (m_data.fragDepth)
2370 							{
2371 								float *dsample = &depthptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2372 								float expected = (float)primID / NUM_TRIANGLES;
2373 								if (fabs(*dsample - expected) > 0.01)
2374 								{
2375 									log << tcu::TestLog::Message << std::hex << "depth write failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")=" << *dsample << " expected " << expected << tcu::TestLog::EndMessage;
2376 									res = QP_TEST_RESULT_FAIL;
2377 									continue;
2378 								}
2379 							}
2380 
2381 							// Check that stencil value = primID
2382 							if (m_data.fragStencil)
2383 							{
2384 								deUint32 *ssample = &stencilptr[((layer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s];
2385 								if (*ssample != primID)
2386 								{
2387 									log << tcu::TestLog::Message << std::hex << "stencil write failed pixel (0x" << x << ",0x" << y << ",sample 0x" << s << ")=" << *ssample << " expected " << primID << tcu::TestLog::EndMessage;
2388 									res = QP_TEST_RESULT_FAIL;
2389 									continue;
2390 								}
2391 							}
2392 
2393 							// Check that primitives are in the right viewport/scissor
2394 							if (m_data.multiViewport)
2395 							{
2396 								VkRect2D *scissor = &scissors[primID & 1];
2397 								if ((int)x < scissor->offset.x || (int)x >= (int)(scissor->offset.x + scissor->extent.width) ||
2398 									(int)y < scissor->offset.y || (int)y >= (int)(scissor->offset.y + scissor->extent.height))
2399 								{
2400 									log << tcu::TestLog::Message << std::hex << "primitive found outside of expected viewport (0x" << x << ",0x" << y << ",sample 0x" << s << ") primID=" << primID << tcu::TestLog::EndMessage;
2401 									res = QP_TEST_RESULT_FAIL;
2402 									continue;
2403 								}
2404 							}
2405 
2406 							// Check that primitives are in the right layer
2407 							if (m_data.colorLayered)
2408 							{
2409 								if (layer != ((primID & 2)>>1))
2410 								{
2411 									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;
2412 									res = QP_TEST_RESULT_FAIL;
2413 									continue;
2414 								}
2415 							}
2416 
2417 							// Check that multiview broadcasts the same primitive to both layers
2418 							if (m_data.multiView)
2419 							{
2420 								deUint32 otherLayer = layer^1;
2421 								deUint32 *othersample = &colorptr[4*(((otherLayer * m_data.framebufferDim.height + y) * m_data.framebufferDim.width + x)*m_data.samples + s)];
2422 								deUint32 otherPrimID = othersample[2] >> 24;
2423 								if (primID != otherPrimID)
2424 								{
2425 									log << tcu::TestLog::Message << std::hex << "multiview primitive mismatch (0x" << x << ",0x" << y << ",sample 0x" << s << ") primID=" << primID << "  otherPrimID=" << otherPrimID << tcu::TestLog::EndMessage;
2426 									res = QP_TEST_RESULT_FAIL;
2427 									continue;
2428 								}
2429 							}
2430 
2431 							// Loop over all samples in the same fragment
2432 							for (deUint32 fx = fragMinX; fx < fragMaxX; ++fx)
2433 							{
2434 								for (deUint32 fy = fragMinY; fy < fragMaxY; ++fy)
2435 								{
2436 									for (deInt32 fs = 0; fs < m_data.samples; ++fs)
2437 									{
2438 										deUint32 *fsample = &colorptr[4*(((layer * m_data.framebufferDim.height + fy) * m_data.framebufferDim.width + fx)*m_data.samples + fs)];
2439 										deUint32 frate = fsample[0];
2440 										deUint32 fprimID = fsample[2] >> 24;
2441 										deUint32 fatomVal = fsample[2] & 0xFFFFFF;
2442 
2443 										// If we write out the sample mask value, check that the samples in the
2444 										// mask must not be uncovered, and that samples not in the mask must not
2445 										// be covered by this primitive
2446 										if (m_data.useSampleMaskIn)
2447 										{
2448 											int p = pixelsX * pixelsY - ((fx - fragMinX) + pixelsX * (fy - fragMinY)) - 1;
2449 											int sampleIdx = fs + m_data.samples * p;
2450 
2451 											if ((sample[1] & (1 << sampleIdx)) && fsample[2] == 0)
2452 											{
2453 												log << tcu::TestLog::Message << std::hex << "sample set in sampleMask but not written (0x" << fx << ",0x" << fy << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2454 												res = QP_TEST_RESULT_FAIL;
2455 												continue;
2456 											}
2457 											if (!(sample[1] & (1 << sampleIdx)) && fsample[2] != 0 && fprimID == primID)
2458 											{
2459 												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;
2460 												res = QP_TEST_RESULT_FAIL;
2461 												continue;
2462 											}
2463 										}
2464 
2465 										// If conservative raster is enabled, or custom sample locations all at the center, check that
2466 										// samples in the same pixel must be covered.
2467 										if (m_data.conservativeEnable ||
2468 											(m_data.sampleLocations && m_context.getFragmentShadingRateProperties().fragmentShadingRateWithCustomSampleLocations))
2469 										{
2470 											// If it's in the same pixel, expect it to be fully covered.
2471 											if (fx == x && fy == y && fsample[2] == 0)
2472 											{
2473 												log << tcu::TestLog::Message << std::hex << "pixel not fully covered (0x" << fx << ",0x" << fy << ",sample 0x" << fs << ")" << tcu::TestLog::EndMessage;
2474 												res = QP_TEST_RESULT_FAIL;
2475 												continue;
2476 											}
2477 										}
2478 
2479 										if (fsample[2] == 0)
2480 											continue;
2481 
2482 										// If the primitive matches this sample, then it must have the same rate and
2483 										// atomic value
2484 										if (fprimID == primID)
2485 										{
2486 											if (rate != frate || (atomVal != fatomVal && !(m_data.sampleShadingEnable || m_data.sampleShadingInput)))
2487 											{
2488 												log << tcu::TestLog::Message << std::hex << "failed pixel (0x" << x << ",0x" << y << ",sample " << s << ")=0x" << ((primID<<24)|atomVal) <<
2489 																							" compared to (0x" << fx << ",0x" << fy << ",sample " << fs << ")=0x" << ((fprimID<<24)|fatomVal) <<
2490 																							" pipelineRate=0x" << pipelineRate << " primitiveRate=0x" << primitiveRate << " attachmentRate =0x" << attachmentRate <<
2491 																							tcu::TestLog::EndMessage;
2492 												res = QP_TEST_RESULT_FAIL;
2493 											}
2494 										}
2495 									}
2496 								}
2497 							}
2498 						}
2499 					}
2500 				}
2501 			}
2502 			if (res == QP_TEST_RESULT_FAIL)
2503 				break;
2504 		}
2505 	}
2506 	// All samples were coerced to 1x1, unexpected
2507 	if (res == QP_TEST_RESULT_PASS &&
2508 		numTotalSamples != 0 &&
2509 		numUnexpected1x1Samples == numTotalSamples &&
2510 		numTotalSamples > 16)
2511 	{
2512 		log << tcu::TestLog::Message << std::hex << "Quality warning - all fragments used 1x1" << tcu::TestLog::EndMessage;
2513 		res = QP_TEST_RESULT_QUALITY_WARNING;
2514 	}
2515 
2516 	return tcu::TestStatus(res, qpGetTestResultName(res));
2517 }
2518 
2519 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat cbFormat,VkFormat dsFormat,VkRenderingFlagsKHR renderingFlags) const2520 void FSRTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat cbFormat, VkFormat dsFormat, VkRenderingFlagsKHR renderingFlags) const
2521 {
2522 	VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
2523 	{
2524 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
2525 		DE_NULL,																// const void*						pNext;
2526 		renderingFlags,															// VkRenderingFlagsKHR				flags;
2527 		m_data.multiView ? 0x3 : 0u,											// uint32_t							viewMask;
2528 		1u,																		// uint32_t							colorAttachmentCount;
2529 		&cbFormat,																// const VkFormat*					pColorAttachmentFormats;
2530 		dsFormat,																// VkFormat							depthAttachmentFormat;
2531 		dsFormat,																// VkFormat							stencilAttachmentFormat;
2532 		m_data.samples,															// VkSampleCountFlagBits			rasterizationSamples;
2533 	};
2534 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
2535 
2536 	VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2537 	if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2538 		usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
2539 
2540 	const VkCommandBufferBeginInfo commandBufBeginParams
2541 	{
2542 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
2543 		DE_NULL,																// const void*						pNext;
2544 		usageFlags,																// VkCommandBufferUsageFlags		flags;
2545 		&bufferInheritanceInfo
2546 	};
2547 
2548 	const DeviceInterface& vk = m_context.getDeviceInterface();
2549 	VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
2550 }
2551 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkImageView srImageView,VkImageLayout srImageLayout,const VkExtent2D & srTexelSize,VkImageView cbImageView,VkImageView dsImageView,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil,VkRenderingFlagsKHR renderingFlags) const2552 void FSRTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkImageView srImageView, VkImageLayout srImageLayout,
2553 										 const VkExtent2D& srTexelSize, VkImageView cbImageView, VkImageView dsImageView,
2554 										 const VkClearValue& clearColor, const VkClearValue& clearDepthStencil,
2555 										 VkRenderingFlagsKHR renderingFlags) const
2556 {
2557 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2558 	VkRect2D				renderArea	= makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
2559 
2560 	VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo
2561 	{
2562 		VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,	// VkStructureType		sType;
2563 		DE_NULL,																// const void*			pNext;
2564 		m_data.useAttachment() ? srImageView : DE_NULL,							// VkImageView			imageView;
2565 		srImageLayout,															// VkImageLayout		imageLayout;
2566 		srTexelSize																// VkExtent2D			shadingRateAttachmentTexelSize;
2567 	};
2568 
2569 	VkRenderingAttachmentInfoKHR colorAttachment
2570 	{
2571 		vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,					// VkStructureType						sType;
2572 		DE_NULL,																// const void*							pNext;
2573 		cbImageView,															// VkImageView							imageView;
2574 		VK_IMAGE_LAYOUT_GENERAL,												// VkImageLayout						imageLayout;
2575 		VK_RESOLVE_MODE_NONE,													// VkResolveModeFlagBits				resolveMode;
2576 		DE_NULL,																// VkImageView							resolveImageView;
2577 		VK_IMAGE_LAYOUT_UNDEFINED,												// VkImageLayout						resolveImageLayout;
2578 		VK_ATTACHMENT_LOAD_OP_LOAD,												// VkAttachmentLoadOp					loadOp;
2579 		VK_ATTACHMENT_STORE_OP_STORE,											// VkAttachmentStoreOp					storeOp;
2580 		clearColor																// VkClearValue							clearValue;
2581 	};
2582 
2583 	std::vector<VkRenderingAttachmentInfoKHR> depthStencilAttachments(2,
2584 		{
2585 			VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,					// VkStructureType						sType;
2586 			DE_NULL,															// const void*							pNext;
2587 			dsImageView,														// VkImageView							imageView;
2588 			VK_IMAGE_LAYOUT_GENERAL,											// VkImageLayout						imageLayout;
2589 			VK_RESOLVE_MODE_NONE,												// VkResolveModeFlagBits				resolveMode;
2590 			DE_NULL,															// VkImageView							resolveImageView;
2591 			VK_IMAGE_LAYOUT_UNDEFINED,											// VkImageLayout						resolveImageLayout;
2592 			VK_ATTACHMENT_LOAD_OP_LOAD,											// VkAttachmentLoadOp					loadOp;
2593 			VK_ATTACHMENT_STORE_OP_STORE,										// VkAttachmentStoreOp					storeOp;
2594 			clearDepthStencil													// VkClearValue							clearValue;
2595 		});
2596 
2597 	vk::VkRenderingInfoKHR renderingInfo
2598 	{
2599 		vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
2600 		m_data.useAttachment() || m_data.useAttachmentWithoutImageView() ? &shadingRateAttachmentInfo : DE_NULL,
2601 		renderingFlags,															// VkRenderingFlagsKHR					flags;
2602 		renderArea,																// VkRect2D								renderArea;
2603 		m_data.multiView ? 1 : m_data.numColorLayers,							// deUint32								layerCount;
2604 		m_data.multiView ? 0x3 : 0u,											// deUint32								viewMask;
2605 		1u,																		// deUint32								colorAttachmentCount;
2606 		&colorAttachment,														// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
2607 		m_data.useDepthStencil ? &depthStencilAttachments[0] : DE_NULL,			// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
2608 		m_data.useDepthStencil ? &depthStencilAttachments[1] : DE_NULL,			// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
2609 	};
2610 
2611 	vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
2612 }
2613 #endif // CTS_USES_VULKANSC
2614 
preRenderCommands(VkCommandBuffer cmdBuffer,ImageWithMemory * cbImage,ImageWithMemory * dsImage,ImageWithMemory * derivImage,deUint32 derivNumLevels,ImageWithMemory * srImage,VkImageLayout srLayout,BufferWithMemory * srFillBuffer,deUint32 numSRLayers,deUint32 srWidth,deUint32 srHeight,deUint32 srFillBpp,const VkClearValue & clearColor,const VkClearValue & clearDepthStencil)2615 void FSRTestInstance::preRenderCommands(VkCommandBuffer cmdBuffer, ImageWithMemory* cbImage, ImageWithMemory* dsImage,
2616 										ImageWithMemory* derivImage, deUint32 derivNumLevels,
2617 										ImageWithMemory* srImage, VkImageLayout srLayout, BufferWithMemory* srFillBuffer,
2618 										deUint32 numSRLayers, deUint32 srWidth, deUint32 srHeight, deUint32 srFillBpp,
2619 										const VkClearValue& clearColor, const VkClearValue& clearDepthStencil)
2620 {
2621 	const DeviceInterface&	vk						= m_context.getDeviceInterface();
2622 	const VkDevice			device					= m_context.getDevice();
2623 
2624 	VkFlags					allPipelineStages		= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
2625 													  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
2626 													  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
2627 													  VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
2628 													  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
2629 													  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
2630 													  VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2631 
2632 	if (m_data.geometryShader)
2633 		allPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
2634 
2635 	VkImageMemoryBarrier imageBarrier
2636 	{
2637 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		sType
2638 		DE_NULL,									// const void*			pNext
2639 		0u,											// VkAccessFlags		srcAccessMask
2640 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags		dstAccessMask
2641 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout		oldLayout
2642 		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		newLayout
2643 		VK_QUEUE_FAMILY_IGNORED,					// uint32_t				srcQueueFamilyIndex
2644 		VK_QUEUE_FAMILY_IGNORED,					// uint32_t				dstQueueFamilyIndex
2645 		cbImage->get(),								// VkImage				image
2646 		{
2647 			VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
2648 			0u,										// uint32_t				baseMipLevel
2649 			VK_REMAINING_MIP_LEVELS,				// uint32_t				mipLevels,
2650 			0u,										// uint32_t				baseArray
2651 			VK_REMAINING_ARRAY_LAYERS,				// uint32_t				arraySize
2652 		}
2653 	};
2654 
2655 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2656 							(VkDependencyFlags)0,
2657 							0, (const VkMemoryBarrier*)DE_NULL,
2658 							0, (const VkBufferMemoryBarrier*)DE_NULL,
2659 							1, &imageBarrier);
2660 
2661 	imageBarrier.image = derivImage->get();
2662 	imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
2663 
2664 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2665 							(VkDependencyFlags)0,
2666 							0, (const VkMemoryBarrier*)DE_NULL,
2667 							0, (const VkBufferMemoryBarrier*)DE_NULL,
2668 							1, &imageBarrier);
2669 
2670 	// Clear level to 1<<level
2671 	for (deUint32 i = 0; i < derivNumLevels; ++i)
2672 	{
2673 		VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, i, 1u, 0u, 1u);
2674 		VkClearValue clearLevelColor = makeClearValueColorU32(1<<i,0,0,0);
2675 		vk.cmdClearColorImage(cmdBuffer, derivImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearLevelColor.color, 1, &range);
2676 	}
2677 
2678 	// Clear color buffer to transparent black
2679 	{
2680 		VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
2681 		vk.cmdClearColorImage(cmdBuffer, cbImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
2682 	}
2683 
2684 	// Clear depth and stencil
2685 	if (m_data.useDepthStencil)
2686 	{
2687 		VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, VK_REMAINING_ARRAY_LAYERS);
2688 		VkImageMemoryBarrier dsBarrier = imageBarrier;
2689 		dsBarrier.image = dsImage->get();
2690 		dsBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
2691 		dsBarrier.subresourceRange = range;
2692 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2693 								0u, // dependencyFlags
2694 								0u, nullptr,
2695 								0u, nullptr,
2696 								1u, &dsBarrier);
2697 		vk.cmdClearDepthStencilImage(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_GENERAL, &clearDepthStencil.depthStencil, 1, &range);
2698 	}
2699 
2700 	// Initialize shading rate image with varying values
2701 	if (m_data.useAttachment())
2702 	{
2703 		imageBarrier.image = srImage->get();
2704 		imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
2705 
2706 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2707 								(VkDependencyFlags)0,
2708 								0, (const VkMemoryBarrier*)DE_NULL,
2709 								0, (const VkBufferMemoryBarrier*)DE_NULL,
2710 								1, &imageBarrier);
2711 
2712 		deUint8 *fillPtr = (deUint8 *)srFillBuffer->getAllocation().getHostPtr();
2713 		for (deUint32 layer = 0; layer < numSRLayers; ++layer)
2714 		{
2715 			for (deUint32 x = 0; x < srWidth; ++x)
2716 			{
2717 				for (deUint32 y = 0; y < srHeight; ++y)
2718 				{
2719 					deUint32 idx = (layer*srHeight + y)*srWidth + x;
2720 					deUint8 val = (deUint8)SanitizeRate(idx & 0xF);
2721 					// actual shading rate is always in the LSBs of the first byte of a texel
2722 					fillPtr[srFillBpp*idx] = val;
2723 				}
2724 			}
2725 		}
2726 		flushAlloc(vk, device, srFillBuffer->getAllocation());
2727 
2728 		const VkBufferImageCopy copyRegion
2729 		{
2730 			0u,																	// VkDeviceSize			bufferOffset;
2731 			0u,																	// deUint32				bufferRowLength;
2732 			0u,																	// deUint32				bufferImageHeight;
2733 			{
2734 				VK_IMAGE_ASPECT_COLOR_BIT,										// VkImageAspectFlags	aspect;
2735 				0u,																// deUint32				mipLevel;
2736 				0u,																// deUint32				baseArrayLayer;
2737 				numSRLayers,													// deUint32				layerCount;
2738 			},																	// VkImageSubresourceLayers imageSubresource;
2739 			{ 0, 0, 0 },														// VkOffset3D			imageOffset;
2740 			{ srWidth, srHeight, 1 },											// VkExtent3D			imageExtent;
2741 		};
2742 
2743 		vk.cmdCopyBufferToImage(cmdBuffer, srFillBuffer->get(), srImage->get(), VK_IMAGE_LAYOUT_GENERAL, 1, &copyRegion);
2744 
2745 		imageBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
2746 		imageBarrier.newLayout = srLayout;
2747 
2748 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2749 								(VkDependencyFlags)0,
2750 								0, (const VkMemoryBarrier*)DE_NULL,
2751 								0, (const VkBufferMemoryBarrier*)DE_NULL,
2752 								1, &imageBarrier);
2753 	}
2754 
2755 	VkMemoryBarrier memBarrier
2756 	{
2757 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// sType
2758 		DE_NULL,							// pNext
2759 		0u,									// srcAccessMask
2760 		0u,									// dstAccessMask
2761 	};
2762 
2763 	memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
2764 	memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
2765 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, allPipelineStages,
2766 						  0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
2767 }
2768 
beginLegacyRender(VkCommandBuffer cmdBuffer,VkRenderPass renderPass,VkFramebuffer framebuffer,VkImageView srImageView,VkImageView cbImageView,VkImageView dsImageView,bool imagelessFB) const2769 void FSRTestInstance::beginLegacyRender(VkCommandBuffer cmdBuffer, VkRenderPass renderPass, VkFramebuffer framebuffer,
2770 										VkImageView srImageView, VkImageView cbImageView, VkImageView dsImageView, bool imagelessFB) const
2771 {
2772 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2773 	VkRect2D				renderArea	= makeRect2D(m_data.framebufferDim.width, m_data.framebufferDim.height);
2774 
2775 	std::vector<VkImageView> attachments = { cbImageView };
2776 	if (m_data.useAttachment())
2777 		attachments.push_back(srImageView);
2778 	if (m_data.useDepthStencil)
2779 		attachments.push_back(dsImageView);
2780 
2781 	const VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo
2782 	{
2783 		VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO,		// VkStructureType		sType;
2784 		DE_NULL,													// const void*			pNext;
2785 		(deUint32)attachments.size(),								// deUint32				attachmentCount;
2786 		&attachments[0]												// const VkImageView*	pAttachments;
2787 	};
2788 
2789 	beginRenderPass(vk, cmdBuffer, renderPass, framebuffer, renderArea,
2790 					0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, imagelessFB ? &renderPassAttachmentBeginInfo : DE_NULL);
2791 }
2792 
drawCommands(VkCommandBuffer cmdBuffer,std::vector<GraphicsPipelineWrapper> & pipelines,const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineDynamicStateCreateInfo * dynamicState,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,VkPipelineFragmentShadingRateStateCreateInfoKHR * shadingRateState,PipelineRenderingCreateInfoWrapper dynamicRenderingState,const VkShaderModule vertShader,const VkShaderModule geomShader,const VkShaderModule meshShader,const VkShaderModule fragShader,const std::vector<VkDescriptorSet> & descriptorSets,VkBuffer vertexBuffer,const uint32_t pushConstantSize)2793 void FSRTestInstance::drawCommands(VkCommandBuffer									cmdBuffer,
2794 								   std::vector<GraphicsPipelineWrapper>&			pipelines,
2795 								   const std::vector<VkViewport>&					viewports,
2796 								   const std::vector<VkRect2D>&						scissors,
2797 								   const VkPipelineLayout							pipelineLayout,
2798 								   const VkRenderPass								renderPass,
2799 								   const VkPipelineVertexInputStateCreateInfo*		vertexInputState,
2800 								   const VkPipelineDynamicStateCreateInfo*			dynamicState,
2801 								   const VkPipelineRasterizationStateCreateInfo*	rasterizationState,
2802 								   const VkPipelineDepthStencilStateCreateInfo*		depthStencilState,
2803 								   const VkPipelineMultisampleStateCreateInfo*		multisampleState,
2804 								   VkPipelineFragmentShadingRateStateCreateInfoKHR*	shadingRateState,
2805 								   PipelineRenderingCreateInfoWrapper				dynamicRenderingState,
2806 								   const VkShaderModule								vertShader,
2807 								   const VkShaderModule								geomShader,
2808 								   const VkShaderModule								meshShader,
2809 								   const VkShaderModule								fragShader,
2810 								   const std::vector<VkDescriptorSet>&				descriptorSets,
2811 								   VkBuffer											vertexBuffer,
2812 								   const uint32_t									pushConstantSize)
2813 {
2814 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
2815 	const VkDevice			device	= m_context.getDevice();
2816 	const bool				useMesh	= (meshShader != DE_NULL);
2817 
2818 #ifdef CTS_USES_VULKANSC
2819 	if (useMesh)
2820 		DE_ASSERT(false);
2821 #endif // CTS_USES_VULKANSC
2822 
2823 	VkFlags allShaderStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
2824 
2825 	if (useMesh)
2826 	{
2827 #ifndef CTS_USES_VULKANSC
2828 		allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
2829 #endif // CTS_USES_VULKANSC
2830 	}
2831 	else
2832 	{
2833 		allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
2834 		if (m_data.geometryShader)
2835 			allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
2836 	}
2837 
2838 	VkPipelineCreateFlags pipelineCreateFlags = (VkPipelineCreateFlags)0;
2839 
2840 #ifndef CTS_USES_VULKANSC
2841 	if (m_data.groupParams->useDynamicRendering)
2842 		pipelineCreateFlags |= VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2843 #endif // CTS_USES_VULKANSC
2844 
2845 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, static_cast<uint32_t>(descriptorSets.size()), de::dataOrNull(descriptorSets), 0, DE_NULL);
2846 
2847 	PipelineRenderingCreateInfoWrapper		pipelineRenderingCreateInfo = dynamicRenderingState;
2848 #ifndef CTS_USES_VULKANSC
2849 	vk::VkPipelineRenderingCreateInfo		pipelineRenderingCreateInfoWithGarbage;
2850 	std::vector<VkFormat>					garbageFormats;
2851 
2852 	if (m_data.garbageAttachment)
2853 	{
2854 		for (int i = 0; i < 10; i++)
2855 			garbageFormats.push_back(VK_FORMAT_UNDEFINED);
2856 
2857 		pipelineRenderingCreateInfoWithGarbage = *dynamicRenderingState.ptr;
2858 		// Just set a bunch of VK_FORMAT_UNDEFINED for garbage_color_attachment tests to make the validation happy.
2859 		pipelineRenderingCreateInfoWithGarbage.colorAttachmentCount		= static_cast<uint32_t>(garbageFormats.size());
2860 		pipelineRenderingCreateInfoWithGarbage.pColorAttachmentFormats  = garbageFormats.data();
2861 		pipelineRenderingCreateInfo = &pipelineRenderingCreateInfoWithGarbage;
2862 	}
2863 #endif
2864 
2865 	// If using dynamic state, create a single graphics pipeline and bind it
2866 	if (m_data.useDynamicState)
2867 	{
2868 		pipelines.emplace_back(vk, device, m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
2869 		auto& pipeline = pipelines.back();
2870 
2871 		pipeline
2872 			.setDefaultColorBlendState()
2873 			.setDynamicState(dynamicState);
2874 
2875 		if (useMesh)
2876 		{
2877 #ifndef CTS_USES_VULKANSC
2878 			pipeline
2879 				.setupPreRasterizationMeshShaderState(viewports,
2880 													  scissors,
2881 													  pipelineLayout,
2882 													  renderPass,
2883 													  0u,
2884 													  DE_NULL,
2885 													  meshShader,
2886 													  rasterizationState,
2887 													  nullptr,
2888 													  nullptr,
2889 													  shadingRateState,
2890 													  pipelineRenderingCreateInfo);
2891 #endif // CTS_USES_VULKANSC
2892 		}
2893 		else
2894 		{
2895 			pipeline
2896 				.setupVertexInputState(vertexInputState)
2897 				.setupPreRasterizationShaderState(viewports,
2898 												  scissors,
2899 												  pipelineLayout,
2900 												  renderPass,
2901 												  0u,
2902 												  vertShader,
2903 												  rasterizationState,
2904 												  DE_NULL,
2905 												  DE_NULL,
2906 												  geomShader,
2907 												  DE_NULL,
2908 												  shadingRateState,
2909 												  pipelineRenderingCreateInfo);
2910 		}
2911 
2912 		pipeline
2913 			.setupFragmentShaderState(pipelineLayout,
2914 									  renderPass,
2915 									  0u,
2916 									  fragShader,
2917 									  depthStencilState,
2918 									  multisampleState)
2919 			.setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
2920 			.setMonolithicPipelineLayout(pipelineLayout)
2921 			.buildPipeline();
2922 
2923 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
2924 	}
2925 
2926 	// Push constant block (must match shaders).
2927 	struct
2928 	{
2929 		int32_t		shadingRate;
2930 		uint32_t	instanceIndex;
2931 	} pushConstantBlock;
2932 
2933 	for (deInt32 i = 0; i < NUM_TRIANGLES; ++i)
2934 	{
2935 		if (!useMesh)
2936 		{
2937 			// Bind vertex attributes pointing to the next triangle
2938 			VkDeviceSize vertexBufferOffset = i * 3 * 2 * sizeof(float);
2939 			vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
2940 		}
2941 
2942 		// Put primitive shading rate and instance index (used in mesh shading cases) in push constants.
2943 		pushConstantBlock.shadingRate	= PrimIDToPrimitiveShadingRate(i);
2944 		pushConstantBlock.instanceIndex	= static_cast<uint32_t>(i);
2945 		vk.cmdPushConstants(cmdBuffer, pipelineLayout, allShaderStages, 0, pushConstantSize, &pushConstantBlock);
2946 
2947 		if (m_data.useDynamicState)
2948 		{
2949 			VkExtent2D fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
2950 			vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, m_data.combinerOp);
2951 		}
2952 		else
2953 		{
2954 			// Create a new pipeline with the desired pipeline shading rate
2955 			shadingRateState->fragmentSize = ShadingRateEnumToExtent(PrimIDToPipelineShadingRate(i));
2956 
2957 			pipelines.emplace_back(vk, device, m_data.groupParams->pipelineConstructionType, pipelineCreateFlags);
2958 			auto& pipeline = pipelines.back();
2959 
2960 			pipeline
2961 				.setDefaultColorBlendState()
2962 				.setDynamicState(dynamicState);
2963 
2964 			if (useMesh)
2965 			{
2966 #ifndef CTS_USES_VULKANSC
2967 				pipeline
2968 					.setupPreRasterizationMeshShaderState(viewports,
2969 														  scissors,
2970 														  pipelineLayout,
2971 														  renderPass,
2972 														  0u,
2973 														  DE_NULL,
2974 														  meshShader,
2975 														  rasterizationState,
2976 														  nullptr,
2977 														  nullptr,
2978 														  shadingRateState,
2979 														  dynamicRenderingState);
2980 #endif // CTS_USES_VULKANSC
2981 			}
2982 			else
2983 			{
2984 				pipeline
2985 					.setupVertexInputState(vertexInputState)
2986 					.setupPreRasterizationShaderState(viewports,
2987 													  scissors,
2988 													  pipelineLayout,
2989 													  renderPass,
2990 													  0u,
2991 													  vertShader,
2992 													  rasterizationState,
2993 													  DE_NULL,
2994 													  DE_NULL,
2995 													  geomShader,
2996 													  DE_NULL,
2997 													  shadingRateState,
2998 													  dynamicRenderingState);
2999 			}
3000 
3001 			pipeline
3002 				.setupFragmentShaderState(pipelineLayout,
3003 										  renderPass,
3004 										  0u,
3005 										  fragShader,
3006 										  depthStencilState,
3007 										  multisampleState)
3008 #ifndef CTS_USES_VULKANSC
3009 				.setRenderingColorAttachmentsInfo(dynamicRenderingState)
3010 #endif
3011 				.setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
3012 				.setMonolithicPipelineLayout(pipelineLayout)
3013 				.buildPipeline();
3014 
3015 			vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
3016 		}
3017 
3018 		if (useMesh)
3019 		{
3020 #ifndef CTS_USES_VULKANSC
3021 			// Create a single workgroup to draw one triangle. The "primitive id" will be in the push constants.
3022 			vk.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
3023 #endif // CTS_USES_VULKANSC
3024 		}
3025 		else
3026 		{
3027 			// Draw one triangle, with "primitive ID" in gl_InstanceIndex
3028 			vk.cmdDraw(cmdBuffer, 3u, 1, 0u, i);
3029 		}
3030 	}
3031 }
3032 
3033 }	// anonymous
3034 
createBasicTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,SharedGroupParams groupParams)3035 void createBasicTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup, SharedGroupParams groupParams)
3036 {
3037 	typedef struct
3038 	{
3039 		deUint32				count;
3040 		const char*				name;
3041 		const char*				description;
3042 	} TestGroupCase;
3043 
3044 	typedef struct
3045 	{
3046 		VkExtent2D				count;
3047 		const char*				name;
3048 		const char*				description;
3049 	} TestGroupCase2D;
3050 
3051 	typedef struct
3052 	{
3053 		AttachmentUsage			usage;
3054 		const char*				name;
3055 		const char*				description;
3056 	} TestGroupUsageCase;
3057 
3058 	TestGroupCase groupCases[] =
3059 	{
3060 		{ 0,	"basic",					"basic tests"											},
3061 		{ 1,	"apisamplemask",			"use pSampleMask"										},
3062 		{ 2,	"samplemaskin",				"use gl_SampleMaskIn"									},
3063 		{ 3,	"conservativeunder",		"conservative underestimation"							},
3064 		{ 4,	"conservativeover",			"conservative overestimation"							},
3065 		{ 5,	"fragdepth",				"depth shader output"									},
3066 		{ 6,	"fragstencil",				"stencil shader output"									},
3067 		{ 7,	"multiviewport",			"multiple viewports and gl_ViewportIndex"				},
3068 		{ 8,	"colorlayered",				"multiple layer color, single layer shading rate"		},
3069 		{ 9,	"srlayered",				"multiple layer color, multiple layers shading rate"	},
3070 		{ 10,	"multiview",				"multiview"												},
3071 		{ 11,	"multiviewsrlayered",		"multiview and multilayer shading rate"					},
3072 		{ 12,	"multiviewcorrelation",		"multiview with correlation mask"						},
3073 		{ 13,	"interlock",				"fragment shader interlock"								},
3074 		{ 14,	"samplelocations",			"custom sample locations"								},
3075 		{ 15,	"sampleshadingenable",		"enable sample shading in createinfo"					},
3076 		{ 16,	"sampleshadinginput",		"enable sample shading by using gl_SampleID"			},
3077 #ifndef CTS_USES_VULKANSC
3078 		{ 17,	"fragdepth_early_late",		"depth shader output"									},
3079 		{ 18,	"fragstencil_early_late",	"stencil shader output"									},
3080 #endif
3081 	};
3082 
3083 	TestGroupCase dynCases[] =
3084 	{
3085 		{ 1,	"dynamic",	"uses dynamic shading rate state"	},
3086 		{ 0,	"static",	"uses static shading rate state"	},
3087 	};
3088 
3089 	TestGroupUsageCase attCases[] =
3090 	{
3091 		{ AttachmentUsage::NO_ATTACHMENT,						"noattachment",				"no shading rate attachment"					},
3092 		{ AttachmentUsage::WITH_ATTACHMENT,						"attachment",				"has shading rate attachment"					},
3093 		{ AttachmentUsage::NO_ATTACHMENT_PTR,					"noattachmentptr",			"no shading rate attachment pointer"			},
3094 		{ AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW,	"attachment_noimageview",	"has shading rate attachment without imageview"	},
3095 	};
3096 
3097 	TestGroupCase shdCases[] =
3098 	{
3099 		{ 0,	"noshaderrate",	"shader doesn't write rate"	},
3100 		{ 1,	"shaderrate",	"shader writes rate"	},
3101 	};
3102 
3103 	TestGroupCase combCases[] =
3104 	{
3105 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,	"keep",		"keep"	},
3106 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR,	"replace",	"replace"	},
3107 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR,		"min",		"min"	},
3108 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR,		"max",		"max"	},
3109 		{ VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR,		"mul",		"mul"	},
3110 	};
3111 
3112 	TestGroupCase2D extentCases[] =
3113 	{
3114 		{ {1,   1},		"1x1",		"1x1"		},
3115 		{ {4,   4},		"4x4",		"4x4"		},
3116 		{ {33,  35},	"33x35",	"33x35"		},
3117 		{ {151, 431},	"151x431",	"151x431"	},
3118 		{ {256, 256},	"256x256",	"256x256"	},
3119 	};
3120 
3121 	TestGroupCase sampCases[] =
3122 	{
3123 		{ VK_SAMPLE_COUNT_1_BIT,	"samples1",		"1 raster sample"	},
3124 		{ VK_SAMPLE_COUNT_2_BIT,	"samples2",		"2 raster samples"	},
3125 		{ VK_SAMPLE_COUNT_4_BIT,	"samples4",		"4 raster samples"	},
3126 		{ VK_SAMPLE_COUNT_8_BIT,	"samples8",		"8 raster samples"	},
3127 		{ VK_SAMPLE_COUNT_16_BIT,	"samples16",	"16 raster samples"	},
3128 	};
3129 
3130 	TestGroupCase shaderCases[] =
3131 	{
3132 		{ 0,	"vs",	"vertex shader only"			},
3133 		{ 1,	"gs",	"vertex and geometry shader"	},
3134 #ifndef CTS_USES_VULKANSC
3135 		{ 2,	"ms",	"mesh shader"					},
3136 #endif // CTS_USES_VULKANSC
3137 	};
3138 
3139 	deInt32 seed = 0;
3140 
3141 	for (int groupNdx = 0; groupNdx < DE_LENGTH_OF_ARRAY(groupCases); groupNdx++)
3142 	{
3143 		if (groupParams->useDynamicRendering && groupNdx == 12)
3144 			continue;
3145 
3146 		if (groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3147 		{
3148 			// for graphics pipeline library we need to repeat only selected groups
3149 			if (std::set<int> { 2, 3, 4, 10, 11, 12, 13, 14, 15 }.count(groupNdx) == 0)
3150 				continue;
3151 		}
3152 
3153 		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, groupCases[groupNdx].name, groupCases[groupNdx].description));
3154 		for (int dynNdx = 0; dynNdx < DE_LENGTH_OF_ARRAY(dynCases); dynNdx++)
3155 		{
3156 			// reduce number of tests for dynamic rendering cases where secondary command buffer is used
3157 			if (groupParams->useSecondaryCmdBuffer && (dynNdx != 0))
3158 				continue;
3159 
3160 			de::MovePtr<tcu::TestCaseGroup> dynGroup(new tcu::TestCaseGroup(testCtx, dynCases[dynNdx].name, dynCases[dynNdx].description));
3161 			for (int attNdx = 0; attNdx < DE_LENGTH_OF_ARRAY(attCases); attNdx++)
3162 			{
3163 				if (groupParams->useDynamicRendering && attCases[attNdx].usage == AttachmentUsage::NO_ATTACHMENT_PTR)
3164 					continue;
3165 
3166 				// WITH_ATTACHMENT_WITHOUT_IMAGEVIEW is only for VkRenderingFragmentShadingRateAttachmentInfoKHR.
3167 				if (!groupParams->useDynamicRendering && attCases[attNdx].usage == AttachmentUsage::WITH_ATTACHMENT_WITHOUT_IMAGEVIEW)
3168 					continue;
3169 
3170 				de::MovePtr<tcu::TestCaseGroup> attGroup(new tcu::TestCaseGroup(testCtx, attCases[attNdx].name, attCases[attNdx].description));
3171 				for (int shdNdx = 0; shdNdx < DE_LENGTH_OF_ARRAY(shdCases); shdNdx++)
3172 				{
3173 					de::MovePtr<tcu::TestCaseGroup> shdGroup(new tcu::TestCaseGroup(testCtx, shdCases[shdNdx].name, shdCases[shdNdx].description));
3174 					for (int cmb0Ndx = 0; cmb0Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb0Ndx++)
3175 					{
3176 						de::MovePtr<tcu::TestCaseGroup> cmb0Group(new tcu::TestCaseGroup(testCtx, combCases[cmb0Ndx].name, combCases[cmb0Ndx].description));
3177 						for (int cmb1Ndx = 0; cmb1Ndx < DE_LENGTH_OF_ARRAY(combCases); cmb1Ndx++)
3178 						{
3179 							de::MovePtr<tcu::TestCaseGroup> cmb1Group(new tcu::TestCaseGroup(testCtx, combCases[cmb1Ndx].name, combCases[cmb1Ndx].description));
3180 							for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
3181 							{
3182 								// reduce number of cases repeat every other extent case for graphics pipeline library
3183 								if ((groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) && ((extNdx % 2) == 1))
3184 									continue;
3185 
3186 								// reduce number of tests for dynamic rendering cases where secondary command buffer is used
3187 								if (groupParams->useSecondaryCmdBuffer && (extNdx != 1))
3188 									continue;
3189 
3190 								de::MovePtr<tcu::TestCaseGroup> extGroup(new tcu::TestCaseGroup(testCtx, extentCases[extNdx].name, extentCases[extNdx].description));
3191 								for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
3192 								{
3193 									// reduce number of tests for dynamic rendering cases where secondary command buffer is used
3194 									if (groupParams->useSecondaryCmdBuffer && (sampNdx != 1))
3195 										continue;
3196 
3197 									de::MovePtr<tcu::TestCaseGroup> sampGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name, sampCases[sampNdx].description));
3198 									for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderCases); shaderNdx++)
3199 									{
3200 										// reduce number of tests for dynamic rendering cases where secondary command buffer is used
3201 										if (groupParams->useSecondaryCmdBuffer && (shaderNdx != 0))
3202 											continue;
3203 
3204 										bool useApiSampleMask = groupNdx == 1;
3205 										bool useSampleMaskIn = groupNdx == 2;
3206 										bool consRast = groupNdx == 3 || groupNdx == 4;
3207 										bool fragDepth = groupNdx == 5 || groupNdx == 17;
3208 										bool fragStencil = groupNdx == 6 || groupNdx == 18;
3209 										bool multiViewport = groupNdx == 7;
3210 										bool colorLayered = groupNdx == 8 || groupNdx == 9;
3211 										bool srLayered = groupNdx == 9 || groupNdx == 11;
3212 										bool multiView = groupNdx == 10 || groupNdx == 11 || groupNdx == 12;
3213 										bool correlationMask = groupNdx == 12;
3214 										bool interlock = groupNdx == 13;
3215 										bool sampleLocations = groupNdx == 14;
3216 										bool sampleShadingEnable = groupNdx == 15;
3217 										bool sampleShadingInput = groupNdx == 16;
3218 										bool useGeometryShader = (shaderCases[shaderNdx].count == 1u);
3219 										bool useMeshShader = (shaderCases[shaderNdx].count == 2u);
3220 										bool earlyAndLateTest = groupNdx == 17 || groupNdx == 18;
3221 
3222 										VkConservativeRasterizationModeEXT conservativeMode = (groupNdx == 3) ? VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT : VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3223 										deUint32 numColorLayers = (colorLayered || multiView) ? 2u : 1u;
3224 
3225 										// Don't bother with geometry shader if we're not testing shader writes
3226 										if (useGeometryShader && !shdCases[shdNdx].count)
3227 											continue;
3228 
3229 										// reduce number of tests
3230 										if ((groupNdx != 0) &&
3231 											(!dynCases[dynNdx].count ||
3232 											 !(combCases[cmb0Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR || combCases[cmb0Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR) ||
3233 											 !(combCases[cmb1Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR || combCases[cmb1Ndx].count == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR)))
3234 											continue;
3235 
3236 										// Don't bother with geometry shader if we're testing conservative raster, sample mask, depth/stencil
3237 										if (useGeometryShader && (useApiSampleMask || useSampleMaskIn || consRast || fragDepth || fragStencil))
3238 											continue;
3239 
3240 										// Don't bother with geometry shader if we're testing non-dynamic state
3241 										if (useGeometryShader && !dynCases[dynNdx].count)
3242 											continue;
3243 
3244 										// Only test multiViewport/layered with shaderWritesRate
3245 										if ((multiViewport || colorLayered) && !shdCases[shdNdx].count)
3246 											continue;
3247 
3248 										// Can't test layered shading rate attachment without an attachment
3249 										if (srLayered && attCases[attNdx].usage != AttachmentUsage::WITH_ATTACHMENT)
3250 											continue;
3251 
3252 										CaseDef c
3253 										{
3254 											groupParams,											// SharedGroupParams groupParams;
3255 											seed++,													// deInt32 seed;
3256 											extentCases[extNdx].count,								// VkExtent2D framebufferDim;
3257 											(VkSampleCountFlagBits)sampCases[sampNdx].count,		// VkSampleCountFlagBits samples;
3258 											{
3259 												(VkFragmentShadingRateCombinerOpKHR)combCases[cmb0Ndx].count,
3260 												(VkFragmentShadingRateCombinerOpKHR)combCases[cmb1Ndx].count
3261 											},														// VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3262 											attCases[attNdx].usage,									// AttachmentUsage attachmentUsage;
3263 											(bool)shdCases[shdNdx].count,							// bool shaderWritesRate;
3264 											useGeometryShader,										// bool geometryShader;
3265 											useMeshShader,											// bool meshShader;
3266 											(bool)dynCases[dynNdx].count,							// bool useDynamicState;
3267 											useApiSampleMask,										// bool useApiSampleMask;
3268 											useSampleMaskIn,										// bool useSampleMaskIn;
3269 											consRast,												// bool conservativeEnable;
3270 											conservativeMode,										// VkConservativeRasterizationModeEXT conservativeMode;
3271 											fragDepth || fragStencil,								// bool useDepthStencil;
3272 											fragDepth,												// bool fragDepth;
3273 											fragStencil,											// bool fragStencil;
3274 											multiViewport,											// bool multiViewport;
3275 											colorLayered,											// bool colorLayered;
3276 											srLayered,												// bool srLayered;
3277 											numColorLayers,											// deUint32 numColorLayers;
3278 											multiView,												// bool multiView;
3279 											correlationMask,										// bool correlationMask;
3280 											interlock,												// bool interlock;
3281 											sampleLocations,										// bool sampleLocations;
3282 											sampleShadingEnable,									// bool sampleShadingEnable;
3283 											sampleShadingInput,										// bool sampleShadingInput;
3284 											false,													// bool sampleMaskTest;
3285 											earlyAndLateTest,										// bool earlyAndLateTest;
3286 											false,													// bool garbageAttachment;
3287 										};
3288 
3289 										sampGroup->addChild(new FSRTestCase(testCtx, shaderCases[shaderNdx].name, shaderCases[shaderNdx].description, c));
3290 									}
3291 									extGroup->addChild(sampGroup.release());
3292 								}
3293 								cmb1Group->addChild(extGroup.release());
3294 							}
3295 							cmb0Group->addChild(cmb1Group.release());
3296 						}
3297 						shdGroup->addChild(cmb0Group.release());
3298 					}
3299 					attGroup->addChild(shdGroup.release());
3300 				}
3301 				dynGroup->addChild(attGroup.release());
3302 			}
3303 			group->addChild(dynGroup.release());
3304 		}
3305 		parentGroup->addChild(group.release());
3306 	}
3307 
3308 	{
3309 		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "misc_tests", "Single tests that don't need to be part of above test matrix"));
3310 
3311 		if (!groupParams->useSecondaryCmdBuffer)
3312 		{
3313 			group->addChild(new FSRTestCase(testCtx, "sample_mask_test", "", {
3314 				groupParams,											// SharedGroupParams groupParams;
3315 				123,													// deInt32 seed;
3316 				{32,  33},												// VkExtent2D framebufferDim;
3317 				VK_SAMPLE_COUNT_4_BIT,									// VkSampleCountFlagBits samples;
3318 				{
3319 					VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3320 					VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR
3321 				},														// VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3322 				AttachmentUsage::NO_ATTACHMENT,							// AttachmentUsage attachmentUsage;
3323 				true,													// bool shaderWritesRate;
3324 				false,													// bool geometryShader;
3325 				false,													// bool meshShader;
3326 				false,													// bool useDynamicState;
3327 				true,													// bool useApiSampleMask;
3328 				false,													// bool useSampleMaskIn;
3329 				false,													// bool conservativeEnable;
3330 				VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,	// VkConservativeRasterizationModeEXT conservativeMode;
3331 				false,													// bool useDepthStencil;
3332 				false,													// bool fragDepth;
3333 				false,													// bool fragStencil;
3334 				false,													// bool multiViewport;
3335 				false,													// bool colorLayered;
3336 				false,													// bool srLayered;
3337 				1u,														// deUint32 numColorLayers;
3338 				false,													// bool multiView;
3339 				false,													// bool correlationMask;
3340 				false,													// bool interlock;
3341 				false,													// bool sampleLocations;
3342 				false,													// bool sampleShadingEnable;
3343 				false,													// bool sampleShadingInput;
3344 				true,													// bool sampleMaskTest;
3345 				false,													// bool earlyAndLateTest;
3346 				false,													// bool garbageAttachment;
3347 			}));
3348 		}
3349 
3350 #ifndef CTS_USES_VULKANSC
3351 		if (groupParams->useDynamicRendering && groupParams->pipelineConstructionType != vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3352 		{
3353 			group->addChild(new FSRTestCase(testCtx, "garbage_color_attachment", "", {
3354 				groupParams,											// SharedGroupParams groupParams;
3355 				123,													// deInt32 seed;
3356 				{32,  33},												// VkExtent2D framebufferDim;
3357 				VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits samples;
3358 				{
3359 					VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3360 					VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR
3361 				},														// VkFragmentShadingRateCombinerOpKHR combinerOp[2];
3362 				AttachmentUsage::NO_ATTACHMENT,							// AttachmentUsage attachmentUsage;
3363 				false,													// bool shaderWritesRate;
3364 				false,													// bool geometryShader;
3365 				false,													// bool meshShader;
3366 				false,													// bool useDynamicState;
3367 				false,													// bool useApiSampleMask;
3368 				false,													// bool useSampleMaskIn;
3369 				false,													// bool conservativeEnable;
3370 				VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,	// VkConservativeRasterizationModeEXT conservativeMode;
3371 				false,													// bool useDepthStencil;
3372 				false,													// bool fragDepth;
3373 				false,													// bool fragStencil;
3374 				false,													// bool multiViewport;
3375 				false,													// bool colorLayered;
3376 				false,													// bool srLayered;
3377 				1u,														// deUint32 numColorLayers;
3378 				false,													// bool multiView;
3379 				false,													// bool correlationMask;
3380 				false,													// bool interlock;
3381 				false,													// bool sampleLocations;
3382 				false,													// bool sampleShadingEnable;
3383 				false,													// bool sampleShadingInput;
3384 				false,													// bool sampleMaskTest;
3385 				false,													// bool earlyAndLateTest;
3386 				true,													// bool garbageAttachment;
3387 			}));
3388 		}
3389 #endif // CTS_USES_VULKANSC
3390 
3391 		parentGroup->addChild(group.release());
3392 	}
3393 }
3394 
3395 }	// FragmentShadingRage
3396 }	// vkt
3397