• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 * Copyright (c) 2020 Valve 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 Extended dynamic state tests
25 *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineExtendedDynamicStateTests.hpp"
28 #include "vktPipelineExtendedDynamicStateMiscTests.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktCustomInstancesDevices.hpp"
32 
33 #include "vkDefs.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkBufferWithMemory.hpp"
38 #include "vkImageWithMemory.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkBarrierUtil.hpp"
43 
44 #include "tcuVector.hpp"
45 #include "tcuMaybe.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuVectorUtil.hpp"
48 #include "tcuStringTemplate.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuCommandLine.hpp"
51 
52 #include "deUniquePtr.hpp"
53 #include "deStringUtil.hpp"
54 
55 #include <vector>
56 #include <sstream>
57 #include <algorithm>
58 #include <utility>
59 #include <iterator>
60 #include <string>
61 #include <limits>
62 #include <memory>
63 #include <functional>
64 #include <cstddef>
65 #include <set>
66 #include <array>
67 
68 namespace vkt
69 {
70 namespace pipeline
71 {
72 
73 namespace
74 {
75 
makeVkBool32(bool value)76 inline vk::VkBool32 makeVkBool32(bool value)
77 {
78 	return (value ? VK_TRUE : VK_FALSE);
79 }
80 
81 #ifndef CTS_USES_VULKANSC
makeProvokingVertexMode(bool lastVertex)82 vk::VkProvokingVertexModeEXT makeProvokingVertexMode (bool lastVertex)
83 {
84 	return (lastVertex ? vk::VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT : vk::VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
85 }
86 #endif // CTS_USES_VULKANSC
87 
88 // Framebuffer size.
89 constexpr deUint32	kFramebufferWidth	= 64u;
90 constexpr deUint32	kFramebufferHeight	= 64u;
91 const auto			kFramebufferExtent	= vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u);
92 
93 // Image formats.
94 constexpr	vk::VkFormat	kUnormColorFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
95 constexpr	vk::VkFormat	kIntColorFormat			= vk::VK_FORMAT_R8G8B8A8_UINT;
96 constexpr	vk::VkFormat	kIntRedColorFormat		= vk::VK_FORMAT_R32_UINT;
97 const		tcu::Vec4		kUnormColorThreshold	(0.005f); // 1/255 < 0.005 < 2/255.
98 
99 // This sample count must be supported for all formats supporting VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT.
100 // See 44.1.1. Supported Sample Counts.
101 const auto kMultiSampleCount	= vk::VK_SAMPLE_COUNT_4_BIT;
102 const auto kSingleSampleCount	= vk::VK_SAMPLE_COUNT_1_BIT;
103 
104 // Image usage flags.
105 const vk::VkImageUsageFlags kColorUsage	= (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
106 const vk::VkImageUsageFlags kDSUsage	= (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
107 
108 // Color components.
109 const auto CR = vk::VK_COLOR_COMPONENT_R_BIT;
110 const auto CG = vk::VK_COLOR_COMPONENT_G_BIT;
111 const auto CB = vk::VK_COLOR_COMPONENT_B_BIT;
112 const auto CA = vk::VK_COLOR_COMPONENT_A_BIT;
113 
componentCodes(vk::VkColorComponentFlags components)114 std::string componentCodes (vk::VkColorComponentFlags components)
115 {
116 	std::string name;
117 
118 	if ((components & CR) != 0u) name += "r";
119 	if ((components & CG) != 0u) name += "g";
120 	if ((components & CB) != 0u) name += "b";
121 	if ((components & CA) != 0u) name += "a";
122 
123 	if (name.empty())
124 		name = "0";
125 	return name;
126 }
127 
128 // Chooses clear or geometry color depending on the selected components.
filterColor(const tcu::Vec4 & clearColor,const tcu::Vec4 & color,vk::VkColorComponentFlags components)129 tcu::Vec4 filterColor (const tcu::Vec4& clearColor, const tcu::Vec4& color, vk::VkColorComponentFlags components)
130 {
131 	const tcu::Vec4 finalColor
132 	(
133 		(((components & CR) != 0u) ? color[0] : clearColor[0]),
134 		(((components & CG) != 0u) ? color[1] : clearColor[1]),
135 		(((components & CB) != 0u) ? color[2] : clearColor[2]),
136 		(((components & CA) != 0u) ? color[3] : clearColor[3])
137 	);
138 	return finalColor;
139 }
140 
141 struct DepthStencilFormat
142 {
143 	vk::VkFormat	imageFormat;
144 	float			depthThreshold;
145 };
146 
147 const DepthStencilFormat kDepthStencilFormats[] =
148 {
149 	{ vk::VK_FORMAT_D32_SFLOAT_S8_UINT,	0.0f		},
150 	{ vk::VK_FORMAT_D24_UNORM_S8_UINT,	1.0e-07f	},	// 1/(2**24-1) < 1.0e-07f < 2/(2**24-1)
151 };
152 
153 using StrideVec = std::vector<vk::VkDeviceSize>;
154 
155 enum class TopologyClass
156 {
157 	POINT,
158 	LINE,
159 	TRIANGLE,
160 	PATCH,
161 	INVALID,
162 };
163 
topologyClassName(TopologyClass tclass)164 std::string topologyClassName (TopologyClass tclass)
165 {
166 	switch (tclass)
167 	{
168 	case TopologyClass::POINT:		return "point";
169 	case TopologyClass::LINE:		return "line";
170 	case TopologyClass::TRIANGLE:	return "triangle";
171 	case TopologyClass::PATCH:		return "patch";
172 	default:
173 		break;
174 	}
175 
176 	DE_ASSERT(false);
177 	return "";
178 }
179 
180 // We will use several data types in vertex bindings. Each type will need to define a few things.
181 class VertexGenerator
182 {
183 public:
184 	// Some generators may need specific features.
checkSupport(Context &) const185 	virtual void													checkSupport (Context&) const {}
186 
187 
188 	// For GLSL.
189 
190 	// Vertex input/output attribute declarations in GLSL form. One sentence per element.
191 	virtual std::vector<std::string>								getAttributeDeclarations()	const = 0;
192 
193 	// Get statements to calculate a vec2 called "vertexCoords" using the vertex input attributes.
194 	virtual std::vector<std::string>								getVertexCoordCalc()		const = 0;
195 
196 	// Get vertex binding declarations as part of descriptor sets, used for mesh shading.
197 	virtual std::vector<std::string>								getDescriptorDeclarations()	const = 0;
198 
199 	// Get statements to calculate a vec2 called "vertexCoords" using descriptor members.
200 	virtual std::vector<std::string>								getDescriptorCoordCalc(TopologyClass topology) const = 0;
201 
202 	// Get fragment input attribute declarations in GLSL form. One sentence per element.
getFragInputAttributes() const203 	virtual std::vector<std::string>								getFragInputAttributes()	const { return std::vector<std::string>(); }
204 
205 	// Get fragment output post-calculations, maybe altering the "color" output variable.
getFragOutputCalc() const206 	virtual std::vector<std::string>								getFragOutputCalc()			const { return std::vector<std::string>(); }
207 
208 	// GLSL extensions if needed.
getGLSLExtensions() const209 	virtual std::vector<std::string>								getGLSLExtensions()			const { return std::vector<std::string>(); }
210 
211 
212 	// For the pipeline.
213 
214 	// Vertex attributes for VkPipelineVertexInputStateCreateInfo.
215 	virtual std::vector<vk::VkVertexInputAttributeDescription>		getAttributeDescriptions() const = 0;
216 
217 	// Vertex attributes for VK_EXT_vertex_input_dynamic_state.
218 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT>	getAttributeDescriptions2()	const = 0;
219 
220 	// Vertex bindings for VkPipelineVertexInputStateCreateInfo.
221 	virtual std::vector<vk::VkVertexInputBindingDescription>		getBindingDescriptions (const StrideVec& strides) const = 0;
222 
223 	// Vertex bindings for VK_EXT_vertex_input_dynamic_state.
224 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT>	getBindingDescriptions2 (const StrideVec& strides) const = 0;
225 
226 	// Create buffer data given an array of coordinates and an initial padding.
227 	virtual std::vector<std::vector<deUint8>>						createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const = 0;
228 
229 	// Stride of vertex data in each binding.
230 	virtual std::vector<vk::VkDeviceSize>							getVertexDataStrides() const = 0;
231 };
232 
233 // Auxiliar function to create these structs more easily.
makeVertexInputAttributeDescription2EXT(deUint32 location,deUint32 binding,vk::VkFormat format,deUint32 offset)234 vk::VkVertexInputAttributeDescription2EXT makeVertexInputAttributeDescription2EXT (deUint32 location, deUint32 binding, vk::VkFormat format, deUint32 offset)
235 {
236 	vk::VkVertexInputAttributeDescription2EXT desc = vk::initVulkanStructure();
237 	desc.location = location;
238 	desc.binding = binding;
239 	desc.format = format;
240 	desc.offset = offset;
241 	return desc;
242 }
243 
makeVertexInputBindingDescription2EXT(deUint32 binding,deUint32 stride,vk::VkVertexInputRate inputRate)244 vk::VkVertexInputBindingDescription2EXT makeVertexInputBindingDescription2EXT (deUint32 binding, deUint32 stride, vk::VkVertexInputRate inputRate)
245 {
246 	vk::VkVertexInputBindingDescription2EXT desc = vk::initVulkanStructure();
247 	desc.binding = binding;
248 	desc.stride = stride;
249 	desc.inputRate = inputRate;
250 	desc.divisor = 1u;
251 	return desc;
252 }
253 
254 // Fill a section of the given buffer (from offset to offset+count) with repeating copies of the given data.
fillWithPattern(void * ptr_,size_t offset,size_t count,const void * src,size_t srcSize)255 void fillWithPattern(void* ptr_, size_t offset, size_t count, const void* src, size_t srcSize)
256 {
257 	auto	ptr		= reinterpret_cast<char*>(ptr_);
258 	size_t	done	= 0u;
259 	size_t	pending	= count;
260 
261 	while (pending > 0u)
262 	{
263 		const size_t stepSize = de::min(srcSize, pending);
264 		deMemcpy(ptr + offset + done, src, stepSize);
265 		done += stepSize;
266 		pending -= stepSize;
267 	}
268 }
269 
270 // Create a single binding vertex data vector given a type T for vertex data.
271 template<class T>
createSingleBindingVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize)272 std::vector<deUint8> createSingleBindingVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize)
273 {
274 	DE_ASSERT(!coords.empty());
275 
276 	const auto dataOffsetSz			= static_cast<size_t>(dataOffset);
277 	const auto trailingPaddingSz	= static_cast<size_t>(trailingPadding);
278 
279 	std::vector<deUint8> buffer;
280 	buffer.resize(dataOffsetSz + coords.size() * sizeof(T) + trailingPaddingSz);
281 
282 	fillWithPattern(buffer.data(), 0u, dataOffsetSz, paddingPattern, patternSize);
283 
284 	auto pos = dataOffsetSz;
285 	for (const auto& coord : coords)
286 	{
287 		new (&buffer[pos]) T(coord);
288 		pos += sizeof(T);
289 	}
290 
291 	fillWithPattern(buffer.data(), pos, trailingPaddingSz, paddingPattern, patternSize);
292 
293 	return buffer;
294 }
295 
296 // Vertices in buffers will have 2 components and a padding to properly test the stride.
297 // This is the vertex type that will be used normally.
298 class VertexWithPadding : public VertexGenerator
299 {
300 protected:
301 	struct VertexData
302 	{
VertexDatavkt::pipeline::__anon5f321d180111::VertexWithPadding::VertexData303 		VertexData(const tcu::Vec2& coords_)
304 			: coords	(coords_)
305 			, padding	(0.0f, 0.0f)
306 		{}
307 
308 		tcu::Vec2 coords;
309 		tcu::Vec2 padding;
310 	};
311 
312 public:
getAttributeDeclarations() const313 	virtual std::vector<std::string> getAttributeDeclarations() const override
314 	{
315 		std::vector<std::string> declarations;
316 		declarations.push_back("layout(location=0) in vec2 position;");
317 		return declarations;
318 	}
319 
getVertexCoordCalc() const320 	virtual std::vector<std::string> getVertexCoordCalc() const override
321 	{
322 		std::vector<std::string> statements;
323 		statements.push_back("vec2 vertexCoords = position;");
324 		return statements;
325 	}
326 
getDescriptorDeclarations() const327 	virtual std::vector<std::string> getDescriptorDeclarations() const override
328 	{
329 		std::vector<std::string> declarations;
330 		declarations.reserve(7u);
331 		declarations.push_back("struct VertexData {");
332 		declarations.push_back("    vec2 position;");
333 		declarations.push_back("    vec2 padding;");
334 		declarations.push_back("};");
335 		declarations.push_back("layout(set=0, binding=0, std430) readonly buffer S0B0Block {");
336 		declarations.push_back("    VertexData data[];");
337 		declarations.push_back("} s0b0buffer;");
338 		return declarations;
339 	}
340 
getDescriptorCoordCalc(TopologyClass topology) const341 	virtual std::vector<std::string> getDescriptorCoordCalc(TopologyClass topology) const override
342 	{
343 		std::vector<std::string> statements;
344 
345 		if (topology == TopologyClass::TRIANGLE)
346 		{
347 			statements.reserve(4u);
348 			statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
349 			statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
350 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
351 			statements.push_back("vec2 vertexCoords = s0b0buffer.data[invIndex].position;");
352 		}
353 		else if (topology == TopologyClass::LINE)
354 		{
355 			statements.reserve(9u);
356 			statements.push_back("const uint linesPerRow = 3u;");
357 			statements.push_back("const uint verticesPerRow = 4u;");
358 			statements.push_back("uint lineIndex = uint(gl_WorkGroupID.x);");
359 			statements.push_back("uint rowIndex = lineIndex / linesPerRow;");
360 			statements.push_back("uint lineInRow = lineIndex % linesPerRow;");
361 			statements.push_back("uint firstVertex = rowIndex * verticesPerRow + lineInRow;");
362 			statements.push_back("uint indices[2] = uint[](firstVertex, firstVertex + 1u);");
363 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
364 			statements.push_back("vec2 vertexCoords = s0b0buffer.data[invIndex].position;");
365 		}
366 		else
367 			DE_ASSERT(false);
368 
369 		return statements;
370 	}
371 
getAttributeDescriptions() const372 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
373 	{
374 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
375 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
376 		return descriptions;
377 	}
378 
379 	// Vertex attributes for VK_EXT_vertex_input_dynamic_state.
getAttributeDescriptions2() const380 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
381 	{
382 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
383 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
384 		return descriptions;
385 	}
386 
387 	// Vertex bindings for VkPipelineVertexInputStateCreateInfo.
getBindingDescriptions(const StrideVec & strides) const388 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
389 	{
390 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
391 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
392 		return descriptions;
393 	}
394 
395 	// Vertex bindings for VK_EXT_vertex_input_dynamic_state.
getBindingDescriptions2(const StrideVec & strides) const396 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
397 	{
398 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
399 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
400 		return descriptions;
401 	}
402 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const403 	virtual std::vector<std::vector<deUint8>> createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const override
404 	{
405 		return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
406 	}
407 
getVertexDataStrides() const408 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
409 	{
410 		return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
411 	}
412 };
413 
414 // Vertices in buffers will have 2 components and a padding. Same as VertexWithPadding but using 16-bit floats.
415 class VertexWithPadding16 : public VertexGenerator
416 {
417 protected:
418 	struct VertexData
419 	{
VertexDatavkt::pipeline::__anon5f321d180111::VertexWithPadding16::VertexData420 		VertexData(const tcu::Vec2& coords_)
421 			: coords	(tcu::Float16(coords_.x()), tcu::Float16(coords_.y()))
422 			, padding	(tcu::Float16(0.0f), tcu::Float16(0.0f))
423 		{}
424 
425 		tcu::F16Vec2 coords;
426 		tcu::F16Vec2 padding;
427 	};
428 
429 public:
checkSupport(Context & context) const430 	virtual void checkSupport (Context& context) const override
431 	{
432 		// We need shaderFloat16 and storageInputOutput16.
433 		const auto& sf16i8Features = context.getShaderFloat16Int8Features();
434 		if (!sf16i8Features.shaderFloat16)
435 			TCU_THROW(NotSupportedError, "shaderFloat16 not supported");
436 
437 		const auto& storage16Features = context.get16BitStorageFeatures();
438 		if (!storage16Features.storageInputOutput16)
439 			TCU_THROW(NotSupportedError, "storageInputOutput16 not supported");
440 	}
441 
getGLSLExtensions() const442 	virtual std::vector<std::string> getGLSLExtensions() const override
443 	{
444 		std::vector<std::string> extensions;
445 		extensions.push_back("#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require");
446 		return extensions;
447 	}
448 
getAttributeDeclarations() const449 	virtual std::vector<std::string> getAttributeDeclarations() const override
450 	{
451 		std::vector<std::string> declarations;
452 		declarations.push_back("layout(location=0) in f16vec2 position;");
453 		return declarations;
454 	}
455 
getVertexCoordCalc() const456 	virtual std::vector<std::string> getVertexCoordCalc() const override
457 	{
458 		std::vector<std::string> statements;
459 		statements.push_back("f16vec2 vertexCoords = position;");
460 		return statements;
461 	}
462 
getDescriptorDeclarations() const463 	virtual std::vector<std::string> getDescriptorDeclarations() const override
464 	{
465 		std::vector<std::string> declarations;
466 		declarations.reserve(7u);
467 		declarations.push_back("struct VertexData {");
468 		declarations.push_back("    f16vec2 position;");
469 		declarations.push_back("    f16vec2 padding;");
470 		declarations.push_back("};");
471 		declarations.push_back("layout(set=0, binding=0, std430) readonly buffer S0B0Block {");
472 		declarations.push_back("    VertexData data[];");
473 		declarations.push_back("} s0b0buffer;");
474 		return declarations;
475 	}
476 
getDescriptorCoordCalc(TopologyClass topology) const477 	virtual std::vector<std::string> getDescriptorCoordCalc(TopologyClass topology) const override
478 	{
479 		std::vector<std::string> statements;
480 
481 		if (topology == TopologyClass::TRIANGLE)
482 		{
483 			statements.reserve(4u);
484 			statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
485 			statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
486 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
487 			statements.push_back("f16vec2 vertexCoords = s0b0buffer.data[invIndex].position;");
488 		}
489 		else if (topology == TopologyClass::LINE)
490 		{
491 			statements.reserve(9u);
492 			statements.push_back("const uint linesPerRow = 3u;");
493 			statements.push_back("const uint verticesPerRow = 4u;");
494 			statements.push_back("uint lineIndex = uint(gl_WorkGroupID.x);");
495 			statements.push_back("uint rowIndex = lineIndex / linesPerRow;");
496 			statements.push_back("uint lineInRow = lineIndex % linesPerRow;");
497 			statements.push_back("uint firstVertex = rowIndex * verticesPerRow + lineInRow;");
498 			statements.push_back("uint indices[2] = uint[](firstVertex, firstVertex + 1u);");
499 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
500 			statements.push_back("f16vec2 vertexCoords = s0b0buffer.data[invIndex].position;");
501 		}
502 		else
503 			DE_ASSERT(false);
504 
505 		return statements;
506 	}
507 
getAttributeDescriptions() const508 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
509 	{
510 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
511 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R16G16_SFLOAT, 0u));
512 		return descriptions;
513 	}
514 
515 	// Vertex attributes for VK_EXT_vertex_input_dynamic_state.
getAttributeDescriptions2() const516 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
517 	{
518 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
519 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R16G16_SFLOAT, 0u));
520 		return descriptions;
521 	}
522 
523 	// Vertex bindings for VkPipelineVertexInputStateCreateInfo.
getBindingDescriptions(const StrideVec & strides) const524 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
525 	{
526 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
527 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
528 		return descriptions;
529 	}
530 
531 	// Vertex bindings for VK_EXT_vertex_input_dynamic_state.
getBindingDescriptions2(const StrideVec & strides) const532 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
533 	{
534 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
535 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
536 		return descriptions;
537 	}
538 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const539 	virtual std::vector<std::vector<deUint8>> createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const override
540 	{
541 		return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
542 	}
543 
getVertexDataStrides() const544 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
545 	{
546 		return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
547 	}
548 };
549 
550 // Two buffers (bindings): one with vertex data, stored contiguously without paddings, and one with instance data. Instance data
551 // will not be stored contiguously: the stride will be twice that of the data size, and the padding space filled with "garbage".
552 // Real instance data will contain a scale and an offset similar to the ones from push constants, and will be used to properly scale
553 // and offset meshes to make them cover the top and bottom halves of the framebuffer.
554 class VertexWithInstanceData : public VertexGenerator
555 {
556 protected:
557 	struct InstanceData
558 	{
InstanceDatavkt::pipeline::__anon5f321d180111::VertexWithInstanceData::InstanceData559 		InstanceData (const tcu::Vec2& scaleAndOffsetY_)
560 			: scaleAndOffsetY	(scaleAndOffsetY_)
561 			, garbage			(0.0f /* bad scale */, 777.0f /* bad offset */)
562 		{}
563 
564 		tcu::Vec2 scaleAndOffsetY;
565 		tcu::Vec2 garbage;
566 	};
567 
568 public:
getAttributeDeclarations() const569 	virtual std::vector<std::string> getAttributeDeclarations() const override
570 	{
571 		std::vector<std::string> declarations;
572 		declarations.push_back("layout(location=0) in vec2 position;");
573 		declarations.push_back("layout(location=1) in vec2 scaleAndOffsetY;");
574 		return declarations;
575 	}
576 
getVertexCoordCalc() const577 	virtual std::vector<std::string> getVertexCoordCalc() const override
578 	{
579 		std::vector<std::string> statements;
580 		statements.push_back("vec2 vertexCoords = vec2(position.x, position.y * scaleAndOffsetY.x + scaleAndOffsetY.y);");
581 		return statements;
582 	}
583 
getDescriptorDeclarations() const584 	virtual std::vector<std::string> getDescriptorDeclarations() const override
585 	{
586 		DE_ASSERT(false); // This vertex generator should not be used with mesh shaders.
587 		return std::vector<std::string>();
588 	}
589 
getDescriptorCoordCalc(TopologyClass) const590 	virtual std::vector<std::string> getDescriptorCoordCalc(TopologyClass) const override
591 	{
592 		DE_ASSERT(false); // This vertex generator should not be used with mesh shaders.
593 		return std::vector<std::string>();
594 	}
595 
getAttributeDescriptions() const596 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
597 	{
598 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
599 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
600 		descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
601 		return descriptions;
602 	}
603 
604 	// Vertex attributes for VK_EXT_vertex_input_dynamic_state.
getAttributeDescriptions2() const605 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
606 	{
607 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
608 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
609 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
610 		return descriptions;
611 	}
612 
613 	// Vertex bindings for VkPipelineVertexInputStateCreateInfo.
getBindingDescriptions(const StrideVec & strides) const614 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
615 	{
616 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
617 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
618 		descriptions.push_back(vk::makeVertexInputBindingDescription(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
619 		return descriptions;
620 	}
621 
622 	// Vertex bindings for VK_EXT_vertex_input_dynamic_state.
getBindingDescriptions2(const StrideVec & strides) const623 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
624 	{
625 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
626 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
627 		descriptions.push_back(makeVertexInputBindingDescription2EXT(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
628 		return descriptions;
629 	}
630 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const631 	virtual std::vector<std::vector<deUint8>> createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const override
632 	{
633 		// Instance data for 2 instances. Scale and offset like we do with push constants.
634 		const std::vector<tcu::Vec2> instanceIds
635 		{
636 			tcu::Vec2(0.5f, -0.5f),
637 			tcu::Vec2(0.5f,  0.5f),
638 		};
639 
640 		std::vector<std::vector<uint8_t>> buffers;
641 		buffers.reserve(2u);
642 		buffers.push_back(createSingleBindingVertexData<tcu::Vec2>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
643 		buffers.push_back(createSingleBindingVertexData<InstanceData>(instanceIds, dataOffset, trailingPadding, paddingPattern, patternSize));
644 
645 		return buffers;
646 	}
647 
getVertexDataStrides() const648 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
649 	{
650 		std::vector<vk::VkDeviceSize> strides;
651 		strides.reserve(2u);
652 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(tcu::Vec2)));
653 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(InstanceData)));
654 		return strides;
655 	}
656 };
657 
658 // Vertex generator used when testing provoking vertices. It has an extra flat vertex output that's also a frag input. Note this
659 // generator only works with 3 vertices.
660 class ProvokingVertexWithPadding : public VertexWithPadding
661 {
662 protected:
663 	bool m_lastVertex;
664 
665 public:
ProvokingVertexWithPadding(bool lastVertex)666 	ProvokingVertexWithPadding (bool lastVertex)
667 		: m_lastVertex (lastVertex)
668 	{}
669 
getAttributeDeclarations() const670 	virtual std::vector<std::string> getAttributeDeclarations() const override
671 	{
672 		auto declarations = VertexWithPadding::getAttributeDeclarations();
673 		declarations.push_back("layout(location=0) flat out uint colorMultiplier;");
674 		return declarations;
675 	}
676 
getDescriptorDeclarations() const677 	virtual std::vector<std::string> getDescriptorDeclarations() const override
678 	{
679 		auto declarations = VertexWithPadding::getDescriptorDeclarations();
680 		declarations.push_back("layout(location=0) flat out uint colorMultiplier[];");
681 		return declarations;
682 	}
683 
getVertexCoordCalc() const684 	virtual std::vector<std::string> getVertexCoordCalc() const override
685 	{
686 		auto statements = VertexWithPadding::getVertexCoordCalc();
687 		statements.push_back("const bool provokingLast = " + std::string(m_lastVertex ? "true" : "false") + ";");
688 		statements.push_back("colorMultiplier = (((!provokingLast && gl_VertexIndex == 0) || (provokingLast && gl_VertexIndex == 2)) ? 1 : 0);");
689 		return statements;
690 	}
691 
getDescriptorCoordCalc(TopologyClass topology) const692 	virtual std::vector<std::string> getDescriptorCoordCalc(TopologyClass topology) const override
693 	{
694 		auto statements = VertexWithPadding::getDescriptorCoordCalc(topology);
695 		statements.push_back("const bool provokingLast = " + std::string(m_lastVertex ? "true" : "false") + ";");
696 		statements.push_back("colorMultiplier[gl_LocalInvocationIndex] = (((!provokingLast && gl_LocalInvocationIndex == 0) || (provokingLast && gl_LocalInvocationIndex == gl_WorkGroupSize.x - 1u)) ? 1 : 0);");
697 		return statements;
698 	}
699 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const700 	virtual std::vector<std::vector<deUint8>> createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const override
701 	{
702 		static constexpr uint32_t kExpectecdCoordCount = 3u;
703 		DE_UNREF(kExpectecdCoordCount); // For release builds.
704 		DE_ASSERT(coords.size() == kExpectecdCoordCount);
705 		return VertexWithPadding::createVertexData(coords, dataOffset, trailingPadding, paddingPattern, patternSize);
706 	}
707 
getFragInputAttributes() const708 	virtual std::vector<std::string> getFragInputAttributes() const override
709 	{
710 		std::vector<std::string> declarations;
711 		declarations.push_back("layout(location=0) flat in uint colorMultiplier;");
712 		return declarations;
713 	}
714 
getFragOutputCalc() const715 	virtual std::vector<std::string> getFragOutputCalc() const override
716 	{
717 		std::vector<std::string> statements;
718 		statements.push_back("color = color * float(colorMultiplier);");
719 		return statements;
720 	}
721 };
722 
723 // Vertices with coordinates, padding and an extra constant field.
724 class VertexWithExtraAttributes : public VertexGenerator
725 {
726 protected:
727 	struct VertexData
728 	{
VertexDatavkt::pipeline::__anon5f321d180111::VertexWithExtraAttributes::VertexData729 		VertexData (const tcu::Vec2& coords_)
730 			: coords	(coords_)
731 			, ones		(1.0f, 1.0f)
732 		{
733 			deMemset(padding, 0, sizeof(padding));
734 		}
735 
736 		tcu::Vec2 coords;
737 		tcu::Vec2 padding[10];
738 		tcu::Vec2 ones;
739 	};
740 
741 public:
getAttributeDeclarations() const742 	virtual std::vector<std::string> getAttributeDeclarations() const override
743 	{
744 		std::vector<std::string> declarations;
745 		declarations.reserve(2u);
746 		declarations.push_back("layout(location=0) in vec2 position;");
747 		declarations.push_back("layout(location=1) in vec2 ones;");
748 		return declarations;
749 	}
750 
getVertexCoordCalc() const751 	virtual std::vector<std::string> getVertexCoordCalc() const override
752 	{
753 		std::vector<std::string> statements;
754 		statements.reserve(2u);
755 		statements.push_back("vec2 vertexCoords = position;");
756 		statements.push_back("vertexCoords = vertexCoords * ones;");
757 		return statements;
758 	}
759 
getDescriptorDeclarations() const760 	virtual std::vector<std::string> getDescriptorDeclarations() const override
761 	{
762 		std::vector<std::string> declarations;
763 		declarations.reserve(8u);
764 		declarations.push_back("struct VertexData {");
765 		declarations.push_back("    vec2 coords;");
766 		declarations.push_back("    vec2 padding[10];");
767 		declarations.push_back("    vec2 ones;");
768 		declarations.push_back("};");
769 		declarations.push_back("layout(set=0, binding=0, std430) readonly buffer S0B0Block {");
770 		declarations.push_back("    VertexData data[];");
771 		declarations.push_back("} s0b0buffer;");
772 		return declarations;
773 	}
774 
getDescriptorCoordCalc(TopologyClass topology) const775 	virtual std::vector<std::string> getDescriptorCoordCalc(TopologyClass topology) const override
776 	{
777 		std::vector<std::string> statements;
778 
779 		if (topology == TopologyClass::TRIANGLE)
780 		{
781 			statements.reserve(6u);
782 			statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
783 			statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
784 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
785 			statements.push_back("vec2 auxPos = s0b0buffer.data[invIndex].coords;");
786 			statements.push_back("vec2 auxOnes = s0b0buffer.data[invIndex].ones;");
787 			statements.push_back("vec2 vertexCoords = auxPos * auxOnes;");
788 		}
789 		else if (topology == TopologyClass::LINE)
790 		{
791 			statements.reserve(11u);
792 			statements.push_back("const uint linesPerRow = 3u;");
793 			statements.push_back("const uint verticesPerRow = 4u;");
794 			statements.push_back("uint lineIndex = uint(gl_WorkGroupID.x);");
795 			statements.push_back("uint rowIndex = lineIndex / linesPerRow;");
796 			statements.push_back("uint lineInRow = lineIndex % linesPerRow;");
797 			statements.push_back("uint firstVertex = rowIndex * verticesPerRow + lineInRow;");
798 			statements.push_back("uint indices[2] = uint[](firstVertex, firstVertex + 1u);");
799 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
800 			statements.push_back("vec2 auxPos = s0b0buffer.data[invIndex].coords;");
801 			statements.push_back("vec2 auxOnes = s0b0buffer.data[invIndex].ones;");
802 			statements.push_back("vec2 vertexCoords = auxPos * auxOnes;");
803 		}
804 		else
805 			DE_ASSERT(false);
806 
807 		return statements;
808 	}
809 
getAttributeDescriptions() const810 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
811 	{
812 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
813 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
814 		descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(VertexData, ones))));
815 		return descriptions;
816 	}
817 
getAttributeDescriptions2() const818 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
819 	{
820 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
821 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
822 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(VertexData, ones))));
823 		return descriptions;
824 	}
825 
getBindingDescriptions(const StrideVec & strides) const826 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
827 	{
828 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
829 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
830 		return descriptions;
831 	}
832 
getBindingDescriptions2(const StrideVec & strides) const833 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
834 	{
835 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
836 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
837 		return descriptions;
838 	}
839 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const840 	virtual std::vector<std::vector<deUint8>> createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const override
841 	{
842 		return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
843 	}
844 
getVertexDataStrides() const845 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
846 	{
847 		return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
848 	}
849 };
850 
851 // Vertices using multiple bindings and constant fields.
852 // Binding 0: no data actually used.
853 // Binding 1: contains location 0, array of PaddingOnes.
854 // Binding 2: no data actually used.
855 // Binding 3: contains location 1, array of CoordsData.
856 // Binding 4: no data actually used.
857 // Binding 5: contains location 2, array of OneZeroPadding.
858 // See getAttributeDeclarations().
859 class MultipleBindingsVertex : public VertexGenerator
860 {
861 protected:
862 	struct CoordsData
863 	{
864 		tcu::Vec2 padding0;
865 		tcu::Vec2 coords;
866 		tcu::Vec2 padding1;
867 
CoordsDatavkt::pipeline::__anon5f321d180111::MultipleBindingsVertex::CoordsData868 		CoordsData (const tcu::Vec2& coords_)
869 			: padding0	(0.0f, 3.0f)
870 			, coords	(coords_)
871 			, padding1	(3.0f, 0.0f)
872 		{}
873 	};
874 
875 	struct PaddingOnes
876 	{
877 		tcu::Vec2 padding[4];
878 		tcu::Vec2 ones;
879 
PaddingOnesvkt::pipeline::__anon5f321d180111::MultipleBindingsVertex::PaddingOnes880 		PaddingOnes (const tcu::Vec2&)
881 			: ones	(1.0f, 1.0f)
882 		{
883 			deMemset(&padding, 0, sizeof(padding));
884 		}
885 	};
886 
887 	struct OneZeroPadding
888 	{
889 		tcu::Vec4 oneZero;
890 		tcu::Vec2 padding[3];
891 
OneZeroPaddingvkt::pipeline::__anon5f321d180111::MultipleBindingsVertex::OneZeroPadding892 		OneZeroPadding (const tcu::Vec2&)
893 			: oneZero	(1.0f, 1.0f, 0.0f, 0.0f)
894 		{
895 			deMemset(&padding, 0, sizeof(padding));
896 		}
897 	};
898 
899 	struct Zeros
900 	{
901 		tcu::Vec2 zeros;
902 
Zerosvkt::pipeline::__anon5f321d180111::MultipleBindingsVertex::Zeros903 		Zeros (const tcu::Vec2&)
904 			: zeros	(0.0f, 0.0f)
905 		{}
906 	};
907 
908 public:
getAttributeDeclarations() const909 	virtual std::vector<std::string> getAttributeDeclarations() const override
910 	{
911 		std::vector<std::string> declarations;
912 		declarations.reserve(3u);
913 
914 		declarations.push_back("layout(location=0) in vec2 ones;");
915 		declarations.push_back("layout(location=1) in vec2 position;");
916 		declarations.push_back("layout(location=2) in vec4 oneZero;");
917 
918 		return declarations;
919 	}
920 
getVertexCoordCalc() const921 	virtual std::vector<std::string> getVertexCoordCalc() const override
922 	{
923 		std::vector<std::string> statements;
924 		statements.reserve(2u);
925 
926 		statements.push_back("vec2 vertexCoords = position;");
927 		statements.push_back("vertexCoords = ((vertexCoords * ones) + oneZero.zw) * oneZero.xy;");
928 
929 		return statements;
930 	}
931 
getDescriptorDeclarations() const932 	virtual std::vector<std::string> getDescriptorDeclarations() const override
933 	{
934 		std::vector<std::string> declarations;
935 		declarations.reserve(23u);
936 
937 		declarations.push_back("struct PaddingOnes {");
938 		declarations.push_back("    vec2 padding[4];");
939 		declarations.push_back("    vec2 ones;");
940 		declarations.push_back("};");
941 		declarations.push_back("struct CoordsData {");
942 		declarations.push_back("    vec2 padding0;");
943 		declarations.push_back("    vec2 coords;");
944 		declarations.push_back("    vec2 padding1;");
945 		declarations.push_back("};");
946 		declarations.push_back("struct OneZeroPadding {");
947 		declarations.push_back("    vec2 ones;");		// Note: we split the vec4 into two vec2s to match CPU-side alignment.
948 		declarations.push_back("    vec2 zeros;");
949 		declarations.push_back("    vec2 padding[3];");
950 		declarations.push_back("};");
951 		declarations.push_back("layout(set=0, binding=1, std430) readonly buffer S0B1Block {");
952 		declarations.push_back("    PaddingOnes data[];");
953 		declarations.push_back("} s0b1buffer;");
954 		declarations.push_back("layout(set=0, binding=3, std430) readonly buffer S0B3Block {");
955 		declarations.push_back("    CoordsData data[];");
956 		declarations.push_back("} s0b3buffer;");
957 		declarations.push_back("layout(set=0, binding=4, std430) readonly buffer S0B5Block {");
958 		declarations.push_back("    OneZeroPadding data[];");
959 		declarations.push_back("} s0b5buffer;");
960 
961 		return declarations;
962 	}
963 
getDescriptorCoordCalc(TopologyClass topology) const964 	virtual std::vector<std::string> getDescriptorCoordCalc(TopologyClass topology) const override
965 	{
966 		std::vector<std::string> statements;
967 
968 		if (topology == TopologyClass::TRIANGLE)
969 		{
970 			statements.reserve(8u);
971 			statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
972 			statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
973 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
974 			statements.push_back("vec2 auxOnes1 = s0b1buffer.data[invIndex].ones;");
975 			statements.push_back("vec2 auxCoords = s0b3buffer.data[invIndex].coords;");
976 			statements.push_back("vec2 auxOnes5 = s0b5buffer.data[invIndex].ones;");
977 			statements.push_back("vec2 auxZeros = s0b5buffer.data[invIndex].zeros;");
978 			statements.push_back("vec2 vertexCoords = ((auxCoords * auxOnes1) + auxZeros) * auxOnes5;");
979 		}
980 		else if (topology == TopologyClass::LINE)
981 		{
982 			statements.reserve(13u);
983 			statements.push_back("const uint linesPerRow = 3u;");
984 			statements.push_back("const uint verticesPerRow = 4u;");
985 			statements.push_back("uint lineIndex = uint(gl_WorkGroupID.x);");
986 			statements.push_back("uint rowIndex = lineIndex / linesPerRow;");
987 			statements.push_back("uint lineInRow = lineIndex % linesPerRow;");
988 			statements.push_back("uint firstVertex = rowIndex * verticesPerRow + lineInRow;");
989 			statements.push_back("uint indices[2] = uint[](firstVertex, firstVertex + 1u);");
990 			statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
991 			statements.push_back("vec2 auxOnes1 = s0b1buffer.data[invIndex].ones;");
992 			statements.push_back("vec2 auxCoords = s0b3buffer.data[invIndex].coords;");
993 			statements.push_back("vec2 auxOnes5 = s0b5buffer.data[invIndex].ones;");
994 			statements.push_back("vec2 auxZeros = s0b5buffer.data[invIndex].zeros;");
995 			statements.push_back("vec2 vertexCoords = ((auxCoords * auxOnes1) + auxZeros) * auxOnes5;");
996 		}
997 		else
998 			DE_ASSERT(false);
999 
1000 		return statements;
1001 	}
1002 
getAttributeDescriptions() const1003 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
1004 	{
1005 		// We create the descriptions vector out of order to make it more interesting. See the attribute declarations.
1006 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
1007 		descriptions.reserve(3u);
1008 
1009 		descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 3u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(CoordsData, coords))));
1010 		descriptions.push_back(vk::makeVertexInputAttributeDescription(2u, 5u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(offsetof(OneZeroPadding, oneZero))));
1011 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(PaddingOnes, ones))));
1012 
1013 		return descriptions;
1014 	}
1015 
getAttributeDescriptions2() const1016 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
1017 	{
1018 		// We create the descriptions vector out of order to make it more interesting. See the attribute declarations.
1019 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
1020 		descriptions.reserve(3u);
1021 
1022 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(2u, 5u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(offsetof(OneZeroPadding, oneZero))));
1023 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 3u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(CoordsData, coords))));
1024 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(PaddingOnes, ones))));
1025 
1026 		return descriptions;
1027 	}
1028 
getBindingDescriptions(const StrideVec & strides) const1029 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
1030 	{
1031 		// Provide descriptions out of order to make it more interesting.
1032 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
1033 		descriptions.reserve(6u);
1034 
1035 		descriptions.push_back(vk::makeVertexInputBindingDescription(2u, static_cast<deUint32>(strides.at(2)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
1036 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
1037 		descriptions.push_back(vk::makeVertexInputBindingDescription(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
1038 		descriptions.push_back(vk::makeVertexInputBindingDescription(4u, static_cast<deUint32>(strides.at(4)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
1039 		descriptions.push_back(vk::makeVertexInputBindingDescription(3u, static_cast<deUint32>(strides.at(3)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
1040 		descriptions.push_back(vk::makeVertexInputBindingDescription(5u, static_cast<deUint32>(strides.at(5)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
1041 
1042 		return descriptions;
1043 	}
1044 
getBindingDescriptions2(const StrideVec & strides) const1045 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
1046 	{
1047 		// Provide descriptions out of order to make it more interesting.
1048 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
1049 		descriptions.reserve(6u);
1050 
1051 		descriptions.push_back(makeVertexInputBindingDescription2EXT(2u, static_cast<deUint32>(strides.at(2)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
1052 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
1053 		descriptions.push_back(makeVertexInputBindingDescription2EXT(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
1054 		descriptions.push_back(makeVertexInputBindingDescription2EXT(5u, static_cast<deUint32>(strides.at(5)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
1055 		descriptions.push_back(makeVertexInputBindingDescription2EXT(4u, static_cast<deUint32>(strides.at(4)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
1056 		descriptions.push_back(makeVertexInputBindingDescription2EXT(3u, static_cast<deUint32>(strides.at(3)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
1057 
1058 		return descriptions;
1059 	}
1060 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const1061 	virtual std::vector<std::vector<deUint8>> createVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize) const override
1062 	{
1063 		std::vector<std::vector<deUint8>> result;
1064 		result.reserve(6u);
1065 
1066 		result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));			// Not actually used.
1067 		result.push_back(createSingleBindingVertexData<PaddingOnes>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));		// Binding 1 contains location=0 as PaddingOnes.
1068 		result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));			// Not actually used.
1069 		result.push_back(createSingleBindingVertexData<CoordsData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));		// Binding 3 contains location=1 as CoordsData.
1070 		result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));			// Not actually used.
1071 		result.push_back(createSingleBindingVertexData<OneZeroPadding>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));	// Binding 5 contains location=2 as OneZeroPadding.
1072 
1073 		return result;
1074 	}
1075 
getVertexDataStrides() const1076 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
1077 	{
1078 		std::vector<vk::VkDeviceSize> strides;
1079 		strides.reserve(6u);
1080 
1081 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
1082 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(PaddingOnes)));
1083 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
1084 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(CoordsData)));
1085 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
1086 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(OneZeroPadding)));
1087 
1088 		return strides;
1089 	}
1090 };
1091 
1092 // Stencil Operation parameters, as used in vkCmdSetStencilOpEXT().
1093 struct StencilOpParams
1094 {
1095 	vk::VkStencilFaceFlags  faceMask;
1096 	vk::VkStencilOp         failOp;
1097 	vk::VkStencilOp         passOp;
1098 	vk::VkStencilOp         depthFailOp;
1099 	vk::VkCompareOp         compareOp;
1100 };
1101 
1102 const StencilOpParams kDefaultStencilOpParams =
1103 {
1104 	vk::VK_STENCIL_FACE_FRONT_AND_BACK,
1105 	vk::VK_STENCIL_OP_KEEP,
1106 	vk::VK_STENCIL_OP_KEEP,
1107 	vk::VK_STENCIL_OP_KEEP,
1108 	vk::VK_COMPARE_OP_ALWAYS
1109 };
1110 
1111 struct DepthBiasParams
1112 {
1113 	float constantFactor;
1114 	float clamp;
1115 };
1116 
isAdvancedBlendOp(const vk::VkBlendOp blendOp)1117 bool isAdvancedBlendOp (const vk::VkBlendOp blendOp)
1118 {
1119 	bool advanced = false;
1120 
1121 	switch (blendOp)
1122 	{
1123 	case vk::VK_BLEND_OP_ZERO_EXT:
1124 	case vk::VK_BLEND_OP_SRC_EXT:
1125 	case vk::VK_BLEND_OP_DST_EXT:
1126 	case vk::VK_BLEND_OP_SRC_OVER_EXT:
1127 	case vk::VK_BLEND_OP_DST_OVER_EXT:
1128 	case vk::VK_BLEND_OP_SRC_IN_EXT:
1129 	case vk::VK_BLEND_OP_DST_IN_EXT:
1130 	case vk::VK_BLEND_OP_SRC_OUT_EXT:
1131 	case vk::VK_BLEND_OP_DST_OUT_EXT:
1132 	case vk::VK_BLEND_OP_SRC_ATOP_EXT:
1133 	case vk::VK_BLEND_OP_DST_ATOP_EXT:
1134 	case vk::VK_BLEND_OP_XOR_EXT:
1135 	case vk::VK_BLEND_OP_MULTIPLY_EXT:
1136 	case vk::VK_BLEND_OP_SCREEN_EXT:
1137 	case vk::VK_BLEND_OP_OVERLAY_EXT:
1138 	case vk::VK_BLEND_OP_DARKEN_EXT:
1139 	case vk::VK_BLEND_OP_LIGHTEN_EXT:
1140 	case vk::VK_BLEND_OP_COLORDODGE_EXT:
1141 	case vk::VK_BLEND_OP_COLORBURN_EXT:
1142 	case vk::VK_BLEND_OP_HARDLIGHT_EXT:
1143 	case vk::VK_BLEND_OP_SOFTLIGHT_EXT:
1144 	case vk::VK_BLEND_OP_DIFFERENCE_EXT:
1145 	case vk::VK_BLEND_OP_EXCLUSION_EXT:
1146 	case vk::VK_BLEND_OP_INVERT_EXT:
1147 	case vk::VK_BLEND_OP_INVERT_RGB_EXT:
1148 	case vk::VK_BLEND_OP_LINEARDODGE_EXT:
1149 	case vk::VK_BLEND_OP_LINEARBURN_EXT:
1150 	case vk::VK_BLEND_OP_VIVIDLIGHT_EXT:
1151 	case vk::VK_BLEND_OP_LINEARLIGHT_EXT:
1152 	case vk::VK_BLEND_OP_PINLIGHT_EXT:
1153 	case vk::VK_BLEND_OP_HARDMIX_EXT:
1154 	case vk::VK_BLEND_OP_HSL_HUE_EXT:
1155 	case vk::VK_BLEND_OP_HSL_SATURATION_EXT:
1156 	case vk::VK_BLEND_OP_HSL_COLOR_EXT:
1157 	case vk::VK_BLEND_OP_HSL_LUMINOSITY_EXT:
1158 	case vk::VK_BLEND_OP_PLUS_EXT:
1159 	case vk::VK_BLEND_OP_PLUS_CLAMPED_EXT:
1160 	case vk::VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT:
1161 	case vk::VK_BLEND_OP_PLUS_DARKER_EXT:
1162 	case vk::VK_BLEND_OP_MINUS_EXT:
1163 	case vk::VK_BLEND_OP_MINUS_CLAMPED_EXT:
1164 	case vk::VK_BLEND_OP_CONTRAST_EXT:
1165 	case vk::VK_BLEND_OP_INVERT_OVG_EXT:
1166 	case vk::VK_BLEND_OP_RED_EXT:
1167 	case vk::VK_BLEND_OP_GREEN_EXT:
1168 	case vk::VK_BLEND_OP_BLUE_EXT:
1169 		advanced = true;
1170 		break;
1171 	default:
1172 		advanced = false;
1173 		break;
1174 	}
1175 
1176 	return advanced;
1177 }
1178 
1179 struct ColorBlendEq
1180 {
1181 	vk::VkBlendFactor	srcColorBlendFactor;
1182 	vk::VkBlendFactor	dstColorBlendFactor;
1183 	vk::VkBlendOp		colorBlendOp;
1184 	vk::VkBlendFactor	srcAlphaBlendFactor;
1185 	vk::VkBlendFactor	dstAlphaBlendFactor;
1186 	vk::VkBlendOp		alphaBlendOp;
1187 
ColorBlendEqvkt::pipeline::__anon5f321d180111::ColorBlendEq1188 	ColorBlendEq ()
1189 		: srcColorBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
1190 		, dstColorBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
1191 		, colorBlendOp			(vk::VK_BLEND_OP_ADD)
1192 		, srcAlphaBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
1193 		, dstAlphaBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
1194 		, alphaBlendOp			(vk::VK_BLEND_OP_ADD)
1195 	{}
1196 
ColorBlendEqvkt::pipeline::__anon5f321d180111::ColorBlendEq1197 	ColorBlendEq (vk::VkBlendFactor	srcColorBlendFactor_,
1198 				  vk::VkBlendFactor	dstColorBlendFactor_,
1199 				  vk::VkBlendOp		colorBlendOp_,
1200 				  vk::VkBlendFactor	srcAlphaBlendFactor_,
1201 				  vk::VkBlendFactor	dstAlphaBlendFactor_,
1202 				  vk::VkBlendOp		alphaBlendOp_)
1203 		: srcColorBlendFactor	(srcColorBlendFactor_)
1204 		, dstColorBlendFactor	(dstColorBlendFactor_)
1205 		, colorBlendOp			(colorBlendOp_)
1206 		, srcAlphaBlendFactor	(srcAlphaBlendFactor_)
1207 		, dstAlphaBlendFactor	(dstAlphaBlendFactor_)
1208 		, alphaBlendOp			(alphaBlendOp_)
1209 	{
1210 		if (isAdvancedBlendOp(colorBlendOp))
1211 			DE_ASSERT(colorBlendOp == alphaBlendOp);
1212 	}
1213 
isAdvancedvkt::pipeline::__anon5f321d180111::ColorBlendEq1214 	bool isAdvanced () const
1215 	{
1216 		return isAdvancedBlendOp(colorBlendOp);
1217 	}
1218 };
1219 
1220 const DepthBiasParams kNoDepthBiasParams = { 0.0f, 0.0f };
1221 
1222 struct LineStippleParams
1223 {
1224 	uint32_t factor;
1225 	uint16_t pattern;
1226 };
1227 
1228 enum class LineRasterizationMode
1229 {
1230 	NONE = 0,
1231 	RECTANGULAR,
1232 	BRESENHAM,
1233 	SMOOTH,
1234 };
1235 
1236 using ViewportVec		= std::vector<vk::VkViewport>;
1237 using ScissorVec		= std::vector<vk::VkRect2D>;
1238 using StencilOpVec		= std::vector<StencilOpParams>;
1239 using SampleMaskVec		= std::vector<vk::VkSampleMask>;
1240 using OptRastStream		= tcu::Maybe<uint32_t>;
1241 using OptBoolean		= tcu::Maybe<bool>;
1242 using OptStippleParams	= tcu::Maybe<LineStippleParams>;
1243 using OptLineRasterMode	= tcu::Maybe<LineRasterizationMode>;
1244 using OptSampleCount	= tcu::Maybe<vk::VkSampleCountFlagBits>;
1245 using CovModTableVec	= std::vector<float>;
1246 using BlendConstArray	= std::array<float, 4>;
1247 using DepthBoundsParams	= std::pair<float, float>;
1248 #ifndef CTS_USES_VULKANSC
1249 using ViewportSwzVec	= std::vector<vk::VkViewportSwizzleNV>;
1250 using OptDepthBiasRepr	= tcu::Maybe<vk::VkDepthBiasRepresentationInfoEXT>;
1251 #endif // CTS_USES_VULKANSC
1252 
1253 // Generic, to be used with any state than can be set statically and, as an option, dynamically.
1254 template<typename T>
1255 struct StaticAndDynamicPair
1256 {
1257 	T				staticValue;
1258 	tcu::Maybe<T>	dynamicValue;
1259 
1260 	// Helper constructor to set a static value and no dynamic value.
StaticAndDynamicPairvkt::pipeline::__anon5f321d180111::StaticAndDynamicPair1261 	StaticAndDynamicPair (const T& value)
1262 		: staticValue	(value)
1263 		, dynamicValue	(tcu::Nothing)
1264 	{
1265 	}
1266 
1267 	// Helper constructor to set both.
StaticAndDynamicPairvkt::pipeline::__anon5f321d180111::StaticAndDynamicPair1268 	StaticAndDynamicPair (const T& sVal, const T& dVal)
1269 		: staticValue	(sVal)
1270 		, dynamicValue	(tcu::just<T>(dVal))
1271 	{
1272 	}
1273 
1274 	// If the dynamic value is present, swap static and dynamic values.
swapValuesvkt::pipeline::__anon5f321d180111::StaticAndDynamicPair1275 	void swapValues (void)
1276 	{
1277 		if (!dynamicValue)
1278 			return;
1279 		std::swap(staticValue, dynamicValue.get());
1280 	}
1281 };
1282 
1283 // For anything boolean, see below.
1284 using BooleanFlagConfig = StaticAndDynamicPair<bool>;
1285 
1286 // Configuration for every aspect of the extended dynamic state.
1287 using CullModeConfig				= StaticAndDynamicPair<vk::VkCullModeFlags>;
1288 using FrontFaceConfig				= StaticAndDynamicPair<vk::VkFrontFace>;
1289 using TopologyConfig				= StaticAndDynamicPair<vk::VkPrimitiveTopology>;
1290 using ViewportConfig				= StaticAndDynamicPair<ViewportVec>;	// At least one element.
1291 using ScissorConfig					= StaticAndDynamicPair<ScissorVec>;		// At least one element.
1292 using StrideConfig					= StaticAndDynamicPair<StrideVec>;		// At least one element.
1293 using DepthTestEnableConfig			= BooleanFlagConfig;
1294 using DepthWriteEnableConfig		= BooleanFlagConfig;
1295 using DepthCompareOpConfig			= StaticAndDynamicPair<vk::VkCompareOp>;
1296 using DepthBoundsTestEnableConfig	= BooleanFlagConfig;
1297 using DepthBoundsConfig				= StaticAndDynamicPair<DepthBoundsParams>;
1298 using StencilTestEnableConfig		= BooleanFlagConfig;
1299 using StencilOpConfig				= StaticAndDynamicPair<StencilOpVec>;	// At least one element.
1300 using VertexGeneratorConfig			= StaticAndDynamicPair<const VertexGenerator*>;
1301 using DepthBiasEnableConfig			= BooleanFlagConfig;
1302 using RastDiscardEnableConfig		= BooleanFlagConfig;
1303 using PrimRestartEnableConfig		= BooleanFlagConfig;
1304 using LogicOpConfig					= StaticAndDynamicPair<vk::VkLogicOp>;
1305 using PatchControlPointsConfig		= StaticAndDynamicPair<deUint8>;
1306 using DepthBiasConfig				= StaticAndDynamicPair<DepthBiasParams>;
1307 using TessDomainOriginConfig		= StaticAndDynamicPair<vk::VkTessellationDomainOrigin>;
1308 using DepthClampEnableConfig		= BooleanFlagConfig;
1309 using PolygonModeConfig				= StaticAndDynamicPair<vk::VkPolygonMode>;
1310 using SampleMaskConfig				= StaticAndDynamicPair<SampleMaskVec>;
1311 using AlphaToCoverageConfig			= BooleanFlagConfig;
1312 using AlphaToOneConfig				= BooleanFlagConfig;
1313 using ColorWriteEnableConfig		= BooleanFlagConfig;
1314 using ColorWriteMaskConfig			= StaticAndDynamicPair<vk::VkColorComponentFlags>;
1315 using RasterizationStreamConfig		= StaticAndDynamicPair<OptRastStream>;
1316 using LogicOpEnableConfig			= BooleanFlagConfig;
1317 using ColorBlendEnableConfig		= BooleanFlagConfig;
1318 using ColorBlendEquationConfig		= StaticAndDynamicPair<ColorBlendEq>;
1319 using BlendConstantsConfig			= StaticAndDynamicPair<BlendConstArray>;
1320 using ProvokingVertexConfig			= StaticAndDynamicPair<OptBoolean>;	// First vertex boolean flag.
1321 using NegativeOneToOneConfig		= StaticAndDynamicPair<OptBoolean>;
1322 using DepthClipEnableConfig			= StaticAndDynamicPair<OptBoolean>;
1323 using LineStippleEnableConfig		= BooleanFlagConfig;
1324 using LineStippleParamsConfig		= StaticAndDynamicPair<OptStippleParams>;
1325 using SampleLocationsEnableConfig	= BooleanFlagConfig;
1326 using ConservativeRasterModeConfig	= StaticAndDynamicPair<vk::VkConservativeRasterizationModeEXT>;
1327 using ExtraPrimitiveOverEstConfig	= StaticAndDynamicPair<float>; // Negative numbers will mean we're not interested in setting it.
1328 using LineRasterModeConfig			= StaticAndDynamicPair<OptLineRasterMode>;
1329 using CoverageToColorEnableConfig	= BooleanFlagConfig;
1330 using CoverageToColorLocationConfig	= StaticAndDynamicPair<uint32_t>;
1331 using RasterizationSamplesConfig	= StaticAndDynamicPair<vk::VkSampleCountFlagBits>;
1332 using LineWidthConfig				= StaticAndDynamicPair<float>;
1333 #ifndef CTS_USES_VULKANSC
1334 using CoverageModulationModeConfig	= StaticAndDynamicPair<vk::VkCoverageModulationModeNV>;
1335 using CoverageModTableEnableConfig	= BooleanFlagConfig;
1336 using CoverageModTableConfig		= StaticAndDynamicPair<CovModTableVec>;
1337 using CoverageReductionModeConfig	= StaticAndDynamicPair<vk::VkCoverageReductionModeNV>;
1338 using ViewportSwizzleConfig			= StaticAndDynamicPair<ViewportSwzVec>;
1339 using ShadingRateImageEnableConfig	= BooleanFlagConfig;
1340 using ViewportWScalingEnableConfig	= BooleanFlagConfig;
1341 using ReprFragTestEnableConfig		= BooleanFlagConfig;
1342 #endif // CTS_USES_VULKANSC
1343 
1344 const tcu::Vec4		kDefaultTriangleColor	(0.0f, 0.0f, 1.0f, 1.0f);	// Opaque blue.
1345 const tcu::Vec4		kDefaultClearColor		(0.0f, 0.0f, 0.0f, 1.0f);	// Opaque black.
1346 const tcu::Vec4		kTransparentColor		(0.0f, 0.0f, 1.0f, 0.0f);	// Transparent version of kDefaultTriangleColor.
1347 const tcu::Vec4		kTransparentClearColor	(0.0f, 0.0f, 0.0f, 0.0f);	// Transparent version of kDefaultClearColor.
1348 const tcu::Vec4		kOpaqueWhite			(1.0f, 1.0f, 1.0f, 1.0f);	// Opaque white, all components active.
1349 
1350 const tcu::UVec4	kLogicOpTriangleColor	(  0u,   0u, 255u, 255u);	// Opaque blue.
1351 const tcu::UVec4	kGreenClearColor		(  0u, 255u,   0u, 255u);	// Opaque green, UINT.
1352 const tcu::UVec4	kLogicOpFinalColor		(  0u, 255u, 255u, 255u);	// Opaque cyan, UINT.
1353 
1354 // Same as kLogicOpTriangleColor. Note: tcu::Vec4 and will be cast to the appropriate type in the shader.
1355 const tcu::Vec4 kLogicOpTriangleColorFl (static_cast<float>(kLogicOpTriangleColor.x()),
1356 										 static_cast<float>(kLogicOpTriangleColor.y()),
1357 										 static_cast<float>(kLogicOpTriangleColor.w()),
1358 										 static_cast<float>(kLogicOpTriangleColor.z()));
1359 
1360 struct MeshParams
1361 {
1362 	tcu::Vec4	color;
1363 	float		depth;
1364 	bool		reversed;
1365 	float		scaleX;
1366 	float		scaleY;
1367 	float		offsetX;
1368 	float		offsetY;
1369 	float		stripScale;
1370 
MeshParamsvkt::pipeline::__anon5f321d180111::MeshParams1371 	MeshParams (const tcu::Vec4&	color_		= kDefaultTriangleColor,
1372 				float				depth_		= 0.0f,
1373 				bool				reversed_	= false,
1374 				float				scaleX_		= 1.0f,
1375 				float				scaleY_		= 1.0f,
1376 				float				offsetX_	= 0.0f,
1377 				float				offsetY_	= 0.0f,
1378 				float				stripScale_	= 0.0f)
1379 		: color			(color_)
1380 		, depth			(depth_)
1381 		, reversed		(reversed_)
1382 		, scaleX		(scaleX_)
1383 		, scaleY		(scaleY_)
1384 		, offsetX		(offsetX_)
1385 		, offsetY		(offsetY_)
1386 		, stripScale	(stripScale_)
1387 	{}
1388 };
1389 
1390 enum class SequenceOrdering
1391 {
1392 	CMD_BUFFER_START	= 0,	// Set state at the start of the command buffer.
1393 	BEFORE_DRAW			= 1,	// After binding dynamic pipeline and just before drawing.
1394 	BETWEEN_PIPELINES	= 2,	// After a static state pipeline has been bound but before the dynamic state pipeline has been bound.
1395 	AFTER_PIPELINES		= 3,	// After a static state pipeline and a second dynamic state pipeline have been bound.
1396 	BEFORE_GOOD_STATIC	= 4,	// Before a static state pipeline with the correct values has been bound.
1397 	TWO_DRAWS_DYNAMIC	= 5,	// Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again.
1398 	TWO_DRAWS_STATIC	= 6,	// Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again.
1399 };
1400 
1401 // This is used when generating some test cases.
1402 enum class ColorBlendSubCase
1403 {
1404 	EQ_ONLY		= 0,	// Only the equation is dynamic.
1405 	ALL_CB		= 1,	// All color blending states are dynamic.
1406 	ALL_BUT_LO	= 2,	// All color blending states are dynamic, except for the ones related to logic op.
1407 };
1408 
1409 class ReferenceColorGenerator
1410 {
1411 public:
1412 	typedef std::unique_ptr<ReferenceColorGenerator> P;
1413 
1414 	virtual void	operator()	(tcu::PixelBufferAccess&)	const = 0;
1415 	virtual P		clone		()							const = 0;
1416 };
1417 
1418 using ColorVerificator = std::function<bool(const tcu::ConstPixelBufferAccess&/*result*/, const tcu::ConstPixelBufferAccess&/*reference*/, const tcu::PixelBufferAccess&/*errorMask*/)>;
1419 
1420 // Most tests expect a single output color in the whole image.
1421 class SingleColorGenerator : public ReferenceColorGenerator
1422 {
1423 public:
SingleColorGenerator(const tcu::Vec4 & color)1424 	SingleColorGenerator (const tcu::Vec4& color)
1425 		: m_colorFloat	(color)
1426 		, m_colorUint	(0u)
1427 		, isUint		(false)
1428 	{}
1429 
SingleColorGenerator(const tcu::UVec4 & color)1430 	SingleColorGenerator (const tcu::UVec4& color)
1431 		: m_colorFloat	(0.0f)
1432 		, m_colorUint	(color)
1433 		, isUint		(true)
1434 	{}
1435 
operator ()(tcu::PixelBufferAccess & access) const1436 	void operator()(tcu::PixelBufferAccess& access) const override
1437 	{
1438 		const auto kWidth	= access.getWidth();
1439 		const auto kHeight	= access.getHeight();
1440 
1441 		for (int y = 0; y < kHeight; ++y)
1442 			for (int x = 0; x < kWidth; ++x)
1443 			{
1444 				if (isUint)
1445 					access.setPixel(m_colorUint, x, y);
1446 				else
1447 					access.setPixel(m_colorFloat, x, y);
1448 			}
1449 	}
1450 
clone() const1451 	P clone() const override
1452 	{
1453 		return P(new SingleColorGenerator(*this));
1454 	}
1455 
1456 private:
1457 	const tcu::Vec4		m_colorFloat;
1458 	const tcu::UVec4	m_colorUint;
1459 	const bool			isUint;
1460 };
1461 
1462 // Some tests expect the upper half and the lower half having different color values.
1463 class HorizontalSplitGenerator : public ReferenceColorGenerator
1464 {
1465 public:
HorizontalSplitGenerator(const tcu::Vec4 & top,const tcu::Vec4 & bottom)1466 	HorizontalSplitGenerator (const tcu::Vec4& top, const tcu::Vec4& bottom)
1467 		: m_top(top), m_bottom(bottom)
1468 	{}
1469 
operator ()(tcu::PixelBufferAccess & access) const1470 	void operator()(tcu::PixelBufferAccess& access) const override
1471 	{
1472 		const auto kWidth		= access.getWidth();
1473 		const auto kHeight		= access.getHeight();
1474 		const auto kHalfHeight	= kHeight / 2;
1475 
1476 		for (int y = 0; y < kHeight; ++y)
1477 			for (int x = 0; x < kWidth; ++x)
1478 			{
1479 				const auto& color = (y < kHalfHeight ? m_top : m_bottom);
1480 				access.setPixel(color, x, y);
1481 			}
1482 	}
1483 
clone() const1484 	P clone() const override
1485 	{
1486 		return P(new HorizontalSplitGenerator(*this));
1487 	}
1488 
1489 private:
1490 	const tcu::Vec4 m_top;
1491 	const tcu::Vec4 m_bottom;
1492 };
1493 
1494 // Primitive restart tests expect the last line to have some missing pixels.
1495 class LastSegmentMissingGenerator : public ReferenceColorGenerator
1496 {
1497 public:
LastSegmentMissingGenerator(const tcu::Vec4 & geomColor,const tcu::Vec4 & clearColor)1498 	LastSegmentMissingGenerator (const tcu::Vec4& geomColor, const tcu::Vec4& clearColor)
1499 		: m_geomColor	(geomColor)
1500 		, m_clearColor	(clearColor)
1501 	{}
1502 
operator ()(tcu::PixelBufferAccess & access) const1503 	void operator()(tcu::PixelBufferAccess& access) const override
1504 	{
1505 		constexpr auto kWidth				= static_cast<int>(kFramebufferWidth);
1506 		constexpr auto kHeight				= static_cast<int>(kFramebufferHeight);
1507 		constexpr auto kLastSegmentStart	= static_cast<int>(kWidth * 0.75f);
1508 
1509 		for (int y = 0; y < kHeight; ++y)
1510 		for (int x = 0; x < kWidth; ++x)
1511 		{
1512 			// The last segment of the last line has the background color.
1513 			const auto& color = ((y == kHeight - 1 && x >= kLastSegmentStart) ? m_clearColor : m_geomColor);
1514 			access.setPixel(color, x, y);
1515 		}
1516 	}
1517 
clone() const1518 	P clone() const override
1519 	{
1520 		return P(new LastSegmentMissingGenerator(*this));
1521 	}
1522 
1523 private:
1524 	const tcu::Vec4 m_geomColor;
1525 	const tcu::Vec4 m_clearColor;
1526 };
1527 
1528 // Some tests (like stippled line tests) expect vertical stripes of a given width.
1529 class VerticalStripesGenerator: public ReferenceColorGenerator
1530 {
1531 public:
VerticalStripesGenerator(const tcu::Vec4 & left,const tcu::Vec4 & right,uint32_t width)1532 	VerticalStripesGenerator (const tcu::Vec4& left, const tcu::Vec4& right, uint32_t width)
1533 		: m_left(left), m_right(right), m_width(width)
1534 	{
1535 		DE_ASSERT(width > 0 && width <= static_cast<uint32_t>(std::numeric_limits<int>::max()));
1536 	}
1537 
operator ()(tcu::PixelBufferAccess & access) const1538 	void operator()(tcu::PixelBufferAccess& access) const override
1539 	{
1540 		constexpr auto kWidth		= static_cast<int>(kFramebufferWidth);
1541 		constexpr auto kHeight		= static_cast<int>(kFramebufferHeight);
1542 
1543 		for (int y = 0; y < kHeight; ++y)
1544 			for (int x = 0; x < kWidth; ++x)
1545 			{
1546 				const int	stripeIdx	= x / static_cast<int>(m_width);
1547 				const auto&	color		= ((stripeIdx % 2 == 0) ? m_left : m_right);
1548 				access.setPixel(color, x, y);
1549 			}
1550 	}
1551 
clone() const1552 	P clone() const override
1553 	{
1554 		return P(new VerticalStripesGenerator(*this));
1555 	}
1556 
1557 private:
1558 	const tcu::Vec4	m_left;
1559 	const tcu::Vec4	m_right;
1560 	const uint32_t	m_width;
1561 };
1562 
1563 // Some tests may expect a center strip in the framebuffer having a different color.
1564 class CenterStripGenerator : public ReferenceColorGenerator
1565 {
1566 public:
CenterStripGenerator(const tcu::Vec4 & sides,const tcu::Vec4 & center)1567 	CenterStripGenerator (const tcu::Vec4& sides, const tcu::Vec4& center)
1568 		: m_sides	(sides)
1569 		, m_center	(center)
1570 		{}
1571 
operator ()(tcu::PixelBufferAccess & access) const1572 	void operator()(tcu::PixelBufferAccess& access) const override
1573 	{
1574 		constexpr auto kWidth		= static_cast<int>(kFramebufferWidth);
1575 		constexpr auto kHeight		= static_cast<int>(kFramebufferHeight);
1576 
1577 		for (int y = 0; y < kHeight; ++y)
1578 			for (int x = 0; x < kWidth; ++x)
1579 			{
1580 				const auto& color = ((x >= kWidth / 4 && x < (kWidth * 3) / 4) ? m_center : m_sides);
1581 				access.setPixel(color, x, y);
1582 			}
1583 	}
1584 
clone() const1585 	P clone() const override
1586 	{
1587 		return P(new CenterStripGenerator(*this));
1588 	}
1589 
1590 private:
1591 	const tcu::Vec4 m_sides;
1592 	const tcu::Vec4 m_center;
1593 };
1594 
1595 // Tests using an off-center triangle may want this generator: fill the image with a solid color but leave the top and left edges in
1596 // a different color.
1597 class TopLeftBorderGenerator : public ReferenceColorGenerator
1598 {
1599 public:
TopLeftBorderGenerator(const tcu::Vec4 & mainColor,const tcu::Vec4 & borderLeft,const tcu::Vec4 & corner,const tcu::Vec4 & borderTop)1600 	TopLeftBorderGenerator (const tcu::Vec4& mainColor, const tcu::Vec4& borderLeft, const tcu::Vec4& corner, const tcu::Vec4& borderTop)
1601 		: m_mainColor	(mainColor)
1602 		, m_borderLeft	(borderLeft)
1603 		, m_corner		(corner)
1604 		, m_borderTop	(borderTop)
1605 	{}
1606 
operator ()(tcu::PixelBufferAccess & access) const1607 	void operator()(tcu::PixelBufferAccess& access) const override
1608 	{
1609 		const auto kWidth		= access.getWidth();
1610 		const auto kHeight		= access.getHeight();
1611 
1612 		for (int y = 0; y < kHeight; ++y)
1613 			for (int x = 0; x < kWidth; ++x)
1614 			{
1615 				tcu::Vec4 color;
1616 
1617 				if (x == 0)
1618 				{
1619 					if (y == 0)
1620 						color = m_corner;
1621 					else
1622 						color = m_borderLeft;
1623 				}
1624 				else if (y == 0)
1625 					color = m_borderTop;
1626 				else
1627 					color = m_mainColor;
1628 
1629 				access.setPixel(color, x, y);
1630 			}
1631 	}
1632 
clone() const1633 	P clone() const override
1634 	{
1635 		return P(new TopLeftBorderGenerator(*this));
1636 	}
1637 
1638 private:
1639 	const tcu::Vec4 m_mainColor;
1640 	const tcu::Vec4 m_borderLeft;
1641 	const tcu::Vec4 m_corner;
1642 	const tcu::Vec4 m_borderTop;
1643 };
1644 
removeAlpha(const tcu::Vec4 & color)1645 tcu::Vec3 removeAlpha (const tcu::Vec4& color)
1646 {
1647 	const tcu::Vec3 rgb (color.x(), color.y(), color.z());
1648 	return rgb;
1649 }
1650 
1651 // Verifies the top left pixel matches exactly.
verifyTopLeftCorner(const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & reference,const tcu::PixelBufferAccess & errorMask,bool partialAlpha)1652 bool verifyTopLeftCorner (const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& reference, const tcu::PixelBufferAccess& errorMask, bool partialAlpha)
1653 {
1654 	// Check corner.
1655 	const auto resultColor		= result.getPixel(0, 0);
1656 	const auto referenceColor	= reference.getPixel(0, 0);
1657 
1658 	const auto resultColorRGB		= removeAlpha(resultColor);
1659 	const auto referenceColorRGB	= removeAlpha(referenceColor);
1660 
1661 	const auto red			= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1662 	const auto green		= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1663 	const auto black		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1664 	const bool alphaMatch	= (partialAlpha ? (resultColor.w() > 0.0f && resultColor.w() < 1.0f) : (resultColor.w() == referenceColor.w()));
1665 	const bool match		= ((resultColorRGB == referenceColorRGB) && alphaMatch);
1666 
1667 	tcu::clear(errorMask, black);
1668 	errorMask.setPixel((match ? green : red), 0, 0);
1669 
1670 	return match;
1671 }
1672 
verifyTopLeftCornerExactly(const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & reference,const tcu::PixelBufferAccess & errorMask)1673 bool verifyTopLeftCornerExactly (const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& reference, const tcu::PixelBufferAccess& errorMask)
1674 {
1675 	return verifyTopLeftCorner(result, reference, errorMask, false/*partialAlpha*/);
1676 }
1677 
verifyTopLeftCornerWithPartialAlpha(const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & reference,const tcu::PixelBufferAccess & errorMask)1678 bool verifyTopLeftCornerWithPartialAlpha (const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& reference, const tcu::PixelBufferAccess& errorMask)
1679 {
1680 	return verifyTopLeftCorner(result, reference, errorMask, true/*partialAlpha*/);
1681 }
1682 
getVertexWithPaddingGenerator()1683 const VertexGenerator* getVertexWithPaddingGenerator ()
1684 {
1685 	static VertexWithPadding vertexWithPadding;
1686 	return &vertexWithPadding;
1687 }
1688 
getVertexWithPadding16Generator()1689 const VertexGenerator* getVertexWithPadding16Generator ()
1690 {
1691 	static VertexWithPadding16 vertexWithPadding16;
1692 	return &vertexWithPadding16;
1693 }
1694 
getVertexWithExtraAttributesGenerator()1695 const VertexGenerator* getVertexWithExtraAttributesGenerator ()
1696 {
1697 	static VertexWithExtraAttributes vertexWithExtraAttributes;
1698 	return &vertexWithExtraAttributes;
1699 }
1700 
getVertexWithMultipleBindingsGenerator()1701 const VertexGenerator* getVertexWithMultipleBindingsGenerator ()
1702 {
1703 	static MultipleBindingsVertex multipleBindingsVertex;
1704 	return &multipleBindingsVertex;
1705 }
1706 
getProvokingVertexWithPaddingGenerator(bool lastVertex)1707 const VertexGenerator* getProvokingVertexWithPaddingGenerator (bool lastVertex)
1708 {
1709 	if (lastVertex)
1710 	{
1711 		static ProvokingVertexWithPadding provokingVertexGeneratorLastVtx (true);
1712 		return &provokingVertexGeneratorLastVtx;
1713 	}
1714 	static ProvokingVertexWithPadding provokingVertexGeneratorFirstVtx (false);
1715 	return &provokingVertexGeneratorFirstVtx;
1716 }
1717 
getVertexWithInstanceDataGenerator()1718 const VertexGenerator* getVertexWithInstanceDataGenerator ()
1719 {
1720 	static VertexWithInstanceData vertexWithInstanceData;
1721 	return &vertexWithInstanceData;
1722 }
1723 
1724 // Create VertexGeneratorConfig varying constructor depending on having none, only the static or both.
makeVertexGeneratorConfig(const VertexGenerator * staticGen,const VertexGenerator * dynamicGen)1725 VertexGeneratorConfig makeVertexGeneratorConfig (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
1726 {
1727 	DE_ASSERT(!(dynamicGen && !staticGen));
1728 	if (dynamicGen)
1729 		return VertexGeneratorConfig(staticGen, dynamicGen);
1730 	if (staticGen)
1731 		return VertexGeneratorConfig(staticGen);
1732 	return VertexGeneratorConfig(getVertexWithPaddingGenerator());	// Only static part with a default option.
1733 }
1734 
1735 // Similar to makeVertexGeneratorConfig, choosing the final value.
chooseVertexGenerator(const VertexGenerator * staticGen,const VertexGenerator * dynamicGen)1736 const VertexGenerator* chooseVertexGenerator (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
1737 {
1738 	DE_ASSERT(!(dynamicGen && !staticGen));
1739 	if (dynamicGen)
1740 		return dynamicGen;
1741 	if (staticGen)
1742 		return staticGen;
1743 	return getVertexWithPaddingGenerator();
1744 }
1745 
1746 #ifndef CTS_USES_VULKANSC
1747 // Is a particular dynamic state incompatible with mesh shading pipelines?
isMeshShadingPipelineIncompatible(vk::VkDynamicState state)1748 bool isMeshShadingPipelineIncompatible (vk::VkDynamicState state)
1749 {
1750 	switch (state)
1751 	{
1752 	case vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT:
1753 	case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT:
1754 	case vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT:
1755 	case vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
1756 	case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
1757 		return true;
1758 	default:
1759 		return false;
1760 	}
1761 
1762 	// Unreachable.
1763 	DE_ASSERT(false);
1764 	return false;
1765 }
1766 
1767 // Is a particular dynamic state compatible with mesh shading pipelines?
isMeshShadingPipelineCompatible(vk::VkDynamicState state)1768 bool isMeshShadingPipelineCompatible (vk::VkDynamicState state)
1769 {
1770 	return !isMeshShadingPipelineIncompatible(state);
1771 }
1772 #endif // CTS_USES_VULKANSC
1773 
getTopologyClass(vk::VkPrimitiveTopology topology)1774 TopologyClass getTopologyClass (vk::VkPrimitiveTopology topology)
1775 {
1776 	switch (topology)
1777 	{
1778 	case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1779 		return TopologyClass::POINT;
1780 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1781 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1782 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1783 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1784 		return TopologyClass::LINE;
1785 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1786 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1787 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1788 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1789 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1790 		return TopologyClass::TRIANGLE;
1791 	case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1792 		return TopologyClass::PATCH;
1793 	default:
1794 		break;
1795 	}
1796 
1797 	DE_ASSERT(false);
1798 	return TopologyClass::INVALID;
1799 }
1800 
selectLineRasterizationMode(const vk::VkPhysicalDeviceLineRasterizationFeaturesEXT & lineRasterFeatures,bool stippleRequired,const tcu::Maybe<LineRasterizationMode> & pref)1801 LineRasterizationMode selectLineRasterizationMode (const vk::VkPhysicalDeviceLineRasterizationFeaturesEXT& lineRasterFeatures, bool stippleRequired, const tcu::Maybe<LineRasterizationMode>& pref)
1802 {
1803 	LineRasterizationMode	selectedMode	= LineRasterizationMode::NONE;
1804 	const bool				hasPref			= static_cast<bool>(pref);
1805 
1806 	if ((!hasPref || pref.get() == LineRasterizationMode::RECTANGULAR) && lineRasterFeatures.rectangularLines && (!stippleRequired || lineRasterFeatures.stippledRectangularLines))
1807 		selectedMode = LineRasterizationMode::RECTANGULAR;
1808 	else if ((!hasPref || pref.get() == LineRasterizationMode::BRESENHAM) && lineRasterFeatures.bresenhamLines && (!stippleRequired || lineRasterFeatures.stippledBresenhamLines))
1809 		selectedMode = LineRasterizationMode::BRESENHAM;
1810 	else if ((!hasPref || pref.get() == LineRasterizationMode::SMOOTH) && lineRasterFeatures.smoothLines && (!stippleRequired || lineRasterFeatures.stippledSmoothLines))
1811 		selectedMode = LineRasterizationMode::SMOOTH;
1812 
1813 	return selectedMode;
1814 }
1815 
makeLineRasterizationMode(LineRasterizationMode mode)1816 vk::VkLineRasterizationModeEXT makeLineRasterizationMode (LineRasterizationMode mode)
1817 {
1818 	vk::VkLineRasterizationModeEXT modeEXT = vk::VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
1819 
1820 	switch (mode)
1821 	{
1822 	case LineRasterizationMode::RECTANGULAR:	modeEXT = vk::VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;			break;
1823 	case LineRasterizationMode::BRESENHAM:		modeEXT = vk::VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;				break;
1824 	case LineRasterizationMode::SMOOTH:			modeEXT = vk::VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;	break;
1825 	default:
1826 		DE_ASSERT(false);
1827 		break;
1828 	}
1829 
1830 	return modeEXT;
1831 }
1832 
1833 struct TestConfig
1834 {
1835 	// Should we use pipeline_library to construct pipeline.
1836 	vk::PipelineConstructionType	pipelineConstructionType;
1837 
1838 	// Main sequence ordering.
1839 	SequenceOrdering				sequenceOrdering;
1840 
1841 	// Drawing parameters: tests will draw one or more flat meshes of triangles covering the whole "screen".
1842 	std::vector<MeshParams>			meshParams;			// Mesh parameters for each full-screen layer of geometry.
1843 	deUint32						referenceStencil;	// Reference stencil value.
1844 
1845 	// Clearing parameters for the framebuffer.
1846 	vk::VkClearValue				clearColorValue;
1847 	float							clearDepthValue;
1848 	deUint32						clearStencilValue;
1849 
1850 	// Expected output in the attachments.
1851 	ReferenceColorGenerator::P		referenceColor;
1852 	float							expectedDepth;
1853 	deUint32						expectedStencil;
1854 
1855 	// Optional verification routine.
1856 	tcu::Maybe<ColorVerificator>	colorVerificator;
1857 
1858 	// Force inclusion of passthrough geometry shader or not.
1859 	bool							forceGeometryShader;
1860 
1861 	// Use mesh shaders instead of classic pipelines.
1862 	bool							useMeshShaders;
1863 
1864 	// Bind an unused mesh shading pipeline before binding the dynamic pipeline.
1865 	// This will only be used in the CMD_BUFFER_START sequence ordering, to minimize the number of cases.
1866 	bool							bindUnusedMeshShadingPipeline;
1867 
1868 	// Force single vertex in the VBO.
1869 	bool							singleVertex;
1870 	deUint32						singleVertexDrawCount;
1871 
1872 	// Force using an oversized triangle as the mesh.
1873 	bool							oversizedTriangle;
1874 
1875 	// Force using a single triangle with a small offset as the mesh.
1876 	bool							offCenterTriangle;
1877 	tcu::Vec2						offCenterProportion; // Relative to pixel size.
1878 
1879 	// Force using a single oblique line: this helps test line rasterization mode.
1880 	bool							obliqueLine;
1881 
1882 	// Offset and extra room after the vertex buffer data.
1883 	vk::VkDeviceSize				vertexDataOffset;
1884 	vk::VkDeviceSize				vertexDataExtraBytes;
1885 
1886 	// Bind and draw with a pipeline that uses dynamic patch control points but doesn't actually use a tessellation
1887 	// shader, before using the real pipelines being tested.
1888 	bool							useExtraDynPCPPipeline;
1889 	// Bind and draw with a pipeline that uses same dynamic states, before using the real pipelines being tested.
1890 	bool							useExtraDynPipeline;
1891 
1892 	// Optional, to be used specifically for color attachments when testing coverage modulation and reduction.
1893 	bool							coverageModulation;
1894 	bool							coverageReduction;
1895 	OptSampleCount					colorSampleCount;
1896 
1897 	// Rasterization stream, if needed, used in the geometry shader.
1898 	OptRastStream					shaderRasterizationStream;
1899 
1900 	// Sample locations, which may be used if testing sample locations.
1901 	tcu::Vec2						sampleLocations;
1902 
1903 	// Optional maximum value for primitiveOverestimationSize so the test works properly.
1904 	tcu::Maybe<float>				maxPrimitiveOverestimationSize;
1905 
1906 	// Number of color attachments in the subpass. Note the fragment shader will only write to the last one.
1907 	uint32_t						colorAttachmentCount;
1908 
1909 	// Instance count.
1910 	uint32_t						instanceCount;
1911 
1912 	// Use viewport swizzle or not.
1913 	bool							viewportSwizzle;
1914 
1915 	// Use shading rate image configuration or not.
1916 	bool							shadingRateImage;
1917 
1918 	// Use viewport W scaling or not.
1919 	bool							viewportWScaling;
1920 
1921 	// Use representative fragment test or not.
1922 	bool							representativeFragmentTest;
1923 
1924 	// Insert extra indices for restarting lines.
1925 	bool							extraLineRestarts;
1926 
1927 	// Consider both the basic and advanced color blend states dynamic if any of them is dynamic.
1928 	bool							colorBlendBoth;
1929 
1930 	// Use color write enable state.
1931 	bool							useColorWriteEnable;
1932 
1933 	// Force UNORM color format.
1934 	bool							forceUnormColorFormat;
1935 
1936 	// Used in some tests to verify color blend pAttachments can be null if all its state is dynamic.
1937 	bool							nullStaticColorBlendAttPtr;
1938 
1939 	// Use dual source blending.
1940 	bool							dualSrcBlend;
1941 
1942 	// Use null pointers when possible for static state.
1943 	bool							favorStaticNullPointers;
1944 
1945 	// Force using atomic counters in the frag shader to count frag shader invocations.
1946 	bool							forceAtomicCounters;
1947 
1948 	// When setting the sample mask dynamically, we can use an alternative sample count specified here.
1949 	OptSampleCount					dynamicSampleMaskCount;
1950 
1951 #ifndef CTS_USES_VULKANSC
1952 	// This structure is optional and can be included statically in the rasterization info or dynamically in vkCmdSetDepthBias2.
1953 	OptDepthBiasRepr				depthBiasReprInfo;
1954 #endif // CTS_USES_VULKANSC
1955 
1956 	tcu::TextureChannelClass		neededDepthChannelClass;
1957 	float							extraDepthThreshold;
1958 
1959 	// Static values for sampleShadingEnable and minSampleShading.
1960 	bool							sampleShadingEnable;
1961 	float							minSampleShading;
1962 
1963 	// Static and dynamic pipeline configuration.
1964 	VertexGeneratorConfig			vertexGenerator;
1965 	CullModeConfig					cullModeConfig;
1966 	FrontFaceConfig					frontFaceConfig;
1967 	TopologyConfig					topologyConfig;
1968 	ViewportConfig					viewportConfig;
1969 	ScissorConfig					scissorConfig;
1970 	StrideConfig					strideConfig;
1971 	DepthTestEnableConfig			depthTestEnableConfig;
1972 	DepthWriteEnableConfig			depthWriteEnableConfig;
1973 	DepthCompareOpConfig			depthCompareOpConfig;
1974 	DepthBoundsTestEnableConfig		depthBoundsTestEnableConfig;
1975 	DepthBoundsConfig				depthBoundsConfig;
1976 	StencilTestEnableConfig			stencilTestEnableConfig;
1977 	StencilOpConfig					stencilOpConfig;
1978 	DepthBiasEnableConfig			depthBiasEnableConfig;
1979 	RastDiscardEnableConfig			rastDiscardEnableConfig;
1980 	PrimRestartEnableConfig			primRestartEnableConfig;
1981 	LogicOpConfig					logicOpConfig;
1982 	PatchControlPointsConfig		patchControlPointsConfig;
1983 	DepthBiasConfig					depthBiasConfig;
1984 	TessDomainOriginConfig			tessDomainOriginConfig;
1985 	DepthClampEnableConfig			depthClampEnableConfig;
1986 	PolygonModeConfig				polygonModeConfig;
1987 	SampleMaskConfig				sampleMaskConfig;
1988 	AlphaToCoverageConfig			alphaToCoverageConfig;
1989 	AlphaToOneConfig				alphaToOneConfig;
1990 	ColorWriteEnableConfig			colorWriteEnableConfig;
1991 	ColorWriteMaskConfig			colorWriteMaskConfig;
1992 	RasterizationStreamConfig		rasterizationStreamConfig;
1993 	LogicOpEnableConfig				logicOpEnableConfig;
1994 	ColorBlendEnableConfig			colorBlendEnableConfig;
1995 	ColorBlendEquationConfig		colorBlendEquationConfig;
1996 	BlendConstantsConfig			blendConstantsConfig;
1997 	ProvokingVertexConfig			provokingVertexConfig;
1998 	NegativeOneToOneConfig			negativeOneToOneConfig;
1999 	DepthClipEnableConfig			depthClipEnableConfig;
2000 	LineStippleEnableConfig			lineStippleEnableConfig;
2001 	LineStippleParamsConfig			lineStippleParamsConfig;
2002 	SampleLocationsEnableConfig		sampleLocationsEnableConfig;
2003 	ConservativeRasterModeConfig	conservativeRasterModeConfig;
2004 	ExtraPrimitiveOverEstConfig		extraPrimitiveOverEstConfig;
2005 	LineRasterModeConfig			lineRasterModeConfig;
2006 	CoverageToColorEnableConfig		coverageToColorEnableConfig;
2007 	CoverageToColorLocationConfig	coverageToColorLocationConfig;
2008 	RasterizationSamplesConfig		rasterizationSamplesConfig;
2009 	LineWidthConfig					lineWidthConfig;
2010 #ifndef CTS_USES_VULKANSC
2011 	CoverageModulationModeConfig	coverageModulationModeConfig;
2012 	CoverageModTableEnableConfig	coverageModTableEnableConfig;
2013 	CoverageModTableConfig			coverageModTableConfig;
2014 	CoverageReductionModeConfig		coverageReductionModeConfig;
2015 	ViewportSwizzleConfig			viewportSwizzleConfig;
2016 	ShadingRateImageEnableConfig	shadingRateImageEnableConfig;
2017 	ViewportWScalingEnableConfig	viewportWScalingEnableConfig;
2018 	ReprFragTestEnableConfig		reprFragTestEnableConfig;
2019 #endif // CTS_USES_VULKANSC
2020 
2021 	// Sane defaults.
TestConfigvkt::pipeline::__anon5f321d180111::TestConfig2022 	TestConfig (vk::PipelineConstructionType pipelineType, SequenceOrdering ordering, bool useMeshShaders_, const VertexGenerator* staticVertexGenerator = nullptr, const VertexGenerator* dynamicVertexGenerator = nullptr)
2023 		: pipelineConstructionType		(pipelineType)
2024 		, sequenceOrdering				(ordering)
2025 		, meshParams					(1u, MeshParams())
2026 		, referenceStencil				(0u)
2027 		, clearColorValue				(vk::makeClearValueColor(kDefaultClearColor))
2028 		, clearDepthValue				(1.0f)
2029 		, clearStencilValue				(0u)
2030 		, referenceColor				(new SingleColorGenerator(kDefaultTriangleColor))
2031 		, expectedDepth					(1.0f)
2032 		, expectedStencil				(0u)
2033 		, colorVerificator				(tcu::Nothing)
2034 		, forceGeometryShader			(false)
2035 		, useMeshShaders				(useMeshShaders_)
2036 		, bindUnusedMeshShadingPipeline	(false)
2037 		, singleVertex					(false)
2038 		, singleVertexDrawCount			(0)
2039 		, oversizedTriangle				(false)
2040 		, offCenterTriangle				(false)
2041 		, offCenterProportion			(0.0f, 0.0f)
2042 		, obliqueLine					(false)
2043 		, vertexDataOffset				(0ull)
2044 		, vertexDataExtraBytes			(0ull)
2045 		, useExtraDynPCPPipeline		(false)
2046 		, useExtraDynPipeline			(false)
2047 		, coverageModulation			(false)
2048 		, coverageReduction				(false)
2049 		, colorSampleCount				(tcu::Nothing)
2050 		, shaderRasterizationStream		(tcu::Nothing)
2051 		, sampleLocations				(0.5f, 0.5f)
2052 		, colorAttachmentCount			(1u)
2053 		, instanceCount					(1u)
2054 		, viewportSwizzle				(false)
2055 		, shadingRateImage				(false)
2056 		, viewportWScaling				(false)
2057 		, representativeFragmentTest	(false)
2058 		, extraLineRestarts				(false)
2059 		, colorBlendBoth				(false)
2060 		, useColorWriteEnable			(false)
2061 		, forceUnormColorFormat			(false)
2062 		, nullStaticColorBlendAttPtr	(false)
2063 		, dualSrcBlend					(false)
2064 		, favorStaticNullPointers		(false)
2065 		, forceAtomicCounters			(false)
2066 		, dynamicSampleMaskCount		(tcu::Nothing)
2067 #ifndef CTS_USES_VULKANSC
2068 		, depthBiasReprInfo				(tcu::Nothing)
2069 #endif // CTS_USES_VULKANSC
2070 		, neededDepthChannelClass		(tcu::TEXTURECHANNELCLASS_LAST)
2071 		, extraDepthThreshold			(0.0f)
2072 		, sampleShadingEnable			(false)
2073 		, minSampleShading				(0.0f)
2074 		, vertexGenerator				(makeVertexGeneratorConfig(staticVertexGenerator, dynamicVertexGenerator))
2075 		, cullModeConfig				(static_cast<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE))
2076 		, frontFaceConfig				(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
2077 		// By default we will use a triangle strip with 6 vertices that could be wrongly interpreted as a triangle list with 2 triangles.
2078 		, topologyConfig				(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2079 		, viewportConfig				(ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight)))
2080 		, scissorConfig					(ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight)))
2081 		// By default, the vertex stride is the size of a vertex according to the chosen vertex type.
2082 		, strideConfig					(chooseVertexGenerator(staticVertexGenerator, dynamicVertexGenerator)->getVertexDataStrides())
2083 		, depthTestEnableConfig			(false)
2084 		, depthWriteEnableConfig		(false)
2085 		, depthCompareOpConfig			(vk::VK_COMPARE_OP_NEVER)
2086 		, depthBoundsTestEnableConfig	(false)
2087 		, depthBoundsConfig				(std::make_pair(0.0f, 1.0f))
2088 		, stencilTestEnableConfig		(false)
2089 		, stencilOpConfig				(StencilOpVec(1u, kDefaultStencilOpParams))
2090 		, depthBiasEnableConfig			(false)
2091 		, rastDiscardEnableConfig		(false)
2092 		, primRestartEnableConfig		(false)
2093 		, logicOpConfig					(vk::VK_LOGIC_OP_CLEAR)
2094 		, patchControlPointsConfig		(1u)
2095 		, depthBiasConfig				(kNoDepthBiasParams)
2096 		, tessDomainOriginConfig		(vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
2097 		, depthClampEnableConfig		(false)
2098 		, polygonModeConfig				(vk::VK_POLYGON_MODE_FILL)
2099 		, sampleMaskConfig				(SampleMaskVec())
2100 		, alphaToCoverageConfig			(false)
2101 		, alphaToOneConfig				(false)
2102 		, colorWriteEnableConfig		(true)
2103 		, colorWriteMaskConfig			(CR | CG | CB | CA)
2104 		, rasterizationStreamConfig		(tcu::Nothing)
2105 		, logicOpEnableConfig			(false)
2106 		, colorBlendEnableConfig		(false)
2107 		, colorBlendEquationConfig		(ColorBlendEq())
2108 		, blendConstantsConfig			(BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f})
2109 		, provokingVertexConfig			(tcu::Nothing)
2110 		, negativeOneToOneConfig		(tcu::Nothing)
2111 		, depthClipEnableConfig			(tcu::Nothing)
2112 		, lineStippleEnableConfig		(false)
2113 		, lineStippleParamsConfig		(tcu::Nothing)
2114 		, sampleLocationsEnableConfig	(false)
2115 		, conservativeRasterModeConfig	(vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT)
2116 		, extraPrimitiveOverEstConfig	(-1.0f)
2117 		, lineRasterModeConfig			(tcu::Nothing)
2118 		, coverageToColorEnableConfig	(false)
2119 		, coverageToColorLocationConfig	(0u)
2120 		, rasterizationSamplesConfig	(kSingleSampleCount)
2121 		, lineWidthConfig				(1.0f)
2122 #ifndef CTS_USES_VULKANSC
2123 		, coverageModulationModeConfig	(vk::VK_COVERAGE_MODULATION_MODE_NONE_NV)
2124 		, coverageModTableEnableConfig	(false)
2125 		, coverageModTableConfig		(CovModTableVec())
2126 		, coverageReductionModeConfig	(vk::VK_COVERAGE_REDUCTION_MODE_MERGE_NV)
2127 		, viewportSwizzleConfig			(ViewportSwzVec())
2128 		, shadingRateImageEnableConfig	(false)
2129 		, viewportWScalingEnableConfig	(false)
2130 		, reprFragTestEnableConfig		(false)
2131 #endif // CTS_USES_VULKANSC
2132 		, m_swappedValues				(false)
2133 	{
2134 	}
2135 
TestConfigvkt::pipeline::__anon5f321d180111::TestConfig2136 	TestConfig (const TestConfig& other)
2137 		: pipelineConstructionType		(other.pipelineConstructionType)
2138 		, sequenceOrdering				(other.sequenceOrdering)
2139 		, meshParams					(other.meshParams)
2140 		, referenceStencil				(other.referenceStencil)
2141 		, clearColorValue				(other.clearColorValue)
2142 		, clearDepthValue				(other.clearDepthValue)
2143 		, clearStencilValue				(other.clearStencilValue)
2144 		, referenceColor				(other.referenceColor->clone())
2145 		, expectedDepth					(other.expectedDepth)
2146 		, expectedStencil				(other.expectedStencil)
2147 		, colorVerificator				(other.colorVerificator)
2148 		, forceGeometryShader			(other.forceGeometryShader)
2149 		, useMeshShaders				(other.useMeshShaders)
2150 		, bindUnusedMeshShadingPipeline	(other.bindUnusedMeshShadingPipeline)
2151 		, singleVertex					(other.singleVertex)
2152 		, singleVertexDrawCount			(other.singleVertexDrawCount)
2153 		, oversizedTriangle				(other.oversizedTriangle)
2154 		, offCenterTriangle				(other.offCenterTriangle)
2155 		, offCenterProportion			(other.offCenterProportion)
2156 		, obliqueLine					(other.obliqueLine)
2157 		, vertexDataOffset				(other.vertexDataOffset)
2158 		, vertexDataExtraBytes			(other.vertexDataExtraBytes)
2159 		, useExtraDynPCPPipeline		(other.useExtraDynPCPPipeline)
2160 		, useExtraDynPipeline			(other.useExtraDynPipeline)
2161 		, coverageModulation			(other.coverageModulation)
2162 		, coverageReduction				(other.coverageReduction)
2163 		, colorSampleCount				(other.colorSampleCount)
2164 		, shaderRasterizationStream		(other.shaderRasterizationStream)
2165 		, sampleLocations				(other.sampleLocations)
2166 		, colorAttachmentCount			(other.colorAttachmentCount)
2167 		, instanceCount					(other.instanceCount)
2168 		, viewportSwizzle				(other.viewportSwizzle)
2169 		, shadingRateImage				(other.shadingRateImage)
2170 		, viewportWScaling				(other.viewportWScaling)
2171 		, representativeFragmentTest	(other.representativeFragmentTest)
2172 		, extraLineRestarts				(other.extraLineRestarts)
2173 		, colorBlendBoth				(other.colorBlendBoth)
2174 		, useColorWriteEnable			(other.useColorWriteEnable)
2175 		, forceUnormColorFormat			(other.forceUnormColorFormat)
2176 		, nullStaticColorBlendAttPtr	(other.nullStaticColorBlendAttPtr)
2177 		, dualSrcBlend					(other.dualSrcBlend)
2178 		, favorStaticNullPointers		(other.favorStaticNullPointers)
2179 		, forceAtomicCounters			(other.forceAtomicCounters)
2180 		, dynamicSampleMaskCount		(other.dynamicSampleMaskCount)
2181 #ifndef CTS_USES_VULKANSC
2182 		, depthBiasReprInfo				(other.depthBiasReprInfo)
2183 #endif // CTS_USES_VULKANSC
2184 		, neededDepthChannelClass		(other.neededDepthChannelClass)
2185 		, extraDepthThreshold			(other.extraDepthThreshold)
2186 		, sampleShadingEnable			(other.sampleShadingEnable)
2187 		, minSampleShading				(other.minSampleShading)
2188 		, vertexGenerator				(other.vertexGenerator)
2189 		, cullModeConfig				(other.cullModeConfig)
2190 		, frontFaceConfig				(other.frontFaceConfig)
2191 		, topologyConfig				(other.topologyConfig)
2192 		, viewportConfig				(other.viewportConfig)
2193 		, scissorConfig					(other.scissorConfig)
2194 		, strideConfig					(other.strideConfig)
2195 		, depthTestEnableConfig			(other.depthTestEnableConfig)
2196 		, depthWriteEnableConfig		(other.depthWriteEnableConfig)
2197 		, depthCompareOpConfig			(other.depthCompareOpConfig)
2198 		, depthBoundsTestEnableConfig	(other.depthBoundsTestEnableConfig)
2199 		, depthBoundsConfig				(other.depthBoundsConfig)
2200 		, stencilTestEnableConfig		(other.stencilTestEnableConfig)
2201 		, stencilOpConfig				(other.stencilOpConfig)
2202 		, depthBiasEnableConfig			(other.depthBiasEnableConfig)
2203 		, rastDiscardEnableConfig		(other.rastDiscardEnableConfig)
2204 		, primRestartEnableConfig		(other.primRestartEnableConfig)
2205 		, logicOpConfig					(other.logicOpConfig)
2206 		, patchControlPointsConfig		(other.patchControlPointsConfig)
2207 		, depthBiasConfig				(other.depthBiasConfig)
2208 		, tessDomainOriginConfig		(other.tessDomainOriginConfig)
2209 		, depthClampEnableConfig		(other.depthClampEnableConfig)
2210 		, polygonModeConfig				(other.polygonModeConfig)
2211 		, sampleMaskConfig				(other.sampleMaskConfig)
2212 		, alphaToCoverageConfig			(other.alphaToCoverageConfig)
2213 		, alphaToOneConfig				(other.alphaToOneConfig)
2214 		, colorWriteEnableConfig		(other.colorWriteEnableConfig)
2215 		, colorWriteMaskConfig			(other.colorWriteMaskConfig)
2216 		, rasterizationStreamConfig		(other.rasterizationStreamConfig)
2217 		, logicOpEnableConfig			(other.logicOpEnableConfig)
2218 		, colorBlendEnableConfig		(other.colorBlendEnableConfig)
2219 		, colorBlendEquationConfig		(other.colorBlendEquationConfig)
2220 		, blendConstantsConfig			(other.blendConstantsConfig)
2221 		, provokingVertexConfig			(other.provokingVertexConfig)
2222 		, negativeOneToOneConfig		(other.negativeOneToOneConfig)
2223 		, depthClipEnableConfig			(other.depthClipEnableConfig)
2224 		, lineStippleEnableConfig		(other.lineStippleEnableConfig)
2225 		, lineStippleParamsConfig		(other.lineStippleParamsConfig)
2226 		, sampleLocationsEnableConfig	(other.sampleLocationsEnableConfig)
2227 		, conservativeRasterModeConfig	(other.conservativeRasterModeConfig)
2228 		, extraPrimitiveOverEstConfig	(other.extraPrimitiveOverEstConfig)
2229 		, lineRasterModeConfig			(other.lineRasterModeConfig)
2230 		, coverageToColorEnableConfig	(other.coverageToColorEnableConfig)
2231 		, coverageToColorLocationConfig	(other.coverageToColorLocationConfig)
2232 		, rasterizationSamplesConfig	(other.rasterizationSamplesConfig)
2233 		, lineWidthConfig				(other.lineWidthConfig)
2234 #ifndef CTS_USES_VULKANSC
2235 		, coverageModulationModeConfig	(other.coverageModulationModeConfig)
2236 		, coverageModTableEnableConfig	(other.coverageModTableEnableConfig)
2237 		, coverageModTableConfig		(other.coverageModTableConfig)
2238 		, coverageReductionModeConfig	(other.coverageReductionModeConfig)
2239 		, viewportSwizzleConfig			(other.viewportSwizzleConfig)
2240 		, shadingRateImageEnableConfig	(other.shadingRateImageEnableConfig)
2241 		, viewportWScalingEnableConfig	(other.viewportWScalingEnableConfig)
2242 		, reprFragTestEnableConfig		(other.reprFragTestEnableConfig)
2243 #endif // CTS_USES_VULKANSC
2244 		, m_swappedValues				(other.m_swappedValues)
2245 	{
2246 	}
2247 
2248 	// Get the proper viewport vector according to the test config.
getActiveViewportVecvkt::pipeline::__anon5f321d180111::TestConfig2249 	const ViewportVec& getActiveViewportVec () const
2250 	{
2251 		return ((viewportConfig.dynamicValue && !m_swappedValues) ? viewportConfig.dynamicValue.get() : viewportConfig.staticValue);
2252 	}
2253 
2254 	// Gets the proper vertex generator according to the test config.
getActiveVertexGeneratorvkt::pipeline::__anon5f321d180111::TestConfig2255 	const VertexGenerator* getActiveVertexGenerator () const
2256 	{
2257 		return ((vertexGenerator.dynamicValue && !m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
2258 	}
2259 
2260 	// Gets the inactive vertex generator according to the test config. If there's only one, return that.
getInactiveVertexGeneratorvkt::pipeline::__anon5f321d180111::TestConfig2261 	const VertexGenerator* getInactiveVertexGenerator () const
2262 	{
2263 		return ((vertexGenerator.dynamicValue && m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
2264 	}
2265 
2266 	// Get the active number of patch control points according to the test config.
getActivePatchControlPointsvkt::pipeline::__anon5f321d180111::TestConfig2267 	deUint32 getActivePatchControlPoints () const
2268 	{
2269 		return ((patchControlPointsConfig.dynamicValue && !m_swappedValues) ? patchControlPointsConfig.dynamicValue.get() : patchControlPointsConfig.staticValue);
2270 	}
2271 
2272 	// Get the active depth bias parameters.
getActiveDepthBiasParamsvkt::pipeline::__anon5f321d180111::TestConfig2273 	DepthBiasParams getActiveDepthBiasParams () const
2274 	{
2275 		return ((depthBiasConfig.dynamicValue && !m_swappedValues) ? depthBiasConfig.dynamicValue.get() : depthBiasConfig.staticValue);
2276 	}
2277 
getActiveTessellationDomainOriginvkt::pipeline::__anon5f321d180111::TestConfig2278 	vk::VkTessellationDomainOrigin getActiveTessellationDomainOrigin () const
2279 	{
2280 		return ((tessDomainOriginConfig.dynamicValue && !m_swappedValues) ? tessDomainOriginConfig.dynamicValue.get() : tessDomainOriginConfig.staticValue);
2281 	}
2282 
getActivePolygonModevkt::pipeline::__anon5f321d180111::TestConfig2283 	vk::VkPolygonMode getActivePolygonMode () const
2284 	{
2285 		return ((polygonModeConfig.dynamicValue && !m_swappedValues) ? polygonModeConfig.dynamicValue.get() : polygonModeConfig.staticValue);
2286 	}
2287 
getActiveSampleCountvkt::pipeline::__anon5f321d180111::TestConfig2288 	vk::VkSampleCountFlagBits getActiveSampleCount () const
2289 	{
2290 		return ((rasterizationSamplesConfig.dynamicValue && !m_swappedValues) ? rasterizationSamplesConfig.dynamicValue.get() : rasterizationSamplesConfig.staticValue);
2291 	}
2292 
getActiveAlphaToOnevkt::pipeline::__anon5f321d180111::TestConfig2293 	bool getActiveAlphaToOne () const
2294 	{
2295 		return ((alphaToOneConfig.dynamicValue && !m_swappedValues) ? alphaToOneConfig.dynamicValue.get() : alphaToOneConfig.staticValue);
2296 	}
2297 
rasterizationStreamStructvkt::pipeline::__anon5f321d180111::TestConfig2298 	bool rasterizationStreamStruct () const
2299 	{
2300 		return (static_cast<bool>(rasterizationStreamConfig.staticValue)
2301 				|| (static_cast<bool>(rasterizationStreamConfig.dynamicValue) && static_cast<bool>(rasterizationStreamConfig.dynamicValue.get())));
2302 	}
2303 
provokingVertexStructvkt::pipeline::__anon5f321d180111::TestConfig2304 	bool provokingVertexStruct () const
2305 	{
2306 		return (static_cast<bool>(provokingVertexConfig.staticValue)
2307 				|| (static_cast<bool>(provokingVertexConfig.dynamicValue) && static_cast<bool>(provokingVertexConfig.dynamicValue.get())));
2308 	}
2309 
negativeOneToOneStructvkt::pipeline::__anon5f321d180111::TestConfig2310 	bool negativeOneToOneStruct () const
2311 	{
2312 		return (static_cast<bool>(negativeOneToOneConfig.staticValue)
2313 				|| (static_cast<bool>(negativeOneToOneConfig.dynamicValue) && static_cast<bool>(negativeOneToOneConfig.dynamicValue.get())));
2314 	}
2315 
depthClipEnableStructvkt::pipeline::__anon5f321d180111::TestConfig2316 	bool depthClipEnableStruct () const
2317 	{
2318 		return (static_cast<bool>(depthClipEnableConfig.staticValue)
2319 				|| (static_cast<bool>(depthClipEnableConfig.dynamicValue) && static_cast<bool>(depthClipEnableConfig.dynamicValue.get())));
2320 	}
2321 
hasStaticLineStippleParamsvkt::pipeline::__anon5f321d180111::TestConfig2322 	bool hasStaticLineStippleParams () const
2323 	{
2324 		return (static_cast<bool>(lineStippleParamsConfig.staticValue));
2325 	}
2326 
hasStaticLineRasterModevkt::pipeline::__anon5f321d180111::TestConfig2327 	bool hasStaticLineRasterMode () const
2328 	{
2329 		return (static_cast<bool>(lineRasterModeConfig.staticValue));
2330 	}
2331 
hasLineStippleParamsvkt::pipeline::__anon5f321d180111::TestConfig2332 	bool hasLineStippleParams () const
2333 	{
2334 		return (hasStaticLineStippleParams()
2335 				|| (static_cast<bool>(lineStippleParamsConfig.dynamicValue) && static_cast<bool>(lineStippleParamsConfig.dynamicValue.get())));
2336 	}
2337 
hasLineRasterModevkt::pipeline::__anon5f321d180111::TestConfig2338 	bool hasLineRasterMode () const
2339 	{
2340 		return (hasStaticLineRasterMode()
2341 				|| (static_cast<bool>(lineRasterModeConfig.dynamicValue) && static_cast<bool>(lineRasterModeConfig.dynamicValue.get())));
2342 	}
2343 
lineStippleSupportRequiredvkt::pipeline::__anon5f321d180111::TestConfig2344 	bool lineStippleSupportRequired () const
2345 	{
2346 		return (lineStippleEnableConfig.staticValue || (static_cast<bool>(lineStippleEnableConfig.dynamicValue) && lineStippleEnableConfig.dynamicValue.get()));
2347 	}
2348 
lineRasterStructvkt::pipeline::__anon5f321d180111::TestConfig2349 	bool lineRasterStruct () const
2350 	{
2351 		return (static_cast<bool>(lineStippleEnableConfig.dynamicValue) || lineStippleEnableConfig.staticValue || hasStaticLineStippleParams() || hasStaticLineRasterMode());
2352 	}
2353 
lineRasterizationExtvkt::pipeline::__anon5f321d180111::TestConfig2354 	bool lineRasterizationExt () const
2355 	{
2356 		return (lineRasterStruct() || hasLineStippleParams() || hasLineRasterMode());
2357 	}
2358 
sampleLocationsStructvkt::pipeline::__anon5f321d180111::TestConfig2359 	bool sampleLocationsStruct () const
2360 	{
2361 		return (static_cast<bool>(sampleLocationsEnableConfig.dynamicValue) || sampleLocationsEnableConfig.staticValue);
2362 	}
2363 
coverageToColorStructvkt::pipeline::__anon5f321d180111::TestConfig2364 	bool coverageToColorStruct () const
2365 	{
2366 		return (static_cast<bool>(coverageToColorEnableConfig.dynamicValue) || coverageToColorEnableConfig.staticValue);
2367 	}
2368 
conservativeRasterStructvkt::pipeline::__anon5f321d180111::TestConfig2369 	bool conservativeRasterStruct () const
2370 	{
2371 		return (static_cast<bool>(conservativeRasterModeConfig.dynamicValue) || conservativeRasterModeConfig.staticValue != vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
2372 				|| static_cast<bool>(extraPrimitiveOverEstConfig.dynamicValue) || extraPrimitiveOverEstConfig.staticValue >= 0.0f);
2373 	}
2374 
getActiveConservativeRasterModevkt::pipeline::__anon5f321d180111::TestConfig2375 	vk::VkConservativeRasterizationModeEXT getActiveConservativeRasterMode () const
2376 	{
2377 		return ((static_cast<bool>(conservativeRasterModeConfig.dynamicValue) && !m_swappedValues) ? conservativeRasterModeConfig.dynamicValue.get() : conservativeRasterModeConfig.staticValue);
2378 	}
2379 
getActiveExtraPrimitiveOverEstSizevkt::pipeline::__anon5f321d180111::TestConfig2380 	float getActiveExtraPrimitiveOverEstSize () const
2381 	{
2382 		return ((static_cast<bool>(extraPrimitiveOverEstConfig.dynamicValue) && !m_swappedValues) ? extraPrimitiveOverEstConfig.dynamicValue.get() : extraPrimitiveOverEstConfig.staticValue);
2383 	}
2384 
getActiveNegativeOneToOneValuevkt::pipeline::__anon5f321d180111::TestConfig2385 	bool getActiveNegativeOneToOneValue () const
2386 	{
2387 		const bool				staticValue		= (static_cast<bool>(negativeOneToOneConfig.staticValue) ? negativeOneToOneConfig.staticValue.get() : false);
2388 		const bool				hasDynamicValue	= (static_cast<bool>(negativeOneToOneConfig.dynamicValue) && static_cast<bool>(negativeOneToOneConfig.dynamicValue.get()));
2389 		const tcu::Maybe<bool>	dynamicValue	= (hasDynamicValue ? tcu::just(negativeOneToOneConfig.dynamicValue->get()) : tcu::nothing<bool>());
2390 
2391 		return ((hasDynamicValue && !m_swappedValues) ? dynamicValue.get() : staticValue);
2392 	}
2393 
getActiveDepthClipEnablevkt::pipeline::__anon5f321d180111::TestConfig2394 	bool getActiveDepthClipEnable () const
2395 	{
2396 		const bool				staticValue		= (static_cast<bool>(depthClipEnableConfig.staticValue) ? depthClipEnableConfig.staticValue.get() : true);
2397 		const bool				hasDynamicValue	= (static_cast<bool>(depthClipEnableConfig.dynamicValue) && static_cast<bool>(depthClipEnableConfig.dynamicValue.get()));
2398 		const tcu::Maybe<bool>	dynamicValue	= (hasDynamicValue ? tcu::just(depthClipEnableConfig.dynamicValue->get()) : tcu::nothing<bool>());
2399 
2400 		return ((hasDynamicValue && !m_swappedValues) ? dynamicValue.get() : staticValue);
2401 	}
2402 
getActiveLineWidthvkt::pipeline::__anon5f321d180111::TestConfig2403 	float getActiveLineWidth () const
2404 	{
2405 		return ((static_cast<bool>(lineWidthConfig.dynamicValue) && !m_swappedValues) ? lineWidthConfig.dynamicValue.get() : lineWidthConfig.staticValue);
2406 	}
2407 
2408 	// Returns true if there is more than one viewport.
isMultiViewportvkt::pipeline::__anon5f321d180111::TestConfig2409 	bool isMultiViewport () const
2410 	{
2411 		return (getActiveViewportVec().size() > 1);
2412 	}
2413 
2414 	// Returns true if the case needs a geometry shader.
needsGeometryShadervkt::pipeline::__anon5f321d180111::TestConfig2415 	bool needsGeometryShader () const
2416 	{
2417 		// Writing to gl_ViewportIndex from vertex or tesselation shaders needs the shaderOutputViewportIndex feature, which is less
2418 		// commonly supported than geometry shaders, so we will use a geometry shader if we need to write to it.
2419 		return ((isMultiViewport() && (!useMeshShaders)) || forceGeometryShader || static_cast<bool>(shaderRasterizationStream));
2420 	}
2421 
2422 	// Returns true if we should use the static and dynamic values exchanged.
2423 	// This makes the static part of the pipeline have the actual expected values.
isReversedvkt::pipeline::__anon5f321d180111::TestConfig2424 	bool isReversed () const
2425 	{
2426 		return (sequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
2427 				sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC);
2428 	}
2429 
2430 	// Returns true if the ordering needs to bind a static pipeline first.
bindStaticFirstvkt::pipeline::__anon5f321d180111::TestConfig2431 	bool bindStaticFirst () const
2432 	{
2433 		return (sequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES	||
2434 				sequenceOrdering == SequenceOrdering::AFTER_PIPELINES	||
2435 				sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC);
2436 	}
2437 
2438 	// Returns true if the test uses a static pipeline.
useStaticPipelinevkt::pipeline::__anon5f321d180111::TestConfig2439 	bool useStaticPipeline () const
2440 	{
2441 		return (bindStaticFirst() || isReversed());
2442 	}
2443 
2444 	// Swaps static and dynamic configuration values.
swapValuesvkt::pipeline::__anon5f321d180111::TestConfig2445 	void swapValues ()
2446 	{
2447 		vertexGenerator.swapValues();
2448 		cullModeConfig.swapValues();
2449 		frontFaceConfig.swapValues();
2450 		topologyConfig.swapValues();
2451 		viewportConfig.swapValues();
2452 		scissorConfig.swapValues();
2453 		strideConfig.swapValues();
2454 		depthTestEnableConfig.swapValues();
2455 		depthWriteEnableConfig.swapValues();
2456 		depthCompareOpConfig.swapValues();
2457 		depthBoundsTestEnableConfig.swapValues();
2458 		depthBoundsConfig.swapValues();
2459 		stencilTestEnableConfig.swapValues();
2460 		stencilOpConfig.swapValues();
2461 		depthBiasEnableConfig.swapValues();
2462 		rastDiscardEnableConfig.swapValues();
2463 		primRestartEnableConfig.swapValues();
2464 		logicOpConfig.swapValues();
2465 		patchControlPointsConfig.swapValues();
2466 		depthBiasConfig.swapValues();
2467 		tessDomainOriginConfig.swapValues();
2468 		depthClampEnableConfig.swapValues();
2469 		polygonModeConfig.swapValues();
2470 		sampleMaskConfig.swapValues();
2471 		alphaToCoverageConfig.swapValues();
2472 		alphaToOneConfig.swapValues();
2473 		colorWriteEnableConfig.swapValues();
2474 		colorWriteMaskConfig.swapValues();
2475 		rasterizationStreamConfig.swapValues();
2476 		logicOpEnableConfig.swapValues();
2477 		colorBlendEnableConfig.swapValues();
2478 		colorBlendEquationConfig.swapValues();
2479 		blendConstantsConfig.swapValues();
2480 		provokingVertexConfig.swapValues();
2481 		negativeOneToOneConfig.swapValues();
2482 		depthClipEnableConfig.swapValues();
2483 		lineStippleEnableConfig.swapValues();
2484 		lineStippleParamsConfig.swapValues();
2485 		sampleLocationsEnableConfig.swapValues();
2486 		conservativeRasterModeConfig.swapValues();
2487 		extraPrimitiveOverEstConfig.swapValues();
2488 		lineRasterModeConfig.swapValues();
2489 		coverageToColorEnableConfig.swapValues();
2490 		coverageToColorLocationConfig.swapValues();
2491 		rasterizationSamplesConfig.swapValues();
2492 		lineWidthConfig.swapValues();
2493 #ifndef CTS_USES_VULKANSC
2494 		coverageModulationModeConfig.swapValues();
2495 		coverageModTableEnableConfig.swapValues();
2496 		coverageModTableConfig.swapValues();
2497 		coverageReductionModeConfig.swapValues();
2498 		viewportSwizzleConfig.swapValues();
2499 		shadingRateImageEnableConfig.swapValues();
2500 		viewportWScalingEnableConfig.swapValues();
2501 		reprFragTestEnableConfig.swapValues();
2502 #endif // CTS_USES_VULKANSC
2503 
2504 		m_swappedValues = !m_swappedValues;
2505 	}
2506 
2507 	// Returns the number of iterations when recording commands.
numIterationsvkt::pipeline::__anon5f321d180111::TestConfig2508 	deUint32 numIterations () const
2509 	{
2510 		deUint32 iterations = 0u;
2511 
2512 		switch (sequenceOrdering)
2513 		{
2514 		case SequenceOrdering::TWO_DRAWS_DYNAMIC:
2515 		case SequenceOrdering::TWO_DRAWS_STATIC:
2516 			iterations = 2u;
2517 			break;
2518 		default:
2519 			iterations = 1u;
2520 			break;
2521 		}
2522 
2523 		return iterations;
2524 	}
2525 
2526 	// Returns true if we're testing the logic op.
testLogicOpvkt::pipeline::__anon5f321d180111::TestConfig2527 	bool testLogicOp () const
2528 	{
2529 		return static_cast<bool>(logicOpConfig.dynamicValue);
2530 	}
2531 
2532 	// Returns true if we're testing the logic op enable state.
testLogicOpEnablevkt::pipeline::__anon5f321d180111::TestConfig2533 	bool testLogicOpEnable () const
2534 	{
2535 		return static_cast<bool>(logicOpEnableConfig.dynamicValue);
2536 	}
2537 
2538 	// Returns true if we're testing the patch control points.
testPatchControlPointsvkt::pipeline::__anon5f321d180111::TestConfig2539 	bool testPatchControlPoints () const
2540 	{
2541 		return static_cast<bool>(patchControlPointsConfig.dynamicValue);
2542 	}
2543 
2544 	// Returns true if we're testing tessellation domain origin.
testTessellationDomainOriginvkt::pipeline::__anon5f321d180111::TestConfig2545 	bool testTessellationDomainOrigin () const
2546 	{
2547 		return static_cast<bool>(tessDomainOriginConfig.dynamicValue);
2548 	}
2549 
2550 	// Returns true if we're testing primitive restart enable.
testPrimRestartEnablevkt::pipeline::__anon5f321d180111::TestConfig2551 	bool testPrimRestartEnable () const
2552 	{
2553 		return static_cast<bool>(primRestartEnableConfig.dynamicValue);
2554 	}
2555 
2556 	// Returns the topology class.
topologyClassvkt::pipeline::__anon5f321d180111::TestConfig2557 	TopologyClass topologyClass () const
2558 	{
2559 		return getTopologyClass(topologyConfig.staticValue);
2560 	}
2561 
2562 	// Returns true if the topology class is patches for tessellation.
patchesTopologyvkt::pipeline::__anon5f321d180111::TestConfig2563 	bool patchesTopology () const
2564 	{
2565 		return (topologyClass() == TopologyClass::PATCH);
2566 	}
2567 
2568 	// Returns true if the test needs tessellation shaders.
needsTessellationvkt::pipeline::__anon5f321d180111::TestConfig2569 	bool needsTessellation () const
2570 	{
2571 		return (testPatchControlPoints() || patchesTopology() || testTessellationDomainOrigin());
2572 	}
2573 
2574 	// Returns the active line stipple enablement flag.
getActiveLineStippleEnablevkt::pipeline::__anon5f321d180111::TestConfig2575 	bool getActiveLineStippleEnable () const
2576 	{
2577 		return ((static_cast<bool>(lineStippleEnableConfig.dynamicValue) && !m_swappedValues) ? lineStippleEnableConfig.dynamicValue.get() : lineStippleEnableConfig.staticValue);
2578 	}
2579 
2580 	// Returns the active primitive restart enablement flag.
getActivePrimRestartEnablevkt::pipeline::__anon5f321d180111::TestConfig2581 	bool getActivePrimRestartEnable () const
2582 	{
2583 		return ((static_cast<bool>(primRestartEnableConfig.dynamicValue) && !m_swappedValues) ? primRestartEnableConfig.dynamicValue.get() : primRestartEnableConfig.staticValue);
2584 	}
2585 
2586 	// Returns the active representative fragment test enablement flag.
getActiveReprFragTestEnablevkt::pipeline::__anon5f321d180111::TestConfig2587 	bool getActiveReprFragTestEnable () const
2588 	{
2589 #ifndef CTS_USES_VULKANSC
2590 		return ((static_cast<bool>(reprFragTestEnableConfig.dynamicValue) && !m_swappedValues) ? reprFragTestEnableConfig.dynamicValue.get() : reprFragTestEnableConfig.staticValue);
2591 #else
2592 		return false;
2593 #endif // CTS_USES_VULKANSC
2594 	}
2595 
2596 	// Returns the active color blend enablement flag.
getActiveColorBlendEnablevkt::pipeline::__anon5f321d180111::TestConfig2597 	bool getActiveColorBlendEnable () const
2598 	{
2599 		return ((static_cast<bool>(colorBlendEnableConfig.dynamicValue) && !m_swappedValues) ? colorBlendEnableConfig.dynamicValue.get() : colorBlendEnableConfig.staticValue);
2600 	}
2601 
2602 	// Returns true if the test needs an index buffer.
needsIndexBuffervkt::pipeline::__anon5f321d180111::TestConfig2603 	bool needsIndexBuffer () const
2604 	{
2605 		return ((testPrimRestartEnable() || getActiveLineStippleEnable()) && !useMeshShaders);
2606 	}
2607 
2608 	// Returns true if the test needs the depth bias clamp feature.
needsDepthBiasClampFeaturevkt::pipeline::__anon5f321d180111::TestConfig2609 	bool needsDepthBiasClampFeature () const
2610 	{
2611 		return (getActiveDepthBiasParams().clamp != 0.0f);
2612 	}
2613 
2614 	// Returns true if the configuration needs VK_EXT_extended_dynamic_state3.
needsEDS3vkt::pipeline::__anon5f321d180111::TestConfig2615 	bool needsEDS3 () const
2616 	{
2617 		return	(	(!!tessDomainOriginConfig.dynamicValue)
2618 				||	(!!depthClampEnableConfig.dynamicValue)
2619 				||	(!!polygonModeConfig.dynamicValue)
2620 				||	(!!sampleMaskConfig.dynamicValue)
2621 				||	(!!alphaToCoverageConfig.dynamicValue)
2622 				||	(!!alphaToOneConfig.dynamicValue)
2623 				||	(!!colorWriteMaskConfig.dynamicValue)
2624 				||	(!!rasterizationStreamConfig.dynamicValue)
2625 				||	(!!logicOpEnableConfig.dynamicValue)
2626 				||	(!!colorBlendEnableConfig.dynamicValue)
2627 				||	(!!colorBlendEquationConfig.dynamicValue)
2628 				||	(!!provokingVertexConfig.dynamicValue)
2629 				||	(!!negativeOneToOneConfig.dynamicValue)
2630 				||	(!!depthClipEnableConfig.dynamicValue)
2631 				||	(!!lineStippleEnableConfig.dynamicValue)
2632 				||	(!!sampleLocationsEnableConfig.dynamicValue)
2633 				||	(!!conservativeRasterModeConfig.dynamicValue)
2634 				||	(!!extraPrimitiveOverEstConfig.dynamicValue)
2635 				||	(!!lineRasterModeConfig.dynamicValue)
2636 				||	(!!coverageToColorEnableConfig.dynamicValue)
2637 				||	(!!coverageToColorLocationConfig.dynamicValue)
2638 				||	(!!rasterizationSamplesConfig.dynamicValue)
2639 #ifndef CTS_USES_VULKANSC
2640 				||	(!!coverageModulationModeConfig.dynamicValue)
2641 				||	(!!coverageModTableEnableConfig.dynamicValue)
2642 				||	(!!coverageModTableConfig.dynamicValue)
2643 				||	(!!coverageReductionModeConfig.dynamicValue)
2644 				||	(!!viewportSwizzleConfig.dynamicValue)
2645 				||	(!!shadingRateImageEnableConfig.dynamicValue)
2646 				||	(!!viewportWScalingEnableConfig.dynamicValue)
2647 				||	(!!reprFragTestEnableConfig.dynamicValue)
2648 #endif // CTS_USES_VULKANSC
2649 				||	favorStaticNullPointers);
2650 	}
2651 
2652 	// Returns the appropriate color image format for the test.
colorFormatvkt::pipeline::__anon5f321d180111::TestConfig2653 	vk::VkFormat colorFormat () const
2654 	{
2655 		// Special case for some tests.
2656 		if (forceUnormColorFormat)
2657 			return kUnormColorFormat;
2658 
2659 		// Pick int color format when testing logic op dynamic states.
2660 		if (testLogicOp() || testLogicOpEnable())
2661 			return kIntColorFormat;
2662 
2663 		// Pick special color format for coverage to color.
2664 		if (coverageToColorStruct())
2665 			return kIntRedColorFormat;
2666 
2667 		return kUnormColorFormat;
2668 	}
2669 
2670 	// Get used color sample count.
getColorSampleCountvkt::pipeline::__anon5f321d180111::TestConfig2671 	vk::VkSampleCountFlagBits getColorSampleCount () const
2672 	{
2673 		const auto usedColorSampleCount	= ((coverageModulation || coverageReduction)
2674 										? colorSampleCount.get()
2675 										: getActiveSampleCount());
2676 		return usedColorSampleCount;
2677 	}
2678 
2679 	// Returns the list of dynamic states affected by this config.
getDynamicStatesvkt::pipeline::__anon5f321d180111::TestConfig2680 	std::vector<vk::VkDynamicState> getDynamicStates () const
2681 	{
2682 		std::vector<vk::VkDynamicState> dynamicStates;
2683 
2684 		if (lineWidthConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_WIDTH);
2685 		if (depthBiasConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS);
2686 		if (cullModeConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
2687 		if (frontFaceConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
2688 		if (topologyConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
2689 		if (viewportConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT);
2690 		if (scissorConfig.dynamicValue)					dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT);
2691 		if (strideConfig.dynamicValue)					dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
2692 		if (depthTestEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
2693 		if (depthWriteEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
2694 		if (depthCompareOpConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
2695 		if (depthBoundsTestEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
2696 		if (depthBoundsConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS);
2697 		if (stencilTestEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
2698 		if (stencilOpConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
2699 		if (vertexGenerator.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
2700 		if (patchControlPointsConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
2701 		if (rastDiscardEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT);
2702 		if (depthBiasEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT);
2703 		if (logicOpConfig.dynamicValue)					dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
2704 		if (primRestartEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT);
2705 		if (colorWriteEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
2706 		if (blendConstantsConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS);
2707 		if (lineStippleParamsConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
2708 #ifndef CTS_USES_VULKANSC
2709 		if (tessDomainOriginConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
2710 		if (depthClampEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
2711 		if (polygonModeConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
2712 		if (sampleMaskConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
2713 		if (alphaToCoverageConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
2714 		if (alphaToOneConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
2715 		if (colorWriteMaskConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
2716 		if (rasterizationStreamConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
2717 		if (logicOpEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
2718 		if (colorBlendEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
2719 		if (colorBlendEquationConfig.dynamicValue)
2720 		{
2721 			if (colorBlendBoth || nullStaticColorBlendAttPtr)
2722 			{
2723 														dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
2724 														dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
2725 			}
2726 			else
2727 			{
2728 														dynamicStates.push_back(colorBlendEquationConfig.staticValue.isAdvanced()
2729 															? vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT
2730 															: vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
2731 			}
2732 		}
2733 		if (provokingVertexConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
2734 		if (negativeOneToOneConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
2735 		if (depthClipEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
2736 		if (lineStippleEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
2737 		if (sampleLocationsEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
2738 		if (conservativeRasterModeConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
2739 		if (extraPrimitiveOverEstConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
2740 		if (lineRasterModeConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
2741 		if (rasterizationSamplesConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
2742 		if (coverageToColorEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
2743 		if (coverageToColorLocationConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
2744 		if (coverageModulationModeConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
2745 		if (coverageModTableEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
2746 		if (coverageModTableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
2747 		if (coverageReductionModeConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
2748 		if (viewportSwizzleConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
2749 		if (shadingRateImageEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
2750 		if (viewportWScalingEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
2751 		if (reprFragTestEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
2752 #endif // CTS_USES_VULKANSC
2753 
2754 		return dynamicStates;
2755 	}
2756 
2757 #ifndef CTS_USES_VULKANSC
2758 	// Returns true if the test configuration uses dynamic states which are incompatible with mesh shading pipelines.
badMeshShadingPipelineDynStatevkt::pipeline::__anon5f321d180111::TestConfig2759 	bool badMeshShadingPipelineDynState () const
2760 	{
2761 		const auto states = getDynamicStates();
2762 		return std::any_of(begin(states), end(states), isMeshShadingPipelineIncompatible);
2763 	}
2764 #endif // CTS_USES_VULKANSC
2765 
testEDSvkt::pipeline::__anon5f321d180111::TestConfig2766 	bool testEDS() const
2767 	{
2768 		return (cullModeConfig.dynamicValue
2769 			|| frontFaceConfig.dynamicValue
2770 			|| topologyConfig.dynamicValue
2771 			|| viewportConfig.dynamicValue
2772 			|| scissorConfig.dynamicValue
2773 			|| strideConfig.dynamicValue
2774 			|| depthTestEnableConfig.dynamicValue
2775 			|| depthWriteEnableConfig.dynamicValue
2776 			|| depthCompareOpConfig.dynamicValue
2777 			|| depthBoundsTestEnableConfig.dynamicValue
2778 			|| stencilTestEnableConfig.dynamicValue
2779 			|| stencilOpConfig.dynamicValue);
2780 	}
2781 
testEDS2vkt::pipeline::__anon5f321d180111::TestConfig2782 	bool testEDS2() const
2783 	{
2784 		return (rastDiscardEnableConfig.dynamicValue
2785 			|| depthBiasEnableConfig.dynamicValue
2786 			|| primRestartEnableConfig.dynamicValue
2787 			|| useExtraDynPCPPipeline);
2788 	}
2789 
testVertexDynamicvkt::pipeline::__anon5f321d180111::TestConfig2790 	bool testVertexDynamic() const
2791 	{
2792 		return static_cast<bool>(vertexGenerator.dynamicValue);
2793 	}
2794 
2795 	// Returns the list of extensions needed by this config. Note some other
2796 	// requirements are checked with feature structs, which is particularly
2797 	// important for extensions which have been partially promoted, like EDS
2798 	// and EDS2. Extensions requested here have not been partially promoted.
getRequiredExtensionsvkt::pipeline::__anon5f321d180111::TestConfig2799 	std::vector<std::string> getRequiredExtensions () const
2800 	{
2801 		std::vector<std::string> extensions;
2802 
2803 		if (needsEDS3())
2804 		{
2805 			extensions.push_back("VK_EXT_extended_dynamic_state3");
2806 		}
2807 
2808 		if (testTessellationDomainOrigin() || getActiveTessellationDomainOrigin() != vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
2809 		{
2810 			extensions.push_back("VK_KHR_maintenance2");
2811 		}
2812 
2813 		if (rasterizationStreamStruct())
2814 		{
2815 			extensions.push_back("VK_EXT_transform_feedback");
2816 		}
2817 
2818 		if (provokingVertexStruct())
2819 		{
2820 			extensions.push_back("VK_EXT_provoking_vertex");
2821 		}
2822 
2823 		if (negativeOneToOneStruct())
2824 		{
2825 			extensions.push_back("VK_EXT_depth_clip_control");
2826 		}
2827 
2828 		if (depthClipEnableStruct())
2829 		{
2830 			extensions.push_back("VK_EXT_depth_clip_enable");
2831 		}
2832 
2833 		if (lineRasterizationExt())
2834 		{
2835 			extensions.push_back("VK_EXT_line_rasterization");
2836 		}
2837 
2838 		if (colorBlendEquationConfig.staticValue.isAdvanced())
2839 		{
2840 			extensions.push_back("VK_EXT_blend_operation_advanced");
2841 		}
2842 
2843 		if (sampleLocationsStruct())
2844 		{
2845 			extensions.push_back("VK_EXT_sample_locations");
2846 		}
2847 
2848 		if (coverageToColorStruct())
2849 		{
2850 			extensions.push_back("VK_NV_fragment_coverage_to_color");
2851 		}
2852 
2853 		if (conservativeRasterStruct() || static_cast<bool>(maxPrimitiveOverestimationSize))
2854 		{
2855 			extensions.push_back("VK_EXT_conservative_rasterization");
2856 		}
2857 
2858 		if (coverageModulation)
2859 		{
2860 			extensions.push_back("VK_NV_framebuffer_mixed_samples");
2861 		}
2862 
2863 		if (coverageReduction)
2864 		{
2865 			extensions.push_back("VK_NV_coverage_reduction_mode");
2866 		}
2867 
2868 		if (viewportSwizzle)
2869 		{
2870 			extensions.push_back("VK_NV_viewport_swizzle");
2871 		}
2872 
2873 		if (shadingRateImage)
2874 		{
2875 			extensions.push_back("VK_NV_shading_rate_image");
2876 		}
2877 
2878 		if (viewportWScaling)
2879 		{
2880 			extensions.push_back("VK_NV_clip_space_w_scaling");
2881 		}
2882 
2883 		if (representativeFragmentTest)
2884 		{
2885 			extensions.push_back("VK_NV_representative_fragment_test");
2886 		}
2887 
2888 		if (useColorWriteEnable)
2889 		{
2890 			extensions.push_back("VK_EXT_color_write_enable");
2891 		}
2892 
2893 		return extensions;
2894 	}
2895 
getFragDescriptorSetIndexvkt::pipeline::__anon5f321d180111::TestConfig2896 	uint32_t getFragDescriptorSetIndex () const
2897 	{
2898 		return (useMeshShaders ? 1u : 0u);
2899 	}
2900 
useFragShaderAtomicsvkt::pipeline::__anon5f321d180111::TestConfig2901 	bool useFragShaderAtomics () const
2902 	{
2903 		return (representativeFragmentTest || forceAtomicCounters);
2904 	}
2905 
2906 private:
2907 	// Extended dynamic state cases as created by createExtendedDynamicStateTests() are based on the assumption that, when a state
2908 	// has a static and a dynamic value configured at the same time, the static value is wrong and the dynamic value will give
2909 	// expected results. That's appropriate for most test variants, but in some others we want to reverse the situation: a dynamic
2910 	// pipeline with wrong values and a static one with good values.
2911 	//
2912 	// Instead of modifying how tests are created, we use isReversed() and swapValues() above, allowing us to swap static and
2913 	// dynamic values and to know if we should do it for a given test case. However, we need to know were the good value is at any
2914 	// given point in time in order to correctly answer some questions while running the test. m_swappedValues tracks that state.
2915 	bool m_swappedValues;
2916 };
2917 
2918 struct PushConstants
2919 {
2920 	tcu::Vec4	triangleColor;
2921 	float		meshDepth;
2922 	deInt32		viewPortIndex;
2923 	float		scaleX;
2924 	float		scaleY;
2925 	float		offsetX;
2926 	float		offsetY;
2927 	float		stripScale;
2928 };
2929 
copy(vk::VkStencilOpState & dst,const StencilOpParams & src)2930 void copy(vk::VkStencilOpState& dst, const StencilOpParams& src)
2931 {
2932 	dst.failOp		= src.failOp;
2933 	dst.passOp		= src.passOp;
2934 	dst.depthFailOp	= src.depthFailOp;
2935 	dst.compareOp	= src.compareOp;
2936 }
2937 
makeImageCreateInfo(vk::VkFormat format,vk::VkExtent3D extent,vk::VkSampleCountFlagBits sampleCount,vk::VkImageUsageFlags usage,vk::VkImageCreateFlags createFlags)2938 vk::VkImageCreateInfo makeImageCreateInfo (vk::VkFormat format, vk::VkExtent3D extent, vk::VkSampleCountFlagBits sampleCount, vk::VkImageUsageFlags usage, vk::VkImageCreateFlags createFlags)
2939 {
2940 	const vk::VkImageCreateInfo imageCreateInfo =
2941 	{
2942 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2943 		nullptr,									//	const void*				pNext;
2944 		createFlags,								//	VkImageCreateFlags		flags;
2945 		vk::VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2946 		format,										//	VkFormat				format;
2947 		extent,										//	VkExtent3D				extent;
2948 		1u,											//	deUint32				mipLevels;
2949 		1u,											//	deUint32				arrayLayers;
2950 		sampleCount,								//	VkSampleCountFlagBits	samples;
2951 		vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2952 		usage,										//	VkImageUsageFlags		usage;
2953 		vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2954 		0u,											//	deUint32				queueFamilyIndexCount;
2955 		nullptr,									//	const deUint32*			pQueueFamilyIndices;
2956 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2957 	};
2958 
2959 	return imageCreateInfo;
2960 }
2961 
2962 class ExtendedDynamicStateTest : public vkt::TestCase
2963 {
2964 public:
2965 							ExtendedDynamicStateTest		(tcu::TestContext& testCtx, const std::string& name, const TestConfig& testConfig);
~ExtendedDynamicStateTest(void)2966 	virtual					~ExtendedDynamicStateTest		(void) {}
2967 
2968 	virtual void			checkSupport					(Context& context) const;
2969 	virtual void			initPrograms					(vk::SourceCollections& programCollection) const;
2970 	virtual TestInstance*	createInstance					(Context& context) const;
2971 
2972 private:
2973 	TestConfig				m_testConfig;
2974 };
2975 
2976 class ExtendedDynamicStateInstance : public vkt::TestInstance
2977 {
2978 public:
2979 								ExtendedDynamicStateInstance	(Context& context, const TestConfig& testConfig);
~ExtendedDynamicStateInstance(void)2980 	virtual						~ExtendedDynamicStateInstance	(void) {}
2981 
2982 	virtual tcu::TestStatus		iterate							(void);
2983 
2984 private:
2985 	TestConfig					m_testConfig;
2986 };
2987 
ExtendedDynamicStateTest(tcu::TestContext & testCtx,const std::string & name,const TestConfig & testConfig)2988 ExtendedDynamicStateTest::ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const TestConfig& testConfig)
2989 	: vkt::TestCase	(testCtx, name)
2990 	, m_testConfig	(testConfig)
2991 {
2992 	const auto staticTopologyClass = getTopologyClass(testConfig.topologyConfig.staticValue);
2993 	DE_UNREF(staticTopologyClass); // For release builds.
2994 
2995 	// Matching topology classes.
2996 	DE_ASSERT(!testConfig.topologyConfig.dynamicValue ||
2997 			  staticTopologyClass == getTopologyClass(testConfig.topologyConfig.dynamicValue.get()));
2998 
2999 	// Supported topology classes for these tests.
3000 	DE_ASSERT(staticTopologyClass == TopologyClass::LINE || staticTopologyClass == TopologyClass::TRIANGLE
3001 		|| staticTopologyClass == TopologyClass::PATCH);
3002 
3003 	// Make sure these are consistent.
3004 	DE_ASSERT(!(m_testConfig.testPatchControlPoints() && !m_testConfig.patchesTopology()));
3005 	DE_ASSERT(!(m_testConfig.patchesTopology() && m_testConfig.getActivePatchControlPoints() <= 1u));
3006 
3007 	// Do not use an extra dynamic patch control points pipeline if we're not testing them.
3008 	DE_ASSERT(!m_testConfig.useExtraDynPCPPipeline || m_testConfig.testPatchControlPoints());
3009 }
3010 
checkSupport(Context & context) const3011 void ExtendedDynamicStateTest::checkSupport (Context& context) const
3012 {
3013 	const auto&	vki				= context.getInstanceInterface();
3014 	const auto	physicalDevice	= context.getPhysicalDevice();
3015 
3016 	// Check feature support.
3017 	const auto& baseFeatures	= context.getDeviceFeatures();
3018 	const auto& edsFeatures		= context.getExtendedDynamicStateFeaturesEXT();
3019 	const auto& eds2Features	= context.getExtendedDynamicState2FeaturesEXT();
3020 	const auto& viFeatures		= context.getVertexInputDynamicStateFeaturesEXT();
3021 #ifndef CTS_USES_VULKANSC
3022 	const auto& meshFeatures	= context.getMeshShaderFeaturesEXT();
3023 #endif // CTS_USES_VULKANSC
3024 
3025 	if (m_testConfig.dualSrcBlend && !baseFeatures.dualSrcBlend)
3026 		TCU_THROW(NotSupportedError, "dualSrcBlend is not supported");
3027 
3028 	if (m_testConfig.testEDS() && !edsFeatures.extendedDynamicState)
3029 		TCU_THROW(NotSupportedError, "extendedDynamicState is not supported");
3030 
3031 	if (m_testConfig.testEDS2() && !eds2Features.extendedDynamicState2)
3032 		TCU_THROW(NotSupportedError, "extendedDynamicState2 is not supported");
3033 
3034 	if (m_testConfig.testLogicOp() && !eds2Features.extendedDynamicState2LogicOp)
3035 		TCU_THROW(NotSupportedError, "extendedDynamicState2LogicOp is not supported");
3036 
3037 	if ((m_testConfig.testPatchControlPoints() || m_testConfig.useExtraDynPCPPipeline) && !eds2Features.extendedDynamicState2PatchControlPoints)
3038 		TCU_THROW(NotSupportedError, "extendedDynamicState2PatchControlPoints is not supported");
3039 
3040 	if (m_testConfig.testVertexDynamic() && !viFeatures.vertexInputDynamicState)
3041 		TCU_THROW(NotSupportedError, "vertexInputDynamicState is not supported");
3042 
3043 #ifndef CTS_USES_VULKANSC
3044 	if ((m_testConfig.useMeshShaders || m_testConfig.bindUnusedMeshShadingPipeline) && !meshFeatures.meshShader)
3045 		TCU_THROW(NotSupportedError, "meshShader is not supported");
3046 #endif // CTS_USES_VULKANSC
3047 
3048 	// Check extension support.
3049 	const auto requiredExtensions = m_testConfig.getRequiredExtensions();
3050 	for (const auto& extension : requiredExtensions)
3051 		context.requireDeviceFunctionality(extension);
3052 
3053 	// Check support needed for the vertex generators.
3054 	m_testConfig.vertexGenerator.staticValue->checkSupport(context);
3055 	if (m_testConfig.vertexGenerator.dynamicValue)
3056 		m_testConfig.vertexGenerator.dynamicValue.get()->checkSupport(context);
3057 
3058 	// Special requirement for rasterizationSamples tests.
3059 	// The first iteration of these tests puts the pipeline in a mixed samples state,
3060 	// where colorCount != rasterizationSamples.
3061 	if (m_testConfig.rasterizationSamplesConfig.dynamicValue &&
3062 		(m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
3063 		 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC) &&
3064 		!context.isDeviceFunctionalitySupported("VK_AMD_mixed_attachment_samples") &&
3065 		!context.isDeviceFunctionalitySupported("VK_NV_framebuffer_mixed_samples"))
3066 
3067 		TCU_THROW(NotSupportedError, "VK_AMD_mixed_attachment_samples or VK_NV_framebuffer_mixed_samples are not supported");
3068 
3069 	if (m_testConfig.rasterizationSamplesConfig.dynamicValue &&
3070 		(m_testConfig.sequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES ||
3071 		 m_testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES ||
3072 		 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
3073 		 m_testConfig.isReversed()) &&
3074 		(context.isDeviceFunctionalitySupported("VK_AMD_mixed_attachment_samples") ||
3075 		context.isDeviceFunctionalitySupported("VK_NV_framebuffer_mixed_samples")))
3076 
3077 		TCU_THROW(NotSupportedError, "Test not supported with VK_AMD_mixed_attachment_samples or VK_NV_framebuffer_mixed_samples");
3078 
3079 	// Check the number of viewports needed and the corresponding limits.
3080 	const auto&	viewportConfig	= m_testConfig.viewportConfig;
3081 	auto		numViewports	= viewportConfig.staticValue.size();
3082 
3083 	if (viewportConfig.dynamicValue)
3084 		numViewports = std::max(numViewports, viewportConfig.dynamicValue.get().size());
3085 
3086 	if (numViewports > 1)
3087 	{
3088 		const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
3089 		if (numViewports > static_cast<decltype(numViewports)>(properties.limits.maxViewports))
3090 			TCU_THROW(NotSupportedError, "Number of viewports not supported (" + de::toString(numViewports) + ")");
3091 	}
3092 
3093 	const auto&	dbTestEnable	= m_testConfig.depthBoundsTestEnableConfig;
3094 	const bool	useDepthBounds	= (dbTestEnable.staticValue || (dbTestEnable.dynamicValue && dbTestEnable.dynamicValue.get()));
3095 
3096 	if (useDepthBounds || m_testConfig.needsGeometryShader() || m_testConfig.needsTessellation() || m_testConfig.needsDepthBiasClampFeature())
3097 	{
3098 		const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
3099 
3100 		// Check depth bounds test support.
3101 		if (useDepthBounds && !features.depthBounds)
3102 			TCU_THROW(NotSupportedError, "Depth bounds feature not supported");
3103 
3104 		// Check geometry shader support.
3105 		if (m_testConfig.needsGeometryShader() && !features.geometryShader)
3106 			TCU_THROW(NotSupportedError, "Geometry shader not supported");
3107 
3108 		// Check tessellation support
3109 		if (m_testConfig.needsTessellation() && !features.tessellationShader)
3110 			TCU_THROW(NotSupportedError, "Tessellation feature not supported");
3111 
3112 		// Check depth bias clamp feature.
3113 		if (m_testConfig.needsDepthBiasClampFeature() && !features.depthBiasClamp)
3114 			TCU_THROW(NotSupportedError, "Depth bias clamp not supported");
3115 	}
3116 
3117 	// Check color image format support (depth/stencil will be chosen and checked at runtime).
3118 	{
3119 		const auto colorFormat		= m_testConfig.colorFormat();
3120 		const auto colorSampleCount	= m_testConfig.getColorSampleCount();
3121 		const auto colorImageInfo	= makeImageCreateInfo(colorFormat, kFramebufferExtent, colorSampleCount, kColorUsage, 0u);
3122 
3123 		vk::VkImageFormatProperties formatProps;
3124 		const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, colorImageInfo.format, colorImageInfo.imageType, colorImageInfo.tiling, colorImageInfo.usage, colorImageInfo.flags, &formatProps);
3125 
3126 		if (result != vk::VK_SUCCESS)
3127 			TCU_THROW(NotSupportedError, "Required color image features not supported");
3128 
3129 		if ((formatProps.sampleCounts & colorSampleCount) != colorSampleCount)
3130 			TCU_THROW(NotSupportedError, "Required color sample count not supported");
3131 
3132 		// If blending is active, we need to check support explicitly.
3133 		if (m_testConfig.getActiveColorBlendEnable())
3134 		{
3135 			const auto colorFormatProps = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, colorFormat);
3136 			DE_ASSERT(colorImageInfo.tiling == vk::VK_IMAGE_TILING_OPTIMAL);
3137 			if (!(colorFormatProps.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
3138 				TCU_THROW(NotSupportedError, "Color format does not support blending");
3139 		}
3140 	}
3141 
3142 	// Extended dynamic state 3 features.
3143 	if (m_testConfig.needsEDS3())
3144 	{
3145 #ifndef CTS_USES_VULKANSC
3146 		const auto& eds3Features = context.getExtendedDynamicState3FeaturesEXT();
3147 
3148 		if (m_testConfig.testTessellationDomainOrigin() && !eds3Features.extendedDynamicState3TessellationDomainOrigin)
3149 			TCU_THROW(NotSupportedError, "extendedDynamicState3TessellationDomainOrigin not supported");
3150 
3151 		if (m_testConfig.depthClampEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3DepthClampEnable)
3152 			TCU_THROW(NotSupportedError, "extendedDynamicState3DepthClampEnable not supported");
3153 
3154 		if (m_testConfig.polygonModeConfig.dynamicValue && !eds3Features.extendedDynamicState3PolygonMode)
3155 			TCU_THROW(NotSupportedError, "extendedDynamicState3PolygonMode not supported");
3156 
3157 		if (m_testConfig.sampleMaskConfig.dynamicValue && !eds3Features.extendedDynamicState3SampleMask)
3158 			TCU_THROW(NotSupportedError, "extendedDynamicState3SampleMask not supported");
3159 
3160 		if (m_testConfig.alphaToCoverageConfig.dynamicValue && !eds3Features.extendedDynamicState3AlphaToCoverageEnable)
3161 			TCU_THROW(NotSupportedError, "extendedDynamicState3AlphaToCoverageEnable not supported");
3162 
3163 		if (m_testConfig.alphaToOneConfig.dynamicValue && !eds3Features.extendedDynamicState3AlphaToOneEnable)
3164 			TCU_THROW(NotSupportedError, "extendedDynamicState3AlphaToOneEnable not supported");
3165 
3166 		if (m_testConfig.colorWriteMaskConfig.dynamicValue && !eds3Features.extendedDynamicState3ColorWriteMask)
3167 			TCU_THROW(NotSupportedError, "extendedDynamicState3ColorWriteMask not supported");
3168 
3169 		if (m_testConfig.rasterizationStreamConfig.dynamicValue && !eds3Features.extendedDynamicState3RasterizationStream)
3170 			TCU_THROW(NotSupportedError, "extendedDynamicState3RasterizationStream not supported");
3171 
3172 		if (m_testConfig.logicOpEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3LogicOpEnable)
3173 			TCU_THROW(NotSupportedError, "extendedDynamicState3LogicOpEnable not supported");
3174 
3175 		if (m_testConfig.colorBlendEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3ColorBlendEnable)
3176 			TCU_THROW(NotSupportedError, "extendedDynamicState3ColorBlendEnable not supported");
3177 
3178 		if (m_testConfig.colorBlendEquationConfig.dynamicValue)
3179 		{
3180 			const auto isAdvanced = m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced();
3181 
3182 			if (isAdvanced || m_testConfig.colorBlendBoth || m_testConfig.nullStaticColorBlendAttPtr)
3183 			{
3184 				if (!eds3Features.extendedDynamicState3ColorBlendAdvanced)
3185 					TCU_THROW(NotSupportedError, "extendedDynamicState3ColorBlendAdvanced not supported");
3186 			}
3187 
3188 			if (!isAdvanced || m_testConfig.colorBlendBoth)
3189 			{
3190 				if (!eds3Features.extendedDynamicState3ColorBlendEquation)
3191 					TCU_THROW(NotSupportedError, "extendedDynamicState3ColorBlendEquation not supported");
3192 			}
3193 		}
3194 
3195 		if (m_testConfig.provokingVertexConfig.dynamicValue && !eds3Features.extendedDynamicState3ProvokingVertexMode)
3196 			TCU_THROW(NotSupportedError, "extendedDynamicState3ProvokingVertexMode not supported");
3197 
3198 		if (m_testConfig.negativeOneToOneConfig.dynamicValue && !eds3Features.extendedDynamicState3DepthClipNegativeOneToOne)
3199 			TCU_THROW(NotSupportedError, "extendedDynamicState3DepthClipNegativeOneToOne not supported");
3200 
3201 		if (m_testConfig.depthClipEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3DepthClipEnable)
3202 			TCU_THROW(NotSupportedError, "extendedDynamicState3DepthClipEnable not supported");
3203 
3204 		if (m_testConfig.lineStippleEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3LineStippleEnable)
3205 			TCU_THROW(NotSupportedError, "extendedDynamicState3LineStippleEnable not supported");
3206 
3207 		if (m_testConfig.sampleLocationsEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3SampleLocationsEnable)
3208 			TCU_THROW(NotSupportedError, "extendedDynamicState3SampleLocationsEnable not supported");
3209 
3210 		if (m_testConfig.conservativeRasterModeConfig.dynamicValue && !eds3Features.extendedDynamicState3ConservativeRasterizationMode)
3211 			TCU_THROW(NotSupportedError, "extendedDynamicState3ConservativeRasterizationMode not supported");
3212 
3213 		if (m_testConfig.extraPrimitiveOverEstConfig.dynamicValue && !eds3Features.extendedDynamicState3ExtraPrimitiveOverestimationSize)
3214 			TCU_THROW(NotSupportedError, "extendedDynamicState3ExtraPrimitiveOverestimationSize not supported");
3215 
3216 		if (m_testConfig.lineRasterModeConfig.dynamicValue && !eds3Features.extendedDynamicState3LineRasterizationMode)
3217 			TCU_THROW(NotSupportedError, "extendedDynamicState3LineRasterizationMode not supported");
3218 
3219 		if (m_testConfig.coverageToColorEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageToColorEnable)
3220 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageToColorEnable not supported");
3221 
3222 		if (m_testConfig.coverageToColorLocationConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageToColorLocation)
3223 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageToColorLocation not supported");
3224 
3225 		if (m_testConfig.coverageModulationModeConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageModulationMode)
3226 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageModulationMode not supported");
3227 
3228 		if (m_testConfig.coverageModTableEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageModulationTableEnable)
3229 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageModulationTableEnable not supported");
3230 
3231 		if (m_testConfig.coverageModTableConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageModulationTable)
3232 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageModulationTable not supported");
3233 
3234 		if (m_testConfig.coverageReductionModeConfig.dynamicValue)
3235 		{
3236 			if (!eds3Features.extendedDynamicState3CoverageReductionMode)
3237 				TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageReductionMode not supported");
3238 
3239 			uint32_t combinationCount = 0U;
3240 			auto result = vki.getPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(physicalDevice, &combinationCount, nullptr);
3241 			if (result != vk::VK_SUCCESS || combinationCount == 0U)
3242 				TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV supported no combinations");
3243 
3244 			const vk::VkFramebufferMixedSamplesCombinationNV defaultCombination = vk::initVulkanStructure();
3245 			std::vector<vk::VkFramebufferMixedSamplesCombinationNV> combinations(combinationCount, defaultCombination);
3246 			result = vki.getPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(physicalDevice, &combinationCount, combinations.data());
3247 			if (result != vk::VK_SUCCESS)
3248 				TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV supported no combinations");
3249 
3250 			auto findCombination = [&](vk::VkCoverageReductionModeNV const coverageReductionMode) -> bool {
3251 				for (uint32_t i = 0U; i < combinationCount; ++i) {
3252 					if (combinations[i].rasterizationSamples == m_testConfig.rasterizationSamplesConfig.staticValue &&
3253 						combinations[i].colorSamples == m_testConfig.getColorSampleCount() &&
3254 						combinations[i].coverageReductionMode == coverageReductionMode)
3255 					{
3256 						return true;
3257 					}
3258 				}
3259 				return false;
3260 			};
3261 			if (!findCombination(m_testConfig.coverageReductionModeConfig.staticValue) || !findCombination(m_testConfig.coverageReductionModeConfig.dynamicValue.get()))
3262 				TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV no matching combination found");
3263 		}
3264 
3265 		if (m_testConfig.viewportSwizzleConfig.dynamicValue && !eds3Features.extendedDynamicState3ViewportSwizzle)
3266 			TCU_THROW(NotSupportedError, "extendedDynamicState3ViewportSwizzle not supported");
3267 
3268 		if (m_testConfig.shadingRateImageEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3ShadingRateImageEnable)
3269 			TCU_THROW(NotSupportedError, "extendedDynamicState3ShadingRateImageEnable not supported");
3270 
3271 		if (m_testConfig.viewportWScalingEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3ViewportWScalingEnable)
3272 			TCU_THROW(NotSupportedError, "extendedDynamicState3ViewportWScalingEnable not supported");
3273 
3274 		if (m_testConfig.reprFragTestEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3RepresentativeFragmentTestEnable)
3275 			TCU_THROW(NotSupportedError, "extendedDynamicState3RepresentativeFragmentTestEnable not supported");
3276 
3277 		if (m_testConfig.rasterizationSamplesConfig.dynamicValue && !eds3Features.extendedDynamicState3RasterizationSamples)
3278 			TCU_THROW(NotSupportedError, "extendedDynamicState3RasterizationSamples not supported");
3279 #else
3280 		TCU_THROW(NotSupportedError, "VulkanSC does not support extended dynamic state 3");
3281 #endif // CTS_USES_VULKANSC
3282 	}
3283 
3284 	if (m_testConfig.getActivePolygonMode() != vk::VK_POLYGON_MODE_FILL)
3285 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FILL_MODE_NON_SOLID);
3286 
3287 	if (m_testConfig.getActiveAlphaToOne())
3288 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_ALPHA_TO_ONE);
3289 
3290 	if (m_testConfig.rasterizationStreamStruct() || static_cast<bool>(m_testConfig.shaderRasterizationStream))
3291 	{
3292 #ifndef CTS_USES_VULKANSC
3293 		const auto& xfProperties = context.getTransformFeedbackPropertiesEXT();
3294 		if (!xfProperties.transformFeedbackRasterizationStreamSelect)
3295 			TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect not supported");
3296 
3297 		// VUID-RuntimeSpirv-Stream-06312
3298 		if (static_cast<bool>(m_testConfig.shaderRasterizationStream))
3299 		{
3300 			const auto shaderStreamId = m_testConfig.shaderRasterizationStream.get();
3301 			if (shaderStreamId >= xfProperties.maxTransformFeedbackStreams)
3302 				TCU_THROW(NotSupportedError, "Geometry shader rasterization stream above maxTransformFeedbackStreams limit");
3303 		}
3304 
3305 		// VUID-VkPipelineRasterizationStateStreamCreateInfoEXT-rasterizationStream-02325
3306 		if (static_cast<bool>(m_testConfig.rasterizationStreamConfig.staticValue))
3307 		{
3308 			const auto staticStreamId = m_testConfig.rasterizationStreamConfig.staticValue.get();
3309 			if (staticStreamId >= xfProperties.maxTransformFeedbackStreams)
3310 				TCU_THROW(NotSupportedError, "Static stream number above maxTransformFeedbackStreams limit");
3311 		}
3312 		if (static_cast<bool>(m_testConfig.rasterizationStreamConfig.dynamicValue && static_cast<bool>(m_testConfig.rasterizationStreamConfig.dynamicValue.get())))
3313 		{
3314 			const auto dynamicStreamId = m_testConfig.rasterizationStreamConfig.dynamicValue->get();
3315 			if (dynamicStreamId >= xfProperties.maxTransformFeedbackStreams)
3316 				TCU_THROW(NotSupportedError, "Dynamic stream number above maxTransformFeedbackStreams limit");
3317 		}
3318 #else
3319 		TCU_THROW(NotSupportedError, "VulkanSC does not support VK_EXT_transform_feedback");
3320 #endif // CTS_USES_VULKANSC
3321 	}
3322 
3323 	if (m_testConfig.lineRasterizationExt())
3324 	{
3325 		// Check the implementation supports some type of stippled line.
3326 		const auto&	lineRastFeatures	= context.getLineRasterizationFeaturesEXT();
3327 		const auto	rasterMode			= selectLineRasterizationMode(lineRastFeatures, m_testConfig.lineStippleSupportRequired(), m_testConfig.lineRasterModeConfig.staticValue);
3328 
3329 		if (rasterMode == LineRasterizationMode::NONE)
3330 			TCU_THROW(NotSupportedError, "Wanted static line rasterization mode not supported");
3331 
3332 		if (static_cast<bool>(m_testConfig.lineRasterModeConfig.dynamicValue) && static_cast<bool>(m_testConfig.lineRasterModeConfig.dynamicValue.get()))
3333 		{
3334 			const auto dynRasterMode = selectLineRasterizationMode(lineRastFeatures, m_testConfig.lineStippleSupportRequired(), m_testConfig.lineRasterModeConfig.dynamicValue.get());
3335 
3336 			if (dynRasterMode == LineRasterizationMode::NONE)
3337 				TCU_THROW(NotSupportedError, "Wanted dynamic line rasterization mode not supported");
3338 		}
3339 	}
3340 
3341 	const auto hasMaxPrimitiveOverestimationSize = static_cast<bool>(m_testConfig.maxPrimitiveOverestimationSize);
3342 
3343 	if (m_testConfig.conservativeRasterStruct() || hasMaxPrimitiveOverestimationSize)
3344 	{
3345 		const auto& conservativeRasterModeProps = context.getConservativeRasterizationPropertiesEXT();
3346 
3347 		if (m_testConfig.getActiveConservativeRasterMode() == vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT && !conservativeRasterModeProps.primitiveUnderestimation)
3348 			TCU_THROW(NotSupportedError, "primitiveUnderestimation not supported");
3349 
3350 		const auto	extraSize	= m_testConfig.getActiveExtraPrimitiveOverEstSize();
3351 		const auto&	maxExtra	= conservativeRasterModeProps.maxExtraPrimitiveOverestimationSize;
3352 
3353 		if (extraSize >= 0.0f && extraSize > maxExtra)
3354 		{
3355 			std::ostringstream msg;
3356 			msg << "Extra primitive overestimation size (" << extraSize << ") above maxExtraPrimitiveOverestimationSize (" << maxExtra << ")";
3357 			TCU_THROW(NotSupportedError, msg.str());
3358 		}
3359 
3360 		if (hasMaxPrimitiveOverestimationSize)
3361 		{
3362 			const auto maxPrimitiveOverestimationSizeVal = m_testConfig.maxPrimitiveOverestimationSize.get();
3363 			if (conservativeRasterModeProps.primitiveOverestimationSize > maxPrimitiveOverestimationSizeVal)
3364 			{
3365 				std::ostringstream msg;
3366 				msg << "primitiveOverestimationSize (" << conservativeRasterModeProps.primitiveOverestimationSize
3367 					<< ") too big for this test (max " << maxPrimitiveOverestimationSizeVal << ")";
3368 				TCU_THROW(NotSupportedError, msg.str());
3369 			}
3370 		}
3371 	}
3372 
3373 	if (m_testConfig.useFragShaderAtomics())
3374 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
3375 
3376 #ifndef CTS_USES_VULKANSC
3377 	if (m_testConfig.depthBiasReprInfo)
3378 	{
3379 		const auto& reprInfo	= m_testConfig.depthBiasReprInfo.get();
3380 		const auto& dbcFeatures	= context.getDepthBiasControlFeaturesEXT();
3381 
3382 		if (reprInfo.depthBiasExact && !dbcFeatures.depthBiasExact)
3383 			TCU_THROW(NotSupportedError, "depthBiasExact not supported");
3384 
3385 		if (reprInfo.depthBiasRepresentation == vk::VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT
3386 			&& !dbcFeatures.leastRepresentableValueForceUnormRepresentation)
3387 		{
3388 			TCU_THROW(NotSupportedError, "leastRepresentableValueForceUnormRepresentation not supported");
3389 		}
3390 
3391 		if (reprInfo.depthBiasRepresentation == vk::VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT && !dbcFeatures.floatRepresentation)
3392 			TCU_THROW(NotSupportedError, "floatRepresentation not supported");
3393 	}
3394 #else
3395 	TCU_THROW(NotSupportedError, "VulkanSC does not support VK_EXT_depth_bias_control");
3396 #endif // CTS_USES_VULKANSC
3397 
3398 	if (m_testConfig.getActiveLineWidth() != 1.0f)
3399 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
3400 
3401 	if (m_testConfig.favorStaticNullPointers)
3402 	{
3403 		if (m_testConfig.primRestartEnableConfig.dynamicValue && m_testConfig.topologyConfig.dynamicValue)
3404 		{
3405 #ifndef CTS_USES_VULKANSC
3406 			const auto& eds3Properties = context.getExtendedDynamicState3PropertiesEXT();
3407 			if (!eds3Properties.dynamicPrimitiveTopologyUnrestricted)
3408 				TCU_THROW(NotSupportedError, "dynamicPrimitiveTopologyUnrestricted not supported");
3409 #else
3410 			TCU_THROW(NotSupportedError, "VulkanSC does not support VK_EXT_extended_dynamic_state3");
3411 #endif // CTS_USES_VULKANSC
3412 		}
3413 	}
3414 
3415 	if (m_testConfig.sampleShadingEnable && !baseFeatures.sampleRateShading)
3416 		TCU_THROW(NotSupportedError, "sampleRateShading not supported");
3417 
3418 	checkPipelineConstructionRequirements(vki, physicalDevice, m_testConfig.pipelineConstructionType);
3419 }
3420 
initPrograms(vk::SourceCollections & programCollection) const3421 void ExtendedDynamicStateTest::initPrograms (vk::SourceCollections& programCollection) const
3422 {
3423 	const vk::ShaderBuildOptions meshBuildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
3424 
3425 	std::ostringstream pushSource;
3426 	std::ostringstream fragOutputLocationStream;
3427 	std::ostringstream vertSourceTemplateStream;
3428 	std::ostringstream fragSourceTemplateStream;
3429 	std::ostringstream geomSource;
3430 	std::ostringstream tescSource;
3431 	std::ostringstream teseSource;
3432 	std::ostringstream meshSourceTemplateStream;
3433 
3434 	pushSource
3435 		<< "layout(push_constant, std430) uniform PushConstantsBlock {\n"
3436 		<< "    vec4  triangleColor;\n"
3437 		<< "    float depthValue;\n"
3438 		<< "    int   viewPortIndex;\n"
3439 		<< "    float scaleX;\n"
3440 		<< "    float scaleY;\n"
3441 		<< "    float offsetX;\n"
3442 		<< "    float offsetY;\n"
3443 		<< "    float stripScale;\n"
3444 		<< "} pushConstants;\n"
3445 		;
3446 	const auto pushConstants = pushSource.str();
3447 
3448 	const bool useAttIndex = m_testConfig.dualSrcBlend;
3449 	for (uint32_t refIdx = 0; refIdx < m_testConfig.colorAttachmentCount; ++refIdx)
3450 	{
3451 		const bool			used		= (refIdx == m_testConfig.colorAttachmentCount - 1u);
3452 		const std::string	attName		= (used ? "color" : "unused" + std::to_string(refIdx));
3453 		const uint32_t		indexCount	= (useAttIndex ? 2u : 1u);
3454 
3455 		for (uint32_t attIdx = 0u; attIdx < indexCount; ++attIdx)
3456 		{
3457 			const auto			idxStr		= std::to_string(attIdx);
3458 			const std::string	indexDecl	= (useAttIndex ? (", index=" + idxStr) : "");
3459 			const std::string	nameSuffix	= ((attIdx > 0u) ? idxStr : "");
3460 
3461 			fragOutputLocationStream << "layout(location=" << refIdx << indexDecl << ") out ${OUT_COLOR_VTYPE} " << attName << nameSuffix << ";\n";
3462 		}
3463 	}
3464 	const auto fragOutputLocations = fragOutputLocationStream.str();
3465 
3466 	// The actual generator, attributes and calculations.
3467 	const auto			topology	= m_testConfig.topologyClass();
3468 	const auto			activeGen	= m_testConfig.getActiveVertexGenerator();
3469 	const auto			attribDecls	= activeGen->getAttributeDeclarations();
3470 	const auto			coordCalcs	= activeGen->getVertexCoordCalc();
3471 	const auto			descDeclsV	= (m_testConfig.useMeshShaders ? activeGen->getDescriptorDeclarations() : std::vector<std::string>());
3472 	const auto			descCalcsV	= (m_testConfig.useMeshShaders ? activeGen->getDescriptorCoordCalc(topology) : std::vector<std::string>());
3473 	const auto			fragInputs	= activeGen->getFragInputAttributes();
3474 	const auto			fragCalcs	= activeGen->getFragOutputCalc();
3475 	const auto			glslExts	= activeGen->getGLSLExtensions();
3476 
3477 	// The static generator, attributes and calculations, for the static pipeline, if needed.
3478 	const auto			inactiveGen			= m_testConfig.getInactiveVertexGenerator();
3479 	const auto			staticAttribDec		= inactiveGen->getAttributeDeclarations();
3480 	const auto			staticCoordCalc		= inactiveGen->getVertexCoordCalc();
3481 	const auto			staticFragInputs	= inactiveGen->getFragInputAttributes();
3482 	const auto			staticFragCalcs		= inactiveGen->getFragOutputCalc();
3483 	const auto			staticGlslExts		= inactiveGen->getGLSLExtensions();
3484 
3485 	std::ostringstream	activeAttribs;
3486 	std::ostringstream	activeCalcs;
3487 	std::ostringstream	activeFragInputs;
3488 	std::ostringstream	activeFragCalcs;
3489 	std::ostringstream	activeExts;
3490 	std::ostringstream	inactiveAttribs;
3491 	std::ostringstream	inactiveCalcs;
3492 	std::ostringstream	descDecls;
3493 	std::ostringstream	descCalcs;
3494 	std::ostringstream	inactiveFragInputs;
3495 	std::ostringstream	inactiveFragCalcs;
3496 	std::ostringstream	inactiveExts;
3497 
3498 	for (const auto& decl : attribDecls)
3499 		activeAttribs << decl << "\n";
3500 
3501 	for (const auto& statement : coordCalcs)
3502 		activeCalcs << "    " << statement << "\n";
3503 
3504 	for (const auto& decl : staticAttribDec)
3505 		inactiveAttribs << decl << "\n";
3506 
3507 	for (const auto& statement : staticCoordCalc)
3508 		inactiveCalcs << "    " << statement << "\n";
3509 
3510 	for (const auto& decl : descDeclsV)
3511 		descDecls << decl << "\n";
3512 
3513 	for (const auto& calc : descCalcsV)
3514 		descCalcs << "    " << calc << "\n";
3515 
3516 	for (const auto& decl : fragInputs)
3517 		activeFragInputs << decl << "\n";
3518 
3519 	for (const auto& statement : fragCalcs)
3520 		activeFragCalcs << "    " << statement << "\n";
3521 
3522 	for (const auto& decl : staticFragInputs)
3523 		inactiveFragInputs << decl << "\n";
3524 
3525 	for (const auto& statement : staticFragCalcs)
3526 		inactiveFragCalcs << "    " << statement << "\n";
3527 
3528 	for (const auto& ext : glslExts)
3529 		activeExts << ext << "\n";
3530 
3531 	for (const auto& ext : staticGlslExts)
3532 		inactiveExts << ext << "\n";
3533 
3534 	vertSourceTemplateStream
3535 		<< "#version 450\n"
3536 		<< "${EXTENSIONS}"
3537 		<< pushConstants
3538 		<< "${ATTRIBUTES}"
3539 		<< "out gl_PerVertex\n"
3540 		<< "{\n"
3541 		<< "    vec4 gl_Position;\n"
3542 		<< "};\n"
3543 		<< "void main() {\n"
3544 		<< "${CALCULATIONS}"
3545 		<< "    gl_Position = vec4(vertexCoords.x * pushConstants.scaleX + pushConstants.offsetX, vertexCoords.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
3546 		<< "    vec2 stripOffset;\n"
3547 		<< "    switch (gl_VertexIndex) {\n"
3548 		<< "    case 0: stripOffset = vec2(0.0, 0.0); break;\n"
3549 		<< "    case 1: stripOffset = vec2(0.0, 1.0); break;\n"
3550 		<< "    case 2: stripOffset = vec2(1.0, 0.0); break;\n"
3551 		<< "    case 3: stripOffset = vec2(1.0, 1.0); break;\n"
3552 		<< "    case 4: stripOffset = vec2(2.0, 0.0); break;\n"
3553 		<< "    case 5: stripOffset = vec2(2.0, 1.0); break;\n"
3554 		<< "    default: stripOffset = vec2(-1000.0); break;\n"
3555 		<< "    }\n"
3556 		<< "    gl_Position.xy += pushConstants.stripScale * stripOffset;\n"
3557 		<< "}\n"
3558 		;
3559 
3560 	tcu::StringTemplate vertSourceTemplate (vertSourceTemplateStream.str());
3561 
3562 	const auto colorFormat	= m_testConfig.colorFormat();
3563 	const auto vecType		= (vk::isUnormFormat(colorFormat) ? "vec4" : "uvec4");
3564 	const auto fragSetIndex	= std::to_string(m_testConfig.getFragDescriptorSetIndex());
3565 	const auto fragAtomics	= m_testConfig.useFragShaderAtomics();
3566 
3567 	fragSourceTemplateStream
3568 		<< "#version 450\n"
3569 		<< (m_testConfig.representativeFragmentTest ? "layout(early_fragment_tests) in;\n" : "")
3570 		<< (fragAtomics ? "layout(set=" + fragSetIndex + ", binding=0, std430) buffer AtomicBlock { uint fragCounter; } counterBuffer;\n" : "")
3571 		<< pushConstants
3572 		<< fragOutputLocations
3573 		<< "${FRAG_INPUTS}"
3574 		<< "void main() {\n"
3575 		<< "    color = ${OUT_COLOR_VTYPE}" << (m_testConfig.dualSrcBlend ? de::toString(kOpaqueWhite) : "(pushConstants.triangleColor)") << ";\n"
3576 		;
3577 
3578 	if (m_testConfig.dualSrcBlend)
3579 	{
3580 		fragSourceTemplateStream
3581 			<< "    color1 = ${OUT_COLOR_VTYPE}(pushConstants.triangleColor);\n"
3582 			;
3583 	}
3584 
3585 	fragSourceTemplateStream
3586 		<< "${FRAG_CALCULATIONS}"
3587 		<< (fragAtomics ? "    atomicAdd(counterBuffer.fragCounter, 1u);\n" : "")
3588 		<< (m_testConfig.sampleShadingEnable ? "    uint sampleId = gl_SampleID;\n" : "") // Enable sample shading for shader objects by reading gl_SampleID
3589 		<< "}\n"
3590 		;
3591 
3592 	tcu::StringTemplate fragSourceTemplate (fragSourceTemplateStream.str());
3593 
3594 	std::map<std::string, std::string> activeMap;
3595 	std::map<std::string, std::string> inactiveMap;
3596 
3597 	activeMap["ATTRIBUTES"]			= activeAttribs.str();
3598 	activeMap["CALCULATIONS"]		= activeCalcs.str();
3599 	activeMap["FRAG_INPUTS"]		= activeFragInputs.str();
3600 	activeMap["FRAG_CALCULATIONS"]	= activeFragCalcs.str();
3601 	activeMap["EXTENSIONS"]			= activeExts.str();
3602 	activeMap["OUT_COLOR_VTYPE"]	= vecType;
3603 
3604 	inactiveMap["ATTRIBUTES"]			= inactiveAttribs.str();
3605 	inactiveMap["CALCULATIONS"]			= inactiveCalcs.str();
3606 	inactiveMap["FRAG_INPUTS"]			= inactiveFragInputs.str();
3607 	inactiveMap["FRAG_CALCULATIONS"]	= inactiveFragCalcs.str();
3608 	inactiveMap["EXTENSIONS"]			= inactiveExts.str();
3609 	inactiveMap["OUT_COLOR_VTYPE"]		= vecType;
3610 
3611 	const auto activeVertSource		= vertSourceTemplate.specialize(activeMap);
3612 	const auto activeFragSource		= fragSourceTemplate.specialize(activeMap);
3613 	const auto inactiveVertSource	= vertSourceTemplate.specialize(inactiveMap);
3614 	const auto inactiveFragSource	= fragSourceTemplate.specialize(inactiveMap);
3615 
3616 	if (m_testConfig.needsGeometryShader())
3617 	{
3618 		const auto			topologyClass	= getTopologyClass(m_testConfig.topologyConfig.staticValue);
3619 		const std::string	inputPrimitive	= ((topologyClass == TopologyClass::LINE) ? "lines" : "triangles");
3620 		const deUint32		vertexCount		= ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
3621 		const std::string	outputPrimitive	= ((topologyClass == TopologyClass::LINE) ? "line_strip" : "triangle_strip");
3622 		const auto			selectStream	= static_cast<bool>(m_testConfig.shaderRasterizationStream);
3623 		const auto			streamNumber	= (selectStream ? m_testConfig.shaderRasterizationStream.get() : 0u);
3624 		const auto			streamNumberStr	= de::toString(streamNumber);
3625 
3626 		geomSource
3627 			<< "#version 450\n"
3628 			<< "layout (" << inputPrimitive << ") in;\n"
3629 			<< "layout (" << outputPrimitive << ", max_vertices=" << vertexCount << ") out;\n"
3630 			<< (m_testConfig.isMultiViewport() ? pushConstants : "")
3631 			<< (selectStream ? "layout (stream=" + streamNumberStr + ") out;\n" : "")
3632 			<< "in gl_PerVertex\n"
3633 			<< "{\n"
3634 			<< "    vec4 gl_Position;\n"
3635 			<< "} gl_in[" << vertexCount << "];\n"
3636 			<< "out gl_PerVertex\n"
3637 			<< "{\n"
3638 			<< "    vec4 gl_Position;\n"
3639 			<< "};\n"
3640 			<< "void main() {\n"
3641 			<< (m_testConfig.isMultiViewport() ? "    gl_ViewportIndex = pushConstants.viewPortIndex;\n" : "")
3642 			;
3643 
3644 		for (deUint32 i = 0; i < vertexCount; ++i)
3645 		{
3646 			geomSource
3647 				<< "    gl_Position = gl_in[" << i << "].gl_Position;\n"
3648 				<< "    " << (selectStream ? ("EmitStreamVertex(" + streamNumberStr + ")") : "EmitVertex()") << ";\n"
3649 				;
3650 		}
3651 
3652 		geomSource
3653 			<< "}\n"
3654 			;
3655 	}
3656 
3657 	if (m_testConfig.needsTessellation())
3658 	{
3659 		tescSource
3660 			<< "#version 450\n"
3661 			<< "#extension GL_EXT_tessellation_shader : require\n"
3662 			<< "layout(vertices=3) out;\n"
3663 			<< "in gl_PerVertex\n"
3664 			<< "{\n"
3665 			<< "    vec4 gl_Position;\n"
3666 			<< "} gl_in[gl_MaxPatchVertices];\n"
3667 			<< "out gl_PerVertex\n"
3668 			<< "{\n"
3669 			<< "  vec4 gl_Position;\n"
3670 			<< "} gl_out[];\n"
3671 			<< "void main() {\n"
3672 			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3673 			<< "  gl_TessLevelOuter[0] = 3.0;\n"
3674 			<< "  gl_TessLevelOuter[1] = 3.0;\n"
3675 			<< "  gl_TessLevelOuter[2] = 3.0;\n"
3676 			<< "  gl_TessLevelInner[0] = 3.0;\n"
3677 			<< "}\n"
3678 			;
3679 		teseSource
3680 			<< "#version 450\n"
3681 			<< "#extension GL_EXT_tessellation_shader : require\n"
3682 			<< "layout(triangles) in;\n"
3683 			<< "in gl_PerVertex\n"
3684 			<< "{\n"
3685 			<< "  vec4 gl_Position;\n"
3686 			<< "} gl_in[gl_MaxPatchVertices];\n"
3687 			<< "out gl_PerVertex\n"
3688 			<< "{\n"
3689 			<< "  vec4 gl_Position;\n"
3690 			<< "};\n"
3691 			<< "void main() {\n"
3692 			<< "  gl_Position = (gl_in[0].gl_Position * gl_TessCoord.x + \n"
3693 			<< "                 gl_in[1].gl_Position * gl_TessCoord.y + \n"
3694 			<< "                 gl_in[2].gl_Position * gl_TessCoord.z);\n"
3695 			<< "}\n"
3696 			;
3697 	}
3698 
3699 #ifndef CTS_USES_VULKANSC
3700 	if (m_testConfig.useMeshShaders)
3701 	{
3702 		DE_ASSERT(!m_testConfig.needsGeometryShader());
3703 		DE_ASSERT(!m_testConfig.needsTessellation());
3704 		//DE_ASSERT(!m_testConfig.needsIndexBuffer());
3705 
3706 		// Make sure no dynamic states incompatible with mesh shading pipelines are used.
3707 		DE_ASSERT(!m_testConfig.badMeshShadingPipelineDynState());
3708 
3709 		// Shader below is designed to work with vertex buffers containing triangle strips as used by default.
3710 		DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ||
3711 				  m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP);
3712 		DE_ASSERT(!m_testConfig.singleVertex);
3713 
3714 		std::string	topologyStr;
3715 		std::string	indicesBuiltIn;
3716 		std::string	indicesVal;
3717 		uint32_t	maxVertices		= 0u;
3718 
3719 		switch (topology)
3720 		{
3721 		case TopologyClass::TRIANGLE:
3722 			topologyStr		= "triangles";
3723 			maxVertices		= 3u;
3724 			indicesBuiltIn	= "gl_PrimitiveTriangleIndicesEXT";
3725 			indicesVal		= "uvec3(0, 1, 2)";
3726 			break;
3727 		case TopologyClass::LINE:
3728 			topologyStr		= "lines";
3729 			maxVertices		= 2u;
3730 			indicesBuiltIn	= "gl_PrimitiveLineIndicesEXT";
3731 			indicesVal		= "uvec2(0, 1)";
3732 			break;
3733 		default:
3734 			DE_ASSERT(false);
3735 			break;
3736 		}
3737 
3738 		meshSourceTemplateStream
3739 			<< "#version 450\n"
3740 			<< "${EXTENSIONS}"
3741 			<< "#extension GL_EXT_mesh_shader : enable\n"
3742 			<< "layout(local_size_x=" << maxVertices << ", local_size_y=1, local_size_z=1) in;\n"
3743 			<< "layout(" << topologyStr << ") out;\n"
3744 			<< "layout(max_vertices=" << maxVertices << ", max_primitives=1) out;\n"
3745 			<< pushConstants
3746 			<< (m_testConfig.isMultiViewport()
3747 				? "perprimitiveEXT out gl_MeshPerPrimitiveEXT { int gl_ViewportIndex; } gl_MeshPrimitivesEXT[];\n"
3748 				: "")
3749 			<< descDecls.str()
3750 			<< "void main() {\n"
3751 			<< descCalcs.str()
3752 			<< "    SetMeshOutputsEXT(" << maxVertices << "u, 1u);\n"
3753 			<< "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(vertexCoords.x * pushConstants.scaleX + pushConstants.offsetX, vertexCoords.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
3754 			<< "    if (gl_LocalInvocationIndex == 0u) {\n"
3755 			<< "        " << indicesBuiltIn << "[0] = " << indicesVal << ";\n"
3756 			<< (m_testConfig.isMultiViewport()
3757 				? "        gl_MeshPrimitivesEXT[0].gl_ViewportIndex = pushConstants.viewPortIndex;\n"
3758 				: "")
3759 			<< "    }\n"
3760 			<< "}\n"
3761 			;
3762 	}
3763 #endif // CTS_USES_VULKANSC
3764 
3765 	// In reversed test configurations, the pipeline with dynamic state needs to have the inactive shader.
3766 	const auto kReversed = m_testConfig.isReversed();
3767 	programCollection.glslSources.add("dynamicVert")	<< glu::VertexSource(kReversed ? inactiveVertSource : activeVertSource);
3768 	programCollection.glslSources.add("staticVert")		<< glu::VertexSource(kReversed ? activeVertSource : inactiveVertSource);
3769 	programCollection.glslSources.add("dynamicFrag")	<< glu::FragmentSource(kReversed ? inactiveFragSource : activeFragSource);
3770 	programCollection.glslSources.add("staticFrag")		<< glu::FragmentSource(kReversed ? activeFragSource : inactiveFragSource);
3771 
3772 	if (m_testConfig.needsGeometryShader())
3773 		programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource.str());
3774 	if (m_testConfig.needsTessellation())
3775 	{
3776 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSource.str());
3777 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSource.str());
3778 	}
3779 	if (m_testConfig.useMeshShaders)
3780 	{
3781 		tcu::StringTemplate meshSourceTemplate (meshSourceTemplateStream.str());
3782 
3783 		const auto activeMeshSource		= meshSourceTemplate.specialize(activeMap);
3784 		const auto inactiveMeshSource	= meshSourceTemplate.specialize(inactiveMap);
3785 
3786 		programCollection.glslSources.add("dynamicMesh")	<< glu::MeshSource(kReversed ? inactiveMeshSource : activeMeshSource) << meshBuildOptions;
3787 		programCollection.glslSources.add("staticMesh")		<< glu::MeshSource(kReversed ? activeMeshSource : inactiveMeshSource) << meshBuildOptions;
3788 	}
3789 
3790 	if (m_testConfig.bindUnusedMeshShadingPipeline)
3791 	{
3792 		std::ostringstream meshNoOut;
3793 		meshNoOut
3794 			<< "#version 450\n"
3795 			<< "#extension GL_EXT_mesh_shader : enable\n"
3796 			<< "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
3797 			<< "layout(triangles) out;\n"
3798 			<< "layout(max_vertices=3, max_primitives=1) out;\n"
3799 			<< "void main() {\n"
3800 			<< "    SetMeshOutputsEXT(0u, 0u);\n"
3801 			<< "}\n"
3802 			;
3803 		programCollection.glslSources.add("meshNoOut") << glu::MeshSource(meshNoOut.str()) << meshBuildOptions;
3804 	}
3805 
3806 	// Extra vert and frag shaders for the extra patch control points pipeline. These draw offscreen.
3807 	if (m_testConfig.useExtraDynPCPPipeline || m_testConfig.useExtraDynPipeline)
3808 	{
3809 		std::ostringstream vertDPCP;
3810 		vertDPCP
3811 			<< "#version 450\n"
3812 			<< "\n"
3813 			<< "vec2 positions[3] = vec2[](\n"
3814 			<< "    vec2(-1.0, -1.0),\n"
3815 			<< "    vec2( 3.0, -1.0),\n"
3816 			<< "    vec2(-1.0,  3.0)\n"
3817 			<< ");\n"
3818 			<< "\n"
3819 			<< "void main() {\n"
3820 			<< "    gl_Position = vec4(positions[gl_VertexIndex] + 10.0 + 1.0 * float(gl_VertexIndex), 0.0, 1.0);\n"
3821 			<< "}\n"
3822 			;
3823 		programCollection.glslSources.add("vertDPCP") << glu::VertexSource(vertDPCP.str());
3824 
3825 		std::ostringstream fragDPCP;
3826 		fragDPCP
3827 			<< "#version 450\n"
3828 			<< "layout(location=0) out " << vecType << " color;\n"
3829 			<< "void main() {\n"
3830 			<< "    color = " << vecType << "(1.0, 1.0, 1.0, 1.0);\n"
3831 			<< "}\n"
3832 			;
3833 		programCollection.glslSources.add("fragDPCP") << glu::FragmentSource(fragDPCP.str());
3834 	}
3835 }
3836 
createInstance(Context & context) const3837 TestInstance* ExtendedDynamicStateTest::createInstance (Context& context) const
3838 {
3839 	return new ExtendedDynamicStateInstance(context, m_testConfig);
3840 }
3841 
ExtendedDynamicStateInstance(Context & context,const TestConfig & testConfig)3842 ExtendedDynamicStateInstance::ExtendedDynamicStateInstance(Context& context, const TestConfig& testConfig)
3843 	: vkt::TestInstance	(context)
3844 	, m_testConfig		(testConfig)
3845 {
3846 }
3847 
3848 using BufferWithMemoryPtr = de::MovePtr<vk::BufferWithMemory>;
3849 
3850 struct VertexBufferInfo
3851 {
VertexBufferInfovkt::pipeline::__anon5f321d180111::VertexBufferInfo3852 	VertexBufferInfo ()
3853 		: buffer	()
3854 		, offset	(0ull)
3855 		, dataSize	(0ull)
3856 	{}
3857 
VertexBufferInfovkt::pipeline::__anon5f321d180111::VertexBufferInfo3858 	VertexBufferInfo (VertexBufferInfo&& other)
3859 		: buffer	(other.buffer.release())
3860 		, offset	(other.offset)
3861 		, dataSize	(other.dataSize)
3862 	{}
3863 
3864 	BufferWithMemoryPtr	buffer;
3865 	vk::VkDeviceSize	offset;
3866 	vk::VkDeviceSize	dataSize;
3867 };
3868 
logErrors(tcu::TestLog & log,const std::string & setName,const std::string & setDesc,const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & errorMask)3869 void logErrors(tcu::TestLog& log, const std::string& setName, const std::string& setDesc, const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& errorMask)
3870 {
3871 	log << tcu::TestLog::ImageSet(setName, setDesc)
3872 		<< tcu::TestLog::Image(setName + "Result", "Result image", result)
3873 		<< tcu::TestLog::Image(setName + "ErrorMask", "Error mask with errors marked in red", errorMask)
3874 		<< tcu::TestLog::EndImageSet;
3875 }
3876 
copyAndFlush(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::BufferWithMemory & buffer,size_t offset,const void * src,size_t size)3877 void copyAndFlush(const vk::DeviceInterface& vkd, vk::VkDevice device, vk::BufferWithMemory& buffer, size_t offset, const void* src, size_t size)
3878 {
3879 	auto&	alloc	= buffer.getAllocation();
3880 	auto	dst		= reinterpret_cast<char*>(alloc.getHostPtr());
3881 
3882 	deMemcpy(dst + offset, src, size);
3883 	vk::flushAlloc(vkd, device, alloc);
3884 }
3885 
3886 // Sets values for dynamic states if needed according to the test configuration.
setDynamicStates(const TestConfig & testConfig,const vk::DeviceInterface & vkd,vk::VkCommandBuffer cmdBuffer)3887 void setDynamicStates(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer)
3888 {
3889 	if (testConfig.lineWidthConfig.dynamicValue)
3890 		vkd.cmdSetLineWidth(cmdBuffer, testConfig.lineWidthConfig.dynamicValue.get());
3891 
3892 	if (testConfig.depthBoundsConfig.dynamicValue)
3893 	{
3894 		const auto& minMaxDepth = testConfig.depthBoundsConfig.dynamicValue.get();
3895 		vkd.cmdSetDepthBounds(cmdBuffer, minMaxDepth.first, minMaxDepth.second);
3896 	}
3897 
3898 	if (testConfig.cullModeConfig.dynamicValue)
3899 #ifndef CTS_USES_VULKANSC
3900 		vkd.cmdSetCullMode(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
3901 #else
3902 		vkd.cmdSetCullModeEXT(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
3903 #endif // CTS_USES_VULKANSC
3904 
3905 	if (testConfig.frontFaceConfig.dynamicValue)
3906 #ifndef CTS_USES_VULKANSC
3907 		vkd.cmdSetFrontFace(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
3908 #else
3909 		vkd.cmdSetFrontFaceEXT(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
3910 #endif // CTS_USES_VULKANSC
3911 
3912 	if (testConfig.topologyConfig.dynamicValue)
3913 #ifndef CTS_USES_VULKANSC
3914 		vkd.cmdSetPrimitiveTopology(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
3915 #else
3916 		vkd.cmdSetPrimitiveTopologyEXT(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
3917 #endif // CTS_USES_VULKANSC
3918 
3919 	if (testConfig.viewportConfig.dynamicValue)
3920 	{
3921 		const auto& viewports = testConfig.viewportConfig.dynamicValue.get();
3922 #ifndef CTS_USES_VULKANSC
3923 		vkd.cmdSetViewportWithCount(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
3924 #else
3925 		vkd.cmdSetViewportWithCountEXT(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
3926 #endif // CTS_USES_VULKANSC
3927 	}
3928 
3929 	if (testConfig.scissorConfig.dynamicValue)
3930 	{
3931 		const auto& scissors = testConfig.scissorConfig.dynamicValue.get();
3932 #ifndef CTS_USES_VULKANSC
3933 		vkd.cmdSetScissorWithCount(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
3934 #else
3935 		vkd.cmdSetScissorWithCountEXT(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
3936 #endif // CTS_USES_VULKANSC
3937 	}
3938 
3939 	if (testConfig.depthTestEnableConfig.dynamicValue)
3940 #ifndef CTS_USES_VULKANSC
3941 		vkd.cmdSetDepthTestEnable(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
3942 #else
3943 		vkd.cmdSetDepthTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
3944 #endif // CTS_USES_VULKANSC
3945 
3946 	if (testConfig.depthWriteEnableConfig.dynamicValue)
3947 #ifndef CTS_USES_VULKANSC
3948 		vkd.cmdSetDepthWriteEnable(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
3949 #else
3950 		vkd.cmdSetDepthWriteEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
3951 #endif // CTS_USES_VULKANSC
3952 
3953 	if (testConfig.depthCompareOpConfig.dynamicValue)
3954 #ifndef CTS_USES_VULKANSC
3955 		vkd.cmdSetDepthCompareOp(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
3956 #else
3957 		vkd.cmdSetDepthCompareOpEXT(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
3958 #endif // CTS_USES_VULKANSC
3959 
3960 	if (testConfig.depthBoundsTestEnableConfig.dynamicValue)
3961 #ifndef CTS_USES_VULKANSC
3962 		vkd.cmdSetDepthBoundsTestEnable(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
3963 #else
3964 		vkd.cmdSetDepthBoundsTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
3965 #endif // CTS_USES_VULKANSC
3966 
3967 	if (testConfig.stencilTestEnableConfig.dynamicValue)
3968 #ifndef CTS_USES_VULKANSC
3969 		vkd.cmdSetStencilTestEnable(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
3970 #else
3971 		vkd.cmdSetStencilTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
3972 #endif // CTS_USES_VULKANSC
3973 
3974 	if (testConfig.depthBiasEnableConfig.dynamicValue)
3975 #ifndef CTS_USES_VULKANSC
3976 		vkd.cmdSetDepthBiasEnable(cmdBuffer, makeVkBool32(testConfig.depthBiasEnableConfig.dynamicValue.get()));
3977 #else
3978 		vkd.cmdSetDepthBiasEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBiasEnableConfig.dynamicValue.get()));
3979 #endif // CTS_USES_VULKANSC
3980 
3981 	if (testConfig.depthBiasConfig.dynamicValue)
3982 	{
3983 		const auto& bias = testConfig.depthBiasConfig.dynamicValue.get();
3984 
3985 #ifndef CTS_USES_VULKANSC
3986 		if (testConfig.depthBiasReprInfo && !testConfig.isReversed())
3987 		{
3988 			vk::VkDepthBiasInfoEXT depthBiasInfo	= vk::initVulkanStructureConst(&testConfig.depthBiasReprInfo.get());
3989 			depthBiasInfo.depthBiasConstantFactor	= bias.constantFactor;
3990 			depthBiasInfo.depthBiasClamp			= bias.clamp;
3991 
3992 			vkd.cmdSetDepthBias2EXT(cmdBuffer, &depthBiasInfo);
3993 		}
3994 		else
3995 #endif // CTS_USES_VULKANSC
3996 		{
3997 			vkd.cmdSetDepthBias(cmdBuffer, bias.constantFactor, bias.clamp, 0.0f);
3998 		}
3999 	}
4000 
4001 	if (testConfig.rastDiscardEnableConfig.dynamicValue)
4002 #ifndef CTS_USES_VULKANSC
4003 		vkd.cmdSetRasterizerDiscardEnable(cmdBuffer, makeVkBool32(testConfig.rastDiscardEnableConfig.dynamicValue.get()));
4004 #else
4005 		vkd.cmdSetRasterizerDiscardEnableEXT(cmdBuffer, makeVkBool32(testConfig.rastDiscardEnableConfig.dynamicValue.get()));
4006 #endif // CTS_USES_VULKANSC
4007 
4008 	if (testConfig.primRestartEnableConfig.dynamicValue)
4009 #ifndef CTS_USES_VULKANSC
4010 		vkd.cmdSetPrimitiveRestartEnable(cmdBuffer, makeVkBool32(testConfig.primRestartEnableConfig.dynamicValue.get()));
4011 #else
4012 		vkd.cmdSetPrimitiveRestartEnableEXT(cmdBuffer, makeVkBool32(testConfig.primRestartEnableConfig.dynamicValue.get()));
4013 #endif // CTS_USES_VULKANSC
4014 
4015 	if (testConfig.logicOpConfig.dynamicValue)
4016 		vkd.cmdSetLogicOpEXT(cmdBuffer, testConfig.logicOpConfig.dynamicValue.get());
4017 
4018 	if (testConfig.patchControlPointsConfig.dynamicValue)
4019 		vkd.cmdSetPatchControlPointsEXT(cmdBuffer, testConfig.patchControlPointsConfig.dynamicValue.get());
4020 
4021 	if (testConfig.stencilOpConfig.dynamicValue)
4022 	{
4023 		for (const auto& params : testConfig.stencilOpConfig.dynamicValue.get())
4024 #ifndef CTS_USES_VULKANSC
4025 			vkd.cmdSetStencilOp(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
4026 #else
4027 			vkd.cmdSetStencilOpEXT(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
4028 #endif // CTS_USES_VULKANSC
4029 	}
4030 
4031 	if (testConfig.vertexGenerator.dynamicValue)
4032 	{
4033 		const auto generator	= testConfig.vertexGenerator.dynamicValue.get();
4034 		const auto bindings		= generator->getBindingDescriptions2(testConfig.strideConfig.staticValue);
4035 		const auto attributes	= generator->getAttributeDescriptions2();
4036 
4037 		vkd.cmdSetVertexInputEXT(cmdBuffer,
4038 			static_cast<deUint32>(bindings.size()), de::dataOrNull(bindings),
4039 			static_cast<deUint32>(attributes.size()), de::dataOrNull(attributes));
4040 	}
4041 
4042 	if (testConfig.colorWriteEnableConfig.dynamicValue)
4043 	{
4044 		const std::vector<vk::VkBool32> colorWriteEnableValues (testConfig.colorAttachmentCount, makeVkBool32(testConfig.colorWriteEnableConfig.dynamicValue.get()));
4045 		vkd.cmdSetColorWriteEnableEXT(cmdBuffer, de::sizeU32(colorWriteEnableValues), de::dataOrNull(colorWriteEnableValues));
4046 	}
4047 
4048 	if (testConfig.blendConstantsConfig.dynamicValue)
4049 		vkd.cmdSetBlendConstants(cmdBuffer, testConfig.blendConstantsConfig.dynamicValue.get().data());
4050 
4051 	if (testConfig.lineStippleParamsConfig.dynamicValue && static_cast<bool>(testConfig.lineStippleParamsConfig.dynamicValue.get()))
4052 	{
4053 		const auto& stippleParams = testConfig.lineStippleParamsConfig.dynamicValue->get();
4054 		vkd.cmdSetLineStippleEXT(cmdBuffer, stippleParams.factor, stippleParams.pattern);
4055 	}
4056 
4057 #ifndef CTS_USES_VULKANSC
4058 	if (testConfig.tessDomainOriginConfig.dynamicValue)
4059 		vkd.cmdSetTessellationDomainOriginEXT(cmdBuffer, testConfig.tessDomainOriginConfig.dynamicValue.get());
4060 
4061 	if (testConfig.depthClampEnableConfig.dynamicValue)
4062 		vkd.cmdSetDepthClampEnableEXT(cmdBuffer, testConfig.depthClampEnableConfig.dynamicValue.get());
4063 
4064 	if (testConfig.polygonModeConfig.dynamicValue)
4065 		vkd.cmdSetPolygonModeEXT(cmdBuffer, testConfig.polygonModeConfig.dynamicValue.get());
4066 
4067 	if (testConfig.rasterizationSamplesConfig.dynamicValue)
4068 		vkd.cmdSetRasterizationSamplesEXT(cmdBuffer, testConfig.rasterizationSamplesConfig.dynamicValue.get());
4069 
4070 	if (testConfig.sampleMaskConfig.dynamicValue)
4071 	{
4072 		const auto sampleCount	= (static_cast<bool>(testConfig.dynamicSampleMaskCount)
4073 								? testConfig.dynamicSampleMaskCount.get()
4074 								: testConfig.getActiveSampleCount());
4075 		vkd.cmdSetSampleMaskEXT(cmdBuffer, sampleCount, testConfig.sampleMaskConfig.dynamicValue.get().data());
4076 	}
4077 
4078 	if (testConfig.alphaToCoverageConfig.dynamicValue)
4079 		vkd.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, makeVkBool32(testConfig.alphaToCoverageConfig.dynamicValue.get()));
4080 
4081 	if (testConfig.alphaToOneConfig.dynamicValue)
4082 		vkd.cmdSetAlphaToOneEnableEXT(cmdBuffer, makeVkBool32(testConfig.alphaToOneConfig.dynamicValue.get()));
4083 
4084 	if (testConfig.colorWriteMaskConfig.dynamicValue)
4085 	{
4086 		const std::vector<vk::VkColorComponentFlags> writeMasks (testConfig.colorAttachmentCount, testConfig.colorWriteMaskConfig.dynamicValue.get());
4087 		vkd.cmdSetColorWriteMaskEXT(cmdBuffer, 0u, de::sizeU32(writeMasks), de::dataOrNull(writeMasks));
4088 	}
4089 
4090 	if (testConfig.rasterizationStreamConfig.dynamicValue && static_cast<bool>(testConfig.rasterizationStreamConfig.dynamicValue.get()))
4091 		vkd.cmdSetRasterizationStreamEXT(cmdBuffer, testConfig.rasterizationStreamConfig.dynamicValue->get());
4092 
4093 	if (testConfig.logicOpEnableConfig.dynamicValue)
4094 		vkd.cmdSetLogicOpEnableEXT(cmdBuffer, makeVkBool32(testConfig.logicOpEnableConfig.dynamicValue.get()));
4095 
4096 	if (testConfig.colorBlendEnableConfig.dynamicValue)
4097 	{
4098 		const auto colorBlendEnableFlag = makeVkBool32(testConfig.colorBlendEnableConfig.dynamicValue.get());
4099 		const std::vector<vk::VkBool32> flags (testConfig.colorAttachmentCount, colorBlendEnableFlag);
4100 		vkd.cmdSetColorBlendEnableEXT(cmdBuffer, 0u, de::sizeU32(flags), de::dataOrNull(flags));
4101 	}
4102 
4103 	if (testConfig.colorBlendEquationConfig.dynamicValue)
4104 	{
4105 		const auto&	configEq	= testConfig.colorBlendEquationConfig.dynamicValue.get();
4106 		const auto	isAdvanced	= testConfig.colorBlendEquationConfig.staticValue.isAdvanced();
4107 
4108 		if (isAdvanced || testConfig.colorBlendBoth || testConfig.nullStaticColorBlendAttPtr)
4109 		{
4110 			const vk::VkColorBlendAdvancedEXT equation =
4111 			{
4112 				configEq.colorBlendOp,					//	VkBlendOp			advancedBlendOp;
4113 				VK_TRUE,								//	VkBool32			srcPremultiplied;
4114 				VK_TRUE,								//	VkBool32			dstPremultiplied;
4115 				vk::VK_BLEND_OVERLAP_UNCORRELATED_EXT,	//	VkBlendOverlapEXT	blendOverlap;
4116 				VK_FALSE,								//	VkBool32			clampResults;
4117 			};
4118 			const std::vector<vk::VkColorBlendAdvancedEXT> equations (testConfig.colorAttachmentCount, equation);
4119 			vkd.cmdSetColorBlendAdvancedEXT(cmdBuffer, 0u, de::sizeU32(equations), de::dataOrNull(equations));
4120 		}
4121 
4122 		if (!isAdvanced || testConfig.colorBlendBoth)
4123 		{
4124 			// VUID-VkColorBlendEquationEXT-colorBlendOp-07361 forbids colorBlendOp and alphaBlendOp to be any advanced operation.
4125 			// When the advanced blend op will be set by vkCmdSetColorBlendAdvancedEXT, we use a legal placeholder in this call.
4126 			vk::VkBlendOp colorBlendOp = vk::VK_BLEND_OP_ADD;
4127 			vk::VkBlendOp alphaBlendOp = vk::VK_BLEND_OP_ADD;
4128 
4129 			if (!isAdvanced)
4130 			{
4131 				colorBlendOp = configEq.colorBlendOp;
4132 				alphaBlendOp = configEq.alphaBlendOp;
4133 			}
4134 
4135 			const vk::VkColorBlendEquationEXT equation =
4136 			{
4137 				configEq.srcColorBlendFactor,	//	VkBlendFactor	srcColorBlendFactor;
4138 				configEq.dstColorBlendFactor,	//	VkBlendFactor	dstColorBlendFactor;
4139 				colorBlendOp,					//	VkBlendOp		colorBlendOp;
4140 				configEq.srcAlphaBlendFactor,	//	VkBlendFactor	srcAlphaBlendFactor;
4141 				configEq.dstAlphaBlendFactor,	//	VkBlendFactor	dstAlphaBlendFactor;
4142 				alphaBlendOp,					//	VkBlendOp		alphaBlendOp;
4143 			};
4144 			const std::vector<vk::VkColorBlendEquationEXT> equations (testConfig.colorAttachmentCount, equation);
4145 			vkd.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, de::sizeU32(equations), de::dataOrNull(equations));
4146 		}
4147 	}
4148 
4149 	if (testConfig.provokingVertexConfig.dynamicValue && static_cast<bool>(testConfig.provokingVertexConfig.dynamicValue.get()))
4150 	{
4151 		const auto provokingVertexMode = makeProvokingVertexMode(testConfig.provokingVertexConfig.dynamicValue->get());
4152 		vkd.cmdSetProvokingVertexModeEXT(cmdBuffer, provokingVertexMode);
4153 	}
4154 
4155 	if (testConfig.negativeOneToOneConfig.dynamicValue && static_cast<bool>(testConfig.negativeOneToOneConfig.dynamicValue.get()))
4156 		vkd.cmdSetDepthClipNegativeOneToOneEXT(cmdBuffer, makeVkBool32(testConfig.negativeOneToOneConfig.dynamicValue->get()));
4157 
4158 	if (testConfig.depthClipEnableConfig.dynamicValue && static_cast<bool>(testConfig.depthClipEnableConfig.dynamicValue.get()))
4159 		vkd.cmdSetDepthClipEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthClipEnableConfig.dynamicValue->get()));
4160 
4161 	if (testConfig.lineStippleEnableConfig.dynamicValue)
4162 		vkd.cmdSetLineStippleEnableEXT(cmdBuffer, makeVkBool32(testConfig.lineStippleEnableConfig.dynamicValue.get()));
4163 
4164 	if (testConfig.sampleLocationsEnableConfig.dynamicValue)
4165 		vkd.cmdSetSampleLocationsEnableEXT(cmdBuffer, makeVkBool32(testConfig.sampleLocationsEnableConfig.dynamicValue.get()));
4166 
4167 	if (testConfig.conservativeRasterModeConfig.dynamicValue)
4168 		vkd.cmdSetConservativeRasterizationModeEXT(cmdBuffer, testConfig.conservativeRasterModeConfig.dynamicValue.get());
4169 
4170 	if (testConfig.extraPrimitiveOverEstConfig.dynamicValue)
4171 		vkd.cmdSetExtraPrimitiveOverestimationSizeEXT(cmdBuffer, testConfig.extraPrimitiveOverEstConfig.dynamicValue.get());
4172 
4173 	if (testConfig.lineRasterModeConfig.dynamicValue && static_cast<bool>(testConfig.lineRasterModeConfig.dynamicValue.get()))
4174 		vkd.cmdSetLineRasterizationModeEXT(cmdBuffer, makeLineRasterizationMode(testConfig.lineRasterModeConfig.dynamicValue->get()));
4175 
4176 	if (testConfig.coverageToColorEnableConfig.dynamicValue)
4177 		vkd.cmdSetCoverageToColorEnableNV(cmdBuffer, makeVkBool32(testConfig.coverageToColorEnableConfig.dynamicValue.get()));
4178 
4179 	if (testConfig.coverageToColorLocationConfig.dynamicValue)
4180 		vkd.cmdSetCoverageToColorLocationNV(cmdBuffer, testConfig.coverageToColorLocationConfig.dynamicValue.get());
4181 
4182 	if (testConfig.coverageModulationModeConfig.dynamicValue)
4183 		vkd.cmdSetCoverageModulationModeNV(cmdBuffer, testConfig.coverageModulationModeConfig.dynamicValue.get());
4184 
4185 	if (testConfig.coverageModTableEnableConfig.dynamicValue)
4186 		vkd.cmdSetCoverageModulationTableEnableNV(cmdBuffer, makeVkBool32(testConfig.coverageModTableEnableConfig.dynamicValue.get()));
4187 
4188 	if (testConfig.coverageModTableConfig.dynamicValue)
4189 	{
4190 		const auto& tableVec = testConfig.coverageModTableConfig.dynamicValue.get();
4191 		vkd.cmdSetCoverageModulationTableNV(cmdBuffer, static_cast<uint32_t>(tableVec.size()), de::dataOrNull(tableVec));
4192 	}
4193 
4194 	if (testConfig.coverageReductionModeConfig.dynamicValue)
4195 		vkd.cmdSetCoverageReductionModeNV(cmdBuffer, testConfig.coverageReductionModeConfig.dynamicValue.get());
4196 
4197 	if (testConfig.viewportSwizzleConfig.dynamicValue)
4198 	{
4199 		const auto& viewportSwizzleVec = testConfig.viewportSwizzleConfig.dynamicValue.get();
4200 		vkd.cmdSetViewportSwizzleNV(cmdBuffer, 0u, static_cast<uint32_t>(viewportSwizzleVec.size()), de::dataOrNull(viewportSwizzleVec));
4201 	}
4202 
4203 	if (testConfig.shadingRateImageEnableConfig.dynamicValue)
4204 		vkd.cmdSetShadingRateImageEnableNV(cmdBuffer, makeVkBool32(testConfig.shadingRateImageEnableConfig.dynamicValue.get()));
4205 
4206 	if (testConfig.viewportWScalingEnableConfig.dynamicValue)
4207 		vkd.cmdSetViewportWScalingEnableNV(cmdBuffer, makeVkBool32(testConfig.viewportWScalingEnableConfig.dynamicValue.get()));
4208 
4209 	if (testConfig.reprFragTestEnableConfig.dynamicValue)
4210 		vkd.cmdSetRepresentativeFragmentTestEnableNV(cmdBuffer, makeVkBool32(testConfig.reprFragTestEnableConfig.dynamicValue.get()));
4211 
4212 #endif // CTS_USES_VULKANSC
4213 }
4214 
4215 // Bind the appropriate vertex buffers using dynamic strides if the test configuration needs a dynamic stride.
4216 // Return true if the vertex buffer was bound.
maybeBindVertexBufferDynStride(const TestConfig & testConfig,const vk::DeviceInterface & vkd,vk::VkCommandBuffer cmdBuffer,size_t meshIdx,const std::vector<VertexBufferInfo> & vertBuffers,const std::vector<VertexBufferInfo> & rvertBuffers)4217 bool maybeBindVertexBufferDynStride(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer, size_t meshIdx, const std::vector<VertexBufferInfo>& vertBuffers, const std::vector<VertexBufferInfo>& rvertBuffers)
4218 {
4219 	if (!testConfig.strideConfig.dynamicValue)
4220 		return false;
4221 
4222 	DE_ASSERT(!testConfig.useMeshShaders);
4223 
4224 	const auto& viewportVec = testConfig.getActiveViewportVec();
4225 	DE_UNREF(viewportVec); // For release builds.
4226 
4227 	// When dynamically setting the vertex buffer stride, we cannot bind the vertex buffer in advance for some sequence
4228 	// orderings if we have several viewports or meshes.
4229 	DE_ASSERT((viewportVec.size() == 1u && testConfig.meshParams.size() == 1u)
4230 				|| testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW
4231 				|| testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
4232 
4233 	// Split buffers, offsets, sizes and strides into their own vectors for the call.
4234 	std::vector<vk::VkBuffer>		buffers;
4235 	std::vector<vk::VkDeviceSize>	offsets;
4236 	std::vector<vk::VkDeviceSize>	sizes;
4237 	const auto						strides = testConfig.strideConfig.dynamicValue.get();
4238 
4239 	const auto& chosenBuffers = (testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers);
4240 
4241 	buffers.reserve	(chosenBuffers.size());
4242 	offsets.reserve	(chosenBuffers.size());
4243 	sizes.reserve	(chosenBuffers.size());
4244 	DE_ASSERT(chosenBuffers.size() == strides.size());
4245 
4246 	for (const auto& vertBuffer : chosenBuffers)
4247 	{
4248 		buffers.push_back	(vertBuffer.buffer->get());
4249 		offsets.push_back	(vertBuffer.offset);
4250 		sizes.push_back		(vertBuffer.dataSize);
4251 	}
4252 
4253 #ifndef CTS_USES_VULKANSC
4254 	vkd.cmdBindVertexBuffers2(cmdBuffer, 0u, static_cast<deUint32>(chosenBuffers.size()), buffers.data(), offsets.data(), sizes.data(), strides.data());
4255 #else
4256 	vkd.cmdBindVertexBuffers2EXT(cmdBuffer, 0u, static_cast<deUint32>(chosenBuffers.size()), buffers.data(), offsets.data(), sizes.data(), strides.data());
4257 #endif // CTS_USES_VULKANSC
4258 
4259 	return true;
4260 }
4261 
4262 // Bind the given vertex buffers with the non-dynamic call. Similar to maybeBindVertexBufferDynStride but simpler.
bindVertexBuffers(const vk::DeviceInterface & vkd,vk::VkCommandBuffer cmdBuffer,const std::vector<VertexBufferInfo> & vertexBuffers)4263 void bindVertexBuffers (const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer, const std::vector<VertexBufferInfo>& vertexBuffers)
4264 {
4265 	std::vector<vk::VkBuffer>		buffers;
4266 	std::vector<vk::VkDeviceSize>	offsets;
4267 
4268 	buffers.reserve	(vertexBuffers.size());
4269 	offsets.reserve	(vertexBuffers.size());
4270 
4271 	for (const auto& vertBuffer : vertexBuffers)
4272 	{
4273 		buffers.push_back	(vertBuffer.buffer->get());
4274 		offsets.push_back	(vertBuffer.offset);
4275 	}
4276 
4277 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, static_cast<deUint32>(vertexBuffers.size()), buffers.data(), offsets.data());
4278 }
4279 
4280 // Create a vector of VertexBufferInfo elements using the given vertex generator and set of vertices.
prepareVertexBuffers(std::vector<VertexBufferInfo> & buffers,const vk::DeviceInterface & vkd,vk::VkDevice device,vk::Allocator & allocator,const VertexGenerator * generator,const std::vector<tcu::Vec2> & vertices,deUint32 dataOffset,deUint32 trailingSize,bool ssbos)4281 void prepareVertexBuffers (	std::vector<VertexBufferInfo>&	buffers,
4282 							const vk::DeviceInterface&		vkd,
4283 							vk::VkDevice					device,
4284 							vk::Allocator&					allocator,
4285 							const VertexGenerator*			generator,
4286 							const std::vector<tcu::Vec2>&	vertices,
4287 							deUint32						dataOffset,
4288 							deUint32						trailingSize,
4289 							bool							ssbos)
4290 {
4291 	const deUint32	paddingBytes	= 0xDEADBEEFu;
4292 	const auto		vertexData		= generator->createVertexData(vertices, dataOffset, trailingSize, &paddingBytes, sizeof(paddingBytes));
4293 
4294 	for (const auto& bufferBytes : vertexData)
4295 	{
4296 		const auto bufferSize	= static_cast<vk::VkDeviceSize>(de::dataSize(bufferBytes));
4297 		const auto extraSize	= static_cast<vk::VkDeviceSize>(dataOffset + trailingSize);
4298 		DE_ASSERT(bufferSize > extraSize);
4299 		const auto dataSize		= bufferSize - extraSize;
4300 
4301 		// Create a full-size buffer but remember the data size and offset for it.
4302 		const auto createInfo = vk::makeBufferCreateInfo(bufferSize, (ssbos ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
4303 
4304 		VertexBufferInfo bufferInfo;
4305 		bufferInfo.buffer	= BufferWithMemoryPtr(new vk::BufferWithMemory(vkd, device, allocator, createInfo, vk::MemoryRequirement::HostVisible));
4306 		bufferInfo.offset	= static_cast<vk::VkDeviceSize>(dataOffset);
4307 		bufferInfo.dataSize	= dataSize;
4308 		buffers.emplace_back(std::move(bufferInfo));
4309 
4310 		// Copy the whole contents to the full buffer.
4311 		copyAndFlush(vkd, device, *buffers.back().buffer, 0, bufferBytes.data(), de::dataSize(bufferBytes));
4312 	}
4313 }
4314 
4315 // Device helper: this is needed in some tests when we create custom devices.
4316 class DeviceHelper
4317 {
4318 public:
~DeviceHelper()4319 	virtual ~DeviceHelper () {}
4320 	virtual const vk::DeviceInterface&		getDeviceInterface	(void) const = 0;
4321 	virtual vk::VkDevice					getDevice			(void) const = 0;
4322 	virtual uint32_t						getQueueFamilyIndex	(void) const = 0;
4323 	virtual vk::VkQueue						getQueue			(void) const = 0;
4324 	virtual vk::Allocator&					getAllocator		(void) const = 0;
4325 	virtual const std::vector<std::string>&	getDeviceExtensions	(void) const = 0;
4326 };
4327 
4328 // This one just reuses the default device from the context.
4329 class ContextDeviceHelper : public DeviceHelper
4330 {
4331 public:
ContextDeviceHelper(Context & context)4332 	ContextDeviceHelper (Context& context)
4333 		: m_deviceInterface		(context.getDeviceInterface())
4334 		, m_device				(context.getDevice())
4335 		, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
4336 		, m_queue				(context.getUniversalQueue())
4337 		, m_allocator			(context.getDefaultAllocator())
4338 		, m_extensions			(context.getDeviceExtensions())
4339 		{}
4340 
~ContextDeviceHelper()4341 	virtual ~ContextDeviceHelper () {}
4342 
getDeviceInterface(void) const4343 	const vk::DeviceInterface&		getDeviceInterface	(void) const override	{ return m_deviceInterface;		}
getDevice(void) const4344 	vk::VkDevice					getDevice			(void) const override	{ return m_device;				}
getQueueFamilyIndex(void) const4345 	uint32_t						getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const4346 	vk::VkQueue						getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const4347 	vk::Allocator&					getAllocator		(void) const override	{ return m_allocator;			}
getDeviceExtensions(void) const4348 	const std::vector<std::string>& getDeviceExtensions	(void) const override	{ return m_extensions; }
4349 
4350 protected:
4351 	const vk::DeviceInterface&	m_deviceInterface;
4352 	const vk::VkDevice			m_device;
4353 	const uint32_t				m_queueFamilyIndex;
4354 	const vk::VkQueue			m_queue;
4355 	vk::Allocator&				m_allocator;
4356 	std::vector<std::string>	m_extensions;
4357 };
4358 
4359 // This one creates a new device with VK_NV_shading_rate_image and VK_EXT_extended_dynamic_state3.
4360 // It also enables other extensions like VK_EXT_mesh_shader if supported, as some tests need them.
4361 class ShadingRateImageDeviceHelper : public DeviceHelper
4362 {
4363 public:
ShadingRateImageDeviceHelper(Context & context)4364 	ShadingRateImageDeviceHelper (Context& context)
4365 	{
4366 		const auto&	vkp				= context.getPlatformInterface();
4367 		const auto&	vki				= context.getInstanceInterface();
4368 		const auto	instance		= context.getInstance();
4369 		const auto	physicalDevice	= context.getPhysicalDevice();
4370 		const auto	queuePriority	= 1.0f;
4371 
4372 		// Queue index first.
4373 		m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4374 
4375 		// Create a universal queue that supports graphics and compute.
4376 		const vk::VkDeviceQueueCreateInfo queueParams =
4377 		{
4378 			vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
4379 			DE_NULL,										// const void*					pNext;
4380 			0u,												// VkDeviceQueueCreateFlags		flags;
4381 			m_queueFamilyIndex,								// deUint32						queueFamilyIndex;
4382 			1u,												// deUint32						queueCount;
4383 			&queuePriority									// const float*					pQueuePriorities;
4384 		};
4385 
4386 #ifndef CTS_USES_VULKANSC
4387 		const auto&	contextMeshFeatures	= context.getMeshShaderFeaturesEXT();
4388 		const auto& contextGPLFeatures	= context.getGraphicsPipelineLibraryFeaturesEXT();
4389 		const auto& contextDBCFeatures	= context.getDepthBiasControlFeaturesEXT();
4390 		const auto&	contextSOFeatures	= context.getShaderObjectFeaturesEXT();
4391 
4392 		const bool	meshShaderSupport	= contextMeshFeatures.meshShader;
4393 		const bool	gplSupport			= contextGPLFeatures.graphicsPipelineLibrary;
4394 		const bool	dbcSupport			= contextDBCFeatures.depthBiasControl;
4395 		const bool  shaderObjectSupport = contextSOFeatures.shaderObject;
4396 
4397 		vk::VkPhysicalDeviceExtendedDynamicState3FeaturesEXT	eds3Features				= vk::initVulkanStructure();
4398 		vk::VkPhysicalDeviceShadingRateImageFeaturesNV			shadingRateImageFeatures	= vk::initVulkanStructure(&eds3Features);
4399 		vk::VkPhysicalDeviceFeatures2							features2					= vk::initVulkanStructure(&shadingRateImageFeatures);
4400 
4401 		vk::VkPhysicalDeviceDepthBiasControlFeaturesEXT			dbcFeatures					= vk::initVulkanStructure();
4402 		vk::VkPhysicalDeviceMeshShaderFeaturesEXT				meshFeatures				= vk::initVulkanStructure();
4403 		vk::VkPhysicalDeviceMultiviewFeatures					multiviewFeatures			= vk::initVulkanStructure();
4404 		vk::VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT	gplFeatures					= vk::initVulkanStructure();
4405 		vk::VkPhysicalDeviceShaderObjectFeaturesEXT				shaderObjectFeatures		= vk::initVulkanStructure();
4406 
4407 		const auto addFeatures = vk::makeStructChainAdder(&features2);
4408 
4409 		if (meshShaderSupport) {
4410 			addFeatures(&meshFeatures);
4411 
4412 			if (contextMeshFeatures.multiviewMeshShader)
4413 			{
4414 				addFeatures(&multiviewFeatures);
4415 			}
4416 		}
4417 
4418 		if (gplSupport)
4419 			addFeatures(&gplFeatures);
4420 
4421 		if (dbcSupport)
4422 			addFeatures(&dbcFeatures);
4423 
4424 		if (shaderObjectSupport)
4425 			addFeatures(&shaderObjectFeatures);
4426 
4427 		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
4428 		// If shadingRateImage feature is enabled pipelineFragmentShadingRate must not be enabled primitiveFragmentShadingRate
4429 		// and if primitiveFragmentShadingRate is not enabled primitiveFragmentShadingRateMeshShader must not be enabled
4430 		meshFeatures.primitiveFragmentShadingRateMeshShader = VK_FALSE;
4431 
4432 #endif // CTS_USES_VULKANSC
4433 
4434 		std::vector<const char*> extensions
4435 		{
4436 			"VK_EXT_extended_dynamic_state3",
4437 			"VK_NV_shading_rate_image",
4438 		};
4439 
4440 #ifndef CTS_USES_VULKANSC
4441 		if (meshShaderSupport)
4442 		{
4443 			extensions.push_back("VK_EXT_mesh_shader");
4444 			if (contextMeshFeatures.multiviewMeshShader)
4445 				extensions.push_back("VK_KHR_multiview");
4446 		}
4447 
4448 		if (gplSupport)
4449 		{
4450 			extensions.push_back("VK_KHR_pipeline_library");
4451 			extensions.push_back("VK_EXT_graphics_pipeline_library");
4452 		}
4453 
4454 		if (dbcSupport)
4455 			extensions.push_back("VK_EXT_depth_bias_control");
4456 
4457 		if (shaderObjectSupport)
4458 			extensions.push_back("VK_EXT_shader_object");
4459 
4460 		// Disable robustness.
4461 		features2.features.robustBufferAccess = VK_FALSE;
4462 #endif // CTS_USES_VULKANSC
4463 
4464 		for (const auto& ext : extensions)
4465 			m_extensions.push_back(ext);
4466 
4467 		const vk::VkDeviceCreateInfo deviceCreateInfo =
4468 		{
4469 			vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,				//sType;
4470 #ifndef CTS_USES_VULKANSC
4471 			&features2,												//pNext;
4472 #else
4473 			nullptr,
4474 #endif // CTS_USES_VULKANSC
4475 			0u,														//flags
4476 			1u,														//queueRecordCount;
4477 			&queueParams,											//pRequestedQueues;
4478 			0u,														//layerCount;
4479 			nullptr,												//ppEnabledLayerNames;
4480 			de::sizeU32(extensions),								// deUint32							enabledExtensionCount;
4481 			de::dataOrNull(extensions),								// const char* const*				ppEnabledExtensionNames;
4482 			nullptr,												//pEnabledFeatures;
4483 		};
4484 
4485 		m_device	= createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
4486 		m_vkd		.reset(new vk::DeviceDriver(vkp, instance, m_device.get(), context.getUsedApiVersion()));
4487 		m_queue		= getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
4488 		m_allocator	.reset(new vk::SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
4489 	}
4490 
~ShadingRateImageDeviceHelper()4491 	virtual ~ShadingRateImageDeviceHelper () {}
4492 
getDeviceInterface(void) const4493 	const vk::DeviceInterface&		getDeviceInterface	(void) const override	{ return *m_vkd;				}
getDevice(void) const4494 	vk::VkDevice					getDevice			(void) const override	{ return m_device.get();		}
getQueueFamilyIndex(void) const4495 	uint32_t						getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const4496 	vk::VkQueue						getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const4497 	vk::Allocator&					getAllocator		(void) const override	{ return *m_allocator;			}
getDeviceExtensions(void) const4498 	const std::vector<std::string>&	getDeviceExtensions	(void) const override	{ return m_extensions;			}
4499 
4500 protected:
4501 	vk::Move<vk::VkDevice>					m_device;
4502 	std::unique_ptr<vk::DeviceDriver>		m_vkd;
4503 	deUint32								m_queueFamilyIndex;
4504 	vk::VkQueue								m_queue;
4505 	std::unique_ptr<vk::SimpleAllocator>	m_allocator;
4506 	std::vector<std::string>				m_extensions;
4507 };
4508 
4509 std::unique_ptr<DeviceHelper> g_shadingRateDeviceHelper;
4510 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
4511 
getDeviceHelper(Context & context,const TestConfig & testConfig)4512 DeviceHelper& getDeviceHelper(Context& context, const TestConfig& testConfig)
4513 {
4514 	if (testConfig.shadingRateImage)
4515 	{
4516 		if (!g_shadingRateDeviceHelper)
4517 			g_shadingRateDeviceHelper.reset(new ShadingRateImageDeviceHelper(context));
4518 		return *g_shadingRateDeviceHelper;
4519 	}
4520 
4521 	if (!g_contextDeviceHelper)
4522 		g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
4523 	return *g_contextDeviceHelper;
4524 }
4525 
cleanupDevices()4526 void cleanupDevices()
4527 {
4528 	g_shadingRateDeviceHelper.reset(nullptr);
4529 	g_contextDeviceHelper.reset(nullptr);
4530 }
4531 
getChannelClass(const tcu::TextureFormat & format)4532 tcu::TextureChannelClass getChannelClass (const tcu::TextureFormat& format)
4533 {
4534 	const auto generalClass = getTextureChannelClass(format.type);
4535 	// Workaround for VK_FORMAT_X8_D24_UNORM_PACK32.
4536 	return ((generalClass == tcu::TEXTURECHANNELCLASS_LAST) ? tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT : generalClass);
4537 }
4538 
iterate(void)4539 tcu::TestStatus ExtendedDynamicStateInstance::iterate (void)
4540 {
4541 	using ImageWithMemoryVec	= std::vector<std::unique_ptr<vk::ImageWithMemory>>;
4542 	using ImageViewVec			= std::vector<vk::Move<vk::VkImageView>>;
4543 	using RenderPassVec			= std::vector<vk::RenderPassWrapper>;
4544 
4545 	const auto&	vki					= m_context.getInstanceInterface();
4546 	const auto	physicalDevice		= m_context.getPhysicalDevice();
4547 	const auto& deviceHelper		= getDeviceHelper(m_context, m_testConfig);
4548 	const auto&	vkd					= deviceHelper.getDeviceInterface();
4549 	const auto	device				= deviceHelper.getDevice();
4550 	auto&		allocator			= deviceHelper.getAllocator();
4551 	const auto	queue				= deviceHelper.getQueue();
4552 	const auto	queueIndex			= deviceHelper.getQueueFamilyIndex();
4553 	auto&		log					= m_context.getTestContext().getLog();
4554 
4555 	const auto	kReversed			= m_testConfig.isReversed();
4556 	const auto	kBindStaticFirst	= m_testConfig.bindStaticFirst();
4557 	const auto	kUseStaticPipeline	= m_testConfig.useStaticPipeline();
4558 	const auto	kNumIterations		= m_testConfig.numIterations();
4559 	const auto	kColorAttCount		= m_testConfig.colorAttachmentCount;
4560 	const auto	kSequenceOrdering	= m_testConfig.sequenceOrdering;
4561 
4562 	const auto	kDSCreateFlags		= (m_testConfig.sampleLocationsStruct() ? static_cast<vk::VkImageCreateFlags>(vk::VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) : 0u);
4563 	const auto	colorFormat			= m_testConfig.colorFormat();
4564 	const auto	colorSampleCount	= m_testConfig.getColorSampleCount();
4565 	const auto	activeSampleCount	= m_testConfig.getActiveSampleCount();
4566 	const bool	vertDataAsSSBO		= m_testConfig.useMeshShaders;
4567 	const auto	pipelineBindPoint	= vk::VK_PIPELINE_BIND_POINT_GRAPHICS;
4568 	const bool	kUseResolveAtt		= (colorSampleCount != kSingleSampleCount);
4569 	const bool	kMultisampleDS		= (activeSampleCount != kSingleSampleCount);
4570 	const bool	kFragAtomics		= m_testConfig.useFragShaderAtomics();
4571 
4572 	// Choose depth/stencil format.
4573 	const DepthStencilFormat* dsFormatInfo = nullptr;
4574 
4575 	for (const auto& kDepthStencilFormat : kDepthStencilFormats)
4576 	{
4577 		// This is how we'll attempt to create images later.
4578 		const auto dsImageInfo = makeImageCreateInfo(kDepthStencilFormat.imageFormat, kFramebufferExtent, activeSampleCount, kDSUsage, kDSCreateFlags);
4579 
4580 		vk::VkImageFormatProperties formatProps;
4581 		const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, dsImageInfo.format, dsImageInfo.imageType, dsImageInfo.tiling, dsImageInfo.usage, dsImageInfo.flags, &formatProps);
4582 
4583 		// Format not supported.
4584 		if (result != vk::VK_SUCCESS)
4585 			continue;
4586 
4587 		// Extent not big enough.
4588 		const auto& maxExtent = formatProps.maxExtent;
4589 		if (maxExtent.width < kFramebufferExtent.width || maxExtent.height < kFramebufferExtent.height || maxExtent.depth < kFramebufferExtent.depth)
4590 			continue;
4591 
4592 		// Sample count not supported.
4593 		if ((formatProps.sampleCounts & activeSampleCount) != activeSampleCount)
4594 			continue;
4595 
4596 		if (m_testConfig.neededDepthChannelClass != tcu::TEXTURECHANNELCLASS_LAST)
4597 		{
4598 			const auto tcuDSFormat	= vk::getDepthCopyFormat(kDepthStencilFormat.imageFormat);
4599 			const auto channelClass	= getChannelClass(tcuDSFormat);
4600 
4601 			if (channelClass != m_testConfig.neededDepthChannelClass)
4602 				continue;
4603 		}
4604 
4605 		dsFormatInfo = &kDepthStencilFormat;
4606 		break;
4607 	}
4608 
4609 	// Note: Not Supported insted of Fail because some features are not mandatory.
4610 	if (!dsFormatInfo)
4611 		TCU_THROW(NotSupportedError, "Required depth/stencil image features not supported");
4612 	log << tcu::TestLog::Message << "Chosen depth/stencil format: " << dsFormatInfo->imageFormat << tcu::TestLog::EndMessage;
4613 	log << tcu::TestLog::Message << "Chosen color format: " << colorFormat << tcu::TestLog::EndMessage;
4614 
4615 	// Swap static and dynamic values in the test configuration so the static pipeline ends up with the expected values for cases
4616 	// where we will bind the static pipeline last before drawing.
4617 	if (kReversed)
4618 		m_testConfig.swapValues();
4619 
4620 	// Create color and depth/stencil images.
4621 	ImageWithMemoryVec colorImages;
4622 	ImageWithMemoryVec dsImages;
4623 	ImageWithMemoryVec resolveImages;
4624 
4625 	const auto colorImageInfo = makeImageCreateInfo(colorFormat, kFramebufferExtent, colorSampleCount, kColorUsage, 0u);
4626 	for (deUint32 i = 0u; i < kNumIterations * kColorAttCount; ++i)
4627 		colorImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, colorImageInfo, vk::MemoryRequirement::Any));
4628 
4629 	const auto dsImageInfo = makeImageCreateInfo(dsFormatInfo->imageFormat, kFramebufferExtent, activeSampleCount, kDSUsage, kDSCreateFlags);
4630 	for (deUint32 i = 0u; i < kNumIterations; ++i)
4631 		dsImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, dsImageInfo, vk::MemoryRequirement::Any));
4632 
4633 	if (kUseResolveAtt)
4634 	{
4635 		const auto resolveImageInfo = makeImageCreateInfo(colorFormat, kFramebufferExtent, kSingleSampleCount, kColorUsage, 0u);
4636 		for (uint32_t i = 0u; i < kNumIterations * kColorAttCount; ++i)
4637 			resolveImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, resolveImageInfo, vk::MemoryRequirement::Any));
4638 	}
4639 
4640 	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
4641 	const auto dsSubresourceRange		= vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
4642 
4643 	ImageViewVec colorImageViews;
4644 	ImageViewVec dsImageViews;
4645 	ImageViewVec resolveImageViews;
4646 
4647 	for (const auto& img : colorImages)
4648 		colorImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
4649 
4650 	for (const auto& img : dsImages)
4651 		dsImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, dsFormatInfo->imageFormat, dsSubresourceRange));
4652 
4653 	for (const auto& img : resolveImages)
4654 		resolveImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
4655 
4656 	// Vertex buffer.
4657 	const auto				topologyClass	= getTopologyClass(m_testConfig.topologyConfig.staticValue);
4658 	std::vector<uint32_t>	indices;
4659 	std::vector<tcu::Vec2>	vertices;
4660 
4661 	if (m_testConfig.oversizedTriangle || m_testConfig.offCenterTriangle)
4662 	{
4663 		DE_ASSERT(topologyClass == TopologyClass::TRIANGLE);
4664 		DE_ASSERT(!m_testConfig.singleVertex);
4665 	}
4666 
4667 	if (m_testConfig.obliqueLine)
4668 		DE_ASSERT(topologyClass == TopologyClass::LINE);
4669 
4670 	if (topologyClass == TopologyClass::TRIANGLE)
4671 	{
4672 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
4673 
4674 		if (m_testConfig.oversizedTriangle)
4675 		{
4676 			vertices.reserve(3u);
4677 			vertices.push_back(tcu::Vec2(-2.0f, -2.0f));
4678 			vertices.push_back(tcu::Vec2(-2.0f,  6.0f));
4679 			vertices.push_back(tcu::Vec2( 6.0f, -2.0f));
4680 		}
4681 		else if (m_testConfig.offCenterTriangle)
4682 		{
4683 			// Triangle covering the whole screen, except for the first row and column, which may not be covered by all samples.
4684 			const float horOffset	= 2.0f / static_cast<float>(kFramebufferWidth) * m_testConfig.offCenterProportion.x();
4685 			const float vertOffset	= 2.0f / static_cast<float>(kFramebufferHeight) * m_testConfig.offCenterProportion.y();
4686 
4687 			vertices.reserve(3u);
4688 			vertices.push_back(tcu::Vec2(-1.0f + horOffset, -1.0f + vertOffset));
4689 			vertices.push_back(tcu::Vec2(-1.0f + horOffset,               4.0f));
4690 			vertices.push_back(tcu::Vec2(             4.0f, -1.0f + vertOffset));
4691 		}
4692 		else
4693 		{
4694 			// Full-screen triangle strip with 6 vertices.
4695 			//
4696 			// 0        2        4
4697 			//  +-------+-------+
4698 			//  |      XX      X|
4699 			//  |     X X     X |
4700 			//  |    X  X    X  |
4701 			//  |   X   X   X   |
4702 			//  |  X    X  X    |
4703 			//  | X     X X     |
4704 			//  |X      XX      |
4705 			//  +-------+-------+
4706 			// 1        3       5
4707 			vertices.reserve(6u);
4708 			vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
4709 			vertices.push_back(tcu::Vec2(-1.0f,  1.0f));
4710 			vertices.push_back(tcu::Vec2( 0.0f, -1.0f));
4711 			vertices.push_back(tcu::Vec2( 0.0f,  1.0f));
4712 			vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
4713 			vertices.push_back(tcu::Vec2( 1.0f,  1.0f));
4714 		}
4715 	}
4716 	else if (topologyClass == TopologyClass::PATCH)
4717 	{
4718 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
4719 		DE_ASSERT(m_testConfig.getActivePatchControlPoints() > 1u);
4720 
4721 		// 2 triangles making a quad
4722 		vertices.reserve(6u);
4723 		vertices.push_back(tcu::Vec2(-1.0f,  1.0f));
4724 		vertices.push_back(tcu::Vec2( 1.0f,  1.0f));
4725 		vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
4726 		vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
4727 		vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
4728 		vertices.push_back(tcu::Vec2(-1.0f,  1.0f));
4729 	}
4730 	else // TopologyClass::LINE
4731 	{
4732 		const float pixelHeight	= 2.0f / static_cast<float>(kFramebufferHeight);
4733 		const float pixelWidth	= 2.0f / static_cast<float>(kFramebufferWidth);
4734 
4735 		if (m_testConfig.obliqueLine)
4736 		{
4737 			// The starting point of the oblique line is located in the top left pixel, in a position below and slightly to the left
4738 			// of the pixel center. The ending point is in the middle of the right side of the framebuffer. Those coordinates make
4739 			// sure that a bresenham-style line covers the center of the top left pixel, because the left edge of the line goes up
4740 			// vertically from that point. However, a rectangular line misses it by a small delta because its edge goes up and to
4741 			// the right, leaving the pixel center to its left. So the top left pixel itself may be covered or not depending on the
4742 			// active line rasterization mode.
4743 			//
4744 			// Note: results may also be affected by multisample and sample locations if those are used.
4745 			vertices.reserve(2u);
4746 			vertices.push_back(tcu::Vec2(pixelWidth * 7.0f / 16.0f - 1.0f, pixelHeight * 12.0f / 16.0f - 1.0f));
4747 			vertices.push_back(tcu::Vec2(1.0f, 0.0f));
4748 		}
4749 		else
4750 		{
4751 			DE_ASSERT(m_testConfig.getActivePrimRestartEnable());
4752 
4753 			// Draw one segmented line per output row of pixels that could be wrongly interpreted as a list of lines that would not cover the whole screen.
4754 			vertices.reserve(kFramebufferHeight * 4u);
4755 
4756 			const auto indicesPerRow = (m_testConfig.extraLineRestarts ? 6u : 5u);
4757 			if (m_testConfig.needsIndexBuffer())
4758 				indices.reserve(kFramebufferHeight * indicesPerRow);
4759 
4760 			for (deUint32 rowIdx = 0; rowIdx < kFramebufferHeight; ++rowIdx)
4761 			{
4762 				// Offset of 0.5 pixels + one pixel per row, from -1 to 1.
4763 				const float yCoord = (pixelHeight / 2.0f) + pixelHeight * static_cast<float>(rowIdx) - 1.0f;
4764 				vertices.push_back(tcu::Vec2(-1.0f, yCoord));
4765 				vertices.push_back(tcu::Vec2(-0.5f, yCoord));
4766 				vertices.push_back(tcu::Vec2( 0.5f, yCoord));
4767 				vertices.push_back(tcu::Vec2( 1.0f, yCoord));
4768 
4769 				if (m_testConfig.needsIndexBuffer())
4770 				{
4771 					indices.push_back(4u * rowIdx + 0u);
4772 					indices.push_back(4u * rowIdx + 1u);
4773 
4774 					// When using extra line restarts, insert a primitive restart index in the middle, which will result in the
4775 					// center strip being skipped, as if the topology was a line list instead of a strip.
4776 					if (m_testConfig.extraLineRestarts)
4777 						indices.push_back(0xFFFFFFFFu);
4778 
4779 					indices.push_back(4u * rowIdx + 2u);
4780 					indices.push_back(4u * rowIdx + 3u);
4781 					indices.push_back(0xFFFFFFFFu); // Restart line strip.
4782 				}
4783 			}
4784 		}
4785 	}
4786 
4787 	if (m_testConfig.singleVertex)
4788 	{
4789 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
4790 		vertices.resize(1);
4791 	}
4792 
4793 	// Reversed vertices order in triangle strip (1, 0, 3, 2, 5, 4)
4794 	std::vector<tcu::Vec2> rvertices;
4795 	if (topologyClass == TopologyClass::TRIANGLE)
4796 	{
4797 		DE_ASSERT(!vertices.empty());
4798 		if (m_testConfig.singleVertex)
4799 			rvertices.push_back(vertices[0]);
4800 		else if (m_testConfig.oversizedTriangle || m_testConfig.offCenterTriangle)
4801 		{
4802 			rvertices.reserve(3u);
4803 			rvertices.push_back(vertices[0]);
4804 			rvertices.push_back(vertices[2]);
4805 			rvertices.push_back(vertices[1]);
4806 		}
4807 		else
4808 		{
4809 			rvertices.reserve(6u);
4810 			rvertices.push_back(vertices[1]);
4811 			rvertices.push_back(vertices[0]);
4812 			rvertices.push_back(vertices[3]);
4813 			rvertices.push_back(vertices[2]);
4814 			rvertices.push_back(vertices[5]);
4815 			rvertices.push_back(vertices[4]);
4816 		}
4817 	}
4818 
4819 	if (topologyClass != TopologyClass::TRIANGLE)
4820 	{
4821 		for (const auto& mesh : m_testConfig.meshParams)
4822 		{
4823 			DE_UNREF(mesh); // For release builds.
4824 			DE_ASSERT(!mesh.reversed);
4825 		}
4826 	}
4827 
4828 	// Buffers with vertex data for the different bindings.
4829 	std::vector<VertexBufferInfo> vertBuffers;
4830 	std::vector<VertexBufferInfo> rvertBuffers;
4831 
4832 	{
4833 		const auto dataOffset	= static_cast<deUint32>(m_testConfig.vertexDataOffset);
4834 		const auto trailingSize	= static_cast<deUint32>(m_testConfig.vertexDataExtraBytes);
4835 		const auto generator	= m_testConfig.getActiveVertexGenerator();
4836 		prepareVertexBuffers(vertBuffers, vkd, device, allocator, generator, vertices, dataOffset, trailingSize, vertDataAsSSBO);
4837 		if (topologyClass == TopologyClass::TRIANGLE)
4838 			prepareVertexBuffers(rvertBuffers, vkd, device, allocator, generator, rvertices, dataOffset, trailingSize, vertDataAsSSBO);
4839 	}
4840 
4841 	// Index buffer.
4842 	BufferWithMemoryPtr indexBuffer;
4843 	if (!indices.empty())
4844 	{
4845 		const auto indexDataSize	= static_cast<vk::VkDeviceSize>(de::dataSize(indices));
4846 		const auto indexBufferInfo	= vk::makeBufferCreateInfo(indexDataSize, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
4847 
4848 		indexBuffer = BufferWithMemoryPtr(new vk::BufferWithMemory(vkd, device, allocator, indexBufferInfo, vk::MemoryRequirement::HostVisible));
4849 		copyAndFlush(vkd, device, *indexBuffer, 0, indices.data(), static_cast<size_t>(indexDataSize));
4850 	}
4851 
4852 	// Fragment counter buffer.
4853 	BufferWithMemoryPtr	counterBuffer;
4854 	const auto			counterBufferSize	= static_cast<vk::VkDeviceSize>(sizeof(uint32_t));
4855 
4856 	if (kFragAtomics)
4857 	{
4858 		const auto		counterBufferInfo	= vk::makeBufferCreateInfo(counterBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
4859 		const uint32_t	initialValue		= 0u;
4860 
4861 		counterBuffer = BufferWithMemoryPtr(new vk::BufferWithMemory(vkd, device, allocator, counterBufferInfo, vk::MemoryRequirement::HostVisible));
4862 		copyAndFlush(vkd, device, *counterBuffer, 0u, &initialValue, static_cast<size_t>(counterBufferSize));
4863 	}
4864 
4865 	// Frag shader descriptor set layout.
4866 	vk::Move<vk::VkDescriptorSetLayout> fragSetLayout;
4867 	{
4868 		vk::DescriptorSetLayoutBuilder layoutBuilder;
4869 		if (kFragAtomics)
4870 			layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
4871 		fragSetLayout = layoutBuilder.build(vkd, device);
4872 	}
4873 
4874 	// Descriptor pool and set.
4875 	vk::Move<vk::VkDescriptorPool>	fragDescriptorPool;
4876 	vk::Move<vk::VkDescriptorSet>	fragDescriptorSet;
4877 
4878 	if (kFragAtomics)
4879 	{
4880 		vk::DescriptorPoolBuilder poolBuilder;
4881 		poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
4882 		fragDescriptorPool	= poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4883 		fragDescriptorSet	= vk::makeDescriptorSet(vkd, device, fragDescriptorPool.get(), fragSetLayout.get());
4884 
4885 		vk::DescriptorSetUpdateBuilder updateBuilder;
4886 		const auto location = vk::DescriptorSetUpdateBuilder::Location::binding(0u);
4887 		const auto descInfo = vk::makeDescriptorBufferInfo(counterBuffer->get(), 0ull, counterBufferSize);
4888 		updateBuilder.writeSingle(fragDescriptorSet.get(), location, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descInfo);
4889 		updateBuilder.update(vkd, device);
4890 	}
4891 
4892 	// Push constant stages (matches SSBO stages if used).
4893 	vk::VkShaderStageFlags pushConstantStageFlags = (
4894 		(m_testConfig.useMeshShaders
4895 #ifndef CTS_USES_VULKANSC
4896 		 ? vk::VK_SHADER_STAGE_MESH_BIT_EXT
4897 #else
4898 		 ? 0
4899 #endif // CTS_USES_VULKANSC
4900 		 : vk::VK_SHADER_STAGE_VERTEX_BIT)
4901 		| vk::VK_SHADER_STAGE_FRAGMENT_BIT);
4902 
4903 	if (m_testConfig.needsGeometryShader())
4904 		pushConstantStageFlags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
4905 
4906 	// Mesh descriptor set layout.
4907 	vk::Move<vk::VkDescriptorSetLayout> meshSetLayout;
4908 	if (vertDataAsSSBO)
4909 	{
4910 		vk::DescriptorSetLayoutBuilder layoutBuilder;
4911 		for (size_t i = 0; i < vertBuffers.size(); ++i)
4912 			layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, pushConstantStageFlags);
4913 		meshSetLayout = layoutBuilder.build(vkd, device);
4914 	}
4915 
4916 	// Descriptor pool and set if needed.
4917 	vk::Move<vk::VkDescriptorPool>	meshDescriptorPool;
4918 	vk::Move<vk::VkDescriptorSet>	meshDescriptorSet;
4919 	vk::Move<vk::VkDescriptorSet>	meshDescriptorSetRev;
4920 
4921 	if (vertDataAsSSBO)
4922 	{
4923 		const auto					hasReversed		= (rvertBuffers.size() > 0u);
4924 		const auto					descType		= vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
4925 		vk::DescriptorPoolBuilder	poolBuilder;
4926 		poolBuilder.addType(descType, static_cast<uint32_t>(vertBuffers.size()) * 2u);
4927 
4928 		meshDescriptorPool		= poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
4929 		meshDescriptorSet		= vk::makeDescriptorSet(vkd, device, meshDescriptorPool.get(), meshSetLayout.get());
4930 
4931 		if (hasReversed)
4932 			meshDescriptorSetRev = vk::makeDescriptorSet(vkd, device, meshDescriptorPool.get(), meshSetLayout.get());
4933 
4934 		std::vector<vk::VkDescriptorBufferInfo> descBufferInfos;
4935 		std::vector<vk::VkDescriptorBufferInfo> descBufferInfosRev;
4936 		descBufferInfos.reserve(vertBuffers.size());
4937 		if (hasReversed)
4938 			descBufferInfosRev.reserve(rvertBuffers.size());
4939 
4940 		vk::DescriptorSetUpdateBuilder updateBuilder;
4941 
4942 		DE_ASSERT(vertBuffers.size() == rvertBuffers.size() || !hasReversed);
4943 		for (size_t i = 0; i < vertBuffers.size(); ++i)
4944 		{
4945 			const auto binding = vk::DescriptorSetUpdateBuilder::Location::binding(static_cast<uint32_t>(i));
4946 
4947 			descBufferInfos.push_back(vk::makeDescriptorBufferInfo(vertBuffers[i].buffer->get(), vertBuffers[i].offset, vertBuffers[i].dataSize));
4948 			updateBuilder.writeSingle(meshDescriptorSet.get(), binding, descType, &descBufferInfos.back());
4949 
4950 			if (hasReversed)
4951 			{
4952 				descBufferInfosRev.push_back(vk::makeDescriptorBufferInfo(rvertBuffers[i].buffer->get(), rvertBuffers[i].offset, rvertBuffers[i].dataSize));
4953 				updateBuilder.writeSingle(meshDescriptorSetRev.get(), binding, descType, &descBufferInfosRev.back());
4954 			}
4955 		}
4956 
4957 		updateBuilder.update(vkd, device);
4958 	}
4959 
4960 	// The frag shader descriptor set is the second one if both exist. See getFragDescriptorSetIndex().
4961 	std::vector<vk::VkDescriptorSetLayout> rawSetLayouts;
4962 
4963 	if (meshSetLayout.get() != VK_NULL_HANDLE)
4964 		rawSetLayouts.push_back(meshSetLayout.get());
4965 
4966 	if (fragSetLayout.get() != VK_NULL_HANDLE)
4967 		rawSetLayouts.push_back(fragSetLayout.get());
4968 
4969 	// Pipeline layout.
4970 	const vk::VkPushConstantRange pushConstantRange =
4971 	{
4972 		pushConstantStageFlags,							//	VkShaderStageFlags	stageFlags;
4973 		0u,												//	deUint32			offset;
4974 		static_cast<deUint32>(sizeof(PushConstants)),	//	deUint32			size;
4975 	};
4976 
4977 	const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
4978 	{
4979 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//	VkStructureType					sType;
4980 		nullptr,											//	const void*						pNext;
4981 		0u,													//	VkPipelineLayoutCreateFlags		flags;
4982 		de::sizeU32(rawSetLayouts),							//	deUint32						setLayoutCount;
4983 		de::dataOrNull(rawSetLayouts),						//	const VkDescriptorSetLayout*	pSetLayouts;
4984 		1u,													//	deUint32						pushConstantRangeCount;
4985 		&pushConstantRange,									//	const VkPushConstantRange*		pPushConstantRanges;
4986 	};
4987 	const vk::PipelineLayoutWrapper pipelineLayout (m_testConfig.pipelineConstructionType, vkd, device, &pipelineLayoutCreateInfo);
4988 
4989 	// Render pass with single subpass. Attachment order:
4990 	// 1) Color attachments (kColorAttCount items).
4991 	// 2) DS attachment.
4992 	// 3) [optional] Resolve attachments (kColorAttCount).
4993 
4994 	DE_ASSERT(kColorAttCount > 0u);
4995 
4996 	std::vector<vk::VkAttachmentReference> colorAttachments;
4997 	std::vector<vk::VkAttachmentReference> resolveAttachments;
4998 
4999 	for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5000 	{
5001 		colorAttachments.push_back(vk::makeAttachmentReference(colorAttIdx, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
5002 		if (kUseResolveAtt)
5003 			resolveAttachments.push_back(vk::makeAttachmentReference(kColorAttCount + 1u + colorAttIdx, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
5004 	}
5005 
5006 	const vk::VkAttachmentReference dsAttachmentReference =
5007 	{
5008 		kColorAttCount,											//	deUint32		attachment;
5009 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
5010 	};
5011 
5012 	const vk::VkSubpassDescription subpassDescription =
5013 	{
5014 		0u,										//	VkSubpassDescriptionFlags		flags;
5015 		pipelineBindPoint,						//	VkPipelineBindPoint				pipelineBindPoint;
5016 		0u,										//	deUint32						inputAttachmentCount;
5017 		nullptr,								//	const VkAttachmentReference*	pInputAttachments;
5018 		kColorAttCount,							//	deUint32						colorAttachmentCount;
5019 		de::dataOrNull(colorAttachments),		//	const VkAttachmentReference*	pColorAttachments;
5020 		de::dataOrNull(resolveAttachments),		//	const VkAttachmentReference*	pResolveAttachments;
5021 		&dsAttachmentReference,					//	const VkAttachmentReference*	pDepthStencilAttachment;
5022 		0u,										//	deUint32						preserveAttachmentCount;
5023 		nullptr,								//	const deUint32*					pPreserveAttachments;
5024 	};
5025 
5026 	std::vector<vk::VkAttachmentDescription> attachmentDescriptions;
5027 
5028 	// For multisample, we care about the resolve attachment, not the color one.
5029 	const auto colorAttachmentStoreOp = (kUseResolveAtt ? vk::VK_ATTACHMENT_STORE_OP_DONT_CARE : vk::VK_ATTACHMENT_STORE_OP_STORE);
5030 
5031 	for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5032 	{
5033 		attachmentDescriptions.push_back(vk::VkAttachmentDescription
5034 		{
5035 			0u,												//	VkAttachmentDescriptionFlags	flags;
5036 			colorFormat,									//	VkFormat						format;
5037 			colorSampleCount,								//	VkSampleCountFlagBits			samples;
5038 			vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				//	VkAttachmentLoadOp				loadOp;
5039 			colorAttachmentStoreOp,							//	VkAttachmentStoreOp				storeOp;
5040 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
5041 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
5042 			vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
5043 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
5044 		});
5045 	}
5046 
5047 	attachmentDescriptions.push_back(vk::VkAttachmentDescription
5048 	{
5049 		0u,														//	VkAttachmentDescriptionFlags	flags;
5050 		dsFormatInfo->imageFormat,								//	VkFormat						format;
5051 		activeSampleCount,										//	VkSampleCountFlagBits			samples;
5052 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
5053 		vk::VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
5054 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				stencilLoadOp;
5055 		vk::VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				stencilStoreOp;
5056 		vk::VK_IMAGE_LAYOUT_UNDEFINED,							//	VkImageLayout					initialLayout;
5057 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
5058 	});
5059 
5060 	if (kUseResolveAtt)
5061 	{
5062 		// Resolve attachments.
5063 		for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5064 		{
5065 			attachmentDescriptions.push_back(vk::VkAttachmentDescription
5066 			{
5067 				0u,												//	VkAttachmentDescriptionFlags	flags;
5068 				colorFormat,									//	VkFormat						format;
5069 				kSingleSampleCount,								//	VkSampleCountFlagBits			samples;
5070 				vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				loadOp;
5071 				vk::VK_ATTACHMENT_STORE_OP_STORE,				//	VkAttachmentStoreOp				storeOp;
5072 				vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
5073 				vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
5074 				vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
5075 				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
5076 			});
5077 		}
5078 	}
5079 
5080 	// Render pass and framebuffers.
5081 	RenderPassVec renderPassFramebuffers;
5082 
5083 	const vk::VkRenderPassCreateInfo renderPassCreateInfo =
5084 	{
5085 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			//	VkStructureType					sType;
5086 		nullptr,												//	const void*						pNext;
5087 		0u,														//	VkRenderPassCreateFlags			flags;
5088 		static_cast<deUint32>(attachmentDescriptions.size()),	//	deUint32						attachmentCount;
5089 		attachmentDescriptions.data(),							//	const VkAttachmentDescription*	pAttachments;
5090 		1u,														//	deUint32						subpassCount;
5091 		&subpassDescription,									//	const VkSubpassDescription*		pSubpasses;
5092 		0u,														//	deUint32						dependencyCount;
5093 		nullptr,												//	const VkSubpassDependency*		pDependencies;
5094 	};
5095 
5096 	DE_ASSERT(colorImageViews.size() == dsImageViews.size() * kColorAttCount);
5097 
5098 	if (kUseResolveAtt)
5099 		DE_ASSERT(colorImageViews.size() == resolveImageViews.size());
5100 
5101 	for (size_t iterIdx = 0; iterIdx < dsImageViews.size(); ++iterIdx)
5102 	{
5103 		std::vector<vk::VkImage>		images;
5104 		std::vector<vk::VkImageView>	attachments;
5105 
5106 		for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5107 		{
5108 			const auto colorViewIdx = iterIdx * kColorAttCount + colorAttIdx;
5109 			images.push_back(colorImages[colorViewIdx].get()->get());
5110 			attachments.push_back(colorImageViews[colorViewIdx].get());
5111 		}
5112 
5113 		images.push_back(dsImages[iterIdx].get()->get());
5114 		attachments.push_back(dsImageViews[iterIdx].get());
5115 
5116 		if (kUseResolveAtt)
5117 		{
5118 			for (uint32_t resolveAttIdx = 0u; resolveAttIdx < kColorAttCount; ++resolveAttIdx)
5119 			{
5120 				const auto resolveViewIdx = iterIdx * kColorAttCount + resolveAttIdx;
5121 				images.push_back(resolveImages[resolveViewIdx].get()->get());
5122 				attachments.push_back(resolveImageViews[resolveViewIdx].get());
5123 			}
5124 		}
5125 
5126 		renderPassFramebuffers.emplace_back(m_testConfig.pipelineConstructionType, vkd, device, &renderPassCreateInfo);
5127 
5128 		const vk::VkFramebufferCreateInfo framebufferCreateInfo =
5129 		{
5130 			vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	//	VkStructureType				sType;
5131 			nullptr,										//	const void*					pNext;
5132 			0u,												//	VkFramebufferCreateFlags	flags;
5133 			renderPassFramebuffers[iterIdx].get(),			//	VkRenderPass				renderPass;
5134 			static_cast<deUint32>(attachments.size()),		//	deUint32					attachmentCount;
5135 			attachments.data(),								//	const VkImageView*			pAttachments;
5136 			kFramebufferWidth,								//	deUint32					width;
5137 			kFramebufferHeight,								//	deUint32					height;
5138 			1u,												//	deUint32					layers;
5139 		};
5140 
5141 		renderPassFramebuffers[iterIdx].createFramebuffer(vkd, device, &framebufferCreateInfo, images);
5142 	}
5143 
5144 	// Shader modules.
5145 	const auto&	binaries			= m_context.getBinaryCollection();
5146 	const auto	dynamicVertModule	= vk::ShaderWrapper(vkd, device, binaries.get("dynamicVert"));
5147 	const auto	staticVertModule	= vk::ShaderWrapper(vkd, device, binaries.get("staticVert"));
5148 	const auto	dynamicFragModule	= vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("dynamicFrag"), 0u);
5149 	const auto	staticFragModule	= vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("staticFrag"), 0u);
5150 	const auto	geomModule			= (m_testConfig.needsGeometryShader() ? vk::ShaderWrapper(vkd, device, binaries.get("geom")) : vk::ShaderWrapper());
5151 	const auto	tescModule			= (m_testConfig.needsTessellation() ? vk::ShaderWrapper(vkd, device, binaries.get("tesc")) : vk::ShaderWrapper());
5152 	const auto	teseModule			= (m_testConfig.needsTessellation() ? vk::ShaderWrapper(vkd, device, binaries.get("tese")) : vk::ShaderWrapper());
5153 	const auto	dynamicMeshModule	= (m_testConfig.useMeshShaders ? vk::ShaderWrapper(vkd, device, binaries.get("dynamicMesh")) : vk::ShaderWrapper());
5154 	const auto	staticMeshModule	= (m_testConfig.useMeshShaders ? vk::ShaderWrapper(vkd, device, binaries.get("staticMesh")) : vk::ShaderWrapper());
5155 	const auto	meshNoOutModule		= (m_testConfig.bindUnusedMeshShadingPipeline ? vk::ShaderWrapper(vkd, device, binaries.get("meshNoOut")) : vk::ShaderWrapper());
5156 
5157 	vk::ShaderWrapper	vertDPCPModule;
5158 	vk::ShaderWrapper	fragDPCPModule;
5159 
5160 	// Input state.
5161 	const auto vertexBindings	= m_testConfig.vertexGenerator.staticValue->getBindingDescriptions(m_testConfig.strideConfig.staticValue);
5162 	const auto vertexAttributes	= m_testConfig.vertexGenerator.staticValue->getAttributeDescriptions();
5163 
5164 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
5165 	{
5166 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
5167 		nullptr,														//	const void*									pNext;
5168 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
5169 		static_cast<deUint32>(vertexBindings.size()),					//	deUint32									vertexBindingDescriptionCount;
5170 		vertexBindings.data(),											//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
5171 		static_cast<deUint32>(vertexAttributes.size()),					//	deUint32									vertexAttributeDescriptionCount;
5172 		vertexAttributes.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
5173 	};
5174 
5175 	// Input assembly.
5176 	const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
5177 	{
5178 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType							sType;
5179 		nullptr,															//	const void*								pNext;
5180 		0u,																	//	VkPipelineInputAssemblyStateCreateFlags	flags;
5181 		m_testConfig.topologyConfig.staticValue,							//	VkPrimitiveTopology						topology;
5182 		makeVkBool32(m_testConfig.primRestartEnableConfig.staticValue),		//	VkBool32								primitiveRestartEnable;
5183 	};
5184 
5185 	// Viewport state.
5186 	if (m_testConfig.viewportConfig.dynamicValue)
5187 		DE_ASSERT(m_testConfig.viewportConfig.dynamicValue.get().size() > 0u);
5188 	else
5189 		DE_ASSERT(m_testConfig.viewportConfig.staticValue.size() > 0u);
5190 
5191 	if (m_testConfig.scissorConfig.dynamicValue)
5192 		DE_ASSERT(m_testConfig.scissorConfig.dynamicValue.get().size() > 0u);
5193 	else
5194 		DE_ASSERT(m_testConfig.scissorConfig.staticValue.size() > 0u);
5195 
5196 	// Rasterization state.
5197 	void* multisamplePnext		= nullptr;
5198 	void* rasterizationPnext	= nullptr;
5199 	void* viewportPnext			= nullptr;
5200 
5201 	const bool			staticStreamInfo			= static_cast<bool>(m_testConfig.rasterizationStreamConfig.staticValue);
5202 	const bool			staticProvokingVtxInfo		= static_cast<bool>(m_testConfig.provokingVertexConfig.staticValue);
5203 	const bool			staticDepthClipEnableInfo	= static_cast<bool>(m_testConfig.depthClipEnableConfig.staticValue);
5204 	const bool			staticDepthClipControlInfo	= static_cast<bool>(m_testConfig.negativeOneToOneConfig.staticValue);
5205 #ifndef CTS_USES_VULKANSC
5206 	using RastStreamInfoPtr		= de::MovePtr<vk::VkPipelineRasterizationStateStreamCreateInfoEXT>;
5207 	using ProvokingVtxModePtr	= de::MovePtr<vk::VkPipelineRasterizationProvokingVertexStateCreateInfoEXT>;
5208 	using DepthClipControlPtr	= de::MovePtr<vk::VkPipelineViewportDepthClipControlCreateInfoEXT>;
5209 	using DepthClipEnablePtr	= de::MovePtr<vk::VkPipelineRasterizationDepthClipStateCreateInfoEXT>;
5210 	using ConservativeRastPtr	= de::MovePtr<vk::VkPipelineRasterizationConservativeStateCreateInfoEXT>;
5211 	using DepthBiasReprInfoPtr	= de::MovePtr<vk::VkDepthBiasRepresentationInfoEXT>;
5212 
5213 	RastStreamInfoPtr	pRasterizationStreamInfo;
5214 
5215 	if (staticStreamInfo)
5216 	{
5217 		pRasterizationStreamInfo = RastStreamInfoPtr(new vk::VkPipelineRasterizationStateStreamCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5218 		pRasterizationStreamInfo->rasterizationStream = m_testConfig.rasterizationStreamConfig.staticValue.get();
5219 		rasterizationPnext = pRasterizationStreamInfo.get();
5220 	}
5221 
5222 	ProvokingVtxModePtr	pProvokingVertexModeInfo;
5223 
5224 	if (staticProvokingVtxInfo)
5225 	{
5226 		pProvokingVertexModeInfo = ProvokingVtxModePtr(new vk::VkPipelineRasterizationProvokingVertexStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5227 		pProvokingVertexModeInfo->provokingVertexMode = makeProvokingVertexMode(m_testConfig.provokingVertexConfig.staticValue.get());
5228 		rasterizationPnext = pProvokingVertexModeInfo.get();
5229 	}
5230 
5231 	DepthClipEnablePtr	pDepthClipEnableInfo;
5232 
5233 	if (staticDepthClipEnableInfo)
5234 	{
5235 		pDepthClipEnableInfo = DepthClipEnablePtr(new vk::VkPipelineRasterizationDepthClipStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5236 		pDepthClipEnableInfo->depthClipEnable = makeVkBool32(m_testConfig.depthClipEnableConfig.staticValue.get());
5237 		rasterizationPnext = pDepthClipEnableInfo.get();
5238 	}
5239 
5240 	DepthClipControlPtr	pDepthClipControlInfo;
5241 
5242 	if (staticDepthClipControlInfo)
5243 	{
5244 		pDepthClipControlInfo = DepthClipControlPtr(new vk::VkPipelineViewportDepthClipControlCreateInfoEXT(vk::initVulkanStructure(viewportPnext)));
5245 		pDepthClipControlInfo->negativeOneToOne = makeVkBool32(m_testConfig.negativeOneToOneConfig.staticValue.get());
5246 		viewportPnext = pDepthClipControlInfo.get();
5247 	}
5248 
5249 	ConservativeRastPtr	pConservativeRasterModeInfo;
5250 
5251 	if (m_testConfig.conservativeRasterStruct())
5252 	{
5253 		pConservativeRasterModeInfo = ConservativeRastPtr(new vk::VkPipelineRasterizationConservativeStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5254 		rasterizationPnext = pConservativeRasterModeInfo.get();
5255 
5256 		pConservativeRasterModeInfo->conservativeRasterizationMode		= m_testConfig.conservativeRasterModeConfig.staticValue;
5257 		pConservativeRasterModeInfo->extraPrimitiveOverestimationSize	= m_testConfig.extraPrimitiveOverEstConfig.staticValue;
5258 	}
5259 
5260 	DepthBiasReprInfoPtr pDepthBiasReprInfo;
5261 
5262 	if (m_testConfig.depthBiasReprInfo && (!m_testConfig.depthBiasConfig.dynamicValue || kReversed))
5263 	{
5264 		// Representation info will be passed statically.
5265 		pDepthBiasReprInfo = DepthBiasReprInfoPtr(new vk::VkDepthBiasRepresentationInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5266 		rasterizationPnext = pDepthBiasReprInfo.get();
5267 
5268 		const auto& reprInfo = m_testConfig.depthBiasReprInfo.get();
5269 		pDepthBiasReprInfo->depthBiasRepresentation	= reprInfo.depthBiasRepresentation;
5270 		pDepthBiasReprInfo->depthBiasExact			= reprInfo.depthBiasExact;
5271 	}
5272 #else
5273 	DE_ASSERT(!staticStreamInfo);
5274 	DE_ASSERT(!staticProvokingVtxInfo);
5275 	DE_ASSERT(!staticDepthClipEnableInfo);
5276 	DE_ASSERT(!staticDepthClipControlInfo);
5277 	DE_ASSERT(!m_testConfig.conservativeRasterStruct());
5278 	DE_UNREF(staticStreamInfo);
5279 	DE_UNREF(staticProvokingVtxInfo);
5280 	DE_UNREF(staticDepthClipEnableInfo);
5281 	DE_UNREF(staticDepthClipControlInfo);
5282 #endif // CTS_USES_VULKANSC
5283 
5284 	using LineRasterModePtr		= de::MovePtr<vk::VkPipelineRasterizationLineStateCreateInfoEXT>;
5285 	LineRasterModePtr	pLineRasterModeInfo;
5286 
5287 	if (m_testConfig.lineRasterStruct())
5288 	{
5289 		DE_ASSERT(static_cast<bool>(m_testConfig.lineStippleParamsConfig.staticValue));
5290 
5291 		pLineRasterModeInfo = LineRasterModePtr(new vk::VkPipelineRasterizationLineStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5292 		rasterizationPnext = pLineRasterModeInfo.get();
5293 
5294 		const auto&	lineRasterFeatures	= m_context.getLineRasterizationFeaturesEXT();
5295 		const auto	lineRasterMode		= selectLineRasterizationMode(lineRasterFeatures, m_testConfig.lineStippleSupportRequired(), m_testConfig.lineRasterModeConfig.staticValue);
5296 		const auto&	staticParams		= m_testConfig.lineStippleParamsConfig.staticValue.get();
5297 
5298 		pLineRasterModeInfo->stippledLineEnable		= m_testConfig.lineStippleEnableConfig.staticValue;
5299 		pLineRasterModeInfo->lineRasterizationMode	= makeLineRasterizationMode(lineRasterMode);
5300 		pLineRasterModeInfo->lineStippleFactor		= staticParams.factor;
5301 		pLineRasterModeInfo->lineStipplePattern		= staticParams.pattern;
5302 	}
5303 
5304 	const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
5305 	{
5306 		vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
5307 		rasterizationPnext,												//	const void*								pNext;
5308 		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
5309 		makeVkBool32(m_testConfig.depthClampEnableConfig.staticValue),	//	VkBool32								depthClampEnable;
5310 		makeVkBool32(m_testConfig.rastDiscardEnableConfig.staticValue),	//	VkBool32								rasterizerDiscardEnable;
5311 		m_testConfig.polygonModeConfig.staticValue,						//	VkPolygonMode							polygonMode;
5312 		m_testConfig.cullModeConfig.staticValue,						//	VkCullModeFlags							cullMode;
5313 		m_testConfig.frontFaceConfig.staticValue,						//	VkFrontFace								frontFace;
5314 		makeVkBool32(m_testConfig.depthBiasEnableConfig.staticValue),	//	VkBool32								depthBiasEnable;
5315 		m_testConfig.depthBiasConfig.staticValue.constantFactor,		//	float									depthBiasConstantFactor;
5316 		m_testConfig.depthBiasConfig.staticValue.clamp,					//	float									depthBiasClamp;
5317 		0.0f,															//	float									depthBiasSlopeFactor;
5318 		m_testConfig.lineWidthConfig.staticValue,						//	float									lineWidth;
5319 	};
5320 
5321 	using SampleLocationsPtr = de::MovePtr<vk::VkPipelineSampleLocationsStateCreateInfoEXT>;
5322 	SampleLocationsPtr						pSampleLocations;
5323 	std::vector<vk::VkSampleLocationEXT>	sampleLocationCoords;
5324 
5325 #ifndef CTS_USES_VULKANSC
5326 	using CoverageToColorPtr = de::MovePtr<vk::VkPipelineCoverageToColorStateCreateInfoNV>;
5327 	CoverageToColorPtr						pCoverageToColor;
5328 
5329 	using CoverageModulationPtr = de::MovePtr<vk::VkPipelineCoverageModulationStateCreateInfoNV>;
5330 	CoverageModulationPtr					pCoverageModulation;
5331 
5332 	using CoverageReductionPtr = de::MovePtr<vk::VkPipelineCoverageReductionStateCreateInfoNV>;
5333 	CoverageReductionPtr					pCoverageReduction;
5334 
5335 	using ViewportSwizzlePtr = de::MovePtr<vk::VkPipelineViewportSwizzleStateCreateInfoNV>;
5336 	ViewportSwizzlePtr						pViewportSwizzle;
5337 
5338 	using ShadingRateImagePtr = de::MovePtr<vk::VkPipelineViewportShadingRateImageStateCreateInfoNV>;
5339 	ShadingRateImagePtr						pShadingRateImage;
5340 
5341 	using ViewportWScalingPtr = de::MovePtr<vk::VkPipelineViewportWScalingStateCreateInfoNV>;
5342 	ViewportWScalingPtr						pViewportWScaling;
5343 
5344 	using ReprFragmentPtr = de::MovePtr<vk::VkPipelineRepresentativeFragmentTestStateCreateInfoNV>;
5345 	ReprFragmentPtr							pReprFragment;
5346 #endif // CTS_USES_VULKANSC
5347 
5348 	if (m_testConfig.sampleLocationsStruct())
5349 	{
5350 		pSampleLocations = SampleLocationsPtr(new vk::VkPipelineSampleLocationsStateCreateInfoEXT(vk::initVulkanStructure(multisamplePnext)));
5351 		multisamplePnext = pSampleLocations.get();
5352 
5353 		pSampleLocations->sampleLocationsEnable							= makeVkBool32(m_testConfig.sampleLocationsEnableConfig.staticValue);
5354 		pSampleLocations->sampleLocationsInfo							= vk::initVulkanStructure();
5355 		pSampleLocations->sampleLocationsInfo.sampleLocationsPerPixel	= activeSampleCount;
5356 		pSampleLocations->sampleLocationsInfo.sampleLocationGridSize	= vk::makeExtent2D(1u, 1u);
5357 		pSampleLocations->sampleLocationsInfo.sampleLocationsCount		= static_cast<uint32_t>(activeSampleCount);
5358 
5359 		sampleLocationCoords.reserve(pSampleLocations->sampleLocationsInfo.sampleLocationsCount);
5360 		for (uint32_t i = 0; i < pSampleLocations->sampleLocationsInfo.sampleLocationsCount; ++i)
5361 			sampleLocationCoords.push_back(vk::VkSampleLocationEXT{m_testConfig.sampleLocations.x(), m_testConfig.sampleLocations.y()});
5362 
5363 		pSampleLocations->sampleLocationsInfo.pSampleLocations = sampleLocationCoords.data();
5364 	}
5365 
5366 #ifndef CTS_USES_VULKANSC
5367 	if (m_testConfig.coverageToColorStruct())
5368 	{
5369 		pCoverageToColor = CoverageToColorPtr(new vk::VkPipelineCoverageToColorStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
5370 		multisamplePnext = pCoverageToColor.get();
5371 
5372 		pCoverageToColor->coverageToColorEnable		= makeVkBool32(m_testConfig.coverageToColorEnableConfig.staticValue);
5373 		pCoverageToColor->coverageToColorLocation	= m_testConfig.coverageToColorLocationConfig.staticValue;
5374 	}
5375 
5376 	if (m_testConfig.coverageModulation)
5377 	{
5378 		pCoverageModulation	= CoverageModulationPtr(new vk::VkPipelineCoverageModulationStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
5379 		multisamplePnext	= pCoverageModulation.get();
5380 
5381 		pCoverageModulation->coverageModulationMode			= m_testConfig.coverageModulationModeConfig.staticValue;
5382 		pCoverageModulation->coverageModulationTableEnable	= makeVkBool32(m_testConfig.coverageModTableEnableConfig.staticValue);
5383 		pCoverageModulation->coverageModulationTableCount	= static_cast<uint32_t>(m_testConfig.coverageModTableConfig.staticValue.size());
5384 		pCoverageModulation->pCoverageModulationTable		= de::dataOrNull(m_testConfig.coverageModTableConfig.staticValue);
5385 	}
5386 
5387 	if (m_testConfig.coverageReduction)
5388 	{
5389 		pCoverageReduction	= CoverageReductionPtr(new vk::VkPipelineCoverageReductionStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
5390 		multisamplePnext	= pCoverageReduction.get();
5391 
5392 		pCoverageReduction->coverageReductionMode = m_testConfig.coverageReductionModeConfig.staticValue;
5393 	}
5394 
5395 	if (m_testConfig.viewportSwizzle)
5396 	{
5397 		pViewportSwizzle	= ViewportSwizzlePtr(new vk::VkPipelineViewportSwizzleStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
5398 		viewportPnext		= pViewportSwizzle.get();
5399 
5400 		const auto& swizzleVec				= m_testConfig.viewportSwizzleConfig.staticValue;
5401 		pViewportSwizzle->viewportCount		= static_cast<uint32_t>(swizzleVec.size());
5402 		pViewportSwizzle->pViewportSwizzles	= de::dataOrNull(swizzleVec);
5403 	}
5404 
5405 	const vk::VkShadingRatePaletteEntryNV	defaultShadingRatePaletteEntry	= vk::VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV;
5406 	const auto								defaultShadingRatePalette		= vk::makeShadingRatePaletteNV(1u, &defaultShadingRatePaletteEntry);
5407 	std::vector<vk::VkShadingRatePaletteNV>	shadingRatePaletteVec;
5408 
5409 	const auto								defaultViewportWScalingFactors	= vk::makeViewportWScalingNV(-1.0f, -1.0f);
5410 	std::vector<vk::VkViewportWScalingNV>	viewportWScalingVec;
5411 
5412 	if (m_testConfig.shadingRateImage)
5413 	{
5414 		pShadingRateImage	= ShadingRateImagePtr(new vk::VkPipelineViewportShadingRateImageStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
5415 		viewportPnext		= pShadingRateImage.get();
5416 
5417 		const auto& viewportVec						= m_testConfig.getActiveViewportVec();
5418 		pShadingRateImage->shadingRateImageEnable	= makeVkBool32(m_testConfig.shadingRateImageEnableConfig.staticValue);
5419 		pShadingRateImage->viewportCount			= de::sizeU32(viewportVec);
5420 
5421 		shadingRatePaletteVec.resize(viewportVec.size(), defaultShadingRatePalette);
5422 		pShadingRateImage->pShadingRatePalettes = shadingRatePaletteVec.data();
5423 	}
5424 
5425 	if (m_testConfig.viewportWScaling)
5426 	{
5427 		pViewportWScaling	= ViewportWScalingPtr(new vk::VkPipelineViewportWScalingStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
5428 		viewportPnext		= pViewportWScaling.get();
5429 
5430 		const auto& viewportVec						= m_testConfig.getActiveViewportVec();
5431 		pViewportWScaling->viewportWScalingEnable	= makeVkBool32(m_testConfig.viewportWScalingEnableConfig.staticValue);
5432 		pViewportWScaling->viewportCount			= de::sizeU32(viewportVec);
5433 
5434 		viewportWScalingVec.resize(viewportVec.size(), defaultViewportWScalingFactors);
5435 		pViewportWScaling->pViewportWScalings = viewportWScalingVec.data();
5436 	}
5437 
5438 	if (m_testConfig.representativeFragmentTest)
5439 	{
5440 		pReprFragment = ReprFragmentPtr(new vk::VkPipelineRepresentativeFragmentTestStateCreateInfoNV(vk::initVulkanStructure()));
5441 		pReprFragment->representativeFragmentTestEnable = makeVkBool32(m_testConfig.reprFragTestEnableConfig.staticValue);
5442 	}
5443 #endif // CTS_USES_VULKANSC
5444 
5445 	// Multisample state.
5446 	const vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
5447 	{
5448 		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
5449 		multisamplePnext,												//	const void*								pNext;
5450 		0u,																//	VkPipelineMultisampleStateCreateFlags	flags;
5451 		m_testConfig.rasterizationSamplesConfig.staticValue,			//	VkSampleCountFlagBits					rasterizationSamples;
5452 		makeVkBool32(m_testConfig.sampleShadingEnable),					//	VkBool32								sampleShadingEnable;
5453 		m_testConfig.minSampleShading,									//	float									minSampleShading;
5454 		de::dataOrNull(m_testConfig.sampleMaskConfig.staticValue),		//	const VkSampleMask*						pSampleMask;
5455 		makeVkBool32(m_testConfig.alphaToCoverageConfig.staticValue),	//	VkBool32								alphaToCoverageEnable;
5456 		makeVkBool32(m_testConfig.alphaToOneConfig.staticValue),		//	VkBool32								alphaToOneEnable;
5457 	};
5458 
5459 	// Depth/stencil state.
5460 	vk::VkStencilOpState	staticFrontStencil;
5461 	vk::VkStencilOpState	staticBackStencil;
5462 	bool					staticFrontStencilSet	= false;
5463 	bool					staticBackStencilSet	= false;
5464 
5465 	// Common setup for the front and back operations.
5466 	staticFrontStencil.compareMask	= 0xFFu;
5467 	staticFrontStencil.writeMask	= 0xFFu;
5468 	staticFrontStencil.reference	= m_testConfig.referenceStencil;
5469 	staticBackStencil				= staticFrontStencil;
5470 
5471 	for (const auto& op : m_testConfig.stencilOpConfig.staticValue)
5472 	{
5473 		if ((op.faceMask & vk::VK_STENCIL_FACE_FRONT_BIT) != 0u)
5474 		{
5475 			copy(staticFrontStencil, op);
5476 			staticFrontStencilSet = true;
5477 		}
5478 		if ((op.faceMask & vk::VK_STENCIL_FACE_BACK_BIT) != 0u)
5479 		{
5480 			copy(staticBackStencil, op);
5481 			staticBackStencilSet = true;
5482 		}
5483 	}
5484 
5485 	// Default values for the static part.
5486 	if (!staticFrontStencilSet)
5487 		copy(staticFrontStencil, kDefaultStencilOpParams);
5488 	if (!staticBackStencilSet)
5489 		copy(staticBackStencil, kDefaultStencilOpParams);
5490 
5491 	const vk::VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
5492 	{
5493 		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		//	VkStructureType							sType;
5494 		nullptr,															//	const void*								pNext;
5495 		0u,																	//	VkPipelineDepthStencilStateCreateFlags	flags;
5496 		makeVkBool32(m_testConfig.depthTestEnableConfig.staticValue),		//	VkBool32								depthTestEnable;
5497 		makeVkBool32(m_testConfig.depthWriteEnableConfig.staticValue),		//	VkBool32								depthWriteEnable;
5498 		m_testConfig.depthCompareOpConfig.staticValue,						//	VkCompareOp								depthCompareOp;
5499 		makeVkBool32(m_testConfig.depthBoundsTestEnableConfig.staticValue),	//	VkBool32								depthBoundsTestEnable;
5500 		makeVkBool32(m_testConfig.stencilTestEnableConfig.staticValue),		//	VkBool32								stencilTestEnable;
5501 		staticFrontStencil,													//	VkStencilOpState						front;
5502 		staticBackStencil,													//	VkStencilOpState						back;
5503 		m_testConfig.depthBoundsConfig.staticValue.first,					//	float									minDepthBounds;
5504 		m_testConfig.depthBoundsConfig.staticValue.second,					//	float									maxDepthBounds;
5505 	};
5506 
5507 	// Dynamic state. Here we will set all states which have a dynamic value.
5508 	const auto dynamicStates = m_testConfig.getDynamicStates();
5509 
5510 	const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
5511 	{
5512 		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
5513 		nullptr,													//	const void*							pNext;
5514 		0u,															//	VkPipelineDynamicStateCreateFlags	flags;
5515 		static_cast<deUint32>(dynamicStates.size()),				//	deUint32							dynamicStateCount;
5516 		de::dataOrNull(dynamicStates),								//	const VkDynamicState*				pDynamicStates;
5517 	};
5518 
5519 	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
5520 	{
5521 		makeVkBool32(m_testConfig.colorBlendEnableConfig.staticValue),			// VkBool32                 blendEnable
5522 		m_testConfig.colorBlendEquationConfig.staticValue.srcColorBlendFactor,	// VkBlendFactor            srcColorBlendFactor
5523 		m_testConfig.colorBlendEquationConfig.staticValue.dstColorBlendFactor,	// VkBlendFactor            dstColorBlendFactor
5524 		m_testConfig.colorBlendEquationConfig.staticValue.colorBlendOp,			// VkBlendOp                colorBlendOp
5525 		m_testConfig.colorBlendEquationConfig.staticValue.srcAlphaBlendFactor,	// VkBlendFactor            srcAlphaBlendFactor
5526 		m_testConfig.colorBlendEquationConfig.staticValue.dstAlphaBlendFactor,	// VkBlendFactor            dstAlphaBlendFactor
5527 		m_testConfig.colorBlendEquationConfig.staticValue.alphaBlendOp,			// VkBlendOp                alphaBlendOp
5528 		m_testConfig.colorWriteMaskConfig.staticValue,							// VkColorComponentFlags    colorWriteMask
5529 	};
5530 	const std::vector<vk::VkPipelineColorBlendAttachmentState> colorBlendAttachmentStateVec (kColorAttCount, colorBlendAttachmentState);
5531 
5532 	void* colorBlendPnext = nullptr;
5533 
5534 	using ColorBlendAdvancedPtr = de::MovePtr<vk::VkPipelineColorBlendAdvancedStateCreateInfoEXT>;
5535 	ColorBlendAdvancedPtr pColorBlendAdvanced;
5536 
5537 	if (m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced())
5538 	{
5539 		pColorBlendAdvanced						= ColorBlendAdvancedPtr(new vk::VkPipelineColorBlendAdvancedStateCreateInfoEXT(vk::initVulkanStructure(colorBlendPnext)));
5540 		pColorBlendAdvanced->srcPremultiplied	= VK_TRUE;
5541 		pColorBlendAdvanced->dstPremultiplied	= VK_TRUE;
5542 		pColorBlendAdvanced->blendOverlap		= vk::VK_BLEND_OVERLAP_UNCORRELATED_EXT;
5543 		colorBlendPnext							= pColorBlendAdvanced.get();
5544 	}
5545 
5546 	const std::vector<vk::VkBool32> colorWriteValues (colorBlendAttachmentStateVec.size(), m_testConfig.colorWriteEnableConfig.staticValue);
5547 
5548 	using ColorWriteEnablePtr = de::MovePtr<vk::VkPipelineColorWriteCreateInfoEXT>;
5549 	ColorWriteEnablePtr pColorWriteEnable;
5550 
5551 	if (m_testConfig.useColorWriteEnable)
5552 	{
5553 		pColorWriteEnable						= ColorWriteEnablePtr(new vk::VkPipelineColorWriteCreateInfoEXT(vk::initVulkanStructure(colorBlendPnext)));
5554 		pColorWriteEnable->attachmentCount		= de::sizeU32(colorWriteValues);
5555 		pColorWriteEnable->pColorWriteEnables	= de::dataOrNull(colorWriteValues);
5556 		colorBlendPnext							= pColorWriteEnable.get();
5557 	}
5558 
5559 	if (m_testConfig.nullStaticColorBlendAttPtr)
5560 	{
5561 		DE_ASSERT(static_cast<bool>(m_testConfig.colorBlendEnableConfig.dynamicValue));
5562 		DE_ASSERT(static_cast<bool>(m_testConfig.colorBlendEquationConfig.dynamicValue));
5563 		DE_ASSERT(static_cast<bool>(m_testConfig.colorWriteMaskConfig.dynamicValue));
5564 	}
5565 
5566 	const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
5567 	{
5568 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType                               sType
5569 		colorBlendPnext,												// const void*                                   pNext
5570 		0u,																// VkPipelineColorBlendStateCreateFlags          flags
5571 		m_testConfig.logicOpEnableConfig.staticValue,					// VkBool32                                      logicOpEnable
5572 		m_testConfig.logicOpConfig.staticValue,							// VkLogicOp                                     logicOp
5573 		static_cast<uint32_t>(colorBlendAttachmentStateVec.size()),		// deUint32                                      attachmentCount
5574 		(m_testConfig.nullStaticColorBlendAttPtr						// const VkPipelineColorBlendAttachmentState*    pAttachments
5575 			? nullptr
5576 			: de::dataOrNull(colorBlendAttachmentStateVec)),
5577 
5578 		{																// float                                         blendConstants[4]
5579 			m_testConfig.blendConstantsConfig.staticValue[0],
5580 			m_testConfig.blendConstantsConfig.staticValue[1],
5581 			m_testConfig.blendConstantsConfig.staticValue[2],
5582 			m_testConfig.blendConstantsConfig.staticValue[3],
5583 		},
5584 	};
5585 
5586 	vk::GraphicsPipelineWrapper	staticPipeline		(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(), m_testConfig.pipelineConstructionType);
5587 
5588 	// Create extra dynamic patch control points pipeline if needed.
5589 	vk::GraphicsPipelineWrapper extraDynPCPPipeline (vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(), m_testConfig.pipelineConstructionType);
5590 
5591 	if (m_testConfig.useExtraDynPCPPipeline)
5592 	{
5593 		vertDPCPModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vertDPCP"));
5594 		fragDPCPModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("fragDPCP"));
5595 
5596 		const vk::VkPipelineVertexInputStateCreateInfo	extraDPCPInputState		= vk::initVulkanStructure();
5597 		const vk::VkDynamicState						extraDynamicState		= vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
5598 		const vk::VkPipelineDynamicStateCreateInfo		extraDynamicStateInfo	=
5599 		{
5600 			vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
5601 			nullptr,													//	const void*							pNext;
5602 			0u,															//	VkPipelineDynamicStateCreateFlags	flags;
5603 			1u,															//	uint32_t							dynamicStateCount;
5604 			&extraDynamicState,											//	const VkDynamicState*				pDynamicStates;
5605 		};
5606 
5607 		const vk::PipelineLayoutWrapper extraPipelineLayout (m_testConfig.pipelineConstructionType, vkd, device);
5608 
5609 		const auto viewports	= m_testConfig.viewportConfig.staticValue;
5610 		const auto scissors		= m_testConfig.scissorConfig.staticValue;
5611 
5612 		extraDynPCPPipeline.setDynamicState(&extraDynamicStateInfo)
5613 						   .setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
5614 						   .setDefaultColorBlendState()
5615 						   .setDefaultMultisampleState()
5616 						   .setupVertexInputState(&extraDPCPInputState)
5617 						   .setupPreRasterizationShaderState(
5618 										viewports,
5619 										scissors,
5620 										extraPipelineLayout,
5621 										*renderPassFramebuffers[0],
5622 										0u,
5623 										vertDPCPModule,
5624 										&rasterizationStateCreateInfo)
5625 						   .setupFragmentShaderState(extraPipelineLayout, *renderPassFramebuffers[0], 0u, fragDPCPModule, &depthStencilStateCreateInfo)
5626 						   .setupFragmentOutputState(*renderPassFramebuffers[0], 0u)
5627 						   .setMonolithicPipelineLayout(extraPipelineLayout)
5628 						   .buildPipeline();
5629 	}
5630 	else if (m_testConfig.useExtraDynPipeline)
5631 	{
5632 		vertDPCPModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vertDPCP"));
5633 	}
5634 
5635 	// Create static pipeline when needed.
5636 	if (kUseStaticPipeline)
5637 	{
5638 		auto viewports	= m_testConfig.viewportConfig.staticValue;
5639 		auto scissors	= m_testConfig.scissorConfig.staticValue;
5640 
5641 		// The viewport and scissor counts must match in the static part, which will be used by the static pipeline.
5642 		const auto minStaticCount = static_cast<deUint32>(std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
5643 		viewports.resize(minStaticCount);
5644 		scissors.resize(minStaticCount);
5645 
5646 		staticPipeline.setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
5647 					  .setViewportStatePnext(viewportPnext)
5648 					  .setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue);
5649 
5650 		// The pAttachments pointer must never be null for the static pipeline.
5651 		vk::VkPipelineColorBlendStateCreateInfo staticCBStateInfo = colorBlendStateCreateInfo;
5652 		if (m_testConfig.nullStaticColorBlendAttPtr)
5653 			staticCBStateInfo.pAttachments = de::dataOrNull(colorBlendAttachmentStateVec);
5654 
5655 #ifndef CTS_USES_VULKANSC
5656 		if (m_testConfig.useMeshShaders)
5657 		{
5658 			staticPipeline.setupPreRasterizationMeshShaderState(
5659 												viewports,
5660 												scissors,
5661 												pipelineLayout,
5662 												*renderPassFramebuffers[0],
5663 												0u,
5664 												vk::ShaderWrapper(),
5665 												staticMeshModule,
5666 												&rasterizationStateCreateInfo);
5667 		}
5668 		else
5669 #endif // CTS_USES_VULKANSC
5670 		{
5671 			staticPipeline.setupVertexInputState(&vertexInputStateCreateInfo, &inputAssemblyStateCreateInfo)
5672 						  .setupPreRasterizationShaderState(
5673 												viewports,
5674 												scissors,
5675 												pipelineLayout,
5676 												*renderPassFramebuffers[0],
5677 												0u,
5678 												staticVertModule,
5679 												&rasterizationStateCreateInfo,
5680 												tescModule,
5681 												teseModule,
5682 												geomModule);
5683 		}
5684 
5685 		vk::ShaderWrapper			emptyFrag		{};
5686 		const vk::ShaderWrapper&	fragForStatic	= m_testConfig.rastDiscardEnableConfig.staticValue ? emptyFrag : staticFragModule;
5687 
5688 		staticPipeline
5689 #ifndef CTS_USES_VULKANSC
5690 					  .setRepresentativeFragmentTestState(pReprFragment.get())
5691 #endif // CTS_USES_VULKANSC
5692 					  .setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, fragForStatic, &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
5693 					  .setupFragmentOutputState(*renderPassFramebuffers[0], 0u, &staticCBStateInfo, &multisampleStateCreateInfo)
5694 					  .setMonolithicPipelineLayout(pipelineLayout)
5695 					  .buildPipeline();
5696 	}
5697 
5698 	// Create dynamic pipeline.
5699 	vk::GraphicsPipelineWrapper graphicsPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(), m_testConfig.pipelineConstructionType);
5700 	vk::GraphicsPipelineWrapper extraDynPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(), m_testConfig.pipelineConstructionType);
5701 	{
5702 		auto viewports	= m_testConfig.viewportConfig.staticValue;
5703 		auto scissors	= m_testConfig.scissorConfig.staticValue;
5704 
5705 		const auto finalDynamicViewportCount = (m_testConfig.viewportConfig.dynamicValue
5706 			? m_testConfig.viewportConfig.dynamicValue.get().size()
5707 			: m_testConfig.viewportConfig.staticValue.size());
5708 
5709 		const auto finalDynamicScissorCount = (m_testConfig.scissorConfig.dynamicValue
5710 			? m_testConfig.scissorConfig.dynamicValue.get().size()
5711 			: m_testConfig.scissorConfig.staticValue.size());
5712 
5713 		const auto minDynamicCount = static_cast<deUint32>(std::min(finalDynamicScissorCount, finalDynamicViewportCount));
5714 
5715 		// The viewport and scissor counts must be zero when a dynamic value will be provided, as per the spec.
5716 		if (m_testConfig.viewportConfig.dynamicValue)
5717 		{
5718 			graphicsPipeline.setDefaultViewportsCount();
5719 			if (m_testConfig.useExtraDynPipeline)
5720 				extraDynPipeline.setDefaultViewportsCount();
5721 			viewports = std::vector<vk::VkViewport>();
5722 		}
5723 		else
5724 			viewports.resize(minDynamicCount);
5725 
5726 		if (m_testConfig.scissorConfig.dynamicValue)
5727 		{
5728 			graphicsPipeline.setDefaultScissorsCount();
5729 			if (m_testConfig.useExtraDynPipeline)
5730 				extraDynPipeline.setDefaultScissorsCount();
5731 			scissors = std::vector<vk::VkRect2D>();
5732 		}
5733 		else
5734 			scissors.resize(minDynamicCount);
5735 
5736 		// Setting patch control points to std::numeric_limits<uint32_t>::max() will force null tessellation state pointer.
5737 		const auto patchControlPoints	= ((m_testConfig.favorStaticNullPointers && m_testConfig.patchControlPointsConfig.dynamicValue)
5738 										? std::numeric_limits<uint32_t>::max()
5739 										: m_testConfig.patchControlPointsConfig.staticValue);
5740 
5741 		const auto disableViewportState	= (m_testConfig.favorStaticNullPointers && m_testConfig.viewportConfig.dynamicValue && m_testConfig.scissorConfig.dynamicValue);
5742 
5743 		graphicsPipeline.setDynamicState(&dynamicStateCreateInfo)
5744 						.setDefaultPatchControlPoints(patchControlPoints)
5745 						.setViewportStatePnext(viewportPnext)
5746 						.setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue)
5747 						.disableViewportState(disableViewportState);
5748 		if (m_testConfig.useExtraDynPipeline)
5749 			extraDynPipeline.setDynamicState(&dynamicStateCreateInfo)
5750 							.setDefaultPatchControlPoints(patchControlPoints)
5751 							.setViewportStatePnext(viewportPnext)
5752 							.setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue)
5753 							.disableViewportState(disableViewportState);
5754 
5755 		const auto staticRasterizationStateCreateInfo	= ((m_testConfig.favorStaticNullPointers
5756 															&& m_testConfig.depthClampEnableConfig.dynamicValue
5757 															&& m_testConfig.rastDiscardEnableConfig.dynamicValue
5758 															&& m_testConfig.polygonModeConfig.dynamicValue
5759 															&& m_testConfig.cullModeConfig.dynamicValue
5760 															&& m_testConfig.frontFaceConfig.dynamicValue
5761 															&& m_testConfig.depthBiasEnableConfig.dynamicValue
5762 															&& m_testConfig.depthBiasConfig.dynamicValue
5763 															&& m_testConfig.lineWidthConfig.dynamicValue)
5764 														? nullptr
5765 														: &rasterizationStateCreateInfo);
5766 
5767 		DE_ASSERT(!m_testConfig.useExtraDynPipeline || !m_testConfig.useMeshShaders);
5768 
5769 		const vk::VkPipelineVertexInputStateCreateInfo emptyVertexInputStateCreateInfo =
5770 		{
5771 			vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
5772 			DE_NULL,														//	const void*									pNext;
5773 			0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
5774 			0u,																//	deUint32									vertexBindingDescriptionCount;
5775 			DE_NULL,														//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
5776 			0u,																//	deUint32									vertexAttributeDescriptionCount;
5777 			DE_NULL,														//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
5778 		};
5779 
5780 #ifndef CTS_USES_VULKANSC
5781 		if (m_testConfig.useMeshShaders)
5782 		{
5783 			graphicsPipeline.setupPreRasterizationMeshShaderState(
5784 												viewports,
5785 												scissors,
5786 												pipelineLayout,
5787 												*renderPassFramebuffers[0],
5788 												0u,
5789 												vk::ShaderWrapper(),
5790 												dynamicMeshModule,
5791 												staticRasterizationStateCreateInfo);
5792 		}
5793 		else
5794 #endif // CTS_USES_VULKANSC
5795 		{
5796 			const auto staticVertexInputStateCreateInfo		= ((m_testConfig.favorStaticNullPointers && m_testConfig.testVertexDynamic())
5797 															? nullptr
5798 															: &vertexInputStateCreateInfo);
5799 
5800 			const auto staticInputAssemblyStateCreateInfo	= ((m_testConfig.favorStaticNullPointers && m_testConfig.primRestartEnableConfig.dynamicValue && m_testConfig.topologyConfig.dynamicValue)
5801 															? nullptr
5802 															: &inputAssemblyStateCreateInfo);
5803 
5804 			graphicsPipeline.setupVertexInputState(
5805 												staticVertexInputStateCreateInfo,
5806 												staticInputAssemblyStateCreateInfo,
5807 												VK_NULL_HANDLE,
5808 												vk::PipelineCreationFeedbackCreateInfoWrapper(),
5809 												m_testConfig.favorStaticNullPointers)
5810 							.setupPreRasterizationShaderState(
5811 												viewports,
5812 												scissors,
5813 												pipelineLayout,
5814 												*renderPassFramebuffers[0],
5815 												0u,
5816 												dynamicVertModule,
5817 												staticRasterizationStateCreateInfo,
5818 												tescModule,
5819 												teseModule,
5820 												geomModule);
5821 
5822 			if (m_testConfig.useExtraDynPipeline)
5823 				extraDynPipeline.setupVertexInputState(
5824 													&emptyVertexInputStateCreateInfo,
5825 													staticInputAssemblyStateCreateInfo,
5826 													VK_NULL_HANDLE,
5827 													vk::PipelineCreationFeedbackCreateInfoWrapper(),
5828 													m_testConfig.favorStaticNullPointers)
5829 								.setupPreRasterizationShaderState(
5830 													viewports,
5831 													scissors,
5832 													pipelineLayout,
5833 													*renderPassFramebuffers[0],
5834 													0u,
5835 													vertDPCPModule,
5836 													staticRasterizationStateCreateInfo);
5837 		}
5838 
5839 		const auto staticMultisampleStateCreateInfo	= ((m_testConfig.favorStaticNullPointers
5840 														&& m_testConfig.rasterizationSamplesConfig.dynamicValue
5841 														&& m_testConfig.sampleMaskConfig.dynamicValue
5842 														&& m_testConfig.alphaToCoverageConfig.dynamicValue
5843 														&& m_testConfig.alphaToOneConfig.dynamicValue)
5844 													? nullptr
5845 													: &multisampleStateCreateInfo);
5846 
5847 		const auto staticDepthStencilStateCreateInfo	= ((m_testConfig.favorStaticNullPointers
5848 															&& m_testConfig.depthTestEnableConfig.dynamicValue
5849 															&& m_testConfig.depthWriteEnableConfig.dynamicValue
5850 															&& m_testConfig.depthCompareOpConfig.dynamicValue
5851 															&& m_testConfig.depthBoundsTestEnableConfig.dynamicValue
5852 															&& m_testConfig.stencilTestEnableConfig.dynamicValue
5853 															&& m_testConfig.stencilOpConfig.dynamicValue
5854 															&& m_testConfig.depthBoundsConfig.dynamicValue)
5855 														? nullptr
5856 														: &depthStencilStateCreateInfo);
5857 
5858 		const auto staticColorBlendStateCreateInfo		= ((m_testConfig.favorStaticNullPointers
5859 															&& m_testConfig.logicOpEnableConfig.dynamicValue
5860 															&& m_testConfig.logicOpConfig.dynamicValue
5861 															&& m_testConfig.colorBlendEnableConfig.dynamicValue
5862 															&& m_testConfig.colorBlendEquationConfig.dynamicValue
5863 															&& (m_testConfig.colorBlendBoth
5864 																|| !m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced())
5865 															&& m_testConfig.colorWriteMaskConfig.dynamicValue
5866 															&& m_testConfig.blendConstantsConfig.dynamicValue)
5867 														? nullptr
5868 														: &colorBlendStateCreateInfo);
5869 		graphicsPipeline
5870 #ifndef CTS_USES_VULKANSC
5871 						.setRepresentativeFragmentTestState(pReprFragment.get())
5872 #endif // CTS_USES_VULKANSC
5873 						.setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, dynamicFragModule, staticDepthStencilStateCreateInfo, staticMultisampleStateCreateInfo)
5874 						.setupFragmentOutputState(*renderPassFramebuffers[0], 0u, staticColorBlendStateCreateInfo, staticMultisampleStateCreateInfo)
5875 						.setMonolithicPipelineLayout(pipelineLayout)
5876 						.buildPipeline();
5877 		if (m_testConfig.useExtraDynPipeline)
5878 			extraDynPipeline
5879 	#ifndef CTS_USES_VULKANSC
5880 							.setRepresentativeFragmentTestState(pReprFragment.get())
5881 	#endif // CTS_USES_VULKANSC
5882 							.setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, dynamicFragModule, staticDepthStencilStateCreateInfo, staticMultisampleStateCreateInfo)
5883 							.setupFragmentOutputState(*renderPassFramebuffers[0], 0u, staticColorBlendStateCreateInfo, staticMultisampleStateCreateInfo)
5884 							.setMonolithicPipelineLayout(pipelineLayout)
5885 							.buildPipeline();
5886 	}
5887 
5888 	vk::GraphicsPipelineWrapper meshNoOutPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(), m_testConfig.pipelineConstructionType);
5889 
5890 #ifndef CTS_USES_VULKANSC
5891 	if (m_testConfig.bindUnusedMeshShadingPipeline)
5892 	{
5893 		// Remove dynamic states which are not compatible with mesh shading pipelines.
5894 		std::vector<vk::VkDynamicState> meshNoOutDynamicStates;
5895 		std::copy_if(begin(dynamicStates), end(dynamicStates), std::back_inserter(meshNoOutDynamicStates), isMeshShadingPipelineCompatible);
5896 
5897 		const vk::VkPipelineDynamicStateCreateInfo meshNoOutDynamicStateInfo =
5898 		{
5899 			vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
5900 			nullptr,													//	const void*							pNext;
5901 			0u,															//	VkPipelineDynamicStateCreateFlags	flags;
5902 			de::sizeU32(meshNoOutDynamicStates),						//	uint32_t							dynamicStateCount;
5903 			de::dataOrNull(meshNoOutDynamicStates),						//	const VkDynamicState*				pDynamicStates;
5904 		};
5905 
5906 		// Provide a viewport state similar to the static pipeline.
5907 		auto viewports	= m_testConfig.viewportConfig.staticValue;
5908 		auto scissors	= m_testConfig.scissorConfig.staticValue;
5909 
5910 		const auto minStaticCount = static_cast<deUint32>(std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
5911 		viewports.resize(minStaticCount);
5912 		scissors.resize(minStaticCount);
5913 
5914 		meshNoOutPipeline.setDynamicState(&meshNoOutDynamicStateInfo)
5915 						 .setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
5916 						 .setupPreRasterizationMeshShaderState(
5917 											viewports,
5918 											scissors,
5919 											pipelineLayout,
5920 											*renderPassFramebuffers[0],
5921 											0u,
5922 											vk::ShaderWrapper(),
5923 											meshNoOutModule,
5924 											&rasterizationStateCreateInfo)
5925 						 .setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, vk::ShaderWrapper(), &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
5926 						 .setupFragmentOutputState(*renderPassFramebuffers[0], 0u, &colorBlendStateCreateInfo, &multisampleStateCreateInfo)
5927 						 .setMonolithicPipelineLayout(pipelineLayout)
5928 						 .buildPipeline();
5929 	}
5930 #endif // CTS_USES_VULKANSC
5931 
5932 	// Command buffer.
5933 	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
5934 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd , device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5935 	const auto cmdBuffer	= cmdBufferPtr.get();
5936 
5937 	// Clear values, clear to green for dynamic logicOp
5938 	std::vector<vk::VkClearValue> clearValues (kColorAttCount, m_testConfig.clearColorValue);
5939 	clearValues.push_back(vk::makeClearValueDepthStencil(m_testConfig.clearDepthValue, m_testConfig.clearStencilValue));
5940 
5941 	// Record command buffer.
5942 	vk::beginCommandBuffer(vkd, cmdBuffer);
5943 
5944 	for (deUint32 iteration = 0u; iteration < kNumIterations; ++iteration)
5945 	{
5946 		// Track in-advance vertex buffer binding.
5947 		bool boundInAdvance = false;
5948 
5949 		// Maybe set extended dynamic state here.
5950 		if (kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START)
5951 		{
5952 			setDynamicStates(m_testConfig, vkd, cmdBuffer);
5953 			boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
5954 		}
5955 
5956 		// Begin render pass.
5957 		renderPassFramebuffers[iteration].begin(vkd, cmdBuffer, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
5958 
5959 			// Bind a static pipeline first if needed.
5960 			if (kBindStaticFirst && iteration == 0u)
5961 				staticPipeline.bind(cmdBuffer);
5962 
5963 			// Maybe set extended dynamic state here.
5964 			if (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES)
5965 			{
5966 				setDynamicStates(m_testConfig, vkd, cmdBuffer);
5967 				boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
5968 			}
5969 
5970 			// Bind dynamic pipeline.
5971 			if ((kSequenceOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC &&
5972 				 kSequenceOrdering != SequenceOrdering::TWO_DRAWS_STATIC) ||
5973 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
5974 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
5975 			{
5976 				if (m_testConfig.bindUnusedMeshShadingPipeline)
5977 				{
5978 					DE_ASSERT(kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START);
5979 					meshNoOutPipeline.bind(cmdBuffer);
5980 				}
5981 
5982 				if (m_testConfig.useExtraDynPCPPipeline)
5983 				{
5984 					extraDynPCPPipeline.bind(cmdBuffer);
5985 
5986 					// In these two sequence orderings, the right dynamic state value will have been set before and we would be
5987 					// setting it to a wrong value here, resulting in test failures. We keep the right value instead.
5988 					if (kSequenceOrdering != SequenceOrdering::CMD_BUFFER_START && kSequenceOrdering != SequenceOrdering::BETWEEN_PIPELINES)
5989 						vkd.cmdSetPatchControlPointsEXT(cmdBuffer, m_testConfig.patchControlPointsConfig.staticValue);
5990 
5991 					vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
5992 				}
5993 
5994 				if (m_testConfig.useExtraDynPipeline)
5995 				{
5996 					extraDynPipeline.bind(cmdBuffer);
5997 
5998 					if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW || kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES || kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC)
5999 						setDynamicStates(m_testConfig, vkd, cmdBuffer);
6000 
6001 					vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
6002 				}
6003 
6004 				graphicsPipeline.bind(cmdBuffer);
6005 
6006 				// When shader objects are used vkCmdSetVertexInput() will overwrite vkCmdBindBuffers2 so we have to call it again
6007 				if (boundInAdvance && vk::isConstructionTypeShaderObject(m_testConfig.pipelineConstructionType))
6008 					maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
6009 			}
6010 
6011 			if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
6012 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
6013 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
6014 			{
6015 				setDynamicStates(m_testConfig, vkd, cmdBuffer);
6016 				boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
6017 			}
6018 
6019 			// Bind a static pipeline last if needed.
6020 			if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
6021 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration > 0u))
6022 			{
6023 				staticPipeline.bind(cmdBuffer);
6024 			}
6025 
6026 			const auto& viewportVec = m_testConfig.getActiveViewportVec();
6027 			for (size_t viewportIdx = 0u; viewportIdx < viewportVec.size(); ++viewportIdx)
6028 			{
6029 				for (size_t meshIdx = 0u; meshIdx < m_testConfig.meshParams.size(); ++meshIdx)
6030 				{
6031 					// Push constants.
6032 					PushConstants pushConstants =
6033 					{
6034 						m_testConfig.meshParams[meshIdx].color,			//	tcu::Vec4	triangleColor;
6035 						m_testConfig.meshParams[meshIdx].depth,			//	float		meshDepth;
6036 						static_cast<deInt32>(viewportIdx),				//	deInt32		viewPortIndex;
6037 						m_testConfig.meshParams[meshIdx].scaleX,		//	float		scaleX;
6038 						m_testConfig.meshParams[meshIdx].scaleY,		//	float		scaleY;
6039 						m_testConfig.meshParams[meshIdx].offsetX,		//	float		offsetX;
6040 						m_testConfig.meshParams[meshIdx].offsetY,		//	float		offsetY;
6041 						m_testConfig.meshParams[meshIdx].stripScale,	//	float		stripScale;
6042 					};
6043 					vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantStageFlags, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
6044 
6045 					// Track vertex bounding state for this mesh.
6046 					bool boundBeforeDraw = false;
6047 
6048 					// Maybe set extended dynamic state here.
6049 					if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW || kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES)
6050 					{
6051 						setDynamicStates(m_testConfig, vkd, cmdBuffer);
6052 						boundBeforeDraw = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, meshIdx, vertBuffers, rvertBuffers);
6053 					}
6054 
6055 					// Bind vertex buffer with static stride if needed and draw.
6056 					if (!(boundInAdvance || boundBeforeDraw) && !m_testConfig.useMeshShaders)
6057 					{
6058 						bindVertexBuffers(vkd, cmdBuffer, (m_testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers));
6059 						if (m_testConfig.needsIndexBuffer())
6060 						{
6061 							const auto indexType = vk::VK_INDEX_TYPE_UINT32;
6062 							vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer->get(), 0, indexType);
6063 						}
6064 					}
6065 
6066 					if (vertDataAsSSBO)
6067 					{
6068 						if (topologyClass == TopologyClass::LINE)
6069 							DE_ASSERT(!m_testConfig.meshParams[meshIdx].reversed);
6070 
6071 						const auto boundSet = (m_testConfig.meshParams[meshIdx].reversed ? meshDescriptorSetRev.get() : meshDescriptorSet.get());
6072 						vkd.cmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, pipelineLayout.get(), 0u, 1u, &boundSet, 0u, nullptr);
6073 					}
6074 
6075 #ifndef CTS_USES_VULKANSC
6076 					// Shading rate image if enabled (we'll use a null handle to simplify, which is valid).
6077 					if (m_testConfig.shadingRateImage)
6078 						vkd.cmdBindShadingRateImageNV(cmdBuffer, VK_NULL_HANDLE, vk::VK_IMAGE_LAYOUT_GENERAL);
6079 #endif // CTS_USES_VULKANSC
6080 
6081 					if (kFragAtomics)
6082 						vkd.cmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, pipelineLayout.get(), m_testConfig.getFragDescriptorSetIndex(), 1u, &fragDescriptorSet.get(), 0u, nullptr);
6083 
6084 					// Draw mesh.
6085 					if (m_testConfig.needsIndexBuffer())
6086 					{
6087 						deUint32 numIndices = static_cast<deUint32>(indices.size());
6088 						// For SequenceOrdering::TWO_DRAWS_DYNAMIC and TWO_DRAWS_STATIC cases, the first draw does not have primitive restart enabled
6089 						// So, draw without using the invalid index, the second draw with primitive restart enabled will replace the results
6090 						// using all indices.
6091 						if (iteration == 0u && m_testConfig.testPrimRestartEnable() &&
6092 							(m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
6093 							m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
6094 						{
6095 							numIndices = 2u;
6096 						}
6097 						vkd.cmdDrawIndexed(cmdBuffer, numIndices, m_testConfig.instanceCount, 0u, 0u, 0u);
6098 					}
6099 #ifndef CTS_USES_VULKANSC
6100 					else if (m_testConfig.useMeshShaders)
6101 					{
6102 						// Make sure drawing this way makes sense.
6103 						const auto minVertCount = ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
6104 						DE_UNREF(minVertCount); // For release builds.
6105 						DE_ASSERT(vertices.size() >= minVertCount);
6106 						DE_ASSERT(m_testConfig.instanceCount == 1u);
6107 						DE_ASSERT(!m_testConfig.topologyConfig.dynamicValue);
6108 
6109 						uint32_t numPrimitives = 0u;
6110 
6111 						if (topologyClass == TopologyClass::TRIANGLE)
6112 						{
6113 							DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
6114 							numPrimitives = de::sizeU32(vertices) - 2u;
6115 						}
6116 						else if (topologyClass == TopologyClass::LINE)
6117 						{
6118 							DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP);
6119 							const auto vertsPerRow = 4u;
6120 							const auto linesPerRow = 3u;
6121 							const auto vertexCount = de::sizeU32(vertices);
6122 							const auto rowCount = vertexCount / vertsPerRow;
6123 							numPrimitives = rowCount * linesPerRow;
6124 
6125 							if (m_testConfig.obliqueLine)
6126 								numPrimitives = 1u;
6127 							else
6128 								DE_ASSERT(vertexCount % vertsPerRow == 0u);
6129 						}
6130 						else
6131 							DE_ASSERT(false);
6132 
6133 						vkd.cmdDrawMeshTasksEXT(cmdBuffer, numPrimitives, 1u, 1u);
6134 					}
6135 #endif // CTS_USES_VULKANSC
6136 					else
6137 					{
6138 						uint32_t vertexCount = static_cast<deUint32>(vertices.size());
6139 						if (m_testConfig.singleVertex)
6140 							vertexCount = m_testConfig.singleVertexDrawCount;
6141 						vkd.cmdDraw(cmdBuffer, vertexCount, m_testConfig.instanceCount, 0u, 0u);
6142 					}
6143 				}
6144 			}
6145 
6146 		renderPassFramebuffers[iteration].end(vkd, cmdBuffer);
6147 	}
6148 
6149 	if (kFragAtomics)
6150 	{
6151 		const auto bufferBarrier = vk::makeMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT);
6152 		vk::cmdPipelineMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, &bufferBarrier);
6153 	}
6154 
6155 	vk::endCommandBuffer(vkd, cmdBuffer);
6156 
6157 	// Submit commands.
6158 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
6159 
6160 	// Read result image aspects from the last used framebuffer.
6161 	using LevelPtr = de::MovePtr<tcu::TextureLevel>;
6162 
6163 	const tcu::UVec2	renderSize		(kFramebufferWidth, kFramebufferHeight);
6164 
6165 	const auto			colorResultImg	= (kUseResolveAtt ? resolveImages.back()->get() : colorImages.back()->get());
6166 	const auto			colorBuffer		= readColorAttachment(vkd, device, queue, queueIndex, allocator, colorResultImg, colorFormat, renderSize);
6167 	const auto			colorAccess		= colorBuffer->getAccess();
6168 
6169 	LevelPtr				depthBuffer;
6170 	LevelPtr				stencilBuffer;
6171 	tcu::PixelBufferAccess	depthAccess;
6172 	tcu::PixelBufferAccess	stencilAccess;
6173 
6174 	if (!kMultisampleDS)
6175 	{
6176 		depthBuffer		= readDepthAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize);
6177 		stencilBuffer	= readStencilAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
6178 		depthAccess		= depthBuffer->getAccess();
6179 		stencilAccess	= stencilBuffer->getAccess();
6180 	}
6181 
6182 	const int kWidth	= static_cast<int>(kFramebufferWidth);
6183 	const int kHeight	= static_cast<int>(kFramebufferHeight);
6184 
6185 	// Generate reference color buffer.
6186 	const auto				tcuColorFormat			= vk::mapVkFormat(colorFormat);
6187 	tcu::TextureLevel		referenceColorLevel		(tcuColorFormat, kWidth, kHeight);
6188 	tcu::PixelBufferAccess	referenceColorAccess	= referenceColorLevel.getAccess();
6189 	(*m_testConfig.referenceColor)(referenceColorAccess);
6190 
6191 	const tcu::TextureFormat	errorFormat			(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
6192 	tcu::TextureLevel			colorError			(errorFormat, kWidth, kHeight);
6193 	tcu::TextureLevel			depthError			(errorFormat, kWidth, kHeight);
6194 	tcu::TextureLevel			stencilError		(errorFormat, kWidth, kHeight);
6195 	const auto					colorErrorAccess	= colorError.getAccess();
6196 	const auto					depthErrorAccess	= depthError.getAccess();
6197 	const auto					stencilErrorAccess	= stencilError.getAccess();
6198 	const tcu::Vec4				kGood				(0.0f, 1.0f, 0.0f, 1.0f);
6199 	const tcu::Vec4				kBad				(1.0f, 0.0f, 0.0f, 1.0f);
6200 
6201 	// Check expected values.
6202 	const bool	hasCustomVerif	= static_cast<bool>(m_testConfig.colorVerificator);
6203 	const auto	minDepth		= m_testConfig.expectedDepth - dsFormatInfo->depthThreshold - m_testConfig.extraDepthThreshold;
6204 	const auto	maxDepth		= m_testConfig.expectedDepth + dsFormatInfo->depthThreshold + m_testConfig.extraDepthThreshold;
6205 	bool		colorMatch		= true;
6206 	bool		depthMatch		= true;
6207 	bool		stencilMatch	= true;
6208 	bool		match;
6209 
6210 	if (hasCustomVerif)
6211 		colorMatch = (*m_testConfig.colorVerificator)(colorAccess, referenceColorAccess, colorErrorAccess);
6212 
6213 	for (int y = 0; y < kHeight; ++y)
6214 		for (int x = 0; x < kWidth; ++x)
6215 		{
6216 			if (!hasCustomVerif)
6217 			{
6218 				if (vk::isUnormFormat(colorFormat))
6219 				{
6220 					const auto colorPixel		= colorAccess.getPixel(x, y);
6221 					const auto expectedPixel	= referenceColorAccess.getPixel(x, y);
6222 					match = tcu::boolAll(tcu::lessThan(tcu::absDiff(colorPixel, expectedPixel), kUnormColorThreshold));
6223 				}
6224 				else
6225 				{
6226 					DE_ASSERT(vk::isUintFormat(colorFormat));
6227 					const auto colorPixel		= colorAccess.getPixelUint(x, y);
6228 					const auto expectedPixel	= referenceColorAccess.getPixelUint(x, y);
6229 					match = (colorPixel == expectedPixel);
6230 				}
6231 
6232 				colorErrorAccess.setPixel((match ? kGood : kBad), x, y);
6233 				if (!match)
6234 					colorMatch = false;
6235 			}
6236 
6237 			if (!kMultisampleDS)
6238 			{
6239 				const auto depthPixel = depthAccess.getPixDepth(x, y);
6240 				match = de::inRange(depthPixel, minDepth, maxDepth);
6241 				depthErrorAccess.setPixel((match ? kGood : kBad), x, y);
6242 				if (!match)
6243 					depthMatch = false;
6244 
6245 				const auto stencilPixel = static_cast<deUint32>(stencilAccess.getPixStencil(x, y));
6246 				match = (stencilPixel == m_testConfig.expectedStencil);
6247 				stencilErrorAccess.setPixel((match ? kGood : kBad), x, y);
6248 				if (!match)
6249 					stencilMatch = false;
6250 			}
6251 		}
6252 
6253 	if (!(colorMatch && depthMatch && stencilMatch))
6254 	{
6255 		if (!colorMatch)
6256 			logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
6257 
6258 		if (!depthMatch)
6259 			logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
6260 
6261 		if (!stencilMatch)
6262 			logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
6263 
6264 		if (!(colorMatch && depthMatch && stencilMatch))
6265 			return tcu::TestStatus::fail("Incorrect value found in attachments; please check logged images");
6266 	}
6267 
6268 	// Check storage buffer if used.
6269 	uint32_t fragCounter = 0u;
6270 
6271 	if (kFragAtomics)
6272 	{
6273 		DE_ASSERT(m_testConfig.oversizedTriangle);
6274 		DE_ASSERT(m_testConfig.meshParams.size() == 1u);
6275 		DE_ASSERT(!m_testConfig.depthWriteEnableConfig.dynamicValue);	// No dynamic value for depth writes.
6276 		DE_ASSERT(!m_testConfig.depthWriteEnableConfig.staticValue);	// No depth writes.
6277 
6278 		auto& counterBufferAlloc	= counterBuffer->getAllocation();
6279 		void* counterBufferData		= counterBufferAlloc.getHostPtr();
6280 		vk::invalidateAlloc(vkd, device, counterBufferAlloc);
6281 
6282 		deMemcpy(&fragCounter, counterBufferData, sizeof(fragCounter));
6283 	}
6284 
6285 	if (m_testConfig.representativeFragmentTest)
6286 	{
6287 		DE_ASSERT(!m_testConfig.rasterizationSamplesConfig.dynamicValue);
6288 
6289 		// The expected number of invocations depends on how many draws are performed with the test enabled.
6290 		// Draws with the test disabled should always result in kFramebufferHeight * kFramebufferWidth invocations.
6291 		// Draws with the test enabled should result in at least 1 invocation, maybe more.
6292 		uint32_t minValue = 0u;
6293 
6294 		const uint32_t minInvocations[] =
6295 		{
6296 			(kFramebufferHeight * kFramebufferWidth * static_cast<uint32_t>(m_testConfig.rasterizationSamplesConfig.staticValue)),
6297 			1u,
6298 		};
6299 
6300 		if (kNumIterations == 1u)
6301 		{
6302 			const auto testEnabled	= m_testConfig.getActiveReprFragTestEnable();
6303 			minValue += minInvocations[testEnabled];
6304 		}
6305 		else if (kNumIterations == 2u)
6306 		{
6307 			for (uint32_t i = 0u; i < kNumIterations; ++i)
6308 			{
6309 				bool testEnabled = false;
6310 
6311 #ifndef CTS_USES_VULKANSC
6312 				// Actually varies depending on TWO_DRAWS_STATIC/_DYNAMIC, but does not affect results.
6313 				const bool staticDraw = (i == 0u);
6314 
6315 				if (staticDraw)
6316 					testEnabled = m_testConfig.reprFragTestEnableConfig.staticValue;
6317 				else
6318 				{
6319 					testEnabled	= (m_testConfig.reprFragTestEnableConfig.dynamicValue
6320 								? m_testConfig.reprFragTestEnableConfig.dynamicValue.get()
6321 								: m_testConfig.reprFragTestEnableConfig.staticValue);
6322 				}
6323 #endif // CTS_USES_VULKANSC
6324 
6325 				minValue += minInvocations[testEnabled];
6326 			}
6327 		}
6328 		else
6329 		{
6330 			DE_ASSERT(false);
6331 		}
6332 
6333 		log << tcu::TestLog::Message << "Fragment counter minimum value: " << minValue << tcu::TestLog::EndMessage;
6334 		log << tcu::TestLog::Message << "Fragment counter: " << fragCounter << tcu::TestLog::EndMessage;
6335 
6336 		if (fragCounter < minValue)
6337 		{
6338 			std::ostringstream msg;
6339 			msg << "Fragment shader invocation counter lower than expected: found " << fragCounter << " and expected at least " << minValue;
6340 			return tcu::TestStatus::fail(msg.str());
6341 		}
6342 	}
6343 	else if (kFragAtomics)
6344 	{
6345 		// The expected number of invocations depends on how many draws are performed and the sample count of each one.
6346 		// Draws with the test disabled should always result in kFramebufferHeight * kFramebufferWidth invocations.
6347 		// Draws with the test enabled should result in at least 1 invocation, maybe more.
6348 		uint32_t sampleCount = 0u;
6349 
6350 		if (kNumIterations == 1u)
6351 		{
6352 			sampleCount += static_cast<uint32_t>(m_testConfig.getActiveSampleCount());
6353 		}
6354 		else if (kNumIterations == 2u)
6355 		{
6356 			for (uint32_t i = 0u; i < kNumIterations; ++i)
6357 			{
6358 				// Actually varies depending on TWO_DRAWS_STATIC/_DYNAMIC, but does not affect results.
6359 				const bool staticDraw = (i == 0u);
6360 
6361 				if (staticDraw)
6362 					sampleCount += static_cast<uint32_t>(m_testConfig.rasterizationSamplesConfig.staticValue);
6363 				else
6364 				{
6365 					sampleCount += static_cast<uint32_t>(m_testConfig.rasterizationSamplesConfig.dynamicValue
6366 									? m_testConfig.rasterizationSamplesConfig.dynamicValue.get()
6367 									: m_testConfig.rasterizationSamplesConfig.staticValue);
6368 				}
6369 			}
6370 		}
6371 		else
6372 		{
6373 			DE_ASSERT(false);
6374 		}
6375 
6376 		const uint32_t expectedValue = sampleCount * kFramebufferWidth * kFramebufferHeight;
6377 
6378 		if (fragCounter != expectedValue)
6379 		{
6380 			std::ostringstream msg;
6381 			msg << "Fragment shader invocation count does not match expected value: found " << fragCounter << " and expected " << expectedValue;
6382 			return tcu::TestStatus::fail(msg.str());
6383 		}
6384 	}
6385 
6386 	return tcu::TestStatus::pass("Pass");
6387 }
6388 
stencilPasses(vk::VkCompareOp op,deUint8 storedValue,deUint8 referenceValue)6389 bool stencilPasses(vk::VkCompareOp op, deUint8 storedValue, deUint8 referenceValue)
6390 {
6391 	switch (op)
6392 	{
6393 	case vk::VK_COMPARE_OP_NEVER:				return false;
6394 	case vk::VK_COMPARE_OP_LESS:				return (referenceValue <	storedValue);
6395 	case vk::VK_COMPARE_OP_EQUAL:				return (referenceValue ==	storedValue);
6396 	case vk::VK_COMPARE_OP_LESS_OR_EQUAL:		return (referenceValue <=	storedValue);
6397 	case vk::VK_COMPARE_OP_GREATER:				return (referenceValue >	storedValue);
6398 	case vk::VK_COMPARE_OP_GREATER_OR_EQUAL:	return (referenceValue >=	storedValue);
6399 	case vk::VK_COMPARE_OP_ALWAYS:				return true;
6400 	default: DE_ASSERT(false); return false;
6401 	}
6402 
6403 	return false;	// Unreachable.
6404 }
6405 
stencilResult(vk::VkStencilOp op,deUint8 storedValue,deUint8 referenceValue,deUint8 min,deUint8 max)6406 deUint8 stencilResult(vk::VkStencilOp op, deUint8 storedValue, deUint8 referenceValue, deUint8 min, deUint8 max)
6407 {
6408 	deUint8 result = storedValue;
6409 
6410 	switch (op)
6411 	{
6412 	case vk::VK_STENCIL_OP_KEEP:					break;
6413 	case vk::VK_STENCIL_OP_ZERO:					result = 0; break;
6414 	case vk::VK_STENCIL_OP_REPLACE:					result = referenceValue; break;
6415 	case vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP:		result = ((result == max) ? result : static_cast<deUint8>(result + 1)); break;
6416 	case vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP:		result = ((result == min) ? result : static_cast<deUint8>(result - 1)); break;
6417 	case vk::VK_STENCIL_OP_INVERT:					result = static_cast<deUint8>(~result); break;
6418 	case vk::VK_STENCIL_OP_INCREMENT_AND_WRAP:		result = ((result == max) ? min : static_cast<deUint8>(result + 1)); break;
6419 	case vk::VK_STENCIL_OP_DECREMENT_AND_WRAP:		result = ((result == min) ? max : static_cast<deUint8>(result - 1)); break;
6420 	default: DE_ASSERT(false); break;
6421 	}
6422 
6423 	return result;
6424 }
6425 
6426 class TestGroupWithClean : public tcu::TestCaseGroup
6427 {
6428 public:
TestGroupWithClean(tcu::TestContext & testCtx,const char * name)6429 			TestGroupWithClean	(tcu::TestContext& testCtx, const char* name)
6430 				: tcu::TestCaseGroup(testCtx, name)
6431 		{}
6432 
deinit(void)6433 	void deinit (void) override { cleanupDevices(); }
6434 };
6435 
6436 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
6437 
6438 } // anonymous namespace
6439 
createExtendedDynamicStateTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)6440 tcu::TestCaseGroup* createExtendedDynamicStateTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
6441 {
6442 	GroupPtr extendedDynamicStateGroup(new TestGroupWithClean(testCtx, "extended_dynamic_state"));
6443 	GroupPtr meshShaderGroup(new tcu::TestCaseGroup(testCtx, "mesh_shader"));
6444 
6445 	// Auxiliar constants.
6446 	const deUint32	kHalfWidthU	= kFramebufferWidth/2u;
6447 	const deInt32	kHalfWidthI	= static_cast<deInt32>(kHalfWidthU);
6448 	const float		kHalfWidthF	= static_cast<float>(kHalfWidthU);
6449 	const float		kWidthF		= static_cast<float>(kFramebufferWidth);
6450 	const float		kHeightF	= static_cast<float>(kFramebufferHeight);
6451 
6452 	static const struct
6453 	{
6454 		SequenceOrdering	ordering;
6455 		std::string			name;
6456 	} kOrderingCases[] =
6457 	{
6458 		// Dynamic state set after command buffer start
6459 		{ SequenceOrdering::CMD_BUFFER_START,	"cmd_buffer_start"},
6460 		// Dynamic state set just before drawing
6461 		{ SequenceOrdering::BEFORE_DRAW,		"before_draw"},
6462 		// Dynamic after a pipeline with static states has been bound and before a pipeline with dynamic states has been bound
6463 		{ SequenceOrdering::BETWEEN_PIPELINES,	"between_pipelines"},
6464 		// Dynamic state set after both a static-state pipeline and a second dynamic-state pipeline have been bound
6465 		{ SequenceOrdering::AFTER_PIPELINES,	"after_pipelines"},
6466 		// Dynamic state set after a dynamic pipeline has been bound and before a second static-state pipeline with the right values has been bound
6467 		{ SequenceOrdering::BEFORE_GOOD_STATIC,	"before_good_static"},
6468 		// Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again
6469 		{ SequenceOrdering::TWO_DRAWS_DYNAMIC,	"two_draws_dynamic"},
6470 		// Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again
6471 		{ SequenceOrdering::TWO_DRAWS_STATIC,	"two_draws_static"},
6472 	};
6473 
6474 	static const struct
6475 	{
6476 		bool			useMeshShaders;
6477 		std::string		groupName;
6478 	} kMeshShadingCases[] =
6479 	{
6480 		{ false,	""				},
6481 #ifndef CTS_USES_VULKANSC
6482 		{ true,		"mesh_shader"	},
6483 #endif // CTS_USES_VULKANSC
6484 	};
6485 
6486 	static const struct
6487 	{
6488 		bool			bindUnusedMeshShadingPipeline;
6489 		std::string		nameSuffix;
6490 	} kBindUnusedCases[] =
6491 	{
6492 		{ false,	""},
6493 #ifndef CTS_USES_VULKANSC
6494 		{ true,		"_bind_unused_ms"},
6495 #endif // CTS_USES_VULKANSC
6496 	};
6497 
6498 	static const std::vector<ColorBlendSubCase> cbSubCases
6499 	{
6500 		ColorBlendSubCase::EQ_ONLY,
6501 		ColorBlendSubCase::ALL_CB,
6502 		ColorBlendSubCase::ALL_BUT_LO,
6503 	};
6504 
6505 	for (const auto& kMeshShadingCase : kMeshShadingCases)
6506 	for (const auto& kOrderingCase : kOrderingCases)
6507 	{
6508 		if (vk::isConstructionTypeShaderObject(pipelineConstructionType) && (kOrderingCase.ordering == SequenceOrdering::BETWEEN_PIPELINES || kOrderingCase.ordering == SequenceOrdering::AFTER_PIPELINES))
6509 			continue;
6510 
6511 		const auto& kUseMeshShaders	= kMeshShadingCase.useMeshShaders;
6512 		const auto& kOrdering		= kOrderingCase.ordering;
6513 
6514 		GroupPtr orderingGroup(new tcu::TestCaseGroup(testCtx, kOrderingCase.name.c_str()));
6515 
6516 		// Cull modes.
6517 		{
6518 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6519 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_FRONT_BIT;
6520 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE);
6521 			// Dynamically set cull mode to none
6522 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_none", config));
6523 		}
6524 		{
6525 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6526 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_FRONT_AND_BACK;
6527 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_BACK_BIT);
6528 			// Dynamically set cull mode to back
6529 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_back", config));
6530 		}
6531 		{
6532 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6533 			// Make triangles look back.
6534 			config.meshParams[0].reversed		= true;
6535 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
6536 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_BIT);
6537 			// Dynamically set cull mode to front
6538 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front", config));
6539 		}
6540 		{
6541 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6542 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_NONE;
6543 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_AND_BACK);
6544 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
6545 			// Dynamically set cull mode to front and back
6546 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front_and_back", config));
6547 		}
6548 
6549 		// Front face.
6550 		{
6551 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6552 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
6553 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_CLOCKWISE;
6554 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
6555 			// Dynamically set front face to clockwise
6556 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw", config));
6557 		}
6558 		{
6559 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6560 			// Pass triangles in clockwise order.
6561 			config.meshParams[0].reversed		= true;
6562 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
6563 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
6564 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
6565 			// Dynamically set front face to counter-clockwise
6566 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw", config));
6567 		}
6568 		{
6569 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6570 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
6571 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
6572 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
6573 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
6574 			// Dynamically set front face to clockwise with a counter-clockwise mesh
6575 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw_reversed", config));
6576 		}
6577 		{
6578 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6579 			// Pass triangles in clockwise order.
6580 			config.meshParams[0].reversed		= true;
6581 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
6582 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_CLOCKWISE;
6583 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
6584 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
6585 			// Dynamically set front face to counter-clockwise with a clockwise mesh
6586 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw_reversed", config));
6587 		}
6588 
6589 		// Rasterizer discard
6590 		{
6591 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6592 			config.rastDiscardEnableConfig.staticValue	= false;
6593 			config.rastDiscardEnableConfig.dynamicValue	= tcu::just(true);
6594 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6595 			// Dynamically disable rasterizer
6596 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "disable_raster", config));
6597 		}
6598 		{
6599 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6600 			config.rastDiscardEnableConfig.staticValue	= true;
6601 			config.rastDiscardEnableConfig.dynamicValue	= tcu::just(false);
6602 			// Dynamically enable rasterizer
6603 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "enable_raster", config));
6604 		}
6605 
6606 		// Logic op
6607 		{
6608 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6609 
6610 			config.logicOpEnableConfig.staticValue	= true;
6611 			config.logicOpConfig.staticValue		= vk::VK_LOGIC_OP_CLEAR;
6612 			config.logicOpConfig.dynamicValue		= tcu::just<vk::VkLogicOp>(vk::VK_LOGIC_OP_OR);
6613 
6614 			// Clear to green, paint in blue, expect cyan due to logic op.
6615 			config.meshParams[0].color	= kLogicOpTriangleColorFl;
6616 			config.clearColorValue		= vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
6617 			config.referenceColor.reset	(new SingleColorGenerator(kLogicOpFinalColor));
6618 
6619 			// Dynamically change logic op to VK_LOGIC_OP_OR
6620 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_or", config));
6621 		}
6622 
6623 		// Logic op enable.
6624 		{
6625 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6626 
6627 			config.logicOpEnableConfig.staticValue	= false;
6628 			config.logicOpEnableConfig.dynamicValue	= true;
6629 			config.logicOpConfig.staticValue		= vk::VK_LOGIC_OP_OR;
6630 
6631 			// Clear to green, paint in blue, expect cyan due to logic op.
6632 			config.meshParams[0].color	= kLogicOpTriangleColorFl;
6633 			config.clearColorValue		= vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
6634 			config.referenceColor.reset (new SingleColorGenerator(kLogicOpFinalColor));
6635 
6636 			// Dynamically enable logic OP
6637 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_enable", config));
6638 		}
6639 		{
6640 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6641 
6642 			config.logicOpEnableConfig.staticValue	= true;
6643 			config.logicOpEnableConfig.dynamicValue	= false;
6644 			config.logicOpConfig.staticValue		= vk::VK_LOGIC_OP_OR;
6645 
6646 			// Clear to green, paint in blue, expect cyan due to logic op.
6647 			config.meshParams[0].color	= kLogicOpTriangleColorFl;
6648 			config.clearColorValue		= vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
6649 			config.referenceColor.reset	(new SingleColorGenerator(kLogicOpTriangleColor));
6650 
6651 			// Dynamically disable logic OP
6652 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_disable", config));
6653 		}
6654 
6655 		// Color blend enable.
6656 		{
6657 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6658 
6659 			// The equation picks the old color instead of the new one if blending is enabled.
6660 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
6661 																	   vk::VK_BLEND_FACTOR_ONE,
6662 																	   vk::VK_BLEND_OP_ADD,
6663 																	   vk::VK_BLEND_FACTOR_ZERO,
6664 																	   vk::VK_BLEND_FACTOR_ONE,
6665 																	   vk::VK_BLEND_OP_ADD);
6666 
6667 			config.colorBlendEnableConfig.staticValue	= false;
6668 			config.colorBlendEnableConfig.dynamicValue	= true;
6669 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6670 
6671 			// Dynamically enable color blending
6672 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_enable", config));
6673 		}
6674 		{
6675 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6676 
6677 			// The equation picks the old color instead of the new one if blending is enabled.
6678 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
6679 																	   vk::VK_BLEND_FACTOR_ONE,
6680 																	   vk::VK_BLEND_OP_ADD,
6681 																	   vk::VK_BLEND_FACTOR_ZERO,
6682 																	   vk::VK_BLEND_FACTOR_ONE,
6683 																	   vk::VK_BLEND_OP_ADD);
6684 
6685 			config.colorBlendEnableConfig.staticValue	= true;
6686 			config.colorBlendEnableConfig.dynamicValue	= false;
6687 
6688 			// Dynamically disable color blending
6689 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_disable", config));
6690 		}
6691 
6692 		// Color blend equation.
6693 		{
6694 			for (const auto& cbSubCase : cbSubCases)
6695 			{
6696 				const bool onlyEq		= (cbSubCase == ColorBlendSubCase::EQ_ONLY);
6697 				const bool allCBDynamic	= (cbSubCase == ColorBlendSubCase::ALL_CB);
6698 
6699 				// Skip two-draws variants as this will use dynamic logic op and force UNORM color attachments, which would result in illegal operations.
6700 				if (allCBDynamic && (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC || kOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC))
6701 					continue;
6702 
6703 				for (int j = 0; j < 2; ++j)
6704 				{
6705 					const bool enableStateValue = (j > 0);
6706 
6707 					// Do not test statically disabling color blend.
6708 					if (onlyEq && !enableStateValue)
6709 						continue;
6710 
6711 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6712 
6713 					// The equation picks the old color instead of the new one if blending is enabled.
6714 					config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
6715 																			   vk::VK_BLEND_FACTOR_ONE,
6716 																			   vk::VK_BLEND_OP_ADD,
6717 																			   vk::VK_BLEND_FACTOR_ZERO,
6718 																			   vk::VK_BLEND_FACTOR_ONE,
6719 																			   vk::VK_BLEND_OP_ADD);
6720 
6721 					// The dynamic value picks the new color.
6722 					config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ONE,
6723 																				vk::VK_BLEND_FACTOR_ZERO,
6724 																				vk::VK_BLEND_OP_ADD,
6725 																				vk::VK_BLEND_FACTOR_ONE,
6726 																				vk::VK_BLEND_FACTOR_ZERO,
6727 																				vk::VK_BLEND_OP_ADD);
6728 
6729 					if (!onlyEq)
6730 					{
6731 						config.colorBlendEnableConfig.staticValue	= !enableStateValue;
6732 						config.colorBlendEnableConfig.dynamicValue	= enableStateValue;
6733 						config.colorWriteMaskConfig.staticValue		= ( 0 |  0 |  0 |  0);
6734 						config.colorWriteMaskConfig.dynamicValue	= (CR | CG | CB | CA);
6735 						config.blendConstantsConfig.staticValue		= BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
6736 						config.blendConstantsConfig.dynamicValue	= BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
6737 						// Note we don't set a dynamic value for alpha to coverage.
6738 
6739 						config.useColorWriteEnable					= true;
6740 						config.colorWriteEnableConfig.staticValue	= false;
6741 						config.colorWriteEnableConfig.dynamicValue	= true;
6742 
6743 						if (allCBDynamic)
6744 						{
6745 							config.forceUnormColorFormat				= true;
6746 							config.logicOpEnableConfig.staticValue		= true;
6747 							config.logicOpEnableConfig.dynamicValue		= false;
6748 							config.logicOpConfig.staticValue			= vk::VK_LOGIC_OP_COPY;
6749 							config.logicOpConfig.dynamicValue			= vk::VK_LOGIC_OP_CLEAR;
6750 						}
6751 					}
6752 					else
6753 					{
6754 						config.colorBlendEnableConfig.staticValue	= enableStateValue;
6755 					}
6756 
6757 					const std::string stateStr		= (enableStateValue ? "enable" : "disable");
6758 					const std::string nameSuffix	= (onlyEq ? "" : (allCBDynamic ? ("_dynamic_" + stateStr) : ("_dynamic_but_logic_op_" + stateStr)));
6759 
6760 					// Dynamically set a color equation that picks the mesh color
6761 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_new_color" + nameSuffix, config));
6762 
6763 					config.colorBlendEquationConfig.swapValues();
6764 					config.referenceColor.reset(new SingleColorGenerator(enableStateValue ? kDefaultClearColor : kDefaultTriangleColor));
6765 
6766 					// Dynamically set a color equation that picks the clear color
6767 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_old_color" + nameSuffix, config));
6768 				}
6769 			}
6770 		}
6771 
6772 		// Color blend advanced.
6773 		{
6774 			for (const auto& cbSubCase : cbSubCases)
6775 			{
6776 				const bool onlyEq		= (cbSubCase == ColorBlendSubCase::EQ_ONLY);
6777 				const bool allCBDynamic	= (cbSubCase == ColorBlendSubCase::ALL_CB);
6778 
6779 				// Skip two-draws variants as this will use dynamic logic op and force UNORM color attachments, which would result in illegal operations.
6780 				if (allCBDynamic && (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC || kOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC))
6781 					continue;
6782 
6783 				for (int j = 0; j < 2; ++j)
6784 				{
6785 					const bool enableStateValue = (j > 0);
6786 
6787 					// Do not test statically disabling color blend.
6788 					if (onlyEq && !enableStateValue)
6789 						continue;
6790 
6791 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6792 
6793 					// This static value picks the old color instead of the new one.
6794 					config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
6795 																			   vk::VK_BLEND_FACTOR_ONE,
6796 																			   vk::VK_BLEND_OP_DARKEN_EXT,
6797 																			   vk::VK_BLEND_FACTOR_ZERO,
6798 																			   vk::VK_BLEND_FACTOR_ONE,
6799 																			   vk::VK_BLEND_OP_DARKEN_EXT);
6800 
6801 					// The dynamic value picks the new color.
6802 					config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ONE,
6803 																				vk::VK_BLEND_FACTOR_ZERO,
6804 																				vk::VK_BLEND_OP_LIGHTEN_EXT,
6805 																				vk::VK_BLEND_FACTOR_ONE,
6806 																				vk::VK_BLEND_FACTOR_ZERO,
6807 																				vk::VK_BLEND_OP_LIGHTEN_EXT);
6808 
6809 					if (!onlyEq)
6810 					{
6811 						config.colorBlendEnableConfig.staticValue	= !enableStateValue;
6812 						config.colorBlendEnableConfig.dynamicValue	= enableStateValue;
6813 						config.colorWriteMaskConfig.staticValue		= ( 0 |  0 |  0 |  0);
6814 						config.colorWriteMaskConfig.dynamicValue	= (CR | CG | CB | CA);
6815 						config.blendConstantsConfig.staticValue		= BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
6816 						config.blendConstantsConfig.dynamicValue	= BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
6817 						// Note we don't set a dynamic value for alpha to coverage.
6818 
6819 						config.useColorWriteEnable					= true;
6820 						config.colorWriteEnableConfig.staticValue	= false;
6821 						config.colorWriteEnableConfig.dynamicValue	= true;
6822 
6823 						if (allCBDynamic)
6824 						{
6825 							config.forceUnormColorFormat				= true;
6826 							config.logicOpEnableConfig.staticValue		= true;
6827 							config.logicOpEnableConfig.dynamicValue		= false;
6828 							config.logicOpConfig.staticValue			= vk::VK_LOGIC_OP_COPY;
6829 							config.logicOpConfig.dynamicValue			= vk::VK_LOGIC_OP_CLEAR;
6830 						}
6831 					}
6832 					else
6833 					{
6834 						config.colorBlendEnableConfig.staticValue	= true;
6835 					}
6836 
6837 					const std::string stateStr		= (enableStateValue ? "enable" : "disable");
6838 					const std::string nameSuffix	= (onlyEq ? "" : (allCBDynamic ? ("_dynamic_" + stateStr) : ("_dynamic_but_logic_op_" + stateStr)));
6839 
6840 					// Dynamically set an advanced color equation that picks the mesh color
6841 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_advanced_new_color" + nameSuffix, config));
6842 
6843 					config.colorBlendEquationConfig.swapValues();
6844 					config.referenceColor.reset(new SingleColorGenerator(enableStateValue ? kDefaultClearColor : kDefaultTriangleColor));
6845 
6846 					// Dynamically set an advanced color equation that picks the clear color
6847 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_advanced_old_color" + nameSuffix, config));
6848 				}
6849 			}
6850 		}
6851 
6852 		// All color blend as dynamic, including both blend equations.
6853 		{
6854 			for (int i = 0; i < 2; ++i)
6855 			{
6856 				for (int j = 0; j < 2; ++j)
6857 				{
6858 					const bool swapEquation			= (j > 0);
6859 					const bool picksNew				= (!swapEquation);
6860 					const auto colorBlendResultName	= (picksNew ? "new" : "old");
6861 
6862 					const bool colorBlendEnableDyn		= (i > 0);
6863 					const bool colorBlendEnableStatic	= !colorBlendEnableDyn;
6864 					const auto colorBlendStateName		= (colorBlendEnableDyn ? "enabled" : "disabled");
6865 
6866 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6867 
6868 					// We need to apply both color blending equation states instead of deciding if it's advanced or not.
6869 					config.colorBlendBoth						= true;
6870 
6871 					config.colorBlendEnableConfig.staticValue	= colorBlendEnableStatic;
6872 					config.colorBlendEnableConfig.dynamicValue	= colorBlendEnableDyn;
6873 
6874 					config.colorWriteMaskConfig.staticValue		= ( 0 |  0 |  0 |  0);
6875 					config.colorWriteMaskConfig.dynamicValue	= (CR | CG | CB | CA);
6876 					config.blendConstantsConfig.staticValue		= BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
6877 					config.blendConstantsConfig.dynamicValue	= BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
6878 
6879 					config.useColorWriteEnable					= true;
6880 					config.colorWriteEnableConfig.staticValue	= false;
6881 					config.colorWriteEnableConfig.dynamicValue	= true;
6882 
6883 					config.forceUnormColorFormat				= true;
6884 					config.logicOpEnableConfig.staticValue		= true;
6885 					config.logicOpEnableConfig.dynamicValue		= false;
6886 					config.logicOpConfig.staticValue			= vk::VK_LOGIC_OP_COPY;
6887 					config.logicOpConfig.dynamicValue			= vk::VK_LOGIC_OP_CLEAR;
6888 
6889 					// This static value picks the new color.
6890 					config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ONE,
6891 																			   vk::VK_BLEND_FACTOR_ZERO,
6892 																			   vk::VK_BLEND_OP_LIGHTEN_EXT,
6893 																			   vk::VK_BLEND_FACTOR_ONE,
6894 																			   vk::VK_BLEND_FACTOR_ZERO,
6895 																			   vk::VK_BLEND_OP_LIGHTEN_EXT);
6896 
6897 					// The dynamic value picks the old color instead of the new one.
6898 					config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
6899 																				vk::VK_BLEND_FACTOR_ONE,
6900 																				vk::VK_BLEND_OP_DARKEN_EXT,
6901 																				vk::VK_BLEND_FACTOR_ZERO,
6902 																				vk::VK_BLEND_FACTOR_ONE,
6903 																				vk::VK_BLEND_OP_DARKEN_EXT);
6904 
6905 					if (swapEquation)
6906 						config.colorBlendEquationConfig.swapValues();
6907 
6908 					// Expected result.
6909 					const auto expectGeomColor = (!colorBlendEnableDyn || swapEquation);
6910 					config.referenceColor.reset(new SingleColorGenerator(expectGeomColor ? kDefaultTriangleColor : kDefaultClearColor));
6911 
6912 					const auto testName = std::string("color_blend_all_") + colorBlendStateName + "_" + colorBlendResultName + "_color";
6913 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
6914 				}
6915 			}
6916 		}
6917 
6918 		// Dynamic color blend equation with dual blending.
6919 		{
6920 			// Two equations: one picks index 0 and the other one picks index 1.
6921 			const struct
6922 			{
6923 				const ColorBlendEq	equation;
6924 				const tcu::Vec4		expectedColor;
6925 			} dualSrcCases[] =
6926 			{
6927 				{
6928 					ColorBlendEq(vk::VK_BLEND_FACTOR_SRC_COLOR,
6929 								 vk::VK_BLEND_FACTOR_ZERO,
6930 								 vk::VK_BLEND_OP_ADD,
6931 								 vk::VK_BLEND_FACTOR_SRC_ALPHA,
6932 								 vk::VK_BLEND_FACTOR_ZERO,
6933 								 vk::VK_BLEND_OP_ADD),
6934 					// This matches our logic in the frag shader for the first color index.
6935 					kOpaqueWhite,
6936 				},
6937 				{
6938 					ColorBlendEq(vk::VK_BLEND_FACTOR_SRC1_COLOR,
6939 								 vk::VK_BLEND_FACTOR_ZERO,
6940 								 vk::VK_BLEND_OP_ADD,
6941 								 vk::VK_BLEND_FACTOR_SRC1_ALPHA,
6942 								 vk::VK_BLEND_FACTOR_ZERO,
6943 								 vk::VK_BLEND_OP_ADD),
6944 					// This matches our logic in the frag shader for color1.
6945 					kDefaultTriangleColor,
6946 				},
6947 			};
6948 
6949 			for (size_t dynamicPick = 0u; dynamicPick < de::arrayLength(dualSrcCases); ++dynamicPick)
6950 			{
6951 				DE_ASSERT(de::arrayLength(dualSrcCases) == size_t{2});
6952 
6953 				const auto& dynamicEq	= dualSrcCases[dynamicPick].equation;
6954 				const auto& staticEq	= dualSrcCases[size_t{1} - dynamicPick].equation;
6955 
6956 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6957 
6958 				config.dualSrcBlend								= true;
6959 				config.colorBlendEnableConfig.staticValue		= true;
6960 				config.colorBlendEquationConfig.staticValue		= staticEq;
6961 				config.colorBlendEquationConfig.dynamicValue	= dynamicEq;
6962 				config.referenceColor.reset						(new SingleColorGenerator(dualSrcCases[dynamicPick].expectedColor));
6963 
6964 				const auto indexStr = std::to_string(dynamicPick);
6965 				// Dynamically change dual source blending equation to pick color index
6966 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_dual_index_" + indexStr, config));
6967 			}
6968 		}
6969 
6970 		// Null color blend pipeline pAttachments pointer with all structure contents as dynamic states.
6971 		{
6972 			TestConfig config (pipelineConstructionType, kOrdering, kUseMeshShaders);
6973 
6974 			// The equation picks the old color instead of the new one if blending is enabled.
6975 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
6976 																		vk::VK_BLEND_FACTOR_ONE,
6977 																		vk::VK_BLEND_OP_ADD,
6978 																		vk::VK_BLEND_FACTOR_ZERO,
6979 																		vk::VK_BLEND_FACTOR_ONE,
6980 																		vk::VK_BLEND_OP_ADD);
6981 
6982 			// The dynamic value picks the new color.
6983 			config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ONE,
6984 																		vk::VK_BLEND_FACTOR_ZERO,
6985 																		vk::VK_BLEND_OP_ADD,
6986 																		vk::VK_BLEND_FACTOR_ONE,
6987 																		vk::VK_BLEND_FACTOR_ZERO,
6988 																		vk::VK_BLEND_OP_ADD);
6989 
6990 			config.colorBlendEnableConfig.staticValue	= false;
6991 			config.colorBlendEnableConfig.dynamicValue	= true;
6992 
6993 			config.colorWriteMaskConfig.staticValue		= ( 0 |  0 |  0 |  0);
6994 			config.colorWriteMaskConfig.dynamicValue	= (CR | CG | CB | CA);
6995 
6996 			config.nullStaticColorBlendAttPtr			= true; // What this test is about.
6997 
6998 			const char* testName = "null_color_blend_att_ptr";
6999 			// Set all VkPipelineColorBlendAttachmentState substates as dynamic and pass a null pointer in VkPipelineColorBlendStateCreateInfo::pAttachments
7000 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7001 		}
7002 
7003 		// Dynamically enable primitive restart
7004 		if (!kUseMeshShaders)
7005 		{
7006 			for (const auto& bindUnusedCase : kBindUnusedCases)
7007 			{
7008 				if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7009 					continue;
7010 
7011 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7012 				config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7013 				config.extraLineRestarts					= true;
7014 				config.primRestartEnableConfig.staticValue	= false;
7015 				config.primRestartEnableConfig.dynamicValue	= tcu::just(true);
7016 				config.bindUnusedMeshShadingPipeline		= bindUnusedCase.bindUnusedMeshShadingPipeline;
7017 				config.referenceColor.reset					(new CenterStripGenerator(kDefaultTriangleColor, kDefaultClearColor));
7018 				// Dynamically enable primitiveRestart
7019 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, std::string("prim_restart_enable") + bindUnusedCase.nameSuffix, config));
7020 			}
7021 		}
7022 
7023 		// Dynamically change the number of primitive control points
7024 		if (!kUseMeshShaders)
7025 		{
7026 			for (const auto& bindUnusedCase : kBindUnusedCases)
7027 			{
7028 				if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7029 					continue;
7030 
7031 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7032 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7033 				config.patchControlPointsConfig.staticValue = 1;
7034 				config.patchControlPointsConfig.dynamicValue = 3;
7035 				config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7036 				// Dynamically change patch control points
7037 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "patch_control_points" + bindUnusedCase.nameSuffix, config));
7038 			}
7039 
7040 			{
7041 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7042 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7043 				config.patchControlPointsConfig.staticValue = 1;
7044 				config.patchControlPointsConfig.dynamicValue = 3;
7045 				config.useExtraDynPCPPipeline = true;
7046 
7047 				const auto testName	= "patch_control_points_extra_pipeline";
7048 				// Dynamically change patch control points and draw first with a pipeline using the state and no tessellation shaders
7049 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7050 			}
7051 		}
7052 
7053 		// Test tessellation domain origin.
7054 		if (!kUseMeshShaders)
7055 		{
7056 			{
7057 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7058 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7059 				config.patchControlPointsConfig.staticValue = 3;
7060 				config.tessDomainOriginConfig.staticValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
7061 				config.tessDomainOriginConfig.dynamicValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
7062 				config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7063 
7064 				// Dynamically set the right domain origin to lower left
7065 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "tess_domain_origin_lower_left", config));
7066 			}
7067 			{
7068 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7069 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7070 				config.patchControlPointsConfig.staticValue = 3;
7071 				config.tessDomainOriginConfig.staticValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
7072 				config.tessDomainOriginConfig.dynamicValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
7073 				config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
7074 
7075 				// Dynamically set the right domain origin to upper left
7076 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "tess_domain_origin_upper_left", config));
7077 			}
7078 		}
7079 
7080 		// Dynamic topology.
7081 		if (!kUseMeshShaders)
7082 		{
7083 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
7084 
7085 			for (int i = 0; i < 2; ++i)
7086 			{
7087 				const bool forceGeometryShader = (i > 0);
7088 
7089 				static const struct
7090 				{
7091 					vk::VkPrimitiveTopology staticVal;
7092 					vk::VkPrimitiveTopology dynamicVal;
7093 				} kTopologyCases[] =
7094 				{
7095 					{ vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP	},
7096 					{ vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP		},
7097 					{ vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,		vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST		},
7098 				};
7099 
7100 				for (const auto& kTopologyCase : kTopologyCases)
7101 				{
7102 					const auto topologyClass = getTopologyClass(kTopologyCase.staticVal);
7103 
7104 					for (const auto& bindUnusedCase : kBindUnusedCases)
7105 					{
7106 						if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7107 							continue;
7108 
7109 						TestConfig config(baseConfig);
7110 						config.forceGeometryShader					= forceGeometryShader;
7111 						config.topologyConfig.staticValue			= kTopologyCase.staticVal;
7112 						config.topologyConfig.dynamicValue			= tcu::just<vk::VkPrimitiveTopology>(kTopologyCase.dynamicVal);
7113 						config.primRestartEnableConfig.staticValue	= (topologyClass == TopologyClass::LINE);
7114 						config.patchControlPointsConfig.staticValue	= (config.needsTessellation() ? 3u : 1u);
7115 						config.bindUnusedMeshShadingPipeline		= bindUnusedCase.bindUnusedMeshShadingPipeline;
7116 
7117 						const std::string	className	= topologyClassName(topologyClass);
7118 						const std::string	name		= "topology_" + className + (forceGeometryShader ? "_geom" : "") + bindUnusedCase.nameSuffix;
7119 						// Dynamically switch primitive topologies
7120 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, name, config));
7121 					}
7122 				}
7123 			}
7124 		}
7125 
7126 		// Line stipple enable.
7127 		{
7128 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7129 
7130 			config.primRestartEnableConfig.staticValue	= true;
7131 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7132 			config.lineStippleEnableConfig.staticValue	= true;
7133 			config.lineStippleEnableConfig.dynamicValue	= false;
7134 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{1u, 0x5555u};
7135 
7136 			// Dynamically disable line stipple
7137 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_disable", config));
7138 
7139 			config.lineStippleEnableConfig.swapValues();
7140 			config.referenceColor.reset(new VerticalStripesGenerator(kDefaultTriangleColor, kDefaultClearColor, 1u));
7141 
7142 			// Dynamycally enable line stipple
7143 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_enable", config));
7144 		}
7145 
7146 		// Line stipple params.
7147 		{
7148 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7149 
7150 			config.primRestartEnableConfig.staticValue	= true;
7151 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7152 			config.lineStippleEnableConfig.staticValue	= true;
7153 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{1u, 0x5555u};
7154 			config.lineStippleParamsConfig.dynamicValue	= LineStippleParams{2u, 0x3333u};
7155 			config.referenceColor.reset					(new VerticalStripesGenerator(kDefaultTriangleColor, kDefaultClearColor, 4u));
7156 
7157 			// Dynamically change the line stipple parameters
7158 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_params", config));
7159 		}
7160 
7161 		// Line rasterization mode.
7162 		{
7163 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7164 
7165 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7166 			config.obliqueLine							= true;
7167 			config.colorVerificator						= verifyTopLeftCornerExactly;
7168 			config.lineStippleEnableConfig.staticValue	= false;
7169 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{0u, 0u};
7170 			config.lineRasterModeConfig.staticValue		= LineRasterizationMode::RECTANGULAR;
7171 			config.lineRasterModeConfig.dynamicValue	= LineRasterizationMode::BRESENHAM;
7172 
7173 			// Dynamically set line rasterization mode to bresenham
7174 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_bresenham", config));
7175 
7176 			config.lineRasterModeConfig.swapValues();
7177 			config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7178 			// Dynamically set line rasterization mode to rectangular
7179 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_rectangular", config));
7180 		}
7181 		{
7182 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7183 
7184 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7185 			config.obliqueLine							= true;
7186 			config.colorVerificator						= verifyTopLeftCornerWithPartialAlpha;
7187 			config.lineStippleEnableConfig.staticValue	= false;
7188 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{0u, 0u};
7189 			config.lineRasterModeConfig.staticValue		= LineRasterizationMode::BRESENHAM;
7190 			config.lineRasterModeConfig.dynamicValue	= LineRasterizationMode::SMOOTH;
7191 
7192 			// Dynamically set line rasterization mode to smooth
7193 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_smooth", config));
7194 		}
7195 
7196 		// Viewport.
7197 		{
7198 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7199 			// 2 scissors, bad static single viewport.
7200 			config.scissorConfig.staticValue	= ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
7201 			config.viewportConfig.staticValue	= ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
7202 			config.viewportConfig.dynamicValue	= ViewportVec{
7203 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7204 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7205 			};
7206 			// Dynamically set 2 viewports
7207 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports", config));
7208 		}
7209 		{
7210 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7211 			// Bad static reduced viewport.
7212 			config.viewportConfig.staticValue	= ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
7213 			config.viewportConfig.staticValue	= ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight));
7214 			// Dynamically set viewport to cover full framebuffer
7215 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_viewport", config));
7216 		}
7217 		{
7218 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7219 			// 2 scissors (left half, right half), 2 reversed static viewports that need fixing (right, left).
7220 			config.scissorConfig.staticValue	= ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
7221 			config.viewportConfig.staticValue	= ViewportVec{
7222 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),	// Right.
7223 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),		// Left.
7224 			};
7225 			config.viewportConfig.dynamicValue	= ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
7226 			// Dynamically switch the order with 2 viewports
7227 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch", config));
7228 		}
7229 		{
7230 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7231 			// 2 scissors, reversed dynamic viewports that should result in no drawing taking place.
7232 			config.scissorConfig.staticValue	= ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
7233 			config.viewportConfig.staticValue	= ViewportVec{
7234 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),		// Left.
7235 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),	// Right.
7236 			};
7237 			config.viewportConfig.dynamicValue	= ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
7238 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
7239 			// Dynamically switch the order with 2 viewports resulting in clean image
7240 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch_clean", config));
7241 		}
7242 
7243 		// Scissor.
7244 		{
7245 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7246 			// 2 viewports, bad static single scissor.
7247 			config.viewportConfig.staticValue	= ViewportVec{
7248 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7249 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7250 			};
7251 			config.scissorConfig.staticValue	= ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
7252 			config.scissorConfig.dynamicValue	= ScissorVec{
7253 				vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
7254 				vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
7255 			};
7256 			// Dynamically set 2 scissors
7257 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors", config));
7258 		}
7259 		{
7260 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7261 			// 1 viewport, bad static single scissor.
7262 			config.scissorConfig.staticValue	= ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
7263 			config.scissorConfig.dynamicValue	= ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight));
7264 			// Dynamically set scissor to cover full framebuffer
7265 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_scissor", config));
7266 		}
7267 		{
7268 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7269 			// 2 viewports, 2 reversed scissors that need fixing.
7270 			config.viewportConfig.staticValue	= ViewportVec{
7271 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7272 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7273 			};
7274 			config.scissorConfig.staticValue	= ScissorVec{
7275 				vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
7276 				vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
7277 			};
7278 			config.scissorConfig.dynamicValue	= ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
7279 			// Dynamically switch the order with 2 scissors
7280 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch", config));
7281 		}
7282 		{
7283 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7284 			// 2 viewports, 2 scissors switched to prevent drawing.
7285 			config.viewportConfig.staticValue	= ViewportVec{
7286 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7287 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7288 			};
7289 			config.scissorConfig.staticValue	= ScissorVec{
7290 				vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
7291 				vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
7292 			};
7293 			config.scissorConfig.dynamicValue	= ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
7294 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
7295 			// Dynamically switch the order with 2 scissors to avoid drawing
7296 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch_clean", config));
7297 		}
7298 
7299 		// Stride.
7300 		if (!kUseMeshShaders)
7301 		{
7302 			struct
7303 			{
7304 				const VertexGenerator*	factory;
7305 				const std::string		prefix;
7306 			} strideCases[] =
7307 			{
7308 				{ getVertexWithPaddingGenerator(),			"stride"		},
7309 				{ getVertexWithExtraAttributesGenerator(),	"large_stride"	},
7310 			};
7311 
7312 			for (const auto& strideCase : strideCases)
7313 			{
7314 				const auto	factory			= strideCase.factory;
7315 				const auto&	prefix			= strideCase.prefix;
7316 				const auto	vertexStrides	= factory->getVertexDataStrides();
7317 				StrideVec	halfStrides;
7318 
7319 				halfStrides.reserve(vertexStrides.size());
7320 				for (const auto& stride : vertexStrides)
7321 					halfStrides.push_back(stride / 2u);
7322 
7323 				if (factory == getVertexWithExtraAttributesGenerator() && kOrdering == SequenceOrdering::TWO_DRAWS_STATIC)
7324 				{
7325 					// This case is invalid because it breaks VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the dynamic
7326 					// stride being less than the extent of the binding for the second attribute.
7327 					continue;
7328 				}
7329 
7330 				for (const auto& bindUnusedCase : kBindUnusedCases)
7331 				{
7332 					if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7333 						continue;
7334 
7335 					{
7336 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
7337 						config.strideConfig.staticValue			= halfStrides;
7338 						config.strideConfig.dynamicValue		= vertexStrides;
7339 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
7340 						// Dynamically set stride
7341 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + bindUnusedCase.nameSuffix, config));
7342 					}
7343 					{
7344 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
7345 						config.strideConfig.staticValue			= halfStrides;
7346 						config.strideConfig.dynamicValue		= vertexStrides;
7347 						config.vertexDataOffset					= vertexStrides[0];
7348 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
7349 						// Dynamically set stride using a nonzero vertex data offset
7350 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset" + bindUnusedCase.nameSuffix, config));
7351 					}
7352 					{
7353 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
7354 						config.strideConfig.staticValue			= halfStrides;
7355 						config.strideConfig.dynamicValue		= vertexStrides;
7356 						config.vertexDataOffset					= vertexStrides[0];
7357 						config.vertexDataExtraBytes				= config.vertexDataOffset;
7358 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
7359 
7360 						// Make the mesh cover the top half only. If the implementation reads data outside the vertex values it may draw something to the bottom half.
7361 						config.referenceColor.reset				(new HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor));
7362 						config.meshParams[0].scaleY				= 0.5f;
7363 						config.meshParams[0].offsetY			= -0.5f;
7364 
7365 						// Dynamically set stride using a nonzero vertex data offset and extra bytes
7366 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset_and_padding" + bindUnusedCase.nameSuffix, config));
7367 					}
7368 				}
7369 			}
7370 
7371 			// Dynamic stride of 0
7372 			//
7373 			// The "two_draws" variants are invalid because the non-zero vertex stride will cause out-of-bounds access
7374 			// when drawing more than one vertex.
7375 			if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC && kOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC)
7376 			{
7377 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithExtraAttributesGenerator());
7378 				config.strideConfig.staticValue		= config.getActiveVertexGenerator()->getVertexDataStrides();
7379 				config.strideConfig.dynamicValue	= { 0 };
7380 				config.vertexDataOffset				= 4;
7381 				config.singleVertex					= true;
7382 				config.singleVertexDrawCount		= 6;
7383 
7384 				// Make the mesh cover the top half only. If the implementation reads data outside the vertex data it should read the
7385 				// offscreen vertex and draw something in the bottom half.
7386 				config.referenceColor.reset		(new HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor));
7387 				config.meshParams[0].scaleY		= 0.5f;
7388 				config.meshParams[0].offsetY	= -0.5f;
7389 
7390 				// Use strip scale to synthesize a strip from a vertex attribute which remains constant over the draw call.
7391 				config.meshParams[0].stripScale = 1.0f;
7392 
7393 				// Dynamically set zero stride using a nonzero vertex data offset
7394 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "zero_stride_with_offset", config));
7395 			}
7396 		}
7397 
7398 		// Depth test enable.
7399 		{
7400 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7401 			config.depthTestEnableConfig.staticValue	= false;
7402 			config.depthTestEnableConfig.dynamicValue	= tcu::just(true);
7403 			// By default, the depth test never passes when enabled.
7404 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
7405 			// Dynamically enable depth test
7406 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_enable", config));
7407 		}
7408 		{
7409 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7410 			config.depthTestEnableConfig.staticValue	= true;
7411 			config.depthTestEnableConfig.dynamicValue	= tcu::just(false);
7412 			// Dynamically disable depth test
7413 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_disable", config));
7414 		}
7415 
7416 		// Depth write enable.
7417 		{
7418 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7419 
7420 			// Enable depth test and set values so it passes.
7421 			config.depthTestEnableConfig.staticValue	= true;
7422 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7423 			config.clearDepthValue						= 0.5f;
7424 			config.meshParams[0].depth					= 0.25f;
7425 
7426 			// Enable writes and expect the mesh value.
7427 			config.depthWriteEnableConfig.staticValue	= false;
7428 			config.depthWriteEnableConfig.dynamicValue	= tcu::just(true);
7429 			config.expectedDepth						= 0.25f;
7430 
7431 			// Dynamically enable writes to the depth buffer
7432 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_enable", config));
7433 		}
7434 		{
7435 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7436 
7437 			// Enable depth test and set values so it passes.
7438 			config.depthTestEnableConfig.staticValue	= true;
7439 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7440 			config.clearDepthValue						= 0.5f;
7441 			config.meshParams[0].depth					= 0.25f;
7442 
7443 			// But disable writing dynamically and expect the clear value.
7444 			config.depthWriteEnableConfig.staticValue	= true;
7445 			config.depthWriteEnableConfig.dynamicValue	= tcu::just(false);
7446 			config.expectedDepth						= 0.5f;
7447 
7448 			// Dynamically disable writes to the depth buffer
7449 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_disable", config));
7450 		}
7451 
7452 		// Depth clamp enable.
7453 		{
7454 			// Without clamping, the mesh depth fails the depth test after applying the viewport transform.
7455 			// With clamping, it should pass thanks to the viewport.
7456 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7457 
7458 			config.meshParams[0].depth					= 1.5f;
7459 			config.clearDepthValue						= 0.625f;
7460 			config.depthTestEnableConfig.staticValue	= true;
7461 			config.depthWriteEnableConfig.staticValue	= true;
7462 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7463 			config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.0f, 0.5f));
7464 			config.expectedDepth						= 0.5f;
7465 
7466 			config.depthClampEnableConfig.staticValue	= false;
7467 			config.depthClampEnableConfig.dynamicValue	= true;
7468 
7469 			// Dynamically enable depth clamp
7470 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable", config));
7471 		}
7472 		{
7473 			// Reverse situation.
7474 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7475 
7476 			config.meshParams[0].depth					= 1.5f;
7477 			config.clearDepthValue						= 0.625f;
7478 			config.depthTestEnableConfig.staticValue	= true;
7479 			config.depthWriteEnableConfig.staticValue	= true;
7480 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7481 			config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.0f, 0.5f));
7482 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
7483 			config.expectedDepth						= 0.625f;
7484 
7485 			config.depthClampEnableConfig.staticValue	= true;
7486 			config.depthClampEnableConfig.dynamicValue	= false;
7487 
7488 			// Dynamically disable depth clamp
7489 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_disable", config));
7490 		}
7491 
7492 #if 0
7493 		// "If the depth clamping state is changed dynamically, and the pipeline was not created with
7494 		// VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT enabled, then depth clipping is enabled when depth clamping is disabled and vice
7495 		// versa"
7496 		//
7497 		// Try to verify the implementation ignores the static depth clipping state. We cannot test the following sequence orderings for this:
7498 		// - BEFORE_GOOD_STATIC and TWO_DRAWS_STATIC because they use static-state pipelines, but for this specific case we need dynamic state as per the spec.
7499 		// - TWO_DRAWS_DYNAMIC because the first draw may modify the framebuffer with undesired side-effects.
7500 		if (kOrdering != SequenceOrdering::BEFORE_GOOD_STATIC && kOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC && kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
7501 		{
7502 			{
7503 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7504 
7505 				config.meshParams[0].depth					= -0.5f;
7506 				config.clearDepthValue						= 1.0f;
7507 				config.depthTestEnableConfig.staticValue	= true;
7508 				config.depthWriteEnableConfig.staticValue	= true;
7509 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
7510 				config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
7511 				config.expectedDepth						= 0.5f; // Geometry will be clamped to this value.
7512 
7513 				config.depthClampEnableConfig.staticValue	= false;
7514 				config.depthClampEnableConfig.dynamicValue	= true;
7515 
7516 				// Dynamically enable depth clamp while making sure depth clip is disabled
7517 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable_no_clip", config));
7518 			}
7519 			{
7520 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7521 
7522 				config.meshParams[0].depth					= -0.5f;
7523 				config.clearDepthValue						= 1.0f;
7524 				config.depthTestEnableConfig.staticValue	= true;
7525 				config.depthWriteEnableConfig.staticValue	= true;
7526 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
7527 				config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
7528 				config.expectedDepth						= 1.0f; // Geometry should be clipped in this case.
7529 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
7530 
7531 				// Enable clamping dynamically, with clipping enabled statically.
7532 				config.depthClampEnableConfig.staticValue	= false;
7533 				config.depthClampEnableConfig.dynamicValue	= true;
7534 				config.depthClipEnableConfig.staticValue	= OptBoolean(true);
7535 
7536 				// Dynamically enable depth clamp while keeping depth clip enabled statically
7537 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable_with_clip", config));
7538 			}
7539 			{
7540 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7541 
7542 				config.meshParams[0].depth					= -0.5f;
7543 				config.clearDepthValue						= 1.0f;
7544 				config.depthTestEnableConfig.staticValue	= true;
7545 				config.depthWriteEnableConfig.staticValue	= true;
7546 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
7547 				config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
7548 				config.expectedDepth						= 1.0f; // Geometry should be clipped in this case.
7549 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
7550 
7551 				config.depthClampEnableConfig.staticValue	= true;
7552 				config.depthClampEnableConfig.dynamicValue	= false;
7553 				if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
7554 					config.depthClipEnableConfig.staticValue = OptBoolean(true);
7555 
7556 				// Dynamically disable depth clamp making sure depth clipping is enabled
7557 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_disable_with_clip", config));
7558 			}
7559 			// Note: the combination of depth clamp disabled and depth clip disabled cannot be tested because if Zf falls outside
7560 			// [Zmin,Zmax] from the viewport, then the value of Zf is undefined during the depth test.
7561 		}
7562 #endif
7563 
7564 		// Polygon mode.
7565 		{
7566 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7567 
7568 			config.polygonModeConfig.staticValue	= vk::VK_POLYGON_MODE_FILL;
7569 			config.polygonModeConfig.dynamicValue	= vk::VK_POLYGON_MODE_POINT;
7570 			config.oversizedTriangle				= true;
7571 			config.referenceColor.reset				(new SingleColorGenerator(kDefaultClearColor));
7572 
7573 			// Dynamically set polygon draw mode to points
7574 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "polygon_mode_point", config));
7575 		}
7576 		{
7577 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7578 
7579 			config.polygonModeConfig.staticValue	= vk::VK_POLYGON_MODE_POINT;
7580 			config.polygonModeConfig.dynamicValue	= vk::VK_POLYGON_MODE_FILL;
7581 			config.oversizedTriangle				= true;
7582 
7583 			// Dynamically set polygon draw mode to fill
7584 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "polygon_mode_fill", config));
7585 		}
7586 
7587 		for (int i = 0; i < 2; ++i)
7588 		{
7589 			const bool			multisample			= (i > 0);
7590 			const auto			activeSampleCount	= (multisample ? kMultiSampleCount : kSingleSampleCount);
7591 			const auto			inactiveSampleCount	= (multisample ? kSingleSampleCount : kMultiSampleCount);
7592 			const std::string	namePrefix			= (multisample ? "multi_sample_" : "single_sample_");
7593 			const std::string	descSuffix			= (multisample ? " in multisample mode" : " in single sample mode");
7594 
7595 			// Sample count.
7596 			{
7597 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7598 
7599 				// The static pipeline would be illegal due to VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853.
7600 				if (!config.useStaticPipeline())
7601 				{
7602 					config.rasterizationSamplesConfig.staticValue	= inactiveSampleCount;
7603 					config.rasterizationSamplesConfig.dynamicValue	= activeSampleCount;
7604 					// Dynamically set the rasterization sample count
7605 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "rasterization_samples", config));
7606 				}
7607 			}
7608 
7609 			// Sample mask
7610 			{
7611 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7612 				config.rasterizationSamplesConfig		= activeSampleCount;
7613 				config.sampleMaskConfig.staticValue		= SampleMaskVec(1u, 0u);
7614 				config.sampleMaskConfig.dynamicValue	= SampleMaskVec(1u, 0xFFu);
7615 
7616 				// Dynamically set a sample mask that allows drawing
7617 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "sample_mask_enable", config));
7618 			}
7619 			{
7620 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7621 				config.rasterizationSamplesConfig		= activeSampleCount;
7622 				config.sampleMaskConfig.staticValue		= SampleMaskVec(1u, 0xFFu);
7623 				config.sampleMaskConfig.dynamicValue	= SampleMaskVec(1u, 0u);
7624 				config.referenceColor.reset				(new SingleColorGenerator(kDefaultClearColor));
7625 
7626 				// Dynamically set a sample mask that prevents drawing
7627 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "sample_mask_disable", config));
7628 			}
7629 
7630 			// Alpha to coverage.
7631 			{
7632 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7633 
7634 				config.rasterizationSamplesConfig			= activeSampleCount;
7635 				config.meshParams[0].color					= kTransparentColor;
7636 				config.alphaToCoverageConfig.staticValue	= false;
7637 				config.alphaToCoverageConfig.dynamicValue	= true;
7638 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
7639 
7640 				// Dynamically enable alpha to coverage
7641 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_coverage_enable", config));
7642 			}
7643 			{
7644 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7645 
7646 				config.rasterizationSamplesConfig			= activeSampleCount;
7647 				config.meshParams[0].color					= kTransparentColor;
7648 				config.alphaToCoverageConfig.staticValue	= true;
7649 				config.alphaToCoverageConfig.dynamicValue	= false;
7650 				config.referenceColor.reset					(new SingleColorGenerator(kTransparentColor));
7651 
7652 				// Dynamically disable alpha to coverage
7653 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_coverage_disable", config));
7654 			}
7655 
7656 			// Alpha to one.
7657 			{
7658 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7659 
7660 				config.rasterizationSamplesConfig		= activeSampleCount;
7661 				config.meshParams[0].color				= kTransparentColor;
7662 				config.alphaToOneConfig.staticValue		= false;
7663 				config.alphaToOneConfig.dynamicValue	= true;
7664 				config.referenceColor.reset				(new SingleColorGenerator(kDefaultTriangleColor));
7665 
7666 				// Dynamically enable alpha to one
7667 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_one_enable", config));
7668 			}
7669 			{
7670 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7671 
7672 				config.rasterizationSamplesConfig		= activeSampleCount;
7673 				config.meshParams[0].color				= kTransparentColor;
7674 				config.alphaToOneConfig.staticValue		= true;
7675 				config.alphaToOneConfig.dynamicValue	= false;
7676 				config.referenceColor.reset				(new SingleColorGenerator(kTransparentColor));
7677 
7678 				// Dynamically disable alpha to one
7679 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_one_disable", config));
7680 			}
7681 		}
7682 
7683 		// Special sample mask case: make sure the dynamic sample mask count does not overwrite the actual sample mask.
7684 		{
7685 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7686 
7687 			// There's guaranteed support for 1 sample and 4 samples. So the official pipeline sample count will be 1 sample, and
7688 			// the one we'll use in the dynamic sample mask call will be 4.
7689 			//
7690 			// When using 4 samples, sample 3 uses a Y offset of 0.875 pixels, so we'll use an off-center triangle to try to trick
7691 			// the implementation into having that one covered by using a Y offset of 0.75.
7692 			config.dynamicSampleMaskCount			= tcu::just(kMultiSampleCount);
7693 			config.sampleMaskConfig.staticValue		= SampleMaskVec(1u, 0u);
7694 			config.sampleMaskConfig.dynamicValue	= SampleMaskVec(1u, 0xFFu);
7695 			config.offCenterTriangle				= true;
7696 			config.offCenterProportion				= tcu::Vec2(0.0f, 0.75f);
7697 			config.referenceColor.reset				(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor));
7698 
7699 			// Dynamically set sample mask with slightly different sample count
7700 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_mask_count", config));
7701 		}
7702 
7703 		// Special rasterization samples case: make sure rasterization samples is taken from the dynamic value, but provide a larger mask.
7704 		{
7705 			const auto kLargeRasterizationSampleCount = vk::VK_SAMPLE_COUNT_64_BIT;
7706 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7707 
7708 			// We cannot create a static pipeline with the configuration below because the render pass attachments will have a
7709 			// sample count of kMultiSampleCount and VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853
7710 			// applies here.
7711 			if (!config.useStaticPipeline())
7712 			{
7713 				config.rasterizationSamplesConfig.staticValue	= kLargeRasterizationSampleCount;
7714 				config.rasterizationSamplesConfig.dynamicValue	= kMultiSampleCount;
7715 				config.sampleMaskConfig.staticValue				= SampleMaskVec{ 0xFFFFFFF0u, 0xFFFFFFFFu }; // Last 4 bits off.
7716 				config.referenceColor.reset						(new SingleColorGenerator(kDefaultClearColor));
7717 
7718 				// Dynamically set the rasterization samples to a low value while disabling bits corresponding to the dynamic sample count
7719 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "large_static_rasterization_samples_off", config));
7720 
7721 				config.sampleMaskConfig.staticValue				= SampleMaskVec{ 0xFu, 0u }; // Last 4 bits on.
7722 				config.referenceColor.reset						(new SingleColorGenerator(kDefaultTriangleColor));
7723 
7724 				// Dynamically set the rasterization samples to a low value while enabling bits corresponding to the dynamic sample count
7725 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "large_static_rasterization_samples_on", config));
7726 			}
7727 		}
7728 
7729 		// Color write mask.
7730 		{
7731 			const struct
7732 			{
7733 				vk::VkColorComponentFlags staticVal;
7734 				vk::VkColorComponentFlags dynamicVal;
7735 			} colorComponentCases[] =
7736 			{
7737 				{	(CR | CG | CB | CA),	(CR |  0 |  0 |  0)		},
7738 				{	(CR | CG | CB | CA),	( 0 | CG |  0 |  0)		},
7739 				{	(CR | CG | CB | CA),	( 0 |  0 | CB |  0)		},
7740 				{	(CR | CG | CB | CA),	( 0 |  0 |  0 | CA)		},
7741 				{	(CR | CG | CB | CA),	( 0 |  0 |  0 |  0)		},
7742 				{	( 0 |  0 |  0 |  0),	(CR |  0 |  0 |  0)		},
7743 				{	( 0 |  0 |  0 |  0),	( 0 | CG |  0 |  0)		},
7744 				{	( 0 |  0 |  0 |  0),	( 0 |  0 | CB |  0)		},
7745 				{	( 0 |  0 |  0 |  0),	( 0 |  0 |  0 | CA)		},
7746 				{	( 0 |  0 |  0 |  0),	(CR | CG | CB | CA)		},
7747 			};
7748 
7749 			for (const auto& colorCompCase : colorComponentCases)
7750 			{
7751 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7752 
7753 				config.clearColorValue						= vk::makeClearValueColor(kTransparentClearColor);
7754 				config.meshParams[0].color					= kOpaqueWhite;
7755 				config.colorWriteMaskConfig.staticValue		= colorCompCase.staticVal;
7756 				config.colorWriteMaskConfig.dynamicValue	= colorCompCase.dynamicVal;
7757 				config.referenceColor.reset					(new SingleColorGenerator(filterColor(kTransparentClearColor, kOpaqueWhite, colorCompCase.dynamicVal)));
7758 
7759 				const auto staticCode	= componentCodes(colorCompCase.staticVal);
7760 				const auto dynamicCode	= componentCodes(colorCompCase.dynamicVal);
7761 				const auto testName		= "color_write_mask_" + staticCode + "_to_" + dynamicCode;
7762 				// Dynamically set color write mask
7763 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7764 			}
7765 		}
7766 
7767 		// Rasterization stream selection.
7768 		if (!kUseMeshShaders)
7769 		{
7770 			const struct
7771 			{
7772 				OptRastStream	shaderStream;	// Stream in the geometry shader.
7773 				OptRastStream	staticVal;		// Static value for the extension struct.
7774 				OptRastStream	dynamicVal;		// Dynamic value for the setter.
7775 				const bool		expectDraw;		// Match between actual stream and active selected value?
7776 				const char*		name;
7777 			} rastStreamCases[] =
7778 			{
7779 				{ tcu::just(1u),	tcu::Nothing,		tcu::just(1u),		true,	"none_to_one"						},
7780 				{ tcu::just(1u),	tcu::just(0u),		tcu::just(1u),		true,	"zero_to_one"						},
7781 				{ tcu::Nothing,		tcu::just(1u),		tcu::just(0u),		true,	"one_to_zero"						},
7782 				{ tcu::just(0u),	tcu::just(1u),		tcu::just(0u),		true,	"one_to_zero_explicit"				},
7783 				{ tcu::just(0u),	tcu::Nothing,		tcu::just(1u),		false,	"none_to_one_mismatch"				},
7784 				{ tcu::just(0u),	tcu::just(0u),		tcu::just(1u),		false,	"zero_to_one_mismatch"				},
7785 				{ tcu::Nothing,		tcu::Nothing,		tcu::just(1u),		false,	"none_to_one_mismatch_implicit"		},
7786 				{ tcu::Nothing,		tcu::just(0u),		tcu::just(1u),		false,	"zero_to_one_mismatch_implicit"		},
7787 			};
7788 
7789 			for (const auto& rastStreamCase : rastStreamCases)
7790 			{
7791 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
7792 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
7793 				// must be set if the used pipeline contains the dynamic state.
7794 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(rastStreamCase.staticVal))
7795 					continue;
7796 
7797 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7798 
7799 				config.rasterizationStreamConfig.staticValue	= rastStreamCase.staticVal;
7800 				config.rasterizationStreamConfig.dynamicValue	= rastStreamCase.dynamicVal;
7801 				config.shaderRasterizationStream				= rastStreamCase.shaderStream;
7802 				config.referenceColor.reset						(new SingleColorGenerator(rastStreamCase.expectDraw ? kDefaultTriangleColor : kDefaultClearColor));
7803 
7804 				const auto testName = std::string("rasterization_stream_") + rastStreamCase.name;
7805 
7806 				// Dynamically switch rasterization streams
7807 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7808 			}
7809 		}
7810 
7811 		// Provoking vertex mode.
7812 		{
7813 			const struct
7814 			{
7815 				OptBoolean		staticVal;
7816 				OptBoolean		dynamicVal;
7817 				const char*		name;
7818 			} provokingVtxCases[] =
7819 			{
7820 				// Dynamically switch provoking vertex mode from none (first) to last
7821 				{ tcu::Nothing,		tcu::just(true),	"provoking_vertex_first_to_last_implicit"	},
7822 				// Dynamically switch provoking vertex mode from first to last
7823 				{ tcu::just(false),	tcu::just(true),	"provoking_vertex_first_to_last_explicit"			},
7824 				// Dynamically switch provoking vertex mode from last to first
7825 				{ tcu::just(true),	tcu::just(false),	"provoking_vertex_last_to_first"			},
7826 			};
7827 
7828 			for (const auto& provokingVtxCase : provokingVtxCases)
7829 			{
7830 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
7831 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
7832 				// must be set if the used pipeline contains the dynamic state.
7833 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(provokingVtxCase.staticVal))
7834 					continue;
7835 
7836 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getProvokingVertexWithPaddingGenerator(provokingVtxCase.dynamicVal.get()));
7837 				config.provokingVertexConfig.staticValue	= provokingVtxCase.staticVal;
7838 				config.provokingVertexConfig.dynamicValue	= provokingVtxCase.dynamicVal;
7839 				config.oversizedTriangle					= true;
7840 
7841 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, provokingVtxCase.name, config));
7842 			}
7843 		}
7844 
7845 		// Depth clip negative one to one.
7846 		{
7847 			const struct
7848 			{
7849 				OptBoolean		staticVal;
7850 				OptBoolean		dynamicVal;
7851 				const char*		name;
7852 			} negativeOneToOneCases[] =
7853 			{
7854 				// Dynamically switch negative one to one mode from none (false) to true
7855 				{ tcu::Nothing,		tcu::just(true),	"negative_one_to_one_false_to_true_implicit"	},
7856 				// Dynamically switch negative one to one mode from false to true
7857 				{ tcu::just(false),	tcu::just(true),	"negative_one_to_one_false_to_true_explicit"		},
7858 				// Dynamically switch negative one to one mode from true to false
7859 				{ tcu::just(true),	tcu::just(false),	"negative_one_to_one_true_to_false"		},
7860 			};
7861 
7862 			for (const auto& negOneToOneCase : negativeOneToOneCases)
7863 			{
7864 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
7865 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
7866 				// must be set if the used pipeline contains the dynamic state.
7867 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(negOneToOneCase.staticVal))
7868 					continue;
7869 
7870 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7871 				config.negativeOneToOneConfig.staticValue	= negOneToOneCase.staticVal;
7872 				config.negativeOneToOneConfig.dynamicValue	= negOneToOneCase.dynamicVal;
7873 
7874 				// Enable depth test and set values so it passes.
7875 				config.depthTestEnableConfig.staticValue	= true;
7876 				config.depthWriteEnableConfig.staticValue	= true;
7877 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7878 				config.meshParams[0].depth					= 0.5f;
7879 				config.expectedDepth						= (config.getActiveNegativeOneToOneValue() ? 0.75f : 0.5f);
7880 
7881 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, negOneToOneCase.name, config));
7882 			}
7883 		}
7884 
7885 		// Depth clip enable.
7886 		{
7887 			const struct
7888 			{
7889 				OptBoolean		staticVal;
7890 				OptBoolean		dynamicVal;
7891 				const char*		name;
7892 			} depthClipEnableCases[] =
7893 			{
7894 				// Dynamically switch negative one to one mode from none (true) to false
7895 				{ tcu::Nothing,		tcu::just(false),	"depth_clip_enable_true_to_false_implicit"	},
7896 				// Dynamically switch negative one to one mode from true to false
7897 				{ tcu::just(true),	tcu::just(false),	"depth_clip_enable_true_to_false_explicit"		},
7898 				// Dynamically switch negative one to one mode from false to true
7899 				{ tcu::just(false),	tcu::just(true),	"depth_clip_enable_true_to_false"		},
7900 			};
7901 
7902 			for (const auto& depthClipEnableCase : depthClipEnableCases)
7903 			{
7904 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
7905 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
7906 				// must be set if the used pipeline contains the dynamic state.
7907 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(depthClipEnableCase.staticVal))
7908 					continue;
7909 
7910 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7911 				config.depthClipEnableConfig.staticValue	= depthClipEnableCase.staticVal;
7912 				config.depthClipEnableConfig.dynamicValue	= depthClipEnableCase.dynamicVal;
7913 
7914 				const bool depthClipActive = config.getActiveDepthClipEnable();
7915 
7916 				// Enable depth test and set values so it passes.
7917 				config.depthTestEnableConfig.staticValue	= true;
7918 				config.depthWriteEnableConfig.staticValue	= true;
7919 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7920 				config.meshParams[0].depth					= -0.5f;
7921 				config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
7922 				config.expectedDepth						= (depthClipActive ? 1.0f : 0.25f);
7923 				config.referenceColor.reset					(new SingleColorGenerator(depthClipActive ? kDefaultClearColor : kDefaultTriangleColor));
7924 
7925 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, depthClipEnableCase.name, config));
7926 			}
7927 		}
7928 
7929 		// Sample locations enablement.
7930 		{
7931 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7932 			config.rasterizationSamplesConfig	= kMultiSampleCount;
7933 			config.offCenterTriangle			= true;
7934 			config.offCenterProportion			= tcu::Vec2(0.90625f, 0.90625f);
7935 
7936 			// Push sample locations towards the bottom right corner so they're able to sample the off-center triangle.
7937 			config.sampleLocations				= tcu::Vec2(1.0f, 1.0f);
7938 
7939 			config.sampleLocationsEnableConfig.staticValue	= false;
7940 			config.sampleLocationsEnableConfig.dynamicValue	= true;
7941 
7942 			// Dynamically enable sample locations
7943 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_locations_enable", config));
7944 
7945 			config.sampleLocationsEnableConfig.swapValues();
7946 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
7947 
7948 			// Dynamically disable sample locations
7949 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_locations_disable", config));
7950 		}
7951 
7952 		// Coverage to color enable.
7953 		{
7954 			for (int i = 0; i < 2; ++i)
7955 			{
7956 				const bool multisample = (i > 0);
7957 
7958 				for (int j = 0; j < 2; ++j)
7959 				{
7960 					const bool		covToColor		= (j > 0);
7961 					const uint32_t	referenceRed	= ((covToColor ? (multisample ? 15u : 1u) : 48u/*matches meshParams[0].color*/));
7962 
7963 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7964 
7965 					config.oversizedTriangle						= true; // This avoids partial coverages in fragments.
7966 					config.rasterizationSamplesConfig				= (multisample ? kMultiSampleCount : kSingleSampleCount);
7967 					config.coverageToColorEnableConfig.staticValue	= !covToColor;
7968 					config.coverageToColorEnableConfig.dynamicValue	= covToColor;
7969 					config.meshParams[0].color						= tcu::Vec4(48.0f, 0.0f, 0.0f, 1.0f); // Distinct value, does not match any coverage mask.
7970 					config.referenceColor.reset						(new SingleColorGenerator(tcu::UVec4(referenceRed, 0u, 0u, 1u)));
7971 
7972 					const std::string	finalState	= (covToColor ? "enable" : "disable");
7973 					const auto			testName	= "coverage_to_color_" + finalState + "_" + (multisample ? "multisample" : "single_sample");
7974 
7975 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7976 				}
7977 			}
7978 		}
7979 
7980 		// Coverage to color location.
7981 		{
7982 			for (int i = 0; i < 2; ++i)
7983 			{
7984 				const bool multisample = (i > 0);
7985 
7986 				for (int j = 0; j < 2; ++j)
7987 				{
7988 					const bool		locationLast	= (j > 0);
7989 					const uint32_t	colorAttCount	= 4u;
7990 					const uint32_t	covToColorLoc	= (locationLast ? colorAttCount - 1u : 0u);
7991 					const uint32_t	referenceRed	= ((locationLast ? (multisample ? 15u : 1u) : 48u/*matches meshParams[0].color*/));
7992 
7993 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7994 
7995 					config.oversizedTriangle							= true; // This avoids partial coverages in fragments.
7996 					config.rasterizationSamplesConfig					= (multisample ? kMultiSampleCount : kSingleSampleCount);
7997 					config.colorAttachmentCount							= colorAttCount;
7998 					config.coverageToColorEnableConfig.staticValue		= true;
7999 					config.coverageToColorLocationConfig.staticValue	= (locationLast ? 0u : colorAttCount - 1u);
8000 					config.coverageToColorLocationConfig.dynamicValue	= covToColorLoc;
8001 					config.meshParams[0].color							= tcu::Vec4(48.0f, 0.0f, 0.0f, 1.0f); // Distinct value, does not match any coverage mask.
8002 					config.referenceColor.reset							(new SingleColorGenerator(tcu::UVec4(referenceRed, 0u, 0u, 1u)));
8003 
8004 					const auto	locName		= std::to_string(covToColorLoc);
8005 					const auto	testName	= "coverage_to_color_location_" + locName + "_" + (multisample ? "multisample" : "single_sample");
8006 					// Dynamically enable coverage to color in location
8007 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8008 				}
8009 			}
8010 		}
8011 
8012 #ifndef CTS_USES_VULKANSC
8013 		// Coverage modulation mode.
8014 		{
8015 			const struct
8016 			{
8017 				vk::VkCoverageModulationModeNV	staticVal;
8018 				vk::VkCoverageModulationModeNV	dynamicVal;
8019 				tcu::Vec4						partialCovFactor; // This will match the expected coverage proportion. See below.
8020 				const char*						name;
8021 			} modulationModeCases[] =
8022 			{
8023 				{ vk::VK_COVERAGE_MODULATION_MODE_NONE_NV,	vk::VK_COVERAGE_MODULATION_MODE_RGB_NV,		tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f),	"rgb"	},
8024 				{ vk::VK_COVERAGE_MODULATION_MODE_NONE_NV,	vk::VK_COVERAGE_MODULATION_MODE_ALPHA_NV,	tcu::Vec4(1.0f, 1.0f, 1.0f, 0.25f),		"alpha"	},
8025 				{ vk::VK_COVERAGE_MODULATION_MODE_NONE_NV,	vk::VK_COVERAGE_MODULATION_MODE_RGBA_NV,	tcu::Vec4(0.25f, 0.25f, 0.25f, 0.25f),	"rgba"	},
8026 				{ vk::VK_COVERAGE_MODULATION_MODE_RGBA_NV,	vk::VK_COVERAGE_MODULATION_MODE_NONE_NV,	tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f),		"none"	},
8027 			};
8028 
8029 			for (const auto& modulationModeCase : modulationModeCases)
8030 			{
8031 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8032 
8033 				config.coverageModulation			= true;
8034 				config.rasterizationSamplesConfig	= kMultiSampleCount;
8035 				config.colorSampleCount				= kSingleSampleCount;
8036 
8037 				// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8038 				// * Leave the corner pixel uncovered.
8039 				// * Cover the top border with sample 3 (1/4 the samples = 0.25).
8040 				// * Cover the left border with sample 1 (1/4 the samples = 0.25).
8041 				config.offCenterProportion	= tcu::Vec2(0.6875f, 0.6875f);
8042 				config.offCenterTriangle	= true;
8043 
8044 				config.coverageModulationModeConfig.staticValue		= modulationModeCase.staticVal;
8045 				config.coverageModulationModeConfig.dynamicValue	= modulationModeCase.dynamicVal;
8046 
8047 				const auto& partialCoverageColor = kDefaultTriangleColor * modulationModeCase.partialCovFactor;
8048 				config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, partialCoverageColor, kDefaultClearColor, partialCoverageColor));
8049 
8050 				const auto testName = std::string("coverage_modulation_mode_") + modulationModeCase.name;
8051 				// Dynamically set coverage modulation mode
8052 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8053 			}
8054 		}
8055 
8056 		// Coverage modulation table enable.
8057 		{
8058 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8059 
8060 			config.coverageModulation			= true;
8061 			config.rasterizationSamplesConfig	= kMultiSampleCount;
8062 			config.colorSampleCount				= kSingleSampleCount;
8063 
8064 			// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8065 			// * Leave the corner pixel uncovered.
8066 			// * Cover the top border with sample 3 (1/4 the samples = 0.25).
8067 			// * Cover the left border with sample 1 (1/4 the samples = 0.25).
8068 			config.offCenterProportion	= tcu::Vec2(0.6875f, 0.6875f);
8069 			config.offCenterTriangle	= true;
8070 
8071 			const CovModTableVec table { 0.75f, 1.0f, 1.0f, 1.0f };
8072 			config.coverageModulationModeConfig.staticValue		= vk::VK_COVERAGE_MODULATION_MODE_RGB_NV;
8073 			config.coverageModTableConfig.staticValue			= table;
8074 
8075 			config.coverageModTableEnableConfig.staticValue		= false;
8076 			config.coverageModTableEnableConfig.dynamicValue	= true;
8077 
8078 			const auto	tableCoverFactor			= tcu::Vec4(0.75f, 0.75f, 0.75f, 1.0f);
8079 			const auto&	tablePartialCoverageColor	= kDefaultTriangleColor * tableCoverFactor;
8080 
8081 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, tablePartialCoverageColor, kDefaultClearColor, tablePartialCoverageColor));
8082 
8083 			// Dynamically enable coverage modulation table
8084 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_enable", config));
8085 
8086 			// Reverse situation, fall back to the default modulation factor.
8087 			config.coverageModTableEnableConfig.swapValues();
8088 			const auto	noTableCoverFactor			= tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f);
8089 			const auto&	noTablePartialCoverageColor	= kDefaultTriangleColor * noTableCoverFactor;
8090 			config.referenceColor.reset				(new TopLeftBorderGenerator(kDefaultTriangleColor, noTablePartialCoverageColor, kDefaultClearColor, noTablePartialCoverageColor));
8091 
8092 			// Dynamically disable coverage modulation table
8093 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_disable", config));
8094 		}
8095 
8096 		// Coverage modulation table.
8097 		{
8098 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8099 
8100 			config.coverageModulation			= true;
8101 			config.rasterizationSamplesConfig	= kMultiSampleCount;
8102 			config.colorSampleCount				= kSingleSampleCount;
8103 
8104 			// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8105 			// * Cover the corner pixel with 1 sample (0.25).
8106 			// * Cover the top border with 2 samples (0.5).
8107 			// * Cover the left border with 2 samples (0.5).
8108 			config.offCenterProportion	= tcu::Vec2(0.5f, 0.5f);
8109 			config.offCenterTriangle	= true;
8110 
8111 			config.coverageModulationModeConfig.staticValue		= vk::VK_COVERAGE_MODULATION_MODE_RGB_NV;
8112 			config.coverageModTableEnableConfig.staticValue		= true;
8113 
8114 			//									corner	border	unused		main
8115 			const CovModTableVec goodTable	{	0.75f,	0.25f,	0.0f,		0.5f	};
8116 			const CovModTableVec badTable	{	0.5f,	0.75f,	1.0f,		0.25f	};
8117 
8118 			config.coverageModTableConfig.staticValue	= badTable;
8119 			config.coverageModTableConfig.dynamicValue	= goodTable;
8120 
8121 			// VK_COVERAGE_MODULATION_MODE_RGB_NV, factors for RGB according to goodTable, alpha untouched.
8122 			const auto	cornerFactor	= tcu::Vec4(0.75f, 0.75f, 0.75f, 1.0f);
8123 			const auto	borderFactor	= tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f);
8124 			const auto	mainFactor		= tcu::Vec4(0.5f,  0.5f,  0.5f,  1.0f);
8125 
8126 			const auto&	cornerColor		= kDefaultTriangleColor * cornerFactor;
8127 			const auto&	borderColor		= kDefaultTriangleColor * borderFactor;
8128 			const auto&	mainColor		= kDefaultTriangleColor * mainFactor;
8129 
8130 			config.referenceColor.reset(new TopLeftBorderGenerator(mainColor, borderColor, cornerColor, borderColor));
8131 
8132 			// Dynamically change coverage modulation table
8133 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_change", config));
8134 		}
8135 
8136 		// Coverage reduction mode.
8137 		{
8138 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8139 
8140 			config.coverageReduction			= true;
8141 			config.rasterizationSamplesConfig	= kMultiSampleCount;
8142 			config.colorSampleCount				= kSingleSampleCount;
8143 
8144 			// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8145 			// * Leave the corner pixel uncovered.
8146 			// * Cover the top border with sample 3 (1/4 the samples = 0.25).
8147 			// * Cover the left border with sample 1 (1/4 the samples = 0.25).
8148 			config.offCenterProportion	= tcu::Vec2(0.6875f, 0.6875f);
8149 			config.offCenterTriangle	= true;
8150 
8151 			config.coverageReductionModeConfig.staticValue	= vk::VK_COVERAGE_REDUCTION_MODE_MERGE_NV;
8152 			config.coverageReductionModeConfig.dynamicValue	= vk::VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV;
8153 
8154 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
8155 			// Dynamically set coverage reduction truncate mode
8156 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_reduction_truncate", config));
8157 
8158 			// In merge mode, the only pixel without coverage should be the corner. However, the spec is a bit ambiguous in this
8159 			// case:
8160 			//
8161 			//    VK_COVERAGE_REDUCTION_MODE_MERGE_NV specifies that each color sample will be associated with an
8162 			//    implementation-dependent subset of samples in the pixel coverage. If any of those associated samples are covered,
8163 			//    the color sample is covered.
8164 			//
8165 			// We cannot be 100% sure the single color sample will be associated with the whole set of 4 rasterization samples, but
8166 			// the test appears to pass in existing HW.
8167 			config.coverageReductionModeConfig.swapValues();
8168 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultTriangleColor, kDefaultClearColor, kDefaultTriangleColor));
8169 			// Dynamically set coverage reduction merge mode
8170 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_reduction_merge", config));
8171 		}
8172 
8173 		// Viewport swizzle.
8174 		{
8175 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8176 
8177 			config.viewportSwizzle				= true;
8178 			config.oversizedTriangle			= true;
8179 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
8180 
8181 			const vk::VkViewportSwizzleNV idSwizzle
8182 			{
8183 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
8184 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
8185 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
8186 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
8187 			};
8188 
8189 			const vk::VkViewportSwizzleNV yxSwizzle // Switches Y and X coordinates, makes the oversized triangle clockwise.
8190 			{
8191 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, // <--
8192 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, // <--
8193 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
8194 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
8195 			};
8196 
8197 			config.viewportSwizzleConfig.staticValue	= ViewportSwzVec(1u, idSwizzle);
8198 			config.viewportSwizzleConfig.dynamicValue	= ViewportSwzVec(1u, yxSwizzle);
8199 			config.frontFaceConfig.staticValue			= vk::VK_FRONT_FACE_CLOCKWISE;
8200 
8201 			// Dynamically set a viewport swizzle with X and Y switched around
8202 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_swizzle_yx", config));
8203 
8204 			config.viewportSwizzleConfig.swapValues();
8205 			config.frontFaceConfig.staticValue			= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
8206 			// Dynamically set the viewport identity swizzle
8207 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_swizzle_xy", config));
8208 		}
8209 
8210 		// Shading rate image enable.
8211 		// VK_NV_shading_rate_image is disabled when using shader objects due to interaction with VK_KHR_fragment_shading_rate
8212 		if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
8213 		{
8214 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8215 
8216 			for (int i = 0; i < 2; ++i)
8217 			{
8218 				const bool			sriEnable	= (i > 0);
8219 				const std::string	enableStr	= (sriEnable ? "enable" : "disable");
8220 
8221 				config.shadingRateImage = true;
8222 				config.shadingRateImageEnableConfig.staticValue = !sriEnable;
8223 				config.shadingRateImageEnableConfig.dynamicValue = sriEnable;
8224 				config.referenceColor.reset(new SingleColorGenerator(sriEnable ? kDefaultClearColor : kDefaultTriangleColor));
8225 
8226 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "shading_rate_image_" + enableStr, config));
8227 			}
8228 		}
8229 
8230 		// Viewport W Scaling enable.
8231 		{
8232 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8233 
8234 			for (int i = 0; i < 2; ++i)
8235 			{
8236 				const bool			wScalingEnable	= (i > 0);
8237 				const std::string	enableStr		= (wScalingEnable ? "enable" : "disable");
8238 
8239 				config.colorVerificator = verifyTopLeftCornerExactly;
8240 				config.viewportWScaling = true;
8241 				config.viewportWScalingEnableConfig.staticValue = !wScalingEnable;
8242 				config.viewportWScalingEnableConfig.dynamicValue = wScalingEnable;
8243 				config.referenceColor.reset(new SingleColorGenerator(wScalingEnable ? kDefaultClearColor : kDefaultTriangleColor));
8244 
8245 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_w_scaling_" + enableStr, config));
8246 			}
8247 		}
8248 
8249 		// Representative fragment test state.
8250 		{
8251 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8252 
8253 			for (int i = 0; i < 2; ++i)
8254 			{
8255 				const bool			reprFragTestEnable	= (i > 0);
8256 				const std::string	enableStr			= (reprFragTestEnable ? "enable" : "disable");
8257 
8258 				config.depthTestEnableConfig.staticValue	= true;
8259 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
8260 				config.colorWriteMaskConfig.staticValue		= 0u; // Disable color writes.
8261 				config.oversizedTriangle					= true;
8262 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
8263 
8264 				config.representativeFragmentTest				= true;
8265 				config.reprFragTestEnableConfig.staticValue		= !reprFragTestEnable;
8266 				config.reprFragTestEnableConfig.dynamicValue	= reprFragTestEnable;
8267 
8268 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "repr_frag_test_" + enableStr, config));
8269 			}
8270 		}
8271 #endif // CTS_USES_VULKANSC
8272 
8273 		// Conservative rasterization mode.
8274 		{
8275 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8276 			config.offCenterTriangle = true;
8277 
8278 			// Single-sampling at the pixel center should not cover this, but overestimation should result in coverage.
8279 			config.offCenterProportion							= tcu::Vec2(0.75f, 0.75f);
8280 			config.extraPrimitiveOverEstConfig.staticValue		= 0.0f;
8281 			config.conservativeRasterModeConfig.staticValue		= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
8282 			config.conservativeRasterModeConfig.dynamicValue	= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
8283 
8284 			// Dynamically set conservative rasterization mode to overestimation
8285 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_overestimate", config));
8286 
8287 			config.conservativeRasterModeConfig.swapValues();
8288 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
8289 			// Dynamically set conservative rasterization mode to disabled
8290 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_disabled", config));
8291 		}
8292 		{
8293 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8294 			config.offCenterTriangle = true;
8295 
8296 			// Single-sampling at the pixel center should cover this, but underestimation should result in lack of coverage.
8297 			config.offCenterProportion							= tcu::Vec2(0.25f, 0.25f);
8298 			config.extraPrimitiveOverEstConfig.staticValue		= 0.0f;
8299 			config.conservativeRasterModeConfig.staticValue		= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
8300 			config.conservativeRasterModeConfig.dynamicValue	= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT;
8301 			config.referenceColor.reset							(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
8302 
8303 			// Dynamically set conservative rasterization mode to underestimation
8304 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_underestimate", config));
8305 		}
8306 
8307 		// Extra primitive overestimation size.
8308 		// Notes as of 2022-08-12 and gpuinfo.org:
8309 		//    * primitiveOverestimationSize is typically 0.0, 0.001953125 or 0.00195313 (i.e. very small).
8310 		//    * maxExtraPrimitiveOverestimationSize is typically 0.0 or 0.75 (no other values).
8311 		//    * extraPrimitiveOverestimationSizeGranularity is typically 0.0 or 0.25 (no other values).
8312 		{
8313 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8314 			config.offCenterTriangle = true;
8315 
8316 			// Move the triangle by more than one pixel, then use an extra overestimation of 0.75 to cover the border pixels too.
8317 			config.offCenterProportion						= tcu::Vec2(1.125f, 1.125f);
8318 			config.maxPrimitiveOverestimationSize			= 0.5f; // Otherwise the base overestimation size will be enough. This should never trigger.
8319 			config.conservativeRasterModeConfig.staticValue	= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
8320 			config.extraPrimitiveOverEstConfig.staticValue	= 0.0f;
8321 			config.extraPrimitiveOverEstConfig.dynamicValue	= 0.75f; // Large enough to reach the center of the border pixel.
8322 
8323 			// Dynamically set the extra overestimation size to a large value
8324 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "extra_overestimation_size_large", config));
8325 
8326 			config.extraPrimitiveOverEstConfig.swapValues();
8327 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
8328 
8329 			// Dynamically set the extra overestimation size to zero
8330 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "extra_overestimation_size_none", config));
8331 		}
8332 
8333 		// Depth bias enable with static or dynamic depth bias parameters.
8334 		{
8335 			const DepthBiasParams kAlternativeDepthBiasParams = { 2e7f, 0.25f };
8336 
8337 			for (int dynamicBiasIter = 0; dynamicBiasIter < 2; ++dynamicBiasIter)
8338 			{
8339 				const bool useDynamicBias = (dynamicBiasIter > 0);
8340 
8341 				{
8342 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8343 
8344 					// Enable depth test and write 1.0f
8345 					config.depthTestEnableConfig.staticValue = true;
8346 					config.depthWriteEnableConfig.staticValue = true;
8347 					config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8348 					// Clear depth buffer to 0.25f
8349 					config.clearDepthValue = 0.25f;
8350 					// Write depth to 0.5f
8351 					config.meshParams[0].depth = 0.5f;
8352 
8353 					// Enable dynamic depth bias and expect the depth value to be clamped to 0.75f based on depthBiasConstantFactor and depthBiasClamp
8354 					if (useDynamicBias)
8355 					{
8356 						config.depthBiasConfig.staticValue	= kNoDepthBiasParams;
8357 						config.depthBiasConfig.dynamicValue	= kAlternativeDepthBiasParams;
8358 					}
8359 					else
8360 					{
8361 						config.depthBiasConfig.staticValue	= kAlternativeDepthBiasParams;
8362 					}
8363 
8364 					config.depthBiasEnableConfig.staticValue = false;
8365 					config.depthBiasEnableConfig.dynamicValue = tcu::just(true);
8366 					config.expectedDepth = 0.75f;
8367 
8368 					std::string caseName = "depth_bias_enable";
8369 
8370 					if (useDynamicBias)
8371 					{
8372 						caseName += "_dynamic_bias_params";
8373 					}
8374 
8375 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
8376 				}
8377 				{
8378 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8379 
8380 					// Enable depth test and write 1.0f
8381 					config.depthTestEnableConfig.staticValue = true;
8382 					config.depthWriteEnableConfig.staticValue = true;
8383 					config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8384 					// Clear depth buffer to 0.25f
8385 					config.clearDepthValue = 0.25f;
8386 					// Write depth to 0.5f
8387 					config.meshParams[0].depth = 0.5f;
8388 
8389 					// Disable dynamic depth bias and expect the depth value to remain at 0.5f based on written value
8390 					if (useDynamicBias)
8391 					{
8392 						config.depthBiasConfig.staticValue	= kNoDepthBiasParams;
8393 						config.depthBiasConfig.dynamicValue	= kAlternativeDepthBiasParams;
8394 					}
8395 					else
8396 					{
8397 						config.depthBiasConfig.staticValue	= kAlternativeDepthBiasParams;
8398 					}
8399 
8400 					config.depthBiasEnableConfig.staticValue = true;
8401 					config.depthBiasEnableConfig.dynamicValue = tcu::just(false);
8402 					config.expectedDepth = 0.5f;
8403 
8404 					std::string caseName = "depth_bias_disable";
8405 
8406 					if (useDynamicBias)
8407 					{
8408 						caseName += "_dynamic_bias_params";
8409 					}
8410 
8411 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
8412 				}
8413 			}
8414 		}
8415 
8416 #ifndef CTS_USES_VULKANSC
8417 		// Depth bias representation info.
8418 		{
8419 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8420 
8421 			// Enable depth test and writes.
8422 			config.depthTestEnableConfig.staticValue	= true;
8423 			config.depthWriteEnableConfig.staticValue	= true;
8424 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
8425 			config.clearDepthValue						= 0.0f;
8426 			config.meshParams[0].depth					= 0.125f;
8427 			const double targetBias						= 0.5f;
8428 			config.expectedDepth						= 0.625f; // mesh depth + target bias
8429 
8430 			vk::VkDepthBiasRepresentationInfoEXT depthBiasReprInfo	= vk::initVulkanStructure();
8431 			depthBiasReprInfo.depthBiasRepresentation				= vk::VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT;
8432 			depthBiasReprInfo.depthBiasExact						= VK_TRUE;
8433 			config.depthBiasReprInfo								= depthBiasReprInfo;
8434 			config.neededDepthChannelClass							= tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
8435 
8436 			// We will choose a format with floating point representation, but force a UNORM exact depth bias representation.
8437 			// With this, the value of R should be 2^(-N), with N being the number of mantissa bits plus one (2^(-24) for D32_SFLOAT).
8438 			// To reach our target bias, the constant factor must be calculated based on it and the value of R.
8439 			//
8440 			// If the VkDepthBiasRepresentationInfoEXT is not taken into account, the value of R would be 2^(E-N), such that:
8441 			// E is the maximum exponent in the range of Z values that the primitive uses (-3 for our mesh depth of 0.125).
8442 			// N is the number of mantissa bits in the floating point format (23 in our case)
8443 			// R would be wrongly calculated as 2^(-26) (1/4th of the intended value).
8444 			const double minR			= 1.0 / static_cast<double>(1u << 24u);
8445 			const double constantFactor	= targetBias / minR;
8446 
8447 			const DepthBiasParams kPositiveBias			{ static_cast<float>(constantFactor), 0.0f };
8448 			config.depthBiasEnableConfig.staticValue	= true;
8449 			config.depthBiasConfig.staticValue			= kNoDepthBiasParams;
8450 			config.depthBiasConfig.dynamicValue			= kPositiveBias;
8451 			config.extraDepthThreshold					= static_cast<float>(minR);
8452 
8453 			const char* caseName = "depth_bias_repr_info";
8454 			// Dynamically set the depth bias representation information
8455 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
8456 		}
8457 		{
8458 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8459 
8460 			// Enable depth test and writes.
8461 			config.depthTestEnableConfig.staticValue	= true;
8462 			config.depthWriteEnableConfig.staticValue	= true;
8463 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
8464 			config.clearDepthValue						= 0.25f;	// Clear depth buffer to 0.25.
8465 			config.meshParams[0].depth					= 0.5f;		// Set mesh depth to 0.5 as a base.
8466 
8467 			// Enable dynamic depth bias to add a 0.25 bias to the mesh depth (using float representation), expecting the final
8468 			// depth to be 0.75.
8469 			vk::VkDepthBiasRepresentationInfoEXT depthBiasReprInfo	= vk::initVulkanStructure();
8470 			depthBiasReprInfo.depthBiasRepresentation				= vk::VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT;
8471 			depthBiasReprInfo.depthBiasExact						= VK_FALSE;
8472 			config.depthBiasReprInfo								= depthBiasReprInfo;
8473 
8474 			const DepthBiasParams kPositiveBias			{ 0.25f, 0.0f };
8475 			config.depthBiasEnableConfig.staticValue	= true;
8476 			config.depthBiasConfig.staticValue			= kNoDepthBiasParams;
8477 			config.depthBiasConfig.dynamicValue			= kPositiveBias;
8478 			config.expectedDepth						= 0.75f;
8479 
8480 			const char* caseName = "depth_bias_repr_info_float";
8481 			// Dynamically set the depth bias representation information to float representation
8482 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
8483 		}
8484 #endif // CTS_USES_VULKANSC
8485 
8486 		// Depth compare op.
8487 		{
8488 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
8489 			const tcu::Vec4 kAlternativeColor				(0.0f, 0.0f, 0.5f, 1.0f);
8490 			baseConfig.depthTestEnableConfig.staticValue	= true;
8491 			baseConfig.depthWriteEnableConfig.staticValue	= true;
8492 			baseConfig.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_NEVER;
8493 			baseConfig.clearDepthValue						= 0.5f;
8494 
8495 			{
8496 				TestConfig config = baseConfig;
8497 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
8498 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_NEVER;
8499 				config.meshParams[0].depth					= 0.25f;
8500 				config.expectedDepth						= 0.5f;
8501 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
8502 				// Dynamically set the depth compare operator to NEVER
8503 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_never", config));
8504 			}
8505 			{
8506 				TestConfig config = baseConfig;
8507 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS;
8508 				config.meshParams[0].depth					= 0.25f;
8509 				config.expectedDepth						= 0.25f;
8510 				// Dynamically set the depth compare operator to LESS
8511 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less", config));
8512 			}
8513 			{
8514 				TestConfig config = baseConfig;
8515 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER;
8516 				config.meshParams[0].depth					= 0.75f;
8517 				config.expectedDepth						= 0.75f;
8518 				// Dynamically set the depth compare operator to GREATER
8519 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater", config));
8520 			}
8521 			{
8522 				TestConfig config = baseConfig;
8523 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_EQUAL;
8524 				config.meshParams[0].depth					= 0.5f;
8525 				config.meshParams[0].color					= kAlternativeColor;
8526 				// Draw another mesh in front to verify it does not pass the equality test.
8527 				config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.25f));
8528 				config.expectedDepth						= 0.5f;
8529 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
8530 				// Dynamically set the depth compare operator to EQUAL
8531 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_equal", config));
8532 			}
8533 			{
8534 				TestConfig config = baseConfig;
8535 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS_OR_EQUAL;
8536 				config.meshParams[0].depth					= 0.25f;
8537 				config.expectedDepth						= 0.25f;
8538 				// Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with smaller depth
8539 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less", config));
8540 			}
8541 			{
8542 				TestConfig config = baseConfig;
8543 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS_OR_EQUAL;
8544 				config.meshParams[0].depth					= 0.5f;
8545 				config.expectedDepth						= 0.5f;
8546 				// Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with equal depth
8547 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_equal", config));
8548 			}
8549 			{
8550 				TestConfig config = baseConfig;
8551 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS_OR_EQUAL;
8552 				config.meshParams[0].depth					= 0.25f;
8553 				// Draw another mesh with the same depth in front of it.
8554 				config.meshParams.push_back(MeshParams(kAlternativeColor, 0.25f));
8555 				config.expectedDepth						= 0.25f;
8556 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
8557 				// Dynamically set the depth compare operator to LESS_OR_EQUAL and draw two meshes with less and equal depth
8558 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less_then_equal", config));
8559 			}
8560 			{
8561 				TestConfig config = baseConfig;
8562 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
8563 				config.meshParams[0].depth					= 0.75f;
8564 				config.expectedDepth						= 0.75f;
8565 				// Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with greater depth
8566 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater", config));
8567 			}
8568 			{
8569 				TestConfig config = baseConfig;
8570 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
8571 				config.meshParams[0].depth					= 0.5f;
8572 				config.expectedDepth						= 0.5f;
8573 				// Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with equal depth
8574 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_equal", config));
8575 			}
8576 			{
8577 				TestConfig config = baseConfig;
8578 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
8579 				config.meshParams[0].depth					= 0.75f;
8580 				// Draw another mesh with the same depth in front of it.
8581 				config.meshParams.push_back(MeshParams(kAlternativeColor, 0.75f));
8582 				config.expectedDepth						= 0.75f;
8583 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
8584 				// Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw two meshes with greater and equal depth
8585 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater_then_equal", config));
8586 			}
8587 			{
8588 				TestConfig config = baseConfig;
8589 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_NOT_EQUAL;
8590 
8591 				// Draw first mesh in front.
8592 				config.meshParams[0].depth					= 0.25f;
8593 				// Draw another mesh in the back, this should pass too.
8594 				config.meshParams.push_back(MeshParams(kAlternativeColor, 0.5f));
8595 				// Finally a new mesh with the same depth. This should not pass.
8596 				config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.5f));
8597 
8598 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
8599 				config.expectedDepth						= 0.5f;
8600 				// Dynamically set the depth compare operator to NOT_EQUAL
8601 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_not_equal", config));
8602 			}
8603 			{
8604 				TestConfig config = baseConfig;
8605 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_ALWAYS;
8606 
8607 				config.meshParams[0].depth					= 0.5f;
8608 				config.expectedDepth						= 0.5f;
8609 				// Dynamically set the depth compare operator to ALWAYS and draw with equal depth
8610 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_equal", config));
8611 
8612 				config.meshParams[0].depth					= 0.25f;
8613 				config.expectedDepth						= 0.25f;
8614 				// Dynamically set the depth compare operator to ALWAYS and draw with less depth
8615 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_less", config));
8616 
8617 				config.meshParams[0].depth					= 0.75f;
8618 				config.expectedDepth						= 0.75f;
8619 				// Dynamically set the depth compare operator to ALWAYS and draw with greater depth
8620 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_greater", config));
8621 			}
8622 		}
8623 
8624 		// Depth bounds test.
8625 		{
8626 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
8627 			baseConfig.depthBoundsConfig.staticValue			= std::make_pair(0.25f, 0.75f);
8628 			baseConfig.meshParams[0].depth						= 0.0f;
8629 
8630 			{
8631 				TestConfig config = baseConfig;
8632 				config.depthBoundsTestEnableConfig.staticValue	= false;
8633 				config.depthBoundsTestEnableConfig.dynamicValue	= tcu::just(true);
8634 				config.referenceColor.reset						(new SingleColorGenerator(kDefaultClearColor));
8635 				// Dynamically enable the depth bounds test
8636 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_enable", config));
8637 			}
8638 			{
8639 				TestConfig config = baseConfig;
8640 				config.depthBoundsTestEnableConfig.staticValue	= true;
8641 				config.depthBoundsTestEnableConfig.dynamicValue	= tcu::just(false);
8642 				// Dynamically disable the depth bounds test
8643 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_disable", config));
8644 			}
8645 		}
8646 
8647 		// Stencil test enable.
8648 		{
8649 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8650 			config.stencilTestEnableConfig.staticValue				= false;
8651 			config.stencilTestEnableConfig.dynamicValue				= tcu::just(true);
8652 			config.stencilOpConfig.staticValue.front().compareOp	= vk::VK_COMPARE_OP_NEVER;
8653 			config.referenceColor.reset								(new SingleColorGenerator(kDefaultClearColor));
8654 			// Dynamically enable the stencil test
8655 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_enable", config));
8656 		}
8657 		{
8658 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8659 			config.stencilTestEnableConfig.staticValue				= true;
8660 			config.stencilTestEnableConfig.dynamicValue				= tcu::just(false);
8661 			config.stencilOpConfig.staticValue.front().compareOp	= vk::VK_COMPARE_OP_NEVER;
8662 			// Dynamically disable the stencil test
8663 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_disable", config));
8664 		}
8665 
8666 		// Stencil operation. Many combinations are possible.
8667 		{
8668 			static const struct
8669 			{
8670 				vk::VkStencilFaceFlags	face;
8671 				std::string				name;
8672 			} kFaces[] =
8673 			{
8674 				{ vk::VK_STENCIL_FACE_FRONT_BIT,			"face_front"		},
8675 				{ vk::VK_STENCIL_FACE_BACK_BIT,				"face_back"			},
8676 				{ vk::VK_STENCIL_FACE_FRONT_AND_BACK,		"face_both_single"	},
8677 				{ vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM,	"face_both_dual"	},	// MAX_ENUM is a placeholder.
8678 			};
8679 
8680 			static const struct
8681 			{
8682 				vk::VkCompareOp		compareOp;
8683 				std::string			name;
8684 			} kCompare[] =
8685 			{
8686 				{ vk::VK_COMPARE_OP_NEVER,				"xf"		},
8687 				{ vk::VK_COMPARE_OP_LESS,				"lt"		},
8688 				{ vk::VK_COMPARE_OP_EQUAL,				"eq"		},
8689 				{ vk::VK_COMPARE_OP_LESS_OR_EQUAL,		"le"		},
8690 				{ vk::VK_COMPARE_OP_GREATER,			"gt"		},
8691 				{ vk::VK_COMPARE_OP_GREATER_OR_EQUAL,	"ge"		},
8692 				{ vk::VK_COMPARE_OP_ALWAYS,				"xt"		},
8693 			};
8694 
8695 			using u8vec = std::vector<deUint8>;
8696 
8697 			static const auto kMinVal	= std::numeric_limits<deUint8>::min();
8698 			static const auto kMaxVal	= std::numeric_limits<deUint8>::max();
8699 			static const auto kMidVal	= static_cast<deUint8>(kMaxVal * 2u / 5u);
8700 			static const auto kMinValI	= static_cast<int>(kMinVal);
8701 			static const auto kMaxValI	= static_cast<int>(kMaxVal);
8702 
8703 			static const struct
8704 			{
8705 				vk::VkStencilOp		stencilOp;
8706 				std::string			name;
8707 				u8vec				clearValues;	// One test per clear value interesting for this operation.
8708 				vk::VkStencilOp		incompatibleOp;	// Alternative operation giving incompatible results for the given values.
8709 			} kStencilOps[] =
8710 			{
8711 				{ vk::VK_STENCIL_OP_KEEP,					"keep",			u8vec{kMidVal},					vk::VK_STENCIL_OP_ZERO					},
8712 				{ vk::VK_STENCIL_OP_ZERO,					"zero",			u8vec{kMidVal},					vk::VK_STENCIL_OP_KEEP					},
8713 				{ vk::VK_STENCIL_OP_REPLACE,				"replace",		u8vec{kMidVal},					vk::VK_STENCIL_OP_ZERO					},
8714 				{ vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP,	"inc_clamp",	u8vec{kMaxVal - 1, kMaxVal},	vk::VK_STENCIL_OP_ZERO					},
8715 				{ vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP,	"dec_clamp",	u8vec{kMinVal + 1, kMinVal},	vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP	},
8716 				{ vk::VK_STENCIL_OP_INVERT,					"invert",		u8vec{kMidVal},					vk::VK_STENCIL_OP_ZERO					},
8717 				{ vk::VK_STENCIL_OP_INCREMENT_AND_WRAP,		"inc_wrap",		u8vec{kMaxVal - 1, kMaxVal},	vk::VK_STENCIL_OP_KEEP					},
8718 				{ vk::VK_STENCIL_OP_DECREMENT_AND_WRAP,		"dec_wrap",		u8vec{kMinVal + 1, kMinVal},	vk::VK_STENCIL_OP_KEEP					},
8719 			};
8720 
8721 			for (const auto& face : kFaces)
8722 			for (const auto& compare : kCompare)
8723 			for (const auto& op : kStencilOps)
8724 			{
8725 				// Try clearing the stencil value with different values.
8726 				for (const auto clearVal : op.clearValues)
8727 				{
8728 					// Use interesting values as the reference stencil value.
8729 					for (int delta = -1; delta <= 1; ++delta)
8730 					{
8731 						const int refVal = clearVal + delta;
8732 						if (refVal < kMinValI || refVal > kMaxValI)
8733 							continue;
8734 
8735 						const auto refValU8		= static_cast<deUint8>(refVal);
8736 						const auto refValU32	= static_cast<deUint32>(refVal);
8737 
8738 						// Calculate outcome of the stencil test itself.
8739 						const bool wouldPass = stencilPasses(compare.compareOp, clearVal, refValU8);
8740 
8741 						// If the test passes, use an additional variant for the depthFail operation.
8742 						const int subCases = (wouldPass ? 2 : 1);
8743 
8744 						for (int subCaseIdx = 0; subCaseIdx < subCases; ++subCaseIdx)
8745 						{
8746 							for (int extraPipelineIter = 0; extraPipelineIter < 2; ++extraPipelineIter)
8747 							{
8748 								const bool useExtraPipeline = (extraPipelineIter > 0);		// Bind and draw with another pipeline using the same dynamic states.
8749 
8750 								if (useExtraPipeline && (kOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC || kOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
8751 									continue;
8752 
8753 								if (useExtraPipeline && kUseMeshShaders)
8754 									continue;
8755 
8756 								const bool depthFail		= (subCaseIdx > 0);				// depthFail would be the second variant.
8757 								const bool globalPass		= (wouldPass && !depthFail);	// Global result of the stencil+depth test.
8758 
8759 								// Start tuning test parameters.
8760 								TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8761 
8762 								// No face culling is applied by default, so both the front and back operations could apply depending on the mesh.
8763 								if (face.face == vk::VK_STENCIL_FACE_FRONT_BIT)
8764 								{
8765 									// Default parameters are OK.
8766 								}
8767 								else if (face.face == vk::VK_STENCIL_FACE_BACK_BIT)
8768 								{
8769 									// Reverse the mesh so it applies the back operation.
8770 									config.meshParams[0].reversed = true;
8771 								}
8772 								else	// Front and back.
8773 								{
8774 									// Draw both a front and a back-facing mesh so both are applied.
8775 									// The first mesh will be drawn in the top half and the second mesh in the bottom half.
8776 
8777 									// Make the second mesh a reversed copy of the first mesh.
8778 									config.meshParams.push_back(config.meshParams.front());
8779 									config.meshParams.back().reversed = true;
8780 
8781 									// Apply scale and offset to the top mesh.
8782 									config.meshParams.front().scaleY = 0.5f;
8783 									config.meshParams.front().offsetY = -0.5f;
8784 
8785 									// Apply scale and offset to the bottom mesh.
8786 									config.meshParams.back().scaleY = 0.5f;
8787 									config.meshParams.back().offsetY = 0.5f;
8788 								}
8789 
8790 								// Enable the stencil test.
8791 								config.stencilTestEnableConfig.staticValue = true;
8792 
8793 								// Set dynamic configuration.
8794 								StencilOpParams dynamicStencilConfig;
8795 								dynamicStencilConfig.faceMask		= face.face;
8796 								dynamicStencilConfig.compareOp		= compare.compareOp;
8797 								dynamicStencilConfig.failOp			= vk::VK_STENCIL_OP_MAX_ENUM;
8798 								dynamicStencilConfig.passOp			= vk::VK_STENCIL_OP_MAX_ENUM;
8799 								dynamicStencilConfig.depthFailOp	= vk::VK_STENCIL_OP_MAX_ENUM;
8800 
8801 								// Set operations so only the appropriate operation for this case gives the right result.
8802 								vk::VkStencilOp* activeOp		= nullptr;
8803 								vk::VkStencilOp* inactiveOps[2]	= { nullptr, nullptr };
8804 								if (wouldPass)
8805 								{
8806 									if (depthFail)
8807 									{
8808 										activeOp		= &dynamicStencilConfig.depthFailOp;
8809 										inactiveOps[0]	= &dynamicStencilConfig.passOp;
8810 										inactiveOps[1]	= &dynamicStencilConfig.failOp;
8811 									}
8812 									else
8813 									{
8814 										activeOp		= &dynamicStencilConfig.passOp;
8815 										inactiveOps[0]	= &dynamicStencilConfig.depthFailOp;
8816 										inactiveOps[1]	= &dynamicStencilConfig.failOp;
8817 									}
8818 								}
8819 								else
8820 								{
8821 									activeOp		= &dynamicStencilConfig.failOp;
8822 									inactiveOps[0]	= &dynamicStencilConfig.passOp;
8823 									inactiveOps[1]	= &dynamicStencilConfig.depthFailOp;
8824 								}
8825 
8826 								*activeOp = op.stencilOp;
8827 								*inactiveOps[0] = op.incompatibleOp;
8828 								*inactiveOps[1] = op.incompatibleOp;
8829 
8830 								// Make sure all ops have been configured properly.
8831 								DE_ASSERT(dynamicStencilConfig.failOp != vk::VK_STENCIL_OP_MAX_ENUM);
8832 								DE_ASSERT(dynamicStencilConfig.passOp != vk::VK_STENCIL_OP_MAX_ENUM);
8833 								DE_ASSERT(dynamicStencilConfig.depthFailOp != vk::VK_STENCIL_OP_MAX_ENUM);
8834 
8835 								// Set an incompatible static operation too.
8836 								auto& staticStencilConfig		= config.stencilOpConfig.staticValue.front();
8837 								staticStencilConfig.faceMask	= face.face;
8838 								staticStencilConfig.compareOp	= (globalPass ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
8839 								staticStencilConfig.passOp		= op.incompatibleOp;
8840 								staticStencilConfig.failOp		= op.incompatibleOp;
8841 								staticStencilConfig.depthFailOp	= op.incompatibleOp;
8842 
8843 								// Set dynamic configuration.
8844 								StencilOpVec stencilOps;
8845 								stencilOps.push_back(dynamicStencilConfig);
8846 
8847 								if (stencilOps.front().faceMask == vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM)
8848 								{
8849 									// This is the dual case. We will set the front and back face values with two separate calls.
8850 									stencilOps.push_back(stencilOps.front());
8851 									stencilOps.front().faceMask		= vk::VK_STENCIL_FACE_FRONT_BIT;
8852 									stencilOps.back().faceMask		= vk::VK_STENCIL_FACE_BACK_BIT;
8853 									staticStencilConfig.faceMask	= vk::VK_STENCIL_FACE_FRONT_AND_BACK;
8854 								}
8855 
8856 								config.stencilOpConfig.dynamicValue	= tcu::just(stencilOps);
8857 								config.clearStencilValue			= clearVal;
8858 								config.referenceStencil				= refValU32;
8859 
8860 								if (depthFail)
8861 								{
8862 									// Enable depth test and make it fail.
8863 									config.depthTestEnableConfig.staticValue	= true;
8864 									config.clearDepthValue						= 0.5f;
8865 									config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
8866 
8867 									for (auto& meshPar : config.meshParams)
8868 										meshPar.depth = 0.75f;
8869 								}
8870 
8871 								// Set expected outcome.
8872 								config.referenceColor.reset	(new SingleColorGenerator(globalPass ? kDefaultTriangleColor : kDefaultClearColor));
8873 								config.expectedDepth		= config.clearDepthValue; // No depth writing by default.
8874 								config.expectedStencil		= stencilResult(op.stencilOp, clearVal, refValU8, kMinVal, kMaxVal);
8875 
8876 								config.useExtraDynPipeline	= useExtraPipeline;
8877 
8878 								const std::string testName = std::string("stencil_state")
8879 									+ ((useExtraPipeline) ? "_extra_pipeline" : "")
8880 									+ "_" + face.name
8881 									+ "_" + compare.name
8882 									+ "_" + op.name
8883 									+ "_clear_" + de::toString(static_cast<int>(clearVal))
8884 									+ "_ref_" + de::toString(refVal)
8885 									+ "_" + (wouldPass ? (depthFail ? "depthfail" : "pass") : "fail");
8886 
8887 								// Dynamically configure stencil test
8888 								orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8889 							}
8890 						}
8891 					}
8892 				}
8893 			}
8894 		}
8895 
8896 		// Vertex input.
8897 		if (!kUseMeshShaders)
8898 		{
8899 			for (const auto& bindUnusedCase : kBindUnusedCases)
8900 			{
8901 				if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
8902 					continue;
8903 
8904 				// TWO_DRAWS_STATIC would be invalid because it violates VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the
8905 				// dynamic stride being less than the extent of the binding for the second attribute.
8906 				if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
8907 				{
8908 					{
8909 						const auto	staticGen	= getVertexWithPaddingGenerator();
8910 						const auto	dynamicGen	= getVertexWithExtraAttributesGenerator();
8911 						const auto	goodStrides	= dynamicGen->getVertexDataStrides();
8912 						StrideVec	badStrides;
8913 
8914 						badStrides.reserve(goodStrides.size());
8915 						for (const auto& stride : goodStrides)
8916 							badStrides.push_back(stride / 2u);
8917 
8918 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, staticGen, dynamicGen);
8919 						config.strideConfig.staticValue			= badStrides;
8920 						config.strideConfig.dynamicValue		= goodStrides;
8921 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
8922 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input" + bindUnusedCase.nameSuffix, config));
8923 					}
8924 					{
8925 						const auto	staticGen	= getVertexWithInstanceDataGenerator();
8926 						const auto	goodStrides	= staticGen->getVertexDataStrides();
8927 						StrideVec	badStrides;
8928 
8929 						DE_ASSERT(goodStrides.size() == 2u);
8930 						badStrides.reserve(2u);
8931 						badStrides.push_back(goodStrides.at(0u));
8932 						badStrides.push_back(goodStrides.at(1u) / 2u); // Halve instance rate stride.
8933 
8934 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, staticGen);
8935 						config.strideConfig.staticValue			= badStrides;
8936 						config.strideConfig.dynamicValue		= goodStrides;
8937 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
8938 						config.instanceCount					= 2u;
8939 						// Dynamically set instance rate stride
8940 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "instance_rate_stride" + bindUnusedCase.nameSuffix, config));
8941 					}
8942 				}
8943 
8944 				{
8945 					// Variant without mixing in the stride config.
8946 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithPaddingGenerator(), getVertexWithExtraAttributesGenerator());
8947 					config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
8948 					// Dynamically set vertex input without using dynamic strides
8949 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_no_dyn_stride" + bindUnusedCase.nameSuffix, config));
8950 				}
8951 
8952 				{
8953 					// Variant using multiple bindings.
8954 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithExtraAttributesGenerator(), getVertexWithMultipleBindingsGenerator());
8955 					config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
8956 					// Dynamically set vertex input with multiple bindings
8957 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_multiple_bindings" + bindUnusedCase.nameSuffix, config));
8958 				}
8959 
8960 				{
8961 					// Variant checking dynamic vertex inputs with 16-bit floats.
8962 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithPaddingGenerator(), getVertexWithPadding16Generator());
8963 					config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
8964 					// Dynamically set vertex input with float16 inputs
8965 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_float16" + bindUnusedCase.nameSuffix, config));
8966 				}
8967 			}
8968 		}
8969 
8970 		// Null state pointers.
8971 		{
8972 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
8973 			baseConfig.favorStaticNullPointers = true;
8974 
8975 			if (!kUseMeshShaders)
8976 			{
8977 				TestConfig config(pipelineConstructionType, kOrdering, false, getVertexWithPaddingGenerator(), getVertexWithExtraAttributesGenerator());
8978 				config.favorStaticNullPointers = true;
8979 				// Use null pVertexInputState
8980 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_vertex_input_state", config));
8981 			}
8982 
8983 			if (!kUseMeshShaders)
8984 			{
8985 				TestConfig config(baseConfig);
8986 				config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
8987 				config.topologyConfig.dynamicValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
8988 				config.extraLineRestarts					= true;
8989 				config.primRestartEnableConfig.staticValue	= false;
8990 				config.primRestartEnableConfig.dynamicValue	= tcu::just(true);
8991 				config.referenceColor.reset					(new CenterStripGenerator(kDefaultTriangleColor, kDefaultClearColor));
8992 				// Use null pVertexInputState
8993 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_input_assembly_state", config));
8994 			}
8995 
8996 			if (!kUseMeshShaders)
8997 			{
8998 				TestConfig config(baseConfig);
8999 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
9000 				config.patchControlPointsConfig.staticValue = 1;
9001 				config.patchControlPointsConfig.dynamicValue = 3;
9002 				// Use null pTessellationState
9003 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_tessellation_state", config));
9004 			}
9005 
9006 			{
9007 				TestConfig config(baseConfig);
9008 
9009 				config.viewportConfig.staticValue	= ViewportVec{
9010 					vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),	// Right.
9011 					vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),		// Left.
9012 				};
9013 
9014 				config.scissorConfig.staticValue	= ScissorVec{
9015 					vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
9016 					vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
9017 				};
9018 
9019 				config.scissorConfig.dynamicValue	= ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
9020 				config.viewportConfig.dynamicValue	= ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
9021 
9022 				// Use null pViewportState
9023 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_viewport_state", config));
9024 			}
9025 
9026 			{
9027 				TestConfig config(baseConfig);
9028 				config.depthClampEnableConfig.staticValue		= true;
9029 				config.depthClampEnableConfig.dynamicValue		= false;
9030 				config.rastDiscardEnableConfig.staticValue		= true;
9031 				config.rastDiscardEnableConfig.dynamicValue		= false;
9032 				config.polygonModeConfig.staticValue			= vk::VK_POLYGON_MODE_POINT;
9033 				config.polygonModeConfig.dynamicValue			= vk::VK_POLYGON_MODE_FILL;
9034 				config.cullModeConfig.staticValue				= vk::VK_CULL_MODE_FRONT_AND_BACK;
9035 				config.cullModeConfig.dynamicValue				= vk::VK_CULL_MODE_NONE;
9036 				config.frontFaceConfig.staticValue				= vk::VK_FRONT_FACE_CLOCKWISE;
9037 				config.frontFaceConfig.dynamicValue				= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
9038 				config.depthBiasEnableConfig.staticValue		= true;
9039 				config.depthBiasEnableConfig.dynamicValue		= false;
9040 				config.depthBiasConfig.staticValue				= DepthBiasParams{1.0f, 1.0f};
9041 				config.depthBiasConfig.dynamicValue				= kNoDepthBiasParams;
9042 				config.lineWidthConfig.staticValue				= 0.0f;
9043 				config.lineWidthConfig.dynamicValue				= 1.0f;
9044 				// Use null pRasterizationState
9045 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_rasterization_state", config));
9046 			}
9047 
9048 			{
9049 				TestConfig config(baseConfig);
9050 				config.rasterizationSamplesConfig.staticValue	= kMultiSampleCount;
9051 				config.rasterizationSamplesConfig.dynamicValue	= kSingleSampleCount;
9052 				config.sampleMaskConfig.staticValue				= SampleMaskVec(1u, 0u);
9053 				config.sampleMaskConfig.dynamicValue			= SampleMaskVec(1u, 0xFFu);
9054 				config.alphaToCoverageConfig.staticValue		= true;
9055 				config.alphaToCoverageConfig.dynamicValue		= false;
9056 				config.alphaToOneConfig.staticValue				= true;
9057 				config.alphaToOneConfig.dynamicValue			= false;
9058 				// Use null pMultisampleState
9059 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_multisample_state", config));
9060 			}
9061 
9062 			{
9063 				TestConfig config(baseConfig);
9064 				config.depthTestEnableConfig.staticValue		= true;
9065 				config.depthTestEnableConfig.dynamicValue		= false;
9066 				config.depthWriteEnableConfig.staticValue		= true;
9067 				config.depthWriteEnableConfig.dynamicValue		= false;
9068 				config.depthCompareOpConfig.staticValue			= vk::VK_COMPARE_OP_NEVER;
9069 				config.depthCompareOpConfig.dynamicValue		= vk::VK_COMPARE_OP_ALWAYS;
9070 				config.depthBoundsTestEnableConfig.staticValue	= true;
9071 				config.depthBoundsTestEnableConfig.dynamicValue	= false;
9072 				config.stencilTestEnableConfig.staticValue		= true;
9073 				config.stencilTestEnableConfig.dynamicValue		= false;
9074 				config.stencilOpConfig.staticValue				= StencilOpVec(1u, StencilOpParams{vk::VK_STENCIL_FACE_FRONT_AND_BACK, vk::VK_STENCIL_OP_INVERT, vk::VK_STENCIL_OP_INVERT, vk::VK_STENCIL_OP_INVERT, vk::VK_COMPARE_OP_NEVER});
9075 				config.stencilOpConfig.dynamicValue				= StencilOpVec(1u, StencilOpParams{vk::VK_STENCIL_FACE_FRONT_AND_BACK, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS});
9076 				config.depthBoundsConfig.staticValue			= std::make_pair(1.0f, 1.0f);
9077 				config.depthBoundsConfig.dynamicValue			= std::make_pair(0.0f, 0.0f);
9078 				// Use null pDepthStencilState
9079 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_depth_stencil_state", config));
9080 			}
9081 
9082 			{
9083 				TestConfig config(baseConfig);
9084 				config.forceUnormColorFormat					= true;
9085 				config.logicOpEnableConfig.staticValue			= true;
9086 				config.logicOpEnableConfig.dynamicValue			= false;
9087 				config.logicOpConfig.staticValue				= vk::VK_LOGIC_OP_CLEAR;
9088 				config.logicOpConfig.dynamicValue				= vk::VK_LOGIC_OP_COPY;
9089 				config.colorBlendEnableConfig.staticValue		= true;
9090 				config.colorBlendEnableConfig.dynamicValue		= false;
9091 				config.colorBlendEquationConfig.staticValue		= ColorBlendEq();
9092 				config.colorBlendEquationConfig.dynamicValue	= ColorBlendEq(vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
9093 				config.colorWriteMaskConfig.staticValue			= 0u;
9094 				config.colorWriteMaskConfig.dynamicValue		= (CR | CG | CB | CA);
9095 				config.blendConstantsConfig.staticValue			= BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
9096 				config.blendConstantsConfig.dynamicValue		= BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
9097 				// Use null pColorBlendState
9098 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_color_blend_state", config));
9099 			}
9100 		}
9101 
9102 		{
9103 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9104 			config.sampleShadingEnable						= true;
9105 			config.minSampleShading							= 1.0f;
9106 			config.forceAtomicCounters						= true;
9107 			config.oversizedTriangle						= true;
9108 			config.rasterizationSamplesConfig.staticValue	= kSingleSampleCount;
9109 			config.rasterizationSamplesConfig.dynamicValue	= kMultiSampleCount;
9110 			// Test number of frag shader invocations with sample shading enabled and dynamic sample counts
9111 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_shading_sample_count", config));
9112 		}
9113 
9114 		tcu::TestCaseGroup* group = (kUseMeshShaders ? meshShaderGroup.get() : extendedDynamicStateGroup.get());
9115 		group->addChild(orderingGroup.release());
9116 	}
9117 
9118 	extendedDynamicStateGroup->addChild(meshShaderGroup.release());
9119 	extendedDynamicStateGroup->addChild(createExtendedDynamicStateMiscTests(testCtx, pipelineConstructionType));
9120 	return extendedDynamicStateGroup.release();
9121 }
9122 
9123 } // pipeline
9124 } // vkt
9125