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