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