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