• 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 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*
21  * \file
22  * \brief Extended dynamic state tests
23 *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineExtendedDynamicStateTests.hpp"
26 #include "vktPipelineImageUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 
41 #include "tcuVector.hpp"
42 #include "tcuMaybe.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuVectorUtil.hpp"
45 #include "tcuStringTemplate.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuCommandLine.hpp"
48 
49 #include "deUniquePtr.hpp"
50 #include "deStringUtil.hpp"
51 
52 #include <vector>
53 #include <sstream>
54 #include <algorithm>
55 #include <utility>
56 #include <iterator>
57 #include <string>
58 #include <limits>
59 #include <memory>
60 #include <functional>
61 #include <cstddef>
62 #include <set>
63 
64 namespace vkt
65 {
66 namespace pipeline
67 {
68 
69 namespace
70 {
71 
makeVkBool32(bool value)72 inline vk::VkBool32 makeVkBool32(bool value)
73 {
74 	return (value ? VK_TRUE : VK_FALSE);
75 }
76 
77 #ifndef CTS_USES_VULKANSC
makeProvokingVertexMode(bool lastVertex)78 vk::VkProvokingVertexModeEXT makeProvokingVertexMode (bool lastVertex)
79 {
80 	return (lastVertex ? vk::VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT : vk::VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
81 }
82 #endif // CTS_USES_VULKANSC
83 
84 // Framebuffer size.
85 constexpr deUint32	kFramebufferWidth	= 64u;
86 constexpr deUint32	kFramebufferHeight	= 64u;
87 const auto			kFramebufferExtent	= vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u);
88 
89 // Image formats.
90 constexpr	vk::VkFormat	kUnormColorFormat		= vk::VK_FORMAT_R8G8B8A8_UNORM;
91 constexpr	vk::VkFormat	kIntColorFormat			= vk::VK_FORMAT_R8G8B8A8_UINT;
92 constexpr	vk::VkFormat	kIntRedColorFormat		= vk::VK_FORMAT_R32_UINT;
93 const		tcu::Vec4		kUnormColorThreshold	(0.005f); // 1/255 < 0.005 < 2/255.
94 
95 // This sample count must be supported for all formats supporting VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT.
96 // See 44.1.1. Supported Sample Counts.
97 const auto kMultiSampleCount	= vk::VK_SAMPLE_COUNT_4_BIT;
98 const auto kSingleSampleCount	= vk::VK_SAMPLE_COUNT_1_BIT;
99 
100 // Image usage flags.
101 const vk::VkImageUsageFlags kColorUsage	= (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
102 const vk::VkImageUsageFlags kDSUsage	= (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
103 
104 // Color components.
105 const auto CR = vk::VK_COLOR_COMPONENT_R_BIT;
106 const auto CG = vk::VK_COLOR_COMPONENT_G_BIT;
107 const auto CB = vk::VK_COLOR_COMPONENT_B_BIT;
108 const auto CA = vk::VK_COLOR_COMPONENT_A_BIT;
109 
componentCodes(vk::VkColorComponentFlags components)110 std::string componentCodes (vk::VkColorComponentFlags components)
111 {
112 	std::string name;
113 
114 	if ((components & CR) != 0u) name += "r";
115 	if ((components & CG) != 0u) name += "g";
116 	if ((components & CB) != 0u) name += "b";
117 	if ((components & CA) != 0u) name += "a";
118 
119 	if (name.empty())
120 		name = "0";
121 	return name;
122 }
123 
124 // Chooses clear or geometry color depending on the selected components.
filterColor(const tcu::Vec4 & clearColor,const tcu::Vec4 & color,vk::VkColorComponentFlags components)125 tcu::Vec4 filterColor (const tcu::Vec4& clearColor, const tcu::Vec4& color, vk::VkColorComponentFlags components)
126 {
127 	const tcu::Vec4 finalColor
128 	(
129 		(((components & CR) != 0u) ? color[0] : clearColor[0]),
130 		(((components & CG) != 0u) ? color[1] : clearColor[1]),
131 		(((components & CB) != 0u) ? color[2] : clearColor[2]),
132 		(((components & CA) != 0u) ? color[3] : clearColor[3])
133 	);
134 	return finalColor;
135 }
136 
137 struct DepthStencilFormat
138 {
139 	vk::VkFormat	imageFormat;
140 	float			depthThreshold;
141 };
142 
143 const DepthStencilFormat kDepthStencilFormats[] =
144 {
145 	{ vk::VK_FORMAT_D32_SFLOAT_S8_UINT,	0.0f		},
146 	{ vk::VK_FORMAT_D24_UNORM_S8_UINT,	1.0e-07f	},	// 1/(2**24-1) < 1.0e-07f < 2/(2**24-1)
147 };
148 
149 using StrideVec = std::vector<vk::VkDeviceSize>;
150 
151 // We will use several data types in vertex bindings. Each type will need to define a few things.
152 class VertexGenerator
153 {
154 public:
155 	// For GLSL.
156 
157 	// Vertex input/output attribute declarations in GLSL form. One sentence per element.
158 	virtual std::vector<std::string>								getAttributeDeclarations()	const = 0;
159 
160 	// Get statements to calculate a vec2 called "vertexCoords" using the vertex input attributes.
161 	virtual std::vector<std::string>								getVertexCoordCalc()		const = 0;
162 
163 	// Get vertex binding declarations as part of descriptor sets, used for mesh shading.
164 	virtual std::vector<std::string>								getDescriptorDeclarations()	const = 0;
165 
166 	// Get statements  to calculate a vec2 called "vertexCoords" using descriptor members.
167 	virtual std::vector<std::string>								getDescriptorCoordCalc()	const = 0;
168 
169 	// Get fragment input attribute declarations in GLSL form. One sentence per element.
getFragInputAttributes() const170 	virtual std::vector<std::string>								getFragInputAttributes()	const { return std::vector<std::string>(); }
171 
172 	// Get fragment output post-calculations, maybe altering the "color" output variable.
getFragOutputCalc() const173 	virtual std::vector<std::string>								getFragOutputCalc()			const { return std::vector<std::string>(); }
174 
175 
176 	// For the pipeline.
177 
178 	// Vertex attributes for VkPipelineVertexInputStateCreateInfo.
179 	virtual std::vector<vk::VkVertexInputAttributeDescription>		getAttributeDescriptions() const = 0;
180 
181 	// Vertex attributes for VK_EXT_vertex_input_dynamic_state.
182 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT>	getAttributeDescriptions2()	const = 0;
183 
184 	// Vertex bindings for VkPipelineVertexInputStateCreateInfo.
185 	virtual std::vector<vk::VkVertexInputBindingDescription>		getBindingDescriptions (const StrideVec& strides) const = 0;
186 
187 	// Vertex bindings for VK_EXT_vertex_input_dynamic_state.
188 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT>	getBindingDescriptions2 (const StrideVec& strides) const = 0;
189 
190 	// Create buffer data given an array of coordinates and an initial padding.
191 	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;
192 
193 	// Stride of vertex data in each binding.
194 	virtual std::vector<vk::VkDeviceSize>							getVertexDataStrides() const = 0;
195 };
196 
197 // Auxiliar function to create these structs more easily.
makeVertexInputAttributeDescription2EXT(deUint32 location,deUint32 binding,vk::VkFormat format,deUint32 offset)198 vk::VkVertexInputAttributeDescription2EXT makeVertexInputAttributeDescription2EXT (deUint32 location, deUint32 binding, vk::VkFormat format, deUint32 offset)
199 {
200 	vk::VkVertexInputAttributeDescription2EXT desc = vk::initVulkanStructure();
201 	desc.location = location;
202 	desc.binding = binding;
203 	desc.format = format;
204 	desc.offset = offset;
205 	return desc;
206 }
207 
makeVertexInputBindingDescription2EXT(deUint32 binding,deUint32 stride,vk::VkVertexInputRate inputRate)208 vk::VkVertexInputBindingDescription2EXT makeVertexInputBindingDescription2EXT (deUint32 binding, deUint32 stride, vk::VkVertexInputRate inputRate)
209 {
210 	vk::VkVertexInputBindingDescription2EXT desc = vk::initVulkanStructure();
211 	desc.binding = binding;
212 	desc.stride = stride;
213 	desc.inputRate = inputRate;
214 	desc.divisor = 1u;
215 	return desc;
216 }
217 
218 // 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)219 void fillWithPattern(void* ptr_, size_t offset, size_t count, const void* src, size_t srcSize)
220 {
221 	auto	ptr		= reinterpret_cast<char*>(ptr_);
222 	size_t	done	= 0u;
223 	size_t	pending	= count;
224 
225 	while (pending > 0u)
226 	{
227 		const size_t stepSize = de::min(srcSize, pending);
228 		deMemcpy(ptr + offset + done, src, stepSize);
229 		done += stepSize;
230 		pending -= stepSize;
231 	}
232 }
233 
234 // Create a single binding vertex data vector given a type T for vertex data.
235 template<class T>
createSingleBindingVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize)236 std::vector<deUint8> createSingleBindingVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize)
237 {
238 	DE_ASSERT(!coords.empty());
239 
240 	const auto dataOffsetSz			= static_cast<size_t>(dataOffset);
241 	const auto trailingPaddingSz	= static_cast<size_t>(trailingPadding);
242 
243 	std::vector<deUint8> buffer;
244 	buffer.resize(dataOffsetSz + coords.size() * sizeof(T) + trailingPaddingSz);
245 
246 	fillWithPattern(buffer.data(), 0u, dataOffsetSz, paddingPattern, patternSize);
247 
248 	auto pos = dataOffsetSz;
249 	for (const auto& coord : coords)
250 	{
251 		new (&buffer[pos]) T(coord);
252 		pos += sizeof(T);
253 	}
254 
255 	fillWithPattern(buffer.data(), pos, trailingPaddingSz, paddingPattern, patternSize);
256 
257 	return buffer;
258 }
259 
260 // Vertices in buffers will have 2 components and a padding to properly test the stride.
261 // This is the vertex type that will be used normally.
262 class VertexWithPadding : public VertexGenerator
263 {
264 protected:
265 	struct VertexData
266 	{
VertexDatavkt::pipeline::__anonaa66a09e0111::VertexWithPadding::VertexData267 		VertexData(const tcu::Vec2& coords_)
268 			: coords	(coords_)
269 			, padding	(0.0f, 0.0f)
270 		{}
271 
272 		tcu::Vec2 coords;
273 		tcu::Vec2 padding;
274 	};
275 
276 public:
getAttributeDeclarations() const277 	virtual std::vector<std::string> getAttributeDeclarations() const override
278 	{
279 		std::vector<std::string> declarations;
280 		declarations.push_back("layout(location=0) in vec2 position;");
281 		return declarations;
282 	}
283 
getVertexCoordCalc() const284 	virtual std::vector<std::string> getVertexCoordCalc() const override
285 	{
286 		std::vector<std::string> statements;
287 		statements.push_back("vec2 vertexCoords = position;");
288 		return statements;
289 	}
290 
getDescriptorDeclarations() const291 	virtual std::vector<std::string> getDescriptorDeclarations() const override
292 	{
293 		std::vector<std::string> declarations;
294 		declarations.reserve(7u);
295 		declarations.push_back("struct VertexData {");
296 		declarations.push_back("    vec2 position;");
297 		declarations.push_back("    vec2 padding;");
298 		declarations.push_back("};");
299 		declarations.push_back("layout(set=0, binding=0, std430) readonly buffer S0B0Block {");
300 		declarations.push_back("    VertexData data[];");
301 		declarations.push_back("} s0b0buffer;");
302 		return declarations;
303 	}
304 
getDescriptorCoordCalc() const305 	virtual std::vector<std::string> getDescriptorCoordCalc() const override
306 	{
307 		std::vector<std::string> statements;
308 		statements.reserve(4u);
309 		statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
310 		statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
311 		statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
312 		statements.push_back("vec2 vertexCoords = s0b0buffer.data[invIndex].position;");
313 		return statements;
314 	}
315 
getAttributeDescriptions() const316 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
317 	{
318 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
319 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
320 		return descriptions;
321 	}
322 
323 	// Vertex attributes for VK_EXT_vertex_input_dynamic_state.
getAttributeDescriptions2() const324 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
325 	{
326 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
327 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
328 		return descriptions;
329 	}
330 
331 	// Vertex bindings for VkPipelineVertexInputStateCreateInfo.
getBindingDescriptions(const StrideVec & strides) const332 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
333 	{
334 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
335 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
336 		return descriptions;
337 	}
338 
339 	// Vertex bindings for VK_EXT_vertex_input_dynamic_state.
getBindingDescriptions2(const StrideVec & strides) const340 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
341 	{
342 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
343 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
344 		return descriptions;
345 	}
346 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const347 	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
348 	{
349 		return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
350 	}
351 
getVertexDataStrides() const352 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
353 	{
354 		return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
355 	}
356 };
357 
358 // Vertex generator used when testing provoking vertices. It has an extra flat vertex output that's also a frag input. Note this
359 // generator only works with 3 vertices.
360 class ProvokingVertexWithPadding : public VertexWithPadding
361 {
362 protected:
363 	bool m_lastVertex;
364 
365 public:
ProvokingVertexWithPadding(bool lastVertex)366 	ProvokingVertexWithPadding (bool lastVertex)
367 		: m_lastVertex (lastVertex)
368 	{}
369 
getAttributeDeclarations() const370 	virtual std::vector<std::string> getAttributeDeclarations() const override
371 	{
372 		auto declarations = VertexWithPadding::getAttributeDeclarations();
373 		declarations.push_back("layout(location=0) flat out uint colorMultiplier;");
374 		return declarations;
375 	}
376 
getDescriptorDeclarations() const377 	virtual std::vector<std::string> getDescriptorDeclarations() const override
378 	{
379 		auto declarations = VertexWithPadding::getDescriptorDeclarations();
380 		declarations.push_back("layout(location=0) flat out uint colorMultiplier[];");
381 		return declarations;
382 	}
383 
getVertexCoordCalc() const384 	virtual std::vector<std::string> getVertexCoordCalc() const override
385 	{
386 		auto statements = VertexWithPadding::getVertexCoordCalc();
387 		statements.push_back("const bool provokingLast = " + std::string(m_lastVertex ? "true" : "false") + ";");
388 		statements.push_back("colorMultiplier = (((!provokingLast && gl_VertexIndex == 0) || (provokingLast && gl_VertexIndex == 2)) ? 1 : 0);");
389 		return statements;
390 	}
391 
getDescriptorCoordCalc() const392 	virtual std::vector<std::string> getDescriptorCoordCalc() const override
393 	{
394 		auto statements = VertexWithPadding::getDescriptorCoordCalc();
395 		statements.push_back("const bool provokingLast = " + std::string(m_lastVertex ? "true" : "false") + ";");
396 		statements.push_back("colorMultiplier[gl_LocalInvocationIndex] = (((!provokingLast && gl_LocalInvocationIndex == 0) || (provokingLast && gl_LocalInvocationIndex == 2)) ? 1 : 0);");
397 		return statements;
398 	}
399 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const400 	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
401 	{
402 		static constexpr uint32_t kExpectecdCoordCount = 3u;
403 		DE_UNREF(kExpectecdCoordCount); // For release builds.
404 		DE_ASSERT(coords.size() == kExpectecdCoordCount);
405 		return VertexWithPadding::createVertexData(coords, dataOffset, trailingPadding, paddingPattern, patternSize);
406 	}
407 
getFragInputAttributes() const408 	virtual std::vector<std::string> getFragInputAttributes() const override
409 	{
410 		std::vector<std::string> declarations;
411 		declarations.push_back("layout(location=0) flat in uint colorMultiplier;");
412 		return declarations;
413 	}
414 
getFragOutputCalc() const415 	virtual std::vector<std::string> getFragOutputCalc() const override
416 	{
417 		std::vector<std::string> statements;
418 		statements.push_back("color = color * float(colorMultiplier);");
419 		return statements;
420 	}
421 };
422 
423 // Vertices with coordinates, padding and an extra constant field.
424 class VertexWithExtraAttributes : public VertexGenerator
425 {
426 protected:
427 	struct VertexData
428 	{
VertexDatavkt::pipeline::__anonaa66a09e0111::VertexWithExtraAttributes::VertexData429 		VertexData (const tcu::Vec2& coords_)
430 			: coords	(coords_)
431 			, ones		(1.0f, 1.0f)
432 		{
433 			deMemset(padding, 0, sizeof(padding));
434 		}
435 
436 		tcu::Vec2 coords;
437 		tcu::Vec2 padding[10];
438 		tcu::Vec2 ones;
439 	};
440 
441 public:
getAttributeDeclarations() const442 	virtual std::vector<std::string> getAttributeDeclarations() const override
443 	{
444 		std::vector<std::string> declarations;
445 		declarations.reserve(2u);
446 		declarations.push_back("layout(location=0) in vec2 position;");
447 		declarations.push_back("layout(location=1) in vec2 ones;");
448 		return declarations;
449 	}
450 
getVertexCoordCalc() const451 	virtual std::vector<std::string> getVertexCoordCalc() const override
452 	{
453 		std::vector<std::string> statements;
454 		statements.reserve(2u);
455 		statements.push_back("vec2 vertexCoords = position;");
456 		statements.push_back("vertexCoords = vertexCoords * ones;");
457 		return statements;
458 	}
459 
getDescriptorDeclarations() const460 	virtual std::vector<std::string> getDescriptorDeclarations() const override
461 	{
462 		std::vector<std::string> declarations;
463 		declarations.reserve(8u);
464 		declarations.push_back("struct VertexData {");
465 		declarations.push_back("    vec2 coords;");
466 		declarations.push_back("    vec2 padding[10];");
467 		declarations.push_back("    vec2 ones;");
468 		declarations.push_back("};");
469 		declarations.push_back("layout(set=0, binding=0, std430) readonly buffer S0B0Block {");
470 		declarations.push_back("    VertexData data[];");
471 		declarations.push_back("} s0b0buffer;");
472 		return declarations;
473 	}
474 
getDescriptorCoordCalc() const475 	virtual std::vector<std::string> getDescriptorCoordCalc() const override
476 	{
477 		std::vector<std::string> statements;
478 		statements.reserve(6u);
479 		statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
480 		statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
481 		statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
482 		statements.push_back("vec2 auxPos = s0b0buffer.data[invIndex].coords;");
483 		statements.push_back("vec2 auxOnes = s0b0buffer.data[invIndex].ones;");
484 		statements.push_back("vec2 vertexCoords = auxPos * auxOnes;");
485 		return statements;
486 	}
487 
getAttributeDescriptions() const488 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
489 	{
490 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
491 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
492 		descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(VertexData, ones))));
493 		return descriptions;
494 	}
495 
getAttributeDescriptions2() const496 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
497 	{
498 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
499 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
500 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(VertexData, ones))));
501 		return descriptions;
502 	}
503 
getBindingDescriptions(const StrideVec & strides) const504 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
505 	{
506 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
507 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
508 		return descriptions;
509 	}
510 
getBindingDescriptions2(const StrideVec & strides) const511 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
512 	{
513 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
514 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
515 		return descriptions;
516 	}
517 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const518 	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
519 	{
520 		return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
521 	}
522 
getVertexDataStrides() const523 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
524 	{
525 		return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
526 	}
527 };
528 
529 // Vertices using multiple bindings and constant fields.
530 // Binding 0: no data actually used.
531 // Binding 1: contains location 0, array of PaddingOnes.
532 // Binding 2: no data actually used.
533 // Binding 3: contains location 1, array of CoordsData.
534 // Binding 4: no data actually used.
535 // Binding 5: contains location 2, array of OneZeroPadding.
536 // See getAttributeDeclarations().
537 class MultipleBindingsVertex : public VertexGenerator
538 {
539 protected:
540 	struct CoordsData
541 	{
542 		tcu::Vec2 padding0;
543 		tcu::Vec2 coords;
544 		tcu::Vec2 padding1;
545 
CoordsDatavkt::pipeline::__anonaa66a09e0111::MultipleBindingsVertex::CoordsData546 		CoordsData (const tcu::Vec2& coords_)
547 			: padding0	(0.0f, 3.0f)
548 			, coords	(coords_)
549 			, padding1	(3.0f, 0.0f)
550 		{}
551 	};
552 
553 	struct PaddingOnes
554 	{
555 		tcu::Vec2 padding[4];
556 		tcu::Vec2 ones;
557 
PaddingOnesvkt::pipeline::__anonaa66a09e0111::MultipleBindingsVertex::PaddingOnes558 		PaddingOnes (const tcu::Vec2&)
559 			: ones	(1.0f, 1.0f)
560 		{
561 			deMemset(&padding, 0, sizeof(padding));
562 		}
563 	};
564 
565 	struct OneZeroPadding
566 	{
567 		tcu::Vec4 oneZero;
568 		tcu::Vec2 padding[3];
569 
OneZeroPaddingvkt::pipeline::__anonaa66a09e0111::MultipleBindingsVertex::OneZeroPadding570 		OneZeroPadding (const tcu::Vec2&)
571 			: oneZero	(1.0f, 1.0f, 0.0f, 0.0f)
572 		{
573 			deMemset(&padding, 0, sizeof(padding));
574 		}
575 	};
576 
577 	struct Zeros
578 	{
579 		tcu::Vec2 zeros;
580 
Zerosvkt::pipeline::__anonaa66a09e0111::MultipleBindingsVertex::Zeros581 		Zeros (const tcu::Vec2&)
582 			: zeros	(0.0f, 0.0f)
583 		{}
584 	};
585 
586 public:
getAttributeDeclarations() const587 	virtual std::vector<std::string> getAttributeDeclarations() const override
588 	{
589 		std::vector<std::string> declarations;
590 		declarations.reserve(3u);
591 
592 		declarations.push_back("layout(location=0) in vec2 ones;");
593 		declarations.push_back("layout(location=1) in vec2 position;");
594 		declarations.push_back("layout(location=2) in vec4 oneZero;");
595 
596 		return declarations;
597 	}
598 
getVertexCoordCalc() const599 	virtual std::vector<std::string> getVertexCoordCalc() const override
600 	{
601 		std::vector<std::string> statements;
602 		statements.reserve(2u);
603 
604 		statements.push_back("vec2 vertexCoords = position;");
605 		statements.push_back("vertexCoords = ((vertexCoords * ones) + oneZero.zw) * oneZero.xy;");
606 
607 		return statements;
608 	}
609 
getDescriptorDeclarations() const610 	virtual std::vector<std::string> getDescriptorDeclarations() const override
611 	{
612 		std::vector<std::string> declarations;
613 		declarations.reserve(23u);
614 
615 		declarations.push_back("struct PaddingOnes {");
616 		declarations.push_back("    vec2 padding[4];");
617 		declarations.push_back("    vec2 ones;");
618 		declarations.push_back("};");
619 		declarations.push_back("struct CoordsData {");
620 		declarations.push_back("    vec2 padding0;");
621 		declarations.push_back("    vec2 coords;");
622 		declarations.push_back("    vec2 padding1;");
623 		declarations.push_back("};");
624 		declarations.push_back("struct OneZeroPadding {");
625 		declarations.push_back("    vec2 ones;");		// Note: we split the vec4 into two vec2s to match CPU-side alignment.
626 		declarations.push_back("    vec2 zeros;");
627 		declarations.push_back("    vec2 padding[3];");
628 		declarations.push_back("};");
629 		declarations.push_back("layout(set=0, binding=1, std430) readonly buffer S0B1Block {");
630 		declarations.push_back("    PaddingOnes data[];");
631 		declarations.push_back("} s0b1buffer;");
632 		declarations.push_back("layout(set=0, binding=3, std430) readonly buffer S0B3Block {");
633 		declarations.push_back("    CoordsData data[];");
634 		declarations.push_back("} s0b3buffer;");
635 		declarations.push_back("layout(set=0, binding=4, std430) readonly buffer S0B5Block {");
636 		declarations.push_back("    OneZeroPadding data[];");
637 		declarations.push_back("} s0b5buffer;");
638 
639 		return declarations;
640 	}
641 
getDescriptorCoordCalc() const642 	virtual std::vector<std::string> getDescriptorCoordCalc() const override
643 	{
644 		std::vector<std::string> statements;
645 		statements.reserve(8u);
646 		statements.push_back("uint prim = uint(gl_WorkGroupID.x);");
647 		statements.push_back("uint indices[3] = uint[](prim, (prim + (1 + prim % 2)), (prim + (2 - prim % 2)));");
648 		statements.push_back("uint invIndex = indices[gl_LocalInvocationIndex];");
649 		statements.push_back("vec2 auxOnes1 = s0b1buffer.data[invIndex].ones;");
650 		statements.push_back("vec2 auxCoords = s0b3buffer.data[invIndex].coords;");
651 		statements.push_back("vec2 auxOnes5 = s0b5buffer.data[invIndex].ones;");
652 		statements.push_back("vec2 auxZeros = s0b5buffer.data[invIndex].zeros;");
653 		statements.push_back("vec2 vertexCoords = ((auxCoords * auxOnes1) + auxZeros) * auxOnes5;");
654 		return statements;
655 	}
656 
getAttributeDescriptions() const657 	virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
658 	{
659 		// We create the descriptions vector out of order to make it more interesting. See the attribute declarations.
660 		std::vector<vk::VkVertexInputAttributeDescription> descriptions;
661 		descriptions.reserve(3u);
662 
663 		descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 3u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(CoordsData, coords))));
664 		descriptions.push_back(vk::makeVertexInputAttributeDescription(2u, 5u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(offsetof(OneZeroPadding, oneZero))));
665 		descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(PaddingOnes, ones))));
666 
667 		return descriptions;
668 	}
669 
getAttributeDescriptions2() const670 	virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
671 	{
672 		// We create the descriptions vector out of order to make it more interesting. See the attribute declarations.
673 		std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
674 		descriptions.reserve(3u);
675 
676 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(2u, 5u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(offsetof(OneZeroPadding, oneZero))));
677 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 3u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(CoordsData, coords))));
678 		descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(PaddingOnes, ones))));
679 
680 		return descriptions;
681 	}
682 
getBindingDescriptions(const StrideVec & strides) const683 	virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
684 	{
685 		// Provide descriptions out of order to make it more interesting.
686 		std::vector<vk::VkVertexInputBindingDescription> descriptions;
687 		descriptions.reserve(6u);
688 
689 		descriptions.push_back(vk::makeVertexInputBindingDescription(2u, static_cast<deUint32>(strides.at(2)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
690 		descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
691 		descriptions.push_back(vk::makeVertexInputBindingDescription(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
692 		descriptions.push_back(vk::makeVertexInputBindingDescription(4u, static_cast<deUint32>(strides.at(4)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
693 		descriptions.push_back(vk::makeVertexInputBindingDescription(3u, static_cast<deUint32>(strides.at(3)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
694 		descriptions.push_back(vk::makeVertexInputBindingDescription(5u, static_cast<deUint32>(strides.at(5)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
695 
696 		return descriptions;
697 	}
698 
getBindingDescriptions2(const StrideVec & strides) const699 	virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
700 	{
701 		// Provide descriptions out of order to make it more interesting.
702 		std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
703 		descriptions.reserve(6u);
704 
705 		descriptions.push_back(makeVertexInputBindingDescription2EXT(2u, static_cast<deUint32>(strides.at(2)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
706 		descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
707 		descriptions.push_back(makeVertexInputBindingDescription2EXT(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
708 		descriptions.push_back(makeVertexInputBindingDescription2EXT(5u, static_cast<deUint32>(strides.at(5)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
709 		descriptions.push_back(makeVertexInputBindingDescription2EXT(4u, static_cast<deUint32>(strides.at(4)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
710 		descriptions.push_back(makeVertexInputBindingDescription2EXT(3u, static_cast<deUint32>(strides.at(3)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
711 
712 		return descriptions;
713 	}
714 
createVertexData(const std::vector<tcu::Vec2> & coords,vk::VkDeviceSize dataOffset,vk::VkDeviceSize trailingPadding,const void * paddingPattern,size_t patternSize) const715 	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
716 	{
717 		std::vector<std::vector<deUint8>> result;
718 		result.reserve(6u);
719 
720 		result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));			// Not actually used.
721 		result.push_back(createSingleBindingVertexData<PaddingOnes>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));		// Binding 1 contains location=0 as PaddingOnes.
722 		result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));			// Not actually used.
723 		result.push_back(createSingleBindingVertexData<CoordsData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));		// Binding 3 contains location=1 as CoordsData.
724 		result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));			// Not actually used.
725 		result.push_back(createSingleBindingVertexData<OneZeroPadding>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));	// Binding 5 contains location=2 as OneZeroPadding.
726 
727 		return result;
728 	}
729 
getVertexDataStrides() const730 	virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
731 	{
732 		std::vector<vk::VkDeviceSize> strides;
733 		strides.reserve(6u);
734 
735 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
736 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(PaddingOnes)));
737 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
738 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(CoordsData)));
739 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
740 		strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(OneZeroPadding)));
741 
742 		return strides;
743 	}
744 };
745 
746 // Stencil Operation parameters, as used in vkCmdSetStencilOpEXT().
747 struct StencilOpParams
748 {
749 	vk::VkStencilFaceFlags  faceMask;
750 	vk::VkStencilOp         failOp;
751 	vk::VkStencilOp         passOp;
752 	vk::VkStencilOp         depthFailOp;
753 	vk::VkCompareOp         compareOp;
754 };
755 
756 const StencilOpParams kDefaultStencilOpParams =
757 {
758 	vk::VK_STENCIL_FACE_FRONT_AND_BACK,
759 	vk::VK_STENCIL_OP_KEEP,
760 	vk::VK_STENCIL_OP_KEEP,
761 	vk::VK_STENCIL_OP_KEEP,
762 	vk::VK_COMPARE_OP_ALWAYS
763 };
764 
765 struct DepthBiasParams
766 {
767 	float constantFactor;
768 	float clamp;
769 };
770 
isAdvancedBlendOp(const vk::VkBlendOp blendOp)771 bool isAdvancedBlendOp (const vk::VkBlendOp blendOp)
772 {
773 	bool advanced = false;
774 
775 	switch (blendOp)
776 	{
777 	case vk::VK_BLEND_OP_ZERO_EXT:
778 	case vk::VK_BLEND_OP_SRC_EXT:
779 	case vk::VK_BLEND_OP_DST_EXT:
780 	case vk::VK_BLEND_OP_SRC_OVER_EXT:
781 	case vk::VK_BLEND_OP_DST_OVER_EXT:
782 	case vk::VK_BLEND_OP_SRC_IN_EXT:
783 	case vk::VK_BLEND_OP_DST_IN_EXT:
784 	case vk::VK_BLEND_OP_SRC_OUT_EXT:
785 	case vk::VK_BLEND_OP_DST_OUT_EXT:
786 	case vk::VK_BLEND_OP_SRC_ATOP_EXT:
787 	case vk::VK_BLEND_OP_DST_ATOP_EXT:
788 	case vk::VK_BLEND_OP_XOR_EXT:
789 	case vk::VK_BLEND_OP_MULTIPLY_EXT:
790 	case vk::VK_BLEND_OP_SCREEN_EXT:
791 	case vk::VK_BLEND_OP_OVERLAY_EXT:
792 	case vk::VK_BLEND_OP_DARKEN_EXT:
793 	case vk::VK_BLEND_OP_LIGHTEN_EXT:
794 	case vk::VK_BLEND_OP_COLORDODGE_EXT:
795 	case vk::VK_BLEND_OP_COLORBURN_EXT:
796 	case vk::VK_BLEND_OP_HARDLIGHT_EXT:
797 	case vk::VK_BLEND_OP_SOFTLIGHT_EXT:
798 	case vk::VK_BLEND_OP_DIFFERENCE_EXT:
799 	case vk::VK_BLEND_OP_EXCLUSION_EXT:
800 	case vk::VK_BLEND_OP_INVERT_EXT:
801 	case vk::VK_BLEND_OP_INVERT_RGB_EXT:
802 	case vk::VK_BLEND_OP_LINEARDODGE_EXT:
803 	case vk::VK_BLEND_OP_LINEARBURN_EXT:
804 	case vk::VK_BLEND_OP_VIVIDLIGHT_EXT:
805 	case vk::VK_BLEND_OP_LINEARLIGHT_EXT:
806 	case vk::VK_BLEND_OP_PINLIGHT_EXT:
807 	case vk::VK_BLEND_OP_HARDMIX_EXT:
808 	case vk::VK_BLEND_OP_HSL_HUE_EXT:
809 	case vk::VK_BLEND_OP_HSL_SATURATION_EXT:
810 	case vk::VK_BLEND_OP_HSL_COLOR_EXT:
811 	case vk::VK_BLEND_OP_HSL_LUMINOSITY_EXT:
812 	case vk::VK_BLEND_OP_PLUS_EXT:
813 	case vk::VK_BLEND_OP_PLUS_CLAMPED_EXT:
814 	case vk::VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT:
815 	case vk::VK_BLEND_OP_PLUS_DARKER_EXT:
816 	case vk::VK_BLEND_OP_MINUS_EXT:
817 	case vk::VK_BLEND_OP_MINUS_CLAMPED_EXT:
818 	case vk::VK_BLEND_OP_CONTRAST_EXT:
819 	case vk::VK_BLEND_OP_INVERT_OVG_EXT:
820 	case vk::VK_BLEND_OP_RED_EXT:
821 	case vk::VK_BLEND_OP_GREEN_EXT:
822 	case vk::VK_BLEND_OP_BLUE_EXT:
823 		advanced = true;
824 		break;
825 	default:
826 		advanced = false;
827 		break;
828 	}
829 
830 	return advanced;
831 }
832 
833 struct ColorBlendEq
834 {
835 	vk::VkBlendFactor	srcColorBlendFactor;
836 	vk::VkBlendFactor	dstColorBlendFactor;
837 	vk::VkBlendOp		colorBlendOp;
838 	vk::VkBlendFactor	srcAlphaBlendFactor;
839 	vk::VkBlendFactor	dstAlphaBlendFactor;
840 	vk::VkBlendOp		alphaBlendOp;
841 
ColorBlendEqvkt::pipeline::__anonaa66a09e0111::ColorBlendEq842 	ColorBlendEq ()
843 		: srcColorBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
844 		, dstColorBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
845 		, colorBlendOp			(vk::VK_BLEND_OP_ADD)
846 		, srcAlphaBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
847 		, dstAlphaBlendFactor	(vk::VK_BLEND_FACTOR_ZERO)
848 		, alphaBlendOp			(vk::VK_BLEND_OP_ADD)
849 	{}
850 
ColorBlendEqvkt::pipeline::__anonaa66a09e0111::ColorBlendEq851 	ColorBlendEq (vk::VkBlendFactor	srcColorBlendFactor_,
852 				  vk::VkBlendFactor	dstColorBlendFactor_,
853 				  vk::VkBlendOp		colorBlendOp_,
854 				  vk::VkBlendFactor	srcAlphaBlendFactor_,
855 				  vk::VkBlendFactor	dstAlphaBlendFactor_,
856 				  vk::VkBlendOp		alphaBlendOp_)
857 		: srcColorBlendFactor	(srcColorBlendFactor_)
858 		, dstColorBlendFactor	(dstColorBlendFactor_)
859 		, colorBlendOp			(colorBlendOp_)
860 		, srcAlphaBlendFactor	(srcAlphaBlendFactor_)
861 		, dstAlphaBlendFactor	(dstAlphaBlendFactor_)
862 		, alphaBlendOp			(alphaBlendOp_)
863 	{
864 		if (isAdvancedBlendOp(colorBlendOp))
865 			DE_ASSERT(colorBlendOp == alphaBlendOp);
866 	}
867 
isAdvancedvkt::pipeline::__anonaa66a09e0111::ColorBlendEq868 	bool isAdvanced () const
869 	{
870 		return isAdvancedBlendOp(colorBlendOp);
871 	}
872 };
873 
874 const DepthBiasParams kNoDepthBiasParams = { 0.0f, 0.0f };
875 
876 struct LineStippleParams
877 {
878 	uint32_t factor;
879 	uint16_t pattern;
880 };
881 
882 enum class LineRasterizationMode
883 {
884 	NONE = 0,
885 	RECTANGULAR,
886 	BRESENHAM,
887 	SMOOTH,
888 };
889 
890 using ViewportVec		= std::vector<vk::VkViewport>;
891 using ScissorVec		= std::vector<vk::VkRect2D>;
892 using StencilOpVec		= std::vector<StencilOpParams>;
893 using SampleMaskVec		= std::vector<vk::VkSampleMask>;
894 using OptRastStream		= tcu::Maybe<uint32_t>;
895 using OptBoolean		= tcu::Maybe<bool>;
896 using OptStippleParams	= tcu::Maybe<LineStippleParams>;
897 using OptLineRasterMode	= tcu::Maybe<LineRasterizationMode>;
898 using OptSampleCount	= tcu::Maybe<vk::VkSampleCountFlagBits>;
899 using CovModTableVec	= std::vector<float>;
900 #ifndef CTS_USES_VULKANSC
901 using ViewportSwzVec	= std::vector<vk::VkViewportSwizzleNV>;
902 #endif // CTS_USES_VULKANSC
903 
904 // Generic, to be used with any state than can be set statically and, as an option, dynamically.
905 template<typename T>
906 struct StaticAndDynamicPair
907 {
908 	T				staticValue;
909 	tcu::Maybe<T>	dynamicValue;
910 
911 	// Helper constructor to set a static value and no dynamic value.
StaticAndDynamicPairvkt::pipeline::__anonaa66a09e0111::StaticAndDynamicPair912 	StaticAndDynamicPair (const T& value)
913 		: staticValue	(value)
914 		, dynamicValue	(tcu::Nothing)
915 	{
916 	}
917 
918 	// Helper constructor to set both.
StaticAndDynamicPairvkt::pipeline::__anonaa66a09e0111::StaticAndDynamicPair919 	StaticAndDynamicPair (const T& sVal, const T& dVal)
920 		: staticValue	(sVal)
921 		, dynamicValue	(tcu::just<T>(dVal))
922 	{
923 	}
924 
925 	// If the dynamic value is present, swap static and dynamic values.
swapValuesvkt::pipeline::__anonaa66a09e0111::StaticAndDynamicPair926 	void swapValues (void)
927 	{
928 		if (!dynamicValue)
929 			return;
930 		std::swap(staticValue, dynamicValue.get());
931 	}
932 };
933 
934 // For anything boolean, see below.
935 using BooleanFlagConfig = StaticAndDynamicPair<bool>;
936 
937 // Configuration for every aspect of the extended dynamic state.
938 using CullModeConfig				= StaticAndDynamicPair<vk::VkCullModeFlags>;
939 using FrontFaceConfig				= StaticAndDynamicPair<vk::VkFrontFace>;
940 using TopologyConfig				= StaticAndDynamicPair<vk::VkPrimitiveTopology>;
941 using ViewportConfig				= StaticAndDynamicPair<ViewportVec>;	// At least one element.
942 using ScissorConfig					= StaticAndDynamicPair<ScissorVec>;		// At least one element.
943 using StrideConfig					= StaticAndDynamicPair<StrideVec>;		// At least one element.
944 using DepthTestEnableConfig			= BooleanFlagConfig;
945 using DepthWriteEnableConfig		= BooleanFlagConfig;
946 using DepthCompareOpConfig			= StaticAndDynamicPair<vk::VkCompareOp>;
947 using DepthBoundsTestEnableConfig	= BooleanFlagConfig;
948 using StencilTestEnableConfig		= BooleanFlagConfig;
949 using StencilOpConfig				= StaticAndDynamicPair<StencilOpVec>;	// At least one element.
950 using VertexGeneratorConfig			= StaticAndDynamicPair<const VertexGenerator*>;
951 using DepthBiasEnableConfig			= BooleanFlagConfig;
952 using RastDiscardEnableConfig		= BooleanFlagConfig;
953 using PrimRestartEnableConfig		= BooleanFlagConfig;
954 using LogicOpConfig					= StaticAndDynamicPair<vk::VkLogicOp>;
955 using PatchControlPointsConfig		= StaticAndDynamicPair<deUint8>;
956 using DepthBiasConfig				= StaticAndDynamicPair<DepthBiasParams>;
957 using TessDomainOriginConfig		= StaticAndDynamicPair<vk::VkTessellationDomainOrigin>;
958 using DepthClampEnableConfig		= BooleanFlagConfig;
959 using PolygonModeConfig				= StaticAndDynamicPair<vk::VkPolygonMode>;
960 using SampleMaskConfig				= StaticAndDynamicPair<SampleMaskVec>;
961 using AlphaToCoverageConfig			= BooleanFlagConfig;
962 using AlphaToOneConfig				= BooleanFlagConfig;
963 using ColorWriteMaskConfig			= StaticAndDynamicPair<vk::VkColorComponentFlags>;
964 using RasterizationStreamConfig		= StaticAndDynamicPair<OptRastStream>;
965 using LogicOpEnableConfig			= BooleanFlagConfig;
966 using ColorBlendEnableConfig		= BooleanFlagConfig;
967 using ColorBlendEquationConfig		= StaticAndDynamicPair<ColorBlendEq>;
968 using ProvokingVertexConfig			= StaticAndDynamicPair<OptBoolean>;	// First vertex boolean flag.
969 using NegativeOneToOneConfig		= StaticAndDynamicPair<OptBoolean>;
970 using DepthClipEnableConfig			= StaticAndDynamicPair<OptBoolean>;
971 using LineStippleEnableConfig		= BooleanFlagConfig;
972 using LineStippleParamsConfig		= StaticAndDynamicPair<OptStippleParams>;
973 using SampleLocationsEnableConfig	= BooleanFlagConfig;
974 using ConservativeRasterModeConfig	= StaticAndDynamicPair<vk::VkConservativeRasterizationModeEXT>;
975 using ExtraPrimitiveOverEstConfig	= StaticAndDynamicPair<float>; // Negative numbers will mean we're not interested in setting it.
976 using LineRasterModeConfig			= StaticAndDynamicPair<OptLineRasterMode>;
977 using CoverageToColorEnableConfig	= BooleanFlagConfig;
978 using CoverageToColorLocationConfig	= StaticAndDynamicPair<uint32_t>;
979 using RasterizationSamplesConfig	= StaticAndDynamicPair<vk::VkSampleCountFlagBits>;
980 #ifndef CTS_USES_VULKANSC
981 using CoverageModulationModeConfig	= StaticAndDynamicPair<vk::VkCoverageModulationModeNV>;
982 using CoverageModTableEnableConfig	= BooleanFlagConfig;
983 using CoverageModTableConfig		= StaticAndDynamicPair<CovModTableVec>;
984 using CoverageReductionModeConfig	= StaticAndDynamicPair<vk::VkCoverageReductionModeNV>;
985 using ViewportSwizzleConfig			= StaticAndDynamicPair<ViewportSwzVec>;
986 using ShadingRateImageEnableConfig	= BooleanFlagConfig;
987 using ViewportWScalingEnableConfig	= BooleanFlagConfig;
988 using ReprFragTestEnableConfig		= BooleanFlagConfig;
989 #endif // CTS_USES_VULKANSC
990 
991 const tcu::Vec4		kDefaultTriangleColor	(0.0f, 0.0f, 1.0f, 1.0f);	// Opaque blue.
992 const tcu::Vec4		kDefaultClearColor		(0.0f, 0.0f, 0.0f, 1.0f);	// Opaque black.
993 const tcu::Vec4		kTransparentColor		(0.0f, 0.0f, 1.0f, 0.0f);	// Transparent version of kDefaultTriangleColor.
994 const tcu::Vec4		kTransparentClearColor	(0.0f, 0.0f, 0.0f, 0.0f);	// Transparent version of kDefaultClearColor.
995 const tcu::Vec4		kOpaqueWhite			(1.0f, 1.0f, 1.0f, 1.0f);	// Opaque white, all components active.
996 
997 const tcu::UVec4	kLogicOpTriangleColor	(  0u,   0u, 255u, 255u);	// Opaque blue.
998 const tcu::UVec4	kGreenClearColor		(  0u, 255u,   0u, 255u);	// Opaque green, UINT.
999 const tcu::UVec4	kLogicOpFinalColor		(  0u, 255u, 255u, 255u);	// Opaque cyan, UINT.
1000 
1001 // Same as kLogicOpTriangleColor. Note: tcu::Vec4 and will be cast to the appropriate type in the shader.
1002 const tcu::Vec4 kLogicOpTriangleColorFl (static_cast<float>(kLogicOpTriangleColor.x()),
1003 										 static_cast<float>(kLogicOpTriangleColor.y()),
1004 										 static_cast<float>(kLogicOpTriangleColor.w()),
1005 										 static_cast<float>(kLogicOpTriangleColor.z()));
1006 
1007 struct MeshParams
1008 {
1009 	tcu::Vec4	color;
1010 	float		depth;
1011 	bool		reversed;
1012 	float		scaleX;
1013 	float		scaleY;
1014 	float		offsetX;
1015 	float		offsetY;
1016 	float		stripScale;
1017 
MeshParamsvkt::pipeline::__anonaa66a09e0111::MeshParams1018 	MeshParams (const tcu::Vec4&	color_		= kDefaultTriangleColor,
1019 				float				depth_		= 0.0f,
1020 				bool				reversed_	= false,
1021 				float				scaleX_		= 1.0f,
1022 				float				scaleY_		= 1.0f,
1023 				float				offsetX_	= 0.0f,
1024 				float				offsetY_	= 0.0f,
1025 				float				stripScale_	= 0.0f)
1026 		: color			(color_)
1027 		, depth			(depth_)
1028 		, reversed		(reversed_)
1029 		, scaleX		(scaleX_)
1030 		, scaleY		(scaleY_)
1031 		, offsetX		(offsetX_)
1032 		, offsetY		(offsetY_)
1033 		, stripScale	(stripScale_)
1034 	{}
1035 };
1036 
1037 enum class SequenceOrdering
1038 {
1039 	CMD_BUFFER_START	= 0,	// Set state at the start of the command buffer.
1040 	BEFORE_DRAW			= 1,	// After binding dynamic pipeline and just before drawing.
1041 	BETWEEN_PIPELINES	= 2,	// After a static state pipeline has been bound but before the dynamic state pipeline has been bound.
1042 	AFTER_PIPELINES		= 3,	// After a static state pipeline and a second dynamic state pipeline have been bound.
1043 	BEFORE_GOOD_STATIC	= 4,	// Before a static state pipeline with the correct values has been bound.
1044 	TWO_DRAWS_DYNAMIC	= 5,	// Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again.
1045 	TWO_DRAWS_STATIC	= 6,	// Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again.
1046 };
1047 
1048 class ReferenceColorGenerator
1049 {
1050 public:
1051 	typedef std::unique_ptr<ReferenceColorGenerator> P;
1052 
1053 	virtual void	operator()	(tcu::PixelBufferAccess&)	const = 0;
1054 	virtual P		clone		()							const = 0;
1055 };
1056 
1057 using ColorVerificator = std::function<bool(const tcu::ConstPixelBufferAccess&/*result*/, const tcu::ConstPixelBufferAccess&/*reference*/, const tcu::PixelBufferAccess&/*errorMask*/)>;
1058 
1059 // Most tests expect a single output color in the whole image.
1060 class SingleColorGenerator : public ReferenceColorGenerator
1061 {
1062 public:
SingleColorGenerator(const tcu::Vec4 & color)1063 	SingleColorGenerator (const tcu::Vec4& color)
1064 		: m_colorFloat	(color)
1065 		, m_colorUint	(0u)
1066 		, isUint		(false)
1067 	{}
1068 
SingleColorGenerator(const tcu::UVec4 & color)1069 	SingleColorGenerator (const tcu::UVec4& color)
1070 		: m_colorFloat	(0.0f)
1071 		, m_colorUint	(color)
1072 		, isUint		(true)
1073 	{}
1074 
operator ()(tcu::PixelBufferAccess & access) const1075 	void operator()(tcu::PixelBufferAccess& access) const override
1076 	{
1077 		const auto kWidth	= access.getWidth();
1078 		const auto kHeight	= access.getHeight();
1079 
1080 		for (int y = 0; y < kHeight; ++y)
1081 			for (int x = 0; x < kWidth; ++x)
1082 			{
1083 				if (isUint)
1084 					access.setPixel(m_colorUint, x, y);
1085 				else
1086 					access.setPixel(m_colorFloat, x, y);
1087 			}
1088 	}
1089 
clone() const1090 	P clone() const override
1091 	{
1092 		return P(new SingleColorGenerator(*this));
1093 	}
1094 
1095 private:
1096 	const tcu::Vec4		m_colorFloat;
1097 	const tcu::UVec4	m_colorUint;
1098 	const bool			isUint;
1099 };
1100 
1101 // Some tests expect the upper half and the lower half having different color values.
1102 class HorizontalSplitGenerator : public ReferenceColorGenerator
1103 {
1104 public:
HorizontalSplitGenerator(const tcu::Vec4 & top,const tcu::Vec4 & bottom)1105 	HorizontalSplitGenerator (const tcu::Vec4& top, const tcu::Vec4& bottom)
1106 		: m_top(top), m_bottom(bottom)
1107 	{}
1108 
operator ()(tcu::PixelBufferAccess & access) const1109 	void operator()(tcu::PixelBufferAccess& access) const override
1110 	{
1111 		const auto kWidth		= access.getWidth();
1112 		const auto kHeight		= access.getHeight();
1113 		const auto kHalfHeight	= kHeight / 2;
1114 
1115 		for (int y = 0; y < kHeight; ++y)
1116 			for (int x = 0; x < kWidth; ++x)
1117 			{
1118 				const auto& color = (y < kHalfHeight ? m_top : m_bottom);
1119 				access.setPixel(color, x, y);
1120 			}
1121 	}
1122 
clone() const1123 	P clone() const override
1124 	{
1125 		return P(new HorizontalSplitGenerator(*this));
1126 	}
1127 
1128 private:
1129 	const tcu::Vec4 m_top;
1130 	const tcu::Vec4 m_bottom;
1131 };
1132 
1133 // Primitive restart tests expect the last line to have some missing pixels.
1134 class LastSegmentMissingGenerator : public ReferenceColorGenerator
1135 {
1136 public:
LastSegmentMissingGenerator(const tcu::Vec4 & geomColor,const tcu::Vec4 & clearColor)1137 	LastSegmentMissingGenerator (const tcu::Vec4& geomColor, const tcu::Vec4& clearColor)
1138 		: m_geomColor	(geomColor)
1139 		, m_clearColor	(clearColor)
1140 	{}
1141 
operator ()(tcu::PixelBufferAccess & access) const1142 	void operator()(tcu::PixelBufferAccess& access) const override
1143 	{
1144 		constexpr auto kWidth				= static_cast<int>(kFramebufferWidth);
1145 		constexpr auto kHeight				= static_cast<int>(kFramebufferHeight);
1146 		constexpr auto kLastSegmentStart	= static_cast<int>(kWidth * 0.75f);
1147 
1148 		for (int y = 0; y < kHeight; ++y)
1149 		for (int x = 0; x < kWidth; ++x)
1150 		{
1151 			// The last segment of the last line has the background color.
1152 			const auto& color = ((y == kHeight - 1 && x >= kLastSegmentStart) ? m_clearColor : m_geomColor);
1153 			access.setPixel(color, x, y);
1154 		}
1155 	}
1156 
clone() const1157 	P clone() const override
1158 	{
1159 		return P(new LastSegmentMissingGenerator(*this));
1160 	}
1161 
1162 private:
1163 	const tcu::Vec4 m_geomColor;
1164 	const tcu::Vec4 m_clearColor;
1165 };
1166 
1167 // Some tests (like stippled line tests) expect vertical stripes of a given width.
1168 class VerticalStripesGenerator: public ReferenceColorGenerator
1169 {
1170 public:
VerticalStripesGenerator(const tcu::Vec4 & left,const tcu::Vec4 & right,uint32_t width)1171 	VerticalStripesGenerator (const tcu::Vec4& left, const tcu::Vec4& right, uint32_t width)
1172 		: m_left(left), m_right(right), m_width(width)
1173 	{
1174 		DE_ASSERT(width > 0 && width <= static_cast<uint32_t>(std::numeric_limits<int>::max()));
1175 	}
1176 
operator ()(tcu::PixelBufferAccess & access) const1177 	void operator()(tcu::PixelBufferAccess& access) const override
1178 	{
1179 		constexpr auto kWidth		= static_cast<int>(kFramebufferWidth);
1180 		constexpr auto kHeight		= static_cast<int>(kFramebufferHeight);
1181 
1182 		for (int y = 0; y < kHeight; ++y)
1183 			for (int x = 0; x < kWidth; ++x)
1184 			{
1185 				const int	stripeIdx	= x / static_cast<int>(m_width);
1186 				const auto&	color		= ((stripeIdx % 2 == 0) ? m_left : m_right);
1187 				access.setPixel(color, x, y);
1188 			}
1189 	}
1190 
clone() const1191 	P clone() const override
1192 	{
1193 		return P(new VerticalStripesGenerator(*this));
1194 	}
1195 
1196 private:
1197 	const tcu::Vec4	m_left;
1198 	const tcu::Vec4	m_right;
1199 	const uint32_t	m_width;
1200 };
1201 
1202 // 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
1203 // a different color.
1204 class TopLeftBorderGenerator : public ReferenceColorGenerator
1205 {
1206 public:
TopLeftBorderGenerator(const tcu::Vec4 & mainColor,const tcu::Vec4 & borderLeft,const tcu::Vec4 & corner,const tcu::Vec4 & borderTop)1207 	TopLeftBorderGenerator (const tcu::Vec4& mainColor, const tcu::Vec4& borderLeft, const tcu::Vec4& corner, const tcu::Vec4& borderTop)
1208 		: m_mainColor	(mainColor)
1209 		, m_borderLeft	(borderLeft)
1210 		, m_corner		(corner)
1211 		, m_borderTop	(borderTop)
1212 	{}
1213 
operator ()(tcu::PixelBufferAccess & access) const1214 	void operator()(tcu::PixelBufferAccess& access) const override
1215 	{
1216 		const auto kWidth		= access.getWidth();
1217 		const auto kHeight		= access.getHeight();
1218 
1219 		for (int y = 0; y < kHeight; ++y)
1220 			for (int x = 0; x < kWidth; ++x)
1221 			{
1222 				tcu::Vec4 color;
1223 
1224 				if (x == 0)
1225 				{
1226 					if (y == 0)
1227 						color = m_corner;
1228 					else
1229 						color = m_borderLeft;
1230 				}
1231 				else if (y == 0)
1232 					color = m_borderTop;
1233 				else
1234 					color = m_mainColor;
1235 
1236 				access.setPixel(color, x, y);
1237 			}
1238 	}
1239 
clone() const1240 	P clone() const override
1241 	{
1242 		return P(new TopLeftBorderGenerator(*this));
1243 	}
1244 
1245 private:
1246 	const tcu::Vec4 m_mainColor;
1247 	const tcu::Vec4 m_borderLeft;
1248 	const tcu::Vec4 m_corner;
1249 	const tcu::Vec4 m_borderTop;
1250 };
1251 
1252 // Verifies the top left pixel matches exactly.
verifyTopLeftCorner(const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & reference,const tcu::PixelBufferAccess & errorMask)1253 bool verifyTopLeftCorner (const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& reference, const tcu::PixelBufferAccess& errorMask)
1254 {
1255 	// Check corner.
1256 	const auto resultColor		= result.getPixel(0, 0);
1257 	const auto referenceColor	= reference.getPixel(0, 0);
1258 
1259 	const auto red		= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1260 	const auto green	= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1261 	const auto black	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1262 	const bool match	= (resultColor == referenceColor);
1263 
1264 	tcu::clear(errorMask, black);
1265 	errorMask.setPixel((match ? green : red), 0, 0);
1266 
1267 	return match;
1268 }
1269 
getVertexWithPaddingGenerator()1270 const VertexGenerator* getVertexWithPaddingGenerator ()
1271 {
1272 	static VertexWithPadding vertexWithPadding;
1273 	return &vertexWithPadding;
1274 }
1275 
getVertexWithExtraAttributesGenerator()1276 const VertexGenerator* getVertexWithExtraAttributesGenerator ()
1277 {
1278 	static VertexWithExtraAttributes vertexWithExtraAttributes;
1279 	return &vertexWithExtraAttributes;
1280 }
1281 
getVertexWithMultipleBindingsGenerator()1282 const VertexGenerator* getVertexWithMultipleBindingsGenerator ()
1283 {
1284 	static MultipleBindingsVertex multipleBindingsVertex;
1285 	return &multipleBindingsVertex;
1286 }
1287 
getProvokingVertexWithPaddingGenerator(bool lastVertex)1288 const VertexGenerator* getProvokingVertexWithPaddingGenerator (bool lastVertex)
1289 {
1290 	if (lastVertex)
1291 	{
1292 		static ProvokingVertexWithPadding provokingVertexGeneratorLastVtx (true);
1293 		return &provokingVertexGeneratorLastVtx;
1294 	}
1295 	static ProvokingVertexWithPadding provokingVertexGeneratorFirstVtx (false);
1296 	return &provokingVertexGeneratorFirstVtx;
1297 }
1298 
1299 // Create VertexGeneratorConfig varying constructor depending on having none, only the static or both.
makeVertexGeneratorConfig(const VertexGenerator * staticGen,const VertexGenerator * dynamicGen)1300 VertexGeneratorConfig makeVertexGeneratorConfig (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
1301 {
1302 	DE_ASSERT(!(dynamicGen && !staticGen));
1303 	if (dynamicGen)
1304 		return VertexGeneratorConfig(staticGen, dynamicGen);
1305 	if (staticGen)
1306 		return VertexGeneratorConfig(staticGen);
1307 	return VertexGeneratorConfig(getVertexWithPaddingGenerator());	// Only static part with a default option.
1308 }
1309 
1310 // Similar to makeVertexGeneratorConfig, choosing the final value.
chooseVertexGenerator(const VertexGenerator * staticGen,const VertexGenerator * dynamicGen)1311 const VertexGenerator* chooseVertexGenerator (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
1312 {
1313 	DE_ASSERT(!(dynamicGen && !staticGen));
1314 	if (dynamicGen)
1315 		return dynamicGen;
1316 	if (staticGen)
1317 		return staticGen;
1318 	return getVertexWithPaddingGenerator();
1319 }
1320 
1321 enum class TopologyClass
1322 {
1323 	POINT,
1324 	LINE,
1325 	TRIANGLE,
1326 	PATCH,
1327 	INVALID,
1328 };
1329 
topologyClassName(TopologyClass tclass)1330 std::string topologyClassName (TopologyClass tclass)
1331 {
1332 	switch (tclass)
1333 	{
1334 	case TopologyClass::POINT:		return "point";
1335 	case TopologyClass::LINE:		return "line";
1336 	case TopologyClass::TRIANGLE:	return "triangle";
1337 	case TopologyClass::PATCH:		return "patch";
1338 	default:
1339 		break;
1340 	}
1341 
1342 	DE_ASSERT(false);
1343 	return "";
1344 }
1345 
1346 #ifndef CTS_USES_VULKANSC
1347 // Is a particular dynamic state incompatible with mesh shading pipelines?
isMeshShadingPipelineIncompatible(vk::VkDynamicState state)1348 bool isMeshShadingPipelineIncompatible (vk::VkDynamicState state)
1349 {
1350 	switch (state)
1351 	{
1352 	case vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT:
1353 	case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT:
1354 	case vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT:
1355 	case vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
1356 	case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
1357 		return true;
1358 	default:
1359 		return false;
1360 	}
1361 
1362 	// Unreachable.
1363 	DE_ASSERT(false);
1364 	return false;
1365 }
1366 
1367 // Is a particular dynamic state compatible with mesh shading pipelines?
isMeshShadingPipelineCompatible(vk::VkDynamicState state)1368 bool isMeshShadingPipelineCompatible (vk::VkDynamicState state)
1369 {
1370 	return !isMeshShadingPipelineIncompatible(state);
1371 }
1372 #endif // CTS_USES_VULKANSC
1373 
getTopologyClass(vk::VkPrimitiveTopology topology)1374 TopologyClass getTopologyClass (vk::VkPrimitiveTopology topology)
1375 {
1376 	switch (topology)
1377 	{
1378 	case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1379 		return TopologyClass::POINT;
1380 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1381 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1382 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1383 	case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1384 		return TopologyClass::LINE;
1385 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1386 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1387 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1388 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1389 	case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1390 		return TopologyClass::TRIANGLE;
1391 	case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1392 		return TopologyClass::PATCH;
1393 	default:
1394 		break;
1395 	}
1396 
1397 	DE_ASSERT(false);
1398 	return TopologyClass::INVALID;
1399 }
1400 
selectLineRasterizationMode(const vk::VkPhysicalDeviceLineRasterizationFeaturesEXT & lineRasterFeatures,bool stippleRequired,const tcu::Maybe<LineRasterizationMode> & pref)1401 LineRasterizationMode selectLineRasterizationMode (const vk::VkPhysicalDeviceLineRasterizationFeaturesEXT& lineRasterFeatures, bool stippleRequired, const tcu::Maybe<LineRasterizationMode>& pref)
1402 {
1403 	LineRasterizationMode	selectedMode	= LineRasterizationMode::NONE;
1404 	const bool				hasPref			= static_cast<bool>(pref);
1405 
1406 	if ((!hasPref || pref.get() == LineRasterizationMode::RECTANGULAR) && lineRasterFeatures.rectangularLines && (!stippleRequired || lineRasterFeatures.stippledRectangularLines))
1407 		selectedMode = LineRasterizationMode::RECTANGULAR;
1408 	else if ((!hasPref || pref.get() == LineRasterizationMode::BRESENHAM) && lineRasterFeatures.bresenhamLines && (!stippleRequired || lineRasterFeatures.stippledBresenhamLines))
1409 		selectedMode = LineRasterizationMode::BRESENHAM;
1410 	else if ((!hasPref || pref.get() == LineRasterizationMode::SMOOTH) && lineRasterFeatures.smoothLines && (!stippleRequired || lineRasterFeatures.stippledSmoothLines))
1411 		selectedMode = LineRasterizationMode::SMOOTH;
1412 
1413 	return selectedMode;
1414 }
1415 
1416 #ifndef CTS_USES_VULKANSC
makeLineRasterizationMode(LineRasterizationMode mode)1417 vk::VkLineRasterizationModeEXT makeLineRasterizationMode (LineRasterizationMode mode)
1418 {
1419 	vk::VkLineRasterizationModeEXT modeEXT = vk::VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
1420 
1421 	switch (mode)
1422 	{
1423 	case LineRasterizationMode::RECTANGULAR:	modeEXT = vk::VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;			break;
1424 	case LineRasterizationMode::BRESENHAM:		modeEXT = vk::VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;				break;
1425 	case LineRasterizationMode::SMOOTH:			modeEXT = vk::VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;	break;
1426 	default:
1427 		DE_ASSERT(false);
1428 		break;
1429 	}
1430 
1431 	return modeEXT;
1432 }
1433 #endif // CTS_USES_VULKANSC
1434 
1435 struct TestConfig
1436 {
1437 	// Should we use pipeline_library to construct pipeline.
1438 	vk::PipelineConstructionType	pipelineConstructionType;
1439 
1440 	// Main sequence ordering.
1441 	SequenceOrdering				sequenceOrdering;
1442 
1443 	// Drawing parameters: tests will draw one or more flat meshes of triangles covering the whole "screen".
1444 	std::vector<MeshParams>			meshParams;			// Mesh parameters for each full-screen layer of geometry.
1445 	deUint32						referenceStencil;	// Reference stencil value.
1446 
1447 	// Clearing parameters for the framebuffer.
1448 	vk::VkClearValue				clearColorValue;
1449 	float							clearDepthValue;
1450 	deUint32						clearStencilValue;
1451 
1452 	// Expected output in the attachments.
1453 	ReferenceColorGenerator::P		referenceColor;
1454 	float							expectedDepth;
1455 	deUint32						expectedStencil;
1456 
1457 	// Optional verification routine.
1458 	tcu::Maybe<ColorVerificator>	colorVerificator;
1459 
1460 	// Depth bounds parameters for the pipeline.
1461 	float							minDepthBounds;
1462 	float							maxDepthBounds;
1463 
1464 	// Force inclusion of passthrough geometry shader or not.
1465 	bool							forceGeometryShader;
1466 
1467 	// Use mesh shaders instead of classic pipelines.
1468 	bool							useMeshShaders;
1469 
1470 	// Bind an unused mesh shading pipeline before binding the dynamic pipeline.
1471 	// This will only be used in the CMD_BUFFER_START sequence ordering, to minimize the number of cases.
1472 	bool							bindUnusedMeshShadingPipeline;
1473 
1474 	// Force single vertex in the VBO.
1475 	bool							singleVertex;
1476 	deUint32						singleVertexDrawCount;
1477 
1478 	// Force using an oversized triangle as the mesh.
1479 	bool							oversizedTriangle;
1480 
1481 	// Force using a single triangle with a small offset as the mesh.
1482 	bool							offCenterTriangle;
1483 	tcu::Vec2						offCenterProportion; // Relative to pixel size.
1484 
1485 	// Force using a single oblique line: this helps test line rasterization mode.
1486 	bool							obliqueLine;
1487 
1488 	// Offset and extra room after the vertex buffer data.
1489 	vk::VkDeviceSize				vertexDataOffset;
1490 	vk::VkDeviceSize				vertexDataExtraBytes;
1491 
1492 	// Bind and draw with a pipeline that uses dynamic patch control points but doesn't actually use a tessellation
1493 	// shader, before using the real pipelines being tested.
1494 	bool							useExtraDynPCPPipeline;
1495 
1496 	// Optional, to be used specifically for color attachments when testing coverage modulation and reduction.
1497 	bool							coverageModulation;
1498 	bool							coverageReduction;
1499 	OptSampleCount					colorSampleCount;
1500 
1501 	// Rasterization stream, if needed, used in the geometry shader.
1502 	OptRastStream					shaderRasterizationStream;
1503 
1504 	// Sample locations, which may be used if testing sample locations.
1505 	tcu::Vec2						sampleLocations;
1506 
1507 	// Optional maximum value for primitiveOverestimationSize so the test works properly.
1508 	tcu::Maybe<float>				maxPrimitiveOverestimationSize;
1509 
1510 	// Number of color attachments in the subpass. Note the fragment shader will only write to the last one.
1511 	uint32_t						colorAttachmentCount;
1512 
1513 	// Use viewport swizzle or not.
1514 	bool							viewportSwizzle;
1515 
1516 	// Use shading rate image configuration or not.
1517 	bool							shadingRateImage;
1518 
1519 	// Use viewport W scaling or not.
1520 	bool							viewportWScaling;
1521 
1522 	// Use representative fragment test or not.
1523 	bool							representativeFragmentTest;
1524 
1525 	// When setting the sample mask dynamically, we can use an alternative sample count specified here.
1526 	OptSampleCount					dynamicSampleMaskCount;
1527 
1528 	// Static and dynamic pipeline configuration.
1529 	VertexGeneratorConfig			vertexGenerator;
1530 	CullModeConfig					cullModeConfig;
1531 	FrontFaceConfig					frontFaceConfig;
1532 	TopologyConfig					topologyConfig;
1533 	ViewportConfig					viewportConfig;
1534 	ScissorConfig					scissorConfig;
1535 	StrideConfig					strideConfig;
1536 	DepthTestEnableConfig			depthTestEnableConfig;
1537 	DepthWriteEnableConfig			depthWriteEnableConfig;
1538 	DepthCompareOpConfig			depthCompareOpConfig;
1539 	DepthBoundsTestEnableConfig		depthBoundsTestEnableConfig;
1540 	StencilTestEnableConfig			stencilTestEnableConfig;
1541 	StencilOpConfig					stencilOpConfig;
1542 	DepthBiasEnableConfig			depthBiasEnableConfig;
1543 	RastDiscardEnableConfig			rastDiscardEnableConfig;
1544 	PrimRestartEnableConfig			primRestartEnableConfig;
1545 	LogicOpConfig					logicOpConfig;
1546 	PatchControlPointsConfig		patchControlPointsConfig;
1547 	DepthBiasConfig					depthBiasConfig;
1548 	TessDomainOriginConfig			tessDomainOriginConfig;
1549 	DepthClampEnableConfig			depthClampEnableConfig;
1550 	PolygonModeConfig				polygonModeConfig;
1551 	SampleMaskConfig				sampleMaskConfig;
1552 	AlphaToCoverageConfig			alphaToCoverageConfig;
1553 	AlphaToOneConfig				alphaToOneConfig;
1554 	ColorWriteMaskConfig			colorWriteMaskConfig;
1555 	RasterizationStreamConfig		rasterizationStreamConfig;
1556 	LogicOpEnableConfig				logicOpEnableConfig;
1557 	ColorBlendEnableConfig			colorBlendEnableConfig;
1558 	ColorBlendEquationConfig		colorBlendEquationConfig;
1559 	ProvokingVertexConfig			provokingVertexConfig;
1560 	NegativeOneToOneConfig			negativeOneToOneConfig;
1561 	DepthClipEnableConfig			depthClipEnableConfig;
1562 	LineStippleEnableConfig			lineStippleEnableConfig;
1563 	LineStippleParamsConfig			lineStippleParamsConfig;
1564 	SampleLocationsEnableConfig		sampleLocationsEnableConfig;
1565 	ConservativeRasterModeConfig	conservativeRasterModeConfig;
1566 	ExtraPrimitiveOverEstConfig		extraPrimitiveOverEstConfig;
1567 	LineRasterModeConfig			lineRasterModeConfig;
1568 	CoverageToColorEnableConfig		coverageToColorEnableConfig;
1569 	CoverageToColorLocationConfig	coverageToColorLocationConfig;
1570 	RasterizationSamplesConfig		rasterizationSamplesConfig;
1571 #ifndef CTS_USES_VULKANSC
1572 	CoverageModulationModeConfig	coverageModulationModeConfig;
1573 	CoverageModTableEnableConfig	coverageModTableEnableConfig;
1574 	CoverageModTableConfig			coverageModTableConfig;
1575 	CoverageReductionModeConfig		coverageReductionModeConfig;
1576 	ViewportSwizzleConfig			viewportSwizzleConfig;
1577 	ShadingRateImageEnableConfig	shadingRateImageEnableConfig;
1578 	ViewportWScalingEnableConfig	viewportWScalingEnableConfig;
1579 	ReprFragTestEnableConfig		reprFragTestEnableConfig;
1580 #endif // CTS_USES_VULKANSC
1581 
1582 	// Sane defaults.
TestConfigvkt::pipeline::__anonaa66a09e0111::TestConfig1583 	TestConfig (vk::PipelineConstructionType pipelineType, SequenceOrdering ordering, bool useMeshShaders_, const VertexGenerator* staticVertexGenerator = nullptr, const VertexGenerator* dynamicVertexGenerator = nullptr)
1584 		: pipelineConstructionType		(pipelineType)
1585 		, sequenceOrdering				(ordering)
1586 		, meshParams					(1u, MeshParams())
1587 		, referenceStencil				(0u)
1588 		, clearColorValue				(vk::makeClearValueColor(kDefaultClearColor))
1589 		, clearDepthValue				(1.0f)
1590 		, clearStencilValue				(0u)
1591 		, referenceColor				(new SingleColorGenerator(kDefaultTriangleColor))
1592 		, expectedDepth					(1.0f)
1593 		, expectedStencil				(0u)
1594 		, colorVerificator				(tcu::Nothing)
1595 		, minDepthBounds				(0.0f)
1596 		, maxDepthBounds				(1.0f)
1597 		, forceGeometryShader			(false)
1598 		, useMeshShaders				(useMeshShaders_)
1599 		, bindUnusedMeshShadingPipeline	(false)
1600 		, singleVertex					(false)
1601 		, singleVertexDrawCount			(0)
1602 		, oversizedTriangle				(false)
1603 		, offCenterTriangle				(false)
1604 		, offCenterProportion			(0.0f, 0.0f)
1605 		, obliqueLine					(false)
1606 		, vertexDataOffset				(0ull)
1607 		, vertexDataExtraBytes			(0ull)
1608 		, useExtraDynPCPPipeline		(false)
1609 		, coverageModulation			(false)
1610 		, coverageReduction				(false)
1611 		, colorSampleCount				(tcu::Nothing)
1612 		, shaderRasterizationStream		(tcu::Nothing)
1613 		, sampleLocations				(0.5f, 0.5f)
1614 		, colorAttachmentCount			(1u)
1615 		, viewportSwizzle				(false)
1616 		, shadingRateImage				(false)
1617 		, viewportWScaling				(false)
1618 		, representativeFragmentTest	(false)
1619 		, dynamicSampleMaskCount		(tcu::Nothing)
1620 		, vertexGenerator				(makeVertexGeneratorConfig(staticVertexGenerator, dynamicVertexGenerator))
1621 		, cullModeConfig				(static_cast<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE))
1622 		, frontFaceConfig				(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
1623 		// By default we will use a triangle strip with 6 vertices that could be wrongly interpreted as a triangle list with 2 triangles.
1624 		, topologyConfig				(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
1625 		, viewportConfig				(ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight)))
1626 		, scissorConfig					(ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight)))
1627 		// By default, the vertex stride is the size of a vertex according to the chosen vertex type.
1628 		, strideConfig					(chooseVertexGenerator(staticVertexGenerator, dynamicVertexGenerator)->getVertexDataStrides())
1629 		, depthTestEnableConfig			(false)
1630 		, depthWriteEnableConfig		(false)
1631 		, depthCompareOpConfig			(vk::VK_COMPARE_OP_NEVER)
1632 		, depthBoundsTestEnableConfig	(false)
1633 		, stencilTestEnableConfig		(false)
1634 		, stencilOpConfig				(StencilOpVec(1u, kDefaultStencilOpParams))
1635 		, depthBiasEnableConfig			(false)
1636 		, rastDiscardEnableConfig		(false)
1637 		, primRestartEnableConfig		(false)
1638 		, logicOpConfig					(vk::VK_LOGIC_OP_CLEAR)
1639 		, patchControlPointsConfig		(1u)
1640 		, depthBiasConfig				(kNoDepthBiasParams)
1641 		, tessDomainOriginConfig		(vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
1642 		, depthClampEnableConfig		(false)
1643 		, polygonModeConfig				(vk::VK_POLYGON_MODE_FILL)
1644 		, sampleMaskConfig				(SampleMaskVec())
1645 		, alphaToCoverageConfig			(false)
1646 		, alphaToOneConfig				(false)
1647 		, colorWriteMaskConfig			(CR | CG | CB | CA)
1648 		, rasterizationStreamConfig		(tcu::Nothing)
1649 		, logicOpEnableConfig			(false)
1650 		, colorBlendEnableConfig		(false)
1651 		, colorBlendEquationConfig		(ColorBlendEq())
1652 		, provokingVertexConfig			(tcu::Nothing)
1653 		, negativeOneToOneConfig		(tcu::Nothing)
1654 		, depthClipEnableConfig			(tcu::Nothing)
1655 		, lineStippleEnableConfig		(false)
1656 		, lineStippleParamsConfig		(tcu::Nothing)
1657 		, sampleLocationsEnableConfig	(false)
1658 		, conservativeRasterModeConfig	(vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT)
1659 		, extraPrimitiveOverEstConfig	(-1.0f)
1660 		, lineRasterModeConfig			(tcu::Nothing)
1661 		, coverageToColorEnableConfig	(false)
1662 		, coverageToColorLocationConfig	(0u)
1663 		, rasterizationSamplesConfig	(kSingleSampleCount)
1664 #ifndef CTS_USES_VULKANSC
1665 		, coverageModulationModeConfig	(vk::VK_COVERAGE_MODULATION_MODE_NONE_NV)
1666 		, coverageModTableEnableConfig	(false)
1667 		, coverageModTableConfig		(CovModTableVec())
1668 		, coverageReductionModeConfig	(vk::VK_COVERAGE_REDUCTION_MODE_MERGE_NV)
1669 		, viewportSwizzleConfig			(ViewportSwzVec())
1670 		, shadingRateImageEnableConfig	(false)
1671 		, viewportWScalingEnableConfig	(false)
1672 		, reprFragTestEnableConfig		(false)
1673 #endif // CTS_USES_VULKANSC
1674 		, m_swappedValues				(false)
1675 	{
1676 	}
1677 
TestConfigvkt::pipeline::__anonaa66a09e0111::TestConfig1678 	TestConfig (const TestConfig& other)
1679 		: pipelineConstructionType		(other.pipelineConstructionType)
1680 		, sequenceOrdering				(other.sequenceOrdering)
1681 		, meshParams					(other.meshParams)
1682 		, referenceStencil				(other.referenceStencil)
1683 		, clearColorValue				(other.clearColorValue)
1684 		, clearDepthValue				(other.clearDepthValue)
1685 		, clearStencilValue				(other.clearStencilValue)
1686 		, referenceColor				(other.referenceColor->clone())
1687 		, expectedDepth					(other.expectedDepth)
1688 		, expectedStencil				(other.expectedStencil)
1689 		, colorVerificator				(other.colorVerificator)
1690 		, minDepthBounds				(other.minDepthBounds)
1691 		, maxDepthBounds				(other.maxDepthBounds)
1692 		, forceGeometryShader			(other.forceGeometryShader)
1693 		, useMeshShaders				(other.useMeshShaders)
1694 		, bindUnusedMeshShadingPipeline	(other.bindUnusedMeshShadingPipeline)
1695 		, singleVertex					(other.singleVertex)
1696 		, singleVertexDrawCount			(other.singleVertexDrawCount)
1697 		, oversizedTriangle				(other.oversizedTriangle)
1698 		, offCenterTriangle				(other.offCenterTriangle)
1699 		, offCenterProportion			(other.offCenterProportion)
1700 		, obliqueLine					(other.obliqueLine)
1701 		, vertexDataOffset				(other.vertexDataOffset)
1702 		, vertexDataExtraBytes			(other.vertexDataExtraBytes)
1703 		, useExtraDynPCPPipeline		(other.useExtraDynPCPPipeline)
1704 		, coverageModulation			(other.coverageModulation)
1705 		, coverageReduction				(other.coverageReduction)
1706 		, colorSampleCount				(other.colorSampleCount)
1707 		, shaderRasterizationStream		(other.shaderRasterizationStream)
1708 		, sampleLocations				(other.sampleLocations)
1709 		, colorAttachmentCount			(other.colorAttachmentCount)
1710 		, viewportSwizzle				(other.viewportSwizzle)
1711 		, shadingRateImage				(other.shadingRateImage)
1712 		, viewportWScaling				(other.viewportWScaling)
1713 		, representativeFragmentTest	(other.representativeFragmentTest)
1714 		, dynamicSampleMaskCount		(other.dynamicSampleMaskCount)
1715 		, vertexGenerator				(other.vertexGenerator)
1716 		, cullModeConfig				(other.cullModeConfig)
1717 		, frontFaceConfig				(other.frontFaceConfig)
1718 		, topologyConfig				(other.topologyConfig)
1719 		, viewportConfig				(other.viewportConfig)
1720 		, scissorConfig					(other.scissorConfig)
1721 		, strideConfig					(other.strideConfig)
1722 		, depthTestEnableConfig			(other.depthTestEnableConfig)
1723 		, depthWriteEnableConfig		(other.depthWriteEnableConfig)
1724 		, depthCompareOpConfig			(other.depthCompareOpConfig)
1725 		, depthBoundsTestEnableConfig	(other.depthBoundsTestEnableConfig)
1726 		, stencilTestEnableConfig		(other.stencilTestEnableConfig)
1727 		, stencilOpConfig				(other.stencilOpConfig)
1728 		, depthBiasEnableConfig			(other.depthBiasEnableConfig)
1729 		, rastDiscardEnableConfig		(other.rastDiscardEnableConfig)
1730 		, primRestartEnableConfig		(other.primRestartEnableConfig)
1731 		, logicOpConfig					(other.logicOpConfig)
1732 		, patchControlPointsConfig		(other.patchControlPointsConfig)
1733 		, depthBiasConfig				(other.depthBiasConfig)
1734 		, tessDomainOriginConfig		(other.tessDomainOriginConfig)
1735 		, depthClampEnableConfig		(other.depthClampEnableConfig)
1736 		, polygonModeConfig				(other.polygonModeConfig)
1737 		, sampleMaskConfig				(other.sampleMaskConfig)
1738 		, alphaToCoverageConfig			(other.alphaToCoverageConfig)
1739 		, alphaToOneConfig				(other.alphaToOneConfig)
1740 		, colorWriteMaskConfig			(other.colorWriteMaskConfig)
1741 		, rasterizationStreamConfig		(other.rasterizationStreamConfig)
1742 		, logicOpEnableConfig			(other.logicOpEnableConfig)
1743 		, colorBlendEnableConfig		(other.colorBlendEnableConfig)
1744 		, colorBlendEquationConfig		(other.colorBlendEquationConfig)
1745 		, provokingVertexConfig			(other.provokingVertexConfig)
1746 		, negativeOneToOneConfig		(other.negativeOneToOneConfig)
1747 		, depthClipEnableConfig			(other.depthClipEnableConfig)
1748 		, lineStippleEnableConfig		(other.lineStippleEnableConfig)
1749 		, lineStippleParamsConfig		(other.lineStippleParamsConfig)
1750 		, sampleLocationsEnableConfig	(other.sampleLocationsEnableConfig)
1751 		, conservativeRasterModeConfig	(other.conservativeRasterModeConfig)
1752 		, extraPrimitiveOverEstConfig	(other.extraPrimitiveOverEstConfig)
1753 		, lineRasterModeConfig			(other.lineRasterModeConfig)
1754 		, coverageToColorEnableConfig	(other.coverageToColorEnableConfig)
1755 		, coverageToColorLocationConfig	(other.coverageToColorLocationConfig)
1756 		, rasterizationSamplesConfig	(other.rasterizationSamplesConfig)
1757 #ifndef CTS_USES_VULKANSC
1758 		, coverageModulationModeConfig	(other.coverageModulationModeConfig)
1759 		, coverageModTableEnableConfig	(other.coverageModTableEnableConfig)
1760 		, coverageModTableConfig		(other.coverageModTableConfig)
1761 		, coverageReductionModeConfig	(other.coverageReductionModeConfig)
1762 		, viewportSwizzleConfig			(other.viewportSwizzleConfig)
1763 		, shadingRateImageEnableConfig	(other.shadingRateImageEnableConfig)
1764 		, viewportWScalingEnableConfig	(other.viewportWScalingEnableConfig)
1765 		, reprFragTestEnableConfig		(other.reprFragTestEnableConfig)
1766 #endif // CTS_USES_VULKANSC
1767 		, m_swappedValues				(other.m_swappedValues)
1768 	{
1769 	}
1770 
1771 	// Get the proper viewport vector according to the test config.
getActiveViewportVecvkt::pipeline::__anonaa66a09e0111::TestConfig1772 	const ViewportVec& getActiveViewportVec () const
1773 	{
1774 		return ((viewportConfig.dynamicValue && !m_swappedValues) ? viewportConfig.dynamicValue.get() : viewportConfig.staticValue);
1775 	}
1776 
1777 	// Gets the proper vertex generator according to the test config.
getActiveVertexGeneratorvkt::pipeline::__anonaa66a09e0111::TestConfig1778 	const VertexGenerator* getActiveVertexGenerator () const
1779 	{
1780 		return ((vertexGenerator.dynamicValue && !m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
1781 	}
1782 
1783 	// Gets the inactive vertex generator according to the test config. If there's only one, return that.
getInactiveVertexGeneratorvkt::pipeline::__anonaa66a09e0111::TestConfig1784 	const VertexGenerator* getInactiveVertexGenerator () const
1785 	{
1786 		return ((vertexGenerator.dynamicValue && m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
1787 	}
1788 
1789 	// Get the active number of patch control points according to the test config.
getActivePatchControlPointsvkt::pipeline::__anonaa66a09e0111::TestConfig1790 	deUint32 getActivePatchControlPoints () const
1791 	{
1792 		return ((patchControlPointsConfig.dynamicValue && !m_swappedValues) ? patchControlPointsConfig.dynamicValue.get() : patchControlPointsConfig.staticValue);
1793 	}
1794 
1795 	// Get the active depth bias parameters.
getActiveDepthBiasParamsvkt::pipeline::__anonaa66a09e0111::TestConfig1796 	DepthBiasParams getActiveDepthBiasParams () const
1797 	{
1798 		return ((depthBiasConfig.dynamicValue && !m_swappedValues) ? depthBiasConfig.dynamicValue.get() : depthBiasConfig.staticValue);
1799 	}
1800 
1801 	// Get the active primitive restart enable value.
getActivePrimitiveRestartEnablevkt::pipeline::__anonaa66a09e0111::TestConfig1802 	bool getActivePrimitiveRestartEnable () const
1803 	{
1804 		return ((primRestartEnableConfig.dynamicValue && !m_swappedValues) ? primRestartEnableConfig.dynamicValue.get() : primRestartEnableConfig.staticValue);
1805 	}
1806 
getActiveTessellationDomainOriginvkt::pipeline::__anonaa66a09e0111::TestConfig1807 	vk::VkTessellationDomainOrigin getActiveTessellationDomainOrigin () const
1808 	{
1809 		return ((tessDomainOriginConfig.dynamicValue && !m_swappedValues) ? tessDomainOriginConfig.dynamicValue.get() : tessDomainOriginConfig.staticValue);
1810 	}
1811 
getActivePolygonModevkt::pipeline::__anonaa66a09e0111::TestConfig1812 	vk::VkPolygonMode getActivePolygonMode () const
1813 	{
1814 		return ((polygonModeConfig.dynamicValue && !m_swappedValues) ? polygonModeConfig.dynamicValue.get() : polygonModeConfig.staticValue);
1815 	}
1816 
getActiveSampleCountvkt::pipeline::__anonaa66a09e0111::TestConfig1817 	vk::VkSampleCountFlagBits getActiveSampleCount () const
1818 	{
1819 		return ((rasterizationSamplesConfig.dynamicValue && !m_swappedValues) ? rasterizationSamplesConfig.dynamicValue.get() : rasterizationSamplesConfig.staticValue);
1820 	}
1821 
getActiveAlphaToOnevkt::pipeline::__anonaa66a09e0111::TestConfig1822 	bool getActiveAlphaToOne () const
1823 	{
1824 		return ((alphaToOneConfig.dynamicValue && !m_swappedValues) ? alphaToOneConfig.dynamicValue.get() : alphaToOneConfig.staticValue);
1825 	}
1826 
rasterizationStreamStructvkt::pipeline::__anonaa66a09e0111::TestConfig1827 	bool rasterizationStreamStruct () const
1828 	{
1829 		return (static_cast<bool>(rasterizationStreamConfig.staticValue)
1830 				|| (static_cast<bool>(rasterizationStreamConfig.dynamicValue) && static_cast<bool>(rasterizationStreamConfig.dynamicValue.get())));
1831 	}
1832 
provokingVertexStructvkt::pipeline::__anonaa66a09e0111::TestConfig1833 	bool provokingVertexStruct () const
1834 	{
1835 		return (static_cast<bool>(provokingVertexConfig.staticValue)
1836 				|| (static_cast<bool>(provokingVertexConfig.dynamicValue) && static_cast<bool>(provokingVertexConfig.dynamicValue.get())));
1837 	}
1838 
negativeOneToOneStructvkt::pipeline::__anonaa66a09e0111::TestConfig1839 	bool negativeOneToOneStruct () const
1840 	{
1841 		return (static_cast<bool>(negativeOneToOneConfig.staticValue)
1842 				|| (static_cast<bool>(negativeOneToOneConfig.dynamicValue) && static_cast<bool>(negativeOneToOneConfig.dynamicValue.get())));
1843 	}
1844 
depthClipEnableStructvkt::pipeline::__anonaa66a09e0111::TestConfig1845 	bool depthClipEnableStruct () const
1846 	{
1847 		return (static_cast<bool>(depthClipEnableConfig.staticValue)
1848 				|| (static_cast<bool>(depthClipEnableConfig.dynamicValue) && static_cast<bool>(depthClipEnableConfig.dynamicValue.get())));
1849 	}
1850 
hasStaticLineStippleParamsvkt::pipeline::__anonaa66a09e0111::TestConfig1851 	bool hasStaticLineStippleParams () const
1852 	{
1853 		return (static_cast<bool>(lineStippleParamsConfig.staticValue));
1854 	}
1855 
hasStaticLineRasterModevkt::pipeline::__anonaa66a09e0111::TestConfig1856 	bool hasStaticLineRasterMode () const
1857 	{
1858 		return (static_cast<bool>(lineRasterModeConfig.staticValue));
1859 	}
1860 
hasLineStippleParamsvkt::pipeline::__anonaa66a09e0111::TestConfig1861 	bool hasLineStippleParams () const
1862 	{
1863 		return (hasStaticLineStippleParams()
1864 				|| (static_cast<bool>(lineStippleParamsConfig.dynamicValue) && static_cast<bool>(lineStippleParamsConfig.dynamicValue.get())));
1865 	}
1866 
hasLineRasterModevkt::pipeline::__anonaa66a09e0111::TestConfig1867 	bool hasLineRasterMode () const
1868 	{
1869 		return (hasStaticLineRasterMode()
1870 				|| (static_cast<bool>(lineRasterModeConfig.dynamicValue) && static_cast<bool>(lineRasterModeConfig.dynamicValue.get())));
1871 	}
1872 
lineStippleSupportRequiredvkt::pipeline::__anonaa66a09e0111::TestConfig1873 	bool lineStippleSupportRequired () const
1874 	{
1875 		return (lineStippleEnableConfig.staticValue || (static_cast<bool>(lineStippleEnableConfig.dynamicValue) && lineStippleEnableConfig.dynamicValue.get()));
1876 	}
1877 
lineRasterStructvkt::pipeline::__anonaa66a09e0111::TestConfig1878 	bool lineRasterStruct () const
1879 	{
1880 		return (static_cast<bool>(lineStippleEnableConfig.dynamicValue) || lineStippleEnableConfig.staticValue || hasStaticLineStippleParams() || hasStaticLineRasterMode());
1881 	}
1882 
lineRasterizationExtvkt::pipeline::__anonaa66a09e0111::TestConfig1883 	bool lineRasterizationExt () const
1884 	{
1885 		return (lineRasterStruct() || hasLineStippleParams() || hasLineRasterMode());
1886 	}
1887 
sampleLocationsStructvkt::pipeline::__anonaa66a09e0111::TestConfig1888 	bool sampleLocationsStruct () const
1889 	{
1890 		return (static_cast<bool>(sampleLocationsEnableConfig.dynamicValue) || sampleLocationsEnableConfig.staticValue);
1891 	}
1892 
coverageToColorStructvkt::pipeline::__anonaa66a09e0111::TestConfig1893 	bool coverageToColorStruct () const
1894 	{
1895 		return (static_cast<bool>(coverageToColorEnableConfig.dynamicValue) || coverageToColorEnableConfig.staticValue);
1896 	}
1897 
conservativeRasterStructvkt::pipeline::__anonaa66a09e0111::TestConfig1898 	bool conservativeRasterStruct () const
1899 	{
1900 		return (static_cast<bool>(conservativeRasterModeConfig.dynamicValue) || conservativeRasterModeConfig.staticValue != vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
1901 				|| static_cast<bool>(extraPrimitiveOverEstConfig.dynamicValue) || extraPrimitiveOverEstConfig.staticValue >= 0.0f);
1902 	}
1903 
getActiveConservativeRasterModevkt::pipeline::__anonaa66a09e0111::TestConfig1904 	vk::VkConservativeRasterizationModeEXT getActiveConservativeRasterMode () const
1905 	{
1906 		return ((static_cast<bool>(conservativeRasterModeConfig.dynamicValue) && !m_swappedValues) ? conservativeRasterModeConfig.dynamicValue.get() : conservativeRasterModeConfig.staticValue);
1907 	}
1908 
getActiveExtraPrimitiveOverEstSizevkt::pipeline::__anonaa66a09e0111::TestConfig1909 	float getActiveExtraPrimitiveOverEstSize () const
1910 	{
1911 		return ((static_cast<bool>(extraPrimitiveOverEstConfig.dynamicValue) && !m_swappedValues) ? extraPrimitiveOverEstConfig.dynamicValue.get() : extraPrimitiveOverEstConfig.staticValue);
1912 	}
1913 
getActiveLogicOpEnablevkt::pipeline::__anonaa66a09e0111::TestConfig1914 	bool getActiveLogicOpEnable () const
1915 	{
1916 		return ((logicOpEnableConfig.dynamicValue && !m_swappedValues) ? logicOpEnableConfig.dynamicValue.get() : logicOpEnableConfig.staticValue);
1917 	}
1918 
getActiveNegativeOneToOneValuevkt::pipeline::__anonaa66a09e0111::TestConfig1919 	bool getActiveNegativeOneToOneValue () const
1920 	{
1921 		const bool				staticValue		= (static_cast<bool>(negativeOneToOneConfig.staticValue) ? negativeOneToOneConfig.staticValue.get() : false);
1922 		const bool				hasDynamicValue	= (static_cast<bool>(negativeOneToOneConfig.dynamicValue) && static_cast<bool>(negativeOneToOneConfig.dynamicValue.get()));
1923 		const tcu::Maybe<bool>	dynamicValue	= (hasDynamicValue ? tcu::just(negativeOneToOneConfig.dynamicValue->get()) : tcu::nothing<bool>());
1924 
1925 		return ((hasDynamicValue && !m_swappedValues) ? dynamicValue.get() : staticValue);
1926 	}
1927 
getActiveDepthClipEnablevkt::pipeline::__anonaa66a09e0111::TestConfig1928 	bool getActiveDepthClipEnable () const
1929 	{
1930 		const bool				staticValue		= (static_cast<bool>(depthClipEnableConfig.staticValue) ? depthClipEnableConfig.staticValue.get() : true);
1931 		const bool				hasDynamicValue	= (static_cast<bool>(depthClipEnableConfig.dynamicValue) && static_cast<bool>(depthClipEnableConfig.dynamicValue.get()));
1932 		const tcu::Maybe<bool>	dynamicValue	= (hasDynamicValue ? tcu::just(depthClipEnableConfig.dynamicValue->get()) : tcu::nothing<bool>());
1933 
1934 		return ((hasDynamicValue && !m_swappedValues) ? dynamicValue.get() : staticValue);
1935 	}
1936 
1937 	// Returns true if there is more than one viewport.
isMultiViewportvkt::pipeline::__anonaa66a09e0111::TestConfig1938 	bool isMultiViewport () const
1939 	{
1940 		return (getActiveViewportVec().size() > 1);
1941 	}
1942 
1943 	// Returns true if the case needs a geometry shader.
needsGeometryShadervkt::pipeline::__anonaa66a09e0111::TestConfig1944 	bool needsGeometryShader () const
1945 	{
1946 		// Writing to gl_ViewportIndex from vertex or tesselation shaders needs the shaderOutputViewportIndex feature, which is less
1947 		// commonly supported than geometry shaders, so we will use a geometry shader if we need to write to it.
1948 		return ((isMultiViewport() && (!useMeshShaders)) || forceGeometryShader || static_cast<bool>(shaderRasterizationStream));
1949 	}
1950 
1951 	// Returns true if we should use the static and dynamic values exchanged.
1952 	// This makes the static part of the pipeline have the actual expected values.
isReversedvkt::pipeline::__anonaa66a09e0111::TestConfig1953 	bool isReversed () const
1954 	{
1955 		return (sequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
1956 				sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC);
1957 	}
1958 
1959 	// Swaps static and dynamic configuration values.
swapValuesvkt::pipeline::__anonaa66a09e0111::TestConfig1960 	void swapValues ()
1961 	{
1962 		vertexGenerator.swapValues();
1963 		cullModeConfig.swapValues();
1964 		frontFaceConfig.swapValues();
1965 		topologyConfig.swapValues();
1966 		viewportConfig.swapValues();
1967 		scissorConfig.swapValues();
1968 		strideConfig.swapValues();
1969 		depthTestEnableConfig.swapValues();
1970 		depthWriteEnableConfig.swapValues();
1971 		depthCompareOpConfig.swapValues();
1972 		depthBoundsTestEnableConfig.swapValues();
1973 		stencilTestEnableConfig.swapValues();
1974 		stencilOpConfig.swapValues();
1975 		depthBiasEnableConfig.swapValues();
1976 		rastDiscardEnableConfig.swapValues();
1977 		primRestartEnableConfig.swapValues();
1978 		logicOpConfig.swapValues();
1979 		patchControlPointsConfig.swapValues();
1980 		depthBiasConfig.swapValues();
1981 		tessDomainOriginConfig.swapValues();
1982 		depthClampEnableConfig.swapValues();
1983 		polygonModeConfig.swapValues();
1984 		sampleMaskConfig.swapValues();
1985 		alphaToCoverageConfig.swapValues();
1986 		alphaToOneConfig.swapValues();
1987 		colorWriteMaskConfig.swapValues();
1988 		rasterizationStreamConfig.swapValues();
1989 		logicOpEnableConfig.swapValues();
1990 		colorBlendEnableConfig.swapValues();
1991 		colorBlendEquationConfig.swapValues();
1992 		provokingVertexConfig.swapValues();
1993 		negativeOneToOneConfig.swapValues();
1994 		depthClipEnableConfig.swapValues();
1995 		lineStippleEnableConfig.swapValues();
1996 		lineStippleParamsConfig.swapValues();
1997 		sampleLocationsEnableConfig.swapValues();
1998 		conservativeRasterModeConfig.swapValues();
1999 		extraPrimitiveOverEstConfig.swapValues();
2000 		lineRasterModeConfig.swapValues();
2001 		coverageToColorEnableConfig.swapValues();
2002 		coverageToColorLocationConfig.swapValues();
2003 		rasterizationSamplesConfig.swapValues();
2004 #ifndef CTS_USES_VULKANSC
2005 		coverageModulationModeConfig.swapValues();
2006 		coverageModTableEnableConfig.swapValues();
2007 		coverageModTableConfig.swapValues();
2008 		coverageReductionModeConfig.swapValues();
2009 		viewportSwizzleConfig.swapValues();
2010 		shadingRateImageEnableConfig.swapValues();
2011 		viewportWScalingEnableConfig.swapValues();
2012 		reprFragTestEnableConfig.swapValues();
2013 #endif // CTS_USES_VULKANSC
2014 
2015 		m_swappedValues = !m_swappedValues;
2016 	}
2017 
2018 	// Returns the number of iterations when recording commands.
numIterationsvkt::pipeline::__anonaa66a09e0111::TestConfig2019 	deUint32 numIterations () const
2020 	{
2021 		deUint32 iterations = 0u;
2022 
2023 		switch (sequenceOrdering)
2024 		{
2025 		case SequenceOrdering::TWO_DRAWS_DYNAMIC:
2026 		case SequenceOrdering::TWO_DRAWS_STATIC:
2027 			iterations = 2u;
2028 			break;
2029 		default:
2030 			iterations = 1u;
2031 			break;
2032 		}
2033 
2034 		return iterations;
2035 	}
2036 
2037 	// Returns true if we're testing the logic op.
testLogicOpvkt::pipeline::__anonaa66a09e0111::TestConfig2038 	bool testLogicOp () const
2039 	{
2040 		return static_cast<bool>(logicOpConfig.dynamicValue);
2041 	}
2042 
2043 	// Returns true if we're testing the logic op enable state.
testLogicOpEnablevkt::pipeline::__anonaa66a09e0111::TestConfig2044 	bool testLogicOpEnable () const
2045 	{
2046 		return static_cast<bool>(logicOpEnableConfig.dynamicValue);
2047 	}
2048 
2049 	// Returns true if we're testing the patch control points.
testPatchControlPointsvkt::pipeline::__anonaa66a09e0111::TestConfig2050 	bool testPatchControlPoints () const
2051 	{
2052 		return static_cast<bool>(patchControlPointsConfig.dynamicValue);
2053 	}
2054 
2055 	// Returns true if we're testing tessellation domain origin.
testTessellationDomainOriginvkt::pipeline::__anonaa66a09e0111::TestConfig2056 	bool testTessellationDomainOrigin () const
2057 	{
2058 		return static_cast<bool>(tessDomainOriginConfig.dynamicValue);
2059 	}
2060 
2061 	// Returns true if we're testing primitive restart enable.
testPrimRestartEnablevkt::pipeline::__anonaa66a09e0111::TestConfig2062 	bool testPrimRestartEnable () const
2063 	{
2064 		return static_cast<bool>(primRestartEnableConfig.dynamicValue);
2065 	}
2066 
2067 	// Returns true if the topology class is patches for tessellation.
patchesTopologyvkt::pipeline::__anonaa66a09e0111::TestConfig2068 	bool patchesTopology () const
2069 	{
2070 		return (getTopologyClass(topologyConfig.staticValue) == TopologyClass::PATCH);
2071 	}
2072 
2073 	// Returns true if the test needs tessellation shaders.
needsTessellationvkt::pipeline::__anonaa66a09e0111::TestConfig2074 	bool needsTessellation () const
2075 	{
2076 		return (testPatchControlPoints() || patchesTopology() || testTessellationDomainOrigin());
2077 	}
2078 
2079 	// Returns the active line stipple enablement flag.
getActiveLineStippleEnablevkt::pipeline::__anonaa66a09e0111::TestConfig2080 	bool getActiveLineStippleEnable () const
2081 	{
2082 		return ((static_cast<bool>(lineStippleEnableConfig.dynamicValue) && !m_swappedValues) ? lineStippleEnableConfig.dynamicValue.get() : lineStippleEnableConfig.staticValue);
2083 	}
2084 
2085 	// Returns the active primitive restart enablement flag.
getActivePrimRestartEnablevkt::pipeline::__anonaa66a09e0111::TestConfig2086 	bool getActivePrimRestartEnable () const
2087 	{
2088 		return ((static_cast<bool>(primRestartEnableConfig.dynamicValue) && !m_swappedValues) ? primRestartEnableConfig.dynamicValue.get() : primRestartEnableConfig.staticValue);
2089 	}
2090 
2091 	// Returns the active representative fragment test enablement flag.
getActiveReprFragTestEnablevkt::pipeline::__anonaa66a09e0111::TestConfig2092 	bool getActiveReprFragTestEnable () const
2093 	{
2094 #ifndef CTS_USES_VULKANSC
2095 		return ((static_cast<bool>(reprFragTestEnableConfig.dynamicValue) && !m_swappedValues) ? reprFragTestEnableConfig.dynamicValue.get() : reprFragTestEnableConfig.staticValue);
2096 #else
2097 		return false;
2098 #endif // CTS_USES_VULKANSC
2099 	}
2100 
2101 	// Returns true if the test needs an index buffer.
needsIndexBuffervkt::pipeline::__anonaa66a09e0111::TestConfig2102 	bool needsIndexBuffer () const
2103 	{
2104 		return (testPrimRestartEnable() || getActiveLineStippleEnable());
2105 	}
2106 
2107 	// Returns true if the test needs the depth bias clamp feature.
needsDepthBiasClampFeaturevkt::pipeline::__anonaa66a09e0111::TestConfig2108 	bool needsDepthBiasClampFeature () const
2109 	{
2110 		return (getActiveDepthBiasParams().clamp != 0.0f);
2111 	}
2112 
2113 	// Returns true if the configuration needs VK_EXT_extended_dynamic_state3.
needsEDS3vkt::pipeline::__anonaa66a09e0111::TestConfig2114 	bool needsEDS3 () const
2115 	{
2116 		return	(	(!!tessDomainOriginConfig.dynamicValue)
2117 				||	(!!depthClampEnableConfig.dynamicValue)
2118 				||	(!!polygonModeConfig.dynamicValue)
2119 				||	(!!sampleMaskConfig.dynamicValue)
2120 				||	(!!alphaToCoverageConfig.dynamicValue)
2121 				||	(!!alphaToOneConfig.dynamicValue)
2122 				||	(!!colorWriteMaskConfig.dynamicValue)
2123 				||	(!!rasterizationStreamConfig.dynamicValue)
2124 				||	(!!logicOpEnableConfig.dynamicValue)
2125 				||	(!!colorBlendEnableConfig.dynamicValue)
2126 				||	(!!colorBlendEquationConfig.dynamicValue)
2127 				||	(!!provokingVertexConfig.dynamicValue)
2128 				||	(!!negativeOneToOneConfig.dynamicValue)
2129 				||	(!!depthClipEnableConfig.dynamicValue)
2130 				||	(!!lineStippleEnableConfig.dynamicValue)
2131 				||	(!!sampleLocationsEnableConfig.dynamicValue)
2132 				||	(!!conservativeRasterModeConfig.dynamicValue)
2133 				||	(!!extraPrimitiveOverEstConfig.dynamicValue)
2134 				||	(!!lineRasterModeConfig.dynamicValue)
2135 				||	(!!coverageToColorEnableConfig.dynamicValue)
2136 				||	(!!coverageToColorLocationConfig.dynamicValue)
2137 				||	(!!rasterizationSamplesConfig.dynamicValue)
2138 #ifndef CTS_USES_VULKANSC
2139 				||	(!!coverageModulationModeConfig.dynamicValue)
2140 				||	(!!coverageModTableEnableConfig.dynamicValue)
2141 				||	(!!coverageModTableConfig.dynamicValue)
2142 				||	(!!coverageReductionModeConfig.dynamicValue)
2143 				||	(!!viewportSwizzleConfig.dynamicValue)
2144 				||	(!!shadingRateImageEnableConfig.dynamicValue)
2145 				||	(!!viewportWScalingEnableConfig.dynamicValue)
2146 				||	(!!reprFragTestEnableConfig.dynamicValue)
2147 #endif // CTS_USES_VULKANSC
2148 				);
2149 	}
2150 
2151 	// Returns the appropriate color image format for the test.
colorFormatvkt::pipeline::__anonaa66a09e0111::TestConfig2152 	vk::VkFormat colorFormat () const
2153 	{
2154 		// Pick int color format when testing logic op dynamic states.
2155 		if (testLogicOp() || testLogicOpEnable())
2156 			return kIntColorFormat;
2157 
2158 		// Pick special color format for coverage to color.
2159 		if (coverageToColorStruct())
2160 			return kIntRedColorFormat;
2161 
2162 		return kUnormColorFormat;
2163 	}
2164 
2165 	// Get used color sample count.
getColorSampleCountvkt::pipeline::__anonaa66a09e0111::TestConfig2166 	vk::VkSampleCountFlagBits getColorSampleCount () const
2167 	{
2168 		const auto usedColorSampleCount	= ((coverageModulation || coverageReduction)
2169 										? colorSampleCount.get()
2170 										: getActiveSampleCount());
2171 		return usedColorSampleCount;
2172 	}
2173 
2174 	// Returns the list of dynamic states affected by this config.
getDynamicStatesvkt::pipeline::__anonaa66a09e0111::TestConfig2175 	std::vector<vk::VkDynamicState> getDynamicStates () const
2176 	{
2177 		std::vector<vk::VkDynamicState> dynamicStates;
2178 
2179 		if (depthBiasConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS);
2180 		if (cullModeConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
2181 		if (frontFaceConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
2182 		if (topologyConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
2183 		if (viewportConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT);
2184 		if (scissorConfig.dynamicValue)					dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT);
2185 		if (strideConfig.dynamicValue)					dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
2186 		if (depthTestEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
2187 		if (depthWriteEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
2188 		if (depthCompareOpConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
2189 		if (depthBoundsTestEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
2190 		if (stencilTestEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
2191 		if (stencilOpConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
2192 		if (vertexGenerator.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
2193 		if (patchControlPointsConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
2194 		if (rastDiscardEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT);
2195 		if (depthBiasEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT);
2196 		if (logicOpConfig.dynamicValue)					dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
2197 		if (primRestartEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT);
2198 #ifndef CTS_USES_VULKANSC
2199 		if (tessDomainOriginConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
2200 		if (depthClampEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
2201 		if (polygonModeConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
2202 		if (sampleMaskConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
2203 		if (alphaToCoverageConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
2204 		if (alphaToOneConfig.dynamicValue)				dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
2205 		if (colorWriteMaskConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
2206 		if (rasterizationStreamConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
2207 		if (logicOpEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
2208 		if (colorBlendEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
2209 		if (colorBlendEquationConfig.dynamicValue)		dynamicStates.push_back(colorBlendEquationConfig.staticValue.isAdvanced()
2210 															? vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT
2211 															: vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
2212 		if (provokingVertexConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
2213 		if (negativeOneToOneConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
2214 		if (depthClipEnableConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
2215 		if (lineStippleEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
2216 		if (lineStippleParamsConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
2217 		if (sampleLocationsEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
2218 		if (conservativeRasterModeConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
2219 		if (extraPrimitiveOverEstConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
2220 		if (lineRasterModeConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
2221 		if (rasterizationSamplesConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
2222 		if (coverageToColorEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
2223 		if (coverageToColorLocationConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
2224 		if (coverageModulationModeConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
2225 		if (coverageModTableEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
2226 		if (coverageModTableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
2227 		if (coverageReductionModeConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
2228 		if (viewportSwizzleConfig.dynamicValue)			dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
2229 		if (shadingRateImageEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
2230 		if (viewportWScalingEnableConfig.dynamicValue)	dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
2231 		if (reprFragTestEnableConfig.dynamicValue)		dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
2232 #else
2233 		DE_ASSERT(false);
2234 #endif // CTS_USES_VULKANSC
2235 
2236 		return dynamicStates;
2237 	}
2238 
2239 #ifndef CTS_USES_VULKANSC
2240 	// Returns true if the test configuration uses dynamic states which are incompatible with mesh shading pipelines.
badMeshShadingPipelineDynStatevkt::pipeline::__anonaa66a09e0111::TestConfig2241 	bool badMeshShadingPipelineDynState () const
2242 	{
2243 		const auto states = getDynamicStates();
2244 		return std::any_of(begin(states), end(states), isMeshShadingPipelineIncompatible);
2245 	}
2246 #endif // CTS_USES_VULKANSC
2247 
testEDSvkt::pipeline::__anonaa66a09e0111::TestConfig2248 	bool testEDS() const
2249 	{
2250 		return (cullModeConfig.dynamicValue
2251 			|| frontFaceConfig.dynamicValue
2252 			|| topologyConfig.dynamicValue
2253 			|| viewportConfig.dynamicValue
2254 			|| scissorConfig.dynamicValue
2255 			|| strideConfig.dynamicValue
2256 			|| depthTestEnableConfig.dynamicValue
2257 			|| depthWriteEnableConfig.dynamicValue
2258 			|| depthCompareOpConfig.dynamicValue
2259 			|| depthBoundsTestEnableConfig.dynamicValue
2260 			|| stencilTestEnableConfig.dynamicValue
2261 			|| stencilOpConfig.dynamicValue);
2262 	}
2263 
testEDS2vkt::pipeline::__anonaa66a09e0111::TestConfig2264 	bool testEDS2() const
2265 	{
2266 		return (rastDiscardEnableConfig.dynamicValue
2267 			|| depthBiasEnableConfig.dynamicValue
2268 			|| primRestartEnableConfig.dynamicValue
2269 			|| useExtraDynPCPPipeline);
2270 	}
2271 
testVertexDynamicvkt::pipeline::__anonaa66a09e0111::TestConfig2272 	bool testVertexDynamic() const
2273 	{
2274 		return static_cast<bool>(vertexGenerator.dynamicValue);
2275 	}
2276 
2277 	// Returns the list of extensions needed by this config. Note some other
2278 	// requirements are checked with feature structs, which is particularly
2279 	// important for extensions which have been partially promoted, like EDS
2280 	// and EDS2. Extensions requested here have not been partially promoted.
getRequiredExtensionsvkt::pipeline::__anonaa66a09e0111::TestConfig2281 	std::vector<std::string> getRequiredExtensions () const
2282 	{
2283 		std::vector<std::string> extensions;
2284 
2285 		if (needsEDS3())
2286 		{
2287 			extensions.push_back("VK_EXT_extended_dynamic_state3");
2288 		}
2289 
2290 		if (testTessellationDomainOrigin() || getActiveTessellationDomainOrigin() != vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
2291 		{
2292 			extensions.push_back("VK_KHR_maintenance2");
2293 		}
2294 
2295 		if (rasterizationStreamStruct())
2296 		{
2297 			extensions.push_back("VK_EXT_transform_feedback");
2298 		}
2299 
2300 		if (provokingVertexStruct())
2301 		{
2302 			extensions.push_back("VK_EXT_provoking_vertex");
2303 		}
2304 
2305 		if (negativeOneToOneStruct())
2306 		{
2307 			extensions.push_back("VK_EXT_depth_clip_control");
2308 		}
2309 
2310 		if (depthClipEnableStruct())
2311 		{
2312 			extensions.push_back("VK_EXT_depth_clip_enable");
2313 		}
2314 
2315 		if (lineRasterizationExt())
2316 		{
2317 			extensions.push_back("VK_EXT_line_rasterization");
2318 		}
2319 
2320 		if (colorBlendEquationConfig.staticValue.isAdvanced())
2321 		{
2322 			extensions.push_back("VK_EXT_blend_operation_advanced");
2323 		}
2324 
2325 		if (sampleLocationsStruct())
2326 		{
2327 			extensions.push_back("VK_EXT_sample_locations");
2328 		}
2329 
2330 		if (coverageToColorStruct())
2331 		{
2332 			extensions.push_back("VK_NV_fragment_coverage_to_color");
2333 		}
2334 
2335 		if (conservativeRasterStruct() || static_cast<bool>(maxPrimitiveOverestimationSize))
2336 		{
2337 			extensions.push_back("VK_EXT_conservative_rasterization");
2338 		}
2339 
2340 		if (coverageModulation)
2341 		{
2342 			extensions.push_back("VK_NV_framebuffer_mixed_samples");
2343 		}
2344 
2345 		if (coverageReduction)
2346 		{
2347 			extensions.push_back("VK_NV_coverage_reduction_mode");
2348 		}
2349 
2350 		if (viewportSwizzle)
2351 		{
2352 			extensions.push_back("VK_NV_viewport_swizzle");
2353 		}
2354 
2355 		if (shadingRateImage)
2356 		{
2357 			extensions.push_back("VK_NV_shading_rate_image");
2358 		}
2359 
2360 		if (viewportWScaling)
2361 		{
2362 			extensions.push_back("VK_NV_clip_space_w_scaling");
2363 		}
2364 
2365 		if (representativeFragmentTest)
2366 		{
2367 			extensions.push_back("VK_NV_representative_fragment_test");
2368 		}
2369 
2370 		return extensions;
2371 	}
2372 
getFragDescriptorSetIndexvkt::pipeline::__anonaa66a09e0111::TestConfig2373 	uint32_t getFragDescriptorSetIndex () const
2374 	{
2375 		return (useMeshShaders ? 1u : 0u);
2376 	}
2377 
2378 private:
2379 	// Extended dynamic state cases as created by createExtendedDynamicStateTests() are based on the assumption that, when a state
2380 	// has a static and a dynamic value configured at the same time, the static value is wrong and the dynamic value will give
2381 	// expected results. That's appropriate for most test variants, but in some others we want to reverse the situation: a dynamic
2382 	// pipeline with wrong values and a static one with good values.
2383 	//
2384 	// Instead of modifying how tests are created, we use isReversed() and swapValues() above, allowing us to swap static and
2385 	// 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
2386 	// given point in time in order to correctly answer some questions while running the test. m_swappedValues tracks that state.
2387 	bool m_swappedValues;
2388 };
2389 
2390 struct PushConstants
2391 {
2392 	tcu::Vec4	triangleColor;
2393 	float		meshDepth;
2394 	deInt32		viewPortIndex;
2395 	float		scaleX;
2396 	float		scaleY;
2397 	float		offsetX;
2398 	float		offsetY;
2399 	float		stripScale;
2400 };
2401 
copy(vk::VkStencilOpState & dst,const StencilOpParams & src)2402 void copy(vk::VkStencilOpState& dst, const StencilOpParams& src)
2403 {
2404 	dst.failOp		= src.failOp;
2405 	dst.passOp		= src.passOp;
2406 	dst.depthFailOp	= src.depthFailOp;
2407 	dst.compareOp	= src.compareOp;
2408 }
2409 
makeImageCreateInfo(vk::VkFormat format,vk::VkExtent3D extent,vk::VkSampleCountFlagBits sampleCount,vk::VkImageUsageFlags usage,vk::VkImageCreateFlags createFlags)2410 vk::VkImageCreateInfo makeImageCreateInfo (vk::VkFormat format, vk::VkExtent3D extent, vk::VkSampleCountFlagBits sampleCount, vk::VkImageUsageFlags usage, vk::VkImageCreateFlags createFlags)
2411 {
2412 	const vk::VkImageCreateInfo imageCreateInfo =
2413 	{
2414 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2415 		nullptr,									//	const void*				pNext;
2416 		createFlags,								//	VkImageCreateFlags		flags;
2417 		vk::VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2418 		format,										//	VkFormat				format;
2419 		extent,										//	VkExtent3D				extent;
2420 		1u,											//	deUint32				mipLevels;
2421 		1u,											//	deUint32				arrayLayers;
2422 		sampleCount,								//	VkSampleCountFlagBits	samples;
2423 		vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2424 		usage,										//	VkImageUsageFlags		usage;
2425 		vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2426 		0u,											//	deUint32				queueFamilyIndexCount;
2427 		nullptr,									//	const deUint32*			pQueueFamilyIndices;
2428 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2429 	};
2430 
2431 	return imageCreateInfo;
2432 }
2433 
2434 class ExtendedDynamicStateTest : public vkt::TestCase
2435 {
2436 public:
2437 							ExtendedDynamicStateTest		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig);
~ExtendedDynamicStateTest(void)2438 	virtual					~ExtendedDynamicStateTest		(void) {}
2439 
2440 	virtual void			checkSupport					(Context& context) const;
2441 	virtual void			initPrograms					(vk::SourceCollections& programCollection) const;
2442 	virtual TestInstance*	createInstance					(Context& context) const;
2443 
2444 private:
2445 	TestConfig				m_testConfig;
2446 };
2447 
2448 class ExtendedDynamicStateInstance : public vkt::TestInstance
2449 {
2450 public:
2451 								ExtendedDynamicStateInstance	(Context& context, const TestConfig& testConfig);
~ExtendedDynamicStateInstance(void)2452 	virtual						~ExtendedDynamicStateInstance	(void) {}
2453 
2454 	virtual tcu::TestStatus		iterate							(void);
2455 
2456 private:
2457 	TestConfig					m_testConfig;
2458 };
2459 
ExtendedDynamicStateTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestConfig & testConfig)2460 ExtendedDynamicStateTest::ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig)
2461 	: vkt::TestCase	(testCtx, name, description)
2462 	, m_testConfig	(testConfig)
2463 {
2464 	const auto staticTopologyClass = getTopologyClass(testConfig.topologyConfig.staticValue);
2465 	DE_UNREF(staticTopologyClass); // For release builds.
2466 
2467 	// Matching topology classes.
2468 	DE_ASSERT(!testConfig.topologyConfig.dynamicValue ||
2469 			  staticTopologyClass == getTopologyClass(testConfig.topologyConfig.dynamicValue.get()));
2470 
2471 	// Supported topology classes for these tests.
2472 	DE_ASSERT(staticTopologyClass == TopologyClass::LINE || staticTopologyClass == TopologyClass::TRIANGLE
2473 		|| staticTopologyClass == TopologyClass::PATCH);
2474 
2475 	// Make sure these are consistent.
2476 	DE_ASSERT(!(m_testConfig.testPatchControlPoints() && !m_testConfig.patchesTopology()));
2477 	DE_ASSERT(!(m_testConfig.patchesTopology() && m_testConfig.getActivePatchControlPoints() <= 1u));
2478 
2479 	// Do not use an extra dynamic patch control points pipeline if we're not testing them.
2480 	DE_ASSERT(!m_testConfig.useExtraDynPCPPipeline || m_testConfig.testPatchControlPoints());
2481 }
2482 
checkSupport(Context & context) const2483 void ExtendedDynamicStateTest::checkSupport (Context& context) const
2484 {
2485 	const auto&	vki				= context.getInstanceInterface();
2486 	const auto	physicalDevice	= context.getPhysicalDevice();
2487 
2488 	// Check feature support.
2489 	const auto& edsFeatures		= context.getExtendedDynamicStateFeaturesEXT();
2490 	const auto& eds2Features	= context.getExtendedDynamicState2FeaturesEXT();
2491 	const auto& viFeatures		= context.getVertexInputDynamicStateFeaturesEXT();
2492 #ifndef CTS_USES_VULKANSC
2493 	const auto& meshFeatures	= context.getMeshShaderFeaturesEXT();
2494 #endif // CTS_USES_VULKANSC
2495 
2496 	if (m_testConfig.testEDS() && !edsFeatures.extendedDynamicState)
2497 		TCU_THROW(NotSupportedError, "extendedDynamicState is not supported");
2498 
2499 	if (m_testConfig.testEDS2() && !eds2Features.extendedDynamicState2)
2500 		TCU_THROW(NotSupportedError, "extendedDynamicState2 is not supported");
2501 
2502 	if (m_testConfig.testLogicOp() && !eds2Features.extendedDynamicState2LogicOp)
2503 		TCU_THROW(NotSupportedError, "extendedDynamicState2LogicOp is not supported");
2504 
2505 	if ((m_testConfig.testPatchControlPoints() || m_testConfig.useExtraDynPCPPipeline) && !eds2Features.extendedDynamicState2PatchControlPoints)
2506 		TCU_THROW(NotSupportedError, "extendedDynamicState2PatchControlPoints is not supported");
2507 
2508 	if (m_testConfig.testVertexDynamic() && !viFeatures.vertexInputDynamicState)
2509 		TCU_THROW(NotSupportedError, "vertexInputDynamicState is not supported");
2510 
2511 #ifndef CTS_USES_VULKANSC
2512 	if ((m_testConfig.useMeshShaders || m_testConfig.bindUnusedMeshShadingPipeline) && !meshFeatures.meshShader)
2513 		TCU_THROW(NotSupportedError, "meshShader is not supported");
2514 #endif // CTS_USES_VULKANSC
2515 
2516 	// Check extension support.
2517 	const auto requiredExtensions = m_testConfig.getRequiredExtensions();
2518 	for (const auto& extension : requiredExtensions)
2519 		context.requireDeviceFunctionality(extension);
2520 
2521 	// Special requirement for rasterizationSamples tests.
2522 	// The first iteration of these tests puts the pipeline in a mixed samples state,
2523 	// where colorCount != rasterizationSamples.
2524 	if (m_testConfig.rasterizationSamplesConfig.dynamicValue &&
2525 		(m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
2526 		 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC) &&
2527 		!context.isDeviceFunctionalitySupported("VK_AMD_mixed_attachment_samples") &&
2528 		!context.isDeviceFunctionalitySupported("VK_NV_framebuffer_mixed_samples"))
2529 
2530 		TCU_THROW(NotSupportedError, "VK_AMD_mixed_attachment_samples or VK_NV_framebuffer_mixed_samples are not supported");
2531 
2532 	if (m_testConfig.rasterizationSamplesConfig.dynamicValue &&
2533 		(m_testConfig.sequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES ||
2534 		 m_testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES ||
2535 		 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
2536 		 m_testConfig.isReversed()) &&
2537 		(context.isDeviceFunctionalitySupported("VK_AMD_mixed_attachment_samples") ||
2538 		context.isDeviceFunctionalitySupported("VK_NV_framebuffer_mixed_samples")))
2539 
2540 		TCU_THROW(NotSupportedError, "Test not supported with VK_AMD_mixed_attachment_samples or VK_NV_framebuffer_mixed_samples");
2541 
2542 	// Check the number of viewports needed and the corresponding limits.
2543 	const auto&	viewportConfig	= m_testConfig.viewportConfig;
2544 	auto		numViewports	= viewportConfig.staticValue.size();
2545 
2546 	if (viewportConfig.dynamicValue)
2547 		numViewports = std::max(numViewports, viewportConfig.dynamicValue.get().size());
2548 
2549 	if (numViewports > 1)
2550 	{
2551 		const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
2552 		if (numViewports > static_cast<decltype(numViewports)>(properties.limits.maxViewports))
2553 			TCU_THROW(NotSupportedError, "Number of viewports not supported (" + de::toString(numViewports) + ")");
2554 	}
2555 
2556 	const auto&	dbTestEnable	= m_testConfig.depthBoundsTestEnableConfig;
2557 	const bool	useDepthBounds	= (dbTestEnable.staticValue || (dbTestEnable.dynamicValue && dbTestEnable.dynamicValue.get()));
2558 
2559 	if (useDepthBounds || m_testConfig.needsGeometryShader() || m_testConfig.needsTessellation() || m_testConfig.needsDepthBiasClampFeature())
2560 	{
2561 		const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
2562 
2563 		// Check depth bounds test support.
2564 		if (useDepthBounds && !features.depthBounds)
2565 			TCU_THROW(NotSupportedError, "Depth bounds feature not supported");
2566 
2567 		// Check geometry shader support.
2568 		if (m_testConfig.needsGeometryShader() && !features.geometryShader)
2569 			TCU_THROW(NotSupportedError, "Geometry shader not supported");
2570 
2571 		// Check tessellation support
2572 		if (m_testConfig.needsTessellation() && !features.tessellationShader)
2573 			TCU_THROW(NotSupportedError, "Tessellation feature not supported");
2574 
2575 		// Check depth bias clamp feature.
2576 		if (m_testConfig.needsDepthBiasClampFeature() && !features.depthBiasClamp)
2577 			TCU_THROW(NotSupportedError, "Depth bias clamp not supported");
2578 	}
2579 
2580 	// Check color image format support (depth/stencil will be chosen and checked at runtime).
2581 	{
2582 		const auto colorFormat		= m_testConfig.colorFormat();
2583 		const auto colorSampleCount	= m_testConfig.getColorSampleCount();
2584 		const auto colorImageInfo	= makeImageCreateInfo(colorFormat, kFramebufferExtent, colorSampleCount, kColorUsage, 0u);
2585 
2586 		vk::VkImageFormatProperties formatProps;
2587 		const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, colorImageInfo.format, colorImageInfo.imageType, colorImageInfo.tiling, colorImageInfo.usage, colorImageInfo.flags, &formatProps);
2588 
2589 		if (result != vk::VK_SUCCESS)
2590 			TCU_THROW(NotSupportedError, "Required color image features not supported");
2591 
2592 		if ((formatProps.sampleCounts & colorSampleCount) != colorSampleCount)
2593 			TCU_THROW(NotSupportedError, "Required color sample count not supported");
2594 	}
2595 
2596 	// Extended dynamic state 3 features.
2597 	if (m_testConfig.needsEDS3())
2598 	{
2599 #ifndef CTS_USES_VULKANSC
2600 		const auto& eds3Features = context.getExtendedDynamicState3FeaturesEXT();
2601 
2602 		if (m_testConfig.testTessellationDomainOrigin() && !eds3Features.extendedDynamicState3TessellationDomainOrigin)
2603 			TCU_THROW(NotSupportedError, "extendedDynamicState3TessellationDomainOrigin not supported");
2604 
2605 		if (m_testConfig.depthClampEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3DepthClampEnable)
2606 			TCU_THROW(NotSupportedError, "extendedDynamicState3DepthClampEnable not supported");
2607 
2608 		if (m_testConfig.polygonModeConfig.dynamicValue && !eds3Features.extendedDynamicState3PolygonMode)
2609 			TCU_THROW(NotSupportedError, "extendedDynamicState3PolygonMode not supported");
2610 
2611 		if (m_testConfig.sampleMaskConfig.dynamicValue && !eds3Features.extendedDynamicState3SampleMask)
2612 			TCU_THROW(NotSupportedError, "extendedDynamicState3SampleMask not supported");
2613 
2614 		if (m_testConfig.alphaToCoverageConfig.dynamicValue && !eds3Features.extendedDynamicState3AlphaToCoverageEnable)
2615 			TCU_THROW(NotSupportedError, "extendedDynamicState3AlphaToCoverageEnable not supported");
2616 
2617 		if (m_testConfig.alphaToOneConfig.dynamicValue && !eds3Features.extendedDynamicState3AlphaToOneEnable)
2618 			TCU_THROW(NotSupportedError, "extendedDynamicState3AlphaToOneEnable not supported");
2619 
2620 		if (m_testConfig.colorWriteMaskConfig.dynamicValue && !eds3Features.extendedDynamicState3ColorWriteMask)
2621 			TCU_THROW(NotSupportedError, "extendedDynamicState3ColorWriteMask not supported");
2622 
2623 		if (m_testConfig.rasterizationStreamConfig.dynamicValue && !eds3Features.extendedDynamicState3RasterizationStream)
2624 			TCU_THROW(NotSupportedError, "extendedDynamicState3RasterizationStream not supported");
2625 
2626 		if (m_testConfig.logicOpEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3LogicOpEnable)
2627 			TCU_THROW(NotSupportedError, "extendedDynamicState3LogicOpEnable not supported");
2628 
2629 		if (m_testConfig.colorBlendEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3ColorBlendEnable)
2630 			TCU_THROW(NotSupportedError, "extendedDynamicState3ColorBlendEnable not supported");
2631 
2632 		if (m_testConfig.colorBlendEquationConfig.dynamicValue)
2633 		{
2634 			if (m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced())
2635 			{
2636 				if (!eds3Features.extendedDynamicState3ColorBlendAdvanced)
2637 					TCU_THROW(NotSupportedError, "extendedDynamicState3ColorBlendAdvanced not supported");
2638 			}
2639 			else
2640 			{
2641 				if (!eds3Features.extendedDynamicState3ColorBlendEquation)
2642 					TCU_THROW(NotSupportedError, "extendedDynamicState3ColorBlendEquation not supported");
2643 			}
2644 		}
2645 
2646 		if (m_testConfig.provokingVertexConfig.dynamicValue && !eds3Features.extendedDynamicState3ProvokingVertexMode)
2647 			TCU_THROW(NotSupportedError, "extendedDynamicState3ProvokingVertexMode not supported");
2648 
2649 		if (m_testConfig.negativeOneToOneConfig.dynamicValue && !eds3Features.extendedDynamicState3DepthClipNegativeOneToOne)
2650 			TCU_THROW(NotSupportedError, "extendedDynamicState3DepthClipNegativeOneToOne not supported");
2651 
2652 		if (m_testConfig.depthClipEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3DepthClipEnable)
2653 			TCU_THROW(NotSupportedError, "extendedDynamicState3DepthClipEnable not supported");
2654 
2655 		if (m_testConfig.lineStippleEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3LineStippleEnable)
2656 			TCU_THROW(NotSupportedError, "extendedDynamicState3LineStippleEnable not supported");
2657 
2658 		if (m_testConfig.sampleLocationsEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3SampleLocationsEnable)
2659 			TCU_THROW(NotSupportedError, "extendedDynamicState3SampleLocationsEnable not supported");
2660 
2661 		if (m_testConfig.conservativeRasterModeConfig.dynamicValue && !eds3Features.extendedDynamicState3ConservativeRasterizationMode)
2662 			TCU_THROW(NotSupportedError, "extendedDynamicState3ConservativeRasterizationMode not supported");
2663 
2664 		if (m_testConfig.extraPrimitiveOverEstConfig.dynamicValue && !eds3Features.extendedDynamicState3ExtraPrimitiveOverestimationSize)
2665 			TCU_THROW(NotSupportedError, "extendedDynamicState3ExtraPrimitiveOverestimationSize not supported");
2666 
2667 		if (m_testConfig.lineRasterModeConfig.dynamicValue && !eds3Features.extendedDynamicState3LineRasterizationMode)
2668 			TCU_THROW(NotSupportedError, "extendedDynamicState3LineRasterizationMode not supported");
2669 
2670 		if (m_testConfig.coverageToColorEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageToColorEnable)
2671 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageToColorEnable not supported");
2672 
2673 		if (m_testConfig.coverageToColorLocationConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageToColorLocation)
2674 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageToColorLocation not supported");
2675 
2676 		if (m_testConfig.coverageModulationModeConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageModulationMode)
2677 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageModulationMode not supported");
2678 
2679 		if (m_testConfig.coverageModTableEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageModulationTableEnable)
2680 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageModulationTableEnable not supported");
2681 
2682 		if (m_testConfig.coverageModTableConfig.dynamicValue && !eds3Features.extendedDynamicState3CoverageModulationTable)
2683 			TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageModulationTable not supported");
2684 
2685 		if (m_testConfig.coverageReductionModeConfig.dynamicValue)
2686 		{
2687 			if (!eds3Features.extendedDynamicState3CoverageReductionMode)
2688 				TCU_THROW(NotSupportedError, "extendedDynamicState3CoverageReductionMode not supported");
2689 
2690 			uint32_t combinationCount = 0U;
2691 			auto result = vki.getPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(physicalDevice, &combinationCount, nullptr);
2692 			if (result != vk::VK_SUCCESS || combinationCount == 0U)
2693 				TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV supported no combinations");
2694 
2695 			std::vector<vk::VkFramebufferMixedSamplesCombinationNV> combinations(combinationCount);
2696 			for (auto& combination : combinations)
2697 				combination = vk::initVulkanStructure();
2698 			result = vki.getPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(physicalDevice, &combinationCount, combinations.data());
2699 			if (result != vk::VK_SUCCESS)
2700 				TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV supported no combinations");
2701 
2702 			auto findCombination = [&](vk::VkCoverageReductionModeNV const coverageReductionMode) -> bool {
2703 				for (uint32_t i = 0U; i < combinationCount; ++i) {
2704 					if (combinations[i].rasterizationSamples == m_testConfig.rasterizationSamplesConfig.staticValue &&
2705 						combinations[i].colorSamples == m_testConfig.getColorSampleCount() &&
2706 						combinations[i].coverageReductionMode == coverageReductionMode) {
2707 
2708 						return true;
2709 					}
2710 				}
2711 				return false;
2712 			};
2713 			if (!findCombination(m_testConfig.coverageReductionModeConfig.staticValue) || !findCombination(m_testConfig.coverageReductionModeConfig.dynamicValue.get()))
2714 				TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV no matching combination found");
2715 		}
2716 
2717 		if (m_testConfig.viewportSwizzleConfig.dynamicValue && !eds3Features.extendedDynamicState3ViewportSwizzle)
2718 			TCU_THROW(NotSupportedError, "extendedDynamicState3ViewportSwizzle not supported");
2719 
2720 		if (m_testConfig.shadingRateImageEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3ShadingRateImageEnable)
2721 			TCU_THROW(NotSupportedError, "extendedDynamicState3ShadingRateImageEnable not supported");
2722 
2723 		if (m_testConfig.viewportWScalingEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3ViewportWScalingEnable)
2724 			TCU_THROW(NotSupportedError, "extendedDynamicState3ViewportWScalingEnable not supported");
2725 
2726 		if (m_testConfig.reprFragTestEnableConfig.dynamicValue && !eds3Features.extendedDynamicState3RepresentativeFragmentTestEnable)
2727 			TCU_THROW(NotSupportedError, "extendedDynamicState3RepresentativeFragmentTestEnable not supported");
2728 
2729 		if (m_testConfig.rasterizationSamplesConfig.dynamicValue && !eds3Features.extendedDynamicState3RasterizationSamples)
2730 			TCU_THROW(NotSupportedError, "extendedDynamicState3RasterizationSamples not supported");
2731 #else
2732 		TCU_THROW(NotSupportedError, "VulkanSC does not support extended dynamic state 3");
2733 #endif // CTS_USES_VULKANSC
2734 	}
2735 
2736 	if (m_testConfig.getActivePolygonMode() != vk::VK_POLYGON_MODE_FILL)
2737 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FILL_MODE_NON_SOLID);
2738 
2739 	if (m_testConfig.getActiveAlphaToOne())
2740 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_ALPHA_TO_ONE);
2741 
2742 	if (m_testConfig.rasterizationStreamStruct() || static_cast<bool>(m_testConfig.shaderRasterizationStream))
2743 	{
2744 #ifndef CTS_USES_VULKANSC
2745 		const auto& xfProperties = context.getTransformFeedbackPropertiesEXT();
2746 		if (!xfProperties.transformFeedbackRasterizationStreamSelect)
2747 			TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect not supported");
2748 
2749 		// VUID-RuntimeSpirv-Stream-06312
2750 		if (static_cast<bool>(m_testConfig.shaderRasterizationStream))
2751 		{
2752 			const auto shaderStreamId = m_testConfig.shaderRasterizationStream.get();
2753 			if (shaderStreamId >= xfProperties.maxTransformFeedbackStreams)
2754 				TCU_THROW(NotSupportedError, "Geometry shader rasterization stream above maxTransformFeedbackStreams limit");
2755 		}
2756 
2757 		// VUID-VkPipelineRasterizationStateStreamCreateInfoEXT-rasterizationStream-02325
2758 		if (static_cast<bool>(m_testConfig.rasterizationStreamConfig.staticValue))
2759 		{
2760 			const auto staticStreamId = m_testConfig.rasterizationStreamConfig.staticValue.get();
2761 			if (staticStreamId >= xfProperties.maxTransformFeedbackStreams)
2762 				TCU_THROW(NotSupportedError, "Static stream number above maxTransformFeedbackStreams limit");
2763 		}
2764 		if (static_cast<bool>(m_testConfig.rasterizationStreamConfig.dynamicValue && static_cast<bool>(m_testConfig.rasterizationStreamConfig.dynamicValue.get())))
2765 		{
2766 			const auto dynamicStreamId = m_testConfig.rasterizationStreamConfig.dynamicValue->get();
2767 			if (dynamicStreamId >= xfProperties.maxTransformFeedbackStreams)
2768 				TCU_THROW(NotSupportedError, "Dynamic stream number above maxTransformFeedbackStreams limit");
2769 		}
2770 #else
2771 		TCU_THROW(NotSupportedError, "VulkanSC does not support VK_EXT_transform_feedback");
2772 #endif // CTS_USES_VULKANSC
2773 	}
2774 
2775 	if (m_testConfig.lineRasterizationExt())
2776 	{
2777 		// Check the implementation supports some type of stippled line.
2778 		const auto&	lineRastFeatures	= context.getLineRasterizationFeaturesEXT();
2779 		const auto	rasterMode			= selectLineRasterizationMode(lineRastFeatures, m_testConfig.lineStippleSupportRequired(), m_testConfig.lineRasterModeConfig.staticValue);
2780 
2781 		if (rasterMode == LineRasterizationMode::NONE)
2782 			TCU_THROW(NotSupportedError, "Wanted static line rasterization mode not supported");
2783 
2784 		if (static_cast<bool>(m_testConfig.lineRasterModeConfig.dynamicValue) && static_cast<bool>(m_testConfig.lineRasterModeConfig.dynamicValue.get()))
2785 		{
2786 			const auto dynRasterMode = selectLineRasterizationMode(lineRastFeatures, m_testConfig.lineStippleSupportRequired(), m_testConfig.lineRasterModeConfig.dynamicValue.get());
2787 
2788 			if (dynRasterMode == LineRasterizationMode::NONE)
2789 				TCU_THROW(NotSupportedError, "Wanted dynamic line rasterization mode not supported");
2790 		}
2791 	}
2792 
2793 	const auto hasMaxPrimitiveOverestimationSize = static_cast<bool>(m_testConfig.maxPrimitiveOverestimationSize);
2794 
2795 	if (m_testConfig.conservativeRasterStruct() || hasMaxPrimitiveOverestimationSize)
2796 	{
2797 		const auto& conservativeRasterModeProps = context.getConservativeRasterizationPropertiesEXT();
2798 
2799 		if (m_testConfig.getActiveConservativeRasterMode() == vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT && !conservativeRasterModeProps.primitiveUnderestimation)
2800 			TCU_THROW(NotSupportedError, "primitiveUnderestimation not supported");
2801 
2802 		const auto	extraSize	= m_testConfig.getActiveExtraPrimitiveOverEstSize();
2803 		const auto&	maxExtra	= conservativeRasterModeProps.maxExtraPrimitiveOverestimationSize;
2804 
2805 		if (extraSize >= 0.0f && extraSize > maxExtra)
2806 		{
2807 			std::ostringstream msg;
2808 			msg << "Extra primitive overestimation size (" << extraSize << ") above maxExtraPrimitiveOverestimationSize (" << maxExtra << ")";
2809 			TCU_THROW(NotSupportedError, msg.str());
2810 		}
2811 
2812 		if (hasMaxPrimitiveOverestimationSize)
2813 		{
2814 			const auto maxPrimitiveOverestimationSizeVal = m_testConfig.maxPrimitiveOverestimationSize.get();
2815 			if (conservativeRasterModeProps.primitiveOverestimationSize > maxPrimitiveOverestimationSizeVal)
2816 			{
2817 				std::ostringstream msg;
2818 				msg << "primitiveOverestimationSize (" << conservativeRasterModeProps.primitiveOverestimationSize
2819 					<< ") too big for this test (max " << maxPrimitiveOverestimationSizeVal << ")";
2820 				TCU_THROW(NotSupportedError, msg.str());
2821 			}
2822 		}
2823 	}
2824 
2825 	if (m_testConfig.representativeFragmentTest)
2826 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
2827 
2828 	checkPipelineLibraryRequirements(vki, physicalDevice, m_testConfig.pipelineConstructionType);
2829 }
2830 
initPrograms(vk::SourceCollections & programCollection) const2831 void ExtendedDynamicStateTest::initPrograms (vk::SourceCollections& programCollection) const
2832 {
2833 	const vk::ShaderBuildOptions meshBuildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
2834 
2835 	std::ostringstream pushSource;
2836 	std::ostringstream fragOutputLocationStream;
2837 	std::ostringstream vertSourceTemplateStream;
2838 	std::ostringstream fragSourceTemplateStream;
2839 	std::ostringstream geomSource;
2840 	std::ostringstream tescSource;
2841 	std::ostringstream teseSource;
2842 	std::ostringstream meshSource;
2843 
2844 	pushSource
2845 		<< "layout(push_constant, std430) uniform PushConstantsBlock {\n"
2846 		<< "    vec4  triangleColor;\n"
2847 		<< "    float depthValue;\n"
2848 		<< "    int   viewPortIndex;\n"
2849 		<< "    float scaleX;\n"
2850 		<< "    float scaleY;\n"
2851 		<< "    float offsetX;\n"
2852 		<< "    float offsetY;\n"
2853 		<< "    float stripScale;\n"
2854 		<< "} pushConstants;\n"
2855 		;
2856 	const auto pushConstants = pushSource.str();
2857 
2858 	for (uint32_t refIdx = 0; refIdx < m_testConfig.colorAttachmentCount; ++refIdx)
2859 	{
2860 		const bool used = (refIdx == m_testConfig.colorAttachmentCount - 1u);
2861 		const std::string attName = (used ? "color" : "unused" + std::to_string(refIdx));
2862 		fragOutputLocationStream << "layout(location=" << refIdx << ") out ${OUT_COLOR_VTYPE} " << attName << ";\n";
2863 	}
2864 	const auto fragOutputLocations = fragOutputLocationStream.str();
2865 
2866 	// The actual generator, attributes and calculations.
2867 	const auto			activeGen	= m_testConfig.getActiveVertexGenerator();
2868 	const auto			attribDecls	= activeGen->getAttributeDeclarations();
2869 	const auto			coordCalcs	= activeGen->getVertexCoordCalc();
2870 	const auto			descDeclsV	= activeGen->getDescriptorDeclarations();
2871 	const auto			descCalcsV	= activeGen->getDescriptorCoordCalc();
2872 	const auto			fragInputs	= activeGen->getFragInputAttributes();
2873 	const auto			fragCalcs	= activeGen->getFragOutputCalc();
2874 
2875 	// The static generator, attributes and calculations, for the static pipeline, if needed.
2876 	const auto			inactiveGen			= m_testConfig.getInactiveVertexGenerator();
2877 	const auto			staticAttribDec		= inactiveGen->getAttributeDeclarations();
2878 	const auto			staticCoordCalc		= inactiveGen->getVertexCoordCalc();
2879 	const auto			staticFragInputs	= inactiveGen->getFragInputAttributes();
2880 	const auto			staticFragCalcs		= inactiveGen->getFragOutputCalc();
2881 
2882 	std::ostringstream	activeAttribs;
2883 	std::ostringstream	activeCalcs;
2884 	std::ostringstream	activeFragInputs;
2885 	std::ostringstream	activeFragCalcs;
2886 	std::ostringstream	inactiveAttribs;
2887 	std::ostringstream	inactiveCalcs;
2888 	std::ostringstream	descDecls;
2889 	std::ostringstream	descCalcs;
2890 	std::ostringstream	inactiveFragInputs;
2891 	std::ostringstream	inactiveFragCalcs;
2892 
2893 	for (const auto& decl : attribDecls)
2894 		activeAttribs << decl << "\n";
2895 
2896 	for (const auto& statement : coordCalcs)
2897 		activeCalcs << "    " << statement << "\n";
2898 
2899 	for (const auto& decl : staticAttribDec)
2900 		inactiveAttribs << decl << "\n";
2901 
2902 	for (const auto& statement : staticCoordCalc)
2903 		inactiveCalcs << "    " << statement << "\n";
2904 
2905 	for (const auto& decl : descDeclsV)
2906 		descDecls << decl << "\n";
2907 
2908 	for (const auto& calc : descCalcsV)
2909 		descCalcs << "    " << calc << "\n";
2910 
2911 	for (const auto& decl : fragInputs)
2912 		activeFragInputs << decl << "\n";
2913 
2914 	for (const auto& statement : fragCalcs)
2915 		activeFragCalcs << "    " << statement << "\n";
2916 
2917 	for (const auto& decl : staticFragInputs)
2918 		inactiveFragInputs << decl << "\n";
2919 
2920 	for (const auto& statement : staticFragCalcs)
2921 		inactiveFragCalcs << "    " << statement << "\n";
2922 
2923 	vertSourceTemplateStream
2924 		<< "#version 450\n"
2925 		<< pushConstants
2926 		<< "${ATTRIBUTES}"
2927 		<< "out gl_PerVertex\n"
2928 		<< "{\n"
2929 		<< "    vec4 gl_Position;\n"
2930 		<< "};\n"
2931 		<< "void main() {\n"
2932 		<< "${CALCULATIONS}"
2933 		<< "    gl_Position = vec4(vertexCoords.x * pushConstants.scaleX + pushConstants.offsetX, vertexCoords.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
2934 		<< "    vec2 stripOffset;\n"
2935 		<< "    switch (gl_VertexIndex) {\n"
2936 		<< "    case 0: stripOffset = vec2(0.0, 0.0); break;\n"
2937 		<< "    case 1: stripOffset = vec2(0.0, 1.0); break;\n"
2938 		<< "    case 2: stripOffset = vec2(1.0, 0.0); break;\n"
2939 		<< "    case 3: stripOffset = vec2(1.0, 1.0); break;\n"
2940 		<< "    case 4: stripOffset = vec2(2.0, 0.0); break;\n"
2941 		<< "    case 5: stripOffset = vec2(2.0, 1.0); break;\n"
2942 		<< "    default: stripOffset = vec2(-1000.0); break;\n"
2943 		<< "    }\n"
2944 		<< "    gl_Position.xy += pushConstants.stripScale * stripOffset;\n"
2945 		<< "}\n"
2946 		;
2947 
2948 	tcu::StringTemplate vertSourceTemplate (vertSourceTemplateStream.str());
2949 
2950 	const auto colorFormat	= m_testConfig.colorFormat();
2951 	const auto vecType		= (vk::isUnormFormat(colorFormat) ? "vec4" : "uvec4");
2952 	const auto fragSetIndex	= std::to_string(m_testConfig.getFragDescriptorSetIndex());
2953 
2954 	fragSourceTemplateStream
2955 		<< "#version 450\n"
2956 		<< (m_testConfig.representativeFragmentTest ? "layout(early_fragment_tests) in;\n" : "")
2957 		<< (m_testConfig.representativeFragmentTest ? "layout(set=" + fragSetIndex + ", binding=0, std430) buffer AtomicBlock { uint fragCounter; } counterBuffer;\n" : "")
2958 		<< pushConstants
2959 		<< fragOutputLocations
2960 		<< "${FRAG_INPUTS}"
2961 		<< "void main() {\n"
2962 		<< "    color = ${OUT_COLOR_VTYPE}(pushConstants.triangleColor);\n"
2963 		<< "${FRAG_CALCULATIONS}"
2964 		<< (m_testConfig.representativeFragmentTest ? "    atomicAdd(counterBuffer.fragCounter, 1u);\n" : "")
2965 		<< "}\n"
2966 		;
2967 
2968 	tcu::StringTemplate fragSourceTemplate (fragSourceTemplateStream.str());
2969 
2970 	std::map<std::string, std::string> activeMap;
2971 	std::map<std::string, std::string> inactiveMap;
2972 
2973 	activeMap["ATTRIBUTES"]			= activeAttribs.str();
2974 	activeMap["CALCULATIONS"]		= activeCalcs.str();
2975 	activeMap["FRAG_INPUTS"]		= activeFragInputs.str();
2976 	activeMap["FRAG_CALCULATIONS"]	= activeFragCalcs.str();
2977 	activeMap["OUT_COLOR_VTYPE"]	= vecType;
2978 
2979 	inactiveMap["ATTRIBUTES"]			= inactiveAttribs.str();
2980 	inactiveMap["CALCULATIONS"]			= inactiveCalcs.str();
2981 	inactiveMap["FRAG_INPUTS"]			= inactiveFragInputs.str();
2982 	inactiveMap["FRAG_CALCULATIONS"]	= inactiveFragCalcs.str();
2983 	inactiveMap["OUT_COLOR_VTYPE"]		= vecType;
2984 
2985 	const auto activeVertSource		= vertSourceTemplate.specialize(activeMap);
2986 	const auto activeFragSource		= fragSourceTemplate.specialize(activeMap);
2987 	const auto inactiveVertSource	= vertSourceTemplate.specialize(inactiveMap);
2988 	const auto inactiveFragSource	= fragSourceTemplate.specialize(inactiveMap);
2989 
2990 	if (m_testConfig.needsGeometryShader())
2991 	{
2992 		const auto			topologyClass	= getTopologyClass(m_testConfig.topologyConfig.staticValue);
2993 		const std::string	inputPrimitive	= ((topologyClass == TopologyClass::LINE) ? "lines" : "triangles");
2994 		const deUint32		vertexCount		= ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
2995 		const std::string	outputPrimitive	= ((topologyClass == TopologyClass::LINE) ? "line_strip" : "triangle_strip");
2996 		const auto			selectStream	= static_cast<bool>(m_testConfig.shaderRasterizationStream);
2997 		const auto			streamNumber	= (selectStream ? m_testConfig.shaderRasterizationStream.get() : 0u);
2998 		const auto			streamNumberStr	= de::toString(streamNumber);
2999 
3000 		geomSource
3001 			<< "#version 450\n"
3002 			<< "layout (" << inputPrimitive << ") in;\n"
3003 			<< "layout (" << outputPrimitive << ", max_vertices=" << vertexCount << ") out;\n"
3004 			<< (m_testConfig.isMultiViewport() ? pushConstants : "")
3005 			<< (selectStream ? "layout (stream=" + streamNumberStr + ") out;\n" : "")
3006 			<< "in gl_PerVertex\n"
3007 			<< "{\n"
3008 			<< "    vec4 gl_Position;\n"
3009 			<< "} gl_in[" << vertexCount << "];\n"
3010 			<< "out gl_PerVertex\n"
3011 			<< "{\n"
3012 			<< "    vec4 gl_Position;\n"
3013 			<< "};\n"
3014 			<< "void main() {\n"
3015 			<< (m_testConfig.isMultiViewport() ? "    gl_ViewportIndex = pushConstants.viewPortIndex;\n" : "")
3016 			;
3017 
3018 		for (deUint32 i = 0; i < vertexCount; ++i)
3019 		{
3020 			geomSource
3021 				<< "    gl_Position = gl_in[" << i << "].gl_Position;\n"
3022 				<< "    " << (selectStream ? ("EmitStreamVertex(" + streamNumberStr + ")") : "EmitVertex()") << ";\n"
3023 				;
3024 		}
3025 
3026 		geomSource
3027 			<< "}\n"
3028 			;
3029 	}
3030 
3031 	if (m_testConfig.needsTessellation())
3032 	{
3033 		tescSource
3034 			<< "#version 450\n"
3035 			<< "#extension GL_EXT_tessellation_shader : require\n"
3036 			<< "layout(vertices=3) out;\n"
3037 			<< "in gl_PerVertex\n"
3038 			<< "{\n"
3039 			<< "    vec4 gl_Position;\n"
3040 			<< "} gl_in[gl_MaxPatchVertices];\n"
3041 			<< "out gl_PerVertex\n"
3042 			<< "{\n"
3043 			<< "  vec4 gl_Position;\n"
3044 			<< "} gl_out[];\n"
3045 			<< "void main() {\n"
3046 			<< "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3047 			<< "  gl_TessLevelOuter[0] = 3.0;\n"
3048 			<< "  gl_TessLevelOuter[1] = 3.0;\n"
3049 			<< "  gl_TessLevelOuter[2] = 3.0;\n"
3050 			<< "  gl_TessLevelInner[0] = 3.0;\n"
3051 			<< "}\n"
3052 			;
3053 		teseSource
3054 			<< "#version 450\n"
3055 			<< "#extension GL_EXT_tessellation_shader : require\n"
3056 			<< "layout(triangles) in;\n"
3057 			<< "in gl_PerVertex\n"
3058 			<< "{\n"
3059 			<< "  vec4 gl_Position;\n"
3060 			<< "} gl_in[gl_MaxPatchVertices];\n"
3061 			<< "out gl_PerVertex\n"
3062 			<< "{\n"
3063 			<< "  vec4 gl_Position;\n"
3064 			<< "};\n"
3065 			<< "void main() {\n"
3066 			<< "  gl_Position = (gl_in[0].gl_Position * gl_TessCoord.x + \n"
3067 			<< "                 gl_in[1].gl_Position * gl_TessCoord.y + \n"
3068 			<< "                 gl_in[2].gl_Position * gl_TessCoord.z);\n"
3069 			<< "}\n"
3070 			;
3071 	}
3072 
3073 #ifndef CTS_USES_VULKANSC
3074 	if (m_testConfig.useMeshShaders)
3075 	{
3076 		DE_ASSERT(!m_testConfig.needsGeometryShader());
3077 		DE_ASSERT(!m_testConfig.needsTessellation());
3078 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
3079 
3080 		// Make sure no dynamic states incompatible with mesh shading pipelines are used.
3081 		DE_ASSERT(!m_testConfig.badMeshShadingPipelineDynState());
3082 
3083 		// Shader below is designed to work with vertex buffers containing triangle strips as used by default.
3084 		DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
3085 		DE_ASSERT(!m_testConfig.singleVertex);
3086 
3087 		meshSource
3088 			<< "#version 450\n"
3089 			<< "#extension GL_EXT_mesh_shader : enable\n"
3090 			<< "layout(local_size_x=3, local_size_y=1, local_size_z=1) in;\n"
3091 			<< "layout(triangles) out;\n"
3092 			<< "layout(max_vertices=3, max_primitives=1) out;\n"
3093 			<< pushConstants
3094 			<< (m_testConfig.isMultiViewport()
3095 				? "perprimitiveEXT out gl_MeshPerPrimitiveEXT { int gl_ViewportIndex; } gl_MeshPrimitivesEXT[];\n"
3096 				: "")
3097 			<< descDecls.str()
3098 			<< "void main() {\n"
3099 			<< descCalcs.str()
3100 			<< "    SetMeshOutputsEXT(3u, 1u);\n"
3101 			<< "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vec4(vertexCoords.x * pushConstants.scaleX + pushConstants.offsetX, vertexCoords.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
3102 			<< "    if (gl_LocalInvocationIndex == 0u) {\n"
3103 			<< "        gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
3104 			<< (m_testConfig.isMultiViewport()
3105 				? "        gl_MeshPrimitivesEXT[0].gl_ViewportIndex = pushConstants.viewPortIndex;\n"
3106 				: "")
3107 			<< "    }\n"
3108 			<< "}\n"
3109 			;
3110 	}
3111 #endif // CTS_USES_VULKANSC
3112 
3113 	// In reversed test configurations, the pipeline with dynamic state needs to have the inactive shader.
3114 	const auto kReversed = m_testConfig.isReversed();
3115 	programCollection.glslSources.add("dynamicVert")	<< glu::VertexSource(kReversed ? inactiveVertSource : activeVertSource);
3116 	programCollection.glslSources.add("staticVert")		<< glu::VertexSource(kReversed ? activeVertSource : inactiveVertSource);
3117 	programCollection.glslSources.add("dynamicFrag")	<< glu::FragmentSource(kReversed ? inactiveFragSource : activeFragSource);
3118 	programCollection.glslSources.add("staticFrag")		<< glu::FragmentSource(kReversed ? activeFragSource : inactiveFragSource);
3119 
3120 	if (m_testConfig.needsGeometryShader())
3121 		programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource.str());
3122 	if (m_testConfig.needsTessellation())
3123 	{
3124 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSource.str());
3125 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSource.str());
3126 	}
3127 	if (m_testConfig.useMeshShaders)
3128 		programCollection.glslSources.add("mesh") << glu::MeshSource(meshSource.str()) << meshBuildOptions;
3129 
3130 	if (m_testConfig.bindUnusedMeshShadingPipeline)
3131 	{
3132 		std::ostringstream meshNoOut;
3133 		meshNoOut
3134 			<< "#version 450\n"
3135 			<< "#extension GL_EXT_mesh_shader : enable\n"
3136 			<< "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
3137 			<< "layout(triangles) out;\n"
3138 			<< "layout(max_vertices=3, max_primitives=1) out;\n"
3139 			<< "void main() {\n"
3140 			<< "    SetMeshOutputsEXT(0u, 0u);\n"
3141 			<< "}\n"
3142 			;
3143 		programCollection.glslSources.add("meshNoOut") << glu::MeshSource(meshNoOut.str()) << meshBuildOptions;
3144 	}
3145 
3146 	// Extra vert and frag shaders for the extra patch control points pipeline. These draw offscreen.
3147 	if (m_testConfig.useExtraDynPCPPipeline)
3148 	{
3149 		std::ostringstream vertDPCP;
3150 		vertDPCP
3151 			<< "#version 450\n"
3152 			<< "\n"
3153 			<< "vec2 positions[3] = vec2[](\n"
3154 			<< "    vec2(-1.0, -1.0),\n"
3155 			<< "    vec2( 3.0, -1.0),\n"
3156 			<< "    vec2(-1.0,  3.0)\n"
3157 			<< ");\n"
3158 			<< "\n"
3159 			<< "void main() {\n"
3160 			<< "    gl_Position = vec4(positions[gl_VertexIndex] + 10.0 + 1.0 * float(gl_VertexIndex), 0.0, 1.0);\n"
3161 			<< "}\n"
3162 			;
3163 		programCollection.glslSources.add("vertDPCP") << glu::VertexSource(vertDPCP.str());
3164 
3165 		std::ostringstream fragDPCP;
3166 		fragDPCP
3167 			<< "#version 450\n"
3168 			<< "layout(location=0) out " << vecType << " color;\n"
3169 			<< "void main() {\n"
3170 			<< "    color = " << vecType << "(1.0, 1.0, 1.0, 1.0);\n"
3171 			<< "}\n"
3172 			;
3173 		programCollection.glslSources.add("fragDPCP") << glu::FragmentSource(fragDPCP.str());
3174 	}
3175 }
3176 
createInstance(Context & context) const3177 TestInstance* ExtendedDynamicStateTest::createInstance (Context& context) const
3178 {
3179 	return new ExtendedDynamicStateInstance(context, m_testConfig);
3180 }
3181 
ExtendedDynamicStateInstance(Context & context,const TestConfig & testConfig)3182 ExtendedDynamicStateInstance::ExtendedDynamicStateInstance(Context& context, const TestConfig& testConfig)
3183 	: vkt::TestInstance	(context)
3184 	, m_testConfig		(testConfig)
3185 {
3186 }
3187 
3188 using BufferWithMemoryPtr = de::MovePtr<vk::BufferWithMemory>;
3189 
3190 struct VertexBufferInfo
3191 {
VertexBufferInfovkt::pipeline::__anonaa66a09e0111::VertexBufferInfo3192 	VertexBufferInfo ()
3193 		: buffer	()
3194 		, offset	(0ull)
3195 		, dataSize	(0ull)
3196 	{}
3197 
VertexBufferInfovkt::pipeline::__anonaa66a09e0111::VertexBufferInfo3198 	VertexBufferInfo (VertexBufferInfo&& other)
3199 		: buffer	(other.buffer.release())
3200 		, offset	(other.offset)
3201 		, dataSize	(other.dataSize)
3202 	{}
3203 
3204 	BufferWithMemoryPtr	buffer;
3205 	vk::VkDeviceSize	offset;
3206 	vk::VkDeviceSize	dataSize;
3207 };
3208 
logErrors(tcu::TestLog & log,const std::string & setName,const std::string & setDesc,const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & errorMask)3209 void logErrors(tcu::TestLog& log, const std::string& setName, const std::string& setDesc, const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& errorMask)
3210 {
3211 	log << tcu::TestLog::ImageSet(setName, setDesc)
3212 		<< tcu::TestLog::Image(setName + "Result", "Result image", result)
3213 		<< tcu::TestLog::Image(setName + "ErrorMask", "Error mask with errors marked in red", errorMask)
3214 		<< tcu::TestLog::EndImageSet;
3215 }
3216 
copyAndFlush(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::BufferWithMemory & buffer,size_t offset,const void * src,size_t size)3217 void copyAndFlush(const vk::DeviceInterface& vkd, vk::VkDevice device, vk::BufferWithMemory& buffer, size_t offset, const void* src, size_t size)
3218 {
3219 	auto&	alloc	= buffer.getAllocation();
3220 	auto	dst		= reinterpret_cast<char*>(alloc.getHostPtr());
3221 
3222 	deMemcpy(dst + offset, src, size);
3223 	vk::flushAlloc(vkd, device, alloc);
3224 }
3225 
3226 // Sets values for dynamic states if needed according to the test configuration.
setDynamicStates(const TestConfig & testConfig,const vk::DeviceInterface & vkd,vk::VkCommandBuffer cmdBuffer)3227 void setDynamicStates(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer)
3228 {
3229 	if (testConfig.cullModeConfig.dynamicValue)
3230 #ifndef CTS_USES_VULKANSC
3231 		vkd.cmdSetCullMode(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
3232 #else
3233 		vkd.cmdSetCullModeEXT(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
3234 #endif // CTS_USES_VULKANSC
3235 
3236 	if (testConfig.frontFaceConfig.dynamicValue)
3237 #ifndef CTS_USES_VULKANSC
3238 		vkd.cmdSetFrontFace(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
3239 #else
3240 		vkd.cmdSetFrontFaceEXT(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
3241 #endif // CTS_USES_VULKANSC
3242 
3243 	if (testConfig.topologyConfig.dynamicValue)
3244 #ifndef CTS_USES_VULKANSC
3245 		vkd.cmdSetPrimitiveTopology(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
3246 #else
3247 		vkd.cmdSetPrimitiveTopologyEXT(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
3248 #endif // CTS_USES_VULKANSC
3249 
3250 	if (testConfig.viewportConfig.dynamicValue)
3251 	{
3252 		const auto& viewports = testConfig.viewportConfig.dynamicValue.get();
3253 #ifndef CTS_USES_VULKANSC
3254 		vkd.cmdSetViewportWithCount(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
3255 #else
3256 		vkd.cmdSetViewportWithCountEXT(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
3257 #endif // CTS_USES_VULKANSC
3258 	}
3259 
3260 	if (testConfig.scissorConfig.dynamicValue)
3261 	{
3262 		const auto& scissors = testConfig.scissorConfig.dynamicValue.get();
3263 #ifndef CTS_USES_VULKANSC
3264 		vkd.cmdSetScissorWithCount(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
3265 #else
3266 		vkd.cmdSetScissorWithCountEXT(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
3267 #endif // CTS_USES_VULKANSC
3268 	}
3269 
3270 	if (testConfig.depthTestEnableConfig.dynamicValue)
3271 #ifndef CTS_USES_VULKANSC
3272 		vkd.cmdSetDepthTestEnable(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
3273 #else
3274 		vkd.cmdSetDepthTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
3275 #endif // CTS_USES_VULKANSC
3276 
3277 	if (testConfig.depthWriteEnableConfig.dynamicValue)
3278 #ifndef CTS_USES_VULKANSC
3279 		vkd.cmdSetDepthWriteEnable(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
3280 #else
3281 		vkd.cmdSetDepthWriteEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
3282 #endif // CTS_USES_VULKANSC
3283 
3284 	if (testConfig.depthCompareOpConfig.dynamicValue)
3285 #ifndef CTS_USES_VULKANSC
3286 		vkd.cmdSetDepthCompareOp(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
3287 #else
3288 		vkd.cmdSetDepthCompareOpEXT(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
3289 #endif // CTS_USES_VULKANSC
3290 
3291 	if (testConfig.depthBoundsTestEnableConfig.dynamicValue)
3292 #ifndef CTS_USES_VULKANSC
3293 		vkd.cmdSetDepthBoundsTestEnable(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
3294 #else
3295 		vkd.cmdSetDepthBoundsTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
3296 #endif // CTS_USES_VULKANSC
3297 
3298 	if (testConfig.stencilTestEnableConfig.dynamicValue)
3299 #ifndef CTS_USES_VULKANSC
3300 		vkd.cmdSetStencilTestEnable(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
3301 #else
3302 		vkd.cmdSetStencilTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
3303 #endif // CTS_USES_VULKANSC
3304 
3305 	if (testConfig.depthBiasEnableConfig.dynamicValue)
3306 #ifndef CTS_USES_VULKANSC
3307 		vkd.cmdSetDepthBiasEnable(cmdBuffer, makeVkBool32(testConfig.depthBiasEnableConfig.dynamicValue.get()));
3308 #else
3309 		vkd.cmdSetDepthBiasEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBiasEnableConfig.dynamicValue.get()));
3310 #endif // CTS_USES_VULKANSC
3311 
3312 	if (testConfig.depthBiasConfig.dynamicValue)
3313 	{
3314 		const auto& bias = testConfig.depthBiasConfig.dynamicValue.get();
3315 		vkd.cmdSetDepthBias(cmdBuffer, bias.constantFactor, bias.clamp, 0.0f);
3316 	}
3317 
3318 	if (testConfig.rastDiscardEnableConfig.dynamicValue)
3319 #ifndef CTS_USES_VULKANSC
3320 		vkd.cmdSetRasterizerDiscardEnable(cmdBuffer, makeVkBool32(testConfig.rastDiscardEnableConfig.dynamicValue.get()));
3321 #else
3322 		vkd.cmdSetRasterizerDiscardEnableEXT(cmdBuffer, makeVkBool32(testConfig.rastDiscardEnableConfig.dynamicValue.get()));
3323 #endif // CTS_USES_VULKANSC
3324 
3325 	if (testConfig.primRestartEnableConfig.dynamicValue)
3326 #ifndef CTS_USES_VULKANSC
3327 		vkd.cmdSetPrimitiveRestartEnable(cmdBuffer, makeVkBool32(testConfig.primRestartEnableConfig.dynamicValue.get()));
3328 #else
3329 		vkd.cmdSetPrimitiveRestartEnableEXT(cmdBuffer, makeVkBool32(testConfig.primRestartEnableConfig.dynamicValue.get()));
3330 #endif // CTS_USES_VULKANSC
3331 
3332 	if (testConfig.logicOpConfig.dynamicValue)
3333 		vkd.cmdSetLogicOpEXT(cmdBuffer, testConfig.logicOpConfig.dynamicValue.get());
3334 
3335 	if (testConfig.patchControlPointsConfig.dynamicValue)
3336 		vkd.cmdSetPatchControlPointsEXT(cmdBuffer, testConfig.patchControlPointsConfig.dynamicValue.get());
3337 
3338 	if (testConfig.stencilOpConfig.dynamicValue)
3339 	{
3340 		for (const auto& params : testConfig.stencilOpConfig.dynamicValue.get())
3341 #ifndef CTS_USES_VULKANSC
3342 			vkd.cmdSetStencilOp(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
3343 #else
3344 			vkd.cmdSetStencilOpEXT(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
3345 #endif // CTS_USES_VULKANSC
3346 	}
3347 
3348 	if (testConfig.vertexGenerator.dynamicValue)
3349 	{
3350 		const auto generator	= testConfig.vertexGenerator.dynamicValue.get();
3351 		const auto bindings		= generator->getBindingDescriptions2(testConfig.strideConfig.staticValue);
3352 		const auto attributes	= generator->getAttributeDescriptions2();
3353 
3354 		vkd.cmdSetVertexInputEXT(cmdBuffer,
3355 			static_cast<deUint32>(bindings.size()), de::dataOrNull(bindings),
3356 			static_cast<deUint32>(attributes.size()), de::dataOrNull(attributes));
3357 	}
3358 
3359 #ifndef CTS_USES_VULKANSC
3360 	if (testConfig.tessDomainOriginConfig.dynamicValue)
3361 		vkd.cmdSetTessellationDomainOriginEXT(cmdBuffer, testConfig.tessDomainOriginConfig.dynamicValue.get());
3362 
3363 	if (testConfig.depthClampEnableConfig.dynamicValue)
3364 		vkd.cmdSetDepthClampEnableEXT(cmdBuffer, testConfig.depthClampEnableConfig.dynamicValue.get());
3365 
3366 	if (testConfig.polygonModeConfig.dynamicValue)
3367 		vkd.cmdSetPolygonModeEXT(cmdBuffer, testConfig.polygonModeConfig.dynamicValue.get());
3368 
3369 	if (testConfig.rasterizationSamplesConfig.dynamicValue)
3370 		vkd.cmdSetRasterizationSamplesEXT(cmdBuffer, testConfig.rasterizationSamplesConfig.dynamicValue.get());
3371 
3372 	if (testConfig.sampleMaskConfig.dynamicValue)
3373 	{
3374 		const auto sampleCount	= (static_cast<bool>(testConfig.dynamicSampleMaskCount)
3375 								? testConfig.dynamicSampleMaskCount.get()
3376 								: testConfig.getActiveSampleCount());
3377 		vkd.cmdSetSampleMaskEXT(cmdBuffer, sampleCount, testConfig.sampleMaskConfig.dynamicValue.get().data());
3378 	}
3379 
3380 	if (testConfig.alphaToCoverageConfig.dynamicValue)
3381 		vkd.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, makeVkBool32(testConfig.alphaToCoverageConfig.dynamicValue.get()));
3382 
3383 	if (testConfig.alphaToOneConfig.dynamicValue)
3384 		vkd.cmdSetAlphaToOneEnableEXT(cmdBuffer, makeVkBool32(testConfig.alphaToOneConfig.dynamicValue.get()));
3385 
3386 	if (testConfig.colorWriteMaskConfig.dynamicValue)
3387 		vkd.cmdSetColorWriteMaskEXT(cmdBuffer, 0u, 1u, &testConfig.colorWriteMaskConfig.dynamicValue.get());
3388 
3389 	if (testConfig.rasterizationStreamConfig.dynamicValue && static_cast<bool>(testConfig.rasterizationStreamConfig.dynamicValue.get()))
3390 		vkd.cmdSetRasterizationStreamEXT(cmdBuffer, testConfig.rasterizationStreamConfig.dynamicValue->get());
3391 
3392 	if (testConfig.logicOpEnableConfig.dynamicValue)
3393 		vkd.cmdSetLogicOpEnableEXT(cmdBuffer, makeVkBool32(testConfig.logicOpEnableConfig.dynamicValue.get()));
3394 
3395 	if (testConfig.colorBlendEnableConfig.dynamicValue)
3396 	{
3397 		const auto colorBlendEnableFlag = makeVkBool32(testConfig.colorBlendEnableConfig.dynamicValue.get());
3398 		vkd.cmdSetColorBlendEnableEXT(cmdBuffer, 0u, 1u, &colorBlendEnableFlag);
3399 	}
3400 
3401 	if (testConfig.colorBlendEquationConfig.dynamicValue)
3402 	{
3403 		const auto& configEq = testConfig.colorBlendEquationConfig.dynamicValue.get();
3404 
3405 		if (testConfig.colorBlendEquationConfig.staticValue.isAdvanced())
3406 		{
3407 			const vk::VkColorBlendAdvancedEXT advanced =
3408 			{
3409 				configEq.colorBlendOp,					//	VkBlendOp			advancedBlendOp;
3410 				VK_TRUE,								//	VkBool32			srcPremultiplied;
3411 				VK_TRUE,								//	VkBool32			dstPremultiplied;
3412 				vk::VK_BLEND_OVERLAP_UNCORRELATED_EXT,	//	VkBlendOverlapEXT	blendOverlap;
3413 				VK_FALSE,								//	VkBool32			clampResults;
3414 			};
3415 			vkd.cmdSetColorBlendAdvancedEXT(cmdBuffer, 0u, 1u, &advanced);
3416 		}
3417 		else
3418 		{
3419 			const vk::VkColorBlendEquationEXT equation =
3420 			{
3421 				configEq.srcColorBlendFactor,	//	VkBlendFactor	srcColorBlendFactor;
3422 				configEq.dstColorBlendFactor,	//	VkBlendFactor	dstColorBlendFactor;
3423 				configEq.colorBlendOp,			//	VkBlendOp		colorBlendOp;
3424 				configEq.srcAlphaBlendFactor,	//	VkBlendFactor	srcAlphaBlendFactor;
3425 				configEq.dstAlphaBlendFactor,	//	VkBlendFactor	dstAlphaBlendFactor;
3426 				configEq.alphaBlendOp,			//	VkBlendOp		alphaBlendOp;
3427 			};
3428 			vkd.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, 1u, &equation);
3429 		}
3430 	}
3431 
3432 	if (testConfig.provokingVertexConfig.dynamicValue && static_cast<bool>(testConfig.provokingVertexConfig.dynamicValue.get()))
3433 	{
3434 		const auto provokingVertexMode = makeProvokingVertexMode(testConfig.provokingVertexConfig.dynamicValue->get());
3435 		vkd.cmdSetProvokingVertexModeEXT(cmdBuffer, provokingVertexMode);
3436 	}
3437 
3438 	if (testConfig.negativeOneToOneConfig.dynamicValue && static_cast<bool>(testConfig.negativeOneToOneConfig.dynamicValue.get()))
3439 		vkd.cmdSetDepthClipNegativeOneToOneEXT(cmdBuffer, makeVkBool32(testConfig.negativeOneToOneConfig.dynamicValue->get()));
3440 
3441 	if (testConfig.depthClipEnableConfig.dynamicValue && static_cast<bool>(testConfig.depthClipEnableConfig.dynamicValue.get()))
3442 		vkd.cmdSetDepthClipEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthClipEnableConfig.dynamicValue->get()));
3443 
3444 	if (testConfig.lineStippleEnableConfig.dynamicValue)
3445 		vkd.cmdSetLineStippleEnableEXT(cmdBuffer, makeVkBool32(testConfig.lineStippleEnableConfig.dynamicValue.get()));
3446 
3447 	if (testConfig.lineStippleParamsConfig.dynamicValue && static_cast<bool>(testConfig.lineStippleParamsConfig.dynamicValue.get()))
3448 	{
3449 		const auto& stippleParams = testConfig.lineStippleParamsConfig.dynamicValue->get();
3450 		vkd.cmdSetLineStippleEXT(cmdBuffer, stippleParams.factor, stippleParams.pattern);
3451 	}
3452 
3453 	if (testConfig.sampleLocationsEnableConfig.dynamicValue)
3454 		vkd.cmdSetSampleLocationsEnableEXT(cmdBuffer, makeVkBool32(testConfig.sampleLocationsEnableConfig.dynamicValue.get()));
3455 
3456 	if (testConfig.conservativeRasterModeConfig.dynamicValue)
3457 		vkd.cmdSetConservativeRasterizationModeEXT(cmdBuffer, testConfig.conservativeRasterModeConfig.dynamicValue.get());
3458 
3459 	if (testConfig.extraPrimitiveOverEstConfig.dynamicValue)
3460 		vkd.cmdSetExtraPrimitiveOverestimationSizeEXT(cmdBuffer, testConfig.extraPrimitiveOverEstConfig.dynamicValue.get());
3461 
3462 	if (testConfig.lineRasterModeConfig.dynamicValue && static_cast<bool>(testConfig.lineRasterModeConfig.dynamicValue.get()))
3463 		vkd.cmdSetLineRasterizationModeEXT(cmdBuffer, makeLineRasterizationMode(testConfig.lineRasterModeConfig.dynamicValue->get()));
3464 
3465 	if (testConfig.coverageToColorEnableConfig.dynamicValue)
3466 		vkd.cmdSetCoverageToColorEnableNV(cmdBuffer, makeVkBool32(testConfig.coverageToColorEnableConfig.dynamicValue.get()));
3467 
3468 	if (testConfig.coverageToColorLocationConfig.dynamicValue)
3469 		vkd.cmdSetCoverageToColorLocationNV(cmdBuffer, testConfig.coverageToColorLocationConfig.dynamicValue.get());
3470 
3471 	if (testConfig.coverageModulationModeConfig.dynamicValue)
3472 		vkd.cmdSetCoverageModulationModeNV(cmdBuffer, testConfig.coverageModulationModeConfig.dynamicValue.get());
3473 
3474 	if (testConfig.coverageModTableEnableConfig.dynamicValue)
3475 		vkd.cmdSetCoverageModulationTableEnableNV(cmdBuffer, makeVkBool32(testConfig.coverageModTableEnableConfig.dynamicValue.get()));
3476 
3477 	if (testConfig.coverageModTableConfig.dynamicValue)
3478 	{
3479 		const auto& tableVec = testConfig.coverageModTableConfig.dynamicValue.get();
3480 		vkd.cmdSetCoverageModulationTableNV(cmdBuffer, static_cast<uint32_t>(tableVec.size()), de::dataOrNull(tableVec));
3481 	}
3482 
3483 	if (testConfig.coverageReductionModeConfig.dynamicValue)
3484 		vkd.cmdSetCoverageReductionModeNV(cmdBuffer, testConfig.coverageReductionModeConfig.dynamicValue.get());
3485 
3486 	if (testConfig.viewportSwizzleConfig.dynamicValue)
3487 	{
3488 		const auto& viewportSwizzleVec = testConfig.viewportSwizzleConfig.dynamicValue.get();
3489 		vkd.cmdSetViewportSwizzleNV(cmdBuffer, 0u, static_cast<uint32_t>(viewportSwizzleVec.size()), de::dataOrNull(viewportSwizzleVec));
3490 	}
3491 
3492 	if (testConfig.shadingRateImageEnableConfig.dynamicValue)
3493 		vkd.cmdSetShadingRateImageEnableNV(cmdBuffer, makeVkBool32(testConfig.shadingRateImageEnableConfig.dynamicValue.get()));
3494 
3495 	if (testConfig.viewportWScalingEnableConfig.dynamicValue)
3496 		vkd.cmdSetViewportWScalingEnableNV(cmdBuffer, makeVkBool32(testConfig.viewportWScalingEnableConfig.dynamicValue.get()));
3497 
3498 	if (testConfig.reprFragTestEnableConfig.dynamicValue)
3499 		vkd.cmdSetRepresentativeFragmentTestEnableNV(cmdBuffer, makeVkBool32(testConfig.reprFragTestEnableConfig.dynamicValue.get()));
3500 #else
3501 	DE_ASSERT(false);
3502 #endif // CTS_USES_VULKANSC
3503 }
3504 
3505 // Bind the appropriate vertex buffers using dynamic strides if the test configuration needs a dynamic stride.
3506 // 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)3507 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)
3508 {
3509 	if (!testConfig.strideConfig.dynamicValue)
3510 		return false;
3511 
3512 	DE_ASSERT(!testConfig.useMeshShaders);
3513 
3514 	const auto& viewportVec = testConfig.getActiveViewportVec();
3515 	DE_UNREF(viewportVec); // For release builds.
3516 
3517 	// When dynamically setting the vertex buffer stride, we cannot bind the vertex buffer in advance for some sequence
3518 	// orderings if we have several viewports or meshes.
3519 	DE_ASSERT((viewportVec.size() == 1u && testConfig.meshParams.size() == 1u)
3520 				|| testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW
3521 				|| testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
3522 
3523 	// Split buffers, offsets, sizes and strides into their own vectors for the call.
3524 	std::vector<vk::VkBuffer>		buffers;
3525 	std::vector<vk::VkDeviceSize>	offsets;
3526 	std::vector<vk::VkDeviceSize>	sizes;
3527 	const auto						strides = testConfig.strideConfig.dynamicValue.get();
3528 
3529 	const auto& chosenBuffers = (testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers);
3530 
3531 	buffers.reserve	(chosenBuffers.size());
3532 	offsets.reserve	(chosenBuffers.size());
3533 	sizes.reserve	(chosenBuffers.size());
3534 	DE_ASSERT(chosenBuffers.size() == strides.size());
3535 
3536 	for (const auto& vertBuffer : chosenBuffers)
3537 	{
3538 		buffers.push_back	(vertBuffer.buffer->get());
3539 		offsets.push_back	(vertBuffer.offset);
3540 		sizes.push_back		(vertBuffer.dataSize);
3541 	}
3542 
3543 #ifndef CTS_USES_VULKANSC
3544 	vkd.cmdBindVertexBuffers2(cmdBuffer, 0u, static_cast<deUint32>(chosenBuffers.size()), buffers.data(), offsets.data(), sizes.data(), strides.data());
3545 #else
3546 	vkd.cmdBindVertexBuffers2EXT(cmdBuffer, 0u, static_cast<deUint32>(chosenBuffers.size()), buffers.data(), offsets.data(), sizes.data(), strides.data());
3547 #endif // CTS_USES_VULKANSC
3548 
3549 	return true;
3550 }
3551 
3552 // 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)3553 void bindVertexBuffers (const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer, const std::vector<VertexBufferInfo>& vertexBuffers)
3554 {
3555 	std::vector<vk::VkBuffer>		buffers;
3556 	std::vector<vk::VkDeviceSize>	offsets;
3557 
3558 	buffers.reserve	(vertexBuffers.size());
3559 	offsets.reserve	(vertexBuffers.size());
3560 
3561 	for (const auto& vertBuffer : vertexBuffers)
3562 	{
3563 		buffers.push_back	(vertBuffer.buffer->get());
3564 		offsets.push_back	(vertBuffer.offset);
3565 	}
3566 
3567 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, static_cast<deUint32>(vertexBuffers.size()), buffers.data(), offsets.data());
3568 }
3569 
3570 // 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)3571 void prepareVertexBuffers (	std::vector<VertexBufferInfo>&	buffers,
3572 							const vk::DeviceInterface&		vkd,
3573 							vk::VkDevice					device,
3574 							vk::Allocator&					allocator,
3575 							const VertexGenerator*			generator,
3576 							const std::vector<tcu::Vec2>&	vertices,
3577 							deUint32						dataOffset,
3578 							deUint32						trailingSize,
3579 							bool							ssbos)
3580 {
3581 	const deUint32	paddingBytes	= 0xDEADBEEFu;
3582 	const auto		vertexData		= generator->createVertexData(vertices, dataOffset, trailingSize, &paddingBytes, sizeof(paddingBytes));
3583 
3584 	for (const auto& bufferBytes : vertexData)
3585 	{
3586 		const auto bufferSize	= static_cast<vk::VkDeviceSize>(de::dataSize(bufferBytes));
3587 		const auto extraSize	= static_cast<vk::VkDeviceSize>(dataOffset + trailingSize);
3588 		DE_ASSERT(bufferSize > extraSize);
3589 		const auto dataSize		= bufferSize - extraSize;
3590 
3591 		// Create a full-size buffer but remember the data size and offset for it.
3592 		const auto createInfo = vk::makeBufferCreateInfo(bufferSize, (ssbos ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
3593 
3594 		VertexBufferInfo bufferInfo;
3595 		bufferInfo.buffer	= BufferWithMemoryPtr(new vk::BufferWithMemory(vkd, device, allocator, createInfo, vk::MemoryRequirement::HostVisible));
3596 		bufferInfo.offset	= static_cast<vk::VkDeviceSize>(dataOffset);
3597 		bufferInfo.dataSize	= dataSize;
3598 		buffers.emplace_back(std::move(bufferInfo));
3599 
3600 		// Copy the whole contents to the full buffer.
3601 		copyAndFlush(vkd, device, *buffers.back().buffer, 0, bufferBytes.data(), de::dataSize(bufferBytes));
3602 	}
3603 }
3604 
3605 // Device helper: this is needed in some tests when we create custom devices.
3606 class DeviceHelper
3607 {
3608 public:
~DeviceHelper()3609 	virtual ~DeviceHelper () {}
3610 	virtual const vk::DeviceInterface&	getDeviceInterface	(void) const = 0;
3611 	virtual vk::VkDevice				getDevice			(void) const = 0;
3612 	virtual uint32_t					getQueueFamilyIndex	(void) const = 0;
3613 	virtual vk::VkQueue					getQueue			(void) const = 0;
3614 	virtual vk::Allocator&				getAllocator		(void) const = 0;
3615 };
3616 
3617 // This one just reuses the default device from the context.
3618 class ContextDeviceHelper : public DeviceHelper
3619 {
3620 public:
ContextDeviceHelper(Context & context)3621 	ContextDeviceHelper (Context& context)
3622 		: m_deviceInterface		(context.getDeviceInterface())
3623 		, m_device				(context.getDevice())
3624 		, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
3625 		, m_queue				(context.getUniversalQueue())
3626 		, m_allocator			(context.getDefaultAllocator())
3627 		{}
3628 
~ContextDeviceHelper()3629 	virtual ~ContextDeviceHelper () {}
3630 
getDeviceInterface(void) const3631 	const vk::DeviceInterface&	getDeviceInterface	(void) const override	{ return m_deviceInterface;		}
getDevice(void) const3632 	vk::VkDevice				getDevice			(void) const override	{ return m_device;				}
getQueueFamilyIndex(void) const3633 	uint32_t					getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const3634 	vk::VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const3635 	vk::Allocator&				getAllocator		(void) const override	{ return m_allocator;			}
3636 
3637 protected:
3638 	const vk::DeviceInterface&	m_deviceInterface;
3639 	const vk::VkDevice			m_device;
3640 	const uint32_t				m_queueFamilyIndex;
3641 	const vk::VkQueue			m_queue;
3642 	vk::Allocator&				m_allocator;
3643 };
3644 
3645 // This one creates a new device with VK_NV_shading_rate_image and VK_EXT_extended_dynamic_state3.
3646 // It also enables VK_EXT_mesh_shader if supported, as some tests need it.
3647 class ShadingRateImageDeviceHelper : public DeviceHelper
3648 {
3649 public:
ShadingRateImageDeviceHelper(Context & context)3650 	ShadingRateImageDeviceHelper (Context& context)
3651 	{
3652 		const auto&	vkp				= context.getPlatformInterface();
3653 		const auto&	vki				= context.getInstanceInterface();
3654 		const auto	instance		= context.getInstance();
3655 		const auto	physicalDevice	= context.getPhysicalDevice();
3656 		const auto	queuePriority	= 1.0f;
3657 
3658 		// Queue index first.
3659 		m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3660 
3661 		// Create a universal queue that supports graphics and compute.
3662 		const vk::VkDeviceQueueCreateInfo queueParams =
3663 		{
3664 			vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
3665 			DE_NULL,										// const void*					pNext;
3666 			0u,												// VkDeviceQueueCreateFlags		flags;
3667 			m_queueFamilyIndex,								// deUint32						queueFamilyIndex;
3668 			1u,												// deUint32						queueCount;
3669 			&queuePriority									// const float*					pQueuePriorities;
3670 		};
3671 
3672 #ifndef CTS_USES_VULKANSC
3673 		const auto&	contextMeshFeatures	= context.getMeshShaderFeaturesEXT();
3674 		const auto& contextGPLFeatures	= context.getGraphicsPipelineLibraryFeaturesEXT();
3675 		const bool	meshShaderSupport	= contextMeshFeatures.meshShader;
3676 		const bool	gplSupport			= contextGPLFeatures.graphicsPipelineLibrary;
3677 
3678 		vk::VkPhysicalDeviceMeshShaderFeaturesEXT				meshFeatures				= vk::initVulkanStructure();
3679 		vk::VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT	gplFeatures					= vk::initVulkanStructure();
3680 
3681 		vk::VkPhysicalDeviceExtendedDynamicState3FeaturesEXT	eds3Features				= vk::initVulkanStructure();
3682 		vk::VkPhysicalDeviceShadingRateImageFeaturesNV			shadingRateImageFeatures	= vk::initVulkanStructure(&eds3Features);
3683 		vk::VkPhysicalDeviceFeatures2							features2					= vk::initVulkanStructure(&shadingRateImageFeatures);
3684 
3685 		if (meshShaderSupport)
3686 		{
3687 			meshFeatures.pNext	= features2.pNext;
3688 			features2.pNext		= &meshFeatures;
3689 		}
3690 
3691 		if (gplSupport)
3692 		{
3693 			gplFeatures.pNext	= features2.pNext;
3694 			features2.pNext		= &gplFeatures;
3695 		}
3696 
3697 		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
3698 #endif // CTS_USES_VULKANSC
3699 
3700 		std::vector<const char*> extensions
3701 		{
3702 			"VK_EXT_extended_dynamic_state3",
3703 			"VK_NV_shading_rate_image",
3704 		};
3705 
3706 #ifndef CTS_USES_VULKANSC
3707 		if (meshShaderSupport)
3708 			extensions.push_back("VK_EXT_mesh_shader");
3709 
3710 		if (gplSupport)
3711 		{
3712 			extensions.push_back("VK_KHR_pipeline_library");
3713 			extensions.push_back("VK_EXT_graphics_pipeline_library");
3714 		}
3715 
3716 		// Disable robustness.
3717 		features2.features.robustBufferAccess = VK_FALSE;
3718 #endif // CTS_USES_VULKANSC
3719 
3720 		const vk::VkDeviceCreateInfo deviceCreateInfo =
3721 		{
3722 			vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,				//sType;
3723 #ifndef CTS_USES_VULKANSC
3724 			&features2,												//pNext;
3725 #else
3726 			nullptr,
3727 #endif // CTS_USES_VULKANSC
3728 			0u,														//flags
3729 			1u,														//queueRecordCount;
3730 			&queueParams,											//pRequestedQueues;
3731 			0u,														//layerCount;
3732 			nullptr,												//ppEnabledLayerNames;
3733 			de::sizeU32(extensions),								// deUint32							enabledExtensionCount;
3734 			de::dataOrNull(extensions),								// const char* const*				ppEnabledExtensionNames;
3735 			nullptr,												//pEnabledFeatures;
3736 		};
3737 
3738 		m_device	= createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
3739 		m_vkd		.reset(new vk::DeviceDriver(vkp, instance, m_device.get()));
3740 		m_queue		= getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
3741 		m_allocator	.reset(new vk::SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
3742 	}
3743 
~ShadingRateImageDeviceHelper()3744 	virtual ~ShadingRateImageDeviceHelper () {}
3745 
getDeviceInterface(void) const3746 	const vk::DeviceInterface&	getDeviceInterface	(void) const override	{ return *m_vkd;				}
getDevice(void) const3747 	vk::VkDevice				getDevice			(void) const override	{ return m_device.get();		}
getQueueFamilyIndex(void) const3748 	uint32_t					getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const3749 	vk::VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const3750 	vk::Allocator&				getAllocator		(void) const override	{ return *m_allocator;			}
3751 
3752 protected:
3753 	vk::Move<vk::VkDevice>					m_device;
3754 	std::unique_ptr<vk::DeviceDriver>		m_vkd;
3755 	deUint32								m_queueFamilyIndex;
3756 	vk::VkQueue								m_queue;
3757 	std::unique_ptr<vk::SimpleAllocator>	m_allocator;
3758 };
3759 
3760 std::unique_ptr<DeviceHelper> g_shadingRateDeviceHelper;
3761 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
3762 
getDeviceHelper(Context & context,const TestConfig & testConfig)3763 DeviceHelper& getDeviceHelper(Context& context, const TestConfig& testConfig)
3764 {
3765 	if (testConfig.shadingRateImage)
3766 	{
3767 		if (!g_shadingRateDeviceHelper)
3768 			g_shadingRateDeviceHelper.reset(new ShadingRateImageDeviceHelper(context));
3769 		return *g_shadingRateDeviceHelper;
3770 	}
3771 
3772 	if (!g_contextDeviceHelper)
3773 		g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
3774 	return *g_contextDeviceHelper;
3775 }
3776 
cleanupDevices()3777 void cleanupDevices()
3778 {
3779 	g_shadingRateDeviceHelper.reset(nullptr);
3780 	g_contextDeviceHelper.reset(nullptr);
3781 }
3782 
iterate(void)3783 tcu::TestStatus ExtendedDynamicStateInstance::iterate (void)
3784 {
3785 	using ImageWithMemoryVec	= std::vector<std::unique_ptr<vk::ImageWithMemory>>;
3786 	using ImageViewVec			= std::vector<vk::Move<vk::VkImageView>>;
3787 	using FramebufferVec		= std::vector<vk::Move<vk::VkFramebuffer>>;
3788 
3789 	const auto&	vki					= m_context.getInstanceInterface();
3790 	const auto	physicalDevice		= m_context.getPhysicalDevice();
3791 	const auto& deviceHelper		= getDeviceHelper(m_context, m_testConfig);
3792 	const auto&	vkd					= deviceHelper.getDeviceInterface();
3793 	const auto	device				= deviceHelper.getDevice();
3794 	auto&		allocator			= deviceHelper.getAllocator();
3795 	const auto	queue				= deviceHelper.getQueue();
3796 	const auto	queueIndex			= deviceHelper.getQueueFamilyIndex();
3797 	auto&		log					= m_context.getTestContext().getLog();
3798 
3799 	const auto	kReversed			= m_testConfig.isReversed();
3800 	const auto	kNumIterations		= m_testConfig.numIterations();
3801 	const auto	kColorAttCount		= m_testConfig.colorAttachmentCount;
3802 	const auto	kSequenceOrdering	= m_testConfig.sequenceOrdering;
3803 
3804 	const auto	kDSCreateFlags		= (m_testConfig.sampleLocationsStruct() ? static_cast<vk::VkImageCreateFlags>(vk::VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) : 0u);
3805 	const auto	colorFormat			= m_testConfig.colorFormat();
3806 	const auto	colorSampleCount	= m_testConfig.getColorSampleCount();
3807 	const auto	activeSampleCount	= m_testConfig.getActiveSampleCount();
3808 	const bool	vertDataAsSSBO		= m_testConfig.useMeshShaders;
3809 	const auto	pipelineBindPoint	= vk::VK_PIPELINE_BIND_POINT_GRAPHICS;
3810 	const bool	kUseResolveAtt		= (colorSampleCount != kSingleSampleCount);
3811 	const bool	kMultisampleDS		= (activeSampleCount != kSingleSampleCount);
3812 
3813 	// Choose depth/stencil format.
3814 	const DepthStencilFormat* dsFormatInfo = nullptr;
3815 
3816 	for (const auto& kDepthStencilFormat : kDepthStencilFormats)
3817 	{
3818 		// This is how we'll attempt to create images later.
3819 		const auto dsImageInfo = makeImageCreateInfo(kDepthStencilFormat.imageFormat, kFramebufferExtent, activeSampleCount, kDSUsage, kDSCreateFlags);
3820 
3821 		vk::VkImageFormatProperties formatProps;
3822 		const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, dsImageInfo.format, dsImageInfo.imageType, dsImageInfo.tiling, dsImageInfo.usage, dsImageInfo.flags, &formatProps);
3823 
3824 		// Format not supported.
3825 		if (result != vk::VK_SUCCESS)
3826 			continue;
3827 
3828 		// Extent not big enough.
3829 		const auto& maxExtent = formatProps.maxExtent;
3830 		if (maxExtent.width < kFramebufferExtent.width || maxExtent.height < kFramebufferExtent.height || maxExtent.depth < kFramebufferExtent.depth)
3831 			continue;
3832 
3833 		// Sample count not supported.
3834 		if ((formatProps.sampleCounts & activeSampleCount) != activeSampleCount)
3835 			continue;
3836 
3837 		dsFormatInfo = &kDepthStencilFormat;
3838 		break;
3839 	}
3840 
3841 	// Note: Not Supported insted of Fail because some features are not mandatory.
3842 	if (!dsFormatInfo)
3843 		TCU_THROW(NotSupportedError, "Required depth/stencil image features not supported");
3844 	log << tcu::TestLog::Message << "Chosen depth/stencil format: " << dsFormatInfo->imageFormat << tcu::TestLog::EndMessage;
3845 
3846 	// Swap static and dynamic values in the test configuration so the static pipeline ends up with the expected values for cases
3847 	// where we will bind the static pipeline last before drawing.
3848 	if (kReversed)
3849 		m_testConfig.swapValues();
3850 
3851 	// Create color and depth/stencil images.
3852 	ImageWithMemoryVec colorImages;
3853 	ImageWithMemoryVec dsImages;
3854 	ImageWithMemoryVec resolveImages;
3855 
3856 	const auto colorImageInfo = makeImageCreateInfo(colorFormat, kFramebufferExtent, colorSampleCount, kColorUsage, 0u);
3857 	for (deUint32 i = 0u; i < kNumIterations * kColorAttCount; ++i)
3858 		colorImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, colorImageInfo, vk::MemoryRequirement::Any));
3859 
3860 	const auto dsImageInfo = makeImageCreateInfo(dsFormatInfo->imageFormat, kFramebufferExtent, activeSampleCount, kDSUsage, kDSCreateFlags);
3861 	for (deUint32 i = 0u; i < kNumIterations; ++i)
3862 		dsImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, dsImageInfo, vk::MemoryRequirement::Any));
3863 
3864 	if (kUseResolveAtt)
3865 	{
3866 		const auto resolveImageInfo = makeImageCreateInfo(colorFormat, kFramebufferExtent, kSingleSampleCount, kColorUsage, 0u);
3867 		for (uint32_t i = 0u; i < kNumIterations * kColorAttCount; ++i)
3868 			resolveImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, resolveImageInfo, vk::MemoryRequirement::Any));
3869 	}
3870 
3871 	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3872 	const auto dsSubresourceRange		= vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
3873 
3874 	ImageViewVec colorImageViews;
3875 	ImageViewVec dsImageViews;
3876 	ImageViewVec resolveImageViews;
3877 
3878 	for (const auto& img : colorImages)
3879 		colorImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
3880 
3881 	for (const auto& img : dsImages)
3882 		dsImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, dsFormatInfo->imageFormat, dsSubresourceRange));
3883 
3884 	for (const auto& img : resolveImages)
3885 		resolveImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
3886 
3887 	// Vertex buffer.
3888 	const auto				topologyClass	= getTopologyClass(m_testConfig.topologyConfig.staticValue);
3889 	std::vector<uint32_t>	indices;
3890 	std::vector<tcu::Vec2>	vertices;
3891 
3892 	if (m_testConfig.oversizedTriangle || m_testConfig.offCenterTriangle)
3893 	{
3894 		DE_ASSERT(topologyClass == TopologyClass::TRIANGLE);
3895 		DE_ASSERT(!m_testConfig.singleVertex);
3896 	}
3897 
3898 	if (m_testConfig.obliqueLine)
3899 		DE_ASSERT(topologyClass == TopologyClass::LINE);
3900 
3901 	if (topologyClass == TopologyClass::TRIANGLE)
3902 	{
3903 		// These indices are used for a subset of cases.
3904 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
3905 
3906 		if (m_testConfig.oversizedTriangle)
3907 		{
3908 			vertices.reserve(3u);
3909 			vertices.push_back(tcu::Vec2(-2.0f, -2.0f));
3910 			vertices.push_back(tcu::Vec2(-2.0f,  6.0f));
3911 			vertices.push_back(tcu::Vec2( 6.0f, -2.0f));
3912 		}
3913 		else if (m_testConfig.offCenterTriangle)
3914 		{
3915 			// Triangle covering the whole screen, except for the first row and column, which may not be covered by all samples.
3916 			const float horOffset	= 2.0f / static_cast<float>(kFramebufferWidth) * m_testConfig.offCenterProportion.x();
3917 			const float vertOffset	= 2.0f / static_cast<float>(kFramebufferHeight) * m_testConfig.offCenterProportion.y();
3918 
3919 			vertices.reserve(3u);
3920 			vertices.push_back(tcu::Vec2(-1.0f + horOffset, -1.0f + vertOffset));
3921 			vertices.push_back(tcu::Vec2(-1.0f + horOffset,               4.0f));
3922 			vertices.push_back(tcu::Vec2(             4.0f, -1.0f + vertOffset));
3923 		}
3924 		else
3925 		{
3926 			// Full-screen triangle strip with 6 vertices.
3927 			//
3928 			// 0        2        4
3929 			//  +-------+-------+
3930 			//  |      XX      X|
3931 			//  |     X X     X |
3932 			//  |    X  X    X  |
3933 			//  |   X   X   X   |
3934 			//  |  X    X  X    |
3935 			//  | X     X X     |
3936 			//  |X      XX      |
3937 			//  +-------+-------+
3938 			// 1        3       5
3939 			vertices.reserve(6u);
3940 			vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
3941 			vertices.push_back(tcu::Vec2(-1.0f,  1.0f));
3942 			vertices.push_back(tcu::Vec2( 0.0f, -1.0f));
3943 			vertices.push_back(tcu::Vec2( 0.0f,  1.0f));
3944 			vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
3945 			vertices.push_back(tcu::Vec2( 1.0f,  1.0f));
3946 		}
3947 	}
3948 	else if (topologyClass == TopologyClass::PATCH)
3949 	{
3950 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
3951 		DE_ASSERT(m_testConfig.getActivePatchControlPoints() > 1u);
3952 
3953 		// 2 triangles making a quad
3954 		vertices.reserve(6u);
3955 		vertices.push_back(tcu::Vec2(-1.0f,  1.0f));
3956 		vertices.push_back(tcu::Vec2( 1.0f,  1.0f));
3957 		vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
3958 		vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
3959 		vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
3960 		vertices.push_back(tcu::Vec2(-1.0f,  1.0f));
3961 	}
3962 	else // TopologyClass::LINE
3963 	{
3964 		const float pixelHeight	= 2.0f / static_cast<float>(kFramebufferHeight);
3965 		const float pixelWidth	= 2.0f / static_cast<float>(kFramebufferWidth);
3966 
3967 		if (m_testConfig.obliqueLine)
3968 		{
3969 			// The starting point of the oblique line is located in the top left pixel, in a position below and slightly to the left
3970 			// of the pixel center. The ending point is in the middle of the right side of the framebuffer. Those coordinates make
3971 			// sure that a bresenham-style line covers the center of the top left pixel, because the left edge of the line goes up
3972 			// vertically from that point. However, a rectangular line misses it by a small delta because its edge goes up and to
3973 			// the right, leaving the pixel center to its left. So the top left pixel itself may be covered or not depending on the
3974 			// active line rasterization mode.
3975 			//
3976 			// Note: results may also be affected by multisample and sample locations if those are used.
3977 			vertices.reserve(2u);
3978 			vertices.push_back(tcu::Vec2(pixelWidth * 7.0f / 16.0f - 1.0f, pixelHeight * 12.0f / 16.0f - 1.0f));
3979 			vertices.push_back(tcu::Vec2(1.0f, 0.0f));
3980 		}
3981 		else
3982 		{
3983 			DE_ASSERT(m_testConfig.getActivePrimRestartEnable());
3984 
3985 			// 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.
3986 			vertices.reserve(kFramebufferHeight * 4u);
3987 
3988 			if (m_testConfig.needsIndexBuffer())
3989 				indices.reserve(kFramebufferHeight * 5u);
3990 
3991 			for (deUint32 rowIdx = 0; rowIdx < kFramebufferHeight; ++rowIdx)
3992 			{
3993 				// Offset of 0.5 pixels + one pixel per row, from -1 to 1.
3994 				const float yCoord = (pixelHeight / 2.0f) + pixelHeight * static_cast<float>(rowIdx) - 1.0f;
3995 				vertices.push_back(tcu::Vec2(-1.0f, yCoord));
3996 				vertices.push_back(tcu::Vec2(-0.5f, yCoord));
3997 				vertices.push_back(tcu::Vec2( 0.5f, yCoord));
3998 				vertices.push_back(tcu::Vec2( 1.0f, yCoord));
3999 
4000 				if (m_testConfig.needsIndexBuffer())
4001 				{
4002 					indices.push_back(4u * rowIdx + 0u);
4003 					indices.push_back(4u * rowIdx + 1u);
4004 					indices.push_back(4u * rowIdx + 2u);
4005 					indices.push_back(4u * rowIdx + 3u);
4006 					indices.push_back(0xFFFFFFFFu); // Restart line strip.
4007 				}
4008 			}
4009 		}
4010 	}
4011 
4012 	if (m_testConfig.singleVertex)
4013 	{
4014 		DE_ASSERT(!m_testConfig.needsIndexBuffer());
4015 		vertices.resize(1);
4016 	}
4017 
4018 	// Reversed vertices order in triangle strip (1, 0, 3, 2, 5, 4)
4019 	std::vector<tcu::Vec2> rvertices;
4020 	if (topologyClass == TopologyClass::TRIANGLE)
4021 	{
4022 		DE_ASSERT(!vertices.empty());
4023 		if (m_testConfig.singleVertex)
4024 			rvertices.push_back(vertices[0]);
4025 		else if (m_testConfig.oversizedTriangle || m_testConfig.offCenterTriangle)
4026 		{
4027 			rvertices.reserve(3u);
4028 			rvertices.push_back(vertices[0]);
4029 			rvertices.push_back(vertices[2]);
4030 			rvertices.push_back(vertices[1]);
4031 		}
4032 		else
4033 		{
4034 			rvertices.reserve(6u);
4035 			rvertices.push_back(vertices[1]);
4036 			rvertices.push_back(vertices[0]);
4037 			rvertices.push_back(vertices[3]);
4038 			rvertices.push_back(vertices[2]);
4039 			rvertices.push_back(vertices[5]);
4040 			rvertices.push_back(vertices[4]);
4041 		}
4042 	}
4043 
4044 	if (topologyClass != TopologyClass::TRIANGLE)
4045 	{
4046 		for (const auto& mesh : m_testConfig.meshParams)
4047 		{
4048 			DE_UNREF(mesh); // For release builds.
4049 			DE_ASSERT(!mesh.reversed);
4050 		}
4051 	}
4052 
4053 	// Buffers with vertex data for the different bindings.
4054 	std::vector<VertexBufferInfo> vertBuffers;
4055 	std::vector<VertexBufferInfo> rvertBuffers;
4056 
4057 	{
4058 		const auto dataOffset	= static_cast<deUint32>(m_testConfig.vertexDataOffset);
4059 		const auto trailingSize	= static_cast<deUint32>(m_testConfig.vertexDataExtraBytes);
4060 		const auto generator	= m_testConfig.getActiveVertexGenerator();
4061 		prepareVertexBuffers(vertBuffers, vkd, device, allocator, generator, vertices, dataOffset, trailingSize, vertDataAsSSBO);
4062 		if (topologyClass == TopologyClass::TRIANGLE)
4063 			prepareVertexBuffers(rvertBuffers, vkd, device, allocator, generator, rvertices, dataOffset, trailingSize, vertDataAsSSBO);
4064 	}
4065 
4066 	// Index buffer.
4067 	BufferWithMemoryPtr indexBuffer;
4068 	if (!indices.empty())
4069 	{
4070 		const auto indexDataSize	= static_cast<vk::VkDeviceSize>(de::dataSize(indices));
4071 		const auto indexBufferInfo	= vk::makeBufferCreateInfo(indexDataSize, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
4072 
4073 		indexBuffer = BufferWithMemoryPtr(new vk::BufferWithMemory(vkd, device, allocator, indexBufferInfo, vk::MemoryRequirement::HostVisible));
4074 		copyAndFlush(vkd, device, *indexBuffer, 0, indices.data(), static_cast<size_t>(indexDataSize));
4075 	}
4076 
4077 	// Fragment counter buffer.
4078 	BufferWithMemoryPtr	counterBuffer;
4079 	const auto			counterBufferSize	= static_cast<vk::VkDeviceSize>(sizeof(uint32_t));
4080 
4081 	if (m_testConfig.representativeFragmentTest)
4082 	{
4083 		const auto		counterBufferInfo	= vk::makeBufferCreateInfo(counterBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
4084 		const uint32_t	initialValue		= 0u;
4085 
4086 		counterBuffer = BufferWithMemoryPtr(new vk::BufferWithMemory(vkd, device, allocator, counterBufferInfo, vk::MemoryRequirement::HostVisible));
4087 		copyAndFlush(vkd, device, *counterBuffer, 0u, &initialValue, static_cast<size_t>(counterBufferSize));
4088 	}
4089 
4090 	// Frag shader descriptor set layout.
4091 	vk::Move<vk::VkDescriptorSetLayout> fragSetLayout;
4092 	{
4093 		vk::DescriptorSetLayoutBuilder layoutBuilder;
4094 		if (m_testConfig.representativeFragmentTest)
4095 			layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
4096 		fragSetLayout = layoutBuilder.build(vkd, device);
4097 	}
4098 
4099 	// Descriptor pool and set.
4100 	vk::Move<vk::VkDescriptorPool>	fragDescriptorPool;
4101 	vk::Move<vk::VkDescriptorSet>	fragDescriptorSet;
4102 
4103 	if (m_testConfig.representativeFragmentTest)
4104 	{
4105 		vk::DescriptorPoolBuilder poolBuilder;
4106 		poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
4107 		fragDescriptorPool	= poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
4108 		fragDescriptorSet	= vk::makeDescriptorSet(vkd, device, fragDescriptorPool.get(), fragSetLayout.get());
4109 
4110 		vk::DescriptorSetUpdateBuilder updateBuilder;
4111 		const auto location = vk::DescriptorSetUpdateBuilder::Location::binding(0u);
4112 		const auto descInfo = vk::makeDescriptorBufferInfo(counterBuffer->get(), 0ull, counterBufferSize);
4113 		updateBuilder.writeSingle(fragDescriptorSet.get(), location, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descInfo);
4114 		updateBuilder.update(vkd, device);
4115 	}
4116 
4117 	// Push constant stages (matches SSBO stages if used).
4118 	vk::VkShaderStageFlags pushConstantStageFlags = (
4119 		(m_testConfig.useMeshShaders
4120 #ifndef CTS_USES_VULKANSC
4121 		 ? vk::VK_SHADER_STAGE_MESH_BIT_EXT
4122 #else
4123 		 ? 0
4124 #endif // CTS_USES_VULKANSC
4125 		 : vk::VK_SHADER_STAGE_VERTEX_BIT)
4126 		| vk::VK_SHADER_STAGE_FRAGMENT_BIT);
4127 
4128 	if (m_testConfig.needsGeometryShader())
4129 		pushConstantStageFlags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
4130 
4131 	// Mesh descriptor set layout.
4132 	vk::Move<vk::VkDescriptorSetLayout> meshSetLayout;
4133 	if (vertDataAsSSBO)
4134 	{
4135 		vk::DescriptorSetLayoutBuilder layoutBuilder;
4136 		for (size_t i = 0; i < vertBuffers.size(); ++i)
4137 			layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, pushConstantStageFlags);
4138 		meshSetLayout = layoutBuilder.build(vkd, device);
4139 	}
4140 
4141 	// Descriptor pool and set if needed.
4142 	vk::Move<vk::VkDescriptorPool>	meshDescriptorPool;
4143 	vk::Move<vk::VkDescriptorSet>	meshDescriptorSet;
4144 	vk::Move<vk::VkDescriptorSet>	meshDescriptorSetRev;
4145 
4146 	if (vertDataAsSSBO)
4147 	{
4148 		const auto					descType		= vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
4149 		vk::DescriptorPoolBuilder	poolBuilder;
4150 		poolBuilder.addType(descType, static_cast<uint32_t>(vertBuffers.size()) * 2u);
4151 
4152 		meshDescriptorPool		= poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
4153 		meshDescriptorSet		= vk::makeDescriptorSet(vkd, device, meshDescriptorPool.get(), meshSetLayout.get());
4154 		meshDescriptorSetRev	= vk::makeDescriptorSet(vkd, device, meshDescriptorPool.get(), meshSetLayout.get());
4155 
4156 		std::vector<vk::VkDescriptorBufferInfo> descBufferInfos;
4157 		std::vector<vk::VkDescriptorBufferInfo> descBufferInfosRev;
4158 		descBufferInfos.reserve(vertBuffers.size());
4159 		descBufferInfosRev.reserve(rvertBuffers.size());
4160 
4161 		vk::DescriptorSetUpdateBuilder updateBuilder;
4162 
4163 		DE_ASSERT(vertBuffers.size() == rvertBuffers.size());
4164 		for (size_t i = 0; i < vertBuffers.size(); ++i)
4165 		{
4166 			descBufferInfos.push_back(vk::makeDescriptorBufferInfo(vertBuffers[i].buffer->get(), vertBuffers[i].offset, vertBuffers[i].dataSize));
4167 			descBufferInfosRev.push_back(vk::makeDescriptorBufferInfo(rvertBuffers[i].buffer->get(), rvertBuffers[i].offset, rvertBuffers[i].dataSize));
4168 
4169 			const auto binding = vk::DescriptorSetUpdateBuilder::Location::binding(static_cast<uint32_t>(i));
4170 
4171 			updateBuilder.writeSingle(meshDescriptorSet.get(), binding, descType, &descBufferInfos.back());
4172 			updateBuilder.writeSingle(meshDescriptorSetRev.get(), binding, descType, &descBufferInfosRev.back());
4173 		}
4174 
4175 		updateBuilder.update(vkd, device);
4176 	}
4177 
4178 	// The frag shader descriptor set is the second one if both exist. See getFragDescriptorSetIndex().
4179 	std::vector<vk::VkDescriptorSetLayout> rawSetLayouts;
4180 
4181 	if (meshSetLayout.get() != VK_NULL_HANDLE)
4182 		rawSetLayouts.push_back(meshSetLayout.get());
4183 
4184 	if (fragSetLayout.get() != VK_NULL_HANDLE)
4185 		rawSetLayouts.push_back(fragSetLayout.get());
4186 
4187 	// Pipeline layout.
4188 	const vk::VkPushConstantRange pushConstantRange =
4189 	{
4190 		pushConstantStageFlags,							//	VkShaderStageFlags	stageFlags;
4191 		0u,												//	deUint32			offset;
4192 		static_cast<deUint32>(sizeof(PushConstants)),	//	deUint32			size;
4193 	};
4194 
4195 	const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
4196 	{
4197 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//	VkStructureType					sType;
4198 		nullptr,											//	const void*						pNext;
4199 		0u,													//	VkPipelineLayoutCreateFlags		flags;
4200 		de::sizeU32(rawSetLayouts),							//	deUint32						setLayoutCount;
4201 		de::dataOrNull(rawSetLayouts),						//	const VkDescriptorSetLayout*	pSetLayouts;
4202 		1u,													//	deUint32						pushConstantRangeCount;
4203 		&pushConstantRange,									//	const VkPushConstantRange*		pPushConstantRanges;
4204 	};
4205 	const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo);
4206 
4207 	// Render pass with single subpass. Attachment order:
4208 	// 1) Color attachments (kColorAttCount items).
4209 	// 2) DS attachment.
4210 	// 3) [optional] Resolve attachments (kColorAttCount).
4211 
4212 	DE_ASSERT(kColorAttCount > 0u);
4213 
4214 	std::vector<vk::VkAttachmentReference> colorAttachments;
4215 	std::vector<vk::VkAttachmentReference> resolveAttachments;
4216 
4217 	for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
4218 	{
4219 		colorAttachments.push_back(vk::makeAttachmentReference(colorAttIdx, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
4220 		if (kUseResolveAtt)
4221 			resolveAttachments.push_back(vk::makeAttachmentReference(kColorAttCount + 1u + colorAttIdx, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
4222 	}
4223 
4224 	const vk::VkAttachmentReference dsAttachmentReference =
4225 	{
4226 		kColorAttCount,											//	deUint32		attachment;
4227 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout	layout;
4228 	};
4229 
4230 	const vk::VkSubpassDescription subpassDescription =
4231 	{
4232 		0u,										//	VkSubpassDescriptionFlags		flags;
4233 		pipelineBindPoint,						//	VkPipelineBindPoint				pipelineBindPoint;
4234 		0u,										//	deUint32						inputAttachmentCount;
4235 		nullptr,								//	const VkAttachmentReference*	pInputAttachments;
4236 		kColorAttCount,							//	deUint32						colorAttachmentCount;
4237 		de::dataOrNull(colorAttachments),		//	const VkAttachmentReference*	pColorAttachments;
4238 		de::dataOrNull(resolveAttachments),		//	const VkAttachmentReference*	pResolveAttachments;
4239 		&dsAttachmentReference,					//	const VkAttachmentReference*	pDepthStencilAttachment;
4240 		0u,										//	deUint32						preserveAttachmentCount;
4241 		nullptr,								//	const deUint32*					pPreserveAttachments;
4242 	};
4243 
4244 	std::vector<vk::VkAttachmentDescription> attachmentDescriptions;
4245 
4246 	// For multisample, we care about the resolve attachment, not the color one.
4247 	const auto colorAttachmentStoreOp = (kUseResolveAtt ? vk::VK_ATTACHMENT_STORE_OP_DONT_CARE : vk::VK_ATTACHMENT_STORE_OP_STORE);
4248 
4249 	for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
4250 	{
4251 		attachmentDescriptions.push_back(vk::VkAttachmentDescription
4252 		{
4253 			0u,												//	VkAttachmentDescriptionFlags	flags;
4254 			colorFormat,									//	VkFormat						format;
4255 			colorSampleCount,								//	VkSampleCountFlagBits			samples;
4256 			vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				//	VkAttachmentLoadOp				loadOp;
4257 			colorAttachmentStoreOp,							//	VkAttachmentStoreOp				storeOp;
4258 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
4259 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
4260 			vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
4261 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
4262 		});
4263 	}
4264 
4265 	attachmentDescriptions.push_back(vk::VkAttachmentDescription
4266 	{
4267 		0u,														//	VkAttachmentDescriptionFlags	flags;
4268 		dsFormatInfo->imageFormat,								//	VkFormat						format;
4269 		activeSampleCount,										//	VkSampleCountFlagBits			samples;
4270 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
4271 		vk::VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
4272 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				stencilLoadOp;
4273 		vk::VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				stencilStoreOp;
4274 		vk::VK_IMAGE_LAYOUT_UNDEFINED,							//	VkImageLayout					initialLayout;
4275 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
4276 	});
4277 
4278 	if (kUseResolveAtt)
4279 	{
4280 		// Resolve attachments.
4281 		for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
4282 		{
4283 			attachmentDescriptions.push_back(vk::VkAttachmentDescription
4284 			{
4285 				0u,												//	VkAttachmentDescriptionFlags	flags;
4286 				colorFormat,									//	VkFormat						format;
4287 				kSingleSampleCount,								//	VkSampleCountFlagBits			samples;
4288 				vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				loadOp;
4289 				vk::VK_ATTACHMENT_STORE_OP_STORE,				//	VkAttachmentStoreOp				storeOp;
4290 				vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			//	VkAttachmentLoadOp				stencilLoadOp;
4291 				vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			//	VkAttachmentStoreOp				stencilStoreOp;
4292 				vk::VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout					initialLayout;
4293 				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout					finalLayout;
4294 			});
4295 		}
4296 	}
4297 
4298 	const vk::VkRenderPassCreateInfo renderPassCreateInfo =
4299 	{
4300 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			//	VkStructureType					sType;
4301 		nullptr,												//	const void*						pNext;
4302 		0u,														//	VkRenderPassCreateFlags			flags;
4303 		static_cast<deUint32>(attachmentDescriptions.size()),	//	deUint32						attachmentCount;
4304 		attachmentDescriptions.data(),							//	const VkAttachmentDescription*	pAttachments;
4305 		1u,														//	deUint32						subpassCount;
4306 		&subpassDescription,									//	const VkSubpassDescription*		pSubpasses;
4307 		0u,														//	deUint32						dependencyCount;
4308 		nullptr,												//	const VkSubpassDependency*		pDependencies;
4309 	};
4310 	const auto renderPass = vk::createRenderPass(vkd, device, &renderPassCreateInfo);
4311 
4312 	// Framebuffers.
4313 	FramebufferVec framebuffers;
4314 
4315 	DE_ASSERT(colorImageViews.size() == dsImageViews.size() * kColorAttCount);
4316 
4317 	if (kUseResolveAtt)
4318 		DE_ASSERT(colorImageViews.size() == resolveImageViews.size());
4319 
4320 	for (size_t iterIdx = 0; iterIdx < dsImageViews.size(); ++iterIdx)
4321 	{
4322 		std::vector<vk::VkImageView> attachments;
4323 
4324 		for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
4325 		{
4326 			const auto colorViewIdx = iterIdx * kColorAttCount + colorAttIdx;
4327 			attachments.push_back(colorImageViews[colorViewIdx].get());
4328 		}
4329 
4330 		attachments.push_back(dsImageViews[iterIdx].get());
4331 
4332 		if (kUseResolveAtt)
4333 		{
4334 			for (uint32_t resolveAttIdx = 0u; resolveAttIdx < kColorAttCount; ++resolveAttIdx)
4335 			{
4336 				const auto resolveViewIdx = iterIdx * kColorAttCount + resolveAttIdx;
4337 				attachments.push_back(resolveImageViews[resolveViewIdx].get());
4338 			}
4339 		}
4340 
4341 		const vk::VkFramebufferCreateInfo framebufferCreateInfo =
4342 		{
4343 			vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	//	VkStructureType				sType;
4344 			nullptr,										//	const void*					pNext;
4345 			0u,												//	VkFramebufferCreateFlags	flags;
4346 			renderPass.get(),								//	VkRenderPass				renderPass;
4347 			static_cast<deUint32>(attachments.size()),		//	deUint32					attachmentCount;
4348 			attachments.data(),								//	const VkImageView*			pAttachments;
4349 			kFramebufferWidth,								//	deUint32					width;
4350 			kFramebufferHeight,								//	deUint32					height;
4351 			1u,												//	deUint32					layers;
4352 		};
4353 
4354 		framebuffers.emplace_back(vk::createFramebuffer(vkd, device, &framebufferCreateInfo));
4355 	}
4356 
4357 	// Shader modules.
4358 	const auto&	binaries			= m_context.getBinaryCollection();
4359 	const auto	dynamicVertModule	= vk::createShaderModule(vkd, device, binaries.get("dynamicVert"));
4360 	const auto	staticVertModule	= vk::createShaderModule(vkd, device, binaries.get("staticVert"));
4361 	const auto	dynamicFragModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("dynamicFrag"), 0u);
4362 	const auto	staticFragModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("staticFrag"), 0u);
4363 	const auto	geomModule			= (m_testConfig.needsGeometryShader() ? vk::createShaderModule(vkd, device, binaries.get("geom")) : vk::Move<vk::VkShaderModule>());
4364 	const auto	tescModule			= (m_testConfig.needsTessellation() ? vk::createShaderModule(vkd, device, binaries.get("tesc")) : vk::Move<vk::VkShaderModule>());
4365 	const auto	teseModule			= (m_testConfig.needsTessellation() ? vk::createShaderModule(vkd, device, binaries.get("tese")) : vk::Move<vk::VkShaderModule>());
4366 	const auto	meshModule			= (m_testConfig.useMeshShaders ? vk::createShaderModule(vkd, device, binaries.get("mesh")) : vk::Move<vk::VkShaderModule>());
4367 	const auto	meshNoOutModule		= (m_testConfig.bindUnusedMeshShadingPipeline ? vk::createShaderModule(vkd, device, binaries.get("meshNoOut")) : vk::Move<vk::VkShaderModule>());
4368 
4369 	vk::Move<vk::VkShaderModule>	vertDPCPModule;
4370 	vk::Move<vk::VkShaderModule>	fragDPCPModule;
4371 
4372 	// Input state.
4373 	const auto vertexBindings	= m_testConfig.vertexGenerator.staticValue->getBindingDescriptions(m_testConfig.strideConfig.staticValue);
4374 	const auto vertexAttributes	= m_testConfig.vertexGenerator.staticValue->getAttributeDescriptions();
4375 
4376 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
4377 	{
4378 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
4379 		nullptr,														//	const void*									pNext;
4380 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
4381 		static_cast<deUint32>(vertexBindings.size()),					//	deUint32									vertexBindingDescriptionCount;
4382 		vertexBindings.data(),											//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
4383 		static_cast<deUint32>(vertexAttributes.size()),					//	deUint32									vertexAttributeDescriptionCount;
4384 		vertexAttributes.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4385 	};
4386 
4387 	// Input assembly.
4388 	const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
4389 	{
4390 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType							sType;
4391 		nullptr,															//	const void*								pNext;
4392 		0u,																	//	VkPipelineInputAssemblyStateCreateFlags	flags;
4393 		m_testConfig.topologyConfig.staticValue,							//	VkPrimitiveTopology						topology;
4394 		makeVkBool32(m_testConfig.primRestartEnableConfig.staticValue),		//	VkBool32								primitiveRestartEnable;
4395 	};
4396 
4397 	// Viewport state.
4398 	if (m_testConfig.viewportConfig.dynamicValue)
4399 		DE_ASSERT(m_testConfig.viewportConfig.dynamicValue.get().size() > 0u);
4400 	else
4401 		DE_ASSERT(m_testConfig.viewportConfig.staticValue.size() > 0u);
4402 
4403 	if (m_testConfig.scissorConfig.dynamicValue)
4404 		DE_ASSERT(m_testConfig.scissorConfig.dynamicValue.get().size() > 0u);
4405 	else
4406 		DE_ASSERT(m_testConfig.scissorConfig.staticValue.size() > 0u);
4407 
4408 	// Rasterization state.
4409 	void* multisamplePnext		= nullptr;
4410 	void* rasterizationPnext	= nullptr;
4411 	void* viewportPnext			= nullptr;
4412 
4413 #ifndef CTS_USES_VULKANSC
4414 	using RastStreamInfoPtr		= de::MovePtr<vk::VkPipelineRasterizationStateStreamCreateInfoEXT>;
4415 	using ProvokingVtxModePtr	= de::MovePtr<vk::VkPipelineRasterizationProvokingVertexStateCreateInfoEXT>;
4416 	using DepthClipControlPtr	= de::MovePtr<vk::VkPipelineViewportDepthClipControlCreateInfoEXT>;
4417 	using DepthClipEnablePtr	= de::MovePtr<vk::VkPipelineRasterizationDepthClipStateCreateInfoEXT>;
4418 	using LineRasterModePtr		= de::MovePtr<vk::VkPipelineRasterizationLineStateCreateInfoEXT>;
4419 	using ConservativeRastPtr	= de::MovePtr<vk::VkPipelineRasterizationConservativeStateCreateInfoEXT>;
4420 
4421 	RastStreamInfoPtr	pRasterizationStreamInfo;
4422 	const bool			staticStreamInfo			= static_cast<bool>(m_testConfig.rasterizationStreamConfig.staticValue);
4423 
4424 	if (staticStreamInfo)
4425 	{
4426 		pRasterizationStreamInfo = RastStreamInfoPtr(new vk::VkPipelineRasterizationStateStreamCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
4427 		pRasterizationStreamInfo->rasterizationStream = m_testConfig.rasterizationStreamConfig.staticValue.get();
4428 		rasterizationPnext = pRasterizationStreamInfo.get();
4429 	}
4430 
4431 	ProvokingVtxModePtr	pProvokingVertexModeInfo;
4432 	const bool			staticProvokingVtxInfo		= static_cast<bool>(m_testConfig.provokingVertexConfig.staticValue);
4433 
4434 	if (staticProvokingVtxInfo)
4435 	{
4436 		pProvokingVertexModeInfo = ProvokingVtxModePtr(new vk::VkPipelineRasterizationProvokingVertexStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
4437 		pProvokingVertexModeInfo->provokingVertexMode = makeProvokingVertexMode(m_testConfig.provokingVertexConfig.staticValue.get());
4438 		rasterizationPnext = pProvokingVertexModeInfo.get();
4439 	}
4440 
4441 	DepthClipEnablePtr	pDepthClipEnableInfo;
4442 	const bool			staticDepthClipEnableInfo	= static_cast<bool>(m_testConfig.depthClipEnableConfig.staticValue);
4443 
4444 	if (staticDepthClipEnableInfo)
4445 	{
4446 		pDepthClipEnableInfo = DepthClipEnablePtr(new vk::VkPipelineRasterizationDepthClipStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
4447 		pDepthClipEnableInfo->depthClipEnable = makeVkBool32(m_testConfig.depthClipEnableConfig.staticValue.get());
4448 		rasterizationPnext = pDepthClipEnableInfo.get();
4449 	}
4450 
4451 	DepthClipControlPtr	pDepthClipControlInfo;
4452 	const bool			staticDepthClipControlInfo	= static_cast<bool>(m_testConfig.negativeOneToOneConfig.staticValue);
4453 
4454 	if (staticDepthClipControlInfo)
4455 	{
4456 		pDepthClipControlInfo = DepthClipControlPtr(new vk::VkPipelineViewportDepthClipControlCreateInfoEXT(vk::initVulkanStructure(viewportPnext)));
4457 		pDepthClipControlInfo->negativeOneToOne = makeVkBool32(m_testConfig.negativeOneToOneConfig.staticValue.get());
4458 		viewportPnext = pDepthClipControlInfo.get();
4459 	}
4460 
4461 	LineRasterModePtr	pLineRasterModeInfo;
4462 
4463 	if (m_testConfig.lineRasterStruct())
4464 	{
4465 		DE_ASSERT(static_cast<bool>(m_testConfig.lineStippleParamsConfig.staticValue));
4466 
4467 		pLineRasterModeInfo = LineRasterModePtr(new vk::VkPipelineRasterizationLineStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
4468 		rasterizationPnext = pLineRasterModeInfo.get();
4469 
4470 		const auto&	lineRasterFeatures	= m_context.getLineRasterizationFeaturesEXT();
4471 		const auto	lineRasterMode		= selectLineRasterizationMode(lineRasterFeatures, m_testConfig.lineStippleSupportRequired(), m_testConfig.lineRasterModeConfig.staticValue);
4472 		const auto&	staticParams		= m_testConfig.lineStippleParamsConfig.staticValue.get();
4473 
4474 		pLineRasterModeInfo->stippledLineEnable		= m_testConfig.lineStippleEnableConfig.staticValue;
4475 		pLineRasterModeInfo->lineRasterizationMode	= makeLineRasterizationMode(lineRasterMode);
4476 		pLineRasterModeInfo->lineStippleFactor		= staticParams.factor;
4477 		pLineRasterModeInfo->lineStipplePattern		= staticParams.pattern;
4478 	}
4479 
4480 	ConservativeRastPtr	pConservativeRasterModeInfo;
4481 
4482 	if (m_testConfig.conservativeRasterStruct())
4483 	{
4484 		pConservativeRasterModeInfo = ConservativeRastPtr(new vk::VkPipelineRasterizationConservativeStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
4485 		rasterizationPnext = pConservativeRasterModeInfo.get();
4486 
4487 		pConservativeRasterModeInfo->conservativeRasterizationMode		= m_testConfig.conservativeRasterModeConfig.staticValue;
4488 		pConservativeRasterModeInfo->extraPrimitiveOverestimationSize	= m_testConfig.extraPrimitiveOverEstConfig.staticValue;
4489 	}
4490 #else
4491 	DE_ASSERT(false);
4492 #endif // CTS_USES_VULKANSC
4493 
4494 	const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
4495 	{
4496 		vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
4497 		rasterizationPnext,												//	const void*								pNext;
4498 		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
4499 		makeVkBool32(m_testConfig.depthClampEnableConfig.staticValue),	//	VkBool32								depthClampEnable;
4500 		makeVkBool32(m_testConfig.rastDiscardEnableConfig.staticValue),	//	VkBool32								rasterizerDiscardEnable;
4501 		m_testConfig.polygonModeConfig.staticValue,						//	VkPolygonMode							polygonMode;
4502 		m_testConfig.cullModeConfig.staticValue,						//	VkCullModeFlags							cullMode;
4503 		m_testConfig.frontFaceConfig.staticValue,						//	VkFrontFace								frontFace;
4504 		makeVkBool32(m_testConfig.depthBiasEnableConfig.staticValue),	//	VkBool32								depthBiasEnable;
4505 		m_testConfig.depthBiasConfig.staticValue.constantFactor,		//	float									depthBiasConstantFactor;
4506 		m_testConfig.depthBiasConfig.staticValue.clamp,					//	float									depthBiasClamp;
4507 		0.0f,															//	float									depthBiasSlopeFactor;
4508 		1.0f,															//	float									lineWidth;
4509 	};
4510 
4511 	using SampleLocationsPtr = de::MovePtr<vk::VkPipelineSampleLocationsStateCreateInfoEXT>;
4512 	SampleLocationsPtr						pSampleLocations;
4513 	std::vector<vk::VkSampleLocationEXT>	sampleLocationCoords;
4514 
4515 #ifndef CTS_USES_VULKANSC
4516 	using CoverageToColorPtr = de::MovePtr<vk::VkPipelineCoverageToColorStateCreateInfoNV>;
4517 	CoverageToColorPtr						pCoverageToColor;
4518 
4519 	using CoverageModulationPtr = de::MovePtr<vk::VkPipelineCoverageModulationStateCreateInfoNV>;
4520 	CoverageModulationPtr					pCoverageModulation;
4521 
4522 	using CoverageReductionPtr = de::MovePtr<vk::VkPipelineCoverageReductionStateCreateInfoNV>;
4523 	CoverageReductionPtr					pCoverageReduction;
4524 
4525 	using ViewportSwizzlePtr = de::MovePtr<vk::VkPipelineViewportSwizzleStateCreateInfoNV>;
4526 	ViewportSwizzlePtr						pViewportSwizzle;
4527 
4528 	using ShadingRateImagePtr = de::MovePtr<vk::VkPipelineViewportShadingRateImageStateCreateInfoNV>;
4529 	ShadingRateImagePtr						pShadingRateImage;
4530 
4531 	using ViewportWScalingPtr = de::MovePtr<vk::VkPipelineViewportWScalingStateCreateInfoNV>;
4532 	ViewportWScalingPtr						pViewportWScaling;
4533 
4534 	using ReprFragmentPtr = de::MovePtr<vk::VkPipelineRepresentativeFragmentTestStateCreateInfoNV>;
4535 	ReprFragmentPtr							pReprFragment;
4536 #endif // CTS_USES_VULKANSC
4537 
4538 	if (m_testConfig.sampleLocationsStruct())
4539 	{
4540 		pSampleLocations = SampleLocationsPtr(new vk::VkPipelineSampleLocationsStateCreateInfoEXT(vk::initVulkanStructure(multisamplePnext)));
4541 		multisamplePnext = pSampleLocations.get();
4542 
4543 		pSampleLocations->sampleLocationsEnable							= makeVkBool32(m_testConfig.sampleLocationsEnableConfig.staticValue);
4544 		pSampleLocations->sampleLocationsInfo							= vk::initVulkanStructure();
4545 		pSampleLocations->sampleLocationsInfo.sampleLocationsPerPixel	= activeSampleCount;
4546 		pSampleLocations->sampleLocationsInfo.sampleLocationGridSize	= vk::makeExtent2D(1u, 1u);
4547 		pSampleLocations->sampleLocationsInfo.sampleLocationsCount		= static_cast<uint32_t>(activeSampleCount);
4548 
4549 		sampleLocationCoords.reserve(pSampleLocations->sampleLocationsInfo.sampleLocationsCount);
4550 		for (uint32_t i = 0; i < pSampleLocations->sampleLocationsInfo.sampleLocationsCount; ++i)
4551 			sampleLocationCoords.push_back(vk::VkSampleLocationEXT{m_testConfig.sampleLocations.x(), m_testConfig.sampleLocations.y()});
4552 
4553 		pSampleLocations->sampleLocationsInfo.pSampleLocations = sampleLocationCoords.data();
4554 	}
4555 
4556 #ifndef CTS_USES_VULKANSC
4557 	if (m_testConfig.coverageToColorStruct())
4558 	{
4559 		pCoverageToColor = CoverageToColorPtr(new vk::VkPipelineCoverageToColorStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
4560 		multisamplePnext = pCoverageToColor.get();
4561 
4562 		pCoverageToColor->coverageToColorEnable		= makeVkBool32(m_testConfig.coverageToColorEnableConfig.staticValue);
4563 		pCoverageToColor->coverageToColorLocation	= m_testConfig.coverageToColorLocationConfig.staticValue;
4564 	}
4565 
4566 	if (m_testConfig.coverageModulation)
4567 	{
4568 		pCoverageModulation	= CoverageModulationPtr(new vk::VkPipelineCoverageModulationStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
4569 		multisamplePnext	= pCoverageModulation.get();
4570 
4571 		pCoverageModulation->coverageModulationMode			= m_testConfig.coverageModulationModeConfig.staticValue;
4572 		pCoverageModulation->coverageModulationTableEnable	= makeVkBool32(m_testConfig.coverageModTableEnableConfig.staticValue);
4573 		pCoverageModulation->coverageModulationTableCount	= static_cast<uint32_t>(m_testConfig.coverageModTableConfig.staticValue.size());
4574 		pCoverageModulation->pCoverageModulationTable		= de::dataOrNull(m_testConfig.coverageModTableConfig.staticValue);
4575 	}
4576 
4577 	if (m_testConfig.coverageReduction)
4578 	{
4579 		pCoverageReduction	= CoverageReductionPtr(new vk::VkPipelineCoverageReductionStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
4580 		multisamplePnext	= pCoverageReduction.get();
4581 
4582 		pCoverageReduction->coverageReductionMode = m_testConfig.coverageReductionModeConfig.staticValue;
4583 	}
4584 
4585 	if (m_testConfig.viewportSwizzle)
4586 	{
4587 		pViewportSwizzle	= ViewportSwizzlePtr(new vk::VkPipelineViewportSwizzleStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
4588 		viewportPnext		= pViewportSwizzle.get();
4589 
4590 		const auto& swizzleVec				= m_testConfig.viewportSwizzleConfig.staticValue;
4591 		pViewportSwizzle->viewportCount		= static_cast<uint32_t>(swizzleVec.size());
4592 		pViewportSwizzle->pViewportSwizzles	= de::dataOrNull(swizzleVec);
4593 	}
4594 
4595 	const vk::VkShadingRatePaletteEntryNV	defaultShadingRatePaletteEntry	= vk::VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV;
4596 	const auto								defaultShadingRatePalette		= vk::makeShadingRatePaletteNV(1u, &defaultShadingRatePaletteEntry);
4597 	std::vector<vk::VkShadingRatePaletteNV>	shadingRatePaletteVec;
4598 
4599 	const auto								defaultViewportWScalingFactors	= vk::makeViewportWScalingNV(-1.0f, -1.0f);
4600 	std::vector<vk::VkViewportWScalingNV>	viewportWScalingVec;
4601 
4602 	if (m_testConfig.shadingRateImage)
4603 	{
4604 		pShadingRateImage	= ShadingRateImagePtr(new vk::VkPipelineViewportShadingRateImageStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
4605 		viewportPnext		= pShadingRateImage.get();
4606 
4607 		const auto& viewportVec						= m_testConfig.getActiveViewportVec();
4608 		pShadingRateImage->shadingRateImageEnable	= makeVkBool32(m_testConfig.shadingRateImageEnableConfig.staticValue);
4609 		pShadingRateImage->viewportCount			= de::sizeU32(viewportVec);
4610 
4611 		shadingRatePaletteVec.resize(viewportVec.size(), defaultShadingRatePalette);
4612 		pShadingRateImage->pShadingRatePalettes = shadingRatePaletteVec.data();
4613 	}
4614 
4615 	if (m_testConfig.viewportWScaling)
4616 	{
4617 		pViewportWScaling	= ViewportWScalingPtr(new vk::VkPipelineViewportWScalingStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
4618 		viewportPnext		= pViewportWScaling.get();
4619 
4620 		const auto& viewportVec						= m_testConfig.getActiveViewportVec();
4621 		pViewportWScaling->viewportWScalingEnable	= makeVkBool32(m_testConfig.viewportWScalingEnableConfig.staticValue);
4622 		pViewportWScaling->viewportCount			= de::sizeU32(viewportVec);
4623 
4624 		viewportWScalingVec.resize(viewportVec.size(), defaultViewportWScalingFactors);
4625 		pViewportWScaling->pViewportWScalings = viewportWScalingVec.data();
4626 	}
4627 
4628 	if (m_testConfig.representativeFragmentTest)
4629 	{
4630 		pReprFragment = ReprFragmentPtr(new vk::VkPipelineRepresentativeFragmentTestStateCreateInfoNV(vk::initVulkanStructure()));
4631 		pReprFragment->representativeFragmentTestEnable = makeVkBool32(m_testConfig.reprFragTestEnableConfig.staticValue);
4632 	}
4633 #endif // CTS_USES_VULKANSC
4634 
4635 	// Multisample state.
4636 	const vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
4637 	{
4638 		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
4639 		multisamplePnext,												//	const void*								pNext;
4640 		0u,																//	VkPipelineMultisampleStateCreateFlags	flags;
4641 		m_testConfig.rasterizationSamplesConfig.staticValue,			//	VkSampleCountFlagBits					rasterizationSamples;
4642 		VK_FALSE,														//	VkBool32								sampleShadingEnable;
4643 		0.0f,															//	float									minSampleShading;
4644 		de::dataOrNull(m_testConfig.sampleMaskConfig.staticValue),		//	const VkSampleMask*						pSampleMask;
4645 		makeVkBool32(m_testConfig.alphaToCoverageConfig.staticValue),	//	VkBool32								alphaToCoverageEnable;
4646 		makeVkBool32(m_testConfig.alphaToOneConfig.staticValue),		//	VkBool32								alphaToOneEnable;
4647 	};
4648 
4649 	// Depth/stencil state.
4650 	vk::VkStencilOpState	staticFrontStencil;
4651 	vk::VkStencilOpState	staticBackStencil;
4652 	bool					staticFrontStencilSet	= false;
4653 	bool					staticBackStencilSet	= false;
4654 
4655 	// Common setup for the front and back operations.
4656 	staticFrontStencil.compareMask	= 0xFFu;
4657 	staticFrontStencil.writeMask	= 0xFFu;
4658 	staticFrontStencil.reference	= m_testConfig.referenceStencil;
4659 	staticBackStencil				= staticFrontStencil;
4660 
4661 	for (const auto& op : m_testConfig.stencilOpConfig.staticValue)
4662 	{
4663 		if ((op.faceMask & vk::VK_STENCIL_FACE_FRONT_BIT) != 0u)
4664 		{
4665 			copy(staticFrontStencil, op);
4666 			staticFrontStencilSet = true;
4667 		}
4668 		if ((op.faceMask & vk::VK_STENCIL_FACE_BACK_BIT) != 0u)
4669 		{
4670 			copy(staticBackStencil, op);
4671 			staticBackStencilSet = true;
4672 		}
4673 	}
4674 
4675 	// Default values for the static part.
4676 	if (!staticFrontStencilSet)
4677 		copy(staticFrontStencil, kDefaultStencilOpParams);
4678 	if (!staticBackStencilSet)
4679 		copy(staticBackStencil, kDefaultStencilOpParams);
4680 
4681 	const vk::VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
4682 	{
4683 		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		//	VkStructureType							sType;
4684 		nullptr,															//	const void*								pNext;
4685 		0u,																	//	VkPipelineDepthStencilStateCreateFlags	flags;
4686 		makeVkBool32(m_testConfig.depthTestEnableConfig.staticValue),		//	VkBool32								depthTestEnable;
4687 		makeVkBool32(m_testConfig.depthWriteEnableConfig.staticValue),		//	VkBool32								depthWriteEnable;
4688 		m_testConfig.depthCompareOpConfig.staticValue,						//	VkCompareOp								depthCompareOp;
4689 		makeVkBool32(m_testConfig.depthBoundsTestEnableConfig.staticValue),	//	VkBool32								depthBoundsTestEnable;
4690 		makeVkBool32(m_testConfig.stencilTestEnableConfig.staticValue),		//	VkBool32								stencilTestEnable;
4691 		staticFrontStencil,													//	VkStencilOpState						front;
4692 		staticBackStencil,													//	VkStencilOpState						back;
4693 		m_testConfig.minDepthBounds,										//	float									minDepthBounds;
4694 		m_testConfig.maxDepthBounds,										//	float									maxDepthBounds;
4695 	};
4696 
4697 	// Dynamic state. Here we will set all states which have a dynamic value.
4698 	const auto dynamicStates = m_testConfig.getDynamicStates();
4699 
4700 	const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
4701 	{
4702 		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
4703 		nullptr,													//	const void*							pNext;
4704 		0u,															//	VkPipelineDynamicStateCreateFlags	flags;
4705 		static_cast<deUint32>(dynamicStates.size()),				//	deUint32							dynamicStateCount;
4706 		de::dataOrNull(dynamicStates),								//	const VkDynamicState*				pDynamicStates;
4707 	};
4708 
4709 	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
4710 	{
4711 		makeVkBool32(m_testConfig.colorBlendEnableConfig.staticValue),			// VkBool32                 blendEnable
4712 		m_testConfig.colorBlendEquationConfig.staticValue.srcColorBlendFactor,	// VkBlendFactor            srcColorBlendFactor
4713 		m_testConfig.colorBlendEquationConfig.staticValue.dstColorBlendFactor,	// VkBlendFactor            dstColorBlendFactor
4714 		m_testConfig.colorBlendEquationConfig.staticValue.colorBlendOp,			// VkBlendOp                colorBlendOp
4715 		m_testConfig.colorBlendEquationConfig.staticValue.srcAlphaBlendFactor,	// VkBlendFactor            srcAlphaBlendFactor
4716 		m_testConfig.colorBlendEquationConfig.staticValue.dstAlphaBlendFactor,	// VkBlendFactor            dstAlphaBlendFactor
4717 		m_testConfig.colorBlendEquationConfig.staticValue.alphaBlendOp,			// VkBlendOp                alphaBlendOp
4718 		m_testConfig.colorWriteMaskConfig.staticValue,							// VkColorComponentFlags    colorWriteMask
4719 	};
4720 	const std::vector<vk::VkPipelineColorBlendAttachmentState> colorBlendAttachmentStateVec (kColorAttCount, colorBlendAttachmentState);
4721 
4722 	using ColorBlendAdvancedPtr = de::MovePtr<vk::VkPipelineColorBlendAdvancedStateCreateInfoEXT>;
4723 	ColorBlendAdvancedPtr pColorBlendAdvanced;
4724 
4725 	if (m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced())
4726 	{
4727 		pColorBlendAdvanced = ColorBlendAdvancedPtr(new vk::VkPipelineColorBlendAdvancedStateCreateInfoEXT(vk::initVulkanStructure()));
4728 		pColorBlendAdvanced->srcPremultiplied	= VK_TRUE;
4729 		pColorBlendAdvanced->dstPremultiplied	= VK_TRUE;
4730 		pColorBlendAdvanced->blendOverlap		= vk::VK_BLEND_OVERLAP_UNCORRELATED_EXT;
4731 	}
4732 
4733 	const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
4734 	{
4735 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType                               sType
4736 		pColorBlendAdvanced.get(),										// const void*                                   pNext
4737 		0u,																// VkPipelineColorBlendStateCreateFlags          flags
4738 		m_testConfig.logicOpEnableConfig.staticValue,					// VkBool32                                      logicOpEnable
4739 		m_testConfig.logicOpConfig.staticValue,							// VkLogicOp                                     logicOp
4740 		static_cast<uint32_t>(colorBlendAttachmentStateVec.size()),		// deUint32                                      attachmentCount
4741 		de::dataOrNull(colorBlendAttachmentStateVec),					// const VkPipelineColorBlendAttachmentState*    pAttachments
4742 		{ 0.0f, 0.0f, 0.0f, 0.0f }										// float                                         blendConstants[4]
4743 	};
4744 
4745 	vk::GraphicsPipelineWrapper	staticPipeline		(vkd, device, m_testConfig.pipelineConstructionType);
4746 	const bool					bindStaticFirst		= (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES	||
4747 													   kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES	||
4748 													   kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC);
4749 	const bool					useStaticPipeline	= (bindStaticFirst || kReversed);
4750 
4751 	// Create extra dynamic patch control points pipeline if needed.
4752 	vk::Move<vk::VkPipeline> extraDynPCPPipeline;
4753 
4754 	if (m_testConfig.useExtraDynPCPPipeline)
4755 	{
4756 		vertDPCPModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vertDPCP"));
4757 		fragDPCPModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("fragDPCP"));
4758 
4759 		const vk::VkPipelineVertexInputStateCreateInfo	extraDPCPInputState		= vk::initVulkanStructure();
4760 		const vk::VkDynamicState						extraDynamicState		= vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
4761 		const vk::VkPipelineDynamicStateCreateInfo		extraDynamicStateInfo	=
4762 		{
4763 			vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
4764 			nullptr,													//	const void*							pNext;
4765 			0u,															//	VkPipelineDynamicStateCreateFlags	flags;
4766 			1u,															//	uint32_t							dynamicStateCount;
4767 			&extraDynamicState,												//	const VkDynamicState*				pDynamicStates;
4768 		};
4769 
4770 		const auto extraPipelineLayout = vk::makePipelineLayout(vkd, device);
4771 
4772 		const auto viewports	= m_testConfig.viewportConfig.staticValue;
4773 		const auto scissors		= m_testConfig.scissorConfig.staticValue;
4774 
4775 		extraDynPCPPipeline = vk::makeGraphicsPipeline(
4776 			vkd, device, *extraPipelineLayout,
4777 			vertDPCPModule.get(), DE_NULL, DE_NULL, DE_NULL, fragDPCPModule.get(),
4778 			renderPass.get(), viewports, scissors, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
4779 			&extraDPCPInputState, nullptr, nullptr, nullptr, nullptr, &extraDynamicStateInfo);
4780 	}
4781 
4782 	// Create static pipeline when needed.
4783 	if (useStaticPipeline)
4784 	{
4785 		auto viewports	= m_testConfig.viewportConfig.staticValue;
4786 		auto scissors	= m_testConfig.scissorConfig.staticValue;
4787 
4788 		// The viewport and scissor counts must match in the static part, which will be used by the static pipeline.
4789 		const auto minStaticCount = static_cast<deUint32>(std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
4790 		viewports.resize(minStaticCount);
4791 		scissors.resize(minStaticCount);
4792 
4793 		staticPipeline.setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
4794 					  .setViewportStatePnext(viewportPnext)
4795 					  .setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue);
4796 
4797 
4798 #ifndef CTS_USES_VULKANSC
4799 		if (m_testConfig.useMeshShaders)
4800 		{
4801 			staticPipeline.setupPreRasterizationMeshShaderState(
4802 												viewports,
4803 												scissors,
4804 												*pipelineLayout,
4805 												*renderPass,
4806 												0u,
4807 												VK_NULL_HANDLE,
4808 												*meshModule,
4809 												&rasterizationStateCreateInfo);
4810 		}
4811 		else
4812 #endif // CTS_USES_VULKANSC
4813 		{
4814 			staticPipeline.setupVertexInputState(&vertexInputStateCreateInfo, &inputAssemblyStateCreateInfo)
4815 						  .setupPreRasterizationShaderState(
4816 												viewports,
4817 												scissors,
4818 												*pipelineLayout,
4819 												*renderPass,
4820 												0u,
4821 												*staticVertModule,
4822 												&rasterizationStateCreateInfo,
4823 												*tescModule,
4824 												*teseModule,
4825 												*geomModule);
4826 		}
4827 
4828 		staticPipeline
4829 #ifndef CTS_USES_VULKANSC
4830 					  .setRepresentativeFragmentTestState(pReprFragment.get())
4831 #endif // CTS_USES_VULKANSC
4832 					  .setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, *staticFragModule, &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
4833 					  .setupFragmentOutputState(*renderPass, 0u, &colorBlendStateCreateInfo, &multisampleStateCreateInfo)
4834 					  .setMonolithicPipelineLayout(*pipelineLayout)
4835 					  .buildPipeline();
4836 	}
4837 
4838 	// Create dynamic pipeline.
4839 	vk::GraphicsPipelineWrapper graphicsPipeline(vkd, device, m_testConfig.pipelineConstructionType);
4840 	{
4841 		auto viewports	= m_testConfig.viewportConfig.staticValue;
4842 		auto scissors	= m_testConfig.scissorConfig.staticValue;
4843 
4844 		const auto finalDynamicViewportCount = (m_testConfig.viewportConfig.dynamicValue
4845 			? m_testConfig.viewportConfig.dynamicValue.get().size()
4846 			: m_testConfig.viewportConfig.staticValue.size());
4847 
4848 		const auto finalDynamicScissorCount = (m_testConfig.scissorConfig.dynamicValue
4849 			? m_testConfig.scissorConfig.dynamicValue.get().size()
4850 			: m_testConfig.scissorConfig.staticValue.size());
4851 
4852 		const auto minDynamicCount = static_cast<deUint32>(std::min(finalDynamicScissorCount, finalDynamicViewportCount));
4853 
4854 		// The viewport and scissor counts must be zero when a dynamic value will be provided, as per the spec.
4855 		if (m_testConfig.viewportConfig.dynamicValue)
4856 		{
4857 			graphicsPipeline.setDefaultViewportsCount();
4858 			viewports = std::vector<vk::VkViewport>();
4859 		}
4860 		else
4861 			viewports.resize(minDynamicCount);
4862 
4863 		if (m_testConfig.scissorConfig.dynamicValue)
4864 		{
4865 			graphicsPipeline.setDefaultScissorsCount();
4866 			scissors = std::vector<vk::VkRect2D>();
4867 		}
4868 		else
4869 			scissors.resize(minDynamicCount);
4870 
4871 		graphicsPipeline.setDynamicState(&dynamicStateCreateInfo)
4872 						.setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
4873 						.setViewportStatePnext(viewportPnext)
4874 						.setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue);
4875 
4876 #ifndef CTS_USES_VULKANSC
4877 		if (m_testConfig.useMeshShaders)
4878 		{
4879 			graphicsPipeline.setupPreRasterizationMeshShaderState(
4880 												viewports,
4881 												scissors,
4882 												*pipelineLayout,
4883 												*renderPass,
4884 												0u,
4885 												DE_NULL,
4886 												*meshModule,
4887 												&rasterizationStateCreateInfo);
4888 		}
4889 		else
4890 #endif // CTS_USES_VULKANSC
4891 		{
4892 			graphicsPipeline.setupVertexInputState(&vertexInputStateCreateInfo, &inputAssemblyStateCreateInfo)
4893 							.setupPreRasterizationShaderState(
4894 												viewports,
4895 												scissors,
4896 												*pipelineLayout,
4897 												*renderPass,
4898 												0u,
4899 												*dynamicVertModule,
4900 												&rasterizationStateCreateInfo,
4901 												*tescModule,
4902 												*teseModule,
4903 												*geomModule);
4904 		}
4905 
4906 		graphicsPipeline
4907 #ifndef CTS_USES_VULKANSC
4908 						.setRepresentativeFragmentTestState(pReprFragment.get())
4909 #endif // CTS_USES_VULKANSC
4910 						.setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, *dynamicFragModule, &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
4911 						.setupFragmentOutputState(*renderPass, 0u, &colorBlendStateCreateInfo, &multisampleStateCreateInfo)
4912 						.setMonolithicPipelineLayout(*pipelineLayout)
4913 						.buildPipeline();
4914 	}
4915 
4916 	vk::GraphicsPipelineWrapper meshNoOutPipeline(vkd, device, m_testConfig.pipelineConstructionType);
4917 
4918 #ifndef CTS_USES_VULKANSC
4919 	if (m_testConfig.bindUnusedMeshShadingPipeline)
4920 	{
4921 		// Remove dynamic states which are not compatible with mesh shading pipelines.
4922 		std::vector<vk::VkDynamicState> meshNoOutDynamicStates;
4923 		std::copy_if(begin(dynamicStates), end(dynamicStates), std::back_inserter(meshNoOutDynamicStates), isMeshShadingPipelineCompatible);
4924 
4925 		const vk::VkPipelineDynamicStateCreateInfo meshNoOutDynamicStateInfo =
4926 		{
4927 			vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
4928 			nullptr,													//	const void*							pNext;
4929 			0u,															//	VkPipelineDynamicStateCreateFlags	flags;
4930 			de::sizeU32(meshNoOutDynamicStates),						//	uint32_t							dynamicStateCount;
4931 			de::dataOrNull(meshNoOutDynamicStates),						//	const VkDynamicState*				pDynamicStates;
4932 		};
4933 
4934 		// Provide a viewport state similar to the static pipeline.
4935 		auto viewports	= m_testConfig.viewportConfig.staticValue;
4936 		auto scissors	= m_testConfig.scissorConfig.staticValue;
4937 
4938 		const auto minStaticCount = static_cast<deUint32>(std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
4939 		viewports.resize(minStaticCount);
4940 		scissors.resize(minStaticCount);
4941 
4942 		meshNoOutPipeline.setDynamicState(&meshNoOutDynamicStateInfo)
4943 						 .setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
4944 						 .setupPreRasterizationMeshShaderState(
4945 											viewports,
4946 											scissors,
4947 											*pipelineLayout,
4948 											*renderPass,
4949 											0u,
4950 											VK_NULL_HANDLE,
4951 											*meshNoOutModule,
4952 											&rasterizationStateCreateInfo)
4953 						 .setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, VK_NULL_HANDLE, &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
4954 						 .setupFragmentOutputState(*renderPass, 0u, &colorBlendStateCreateInfo, &multisampleStateCreateInfo)
4955 						 .setMonolithicPipelineLayout(*pipelineLayout)
4956 						 .buildPipeline();
4957 	}
4958 #endif // CTS_USES_VULKANSC
4959 
4960 	// Command buffer.
4961 	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
4962 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd , device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
4963 	const auto cmdBuffer	= cmdBufferPtr.get();
4964 
4965 	// Clear values, clear to green for dynamic logicOp
4966 	std::vector<vk::VkClearValue> clearValues (kColorAttCount, m_testConfig.clearColorValue);
4967 	clearValues.push_back(vk::makeClearValueDepthStencil(m_testConfig.clearDepthValue, m_testConfig.clearStencilValue));
4968 
4969 	// Record command buffer.
4970 	vk::beginCommandBuffer(vkd, cmdBuffer);
4971 
4972 	for (deUint32 iteration = 0u; iteration < kNumIterations; ++iteration)
4973 	{
4974 		// Track in-advance vertex buffer binding.
4975 		bool boundInAdvance = false;
4976 
4977 		// Maybe set extended dynamic state here.
4978 		if (kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START)
4979 		{
4980 			setDynamicStates(m_testConfig, vkd, cmdBuffer);
4981 			boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
4982 		}
4983 
4984 		// Begin render pass.
4985 		vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffers[iteration].get(), vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
4986 
4987 			// Bind a static pipeline first if needed.
4988 			if (bindStaticFirst && iteration == 0u)
4989 				vkd.cmdBindPipeline(cmdBuffer, pipelineBindPoint, staticPipeline.getPipeline());
4990 
4991 			// Maybe set extended dynamic state here.
4992 			if (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES)
4993 			{
4994 				setDynamicStates(m_testConfig, vkd, cmdBuffer);
4995 				boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
4996 			}
4997 
4998 			// Bind dynamic pipeline.
4999 			if ((kSequenceOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC &&
5000 				 kSequenceOrdering != SequenceOrdering::TWO_DRAWS_STATIC) ||
5001 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
5002 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
5003 			{
5004 				if (m_testConfig.bindUnusedMeshShadingPipeline)
5005 				{
5006 					DE_ASSERT(kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START);
5007 					vkd.cmdBindPipeline(cmdBuffer, pipelineBindPoint, meshNoOutPipeline.getPipeline());
5008 				}
5009 
5010 				if (m_testConfig.useExtraDynPCPPipeline)
5011 				{
5012 					vkd.cmdBindPipeline(cmdBuffer, pipelineBindPoint, extraDynPCPPipeline.get());
5013 
5014 					// In these two sequence orderings, the right dynamic state value will have been set before and we would be
5015 					// setting it to a wrong value here, resulting in test failures. We keep the right value instead.
5016 					if (kSequenceOrdering != SequenceOrdering::CMD_BUFFER_START && kSequenceOrdering != SequenceOrdering::BETWEEN_PIPELINES)
5017 						vkd.cmdSetPatchControlPointsEXT(cmdBuffer, m_testConfig.patchControlPointsConfig.staticValue);
5018 
5019 					vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
5020 				}
5021 
5022 				vkd.cmdBindPipeline(cmdBuffer, pipelineBindPoint, graphicsPipeline.getPipeline());
5023 			}
5024 
5025 			if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
5026 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
5027 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
5028 			{
5029 				setDynamicStates(m_testConfig, vkd, cmdBuffer);
5030 				boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
5031 			}
5032 
5033 			// Bind a static pipeline last if needed.
5034 			if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
5035 				(kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration > 0u))
5036 			{
5037 				vkd.cmdBindPipeline(cmdBuffer, pipelineBindPoint, staticPipeline.getPipeline());
5038 			}
5039 
5040 			const auto& viewportVec = m_testConfig.getActiveViewportVec();
5041 			for (size_t viewportIdx = 0u; viewportIdx < viewportVec.size(); ++viewportIdx)
5042 			{
5043 				for (size_t meshIdx = 0u; meshIdx < m_testConfig.meshParams.size(); ++meshIdx)
5044 				{
5045 					// Push constants.
5046 					PushConstants pushConstants =
5047 					{
5048 						m_testConfig.meshParams[meshIdx].color,			//	tcu::Vec4	triangleColor;
5049 						m_testConfig.meshParams[meshIdx].depth,			//	float		meshDepth;
5050 						static_cast<deInt32>(viewportIdx),				//	deInt32		viewPortIndex;
5051 						m_testConfig.meshParams[meshIdx].scaleX,		//	float		scaleX;
5052 						m_testConfig.meshParams[meshIdx].scaleY,		//	float		scaleY;
5053 						m_testConfig.meshParams[meshIdx].offsetX,		//	float		offsetX;
5054 						m_testConfig.meshParams[meshIdx].offsetY,		//	float		offsetY;
5055 						m_testConfig.meshParams[meshIdx].stripScale,	//	float		stripScale;
5056 					};
5057 					vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantStageFlags, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
5058 
5059 					// Track vertex bounding state for this mesh.
5060 					bool boundBeforeDraw = false;
5061 
5062 					// Maybe set extended dynamic state here.
5063 					if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW || kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES)
5064 					{
5065 						setDynamicStates(m_testConfig, vkd, cmdBuffer);
5066 						boundBeforeDraw = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, meshIdx, vertBuffers, rvertBuffers);
5067 					}
5068 
5069 					// Bind vertex buffer with static stride if needed and draw.
5070 					if (!(boundInAdvance || boundBeforeDraw) && !m_testConfig.useMeshShaders)
5071 					{
5072 						bindVertexBuffers(vkd, cmdBuffer, (m_testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers));
5073 						if (m_testConfig.needsIndexBuffer())
5074 						{
5075 							const auto indexType = vk::VK_INDEX_TYPE_UINT32;
5076 							vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer->get(), 0, indexType);
5077 						}
5078 					}
5079 
5080 					if (vertDataAsSSBO)
5081 					{
5082 						const auto boundSet = (m_testConfig.meshParams[meshIdx].reversed ? meshDescriptorSetRev.get() : meshDescriptorSet.get());
5083 						vkd.cmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, pipelineLayout.get(), 0u, 1u, &boundSet, 0u, nullptr);
5084 					}
5085 
5086 #ifndef CTS_USES_VULKANSC
5087 					// Shading rate image if enabled (we'll use a null handle to simplify, which is valid).
5088 					if (m_testConfig.shadingRateImage)
5089 						vkd.cmdBindShadingRateImageNV(cmdBuffer, VK_NULL_HANDLE, vk::VK_IMAGE_LAYOUT_GENERAL);
5090 #endif // CTS_USES_VULKANSC
5091 
5092 					if (m_testConfig.representativeFragmentTest)
5093 						vkd.cmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, pipelineLayout.get(), m_testConfig.getFragDescriptorSetIndex(), 1u, &fragDescriptorSet.get(), 0u, nullptr);
5094 
5095 					// Draw mesh.
5096 					if (m_testConfig.needsIndexBuffer())
5097 					{
5098 						deUint32 numIndices = static_cast<deUint32>(indices.size());
5099 						// For SequenceOrdering::TWO_DRAWS_DYNAMIC and TWO_DRAWS_STATIC cases, the first draw does not have primitive restart enabled
5100 						// So, draw without using the invalid index, the second draw with primitive restart enabled will replace the results
5101 						// using all indices.
5102 						if (iteration == 0u && m_testConfig.testPrimRestartEnable() &&
5103 							(m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
5104 							m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
5105 						{
5106 							numIndices = 3u;
5107 						}
5108 						vkd.cmdDrawIndexed(cmdBuffer, numIndices, 1u, 0u, 0u, 0u);
5109 					}
5110 #ifndef CTS_USES_VULKANSC
5111 					else if (m_testConfig.useMeshShaders)
5112 					{
5113 						// Make sure drawing this way makes sense.
5114 						DE_ASSERT(vertices.size() > 2u);
5115 						DE_ASSERT(!m_testConfig.topologyConfig.dynamicValue);
5116 						DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
5117 
5118 						const auto numPrimitives = static_cast<uint32_t>(vertices.size()) - 2u;
5119 						vkd.cmdDrawMeshTasksEXT(cmdBuffer, numPrimitives, 1u, 1u);
5120 					}
5121 #endif // CTS_USES_VULKANSC
5122 					else
5123 					{
5124 						deUint32 vertex_count = static_cast<deUint32>(vertices.size());
5125 						if (m_testConfig.singleVertex)
5126 							vertex_count = m_testConfig.singleVertexDrawCount;
5127 						vkd.cmdDraw(cmdBuffer, vertex_count, 1u, 0u, 0u);
5128 					}
5129 				}
5130 			}
5131 
5132 		vk::endRenderPass(vkd, cmdBuffer);
5133 	}
5134 
5135 	if (m_testConfig.representativeFragmentTest)
5136 	{
5137 		const auto bufferBarrier = vk::makeMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT);
5138 		vk::cmdPipelineMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, &bufferBarrier);
5139 	}
5140 
5141 	vk::endCommandBuffer(vkd, cmdBuffer);
5142 
5143 	// Submit commands.
5144 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
5145 
5146 	// Read result image aspects from the last used framebuffer.
5147 	using LevelPtr = de::MovePtr<tcu::TextureLevel>;
5148 
5149 	const tcu::UVec2	renderSize		(kFramebufferWidth, kFramebufferHeight);
5150 
5151 	const auto			colorResultImg	= (kUseResolveAtt ? resolveImages.back()->get() : colorImages.back()->get());
5152 	const auto			colorBuffer		= readColorAttachment(vkd, device, queue, queueIndex, allocator, colorResultImg, colorFormat, renderSize);
5153 	const auto			colorAccess		= colorBuffer->getAccess();
5154 
5155 	LevelPtr				depthBuffer;
5156 	LevelPtr				stencilBuffer;
5157 	tcu::PixelBufferAccess	depthAccess;
5158 	tcu::PixelBufferAccess	stencilAccess;
5159 
5160 	if (!kMultisampleDS)
5161 	{
5162 		depthBuffer		= readDepthAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize);
5163 		stencilBuffer	= readStencilAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
5164 		depthAccess		= depthBuffer->getAccess();
5165 		stencilAccess	= stencilBuffer->getAccess();
5166 	}
5167 
5168 	const int kWidth	= static_cast<int>(kFramebufferWidth);
5169 	const int kHeight	= static_cast<int>(kFramebufferHeight);
5170 
5171 	// Generate reference color buffer.
5172 	const auto				tcuColorFormat			= vk::mapVkFormat(colorFormat);
5173 	tcu::TextureLevel		referenceColorLevel		(tcuColorFormat, kWidth, kHeight);
5174 	tcu::PixelBufferAccess	referenceColorAccess	= referenceColorLevel.getAccess();
5175 	(*m_testConfig.referenceColor)(referenceColorAccess);
5176 
5177 	const tcu::TextureFormat	errorFormat			(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
5178 	tcu::TextureLevel			colorError			(errorFormat, kWidth, kHeight);
5179 	tcu::TextureLevel			depthError			(errorFormat, kWidth, kHeight);
5180 	tcu::TextureLevel			stencilError		(errorFormat, kWidth, kHeight);
5181 	const auto					colorErrorAccess	= colorError.getAccess();
5182 	const auto					depthErrorAccess	= depthError.getAccess();
5183 	const auto					stencilErrorAccess	= stencilError.getAccess();
5184 	const tcu::Vec4				kGood				(0.0f, 1.0f, 0.0f, 1.0f);
5185 	const tcu::Vec4				kBad				(1.0f, 0.0f, 0.0f, 1.0f);
5186 
5187 	// Check expected values.
5188 	const bool	hasCustomVerif	= static_cast<bool>(m_testConfig.colorVerificator);
5189 	const auto	minDepth		= m_testConfig.expectedDepth - dsFormatInfo->depthThreshold;
5190 	const auto	maxDepth		= m_testConfig.expectedDepth + dsFormatInfo->depthThreshold;
5191 	bool		colorMatch		= true;
5192 	bool		depthMatch		= true;
5193 	bool		stencilMatch	= true;
5194 	bool		match;
5195 
5196 	if (hasCustomVerif)
5197 		colorMatch = (*m_testConfig.colorVerificator)(colorAccess, referenceColorAccess, colorErrorAccess);
5198 
5199 	for (int y = 0; y < kHeight; ++y)
5200 		for (int x = 0; x < kWidth; ++x)
5201 		{
5202 			if (!hasCustomVerif)
5203 			{
5204 				if (vk::isUnormFormat(colorFormat))
5205 				{
5206 					const auto colorPixel		= colorAccess.getPixel(x, y);
5207 					const auto expectedPixel	= referenceColorAccess.getPixel(x, y);
5208 					match = tcu::boolAll(tcu::lessThan(tcu::absDiff(colorPixel, expectedPixel), kUnormColorThreshold));
5209 				}
5210 				else
5211 				{
5212 					DE_ASSERT(vk::isUintFormat(colorFormat));
5213 					const auto colorPixel		= colorAccess.getPixelUint(x, y);
5214 					const auto expectedPixel	= referenceColorAccess.getPixelUint(x, y);
5215 					match = (colorPixel == expectedPixel);
5216 				}
5217 
5218 				colorErrorAccess.setPixel((match ? kGood : kBad), x, y);
5219 				if (!match)
5220 					colorMatch = false;
5221 			}
5222 
5223 			if (!kMultisampleDS)
5224 			{
5225 				const auto depthPixel = depthAccess.getPixDepth(x, y);
5226 				match = de::inRange(depthPixel, minDepth, maxDepth);
5227 				depthErrorAccess.setPixel((match ? kGood : kBad), x, y);
5228 				if (!match)
5229 					depthMatch = false;
5230 
5231 				const auto stencilPixel = static_cast<deUint32>(stencilAccess.getPixStencil(x, y));
5232 				match = (stencilPixel == m_testConfig.expectedStencil);
5233 				stencilErrorAccess.setPixel((match ? kGood : kBad), x, y);
5234 				if (!match)
5235 					stencilMatch = false;
5236 			}
5237 		}
5238 
5239 	if (!colorMatch)
5240 		logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
5241 
5242 	if (!depthMatch)
5243 		logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
5244 
5245 	if (!stencilMatch)
5246 		logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
5247 
5248 	if (!(colorMatch && depthMatch && stencilMatch))
5249 	{
5250 		if (!colorMatch)
5251 			logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
5252 
5253 		if (!depthMatch)
5254 			logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
5255 
5256 		if (!stencilMatch)
5257 			logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
5258 
5259 		if (!(colorMatch && depthMatch && stencilMatch))
5260 			return tcu::TestStatus::fail("Incorrect value found in attachments; please check logged images");
5261 	}
5262 
5263 	// Check storage buffer if used.
5264 	if (m_testConfig.representativeFragmentTest)
5265 	{
5266 		DE_ASSERT(m_testConfig.oversizedTriangle);
5267 		DE_ASSERT(m_testConfig.meshParams.size() == 1u);
5268 		DE_ASSERT(!m_testConfig.depthWriteEnableConfig.dynamicValue);	// No dynamic value for depth writes.
5269 		DE_ASSERT(!m_testConfig.depthWriteEnableConfig.staticValue);	// No depth writes.
5270 
5271 		// The expected number of invocations depends on how many draws are performed with the test enabled.
5272 		// Draws with the test disabled should always result in kFramebufferHeight * kFramebufferWidth invocations.
5273 		// Draws with the test enabled should result in at least 1 invocation, maybe more.
5274 		uint32_t minValue = 0u;
5275 
5276 		const uint32_t minInvocations[] = { (kFramebufferHeight * kFramebufferWidth), 1u };
5277 
5278 		if (kNumIterations == 1u)
5279 		{
5280 			const auto testEnabled	= m_testConfig.getActiveReprFragTestEnable();
5281 			minValue += minInvocations[testEnabled];
5282 		}
5283 		else if (kNumIterations == 2u)
5284 		{
5285 
5286 			for (uint32_t i = 0u; i < kNumIterations; ++i)
5287 			{
5288 				bool testEnabled = false;
5289 
5290 #ifndef CTS_USES_VULKANSC
5291 				// Actually varies depending on TWO_DRAWS_STATIC/_DYNAMIC, but does not affect results.
5292 				const bool staticDraw = (i == 0u);
5293 
5294 				if (staticDraw)
5295 					testEnabled = m_testConfig.reprFragTestEnableConfig.staticValue;
5296 				else
5297 				{
5298 					testEnabled	= (m_testConfig.reprFragTestEnableConfig.dynamicValue
5299 								? m_testConfig.reprFragTestEnableConfig.dynamicValue.get()
5300 								: m_testConfig.reprFragTestEnableConfig.staticValue);
5301 				}
5302 #endif // CTS_USES_VULKANSC
5303 
5304 				minValue += minInvocations[testEnabled];
5305 			}
5306 		}
5307 		else
5308 		{
5309 			DE_ASSERT(false);
5310 		}
5311 
5312 		auto& counterBufferAlloc	= counterBuffer->getAllocation();
5313 		void* counterBufferData		= counterBufferAlloc.getHostPtr();
5314 		vk::invalidateAlloc(vkd, device, counterBufferAlloc);
5315 
5316 		uint32_t fragCounter;
5317 		deMemcpy(&fragCounter, counterBufferData, sizeof(fragCounter));
5318 
5319 		log << tcu::TestLog::Message << "Fragment counter minimum value: " << minValue << tcu::TestLog::EndMessage;
5320 		log << tcu::TestLog::Message << "Fragment counter: " << fragCounter << tcu::TestLog::EndMessage;
5321 
5322 		if (fragCounter < minValue)
5323 		{
5324 			std::ostringstream msg;
5325 			msg << "Fragment shader invocation counter lower than expected: found " << fragCounter << " and expected at least " << minValue;
5326 			return tcu::TestStatus::fail(msg.str());
5327 		}
5328 	}
5329 
5330 	return tcu::TestStatus::pass("Pass");
5331 }
5332 
stencilPasses(vk::VkCompareOp op,deUint8 storedValue,deUint8 referenceValue)5333 bool stencilPasses(vk::VkCompareOp op, deUint8 storedValue, deUint8 referenceValue)
5334 {
5335 	switch (op)
5336 	{
5337 	case vk::VK_COMPARE_OP_NEVER:				return false;
5338 	case vk::VK_COMPARE_OP_LESS:				return (referenceValue <	storedValue);
5339 	case vk::VK_COMPARE_OP_EQUAL:				return (referenceValue ==	storedValue);
5340 	case vk::VK_COMPARE_OP_LESS_OR_EQUAL:		return (referenceValue <=	storedValue);
5341 	case vk::VK_COMPARE_OP_GREATER:				return (referenceValue >	storedValue);
5342 	case vk::VK_COMPARE_OP_GREATER_OR_EQUAL:	return (referenceValue >=	storedValue);
5343 	case vk::VK_COMPARE_OP_ALWAYS:				return true;
5344 	default: DE_ASSERT(false); return false;
5345 	}
5346 
5347 	return false;	// Unreachable.
5348 }
5349 
stencilResult(vk::VkStencilOp op,deUint8 storedValue,deUint8 referenceValue,deUint8 min,deUint8 max)5350 deUint8 stencilResult(vk::VkStencilOp op, deUint8 storedValue, deUint8 referenceValue, deUint8 min, deUint8 max)
5351 {
5352 	deUint8 result = storedValue;
5353 
5354 	switch (op)
5355 	{
5356 	case vk::VK_STENCIL_OP_KEEP:					break;
5357 	case vk::VK_STENCIL_OP_ZERO:					result = 0; break;
5358 	case vk::VK_STENCIL_OP_REPLACE:					result = referenceValue; break;
5359 	case vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP:		result = ((result == max) ? result : static_cast<deUint8>(result + 1)); break;
5360 	case vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP:		result = ((result == min) ? result : static_cast<deUint8>(result - 1)); break;
5361 	case vk::VK_STENCIL_OP_INVERT:					result = static_cast<deUint8>(~result); break;
5362 	case vk::VK_STENCIL_OP_INCREMENT_AND_WRAP:		result = ((result == max) ? min : static_cast<deUint8>(result + 1)); break;
5363 	case vk::VK_STENCIL_OP_DECREMENT_AND_WRAP:		result = ((result == min) ? max : static_cast<deUint8>(result - 1)); break;
5364 	default: DE_ASSERT(false); break;
5365 	}
5366 
5367 	return result;
5368 }
5369 
5370 class TestGroupWithClean : public tcu::TestCaseGroup
5371 {
5372 public:
TestGroupWithClean(tcu::TestContext & testCtx,const char * name,const char * description)5373 			TestGroupWithClean	(tcu::TestContext& testCtx, const char* name, const char* description)
5374 				: tcu::TestCaseGroup(testCtx, name, description)
5375 				{}
5376 
~TestGroupWithClean(void)5377 	virtual	~TestGroupWithClean	(void) { cleanupDevices(); }
5378 };
5379 
5380 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
5381 
5382 } // anonymous namespace
5383 
createExtendedDynamicStateTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)5384 tcu::TestCaseGroup* createExtendedDynamicStateTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
5385 {
5386 	GroupPtr extendedDynamicStateGroup(new TestGroupWithClean(testCtx, "extended_dynamic_state", "Tests for VK_EXT_extended_dynamic_state"));
5387 	GroupPtr meshShaderGroup(new tcu::TestCaseGroup(testCtx, "mesh_shader", "Extended dynamic state with mesh shading pipelines"));
5388 
5389 	// Auxiliar constants.
5390 	const deUint32	kHalfWidthU	= kFramebufferWidth/2u;
5391 	const deInt32	kHalfWidthI	= static_cast<deInt32>(kHalfWidthU);
5392 	const float		kHalfWidthF	= static_cast<float>(kHalfWidthU);
5393 	const float		kWidthF		= static_cast<float>(kFramebufferWidth);
5394 	const float		kHeightF	= static_cast<float>(kFramebufferHeight);
5395 
5396 	static const struct
5397 	{
5398 		SequenceOrdering	ordering;
5399 		std::string			name;
5400 		std::string			desc;
5401 	} kOrderingCases[] =
5402 	{
5403 		{ SequenceOrdering::CMD_BUFFER_START,	"cmd_buffer_start",		"Dynamic state set after command buffer start"																								},
5404 		{ SequenceOrdering::BEFORE_DRAW,		"before_draw",			"Dynamic state set just before drawing"																										},
5405 		{ SequenceOrdering::BETWEEN_PIPELINES,	"between_pipelines",	"Dynamic after a pipeline with static states has been bound and before a pipeline with dynamic states has been bound"						},
5406 		{ SequenceOrdering::AFTER_PIPELINES,	"after_pipelines",		"Dynamic state set after both a static-state pipeline and a second dynamic-state pipeline have been bound"									},
5407 		{ SequenceOrdering::BEFORE_GOOD_STATIC,	"before_good_static",	"Dynamic state set after a dynamic pipeline has been bound and before a second static-state pipeline with the right values has been bound"	},
5408 		{ SequenceOrdering::TWO_DRAWS_DYNAMIC,	"two_draws_dynamic",	"Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again"											},
5409 		{ SequenceOrdering::TWO_DRAWS_STATIC,	"two_draws_static",		"Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again"											},
5410 	};
5411 
5412 	static const struct
5413 	{
5414 		bool			useMeshShaders;
5415 		std::string		groupName;
5416 	} kMeshShadingCases[] =
5417 	{
5418 		{ false,	""				},
5419 #ifndef CTS_USES_VULKANSC
5420 		{ true,		"mesh_shader"	},
5421 #endif // CTS_USES_VULKANSC
5422 	};
5423 
5424 	static const struct
5425 	{
5426 		bool			bindUnusedMeshShadingPipeline;
5427 		std::string		nameSuffix;
5428 		std::string		descSuffix;
5429 	} kBindUnusedCases[] =
5430 	{
5431 		{ false,	"",					""																},
5432 #ifndef CTS_USES_VULKANSC
5433 		{ true,		"_bind_unused_ms",	" and bind unused mesh shading pipeline before the dynamic one"	},
5434 #endif // CTS_USES_VULKANSC
5435 	};
5436 
5437 	for (const auto& kMeshShadingCase : kMeshShadingCases)
5438 	for (const auto& kOrderingCase : kOrderingCases)
5439 	{
5440 		const auto& kUseMeshShaders	= kMeshShadingCase.useMeshShaders;
5441 		const auto& kOrdering		= kOrderingCase.ordering;
5442 
5443 		GroupPtr orderingGroup(new tcu::TestCaseGroup(testCtx, kOrderingCase.name.c_str(), kOrderingCase.desc.c_str()));
5444 
5445 		// Cull modes.
5446 		{
5447 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5448 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_FRONT_BIT;
5449 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE);
5450 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_none", "Dynamically set cull mode to none", config));
5451 		}
5452 		{
5453 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5454 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_FRONT_AND_BACK;
5455 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_BACK_BIT);
5456 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_back", "Dynamically set cull mode to back", config));
5457 		}
5458 		{
5459 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5460 			// Make triangles look back.
5461 			config.meshParams[0].reversed		= true;
5462 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
5463 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_BIT);
5464 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front", "Dynamically set cull mode to front", config));
5465 		}
5466 		{
5467 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5468 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_NONE;
5469 			config.cullModeConfig.dynamicValue	= tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_AND_BACK);
5470 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
5471 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front_and_back", "Dynamically set cull mode to front and back", config));
5472 		}
5473 
5474 		// Front face.
5475 		{
5476 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5477 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
5478 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_CLOCKWISE;
5479 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
5480 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw", "Dynamically set front face to clockwise", config));
5481 		}
5482 		{
5483 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5484 			// Pass triangles in clockwise order.
5485 			config.meshParams[0].reversed		= true;
5486 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
5487 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
5488 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
5489 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw", "Dynamically set front face to counter-clockwise", config));
5490 		}
5491 		{
5492 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5493 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
5494 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
5495 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
5496 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
5497 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw_reversed", "Dynamically set front face to clockwise with a counter-clockwise mesh", config));
5498 		}
5499 		{
5500 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5501 			// Pass triangles in clockwise order.
5502 			config.meshParams[0].reversed		= true;
5503 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
5504 			config.frontFaceConfig.staticValue	= vk::VK_FRONT_FACE_CLOCKWISE;
5505 			config.frontFaceConfig.dynamicValue	= tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
5506 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
5507 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw_reversed", "Dynamically set front face to counter-clockwise with a clockwise mesh", config));
5508 		}
5509 
5510 		// Rasterizer discard
5511 		{
5512 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5513 			config.rastDiscardEnableConfig.staticValue	= false;
5514 			config.rastDiscardEnableConfig.dynamicValue	= tcu::just(true);
5515 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
5516 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "disable_raster", "Dynamically disable rasterizer", config));
5517 		}
5518 		{
5519 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5520 			config.rastDiscardEnableConfig.staticValue	= true;
5521 			config.rastDiscardEnableConfig.dynamicValue	= tcu::just(false);
5522 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "enable_raster", "Dynamically enable rasterizer", config));
5523 		}
5524 
5525 		// Logic op
5526 		{
5527 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5528 
5529 			config.logicOpEnableConfig.staticValue	= true;
5530 			config.logicOpConfig.staticValue		= vk::VK_LOGIC_OP_CLEAR;
5531 			config.logicOpConfig.dynamicValue		= tcu::just<vk::VkLogicOp>(vk::VK_LOGIC_OP_OR);
5532 
5533 			// Clear to green, paint in blue, expect cyan due to logic op.
5534 			config.meshParams[0].color	= kLogicOpTriangleColorFl;
5535 			config.clearColorValue		= vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
5536 			config.referenceColor.reset	(new SingleColorGenerator(kLogicOpFinalColor));
5537 
5538 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_or", "Dynamically change logic op to VK_LOGIC_OP_OR", config));
5539 		}
5540 
5541 		// Logic op enable.
5542 		{
5543 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5544 
5545 			config.logicOpEnableConfig.staticValue	= false;
5546 			config.logicOpEnableConfig.dynamicValue	= true;
5547 			config.logicOpConfig.staticValue		= vk::VK_LOGIC_OP_OR;
5548 
5549 			// Clear to green, paint in blue, expect cyan due to logic op.
5550 			config.meshParams[0].color	= kLogicOpTriangleColorFl;
5551 			config.clearColorValue		= vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
5552 			config.referenceColor.reset (new SingleColorGenerator(kLogicOpFinalColor));
5553 
5554 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_enable", "Dynamically enable logic OP", config));
5555 		}
5556 		{
5557 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5558 
5559 			config.logicOpEnableConfig.staticValue	= true;
5560 			config.logicOpEnableConfig.dynamicValue	= false;
5561 			config.logicOpConfig.staticValue		= vk::VK_LOGIC_OP_OR;
5562 
5563 			// Clear to green, paint in blue, expect cyan due to logic op.
5564 			config.meshParams[0].color	= kLogicOpTriangleColorFl;
5565 			config.clearColorValue		= vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
5566 			config.referenceColor.reset	(new SingleColorGenerator(kLogicOpTriangleColor));
5567 
5568 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_disable", "Dynamically disable logic OP", config));
5569 		}
5570 
5571 		// Color blend enable.
5572 		{
5573 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5574 
5575 			// The equation picks the old color instead of the new one if blending is enabled.
5576 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
5577 																	   vk::VK_BLEND_FACTOR_ONE,
5578 																	   vk::VK_BLEND_OP_ADD,
5579 																	   vk::VK_BLEND_FACTOR_ZERO,
5580 																	   vk::VK_BLEND_FACTOR_ONE,
5581 																	   vk::VK_BLEND_OP_ADD);
5582 
5583 			config.colorBlendEnableConfig.staticValue	= false;
5584 			config.colorBlendEnableConfig.dynamicValue	= true;
5585 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
5586 
5587 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_enable", "Dynamically enable color blending", config));
5588 		}
5589 		{
5590 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5591 
5592 			// The equation picks the old color instead of the new one if blending is enabled.
5593 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
5594 																	   vk::VK_BLEND_FACTOR_ONE,
5595 																	   vk::VK_BLEND_OP_ADD,
5596 																	   vk::VK_BLEND_FACTOR_ZERO,
5597 																	   vk::VK_BLEND_FACTOR_ONE,
5598 																	   vk::VK_BLEND_OP_ADD);
5599 
5600 			config.colorBlendEnableConfig.staticValue	= true;
5601 			config.colorBlendEnableConfig.dynamicValue	= false;
5602 
5603 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_disable", "Dynamically disable color blending", config));
5604 		}
5605 
5606 		// Color blend equation.
5607 		{
5608 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5609 
5610 			// The equation picks the old color instead of the new one if blending is enabled.
5611 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
5612 																	   vk::VK_BLEND_FACTOR_ONE,
5613 																	   vk::VK_BLEND_OP_ADD,
5614 																	   vk::VK_BLEND_FACTOR_ZERO,
5615 																	   vk::VK_BLEND_FACTOR_ONE,
5616 																	   vk::VK_BLEND_OP_ADD);
5617 
5618 			// The dynamic value picks the new color.
5619 			config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ONE,
5620 																		vk::VK_BLEND_FACTOR_ZERO,
5621 																		vk::VK_BLEND_OP_ADD,
5622 																		vk::VK_BLEND_FACTOR_ONE,
5623 																		vk::VK_BLEND_FACTOR_ZERO,
5624 																		vk::VK_BLEND_OP_ADD);
5625 
5626 			config.colorBlendEnableConfig.staticValue	= true;
5627 
5628 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_new_color", "Dynamically set a color equation that picks the mesh color", config));
5629 
5630 			config.colorBlendEquationConfig.swapValues();
5631 			config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
5632 
5633 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_old_color", "Dynamically set a color equation that picks the clear color", config));
5634 		}
5635 
5636 		// Color blend advanced.
5637 		{
5638 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5639 
5640 			// This static value picks the old color instead of the new one.
5641 			config.colorBlendEquationConfig.staticValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO,
5642 																	   vk::VK_BLEND_FACTOR_ONE,
5643 																	   vk::VK_BLEND_OP_DARKEN_EXT,
5644 																	   vk::VK_BLEND_FACTOR_ZERO,
5645 																	   vk::VK_BLEND_FACTOR_ONE,
5646 																	   vk::VK_BLEND_OP_DARKEN_EXT);
5647 
5648 			// The dynamic value picks the new color.
5649 			config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(vk::VK_BLEND_FACTOR_ONE,
5650 																		vk::VK_BLEND_FACTOR_ZERO,
5651 																		vk::VK_BLEND_OP_LIGHTEN_EXT,
5652 																		vk::VK_BLEND_FACTOR_ONE,
5653 																		vk::VK_BLEND_FACTOR_ZERO,
5654 																		vk::VK_BLEND_OP_LIGHTEN_EXT);
5655 
5656 			config.colorBlendEnableConfig.staticValue	= true;
5657 
5658 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_advanced_new_color", "Dynamically set an advanced color equation that picks the mesh color", config));
5659 
5660 			config.colorBlendEquationConfig.swapValues();
5661 			config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
5662 
5663 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_equation_advanced_old_color", "Dynamically set an advanced color equation that picks the clear color", config));
5664 		}
5665 
5666 		// Dynamically enable primitive restart
5667 		if (!kUseMeshShaders)
5668 		{
5669 			for (const auto& bindUnusedCase : kBindUnusedCases)
5670 			{
5671 				if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
5672 					continue;
5673 
5674 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5675 				config.primRestartEnableConfig.staticValue	= false;
5676 				config.primRestartEnableConfig.dynamicValue	= tcu::just(true);
5677 				config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
5678 				config.bindUnusedMeshShadingPipeline		= bindUnusedCase.bindUnusedMeshShadingPipeline;
5679 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, std::string("prim_restart_enable") + bindUnusedCase.nameSuffix, "Dynamically enable primitiveRestart" + bindUnusedCase.descSuffix, config));
5680 			}
5681 		}
5682 
5683 		// Dynamically change the number of primitive control points
5684 		if (!kUseMeshShaders)
5685 		{
5686 			for (const auto& bindUnusedCase : kBindUnusedCases)
5687 			{
5688 				if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
5689 					continue;
5690 
5691 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5692 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
5693 				config.patchControlPointsConfig.staticValue = 1;
5694 				config.patchControlPointsConfig.dynamicValue = 3;
5695 				config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
5696 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "patch_control_points" + bindUnusedCase.nameSuffix, "Dynamically change patch control points" + bindUnusedCase.descSuffix, config));
5697 			}
5698 
5699 			{
5700 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5701 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
5702 				config.patchControlPointsConfig.staticValue = 1;
5703 				config.patchControlPointsConfig.dynamicValue = 3;
5704 				config.useExtraDynPCPPipeline = true;
5705 
5706 				const auto testName	= "patch_control_points_extra_pipeline";
5707 				const auto testDesc	= "Dynamically change patch control points and draw first with a pipeline using the state and no tessellation shaders";
5708 
5709 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, testDesc, config));
5710 			}
5711 		}
5712 
5713 		// Test tessellation domain origin.
5714 		if (!kUseMeshShaders)
5715 		{
5716 			{
5717 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5718 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
5719 				config.patchControlPointsConfig.staticValue = 3;
5720 				config.tessDomainOriginConfig.staticValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
5721 				config.tessDomainOriginConfig.dynamicValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
5722 				config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
5723 
5724 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "tess_domain_origin_lower_left", "Dynamically set the right domain origin to lower left", config));
5725 			}
5726 			{
5727 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5728 				config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
5729 				config.patchControlPointsConfig.staticValue = 3;
5730 				config.tessDomainOriginConfig.staticValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
5731 				config.tessDomainOriginConfig.dynamicValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
5732 				config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
5733 
5734 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "tess_domain_origin_upper_left", "Dynamically set the right domain origin to upper left", config));
5735 			}
5736 		}
5737 
5738 		// Dynamic topology.
5739 		if (!kUseMeshShaders)
5740 		{
5741 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
5742 
5743 			for (int i = 0; i < 2; ++i)
5744 			{
5745 				const bool forceGeometryShader = (i > 0);
5746 
5747 				static const struct
5748 				{
5749 					vk::VkPrimitiveTopology staticVal;
5750 					vk::VkPrimitiveTopology dynamicVal;
5751 				} kTopologyCases[] =
5752 				{
5753 					{ vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP	},
5754 					{ vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP		},
5755 					{ vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,		vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST		},
5756 				};
5757 
5758 				for (const auto& kTopologyCase : kTopologyCases)
5759 				{
5760 					const auto topologyClass = getTopologyClass(kTopologyCase.staticVal);
5761 
5762 					for (const auto& bindUnusedCase : kBindUnusedCases)
5763 					{
5764 						if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
5765 							continue;
5766 
5767 						TestConfig config(baseConfig);
5768 						config.forceGeometryShader					= forceGeometryShader;
5769 						config.topologyConfig.staticValue			= kTopologyCase.staticVal;
5770 						config.topologyConfig.dynamicValue			= tcu::just<vk::VkPrimitiveTopology>(kTopologyCase.dynamicVal);
5771 						config.primRestartEnableConfig.staticValue	= (topologyClass == TopologyClass::LINE);
5772 						config.patchControlPointsConfig.staticValue	= (config.needsTessellation() ? 3u : 1u);
5773 						config.bindUnusedMeshShadingPipeline		= bindUnusedCase.bindUnusedMeshShadingPipeline;
5774 
5775 						const std::string	className	= topologyClassName(topologyClass);
5776 						const std::string	name		= "topology_" + className + (forceGeometryShader ? "_geom" : "") + bindUnusedCase.nameSuffix;
5777 						const std::string	desc		= "Dynamically switch primitive topologies from the " + className + " class" + (forceGeometryShader ? " and use a geometry shader" : "") + bindUnusedCase.descSuffix;
5778 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, name, desc, config));
5779 					}
5780 				}
5781 			}
5782 		}
5783 
5784 		// Line stipple enable.
5785 		if (!kUseMeshShaders)
5786 		{
5787 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5788 
5789 			config.primRestartEnableConfig.staticValue	= true;
5790 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
5791 			config.lineStippleEnableConfig.staticValue	= true;
5792 			config.lineStippleEnableConfig.dynamicValue	= false;
5793 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{1u, 0x5555u};
5794 
5795 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_disable", "Dynamically disable line stipple", config));
5796 
5797 			config.lineStippleEnableConfig.swapValues();
5798 			config.referenceColor.reset(new VerticalStripesGenerator(kDefaultTriangleColor, kDefaultClearColor, 1u));
5799 
5800 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_enable", "Dynamycally enable line stipple", config));
5801 		}
5802 
5803 		// Line stipple params.
5804 		if (!kUseMeshShaders)
5805 		{
5806 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5807 
5808 			config.primRestartEnableConfig.staticValue	= true;
5809 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
5810 			config.lineStippleEnableConfig.staticValue	= true;
5811 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{1u, 0x5555u};
5812 			config.lineStippleParamsConfig.dynamicValue	= LineStippleParams{2u, 0x3333u};
5813 			config.referenceColor.reset					(new VerticalStripesGenerator(kDefaultTriangleColor, kDefaultClearColor, 4u));
5814 
5815 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_params", "Dynamically change the line stipple parameters", config));
5816 		}
5817 
5818 		// Line rasterization mode.
5819 		if (!kUseMeshShaders)
5820 		{
5821 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5822 
5823 			config.topologyConfig.staticValue			= vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
5824 			config.obliqueLine							= true;
5825 			config.colorVerificator						= verifyTopLeftCorner;
5826 			config.lineStippleEnableConfig.staticValue	= false;
5827 			config.lineStippleParamsConfig.staticValue	= LineStippleParams{0u, 0u};
5828 			config.lineRasterModeConfig.staticValue		= LineRasterizationMode::RECTANGULAR;
5829 			config.lineRasterModeConfig.dynamicValue	= LineRasterizationMode::BRESENHAM;
5830 
5831 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_bresenham", "Dynamically set line rasterization mode to bresenham", config));
5832 
5833 			config.lineRasterModeConfig.swapValues();
5834 			config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
5835 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_rectangular", "Dynamically set line rasterization mode to rectangular", config));
5836 		}
5837 
5838 		// Viewport.
5839 		{
5840 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5841 			// 2 scissors, bad static single viewport.
5842 			config.scissorConfig.staticValue	= ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
5843 			config.viewportConfig.staticValue	= ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
5844 			config.viewportConfig.dynamicValue	= ViewportVec{
5845 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5846 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5847 			};
5848 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports", "Dynamically set 2 viewports", config));
5849 		}
5850 		{
5851 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5852 			// Bad static reduced viewport.
5853 			config.viewportConfig.staticValue	= ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
5854 			config.viewportConfig.staticValue	= ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight));
5855 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_viewport", "Dynamically set viewport to cover full framebuffer", config));
5856 		}
5857 		{
5858 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5859 			// 2 scissors (left half, right half), 2 reversed static viewports that need fixing (right, left).
5860 			config.scissorConfig.staticValue	= ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
5861 			config.viewportConfig.staticValue	= ViewportVec{
5862 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),	// Right.
5863 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),		// Left.
5864 			};
5865 			config.viewportConfig.dynamicValue	= ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
5866 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch", "Dynamically switch the order with 2 viewports", config));
5867 		}
5868 		{
5869 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5870 			// 2 scissors, reversed dynamic viewports that should result in no drawing taking place.
5871 			config.scissorConfig.staticValue	= ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
5872 			config.viewportConfig.staticValue	= ViewportVec{
5873 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),		// Left.
5874 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),	// Right.
5875 			};
5876 			config.viewportConfig.dynamicValue	= ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
5877 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
5878 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch_clean", "Dynamically switch the order with 2 viewports resulting in clean image", config));
5879 		}
5880 
5881 		// Scissor.
5882 		{
5883 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5884 			// 2 viewports, bad static single scissor.
5885 			config.viewportConfig.staticValue	= ViewportVec{
5886 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5887 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5888 			};
5889 			config.scissorConfig.staticValue	= ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
5890 			config.scissorConfig.dynamicValue	= ScissorVec{
5891 				vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
5892 				vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
5893 			};
5894 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors", "Dynamically set 2 scissors", config));
5895 		}
5896 		{
5897 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5898 			// 1 viewport, bad static single scissor.
5899 			config.scissorConfig.staticValue	= ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
5900 			config.scissorConfig.dynamicValue	= ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight));
5901 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_scissor", "Dynamically set scissor to cover full framebuffer", config));
5902 		}
5903 		{
5904 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5905 			// 2 viewports, 2 reversed scissors that need fixing.
5906 			config.viewportConfig.staticValue	= ViewportVec{
5907 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5908 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5909 			};
5910 			config.scissorConfig.staticValue	= ScissorVec{
5911 				vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
5912 				vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
5913 			};
5914 			config.scissorConfig.dynamicValue	= ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
5915 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch", "Dynamically switch the order with 2 scissors", config));
5916 		}
5917 		{
5918 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
5919 			// 2 viewports, 2 scissors switched to prevent drawing.
5920 			config.viewportConfig.staticValue	= ViewportVec{
5921 				vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5922 				vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
5923 			};
5924 			config.scissorConfig.staticValue	= ScissorVec{
5925 				vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
5926 				vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
5927 			};
5928 			config.scissorConfig.dynamicValue	= ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
5929 			config.referenceColor.reset			(new SingleColorGenerator(kDefaultClearColor));
5930 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch_clean", "Dynamically switch the order with 2 scissors to avoid drawing", config));
5931 		}
5932 
5933 		// Stride.
5934 		if (!kUseMeshShaders)
5935 		{
5936 			struct
5937 			{
5938 				const VertexGenerator*	factory;
5939 				const std::string		prefix;
5940 			} strideCases[] =
5941 			{
5942 				{ getVertexWithPaddingGenerator(),			"stride"		},
5943 				{ getVertexWithExtraAttributesGenerator(),	"large_stride"	},
5944 			};
5945 
5946 			for (const auto& strideCase : strideCases)
5947 			{
5948 				const auto	factory			= strideCase.factory;
5949 				const auto&	prefix			= strideCase.prefix;
5950 				const auto	vertexStrides	= factory->getVertexDataStrides();
5951 				StrideVec	halfStrides;
5952 
5953 				halfStrides.reserve(vertexStrides.size());
5954 				for (const auto& stride : vertexStrides)
5955 					halfStrides.push_back(stride / 2u);
5956 
5957 				if (factory == getVertexWithExtraAttributesGenerator() && kOrdering == SequenceOrdering::TWO_DRAWS_STATIC)
5958 				{
5959 					// This case is invalid because it breaks VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the dynamic
5960 					// stride being less than the extent of the binding for the second attribute.
5961 					continue;
5962 				}
5963 
5964 				for (const auto& bindUnusedCase : kBindUnusedCases)
5965 				{
5966 					if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
5967 						continue;
5968 
5969 					{
5970 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
5971 						config.strideConfig.staticValue			= halfStrides;
5972 						config.strideConfig.dynamicValue		= vertexStrides;
5973 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
5974 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + bindUnusedCase.nameSuffix, "Dynamically set stride" + bindUnusedCase.descSuffix, config));
5975 					}
5976 					{
5977 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
5978 						config.strideConfig.staticValue			= halfStrides;
5979 						config.strideConfig.dynamicValue		= vertexStrides;
5980 						config.vertexDataOffset					= vertexStrides[0];
5981 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
5982 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset" + bindUnusedCase.nameSuffix, "Dynamically set stride using a nonzero vertex data offset" + bindUnusedCase.descSuffix, config));
5983 					}
5984 					{
5985 						TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
5986 						config.strideConfig.staticValue			= halfStrides;
5987 						config.strideConfig.dynamicValue		= vertexStrides;
5988 						config.vertexDataOffset					= vertexStrides[0];
5989 						config.vertexDataExtraBytes				= config.vertexDataOffset;
5990 						config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
5991 
5992 						// 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.
5993 						config.referenceColor.reset				(new HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor));
5994 						config.meshParams[0].scaleY				= 0.5f;
5995 						config.meshParams[0].offsetY			= -0.5f;
5996 
5997 						orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset_and_padding" + bindUnusedCase.nameSuffix, "Dynamically set stride using a nonzero vertex data offset and extra bytes" + bindUnusedCase.descSuffix, config));
5998 					}
5999 				}
6000 			}
6001 
6002 			// Dynamic stride of 0
6003 			//
6004 			// The "two_draws" variants are invalid because the non-zero vertex stride will cause out-of-bounds access
6005 			// when drawing more than one vertex.
6006 			if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC && kOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC)
6007 			{
6008 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithExtraAttributesGenerator());
6009 				config.strideConfig.staticValue		= config.getActiveVertexGenerator()->getVertexDataStrides();
6010 				config.strideConfig.dynamicValue	= { 0 };
6011 				config.vertexDataOffset				= 4;
6012 				config.singleVertex					= true;
6013 				config.singleVertexDrawCount		= 6;
6014 
6015 				// Make the mesh cover the top half only. If the implementation reads data outside the vertex data it should read the
6016 				// offscreen vertex and draw something in the bottom half.
6017 				config.referenceColor.reset		(new HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor));
6018 				config.meshParams[0].scaleY		= 0.5f;
6019 				config.meshParams[0].offsetY	= -0.5f;
6020 
6021 				// Use strip scale to synthesize a strip from a vertex attribute which remains constant over the draw call.
6022 				config.meshParams[0].stripScale = 1.0f;
6023 
6024 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "zero_stride_with_offset", "Dynamically set zero stride using a nonzero vertex data offset", config));
6025 			}
6026 		}
6027 
6028 		// Depth test enable.
6029 		{
6030 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6031 			config.depthTestEnableConfig.staticValue	= false;
6032 			config.depthTestEnableConfig.dynamicValue	= tcu::just(true);
6033 			// By default, the depth test never passes when enabled.
6034 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6035 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_enable", "Dynamically enable depth test", config));
6036 		}
6037 		{
6038 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6039 			config.depthTestEnableConfig.staticValue	= true;
6040 			config.depthTestEnableConfig.dynamicValue	= tcu::just(false);
6041 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_disable", "Dynamically disable depth test", config));
6042 		}
6043 
6044 		// Depth write enable.
6045 		{
6046 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6047 
6048 			// Enable depth test and set values so it passes.
6049 			config.depthTestEnableConfig.staticValue	= true;
6050 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6051 			config.clearDepthValue						= 0.5f;
6052 			config.meshParams[0].depth					= 0.25f;
6053 
6054 			// Enable writes and expect the mesh value.
6055 			config.depthWriteEnableConfig.staticValue	= false;
6056 			config.depthWriteEnableConfig.dynamicValue	= tcu::just(true);
6057 			config.expectedDepth						= 0.25f;
6058 
6059 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_enable", "Dynamically enable writes to the depth buffer", config));
6060 		}
6061 		{
6062 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6063 
6064 			// Enable depth test and set values so it passes.
6065 			config.depthTestEnableConfig.staticValue	= true;
6066 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6067 			config.clearDepthValue						= 0.5f;
6068 			config.meshParams[0].depth					= 0.25f;
6069 
6070 			// But disable writing dynamically and expect the clear value.
6071 			config.depthWriteEnableConfig.staticValue	= true;
6072 			config.depthWriteEnableConfig.dynamicValue	= tcu::just(false);
6073 			config.expectedDepth						= 0.5f;
6074 
6075 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_disable", "Dynamically disable writes to the depth buffer", config));
6076 		}
6077 
6078 		// Depth clamp enable.
6079 		{
6080 			// Without clamping, the mesh depth fails the depth test after applying the viewport transform.
6081 			// With clamping, it should pass thanks to the viewport.
6082 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6083 
6084 			config.meshParams[0].depth					= 1.5f;
6085 			config.clearDepthValue						= 0.625f;
6086 			config.depthTestEnableConfig.staticValue	= true;
6087 			config.depthWriteEnableConfig.staticValue	= true;
6088 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6089 			config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.0f, 0.5f));
6090 			config.expectedDepth						= 0.5f;
6091 
6092 			config.depthClampEnableConfig.staticValue	= false;
6093 			config.depthClampEnableConfig.dynamicValue	= true;
6094 
6095 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable", "Dynamically enable depth clamp", config));
6096 		}
6097 		{
6098 			// Reverse situation.
6099 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6100 
6101 			config.meshParams[0].depth					= 1.5f;
6102 			config.clearDepthValue						= 0.625f;
6103 			config.depthTestEnableConfig.staticValue	= true;
6104 			config.depthWriteEnableConfig.staticValue	= true;
6105 			config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6106 			config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.0f, 0.5f));
6107 			config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6108 			config.expectedDepth						= 0.625f;
6109 
6110 			config.depthClampEnableConfig.staticValue	= true;
6111 			config.depthClampEnableConfig.dynamicValue	= false;
6112 
6113 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_disable", "Dynamically disable depth clamp", config));
6114 		}
6115 
6116 		// Polygon mode.
6117 		{
6118 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6119 
6120 			config.polygonModeConfig.staticValue	= vk::VK_POLYGON_MODE_FILL;
6121 			config.polygonModeConfig.dynamicValue	= vk::VK_POLYGON_MODE_POINT;
6122 			config.oversizedTriangle				= true;
6123 			config.referenceColor.reset				(new SingleColorGenerator(kDefaultClearColor));
6124 
6125 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "polygon_mode_point", "Dynamically set polygon draw mode to points", config));
6126 		}
6127 		{
6128 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6129 
6130 			config.polygonModeConfig.staticValue	= vk::VK_POLYGON_MODE_POINT;
6131 			config.polygonModeConfig.dynamicValue	= vk::VK_POLYGON_MODE_FILL;
6132 			config.oversizedTriangle				= true;
6133 
6134 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "polygon_mode_fill", "Dynamically set polygon draw mode to fill", config));
6135 		}
6136 
6137 		for (int i = 0; i < 2; ++i)
6138 		{
6139 			const bool			multisample			= (i > 0);
6140 			const auto			activeSampleCount	= (multisample ? kMultiSampleCount : kSingleSampleCount);
6141 			const auto			inactiveSampleCount	= (multisample ? kSingleSampleCount : kMultiSampleCount);
6142 			const std::string	namePrefix			= (multisample ? "multi_sample_" : "single_sample_");
6143 			const std::string	descSuffix			= (multisample ? " in multisample mode" : " in single sample mode");
6144 
6145 			// Sample count.
6146 			{
6147 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6148 				config.rasterizationSamplesConfig.staticValue	= inactiveSampleCount;
6149 				config.rasterizationSamplesConfig.dynamicValue	= activeSampleCount;
6150 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "rasterization_samples", "Dynamically set the rasterization sample count" + descSuffix, config));
6151 			}
6152 
6153 			// Sample mask
6154 			{
6155 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6156 				config.rasterizationSamplesConfig		= activeSampleCount;
6157 				config.sampleMaskConfig.staticValue		= SampleMaskVec(1u, 0u);
6158 				config.sampleMaskConfig.dynamicValue	= SampleMaskVec(1u, 0xFFu);
6159 
6160 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "sample_mask_enable", "Dynamically set a sample mask that allows drawing" + descSuffix, config));
6161 			}
6162 			{
6163 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6164 				config.rasterizationSamplesConfig		= activeSampleCount;
6165 				config.sampleMaskConfig.staticValue		= SampleMaskVec(1u, 0xFFu);
6166 				config.sampleMaskConfig.dynamicValue	= SampleMaskVec(1u, 0u);
6167 				config.referenceColor.reset				(new SingleColorGenerator(kDefaultClearColor));
6168 
6169 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "sample_mask_disable", "Dynamically set a sample mask that prevents drawing" + descSuffix, config));
6170 			}
6171 
6172 			// Alpha to coverage.
6173 			{
6174 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6175 
6176 				config.rasterizationSamplesConfig			= activeSampleCount;
6177 				config.meshParams[0].color					= kTransparentColor;
6178 				config.alphaToCoverageConfig.staticValue	= false;
6179 				config.alphaToCoverageConfig.dynamicValue	= true;
6180 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6181 
6182 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_coverage_enable", "Dynamically enable alpha to coverage" + descSuffix, config));
6183 			}
6184 			{
6185 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6186 
6187 				config.rasterizationSamplesConfig			= activeSampleCount;
6188 				config.meshParams[0].color					= kTransparentColor;
6189 				config.alphaToCoverageConfig.staticValue	= true;
6190 				config.alphaToCoverageConfig.dynamicValue	= false;
6191 				config.referenceColor.reset					(new SingleColorGenerator(kTransparentColor));
6192 
6193 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_coverage_disable", "Dynamically disable alpha to coverage" + descSuffix, config));
6194 			}
6195 
6196 			// Alpha to one.
6197 			{
6198 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6199 
6200 				config.rasterizationSamplesConfig		= activeSampleCount;
6201 				config.meshParams[0].color				= kTransparentColor;
6202 				config.alphaToOneConfig.staticValue		= false;
6203 				config.alphaToOneConfig.dynamicValue	= true;
6204 				config.referenceColor.reset				(new SingleColorGenerator(kDefaultTriangleColor));
6205 
6206 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_one_enable", "Dynamically enable alpha to one" + descSuffix, config));
6207 			}
6208 			{
6209 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6210 
6211 				config.rasterizationSamplesConfig		= activeSampleCount;
6212 				config.meshParams[0].color				= kTransparentColor;
6213 				config.alphaToOneConfig.staticValue		= true;
6214 				config.alphaToOneConfig.dynamicValue	= false;
6215 				config.referenceColor.reset				(new SingleColorGenerator(kTransparentColor));
6216 
6217 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_one_disable", "Dynamically disable alpha to one" + descSuffix, config));
6218 			}
6219 		}
6220 
6221 		// Special sample mask case: make sure the dynamic sample mask count does not overwrite the actual sample mask.
6222 		{
6223 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6224 
6225 			// There's guaranteed support for 1 sample and 4 samples. So the official pipeline sample count will be 1 sample, and
6226 			// the one we'll use in the dynamic sample mask call will be 4.
6227 			//
6228 			// 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
6229 			// the implementation into having that one covered by using a Y offset of 0.75.
6230 			config.dynamicSampleMaskCount			= tcu::just(kMultiSampleCount);
6231 			config.sampleMaskConfig.staticValue		= SampleMaskVec(1u, 0u);
6232 			config.sampleMaskConfig.dynamicValue	= SampleMaskVec(1u, 0xFFu);
6233 			config.offCenterTriangle				= true;
6234 			config.offCenterProportion				= tcu::Vec2(0.0f, 0.75f);
6235 			config.referenceColor.reset				(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor));
6236 
6237 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_mask_count", "Dynamically set sample mask with slightly different sample count", config));
6238 		}
6239 
6240 		// Color write mask.
6241 		{
6242 			const struct
6243 			{
6244 				vk::VkColorComponentFlags staticVal;
6245 				vk::VkColorComponentFlags dynamicVal;
6246 			} colorComponentCases[] =
6247 			{
6248 				{	(CR | CG | CB | CA),	(CR |  0 |  0 |  0)		},
6249 				{	(CR | CG | CB | CA),	( 0 | CG |  0 |  0)		},
6250 				{	(CR | CG | CB | CA),	( 0 |  0 | CB |  0)		},
6251 				{	(CR | CG | CB | CA),	( 0 |  0 |  0 | CA)		},
6252 				{	(CR | CG | CB | CA),	( 0 |  0 |  0 |  0)		},
6253 				{	( 0 |  0 |  0 |  0),	(CR |  0 |  0 |  0)		},
6254 				{	( 0 |  0 |  0 |  0),	( 0 | CG |  0 |  0)		},
6255 				{	( 0 |  0 |  0 |  0),	( 0 |  0 | CB |  0)		},
6256 				{	( 0 |  0 |  0 |  0),	( 0 |  0 |  0 | CA)		},
6257 				{	( 0 |  0 |  0 |  0),	(CR | CG | CB | CA)		},
6258 			};
6259 
6260 			for (const auto& colorCompCase : colorComponentCases)
6261 			{
6262 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6263 
6264 				config.clearColorValue						= vk::makeClearValueColor(kTransparentClearColor);
6265 				config.meshParams[0].color					= kOpaqueWhite;
6266 				config.colorWriteMaskConfig.staticValue		= colorCompCase.staticVal;
6267 				config.colorWriteMaskConfig.dynamicValue	= colorCompCase.dynamicVal;
6268 				config.referenceColor.reset					(new SingleColorGenerator(filterColor(kTransparentClearColor, kOpaqueWhite, colorCompCase.dynamicVal)));
6269 
6270 				const auto staticCode	= componentCodes(colorCompCase.staticVal);
6271 				const auto dynamicCode	= componentCodes(colorCompCase.dynamicVal);
6272 				const auto testName		= "color_write_mask_" + staticCode + "_to_" + dynamicCode;
6273 
6274 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, "Dynamically set color write mask to " + dynamicCode, config));
6275 			}
6276 		}
6277 
6278 		// Rasterization stream selection.
6279 		if (!kUseMeshShaders)
6280 		{
6281 			const struct
6282 			{
6283 				OptRastStream	shaderStream;	// Stream in the geometry shader.
6284 				OptRastStream	staticVal;		// Static value for the extension struct.
6285 				OptRastStream	dynamicVal;		// Dynamic value for the setter.
6286 				const bool		expectDraw;		// Match between actual stream and active selected value?
6287 				const char*		name;
6288 			} rastStreamCases[] =
6289 			{
6290 				{ tcu::just(1u),	tcu::Nothing,		tcu::just(1u),		true,	"none_to_one"						},
6291 				{ tcu::just(1u),	tcu::just(0u),		tcu::just(1u),		true,	"zero_to_one"						},
6292 				{ tcu::Nothing,		tcu::just(1u),		tcu::just(0u),		true,	"one_to_zero"						},
6293 				{ tcu::just(0u),	tcu::just(1u),		tcu::just(0u),		true,	"one_to_zero_explicit"				},
6294 				{ tcu::just(0u),	tcu::Nothing,		tcu::just(1u),		false,	"none_to_one_mismatch"				},
6295 				{ tcu::just(0u),	tcu::just(0u),		tcu::just(1u),		false,	"zero_to_one_mismatch"				},
6296 				{ tcu::Nothing,		tcu::Nothing,		tcu::just(1u),		false,	"none_to_one_mismatch_implicit"		},
6297 				{ tcu::Nothing,		tcu::just(0u),		tcu::just(1u),		false,	"zero_to_one_mismatch_implicit"		},
6298 			};
6299 
6300 			for (const auto& rastStreamCase : rastStreamCases)
6301 			{
6302 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
6303 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
6304 				// must be set if the used pipeline contains the dynamic state.
6305 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(rastStreamCase.staticVal))
6306 					continue;
6307 
6308 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6309 
6310 				config.rasterizationStreamConfig.staticValue	= rastStreamCase.staticVal;
6311 				config.rasterizationStreamConfig.dynamicValue	= rastStreamCase.dynamicVal;
6312 				config.shaderRasterizationStream				= rastStreamCase.shaderStream;
6313 				config.referenceColor.reset						(new SingleColorGenerator(rastStreamCase.expectDraw ? kDefaultTriangleColor : kDefaultClearColor));
6314 
6315 				const auto testName = std::string("rasterization_stream_") + rastStreamCase.name;
6316 
6317 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, "Dynamically switch rasterization streams", config));
6318 			}
6319 		}
6320 
6321 		// Provoking vertex mode.
6322 		{
6323 			const struct
6324 			{
6325 				OptBoolean		staticVal;
6326 				OptBoolean		dynamicVal;
6327 				const char*		name;
6328 				const char*		desc;
6329 			} provokingVtxCases[] =
6330 			{
6331 				{ tcu::Nothing,		tcu::just(true),	"provoking_vertex_first_to_last_implicit",	"Dynamically switch provoking vertex mode from none (first) to last"	},
6332 				{ tcu::just(false),	tcu::just(true),	"provoking_vertex_first_to_last_explicit",	"Dynamically switch provoking vertex mode from first to last"			},
6333 				{ tcu::just(true),	tcu::just(false),	"provoking_vertex_last_to_first",			"Dynamically switch provoking vertex mode from last to first"			},
6334 			};
6335 
6336 			for (const auto& provokingVtxCase : provokingVtxCases)
6337 			{
6338 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
6339 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
6340 				// must be set if the used pipeline contains the dynamic state.
6341 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(provokingVtxCase.staticVal))
6342 					continue;
6343 
6344 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getProvokingVertexWithPaddingGenerator(provokingVtxCase.dynamicVal.get()));
6345 				config.provokingVertexConfig.staticValue	= provokingVtxCase.staticVal;
6346 				config.provokingVertexConfig.dynamicValue	= provokingVtxCase.dynamicVal;
6347 				config.oversizedTriangle					= true;
6348 
6349 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, provokingVtxCase.name, provokingVtxCase.desc, config));
6350 			}
6351 		}
6352 
6353 		// Depth clip negative one to one.
6354 		{
6355 			const struct
6356 			{
6357 				OptBoolean		staticVal;
6358 				OptBoolean		dynamicVal;
6359 				const char*		name;
6360 				const char*		desc;
6361 			} negativeOneToOneCases[] =
6362 			{
6363 				{ tcu::Nothing,		tcu::just(true),	"negative_one_to_one_false_to_true_implicit",	"Dynamically switch negative one to one mode from none (false) to true"	},
6364 				{ tcu::just(false),	tcu::just(true),	"negative_one_to_one_false_to_true_explicit",	"Dynamically switch negative one to one mode from false to true"		},
6365 				{ tcu::just(true),	tcu::just(false),	"negative_one_to_one_true_to_false",			"Dynamically switch negative one to one mode from true to false"		},
6366 			};
6367 
6368 			for (const auto& negOneToOneCase : negativeOneToOneCases)
6369 			{
6370 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
6371 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
6372 				// must be set if the used pipeline contains the dynamic state.
6373 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(negOneToOneCase.staticVal))
6374 					continue;
6375 
6376 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6377 				config.negativeOneToOneConfig.staticValue	= negOneToOneCase.staticVal;
6378 				config.negativeOneToOneConfig.dynamicValue	= negOneToOneCase.dynamicVal;
6379 
6380 				// Enable depth test and set values so it passes.
6381 				config.depthTestEnableConfig.staticValue	= true;
6382 				config.depthWriteEnableConfig.staticValue	= true;
6383 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6384 				config.meshParams[0].depth					= 0.5f;
6385 				config.expectedDepth						= (config.getActiveNegativeOneToOneValue() ? 0.75f : 0.5f);
6386 
6387 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, negOneToOneCase.name, negOneToOneCase.desc, config));
6388 			}
6389 		}
6390 
6391 		// Depth clip enable.
6392 		{
6393 			const struct
6394 			{
6395 				OptBoolean		staticVal;
6396 				OptBoolean		dynamicVal;
6397 				const char*		name;
6398 				const char*		desc;
6399 			} depthClipEnableCases[] =
6400 			{
6401 				{ tcu::Nothing,		tcu::just(false),	"depth_clip_enable_true_to_false_implicit",	"Dynamically switch negative one to one mode from none (true) to false"	},
6402 				{ tcu::just(true),	tcu::just(false),	"depth_clip_enable_true_to_false_explicit",	"Dynamically switch negative one to one mode from true to false"		},
6403 				{ tcu::just(false),	tcu::just(true),	"depth_clip_enable_true_to_false",			"Dynamically switch negative one to one mode from false to true"		},
6404 			};
6405 
6406 			for (const auto& depthClipEnableCase : depthClipEnableCases)
6407 			{
6408 				// In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
6409 				// calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
6410 				// must be set if the used pipeline contains the dynamic state.
6411 				if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(depthClipEnableCase.staticVal))
6412 					continue;
6413 
6414 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6415 				config.depthClipEnableConfig.staticValue	= depthClipEnableCase.staticVal;
6416 				config.depthClipEnableConfig.dynamicValue	= depthClipEnableCase.dynamicVal;
6417 
6418 				const bool depthClipActive = config.getActiveDepthClipEnable();
6419 
6420 				// Enable depth test and set values so it passes.
6421 				config.depthTestEnableConfig.staticValue	= true;
6422 				config.depthWriteEnableConfig.staticValue	= true;
6423 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6424 				config.meshParams[0].depth					= -0.5f;
6425 				config.viewportConfig.staticValue			= ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
6426 				config.expectedDepth						= (depthClipActive ? 1.0f : 0.25f);
6427 				config.referenceColor.reset					(new SingleColorGenerator(depthClipActive ? kDefaultClearColor : kDefaultTriangleColor));
6428 
6429 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, depthClipEnableCase.name, depthClipEnableCase.desc, config));
6430 			}
6431 		}
6432 
6433 		// Sample locations enablement.
6434 		{
6435 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6436 			config.rasterizationSamplesConfig	= kMultiSampleCount;
6437 			config.offCenterTriangle			= true;
6438 			config.offCenterProportion			= tcu::Vec2(0.90625f, 0.90625f);
6439 
6440 			// Push sample locations towards the bottom right corner so they're able to sample the off-center triangle.
6441 			config.sampleLocations				= tcu::Vec2(1.0f, 1.0f);
6442 
6443 			config.sampleLocationsEnableConfig.staticValue	= false;
6444 			config.sampleLocationsEnableConfig.dynamicValue	= true;
6445 
6446 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_locations_enable", "Dynamically enable sample locations", config));
6447 
6448 			config.sampleLocationsEnableConfig.swapValues();
6449 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
6450 
6451 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_locations_disable", "Dynamically disable sample locations", config));
6452 		}
6453 
6454 		// Coverage to color enable.
6455 		{
6456 			for (int i = 0; i < 2; ++i)
6457 			{
6458 				const bool multisample = (i > 0);
6459 
6460 				for (int j = 0; j < 2; ++j)
6461 				{
6462 					const bool		covToColor		= (j > 0);
6463 					const uint32_t	referenceRed	= ((covToColor ? (multisample ? 15u : 1u) : 48u/*matches meshParams[0].color*/));
6464 
6465 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6466 
6467 					config.oversizedTriangle						= true; // This avoids partial coverages in fragments.
6468 					config.rasterizationSamplesConfig				= (multisample ? kMultiSampleCount : kSingleSampleCount);
6469 					config.coverageToColorEnableConfig.staticValue	= !covToColor;
6470 					config.coverageToColorEnableConfig.dynamicValue	= covToColor;
6471 					config.meshParams[0].color						= tcu::Vec4(48.0f, 0.0f, 0.0f, 1.0f); // Distinct value, does not match any coverage mask.
6472 					config.referenceColor.reset						(new SingleColorGenerator(tcu::UVec4(referenceRed, 0u, 0u, 1u)));
6473 
6474 					const std::string	finalState	= (covToColor ? "enable" : "disable");
6475 					const auto			testName	= "coverage_to_color_" + finalState + "_" + (multisample ? "multisample" : "single_sample");
6476 					const auto			testDesc	= "Dynamically " + finalState + " coverage to color in " + (multisample ? "multisample" : "single sample") + " images";
6477 
6478 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, testDesc, config));
6479 				}
6480 			}
6481 		}
6482 
6483 		// Coverage to color location.
6484 		{
6485 			for (int i = 0; i < 2; ++i)
6486 			{
6487 				const bool multisample = (i > 0);
6488 
6489 				for (int j = 0; j < 2; ++j)
6490 				{
6491 					const bool		locationLast	= (j > 0);
6492 					const uint32_t	colorAttCount	= 4u;
6493 					const uint32_t	covToColorLoc	= (locationLast ? colorAttCount - 1u : 0u);
6494 					const uint32_t	referenceRed	= ((locationLast ? (multisample ? 15u : 1u) : 48u/*matches meshParams[0].color*/));
6495 
6496 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6497 
6498 					config.oversizedTriangle							= true; // This avoids partial coverages in fragments.
6499 					config.rasterizationSamplesConfig					= (multisample ? kMultiSampleCount : kSingleSampleCount);
6500 					config.colorAttachmentCount							= colorAttCount;
6501 					config.coverageToColorEnableConfig.staticValue		= true;
6502 					config.coverageToColorLocationConfig.staticValue	= (locationLast ? 0u : colorAttCount - 1u);
6503 					config.coverageToColorLocationConfig.dynamicValue	= covToColorLoc;
6504 					config.meshParams[0].color							= tcu::Vec4(48.0f, 0.0f, 0.0f, 1.0f); // Distinct value, does not match any coverage mask.
6505 					config.referenceColor.reset							(new SingleColorGenerator(tcu::UVec4(referenceRed, 0u, 0u, 1u)));
6506 
6507 					const auto	locName		= std::to_string(covToColorLoc);
6508 					const auto	testName	= "coverage_to_color_location_" + locName + "_" + (multisample ? "multisample" : "single_sample");
6509 					const auto	testDesc	= "Dynamically enable coverage to color in location " + locName + " using " + (multisample ? "multisample" : "single sample") + " images";
6510 
6511 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, testDesc, config));
6512 				}
6513 			}
6514 		}
6515 
6516 #ifndef CTS_USES_VULKANSC
6517 		// Coverage modulation mode.
6518 		{
6519 			const struct
6520 			{
6521 				vk::VkCoverageModulationModeNV	staticVal;
6522 				vk::VkCoverageModulationModeNV	dynamicVal;
6523 				tcu::Vec4						partialCovFactor; // This will match the expected coverage proportion. See below.
6524 				const char*						name;
6525 			} modulationModeCases[] =
6526 			{
6527 				{ 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"	},
6528 				{ 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"	},
6529 				{ 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"	},
6530 				{ 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"	},
6531 			};
6532 
6533 			for (const auto& modulationModeCase : modulationModeCases)
6534 			{
6535 				TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6536 
6537 				config.coverageModulation			= true;
6538 				config.rasterizationSamplesConfig	= kMultiSampleCount;
6539 				config.colorSampleCount				= kSingleSampleCount;
6540 
6541 				// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
6542 				// * Leave the corner pixel uncovered.
6543 				// * Cover the top border with sample 3 (1/4 the samples = 0.25).
6544 				// * Cover the left border with sample 1 (1/4 the samples = 0.25).
6545 				config.offCenterProportion	= tcu::Vec2(0.6875f, 0.6875f);
6546 				config.offCenterTriangle	= true;
6547 
6548 				config.coverageModulationModeConfig.staticValue		= modulationModeCase.staticVal;
6549 				config.coverageModulationModeConfig.dynamicValue	= modulationModeCase.dynamicVal;
6550 
6551 				const auto& partialCoverageColor = kDefaultTriangleColor * modulationModeCase.partialCovFactor;
6552 				config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, partialCoverageColor, kDefaultClearColor, partialCoverageColor));
6553 
6554 				const auto testName = std::string("coverage_modulation_mode_") + modulationModeCase.name;
6555 				const auto testDesc = std::string("Dynamically set coverage modulation mode to ") + modulationModeCase.name;
6556 
6557 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, testDesc, config));
6558 			}
6559 		}
6560 
6561 		// Coverage modulation table enable.
6562 		{
6563 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6564 
6565 			config.coverageModulation			= true;
6566 			config.rasterizationSamplesConfig	= kMultiSampleCount;
6567 			config.colorSampleCount				= kSingleSampleCount;
6568 
6569 			// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
6570 			// * Leave the corner pixel uncovered.
6571 			// * Cover the top border with sample 3 (1/4 the samples = 0.25).
6572 			// * Cover the left border with sample 1 (1/4 the samples = 0.25).
6573 			config.offCenterProportion	= tcu::Vec2(0.6875f, 0.6875f);
6574 			config.offCenterTriangle	= true;
6575 
6576 			const CovModTableVec table { 0.75f, 1.0f, 1.0f, 1.0f };
6577 			config.coverageModulationModeConfig.staticValue		= vk::VK_COVERAGE_MODULATION_MODE_RGB_NV;
6578 			config.coverageModTableConfig.staticValue			= table;
6579 
6580 			config.coverageModTableEnableConfig.staticValue		= false;
6581 			config.coverageModTableEnableConfig.dynamicValue	= true;
6582 
6583 			const auto	tableCoverFactor			= tcu::Vec4(0.75f, 0.75f, 0.75f, 1.0f);
6584 			const auto&	tablePartialCoverageColor	= kDefaultTriangleColor * tableCoverFactor;
6585 
6586 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, tablePartialCoverageColor, kDefaultClearColor, tablePartialCoverageColor));
6587 
6588 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_enable", "Dynamically enable coverage modulation table", config));
6589 
6590 			// Reverse situation, fall back to the default modulation factor.
6591 			config.coverageModTableEnableConfig.swapValues();
6592 			const auto	noTableCoverFactor			= tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f);
6593 			const auto&	noTablePartialCoverageColor	= kDefaultTriangleColor * noTableCoverFactor;
6594 			config.referenceColor.reset				(new TopLeftBorderGenerator(kDefaultTriangleColor, noTablePartialCoverageColor, kDefaultClearColor, noTablePartialCoverageColor));
6595 
6596 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_disable", "Dynamically disable coverage modulation table", config));
6597 		}
6598 
6599 		// Coverage modulation table.
6600 		{
6601 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6602 
6603 			config.coverageModulation			= true;
6604 			config.rasterizationSamplesConfig	= kMultiSampleCount;
6605 			config.colorSampleCount				= kSingleSampleCount;
6606 
6607 			// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
6608 			// * Cover the corner pixel with 1 sample (0.25).
6609 			// * Cover the top border with 2 samples (0.5).
6610 			// * Cover the left border with 2 samples (0.5).
6611 			config.offCenterProportion	= tcu::Vec2(0.5f, 0.5f);
6612 			config.offCenterTriangle	= true;
6613 
6614 			config.coverageModulationModeConfig.staticValue		= vk::VK_COVERAGE_MODULATION_MODE_RGB_NV;
6615 			config.coverageModTableEnableConfig.staticValue		= true;
6616 
6617 			//									corner	border	unused		main
6618 			const CovModTableVec goodTable	{	0.75f,	0.25f,	0.0f,		0.5f	};
6619 			const CovModTableVec badTable	{	0.5f,	0.75f,	1.0f,		0.25f	};
6620 
6621 			config.coverageModTableConfig.staticValue	= badTable;
6622 			config.coverageModTableConfig.dynamicValue	= goodTable;
6623 
6624 			// VK_COVERAGE_MODULATION_MODE_RGB_NV, factors for RGB according to goodTable, alpha untouched.
6625 			const auto	cornerFactor	= tcu::Vec4(0.75f, 0.75f, 0.75f, 1.0f);
6626 			const auto	borderFactor	= tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f);
6627 			const auto	mainFactor		= tcu::Vec4(0.5f,  0.5f,  0.5f,  1.0f);
6628 
6629 			const auto&	cornerColor		= kDefaultTriangleColor * cornerFactor;
6630 			const auto&	borderColor		= kDefaultTriangleColor * borderFactor;
6631 			const auto&	mainColor		= kDefaultTriangleColor * mainFactor;
6632 
6633 			config.referenceColor.reset(new TopLeftBorderGenerator(mainColor, borderColor, cornerColor, borderColor));
6634 
6635 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_change", "Dynamically change coverage modulation table", config));
6636 		}
6637 
6638 		// Coverage reduction mode.
6639 		{
6640 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6641 
6642 			config.coverageReduction			= true;
6643 			config.rasterizationSamplesConfig	= kMultiSampleCount;
6644 			config.colorSampleCount				= kSingleSampleCount;
6645 
6646 			// With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
6647 			// * Leave the corner pixel uncovered.
6648 			// * Cover the top border with sample 3 (1/4 the samples = 0.25).
6649 			// * Cover the left border with sample 1 (1/4 the samples = 0.25).
6650 			config.offCenterProportion	= tcu::Vec2(0.6875f, 0.6875f);
6651 			config.offCenterTriangle	= true;
6652 
6653 			config.coverageReductionModeConfig.staticValue	= vk::VK_COVERAGE_REDUCTION_MODE_MERGE_NV;
6654 			config.coverageReductionModeConfig.dynamicValue	= vk::VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV;
6655 
6656 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
6657 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_reduction_truncate", "Dynamically set coverage reduction truncate mode", config));
6658 
6659 			// In merge mode, the only pixel without coverage should be the corner. However, the spec is a bit ambiguous in this
6660 			// case:
6661 			//
6662 			//    VK_COVERAGE_REDUCTION_MODE_MERGE_NV specifies that each color sample will be associated with an
6663 			//    implementation-dependent subset of samples in the pixel coverage. If any of those associated samples are covered,
6664 			//    the color sample is covered.
6665 			//
6666 			// We cannot be 100% sure the single color sample will be associated with the whole set of 4 rasterization samples, but
6667 			// the test appears to pass in existing HW.
6668 			config.coverageReductionModeConfig.swapValues();
6669 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultTriangleColor, kDefaultClearColor, kDefaultTriangleColor));
6670 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_reduction_merge", "Dynamically set coverage reduction merge mode", config));
6671 		}
6672 
6673 		// Viewport swizzle.
6674 		{
6675 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6676 
6677 			config.viewportSwizzle				= true;
6678 			config.oversizedTriangle			= true;
6679 			config.cullModeConfig.staticValue	= vk::VK_CULL_MODE_BACK_BIT;
6680 
6681 			const vk::VkViewportSwizzleNV idSwizzle
6682 			{
6683 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
6684 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
6685 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
6686 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
6687 			};
6688 
6689 			const vk::VkViewportSwizzleNV yxSwizzle // Switches Y and X coordinates, makes the oversized triangle clockwise.
6690 			{
6691 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, // <--
6692 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, // <--
6693 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
6694 				vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
6695 			};
6696 
6697 			config.viewportSwizzleConfig.staticValue	= ViewportSwzVec(1u, idSwizzle);
6698 			config.viewportSwizzleConfig.dynamicValue	= ViewportSwzVec(1u, yxSwizzle);
6699 			config.frontFaceConfig.staticValue			= vk::VK_FRONT_FACE_CLOCKWISE;
6700 
6701 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_swizzle_yx", "Dynamically set a viewport swizzle with X and Y switched around", config));
6702 
6703 			config.viewportSwizzleConfig.swapValues();
6704 			config.frontFaceConfig.staticValue			= vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
6705 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_swizzle_xy", "Dynamically set the viewport identity swizzle", config));
6706 		}
6707 
6708 		// Shading rate image enable.
6709 		{
6710 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6711 
6712 			for (int i = 0; i < 2; ++i)
6713 			{
6714 				const bool			sriEnable	= (i > 0);
6715 				const std::string	enableStr	= (sriEnable ? "enable" : "disable");
6716 
6717 				config.shadingRateImage = true;
6718 				config.shadingRateImageEnableConfig.staticValue = !sriEnable;
6719 				config.shadingRateImageEnableConfig.dynamicValue = sriEnable;
6720 				config.referenceColor.reset(new SingleColorGenerator(sriEnable ? kDefaultClearColor : kDefaultTriangleColor));
6721 
6722 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "shading_rate_image_" + enableStr, "Dynamically " + enableStr + " a shading rate image", config));
6723 			}
6724 		}
6725 
6726 		// Viewport W Scaling enable.
6727 		{
6728 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6729 
6730 			for (int i = 0; i < 2; ++i)
6731 			{
6732 				const bool			wScalingEnable	= (i > 0);
6733 				const std::string	enableStr		= (wScalingEnable ? "enable" : "disable");
6734 
6735 				config.colorVerificator = verifyTopLeftCorner;
6736 				config.viewportWScaling = true;
6737 				config.viewportWScalingEnableConfig.staticValue = !wScalingEnable;
6738 				config.viewportWScalingEnableConfig.dynamicValue = wScalingEnable;
6739 				config.referenceColor.reset(new SingleColorGenerator(wScalingEnable ? kDefaultClearColor : kDefaultTriangleColor));
6740 
6741 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_w_scaling_" + enableStr, "Dynamically " + enableStr + " viewport W scaling", config));
6742 			}
6743 		}
6744 
6745 		// Representative fragment test state.
6746 		{
6747 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6748 
6749 			for (int i = 0; i < 2; ++i)
6750 			{
6751 				const bool			reprFragTestEnable	= (i > 0);
6752 				const std::string	enableStr			= (reprFragTestEnable ? "enable" : "disable");
6753 
6754 				config.depthTestEnableConfig.staticValue	= true;
6755 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
6756 				config.colorWriteMaskConfig.staticValue		= 0u; // Disable color writes.
6757 				config.oversizedTriangle					= true;
6758 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6759 
6760 				config.representativeFragmentTest				= true;
6761 				config.reprFragTestEnableConfig.staticValue		= !reprFragTestEnable;
6762 				config.reprFragTestEnableConfig.dynamicValue	= reprFragTestEnable;
6763 
6764 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "repr_frag_test_" + enableStr, "Dynamically " + enableStr + " representative frag test", config));
6765 			}
6766 		}
6767 #endif // CTS_USES_VULKANSC
6768 
6769 		// Conservative rasterization mode.
6770 		{
6771 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6772 			config.offCenterTriangle = true;
6773 
6774 			// Single-sampling at the pixel center should not cover this, but overestimation should result in coverage.
6775 			config.offCenterProportion							= tcu::Vec2(0.75f, 0.75f);
6776 			config.extraPrimitiveOverEstConfig.staticValue		= 0.0f;
6777 			config.conservativeRasterModeConfig.staticValue		= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
6778 			config.conservativeRasterModeConfig.dynamicValue	= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
6779 
6780 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_overestimate", "Dynamically set conservative rasterization mode to overestimation", config));
6781 
6782 			config.conservativeRasterModeConfig.swapValues();
6783 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
6784 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_disabled", "Dynamically set conservative rasterization mode to disabled", config));
6785 		}
6786 		{
6787 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6788 			config.offCenterTriangle = true;
6789 
6790 			// Single-sampling at the pixel center should cover this, but underestimation should result in lack of coverage.
6791 			config.offCenterProportion							= tcu::Vec2(0.25f, 0.25f);
6792 			config.extraPrimitiveOverEstConfig.staticValue		= 0.0f;
6793 			config.conservativeRasterModeConfig.staticValue		= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
6794 			config.conservativeRasterModeConfig.dynamicValue	= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT;
6795 			config.referenceColor.reset							(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
6796 
6797 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_underestimate", "Dynamically set conservative rasterization mode to underestimation", config));
6798 		}
6799 
6800 		// Extra primitive overestimation size.
6801 		// Notes as of 2022-08-12 and gpuinfo.org:
6802 		//    * primitiveOverestimationSize is typically 0.0, 0.001953125 or 0.00195313 (i.e. very small).
6803 		//    * maxExtraPrimitiveOverestimationSize is typically 0.0 or 0.75 (no other values).
6804 		//    * extraPrimitiveOverestimationSizeGranularity is typically 0.0 or 0.25 (no other values).
6805 		{
6806 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6807 			config.offCenterTriangle = true;
6808 
6809 			// Move the triangle by more than one pixel, then use an extra overestimation of 0.75 to cover the border pixels too.
6810 			config.offCenterProportion						= tcu::Vec2(1.125f, 1.125f);
6811 			config.maxPrimitiveOverestimationSize			= 0.5f; // Otherwise the base overestimation size will be enough. This should never trigger.
6812 			config.conservativeRasterModeConfig.staticValue	= vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
6813 			config.extraPrimitiveOverEstConfig.staticValue	= 0.0f;
6814 			config.extraPrimitiveOverEstConfig.dynamicValue	= 0.75f; // Large enough to reach the center of the border pixel.
6815 
6816 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "extra_overestimation_size_large", "Dynamically set the extra overestimation size to a large value", config));
6817 
6818 			config.extraPrimitiveOverEstConfig.swapValues();
6819 			config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor, kDefaultClearColor, kDefaultClearColor));
6820 
6821 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "extra_overestimation_size_none", "Dynamically set the extra overestimation size to zero", config));
6822 		}
6823 
6824 		// Depth bias enable with static or dynamic depth bias parameters.
6825 		{
6826 			const DepthBiasParams kAlternativeDepthBiasParams = { 2e7f, 0.25f };
6827 
6828 			for (int dynamicBiasIter = 0; dynamicBiasIter < 2; ++dynamicBiasIter)
6829 			{
6830 				const bool useDynamicBias = (dynamicBiasIter > 0);
6831 
6832 				{
6833 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6834 
6835 					// Enable depth test and write 1.0f
6836 					config.depthTestEnableConfig.staticValue = true;
6837 					config.depthWriteEnableConfig.staticValue = true;
6838 					config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
6839 					// Clear depth buffer to 0.25f
6840 					config.clearDepthValue = 0.25f;
6841 					// Write depth to 0.5f
6842 					config.meshParams[0].depth = 0.5f;
6843 
6844 					// Enable dynamic depth bias and expect the depth value to be clamped to 0.75f based on depthBiasConstantFactor and depthBiasClamp
6845 					if (useDynamicBias)
6846 					{
6847 						config.depthBiasConfig.staticValue	= kNoDepthBiasParams;
6848 						config.depthBiasConfig.dynamicValue	= kAlternativeDepthBiasParams;
6849 					}
6850 					else
6851 					{
6852 						config.depthBiasConfig.staticValue	= kAlternativeDepthBiasParams;
6853 					}
6854 
6855 					config.depthBiasEnableConfig.staticValue = false;
6856 					config.depthBiasEnableConfig.dynamicValue = tcu::just(true);
6857 					config.expectedDepth = 0.75f;
6858 
6859 					std::string caseName = "depth_bias_enable";
6860 					std::string caseDesc = "Dynamically enable the depth bias";
6861 
6862 					if (useDynamicBias)
6863 					{
6864 						caseName += "_dynamic_bias_params";
6865 						caseDesc += " and set the bias params dynamically";
6866 					}
6867 
6868 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, caseDesc, config));
6869 				}
6870 				{
6871 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6872 
6873 					// Enable depth test and write 1.0f
6874 					config.depthTestEnableConfig.staticValue = true;
6875 					config.depthWriteEnableConfig.staticValue = true;
6876 					config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
6877 					// Clear depth buffer to 0.25f
6878 					config.clearDepthValue = 0.25f;
6879 					// Write depth to 0.5f
6880 					config.meshParams[0].depth = 0.5f;
6881 
6882 					// Disable dynamic depth bias and expect the depth value to remain at 0.5f based on written value
6883 					if (useDynamicBias)
6884 					{
6885 						config.depthBiasConfig.staticValue	= kNoDepthBiasParams;
6886 						config.depthBiasConfig.dynamicValue	= kAlternativeDepthBiasParams;
6887 					}
6888 					else
6889 					{
6890 						config.depthBiasConfig.staticValue	= kAlternativeDepthBiasParams;
6891 					}
6892 
6893 					config.depthBiasEnableConfig.staticValue = true;
6894 					config.depthBiasEnableConfig.dynamicValue = tcu::just(false);
6895 					config.expectedDepth = 0.5f;
6896 
6897 					std::string caseName = "depth_bias_disable";
6898 					std::string caseDesc = "Dynamically disable the depth bias";
6899 
6900 					if (useDynamicBias)
6901 					{
6902 						caseName += "_dynamic_bias_params";
6903 						caseDesc += " and set the bias params dynamically";
6904 					}
6905 
6906 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, caseDesc, config));
6907 				}
6908 			}
6909 		}
6910 
6911 		// Depth compare op.
6912 		{
6913 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
6914 			const tcu::Vec4 kAlternativeColor				(0.0f, 0.0f, 0.5f, 1.0f);
6915 			baseConfig.depthTestEnableConfig.staticValue	= true;
6916 			baseConfig.depthWriteEnableConfig.staticValue	= true;
6917 			baseConfig.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_NEVER;
6918 			baseConfig.clearDepthValue						= 0.5f;
6919 
6920 			{
6921 				TestConfig config = baseConfig;
6922 				config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_ALWAYS;
6923 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_NEVER;
6924 				config.meshParams[0].depth					= 0.25f;
6925 				config.expectedDepth						= 0.5f;
6926 				config.referenceColor.reset					(new SingleColorGenerator(kDefaultClearColor));
6927 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_never", "Dynamically set the depth compare operator to NEVER", config));
6928 			}
6929 			{
6930 				TestConfig config = baseConfig;
6931 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS;
6932 				config.meshParams[0].depth					= 0.25f;
6933 				config.expectedDepth						= 0.25f;
6934 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less", "Dynamically set the depth compare operator to LESS", config));
6935 			}
6936 			{
6937 				TestConfig config = baseConfig;
6938 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER;
6939 				config.meshParams[0].depth					= 0.75f;
6940 				config.expectedDepth						= 0.75f;
6941 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater", "Dynamically set the depth compare operator to GREATER", config));
6942 			}
6943 			{
6944 				TestConfig config = baseConfig;
6945 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_EQUAL;
6946 				config.meshParams[0].depth					= 0.5f;
6947 				config.meshParams[0].color					= kAlternativeColor;
6948 				// Draw another mesh in front to verify it does not pass the equality test.
6949 				config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.25f));
6950 				config.expectedDepth						= 0.5f;
6951 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
6952 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_equal", "Dynamically set the depth compare operator to EQUAL", config));
6953 			}
6954 			{
6955 				TestConfig config = baseConfig;
6956 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS_OR_EQUAL;
6957 				config.meshParams[0].depth					= 0.25f;
6958 				config.expectedDepth						= 0.25f;
6959 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less", "Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with smaller depth", config));
6960 			}
6961 			{
6962 				TestConfig config = baseConfig;
6963 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS_OR_EQUAL;
6964 				config.meshParams[0].depth					= 0.5f;
6965 				config.expectedDepth						= 0.5f;
6966 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_equal", "Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with equal depth", config));
6967 			}
6968 			{
6969 				TestConfig config = baseConfig;
6970 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_LESS_OR_EQUAL;
6971 				config.meshParams[0].depth					= 0.25f;
6972 				// Draw another mesh with the same depth in front of it.
6973 				config.meshParams.push_back(MeshParams(kAlternativeColor, 0.25f));
6974 				config.expectedDepth						= 0.25f;
6975 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
6976 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less_then_equal", "Dynamically set the depth compare operator to LESS_OR_EQUAL and draw two meshes with less and equal depth", config));
6977 			}
6978 			{
6979 				TestConfig config = baseConfig;
6980 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
6981 				config.meshParams[0].depth					= 0.75f;
6982 				config.expectedDepth						= 0.75f;
6983 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater", "Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with greater depth", config));
6984 			}
6985 			{
6986 				TestConfig config = baseConfig;
6987 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
6988 				config.meshParams[0].depth					= 0.5f;
6989 				config.expectedDepth						= 0.5f;
6990 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_equal", "Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with equal depth", config));
6991 			}
6992 			{
6993 				TestConfig config = baseConfig;
6994 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
6995 				config.meshParams[0].depth					= 0.75f;
6996 				// Draw another mesh with the same depth in front of it.
6997 				config.meshParams.push_back(MeshParams(kAlternativeColor, 0.75f));
6998 				config.expectedDepth						= 0.75f;
6999 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
7000 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater_then_equal", "Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw two meshes with greater and equal depth", config));
7001 			}
7002 			{
7003 				TestConfig config = baseConfig;
7004 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_NOT_EQUAL;
7005 
7006 				// Draw first mesh in front.
7007 				config.meshParams[0].depth					= 0.25f;
7008 				// Draw another mesh in the back, this should pass too.
7009 				config.meshParams.push_back(MeshParams(kAlternativeColor, 0.5f));
7010 				// Finally a new mesh with the same depth. This should not pass.
7011 				config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.5f));
7012 
7013 				config.referenceColor.reset					(new SingleColorGenerator(kAlternativeColor));
7014 				config.expectedDepth						= 0.5f;
7015 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_not_equal", "Dynamically set the depth compare operator to NOT_EQUAL", config));
7016 			}
7017 			{
7018 				TestConfig config = baseConfig;
7019 				config.depthCompareOpConfig.dynamicValue	= vk::VK_COMPARE_OP_ALWAYS;
7020 
7021 				config.meshParams[0].depth					= 0.5f;
7022 				config.expectedDepth						= 0.5f;
7023 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_equal", "Dynamically set the depth compare operator to ALWAYS and draw with equal depth", config));
7024 
7025 				config.meshParams[0].depth					= 0.25f;
7026 				config.expectedDepth						= 0.25f;
7027 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_less", "Dynamically set the depth compare operator to ALWAYS and draw with less depth", config));
7028 
7029 				config.meshParams[0].depth					= 0.75f;
7030 				config.expectedDepth						= 0.75f;
7031 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_greater", "Dynamically set the depth compare operator to ALWAYS and draw with greater depth", config));
7032 			}
7033 		}
7034 
7035 		// Depth bounds test.
7036 		{
7037 			TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
7038 			baseConfig.minDepthBounds							= 0.25f;
7039 			baseConfig.maxDepthBounds							= 0.75f;
7040 			baseConfig.meshParams[0].depth						= 0.0f;
7041 
7042 			{
7043 				TestConfig config = baseConfig;
7044 				config.depthBoundsTestEnableConfig.staticValue	= false;
7045 				config.depthBoundsTestEnableConfig.dynamicValue	= tcu::just(true);
7046 				config.referenceColor.reset						(new SingleColorGenerator(kDefaultClearColor));
7047 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_enable", "Dynamically enable the depth bounds test", config));
7048 			}
7049 			{
7050 				TestConfig config = baseConfig;
7051 				config.depthBoundsTestEnableConfig.staticValue	= true;
7052 				config.depthBoundsTestEnableConfig.dynamicValue	= tcu::just(false);
7053 				orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_disable", "Dynamically disable the depth bounds test", config));
7054 			}
7055 		}
7056 
7057 		// Stencil test enable.
7058 		{
7059 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7060 			config.stencilTestEnableConfig.staticValue				= false;
7061 			config.stencilTestEnableConfig.dynamicValue				= tcu::just(true);
7062 			config.stencilOpConfig.staticValue.front().compareOp	= vk::VK_COMPARE_OP_NEVER;
7063 			config.referenceColor.reset								(new SingleColorGenerator(kDefaultClearColor));
7064 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_enable", "Dynamically enable the stencil test", config));
7065 		}
7066 		{
7067 			TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7068 			config.stencilTestEnableConfig.staticValue				= true;
7069 			config.stencilTestEnableConfig.dynamicValue				= tcu::just(false);
7070 			config.stencilOpConfig.staticValue.front().compareOp	= vk::VK_COMPARE_OP_NEVER;
7071 			orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_disable", "Dynamically disable the stencil test", config));
7072 		}
7073 
7074 		// Stencil operation. Many combinations are possible.
7075 		{
7076 			static const struct
7077 			{
7078 				vk::VkStencilFaceFlags	face;
7079 				std::string				name;
7080 			} kFaces[] =
7081 			{
7082 				{ vk::VK_STENCIL_FACE_FRONT_BIT,			"face_front"		},
7083 				{ vk::VK_STENCIL_FACE_BACK_BIT,				"face_back"			},
7084 				{ vk::VK_STENCIL_FACE_FRONT_AND_BACK,		"face_both_single"	},
7085 				{ vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM,	"face_both_dual"	},	// MAX_ENUM is a placeholder.
7086 			};
7087 
7088 			static const struct
7089 			{
7090 				vk::VkCompareOp		compareOp;
7091 				std::string			name;
7092 			} kCompare[] =
7093 			{
7094 				{ vk::VK_COMPARE_OP_NEVER,				"xf"		},
7095 				{ vk::VK_COMPARE_OP_LESS,				"lt"		},
7096 				{ vk::VK_COMPARE_OP_EQUAL,				"eq"		},
7097 				{ vk::VK_COMPARE_OP_LESS_OR_EQUAL,		"le"		},
7098 				{ vk::VK_COMPARE_OP_GREATER,			"gt"		},
7099 				{ vk::VK_COMPARE_OP_GREATER_OR_EQUAL,	"ge"		},
7100 				{ vk::VK_COMPARE_OP_ALWAYS,				"xt"		},
7101 			};
7102 
7103 			using u8vec = std::vector<deUint8>;
7104 
7105 			static const auto kMinVal	= std::numeric_limits<deUint8>::min();
7106 			static const auto kMaxVal	= std::numeric_limits<deUint8>::max();
7107 			static const auto kMidVal	= static_cast<deUint8>(kMaxVal * 2u / 5u);
7108 			static const auto kMinValI	= static_cast<int>(kMinVal);
7109 			static const auto kMaxValI	= static_cast<int>(kMaxVal);
7110 
7111 			static const struct
7112 			{
7113 				vk::VkStencilOp		stencilOp;
7114 				std::string			name;
7115 				u8vec				clearValues;	// One test per clear value interesting for this operation.
7116 				vk::VkStencilOp		incompatibleOp;	// Alternative operation giving incompatible results for the given values.
7117 			} kStencilOps[] =
7118 			{
7119 				{ vk::VK_STENCIL_OP_KEEP,					"keep",			u8vec{kMidVal},					vk::VK_STENCIL_OP_ZERO					},
7120 				{ vk::VK_STENCIL_OP_ZERO,					"zero",			u8vec{kMidVal},					vk::VK_STENCIL_OP_KEEP					},
7121 				{ vk::VK_STENCIL_OP_REPLACE,				"replace",		u8vec{kMidVal},					vk::VK_STENCIL_OP_ZERO					},
7122 				{ vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP,	"inc_clamp",	u8vec{kMaxVal - 1, kMaxVal},	vk::VK_STENCIL_OP_ZERO					},
7123 				{ vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP,	"dec_clamp",	u8vec{kMinVal + 1, kMinVal},	vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP	},
7124 				{ vk::VK_STENCIL_OP_INVERT,					"invert",		u8vec{kMidVal},					vk::VK_STENCIL_OP_ZERO					},
7125 				{ vk::VK_STENCIL_OP_INCREMENT_AND_WRAP,		"inc_wrap",		u8vec{kMaxVal - 1, kMaxVal},	vk::VK_STENCIL_OP_KEEP					},
7126 				{ vk::VK_STENCIL_OP_DECREMENT_AND_WRAP,		"dec_wrap",		u8vec{kMinVal + 1, kMinVal},	vk::VK_STENCIL_OP_KEEP					},
7127 			};
7128 
7129 			for (const auto& face : kFaces)
7130 			for (const auto& compare : kCompare)
7131 			for (const auto& op : kStencilOps)
7132 			{
7133 				// Try clearing the stencil value with different values.
7134 				for (const auto clearVal : op.clearValues)
7135 				{
7136 					// Use interesting values as the reference stencil value.
7137 					for (int delta = -1; delta <= 1; ++delta)
7138 					{
7139 						const int refVal = clearVal + delta;
7140 						if (refVal < kMinValI || refVal > kMaxValI)
7141 							continue;
7142 
7143 						const auto refValU8		= static_cast<deUint8>(refVal);
7144 						const auto refValU32	= static_cast<deUint32>(refVal);
7145 
7146 						// Calculate outcome of the stencil test itself.
7147 						const bool wouldPass = stencilPasses(compare.compareOp, clearVal, refValU8);
7148 
7149 						// If the test passes, use an additional variant for the depthFail operation.
7150 						const int subCases = (wouldPass ? 2 : 1);
7151 
7152 						for (int subCaseIdx = 0; subCaseIdx < subCases; ++subCaseIdx)
7153 						{
7154 							const bool depthFail	= (subCaseIdx > 0);				// depthFail would be the second variant.
7155 							const bool globalPass	= (wouldPass && !depthFail);	// Global result of the stencil+depth test.
7156 
7157 							// Start tuning test parameters.
7158 							TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7159 
7160 							// No face culling is applied by default, so both the front and back operations could apply depending on the mesh.
7161 							if (face.face == vk::VK_STENCIL_FACE_FRONT_BIT)
7162 							{
7163 								// Default parameters are OK.
7164 							}
7165 							else if (face.face == vk::VK_STENCIL_FACE_BACK_BIT)
7166 							{
7167 								// Reverse the mesh so it applies the back operation.
7168 								config.meshParams[0].reversed = true;
7169 							}
7170 							else	// Front and back.
7171 							{
7172 								// Draw both a front and a back-facing mesh so both are applied.
7173 								// The first mesh will be drawn in the top half and the second mesh in the bottom half.
7174 
7175 								// Make the second mesh a reversed copy of the first mesh.
7176 								config.meshParams.push_back(config.meshParams.front());
7177 								config.meshParams.back().reversed = true;
7178 
7179 								// Apply scale and offset to the top mesh.
7180 								config.meshParams.front().scaleY = 0.5f;
7181 								config.meshParams.front().offsetY = -0.5f;
7182 
7183 								// Apply scale and offset to the bottom mesh.
7184 								config.meshParams.back().scaleY = 0.5f;
7185 								config.meshParams.back().offsetY = 0.5f;
7186 							}
7187 
7188 							// Enable the stencil test.
7189 							config.stencilTestEnableConfig.staticValue = true;
7190 
7191 							// Set dynamic configuration.
7192 							StencilOpParams dynamicStencilConfig;
7193 							dynamicStencilConfig.faceMask		= face.face;
7194 							dynamicStencilConfig.compareOp		= compare.compareOp;
7195 							dynamicStencilConfig.failOp			= vk::VK_STENCIL_OP_MAX_ENUM;
7196 							dynamicStencilConfig.passOp			= vk::VK_STENCIL_OP_MAX_ENUM;
7197 							dynamicStencilConfig.depthFailOp	= vk::VK_STENCIL_OP_MAX_ENUM;
7198 
7199 							// Set operations so only the appropriate operation for this case gives the right result.
7200 							vk::VkStencilOp* activeOp		= nullptr;
7201 							vk::VkStencilOp* inactiveOps[2]	= { nullptr, nullptr };
7202 							if (wouldPass)
7203 							{
7204 								if (depthFail)
7205 								{
7206 									activeOp		= &dynamicStencilConfig.depthFailOp;
7207 									inactiveOps[0]	= &dynamicStencilConfig.passOp;
7208 									inactiveOps[1]	= &dynamicStencilConfig.failOp;
7209 								}
7210 								else
7211 								{
7212 									activeOp		= &dynamicStencilConfig.passOp;
7213 									inactiveOps[0]	= &dynamicStencilConfig.depthFailOp;
7214 									inactiveOps[1]	= &dynamicStencilConfig.failOp;
7215 								}
7216 							}
7217 							else
7218 							{
7219 								activeOp		= &dynamicStencilConfig.failOp;
7220 								inactiveOps[0]	= &dynamicStencilConfig.passOp;
7221 								inactiveOps[1]	= &dynamicStencilConfig.depthFailOp;
7222 							}
7223 
7224 							*activeOp = op.stencilOp;
7225 							*inactiveOps[0] = op.incompatibleOp;
7226 							*inactiveOps[1] = op.incompatibleOp;
7227 
7228 							// Make sure all ops have been configured properly.
7229 							DE_ASSERT(dynamicStencilConfig.failOp != vk::VK_STENCIL_OP_MAX_ENUM);
7230 							DE_ASSERT(dynamicStencilConfig.passOp != vk::VK_STENCIL_OP_MAX_ENUM);
7231 							DE_ASSERT(dynamicStencilConfig.depthFailOp != vk::VK_STENCIL_OP_MAX_ENUM);
7232 
7233 							// Set an incompatible static operation too.
7234 							auto& staticStencilConfig		= config.stencilOpConfig.staticValue.front();
7235 							staticStencilConfig.faceMask	= face.face;
7236 							staticStencilConfig.compareOp	= (globalPass ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
7237 							staticStencilConfig.passOp		= op.incompatibleOp;
7238 							staticStencilConfig.failOp		= op.incompatibleOp;
7239 							staticStencilConfig.depthFailOp	= op.incompatibleOp;
7240 
7241 							// Set dynamic configuration.
7242 							StencilOpVec stencilOps;
7243 							stencilOps.push_back(dynamicStencilConfig);
7244 
7245 							if (stencilOps.front().faceMask == vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM)
7246 							{
7247 								// This is the dual case. We will set the front and back face values with two separate calls.
7248 								stencilOps.push_back(stencilOps.front());
7249 								stencilOps.front().faceMask		= vk::VK_STENCIL_FACE_FRONT_BIT;
7250 								stencilOps.back().faceMask		= vk::VK_STENCIL_FACE_BACK_BIT;
7251 								staticStencilConfig.faceMask	= vk::VK_STENCIL_FACE_FRONT_AND_BACK;
7252 							}
7253 
7254 							config.stencilOpConfig.dynamicValue	= tcu::just(stencilOps);
7255 							config.clearStencilValue			= clearVal;
7256 							config.referenceStencil				= refValU32;
7257 
7258 							if (depthFail)
7259 							{
7260 								// Enable depth test and make it fail.
7261 								config.depthTestEnableConfig.staticValue	= true;
7262 								config.clearDepthValue						= 0.5f;
7263 								config.depthCompareOpConfig.staticValue		= vk::VK_COMPARE_OP_LESS;
7264 
7265 								for (auto& meshPar : config.meshParams)
7266 									meshPar.depth = 0.75f;
7267 							}
7268 
7269 							// Set expected outcome.
7270 							config.referenceColor.reset	(new SingleColorGenerator(globalPass ? kDefaultTriangleColor : kDefaultClearColor));
7271 							config.expectedDepth		= config.clearDepthValue; // No depth writing by default.
7272 							config.expectedStencil		= stencilResult(op.stencilOp, clearVal, refValU8, kMinVal, kMaxVal);
7273 
7274 							const std::string testName = std::string("stencil_state")
7275 								+ "_" + face.name
7276 								+ "_" + compare.name
7277 								+ "_" + op.name
7278 								+ "_clear_" + de::toString(static_cast<int>(clearVal))
7279 								+ "_ref_" + de::toString(refVal)
7280 								+ "_" + (wouldPass ? (depthFail ? "depthfail" : "pass") : "fail");
7281 
7282 							orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, "Dynamically configure stencil test, variant " + testName, config));
7283 						}
7284 					}
7285 				}
7286 			}
7287 		}
7288 
7289 		// Vertex input.
7290 		if (!kUseMeshShaders)
7291 		{
7292 			for (const auto& bindUnusedCase : kBindUnusedCases)
7293 			{
7294 				if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7295 					continue;
7296 
7297 				// TWO_DRAWS_STATIC would be invalid because it violates VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the
7298 				// dynamic stride being less than the extent of the binding for the second attribute.
7299 				if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
7300 				{
7301 					const auto	staticGen	= getVertexWithPaddingGenerator();
7302 					const auto	dynamicGen	= getVertexWithExtraAttributesGenerator();
7303 					const auto	goodStrides	= dynamicGen->getVertexDataStrides();
7304 					StrideVec	badStrides;
7305 
7306 					badStrides.reserve(goodStrides.size());
7307 					for (const auto& stride : goodStrides)
7308 						badStrides.push_back(stride / 2u);
7309 
7310 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, staticGen, dynamicGen);
7311 					config.strideConfig.staticValue			= badStrides;
7312 					config.strideConfig.dynamicValue		= goodStrides;
7313 					config.bindUnusedMeshShadingPipeline	= bindUnusedCase.bindUnusedMeshShadingPipeline;
7314 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input" + bindUnusedCase.nameSuffix, "Dynamically set vertex input" + bindUnusedCase.descSuffix, config));
7315 				}
7316 
7317 				{
7318 					// Variant without mixing in the stride config.
7319 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithPaddingGenerator(), getVertexWithExtraAttributesGenerator());
7320 					config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7321 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_no_dyn_stride" + bindUnusedCase.nameSuffix, "Dynamically set vertex input without using dynamic strides" + bindUnusedCase.descSuffix, config));
7322 				}
7323 
7324 				{
7325 					// Variant using multiple bindings.
7326 					TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, getVertexWithExtraAttributesGenerator(), getVertexWithMultipleBindingsGenerator());
7327 					config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7328 					orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_multiple_bindings" + bindUnusedCase.nameSuffix, "Dynamically set vertex input with multiple bindings" + bindUnusedCase.descSuffix, config));
7329 				}
7330 			}
7331 		}
7332 
7333 		tcu::TestCaseGroup* group = (kUseMeshShaders ? meshShaderGroup.get() : extendedDynamicStateGroup.get());
7334 		group->addChild(orderingGroup.release());
7335 	}
7336 
7337 	extendedDynamicStateGroup->addChild(meshShaderGroup.release());
7338 	return extendedDynamicStateGroup.release();
7339 }
7340 
7341 } // pipeline
7342 } // vkt
7343