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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::StaticAndDynamicPair1344 StaticAndDynamicPair(const T &value) : staticValue(value), dynamicValue(tcu::Nothing)
1345 {
1346 }
1347
1348 // Helper constructor to set both.
StaticAndDynamicPairvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig2395 DepthBiasParams getActiveDepthBiasParams() const
2396 {
2397 return ((depthBiasConfig.dynamicValue && !m_swappedValues) ? depthBiasConfig.dynamicValue.get() :
2398 depthBiasConfig.staticValue);
2399 }
2400
getActiveTessellationDomainOriginvkt::pipeline::__anon851b088d0111::TestConfig2401 vk::VkTessellationDomainOrigin getActiveTessellationDomainOrigin() const
2402 {
2403 return ((tessDomainOriginConfig.dynamicValue && !m_swappedValues) ? tessDomainOriginConfig.dynamicValue.get() :
2404 tessDomainOriginConfig.staticValue);
2405 }
2406
getActivePolygonModevkt::pipeline::__anon851b088d0111::TestConfig2407 vk::VkPolygonMode getActivePolygonMode() const
2408 {
2409 return ((polygonModeConfig.dynamicValue && !m_swappedValues) ? polygonModeConfig.dynamicValue.get() :
2410 polygonModeConfig.staticValue);
2411 }
2412
getActiveSampleCountvkt::pipeline::__anon851b088d0111::TestConfig2413 vk::VkSampleCountFlagBits getActiveSampleCount() const
2414 {
2415 return ((rasterizationSamplesConfig.dynamicValue && !m_swappedValues) ?
2416 rasterizationSamplesConfig.dynamicValue.get() :
2417 rasterizationSamplesConfig.staticValue);
2418 }
2419
getActiveAlphaToOnevkt::pipeline::__anon851b088d0111::TestConfig2420 bool getActiveAlphaToOne() const
2421 {
2422 return ((alphaToOneConfig.dynamicValue && !m_swappedValues) ? alphaToOneConfig.dynamicValue.get() :
2423 alphaToOneConfig.staticValue);
2424 }
2425
rasterizationStreamStructvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig2454 bool hasStaticLineStippleParams() const
2455 {
2456 return (static_cast<bool>(lineStippleParamsConfig.staticValue));
2457 }
2458
hasStaticLineRasterModevkt::pipeline::__anon851b088d0111::TestConfig2459 bool hasStaticLineRasterMode() const
2460 {
2461 return (static_cast<bool>(lineRasterModeConfig.staticValue));
2462 }
2463
hasLineStippleParamsvkt::pipeline::__anon851b088d0111::TestConfig2464 bool hasLineStippleParams() const
2465 {
2466 return (hasStaticLineStippleParams() || (static_cast<bool>(lineStippleParamsConfig.dynamicValue) &&
2467 static_cast<bool>(lineStippleParamsConfig.dynamicValue.get())));
2468 }
2469
hasLineRasterModevkt::pipeline::__anon851b088d0111::TestConfig2470 bool hasLineRasterMode() const
2471 {
2472 return (hasStaticLineRasterMode() || (static_cast<bool>(lineRasterModeConfig.dynamicValue) &&
2473 static_cast<bool>(lineRasterModeConfig.dynamicValue.get())));
2474 }
2475
lineStippleSupportRequiredvkt::pipeline::__anon851b088d0111::TestConfig2476 bool lineStippleSupportRequired() const
2477 {
2478 return (lineStippleEnableConfig.staticValue || (static_cast<bool>(lineStippleEnableConfig.dynamicValue) &&
2479 lineStippleEnableConfig.dynamicValue.get()));
2480 }
2481
lineRasterStructvkt::pipeline::__anon851b088d0111::TestConfig2482 bool lineRasterStruct() const
2483 {
2484 return (static_cast<bool>(lineStippleEnableConfig.dynamicValue) || lineStippleEnableConfig.staticValue ||
2485 hasStaticLineStippleParams() || hasStaticLineRasterMode());
2486 }
2487
lineRasterizationExtvkt::pipeline::__anon851b088d0111::TestConfig2488 bool lineRasterizationExt() const
2489 {
2490 return (lineRasterStruct() || hasLineStippleParams() || hasLineRasterMode());
2491 }
2492
sampleLocationsStructvkt::pipeline::__anon851b088d0111::TestConfig2493 bool sampleLocationsStruct() const
2494 {
2495 return (static_cast<bool>(sampleLocationsEnableConfig.dynamicValue) || sampleLocationsEnableConfig.staticValue);
2496 }
2497
coverageToColorStructvkt::pipeline::__anon851b088d0111::TestConfig2498 bool coverageToColorStruct() const
2499 {
2500 return (static_cast<bool>(coverageToColorEnableConfig.dynamicValue) || coverageToColorEnableConfig.staticValue);
2501 }
2502
conservativeRasterStructvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig2557 bool isMultiViewport() const
2558 {
2559 return (getActiveViewportVec().size() > 1);
2560 }
2561
2562 // Returns true if the case needs a geometry shader.
needsGeometryShadervkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig2588 bool useStaticPipeline() const
2589 {
2590 return (bindStaticFirst() || isReversed());
2591 }
2592
2593 // Swaps static and dynamic configuration values.
swapValuesvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig2700 bool testPrimRestartEnable() const
2701 {
2702 return static_cast<bool>(primRestartEnableConfig.dynamicValue);
2703 }
2704
2705 // Returns the topology class.
topologyClassvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::TestConfig2712 bool patchesTopology() const
2713 {
2714 return (topologyClass() == TopologyClass::PATCH);
2715 }
2716
2717 // Returns true if the test needs tessellation shaders.
needsTessellationvkt::pipeline::__anon851b088d0111::TestConfig2718 bool needsTessellation() const
2719 {
2720 return (testPatchControlPoints() || patchesTopology() || testTessellationDomainOrigin());
2721 }
2722
2723 // Returns the active line stipple enablement flag.
getActiveLineStippleEnablevkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig2969 bool testEDS2() const
2970 {
2971 return (rastDiscardEnableConfig.dynamicValue || depthBiasEnableConfig.dynamicValue ||
2972 primRestartEnableConfig.dynamicValue || useExtraDynPCPPipeline);
2973 }
2974
testVertexDynamicvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::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::__anon851b088d0111::TestConfig3082 uint32_t getFragDescriptorSetIndex() const
3083 {
3084 return (useMeshShaders ? 1u : 0u);
3085 }
3086
useFragShaderAtomicsvkt::pipeline::__anon851b088d0111::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::__anon851b088d0111::VertexBufferInfo4088 VertexBufferInfo() : buffer(), offset(0ull), dataSize(0ull)
4089 {
4090 }
4091
VertexBufferInfovkt::pipeline::__anon851b088d0111::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 {
4372 // VUID-VkColorBlendEquationEXT-colorBlendOp-07361 forbids colorBlendOp and alphaBlendOp to be any advanced operation.
4373 // When the advanced blend op will be set by vkCmdSetColorBlendAdvancedEXT, we use a legal placeholder in this call.
4374 vk::VkBlendOp colorBlendOp = vk::VK_BLEND_OP_ADD;
4375 vk::VkBlendOp alphaBlendOp = vk::VK_BLEND_OP_ADD;
4376
4377 if (!isAdvanced)
4378 {
4379 colorBlendOp = configEq.colorBlendOp;
4380 alphaBlendOp = configEq.alphaBlendOp;
4381 }
4382
4383 const vk::VkColorBlendEquationEXT equation = {
4384 configEq.srcColorBlendFactor, // VkBlendFactor srcColorBlendFactor;
4385 configEq.dstColorBlendFactor, // VkBlendFactor dstColorBlendFactor;
4386 colorBlendOp, // VkBlendOp colorBlendOp;
4387 configEq.srcAlphaBlendFactor, // VkBlendFactor srcAlphaBlendFactor;
4388 configEq.dstAlphaBlendFactor, // VkBlendFactor dstAlphaBlendFactor;
4389 alphaBlendOp, // VkBlendOp alphaBlendOp;
4390 };
4391 const std::vector<vk::VkColorBlendEquationEXT> equations(testConfig.colorAttachmentCount, equation);
4392 vkd.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, de::sizeU32(equations), de::dataOrNull(equations));
4393 }
4394 }
4395
4396 if (testConfig.provokingVertexConfig.dynamicValue &&
4397 static_cast<bool>(testConfig.provokingVertexConfig.dynamicValue.get()))
4398 {
4399 const auto provokingVertexMode = makeProvokingVertexMode(testConfig.provokingVertexConfig.dynamicValue->get());
4400 vkd.cmdSetProvokingVertexModeEXT(cmdBuffer, provokingVertexMode);
4401 }
4402
4403 if (testConfig.negativeOneToOneConfig.dynamicValue &&
4404 static_cast<bool>(testConfig.negativeOneToOneConfig.dynamicValue.get()))
4405 vkd.cmdSetDepthClipNegativeOneToOneEXT(cmdBuffer,
4406 makeVkBool32(testConfig.negativeOneToOneConfig.dynamicValue->get()));
4407
4408 if (testConfig.depthClipEnableConfig.dynamicValue &&
4409 static_cast<bool>(testConfig.depthClipEnableConfig.dynamicValue.get()))
4410 vkd.cmdSetDepthClipEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthClipEnableConfig.dynamicValue->get()));
4411
4412 if (testConfig.lineStippleEnableConfig.dynamicValue)
4413 vkd.cmdSetLineStippleEnableEXT(cmdBuffer, makeVkBool32(testConfig.lineStippleEnableConfig.dynamicValue.get()));
4414
4415 if (testConfig.sampleLocationsEnableConfig.dynamicValue)
4416 vkd.cmdSetSampleLocationsEnableEXT(cmdBuffer,
4417 makeVkBool32(testConfig.sampleLocationsEnableConfig.dynamicValue.get()));
4418
4419 if (testConfig.conservativeRasterModeConfig.dynamicValue)
4420 vkd.cmdSetConservativeRasterizationModeEXT(cmdBuffer,
4421 testConfig.conservativeRasterModeConfig.dynamicValue.get());
4422
4423 if (testConfig.extraPrimitiveOverEstConfig.dynamicValue)
4424 vkd.cmdSetExtraPrimitiveOverestimationSizeEXT(cmdBuffer,
4425 testConfig.extraPrimitiveOverEstConfig.dynamicValue.get());
4426
4427 if (testConfig.lineRasterModeConfig.dynamicValue &&
4428 static_cast<bool>(testConfig.lineRasterModeConfig.dynamicValue.get()))
4429 vkd.cmdSetLineRasterizationModeEXT(
4430 cmdBuffer, makeLineRasterizationMode(testConfig.lineRasterModeConfig.dynamicValue->get()));
4431
4432 if (testConfig.coverageToColorEnableConfig.dynamicValue)
4433 vkd.cmdSetCoverageToColorEnableNV(cmdBuffer,
4434 makeVkBool32(testConfig.coverageToColorEnableConfig.dynamicValue.get()));
4435
4436 if (testConfig.coverageToColorLocationConfig.dynamicValue)
4437 vkd.cmdSetCoverageToColorLocationNV(cmdBuffer, testConfig.coverageToColorLocationConfig.dynamicValue.get());
4438
4439 if (testConfig.coverageModulationModeConfig.dynamicValue)
4440 vkd.cmdSetCoverageModulationModeNV(cmdBuffer, testConfig.coverageModulationModeConfig.dynamicValue.get());
4441
4442 if (testConfig.coverageModTableEnableConfig.dynamicValue)
4443 vkd.cmdSetCoverageModulationTableEnableNV(
4444 cmdBuffer, makeVkBool32(testConfig.coverageModTableEnableConfig.dynamicValue.get()));
4445
4446 if (testConfig.coverageModTableConfig.dynamicValue)
4447 {
4448 const auto &tableVec = testConfig.coverageModTableConfig.dynamicValue.get();
4449 vkd.cmdSetCoverageModulationTableNV(cmdBuffer, static_cast<uint32_t>(tableVec.size()),
4450 de::dataOrNull(tableVec));
4451 }
4452
4453 if (testConfig.coverageReductionModeConfig.dynamicValue)
4454 vkd.cmdSetCoverageReductionModeNV(cmdBuffer, testConfig.coverageReductionModeConfig.dynamicValue.get());
4455
4456 if (testConfig.viewportSwizzleConfig.dynamicValue)
4457 {
4458 const auto &viewportSwizzleVec = testConfig.viewportSwizzleConfig.dynamicValue.get();
4459 vkd.cmdSetViewportSwizzleNV(cmdBuffer, 0u, static_cast<uint32_t>(viewportSwizzleVec.size()),
4460 de::dataOrNull(viewportSwizzleVec));
4461 }
4462
4463 if (testConfig.shadingRateImageEnableConfig.dynamicValue)
4464 vkd.cmdSetShadingRateImageEnableNV(cmdBuffer,
4465 makeVkBool32(testConfig.shadingRateImageEnableConfig.dynamicValue.get()));
4466
4467 if (testConfig.viewportWScalingEnableConfig.dynamicValue)
4468 vkd.cmdSetViewportWScalingEnableNV(cmdBuffer,
4469 makeVkBool32(testConfig.viewportWScalingEnableConfig.dynamicValue.get()));
4470
4471 if (testConfig.reprFragTestEnableConfig.dynamicValue)
4472 vkd.cmdSetRepresentativeFragmentTestEnableNV(
4473 cmdBuffer, makeVkBool32(testConfig.reprFragTestEnableConfig.dynamicValue.get()));
4474
4475 #endif // CTS_USES_VULKANSC
4476 }
4477
4478 // Bind the appropriate vertex buffers using dynamic strides if the test configuration needs a dynamic stride.
4479 // 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)4480 bool maybeBindVertexBufferDynStride(const TestConfig &testConfig, const vk::DeviceInterface &vkd,
4481 vk::VkCommandBuffer cmdBuffer, size_t meshIdx,
4482 const std::vector<VertexBufferInfo> &vertBuffers,
4483 const std::vector<VertexBufferInfo> &rvertBuffers)
4484 {
4485 if (!testConfig.strideConfig.dynamicValue)
4486 return false;
4487
4488 DE_ASSERT(!testConfig.useMeshShaders);
4489
4490 const auto &viewportVec = testConfig.getActiveViewportVec();
4491 DE_UNREF(viewportVec); // For release builds.
4492
4493 // When dynamically setting the vertex buffer stride, we cannot bind the vertex buffer in advance for some sequence
4494 // orderings if we have several viewports or meshes.
4495 DE_ASSERT((viewportVec.size() == 1u && testConfig.meshParams.size() == 1u) ||
4496 testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW ||
4497 testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
4498
4499 // Split buffers, offsets, sizes and strides into their own vectors for the call.
4500 std::vector<vk::VkBuffer> buffers;
4501 std::vector<vk::VkDeviceSize> offsets;
4502 std::vector<vk::VkDeviceSize> sizes;
4503 const auto strides = testConfig.strideConfig.dynamicValue.get();
4504
4505 const auto &chosenBuffers = (testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers);
4506
4507 buffers.reserve(chosenBuffers.size());
4508 offsets.reserve(chosenBuffers.size());
4509 sizes.reserve(chosenBuffers.size());
4510 DE_ASSERT(chosenBuffers.size() == strides.size());
4511
4512 for (const auto &vertBuffer : chosenBuffers)
4513 {
4514 buffers.push_back(vertBuffer.buffer->get());
4515 offsets.push_back(vertBuffer.offset);
4516 sizes.push_back(vertBuffer.dataSize);
4517 }
4518
4519 #ifndef CTS_USES_VULKANSC
4520 vkd.cmdBindVertexBuffers2(cmdBuffer, 0u, static_cast<uint32_t>(chosenBuffers.size()), buffers.data(),
4521 offsets.data(), sizes.data(), strides.data());
4522 #else
4523 vkd.cmdBindVertexBuffers2EXT(cmdBuffer, 0u, static_cast<uint32_t>(chosenBuffers.size()), buffers.data(),
4524 offsets.data(), sizes.data(), strides.data());
4525 #endif // CTS_USES_VULKANSC
4526
4527 return true;
4528 }
4529
4530 // 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)4531 void bindVertexBuffers(const vk::DeviceInterface &vkd, vk::VkCommandBuffer cmdBuffer,
4532 const std::vector<VertexBufferInfo> &vertexBuffers)
4533 {
4534 std::vector<vk::VkBuffer> buffers;
4535 std::vector<vk::VkDeviceSize> offsets;
4536
4537 buffers.reserve(vertexBuffers.size());
4538 offsets.reserve(vertexBuffers.size());
4539
4540 for (const auto &vertBuffer : vertexBuffers)
4541 {
4542 buffers.push_back(vertBuffer.buffer->get());
4543 offsets.push_back(vertBuffer.offset);
4544 }
4545
4546 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, static_cast<uint32_t>(vertexBuffers.size()), buffers.data(),
4547 offsets.data());
4548 }
4549
4550 // 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)4551 void prepareVertexBuffers(std::vector<VertexBufferInfo> &buffers, const vk::DeviceInterface &vkd, vk::VkDevice device,
4552 vk::Allocator &allocator, const VertexGenerator *generator,
4553 const std::vector<tcu::Vec2> &vertices, uint32_t dataOffset, uint32_t trailingSize,
4554 bool ssbos)
4555 {
4556 const uint32_t paddingBytes = 0xDEADBEEFu;
4557 const auto vertexData =
4558 generator->createVertexData(vertices, dataOffset, trailingSize, &paddingBytes, sizeof(paddingBytes));
4559
4560 for (const auto &bufferBytes : vertexData)
4561 {
4562 const auto bufferSize = static_cast<vk::VkDeviceSize>(de::dataSize(bufferBytes));
4563 const auto extraSize = static_cast<vk::VkDeviceSize>(dataOffset + trailingSize);
4564 DE_ASSERT(bufferSize > extraSize);
4565 const auto dataSize = bufferSize - extraSize;
4566
4567 // Create a full-size buffer but remember the data size and offset for it.
4568 const auto createInfo = vk::makeBufferCreateInfo(
4569 bufferSize, (ssbos ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
4570
4571 VertexBufferInfo bufferInfo;
4572 bufferInfo.buffer = BufferWithMemoryPtr(
4573 new vk::BufferWithMemory(vkd, device, allocator, createInfo, vk::MemoryRequirement::HostVisible));
4574 bufferInfo.offset = static_cast<vk::VkDeviceSize>(dataOffset);
4575 bufferInfo.dataSize = dataSize;
4576 buffers.emplace_back(std::move(bufferInfo));
4577
4578 // Copy the whole contents to the full buffer.
4579 copyAndFlush(vkd, device, *buffers.back().buffer, 0, bufferBytes.data(), de::dataSize(bufferBytes));
4580 }
4581 }
4582
4583 // Device helper: this is needed in some tests when we create custom devices.
4584 class DeviceHelper
4585 {
4586 public:
~DeviceHelper()4587 virtual ~DeviceHelper()
4588 {
4589 }
4590 virtual const vk::DeviceInterface &getDeviceInterface(void) const = 0;
4591 virtual vk::VkDevice getDevice(void) const = 0;
4592 virtual uint32_t getQueueFamilyIndex(void) const = 0;
4593 virtual vk::VkQueue getQueue(void) const = 0;
4594 virtual vk::Allocator &getAllocator(void) const = 0;
4595 virtual const std::vector<std::string> &getDeviceExtensions(void) const = 0;
4596 };
4597
4598 // This one just reuses the default device from the context.
4599 class ContextDeviceHelper : public DeviceHelper
4600 {
4601 public:
ContextDeviceHelper(Context & context)4602 ContextDeviceHelper(Context &context)
4603 : m_deviceInterface(context.getDeviceInterface())
4604 , m_device(context.getDevice())
4605 , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
4606 , m_queue(context.getUniversalQueue())
4607 , m_allocator(context.getDefaultAllocator())
4608 , m_extensions(context.getDeviceExtensions())
4609 {
4610 }
4611
~ContextDeviceHelper()4612 virtual ~ContextDeviceHelper()
4613 {
4614 }
4615
getDeviceInterface(void) const4616 const vk::DeviceInterface &getDeviceInterface(void) const override
4617 {
4618 return m_deviceInterface;
4619 }
getDevice(void) const4620 vk::VkDevice getDevice(void) const override
4621 {
4622 return m_device;
4623 }
getQueueFamilyIndex(void) const4624 uint32_t getQueueFamilyIndex(void) const override
4625 {
4626 return m_queueFamilyIndex;
4627 }
getQueue(void) const4628 vk::VkQueue getQueue(void) const override
4629 {
4630 return m_queue;
4631 }
getAllocator(void) const4632 vk::Allocator &getAllocator(void) const override
4633 {
4634 return m_allocator;
4635 }
getDeviceExtensions(void) const4636 const std::vector<std::string> &getDeviceExtensions(void) const override
4637 {
4638 return m_extensions;
4639 }
4640
4641 protected:
4642 const vk::DeviceInterface &m_deviceInterface;
4643 const vk::VkDevice m_device;
4644 const uint32_t m_queueFamilyIndex;
4645 const vk::VkQueue m_queue;
4646 vk::Allocator &m_allocator;
4647 std::vector<std::string> m_extensions;
4648 };
4649
4650 // A non-default device helper that can create a custom device with some options that can be specify in the constructor.
4651 class CustomizedDeviceHelper : public DeviceHelper
4652 {
4653 public:
4654 // Options, chosen so that a default value of false gives the default device.
4655 struct Options
4656 {
4657 bool shadingRateImage; // Enable VK_NV_shading_rate_image.
4658 bool disableAlphaToOne; // Forcefully disable alphaToOne.
4659 bool disableAdvBlendingCoherentOps;
4660
4661 // We need to sort these options in a map below, so we need operator< and the boilerplate below.
operator <vkt::pipeline::__anon851b088d0111::CustomizedDeviceHelper::Options4662 bool operator<(const Options &other) const
4663 {
4664 return (this->toVec() < other.toVec());
4665 }
4666
4667 private:
toVecvkt::pipeline::__anon851b088d0111::CustomizedDeviceHelper::Options4668 std::vector<bool> toVec(void) const
4669 {
4670 return std::vector<bool>{shadingRateImage, disableAlphaToOne, disableAdvBlendingCoherentOps};
4671 }
4672 };
4673
CustomizedDeviceHelper(Context & context,const Options & options)4674 CustomizedDeviceHelper(Context &context, const Options &options)
4675 {
4676 const auto &vkp = context.getPlatformInterface();
4677 const auto &vki = context.getInstanceInterface();
4678 const auto instance = context.getInstance();
4679 const auto physicalDevice = context.getPhysicalDevice();
4680 const auto queuePriority = 1.0f;
4681
4682 // Queue index first.
4683 m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4684
4685 // Create a universal queue that supports graphics and compute.
4686 const vk::VkDeviceQueueCreateInfo queueParams = {
4687 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
4688 DE_NULL, // const void* pNext;
4689 0u, // VkDeviceQueueCreateFlags flags;
4690 m_queueFamilyIndex, // uint32_t queueFamilyIndex;
4691 1u, // uint32_t queueCount;
4692 &queuePriority // const float* pQueuePriorities;
4693 };
4694
4695 #ifndef CTS_USES_VULKANSC
4696 const auto &contextMeshFeatures = context.getMeshShaderFeaturesEXT();
4697 const auto &contextGPLFeatures = context.getGraphicsPipelineLibraryFeaturesEXT();
4698 const auto &contextDBCFeatures = context.getDepthBiasControlFeaturesEXT();
4699 const auto &contextSOFeatures = context.getShaderObjectFeaturesEXT();
4700 const auto &contextBlendFeatures = context.getBlendOperationAdvancedFeaturesEXT();
4701
4702 const bool meshShaderSupport = contextMeshFeatures.meshShader;
4703 const bool gplSupport = contextGPLFeatures.graphicsPipelineLibrary;
4704 const bool dbcSupport = contextDBCFeatures.depthBiasControl;
4705 const bool shaderObjectSupport = contextSOFeatures.shaderObject;
4706 const bool eds3Support = context.isDeviceFunctionalitySupported("VK_EXT_extended_dynamic_state3");
4707 const bool blendFeaturesSupport = contextBlendFeatures.advancedBlendCoherentOperations;
4708
4709 // Mandatory.
4710 vk::VkPhysicalDeviceFeatures2 features2 = vk::initVulkanStructure();
4711
4712 // Optional.
4713 vk::VkPhysicalDeviceExtendedDynamicState3FeaturesEXT eds3Features = vk::initVulkanStructure();
4714 vk::VkPhysicalDeviceShadingRateImageFeaturesNV shadingRateImageFeatures = vk::initVulkanStructure();
4715 vk::VkPhysicalDeviceDepthBiasControlFeaturesEXT dbcFeatures = vk::initVulkanStructure();
4716 vk::VkPhysicalDeviceMeshShaderFeaturesEXT meshFeatures = vk::initVulkanStructure();
4717 vk::VkPhysicalDeviceMultiviewFeatures multiviewFeatures = vk::initVulkanStructure();
4718 vk::VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT gplFeatures = vk::initVulkanStructure();
4719 vk::VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeatures = vk::initVulkanStructure();
4720 vk::VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures = vk::initVulkanStructure();
4721 vk::VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT blendOperationAdvFeatures = vk::initVulkanStructure();
4722 vk::VkPhysicalDeviceFragmentShadingRateFeaturesKHR fragmentShadingRateFeatures = vk::initVulkanStructure();
4723
4724 const auto addFeatures = vk::makeStructChainAdder(&features2);
4725
4726 if (eds3Support)
4727 addFeatures(&eds3Features);
4728
4729 if (options.shadingRateImage)
4730 addFeatures(&shadingRateImageFeatures);
4731
4732 if (meshShaderSupport)
4733 {
4734 addFeatures(&meshFeatures);
4735
4736 if (contextMeshFeatures.multiviewMeshShader)
4737 addFeatures(&multiviewFeatures);
4738 }
4739
4740 if (gplSupport)
4741 addFeatures(&gplFeatures);
4742
4743 if (dbcSupport)
4744 addFeatures(&dbcFeatures);
4745
4746 if (shaderObjectSupport)
4747 {
4748 addFeatures(&shaderObjectFeatures);
4749 addFeatures(&dynamicRenderingFeatures);
4750 }
4751
4752 if (options.disableAdvBlendingCoherentOps && blendFeaturesSupport)
4753 addFeatures(&blendOperationAdvFeatures);
4754
4755 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
4756
4757 if (options.shadingRateImage)
4758 {
4759 // [VUID-VkDeviceCreateInfo-shadingRateImage-04479]
4760 // If the shadingRateImage feature is enabled primitiveFragmentShadingRate must not be enabled
4761 //
4762 // [VUID-VkPhysicalDeviceMeshShaderFeaturesEXT-primitiveFragmentShadingRateMeshShader-07033]
4763 // If primitiveFragmentShadingRateMeshShader is enabled then
4764 // VkPhysicalDeviceFragmentShadingRateFeaturesKHR::primitiveFragmentShadingRate must also be enabled
4765 meshFeatures.primitiveFragmentShadingRateMeshShader = VK_FALSE;
4766 }
4767 else if (meshFeatures.primitiveFragmentShadingRateMeshShader)
4768 {
4769 addFeatures(&fragmentShadingRateFeatures);
4770 fragmentShadingRateFeatures.primitiveFragmentShadingRate = VK_TRUE;
4771 }
4772
4773 // Disable alpha-to-one if requested by options.
4774 if (options.disableAlphaToOne)
4775 features2.features.alphaToOne = VK_FALSE;
4776
4777 // Disable robust buffer access and advanced color blend operations explicitly.
4778 features2.features.robustBufferAccess = VK_FALSE;
4779 blendOperationAdvFeatures.advancedBlendCoherentOperations = VK_FALSE;
4780
4781 #endif // CTS_USES_VULKANSC
4782
4783 std::vector<const char *> extensions;
4784
4785 #ifndef CTS_USES_VULKANSC
4786 if (options.shadingRateImage)
4787 extensions.push_back("VK_NV_shading_rate_image");
4788
4789 if (eds3Support)
4790 extensions.push_back("VK_EXT_extended_dynamic_state3");
4791
4792 if (meshShaderSupport)
4793 {
4794 extensions.push_back("VK_EXT_mesh_shader");
4795 if (contextMeshFeatures.multiviewMeshShader)
4796 extensions.push_back("VK_KHR_multiview");
4797 }
4798
4799 if (gplSupport)
4800 {
4801 extensions.push_back("VK_KHR_pipeline_library");
4802 extensions.push_back("VK_EXT_graphics_pipeline_library");
4803 }
4804
4805 if (dbcSupport)
4806 extensions.push_back("VK_EXT_depth_bias_control");
4807
4808 if (shaderObjectSupport)
4809 {
4810 extensions.push_back("VK_KHR_dynamic_rendering");
4811 extensions.push_back("VK_EXT_shader_object");
4812 }
4813 #endif // CTS_USES_VULKANSC
4814
4815 for (const auto &ext : extensions)
4816 m_extensions.push_back(ext);
4817
4818 const vk::VkDeviceCreateInfo deviceCreateInfo = {
4819 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
4820 #ifndef CTS_USES_VULKANSC
4821 &features2, //pNext;
4822 #else
4823 nullptr,
4824 #endif // CTS_USES_VULKANSC
4825 0u, //flags
4826 1u, //queueRecordCount;
4827 &queueParams, //pRequestedQueues;
4828 0u, //layerCount;
4829 nullptr, //ppEnabledLayerNames;
4830 de::sizeU32(extensions), // uint32_t enabledExtensionCount;
4831 de::dataOrNull(extensions), // const char* const* ppEnabledExtensionNames;
4832 nullptr, //pEnabledFeatures;
4833 };
4834
4835 m_device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance,
4836 vki, physicalDevice, &deviceCreateInfo);
4837 m_vkd.reset(new vk::DeviceDriver(vkp, instance, m_device.get(), context.getUsedApiVersion(),
4838 context.getTestContext().getCommandLine()));
4839 m_queue = getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
4840 m_allocator.reset(
4841 new vk::SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
4842
4843 #ifdef CTS_USES_VULKANSC
4844 DE_UNREF(options);
4845 #endif // CTS_USES_VULKANSC
4846 }
4847
~CustomizedDeviceHelper()4848 virtual ~CustomizedDeviceHelper()
4849 {
4850 }
4851
getDeviceInterface(void) const4852 const vk::DeviceInterface &getDeviceInterface(void) const override
4853 {
4854 return *m_vkd;
4855 }
getDevice(void) const4856 vk::VkDevice getDevice(void) const override
4857 {
4858 return m_device.get();
4859 }
getQueueFamilyIndex(void) const4860 uint32_t getQueueFamilyIndex(void) const override
4861 {
4862 return m_queueFamilyIndex;
4863 }
getQueue(void) const4864 vk::VkQueue getQueue(void) const override
4865 {
4866 return m_queue;
4867 }
getAllocator(void) const4868 vk::Allocator &getAllocator(void) const override
4869 {
4870 return *m_allocator;
4871 }
getDeviceExtensions(void) const4872 const std::vector<std::string> &getDeviceExtensions(void) const override
4873 {
4874 return m_extensions;
4875 }
4876
4877 protected:
4878 vk::Move<vk::VkDevice> m_device;
4879 std::unique_ptr<vk::DeviceDriver> m_vkd;
4880 uint32_t m_queueFamilyIndex;
4881 vk::VkQueue m_queue;
4882 std::unique_ptr<vk::SimpleAllocator> m_allocator;
4883 std::vector<std::string> m_extensions;
4884 };
4885
4886 using DeviceHelperPtr = std::unique_ptr<DeviceHelper>;
4887 std::map<CustomizedDeviceHelper::Options, DeviceHelperPtr> g_deviceHelpers;
4888
getDeviceHelper(Context & context,const TestConfig & testConfig)4889 DeviceHelper &getDeviceHelper(Context &context, const TestConfig &testConfig)
4890 {
4891 const CustomizedDeviceHelper::Options deviceOptions{
4892 testConfig.shadingRateImage,
4893 testConfig.disableAlphaToOneFeature,
4894 testConfig.disableAdvBlendingCoherentOps,
4895 };
4896
4897 auto itr = g_deviceHelpers.find(deviceOptions);
4898 if (itr == g_deviceHelpers.end())
4899 {
4900 using MapValueType = decltype(g_deviceHelpers)::value_type;
4901
4902 // Using the default options results in a non-custom device from the context. Otherwise a custom device is created.
4903 const bool defaultOptions = (!deviceOptions.shadingRateImage && !deviceOptions.disableAlphaToOne &&
4904 !deviceOptions.disableAdvBlendingCoherentOps);
4905 DeviceHelperPtr ptr = DeviceHelperPtr(
4906 defaultOptions ? static_cast<DeviceHelper *>(new ContextDeviceHelper(context)) :
4907 static_cast<DeviceHelper *>(new CustomizedDeviceHelper(context, deviceOptions)));
4908 MapValueType mapValue(std::move(deviceOptions), std::move(ptr));
4909
4910 itr = g_deviceHelpers.insert(std::move(mapValue)).first;
4911 }
4912 return *itr->second;
4913 }
4914
cleanupDevices()4915 void cleanupDevices()
4916 {
4917 for (auto &keyValue : g_deviceHelpers)
4918 keyValue.second.reset(nullptr);
4919 g_deviceHelpers.clear();
4920 }
4921
getChannelClass(const tcu::TextureFormat & format)4922 tcu::TextureChannelClass getChannelClass(const tcu::TextureFormat &format)
4923 {
4924 const auto generalClass = getTextureChannelClass(format.type);
4925 // Workaround for VK_FORMAT_X8_D24_UNORM_PACK32.
4926 return ((generalClass == tcu::TEXTURECHANNELCLASS_LAST) ? tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT :
4927 generalClass);
4928 }
4929
iterate(void)4930 tcu::TestStatus ExtendedDynamicStateInstance::iterate(void)
4931 {
4932 using ImageWithMemoryVec = std::vector<std::unique_ptr<vk::ImageWithMemory>>;
4933 using ImageViewVec = std::vector<vk::Move<vk::VkImageView>>;
4934 using RenderPassVec = std::vector<vk::RenderPassWrapper>;
4935
4936 const auto &vki = m_context.getInstanceInterface();
4937 const auto physicalDevice = m_context.getPhysicalDevice();
4938 const auto &deviceHelper = getDeviceHelper(m_context, m_testConfig);
4939 const auto &vkd = deviceHelper.getDeviceInterface();
4940 const auto device = deviceHelper.getDevice();
4941 auto &allocator = deviceHelper.getAllocator();
4942 const auto queue = deviceHelper.getQueue();
4943 const auto queueIndex = deviceHelper.getQueueFamilyIndex();
4944 auto &log = m_context.getTestContext().getLog();
4945
4946 const auto kReversed = m_testConfig.isReversed();
4947 const auto kBindStaticFirst = m_testConfig.bindStaticFirst();
4948 const auto kUseStaticPipeline = m_testConfig.useStaticPipeline();
4949 const auto kNumIterations = m_testConfig.numIterations();
4950 const auto kColorAttCount = m_testConfig.colorAttachmentCount;
4951 const auto kSequenceOrdering = m_testConfig.sequenceOrdering;
4952
4953 const auto kDSCreateFlags =
4954 (m_testConfig.sampleLocationsStruct() ?
4955 static_cast<vk::VkImageCreateFlags>(vk::VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) :
4956 0u);
4957 const auto colorFormat = m_testConfig.colorFormat();
4958 const auto colorSampleCount = m_testConfig.getColorSampleCount();
4959 const auto activeSampleCount = m_testConfig.getActiveSampleCount();
4960 const bool vertDataAsSSBO = m_testConfig.useMeshShaders;
4961 const auto pipelineBindPoint = vk::VK_PIPELINE_BIND_POINT_GRAPHICS;
4962 const bool kUseResolveAtt = (colorSampleCount != kSingleSampleCount);
4963 const bool kMultisampleDS = (activeSampleCount != kSingleSampleCount);
4964 const bool kFragAtomics = m_testConfig.useFragShaderAtomics();
4965
4966 // Choose depth/stencil format.
4967 const DepthStencilFormat *dsFormatInfo = nullptr;
4968
4969 for (const auto &kDepthStencilFormat : kDepthStencilFormats)
4970 {
4971 // This is how we'll attempt to create images later.
4972 const auto dsImageInfo = makeImageCreateInfo(kDepthStencilFormat.imageFormat, kFramebufferExtent,
4973 activeSampleCount, kDSUsage, kDSCreateFlags);
4974
4975 vk::VkImageFormatProperties formatProps;
4976 const auto result = vki.getPhysicalDeviceImageFormatProperties(
4977 physicalDevice, dsImageInfo.format, dsImageInfo.imageType, dsImageInfo.tiling, dsImageInfo.usage,
4978 dsImageInfo.flags, &formatProps);
4979
4980 // Format not supported.
4981 if (result != vk::VK_SUCCESS)
4982 continue;
4983
4984 // Extent not big enough.
4985 const auto &maxExtent = formatProps.maxExtent;
4986 if (maxExtent.width < kFramebufferExtent.width || maxExtent.height < kFramebufferExtent.height ||
4987 maxExtent.depth < kFramebufferExtent.depth)
4988 continue;
4989
4990 // Sample count not supported.
4991 if ((formatProps.sampleCounts & activeSampleCount) != activeSampleCount)
4992 continue;
4993
4994 if (m_testConfig.neededDepthChannelClass != tcu::TEXTURECHANNELCLASS_LAST)
4995 {
4996 const auto tcuDSFormat = vk::getDepthCopyFormat(kDepthStencilFormat.imageFormat);
4997 const auto channelClass = getChannelClass(tcuDSFormat);
4998
4999 if (channelClass != m_testConfig.neededDepthChannelClass)
5000 continue;
5001 }
5002
5003 dsFormatInfo = &kDepthStencilFormat;
5004 break;
5005 }
5006
5007 // Note: Not Supported insted of Fail because some features are not mandatory.
5008 if (!dsFormatInfo)
5009 TCU_THROW(NotSupportedError, "Required depth/stencil image features not supported");
5010 log << tcu::TestLog::Message << "Chosen depth/stencil format: " << dsFormatInfo->imageFormat
5011 << tcu::TestLog::EndMessage;
5012 log << tcu::TestLog::Message << "Chosen color format: " << colorFormat << tcu::TestLog::EndMessage;
5013
5014 // Swap static and dynamic values in the test configuration so the static pipeline ends up with the expected values for cases
5015 // where we will bind the static pipeline last before drawing.
5016 if (kReversed)
5017 m_testConfig.swapValues();
5018
5019 // Create color and depth/stencil images.
5020 ImageWithMemoryVec colorImages;
5021 ImageWithMemoryVec dsImages;
5022 ImageWithMemoryVec resolveImages;
5023
5024 const auto colorImageInfo = makeImageCreateInfo(colorFormat, kFramebufferExtent, colorSampleCount, kColorUsage, 0u);
5025 for (uint32_t i = 0u; i < kNumIterations * kColorAttCount; ++i)
5026 colorImages.emplace_back(
5027 new vk::ImageWithMemory(vkd, device, allocator, colorImageInfo, vk::MemoryRequirement::Any));
5028
5029 const auto dsImageInfo =
5030 makeImageCreateInfo(dsFormatInfo->imageFormat, kFramebufferExtent, activeSampleCount, kDSUsage, kDSCreateFlags);
5031 for (uint32_t i = 0u; i < kNumIterations; ++i)
5032 dsImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, dsImageInfo, vk::MemoryRequirement::Any));
5033
5034 if (kUseResolveAtt)
5035 {
5036 const auto resolveImageInfo =
5037 makeImageCreateInfo(colorFormat, kFramebufferExtent, kSingleSampleCount, kColorUsage, 0u);
5038 for (uint32_t i = 0u; i < kNumIterations * kColorAttCount; ++i)
5039 resolveImages.emplace_back(
5040 new vk::ImageWithMemory(vkd, device, allocator, resolveImageInfo, vk::MemoryRequirement::Any));
5041 }
5042
5043 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
5044 const auto dsSubresourceRange = vk::makeImageSubresourceRange(
5045 (vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
5046
5047 ImageViewVec colorImageViews;
5048 ImageViewVec dsImageViews;
5049 ImageViewVec resolveImageViews;
5050
5051 for (const auto &img : colorImages)
5052 colorImageViews.emplace_back(
5053 vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
5054
5055 for (const auto &img : dsImages)
5056 dsImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D,
5057 dsFormatInfo->imageFormat, dsSubresourceRange));
5058
5059 for (const auto &img : resolveImages)
5060 resolveImageViews.emplace_back(
5061 vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
5062
5063 // Vertex buffer.
5064 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
5065 std::vector<uint32_t> indices;
5066 std::vector<tcu::Vec2> vertices;
5067
5068 if (m_testConfig.oversizedTriangle || m_testConfig.offCenterTriangle)
5069 {
5070 DE_ASSERT(topologyClass == TopologyClass::TRIANGLE);
5071 DE_ASSERT(!m_testConfig.singleVertex);
5072 }
5073
5074 if (m_testConfig.obliqueLine)
5075 DE_ASSERT(topologyClass == TopologyClass::LINE);
5076
5077 if (topologyClass == TopologyClass::TRIANGLE)
5078 {
5079 DE_ASSERT(!m_testConfig.needsIndexBuffer());
5080
5081 if (m_testConfig.oversizedTriangle)
5082 {
5083 vertices.reserve(3u);
5084 vertices.push_back(tcu::Vec2(-2.0f, -2.0f));
5085 vertices.push_back(tcu::Vec2(-2.0f, 6.0f));
5086 vertices.push_back(tcu::Vec2(6.0f, -2.0f));
5087 }
5088 else if (m_testConfig.offCenterTriangle)
5089 {
5090 // Triangle covering the whole screen, except for the first row and column, which may not be covered by all samples.
5091 const float horOffset = 2.0f / static_cast<float>(kFramebufferWidth) * m_testConfig.offCenterProportion.x();
5092 const float vertOffset =
5093 2.0f / static_cast<float>(kFramebufferHeight) * m_testConfig.offCenterProportion.y();
5094
5095 vertices.reserve(3u);
5096 vertices.push_back(tcu::Vec2(-1.0f + horOffset, -1.0f + vertOffset));
5097 vertices.push_back(tcu::Vec2(-1.0f + horOffset, 4.0f));
5098 vertices.push_back(tcu::Vec2(4.0f, -1.0f + vertOffset));
5099 }
5100 else
5101 {
5102 // Full-screen triangle strip with 6 vertices.
5103 //
5104 // 0 2 4
5105 // +-------+-------+
5106 // | XX X|
5107 // | X X X |
5108 // | X X X |
5109 // | X X X |
5110 // | X X X |
5111 // | X X X |
5112 // |X XX |
5113 // +-------+-------+
5114 // 1 3 5
5115 vertices.reserve(6u);
5116 vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
5117 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
5118 vertices.push_back(tcu::Vec2(0.0f, -1.0f));
5119 vertices.push_back(tcu::Vec2(0.0f, 1.0f));
5120 vertices.push_back(tcu::Vec2(1.0f, -1.0f));
5121 vertices.push_back(tcu::Vec2(1.0f, 1.0f));
5122 }
5123 }
5124 else if (topologyClass == TopologyClass::PATCH)
5125 {
5126 DE_ASSERT(!m_testConfig.needsIndexBuffer());
5127 DE_ASSERT(m_testConfig.getActivePatchControlPoints() > 1u);
5128
5129 // 2 triangles making a quad
5130 vertices.reserve(6u);
5131 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
5132 vertices.push_back(tcu::Vec2(1.0f, 1.0f));
5133 vertices.push_back(tcu::Vec2(1.0f, -1.0f));
5134 vertices.push_back(tcu::Vec2(1.0f, -1.0f));
5135 vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
5136 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
5137 }
5138 else // TopologyClass::LINE
5139 {
5140 const float pixelHeight = 2.0f / static_cast<float>(kFramebufferHeight);
5141 const float pixelWidth = 2.0f / static_cast<float>(kFramebufferWidth);
5142
5143 if (m_testConfig.obliqueLine)
5144 {
5145 // The starting point of the oblique line is located in the top left pixel, in a position below and slightly to the left
5146 // of the pixel center. The ending point is in the middle of the right side of the framebuffer. Those coordinates make
5147 // sure that a bresenham-style line covers the center of the top left pixel, because the left edge of the line goes up
5148 // vertically from that point. However, a rectangular line misses it by a small delta because its edge goes up and to
5149 // the right, leaving the pixel center to its left. So the top left pixel itself may be covered or not depending on the
5150 // active line rasterization mode.
5151 //
5152 // Note: results may also be affected by multisample and sample locations if those are used.
5153 vertices.reserve(2u);
5154 vertices.push_back(tcu::Vec2(pixelWidth * 7.0f / 16.0f - 1.0f, pixelHeight * 12.0f / 16.0f - 1.0f));
5155 vertices.push_back(tcu::Vec2(1.0f, 0.0f));
5156 }
5157 else
5158 {
5159 DE_ASSERT(m_testConfig.getActivePrimRestartEnable());
5160
5161 // 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.
5162 vertices.reserve(kFramebufferHeight * 4u);
5163
5164 const auto indicesPerRow = (m_testConfig.extraLineRestarts ? 6u : 5u);
5165 if (m_testConfig.needsIndexBuffer())
5166 indices.reserve(kFramebufferHeight * indicesPerRow);
5167
5168 for (uint32_t rowIdx = 0; rowIdx < kFramebufferHeight; ++rowIdx)
5169 {
5170 // Offset of 0.5 pixels + one pixel per row, from -1 to 1.
5171 const float yCoord = (pixelHeight / 2.0f) + pixelHeight * static_cast<float>(rowIdx) - 1.0f;
5172 vertices.push_back(tcu::Vec2(-1.0f, yCoord));
5173 vertices.push_back(tcu::Vec2(-0.5f, yCoord));
5174 vertices.push_back(tcu::Vec2(0.5f, yCoord));
5175 vertices.push_back(tcu::Vec2(1.0f, yCoord));
5176
5177 if (m_testConfig.needsIndexBuffer())
5178 {
5179 indices.push_back(4u * rowIdx + 0u);
5180 indices.push_back(4u * rowIdx + 1u);
5181
5182 // When using extra line restarts, insert a primitive restart index in the middle, which will result in the
5183 // center strip being skipped, as if the topology was a line list instead of a strip.
5184 if (m_testConfig.extraLineRestarts)
5185 indices.push_back(0xFFFFFFFFu);
5186
5187 indices.push_back(4u * rowIdx + 2u);
5188 indices.push_back(4u * rowIdx + 3u);
5189 indices.push_back(0xFFFFFFFFu); // Restart line strip.
5190 }
5191 }
5192 }
5193 }
5194
5195 if (m_testConfig.singleVertex)
5196 {
5197 DE_ASSERT(!m_testConfig.needsIndexBuffer());
5198 vertices.resize(1);
5199 }
5200
5201 // Reversed vertices order in triangle strip (1, 0, 3, 2, 5, 4)
5202 std::vector<tcu::Vec2> rvertices;
5203 if (topologyClass == TopologyClass::TRIANGLE)
5204 {
5205 DE_ASSERT(!vertices.empty());
5206 if (m_testConfig.singleVertex)
5207 rvertices.push_back(vertices[0]);
5208 else if (m_testConfig.oversizedTriangle || m_testConfig.offCenterTriangle)
5209 {
5210 rvertices.reserve(3u);
5211 rvertices.push_back(vertices[0]);
5212 rvertices.push_back(vertices[2]);
5213 rvertices.push_back(vertices[1]);
5214 }
5215 else
5216 {
5217 rvertices.reserve(6u);
5218 rvertices.push_back(vertices[1]);
5219 rvertices.push_back(vertices[0]);
5220 rvertices.push_back(vertices[3]);
5221 rvertices.push_back(vertices[2]);
5222 rvertices.push_back(vertices[5]);
5223 rvertices.push_back(vertices[4]);
5224 }
5225 }
5226
5227 if (topologyClass != TopologyClass::TRIANGLE)
5228 {
5229 for (const auto &mesh : m_testConfig.meshParams)
5230 {
5231 DE_UNREF(mesh); // For release builds.
5232 DE_ASSERT(!mesh.reversed);
5233 }
5234 }
5235
5236 // Buffers with vertex data for the different bindings.
5237 std::vector<VertexBufferInfo> vertBuffers;
5238 std::vector<VertexBufferInfo> rvertBuffers;
5239
5240 {
5241 const auto dataOffset = static_cast<uint32_t>(m_testConfig.vertexDataOffset);
5242 const auto trailingSize = static_cast<uint32_t>(m_testConfig.vertexDataExtraBytes);
5243 const auto generator = m_testConfig.getActiveVertexGenerator();
5244 prepareVertexBuffers(vertBuffers, vkd, device, allocator, generator, vertices, dataOffset, trailingSize,
5245 vertDataAsSSBO);
5246 if (topologyClass == TopologyClass::TRIANGLE)
5247 prepareVertexBuffers(rvertBuffers, vkd, device, allocator, generator, rvertices, dataOffset, trailingSize,
5248 vertDataAsSSBO);
5249 }
5250
5251 // Index buffer.
5252 BufferWithMemoryPtr indexBuffer;
5253 if (!indices.empty())
5254 {
5255 const auto indexDataSize = static_cast<vk::VkDeviceSize>(de::dataSize(indices));
5256 const auto indexBufferInfo = vk::makeBufferCreateInfo(indexDataSize, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
5257
5258 indexBuffer = BufferWithMemoryPtr(
5259 new vk::BufferWithMemory(vkd, device, allocator, indexBufferInfo, vk::MemoryRequirement::HostVisible));
5260 copyAndFlush(vkd, device, *indexBuffer, 0, indices.data(), static_cast<size_t>(indexDataSize));
5261 }
5262
5263 // Fragment counter buffer.
5264 BufferWithMemoryPtr counterBuffer;
5265 const auto counterBufferSize = static_cast<vk::VkDeviceSize>(sizeof(uint32_t));
5266
5267 if (kFragAtomics)
5268 {
5269 const auto counterBufferInfo =
5270 vk::makeBufferCreateInfo(counterBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
5271 const uint32_t initialValue = 0u;
5272
5273 counterBuffer = BufferWithMemoryPtr(
5274 new vk::BufferWithMemory(vkd, device, allocator, counterBufferInfo, vk::MemoryRequirement::HostVisible));
5275 copyAndFlush(vkd, device, *counterBuffer, 0u, &initialValue, static_cast<size_t>(counterBufferSize));
5276 }
5277
5278 // Frag shader descriptor set layout.
5279 vk::Move<vk::VkDescriptorSetLayout> fragSetLayout;
5280 {
5281 vk::DescriptorSetLayoutBuilder layoutBuilder;
5282 if (kFragAtomics)
5283 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
5284 fragSetLayout = layoutBuilder.build(vkd, device);
5285 }
5286
5287 // Descriptor pool and set.
5288 vk::Move<vk::VkDescriptorPool> fragDescriptorPool;
5289 vk::Move<vk::VkDescriptorSet> fragDescriptorSet;
5290
5291 if (kFragAtomics)
5292 {
5293 vk::DescriptorPoolBuilder poolBuilder;
5294 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
5295 fragDescriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
5296 fragDescriptorSet = vk::makeDescriptorSet(vkd, device, fragDescriptorPool.get(), fragSetLayout.get());
5297
5298 vk::DescriptorSetUpdateBuilder updateBuilder;
5299 const auto location = vk::DescriptorSetUpdateBuilder::Location::binding(0u);
5300 const auto descInfo = vk::makeDescriptorBufferInfo(counterBuffer->get(), 0ull, counterBufferSize);
5301 updateBuilder.writeSingle(fragDescriptorSet.get(), location, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descInfo);
5302 updateBuilder.update(vkd, device);
5303 }
5304
5305 // Push constant stages (matches SSBO stages if used).
5306 vk::VkShaderStageFlags pushConstantStageFlags = ((m_testConfig.useMeshShaders
5307 #ifndef CTS_USES_VULKANSC
5308 ?
5309 vk::VK_SHADER_STAGE_MESH_BIT_EXT
5310 #else
5311 ?
5312 0
5313 #endif // CTS_USES_VULKANSC
5314 :
5315 vk::VK_SHADER_STAGE_VERTEX_BIT) |
5316 vk::VK_SHADER_STAGE_FRAGMENT_BIT);
5317
5318 if (m_testConfig.needsGeometryShader())
5319 pushConstantStageFlags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
5320
5321 // Mesh descriptor set layout.
5322 vk::Move<vk::VkDescriptorSetLayout> meshSetLayout;
5323 if (vertDataAsSSBO)
5324 {
5325 vk::DescriptorSetLayoutBuilder layoutBuilder;
5326 for (size_t i = 0; i < vertBuffers.size(); ++i)
5327 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, pushConstantStageFlags);
5328 meshSetLayout = layoutBuilder.build(vkd, device);
5329 }
5330
5331 // Descriptor pool and set if needed.
5332 vk::Move<vk::VkDescriptorPool> meshDescriptorPool;
5333 vk::Move<vk::VkDescriptorSet> meshDescriptorSet;
5334 vk::Move<vk::VkDescriptorSet> meshDescriptorSetRev;
5335
5336 if (vertDataAsSSBO)
5337 {
5338 const auto hasReversed = (rvertBuffers.size() > 0u);
5339 const auto descType = vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
5340 vk::DescriptorPoolBuilder poolBuilder;
5341 poolBuilder.addType(descType, static_cast<uint32_t>(vertBuffers.size()) * 2u);
5342
5343 meshDescriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
5344 meshDescriptorSet = vk::makeDescriptorSet(vkd, device, meshDescriptorPool.get(), meshSetLayout.get());
5345
5346 if (hasReversed)
5347 meshDescriptorSetRev = vk::makeDescriptorSet(vkd, device, meshDescriptorPool.get(), meshSetLayout.get());
5348
5349 std::vector<vk::VkDescriptorBufferInfo> descBufferInfos;
5350 std::vector<vk::VkDescriptorBufferInfo> descBufferInfosRev;
5351 descBufferInfos.reserve(vertBuffers.size());
5352 if (hasReversed)
5353 descBufferInfosRev.reserve(rvertBuffers.size());
5354
5355 vk::DescriptorSetUpdateBuilder updateBuilder;
5356
5357 DE_ASSERT(vertBuffers.size() == rvertBuffers.size() || !hasReversed);
5358 for (size_t i = 0; i < vertBuffers.size(); ++i)
5359 {
5360 const auto binding = vk::DescriptorSetUpdateBuilder::Location::binding(static_cast<uint32_t>(i));
5361
5362 descBufferInfos.push_back(vk::makeDescriptorBufferInfo(vertBuffers[i].buffer->get(), vertBuffers[i].offset,
5363 vertBuffers[i].dataSize));
5364 updateBuilder.writeSingle(meshDescriptorSet.get(), binding, descType, &descBufferInfos.back());
5365
5366 if (hasReversed)
5367 {
5368 descBufferInfosRev.push_back(vk::makeDescriptorBufferInfo(
5369 rvertBuffers[i].buffer->get(), rvertBuffers[i].offset, rvertBuffers[i].dataSize));
5370 updateBuilder.writeSingle(meshDescriptorSetRev.get(), binding, descType, &descBufferInfosRev.back());
5371 }
5372 }
5373
5374 updateBuilder.update(vkd, device);
5375 }
5376
5377 // The frag shader descriptor set is the second one if both exist. See getFragDescriptorSetIndex().
5378 std::vector<vk::VkDescriptorSetLayout> rawSetLayouts;
5379
5380 if (meshSetLayout.get() != VK_NULL_HANDLE)
5381 rawSetLayouts.push_back(meshSetLayout.get());
5382
5383 if (fragSetLayout.get() != VK_NULL_HANDLE)
5384 rawSetLayouts.push_back(fragSetLayout.get());
5385
5386 // Pipeline layout.
5387 const vk::VkPushConstantRange pushConstantRange = {
5388 pushConstantStageFlags, // VkShaderStageFlags stageFlags;
5389 0u, // uint32_t offset;
5390 static_cast<uint32_t>(sizeof(PushConstants)), // uint32_t size;
5391 };
5392
5393 const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
5394 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
5395 nullptr, // const void* pNext;
5396 0u, // VkPipelineLayoutCreateFlags flags;
5397 de::sizeU32(rawSetLayouts), // uint32_t setLayoutCount;
5398 de::dataOrNull(rawSetLayouts), // const VkDescriptorSetLayout* pSetLayouts;
5399 1u, // uint32_t pushConstantRangeCount;
5400 &pushConstantRange, // const VkPushConstantRange* pPushConstantRanges;
5401 };
5402 const vk::PipelineLayoutWrapper pipelineLayout(m_testConfig.pipelineConstructionType, vkd, device,
5403 &pipelineLayoutCreateInfo);
5404
5405 // Render pass with single subpass. Attachment order:
5406 // 1) Color attachments (kColorAttCount items).
5407 // 2) DS attachment.
5408 // 3) [optional] Resolve attachments (kColorAttCount).
5409
5410 DE_ASSERT(kColorAttCount > 0u);
5411
5412 std::vector<vk::VkAttachmentReference> colorAttachments;
5413 std::vector<vk::VkAttachmentReference> resolveAttachments;
5414
5415 for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5416 {
5417 colorAttachments.push_back(
5418 vk::makeAttachmentReference(colorAttIdx, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
5419 if (kUseResolveAtt)
5420 resolveAttachments.push_back(vk::makeAttachmentReference(kColorAttCount + 1u + colorAttIdx,
5421 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
5422 }
5423
5424 const vk::VkAttachmentReference dsAttachmentReference = {
5425 kColorAttCount, // uint32_t attachment;
5426 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
5427 };
5428
5429 const vk::VkSubpassDescription subpassDescription = {
5430 0u, // VkSubpassDescriptionFlags flags;
5431 pipelineBindPoint, // VkPipelineBindPoint pipelineBindPoint;
5432 0u, // uint32_t inputAttachmentCount;
5433 nullptr, // const VkAttachmentReference* pInputAttachments;
5434 kColorAttCount, // uint32_t colorAttachmentCount;
5435 de::dataOrNull(colorAttachments), // const VkAttachmentReference* pColorAttachments;
5436 de::dataOrNull(resolveAttachments), // const VkAttachmentReference* pResolveAttachments;
5437 &dsAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
5438 0u, // uint32_t preserveAttachmentCount;
5439 nullptr, // const uint32_t* pPreserveAttachments;
5440 };
5441
5442 std::vector<vk::VkAttachmentDescription> attachmentDescriptions;
5443
5444 // For multisample, we care about the resolve attachment, not the color one.
5445 const auto colorAttachmentStoreOp =
5446 (kUseResolveAtt ? vk::VK_ATTACHMENT_STORE_OP_DONT_CARE : vk::VK_ATTACHMENT_STORE_OP_STORE);
5447
5448 for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5449 {
5450 attachmentDescriptions.push_back(vk::VkAttachmentDescription{
5451 0u, // VkAttachmentDescriptionFlags flags;
5452 colorFormat, // VkFormat format;
5453 colorSampleCount, // VkSampleCountFlagBits samples;
5454 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
5455 colorAttachmentStoreOp, // VkAttachmentStoreOp storeOp;
5456 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
5457 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
5458 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
5459 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5460 });
5461 }
5462
5463 attachmentDescriptions.push_back(vk::VkAttachmentDescription{
5464 0u, // VkAttachmentDescriptionFlags flags;
5465 dsFormatInfo->imageFormat, // VkFormat format;
5466 activeSampleCount, // VkSampleCountFlagBits samples;
5467 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
5468 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
5469 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
5470 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
5471 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
5472 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5473 });
5474
5475 if (kUseResolveAtt)
5476 {
5477 // Resolve attachments.
5478 for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5479 {
5480 attachmentDescriptions.push_back(vk::VkAttachmentDescription{
5481 0u, // VkAttachmentDescriptionFlags flags;
5482 colorFormat, // VkFormat format;
5483 kSingleSampleCount, // VkSampleCountFlagBits samples;
5484 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
5485 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
5486 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
5487 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
5488 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
5489 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
5490 });
5491 }
5492 }
5493
5494 // Render pass and framebuffers.
5495 RenderPassVec renderPassFramebuffers;
5496
5497 const vk::VkRenderPassCreateInfo renderPassCreateInfo = {
5498 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
5499 nullptr, // const void* pNext;
5500 0u, // VkRenderPassCreateFlags flags;
5501 static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
5502 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
5503 1u, // uint32_t subpassCount;
5504 &subpassDescription, // const VkSubpassDescription* pSubpasses;
5505 0u, // uint32_t dependencyCount;
5506 nullptr, // const VkSubpassDependency* pDependencies;
5507 };
5508
5509 DE_ASSERT(colorImageViews.size() == dsImageViews.size() * kColorAttCount);
5510
5511 if (kUseResolveAtt)
5512 DE_ASSERT(colorImageViews.size() == resolveImageViews.size());
5513
5514 for (size_t iterIdx = 0; iterIdx < dsImageViews.size(); ++iterIdx)
5515 {
5516 std::vector<vk::VkImage> images;
5517 std::vector<vk::VkImageView> attachments;
5518
5519 for (uint32_t colorAttIdx = 0u; colorAttIdx < kColorAttCount; ++colorAttIdx)
5520 {
5521 const auto colorViewIdx = iterIdx * kColorAttCount + colorAttIdx;
5522 images.push_back(colorImages[colorViewIdx].get()->get());
5523 attachments.push_back(colorImageViews[colorViewIdx].get());
5524 }
5525
5526 images.push_back(dsImages[iterIdx].get()->get());
5527 attachments.push_back(dsImageViews[iterIdx].get());
5528
5529 if (kUseResolveAtt)
5530 {
5531 for (uint32_t resolveAttIdx = 0u; resolveAttIdx < kColorAttCount; ++resolveAttIdx)
5532 {
5533 const auto resolveViewIdx = iterIdx * kColorAttCount + resolveAttIdx;
5534 images.push_back(resolveImages[resolveViewIdx].get()->get());
5535 attachments.push_back(resolveImageViews[resolveViewIdx].get());
5536 }
5537 }
5538
5539 renderPassFramebuffers.emplace_back(m_testConfig.pipelineConstructionType, vkd, device, &renderPassCreateInfo);
5540
5541 const vk::VkFramebufferCreateInfo framebufferCreateInfo = {
5542 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
5543 nullptr, // const void* pNext;
5544 0u, // VkFramebufferCreateFlags flags;
5545 renderPassFramebuffers[iterIdx].get(), // VkRenderPass renderPass;
5546 static_cast<uint32_t>(attachments.size()), // uint32_t attachmentCount;
5547 attachments.data(), // const VkImageView* pAttachments;
5548 kFramebufferWidth, // uint32_t width;
5549 kFramebufferHeight, // uint32_t height;
5550 1u, // uint32_t layers;
5551 };
5552
5553 renderPassFramebuffers[iterIdx].createFramebuffer(vkd, device, &framebufferCreateInfo, images);
5554 }
5555
5556 // Shader modules.
5557 const auto &binaries = m_context.getBinaryCollection();
5558 const auto dynamicVertModule = vk::ShaderWrapper(vkd, device, binaries.get("dynamicVert"));
5559 const auto staticVertModule = vk::ShaderWrapper(vkd, device, binaries.get("staticVert"));
5560 const auto dynamicFragModule =
5561 vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("dynamicFrag"), 0u);
5562 const auto staticFragModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("staticFrag"), 0u);
5563 const auto geomModule = (m_testConfig.needsGeometryShader() ? vk::ShaderWrapper(vkd, device, binaries.get("geom")) :
5564 vk::ShaderWrapper());
5565 const auto tescModule =
5566 (m_testConfig.needsTessellation() ? vk::ShaderWrapper(vkd, device, binaries.get("tesc")) : vk::ShaderWrapper());
5567 const auto teseModule =
5568 (m_testConfig.needsTessellation() ? vk::ShaderWrapper(vkd, device, binaries.get("tese")) : vk::ShaderWrapper());
5569 const auto dynamicMeshModule =
5570 (m_testConfig.useMeshShaders ? vk::ShaderWrapper(vkd, device, binaries.get("dynamicMesh")) :
5571 vk::ShaderWrapper());
5572 const auto staticMeshModule =
5573 (m_testConfig.useMeshShaders ? vk::ShaderWrapper(vkd, device, binaries.get("staticMesh")) :
5574 vk::ShaderWrapper());
5575 const auto meshNoOutModule =
5576 (m_testConfig.bindUnusedMeshShadingPipeline ? vk::ShaderWrapper(vkd, device, binaries.get("meshNoOut")) :
5577 vk::ShaderWrapper());
5578
5579 vk::ShaderWrapper vertDPCPModule;
5580 vk::ShaderWrapper fragDPCPModule;
5581
5582 // Input state.
5583 const auto vertexBindings =
5584 m_testConfig.vertexGenerator.staticValue->getBindingDescriptions(m_testConfig.strideConfig.staticValue);
5585 const auto vertexAttributes = m_testConfig.vertexGenerator.staticValue->getAttributeDescriptions();
5586
5587 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
5588 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
5589 nullptr, // const void* pNext;
5590 0u, // VkPipelineVertexInputStateCreateFlags flags;
5591 static_cast<uint32_t>(vertexBindings.size()), // uint32_t vertexBindingDescriptionCount;
5592 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
5593 static_cast<uint32_t>(vertexAttributes.size()), // uint32_t vertexAttributeDescriptionCount;
5594 vertexAttributes.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
5595 };
5596
5597 // Input assembly.
5598 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
5599 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
5600 nullptr, // const void* pNext;
5601 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
5602 m_testConfig.topologyConfig.staticValue, // VkPrimitiveTopology topology;
5603 makeVkBool32(m_testConfig.primRestartEnableConfig.staticValue), // VkBool32 primitiveRestartEnable;
5604 };
5605
5606 // Viewport state.
5607 if (m_testConfig.viewportConfig.dynamicValue)
5608 DE_ASSERT(m_testConfig.viewportConfig.dynamicValue.get().size() > 0u);
5609 else
5610 DE_ASSERT(m_testConfig.viewportConfig.staticValue.size() > 0u);
5611
5612 if (m_testConfig.scissorConfig.dynamicValue)
5613 DE_ASSERT(m_testConfig.scissorConfig.dynamicValue.get().size() > 0u);
5614 else
5615 DE_ASSERT(m_testConfig.scissorConfig.staticValue.size() > 0u);
5616
5617 // Rasterization state.
5618 void *multisamplePnext = nullptr;
5619 void *rasterizationPnext = nullptr;
5620 void *viewportPnext = nullptr;
5621
5622 const bool staticStreamInfo = static_cast<bool>(m_testConfig.rasterizationStreamConfig.staticValue);
5623 const bool staticProvokingVtxInfo = static_cast<bool>(m_testConfig.provokingVertexConfig.staticValue);
5624 const bool staticDepthClipEnableInfo = static_cast<bool>(m_testConfig.depthClipEnableConfig.staticValue);
5625 const bool staticDepthClipControlInfo = static_cast<bool>(m_testConfig.negativeOneToOneConfig.staticValue);
5626 #ifndef CTS_USES_VULKANSC
5627 using RastStreamInfoPtr = de::MovePtr<vk::VkPipelineRasterizationStateStreamCreateInfoEXT>;
5628 using ProvokingVtxModePtr = de::MovePtr<vk::VkPipelineRasterizationProvokingVertexStateCreateInfoEXT>;
5629 using DepthClipControlPtr = de::MovePtr<vk::VkPipelineViewportDepthClipControlCreateInfoEXT>;
5630 using DepthClipEnablePtr = de::MovePtr<vk::VkPipelineRasterizationDepthClipStateCreateInfoEXT>;
5631 using ConservativeRastPtr = de::MovePtr<vk::VkPipelineRasterizationConservativeStateCreateInfoEXT>;
5632 using DepthBiasReprInfoPtr = de::MovePtr<vk::VkDepthBiasRepresentationInfoEXT>;
5633
5634 RastStreamInfoPtr pRasterizationStreamInfo;
5635
5636 if (staticStreamInfo)
5637 {
5638 pRasterizationStreamInfo = RastStreamInfoPtr(
5639 new vk::VkPipelineRasterizationStateStreamCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5640 pRasterizationStreamInfo->rasterizationStream = m_testConfig.rasterizationStreamConfig.staticValue.get();
5641 rasterizationPnext = pRasterizationStreamInfo.get();
5642 }
5643
5644 ProvokingVtxModePtr pProvokingVertexModeInfo;
5645
5646 if (staticProvokingVtxInfo)
5647 {
5648 pProvokingVertexModeInfo = ProvokingVtxModePtr(new vk::VkPipelineRasterizationProvokingVertexStateCreateInfoEXT(
5649 vk::initVulkanStructure(rasterizationPnext)));
5650 pProvokingVertexModeInfo->provokingVertexMode =
5651 makeProvokingVertexMode(m_testConfig.provokingVertexConfig.staticValue.get());
5652 rasterizationPnext = pProvokingVertexModeInfo.get();
5653 }
5654
5655 DepthClipEnablePtr pDepthClipEnableInfo;
5656
5657 if (staticDepthClipEnableInfo)
5658 {
5659 pDepthClipEnableInfo = DepthClipEnablePtr(
5660 new vk::VkPipelineRasterizationDepthClipStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5661 pDepthClipEnableInfo->depthClipEnable = makeVkBool32(m_testConfig.depthClipEnableConfig.staticValue.get());
5662 rasterizationPnext = pDepthClipEnableInfo.get();
5663 }
5664
5665 DepthClipControlPtr pDepthClipControlInfo;
5666
5667 if (staticDepthClipControlInfo)
5668 {
5669 pDepthClipControlInfo = DepthClipControlPtr(
5670 new vk::VkPipelineViewportDepthClipControlCreateInfoEXT(vk::initVulkanStructure(viewportPnext)));
5671 pDepthClipControlInfo->negativeOneToOne = makeVkBool32(m_testConfig.negativeOneToOneConfig.staticValue.get());
5672 viewportPnext = pDepthClipControlInfo.get();
5673 }
5674
5675 ConservativeRastPtr pConservativeRasterModeInfo;
5676
5677 if (m_testConfig.conservativeRasterStruct())
5678 {
5679 pConservativeRasterModeInfo = ConservativeRastPtr(
5680 new vk::VkPipelineRasterizationConservativeStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5681 rasterizationPnext = pConservativeRasterModeInfo.get();
5682
5683 pConservativeRasterModeInfo->conservativeRasterizationMode =
5684 m_testConfig.conservativeRasterModeConfig.staticValue;
5685 pConservativeRasterModeInfo->extraPrimitiveOverestimationSize =
5686 m_testConfig.extraPrimitiveOverEstConfig.staticValue;
5687 }
5688
5689 DepthBiasReprInfoPtr pDepthBiasReprInfo;
5690
5691 if (m_testConfig.depthBiasReprInfo && (!m_testConfig.depthBiasConfig.dynamicValue || kReversed))
5692 {
5693 // Representation info will be passed statically.
5694 pDepthBiasReprInfo =
5695 DepthBiasReprInfoPtr(new vk::VkDepthBiasRepresentationInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5696 rasterizationPnext = pDepthBiasReprInfo.get();
5697
5698 const auto &reprInfo = m_testConfig.depthBiasReprInfo.get();
5699 pDepthBiasReprInfo->depthBiasRepresentation = reprInfo.depthBiasRepresentation;
5700 pDepthBiasReprInfo->depthBiasExact = reprInfo.depthBiasExact;
5701 }
5702 #else
5703 DE_ASSERT(!staticStreamInfo);
5704 DE_ASSERT(!staticProvokingVtxInfo);
5705 DE_ASSERT(!staticDepthClipEnableInfo);
5706 DE_ASSERT(!staticDepthClipControlInfo);
5707 DE_ASSERT(!m_testConfig.conservativeRasterStruct());
5708 DE_UNREF(staticStreamInfo);
5709 DE_UNREF(staticProvokingVtxInfo);
5710 DE_UNREF(staticDepthClipEnableInfo);
5711 DE_UNREF(staticDepthClipControlInfo);
5712 #endif // CTS_USES_VULKANSC
5713
5714 using LineRasterModePtr = de::MovePtr<vk::VkPipelineRasterizationLineStateCreateInfoEXT>;
5715 LineRasterModePtr pLineRasterModeInfo;
5716
5717 if (m_testConfig.lineRasterStruct())
5718 {
5719 DE_ASSERT(static_cast<bool>(m_testConfig.lineStippleParamsConfig.staticValue));
5720
5721 pLineRasterModeInfo = LineRasterModePtr(
5722 new vk::VkPipelineRasterizationLineStateCreateInfoEXT(vk::initVulkanStructure(rasterizationPnext)));
5723 rasterizationPnext = pLineRasterModeInfo.get();
5724
5725 const auto &lineRasterFeatures = m_context.getLineRasterizationFeatures();
5726 const auto lineRasterMode =
5727 selectLineRasterizationMode(lineRasterFeatures, m_testConfig.lineStippleSupportRequired(),
5728 m_testConfig.lineRasterModeConfig.staticValue);
5729 const auto &staticParams = m_testConfig.lineStippleParamsConfig.staticValue.get();
5730
5731 pLineRasterModeInfo->stippledLineEnable = m_testConfig.lineStippleEnableConfig.staticValue;
5732 pLineRasterModeInfo->lineRasterizationMode = makeLineRasterizationMode(lineRasterMode);
5733 pLineRasterModeInfo->lineStippleFactor = staticParams.factor;
5734 pLineRasterModeInfo->lineStipplePattern = staticParams.pattern;
5735 }
5736
5737 const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
5738 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
5739 rasterizationPnext, // const void* pNext;
5740 0u, // VkPipelineRasterizationStateCreateFlags flags;
5741 makeVkBool32(m_testConfig.depthClampEnableConfig.staticValue), // VkBool32 depthClampEnable;
5742 makeVkBool32(m_testConfig.rastDiscardEnableConfig.staticValue), // VkBool32 rasterizerDiscardEnable;
5743 m_testConfig.polygonModeConfig.staticValue, // VkPolygonMode polygonMode;
5744 m_testConfig.cullModeConfig.staticValue, // VkCullModeFlags cullMode;
5745 m_testConfig.frontFaceConfig.staticValue, // VkFrontFace frontFace;
5746 makeVkBool32(m_testConfig.depthBiasEnableConfig.staticValue), // VkBool32 depthBiasEnable;
5747 m_testConfig.depthBiasConfig.staticValue.constantFactor, // float depthBiasConstantFactor;
5748 m_testConfig.depthBiasConfig.staticValue.clamp, // float depthBiasClamp;
5749 0.0f, // float depthBiasSlopeFactor;
5750 m_testConfig.lineWidthConfig.staticValue, // float lineWidth;
5751 };
5752
5753 using SampleLocationsPtr = de::MovePtr<vk::VkPipelineSampleLocationsStateCreateInfoEXT>;
5754 SampleLocationsPtr pSampleLocations;
5755 std::vector<vk::VkSampleLocationEXT> sampleLocationCoords;
5756
5757 #ifndef CTS_USES_VULKANSC
5758 using CoverageToColorPtr = de::MovePtr<vk::VkPipelineCoverageToColorStateCreateInfoNV>;
5759 CoverageToColorPtr pCoverageToColor;
5760
5761 using CoverageModulationPtr = de::MovePtr<vk::VkPipelineCoverageModulationStateCreateInfoNV>;
5762 CoverageModulationPtr pCoverageModulation;
5763
5764 using CoverageReductionPtr = de::MovePtr<vk::VkPipelineCoverageReductionStateCreateInfoNV>;
5765 CoverageReductionPtr pCoverageReduction;
5766
5767 using ViewportSwizzlePtr = de::MovePtr<vk::VkPipelineViewportSwizzleStateCreateInfoNV>;
5768 ViewportSwizzlePtr pViewportSwizzle;
5769
5770 using ShadingRateImagePtr = de::MovePtr<vk::VkPipelineViewportShadingRateImageStateCreateInfoNV>;
5771 ShadingRateImagePtr pShadingRateImage;
5772
5773 using ViewportWScalingPtr = de::MovePtr<vk::VkPipelineViewportWScalingStateCreateInfoNV>;
5774 ViewportWScalingPtr pViewportWScaling;
5775
5776 using ReprFragmentPtr = de::MovePtr<vk::VkPipelineRepresentativeFragmentTestStateCreateInfoNV>;
5777 ReprFragmentPtr pReprFragment;
5778 #endif // CTS_USES_VULKANSC
5779
5780 if (m_testConfig.sampleLocationsStruct())
5781 {
5782 pSampleLocations = SampleLocationsPtr(
5783 new vk::VkPipelineSampleLocationsStateCreateInfoEXT(vk::initVulkanStructure(multisamplePnext)));
5784 multisamplePnext = pSampleLocations.get();
5785
5786 pSampleLocations->sampleLocationsEnable = makeVkBool32(m_testConfig.sampleLocationsEnableConfig.staticValue);
5787 pSampleLocations->sampleLocationsInfo = vk::initVulkanStructure();
5788 pSampleLocations->sampleLocationsInfo.sampleLocationsPerPixel = activeSampleCount;
5789 pSampleLocations->sampleLocationsInfo.sampleLocationGridSize = vk::makeExtent2D(1u, 1u);
5790 pSampleLocations->sampleLocationsInfo.sampleLocationsCount = static_cast<uint32_t>(activeSampleCount);
5791
5792 sampleLocationCoords.reserve(pSampleLocations->sampleLocationsInfo.sampleLocationsCount);
5793 for (uint32_t i = 0; i < pSampleLocations->sampleLocationsInfo.sampleLocationsCount; ++i)
5794 sampleLocationCoords.push_back(
5795 vk::VkSampleLocationEXT{m_testConfig.sampleLocations.x(), m_testConfig.sampleLocations.y()});
5796
5797 pSampleLocations->sampleLocationsInfo.pSampleLocations = sampleLocationCoords.data();
5798 }
5799
5800 #ifndef CTS_USES_VULKANSC
5801 if (m_testConfig.coverageToColorStruct())
5802 {
5803 pCoverageToColor = CoverageToColorPtr(
5804 new vk::VkPipelineCoverageToColorStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
5805 multisamplePnext = pCoverageToColor.get();
5806
5807 pCoverageToColor->coverageToColorEnable = makeVkBool32(m_testConfig.coverageToColorEnableConfig.staticValue);
5808 pCoverageToColor->coverageToColorLocation = m_testConfig.coverageToColorLocationConfig.staticValue;
5809 }
5810
5811 if (m_testConfig.coverageModulation)
5812 {
5813 pCoverageModulation = CoverageModulationPtr(
5814 new vk::VkPipelineCoverageModulationStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
5815 multisamplePnext = pCoverageModulation.get();
5816
5817 pCoverageModulation->coverageModulationMode = m_testConfig.coverageModulationModeConfig.staticValue;
5818 pCoverageModulation->coverageModulationTableEnable =
5819 makeVkBool32(m_testConfig.coverageModTableEnableConfig.staticValue);
5820 pCoverageModulation->coverageModulationTableCount =
5821 static_cast<uint32_t>(m_testConfig.coverageModTableConfig.staticValue.size());
5822 pCoverageModulation->pCoverageModulationTable = de::dataOrNull(m_testConfig.coverageModTableConfig.staticValue);
5823 }
5824
5825 if (m_testConfig.coverageReduction)
5826 {
5827 pCoverageReduction = CoverageReductionPtr(
5828 new vk::VkPipelineCoverageReductionStateCreateInfoNV(vk::initVulkanStructure(multisamplePnext)));
5829 multisamplePnext = pCoverageReduction.get();
5830
5831 pCoverageReduction->coverageReductionMode = m_testConfig.coverageReductionModeConfig.staticValue;
5832 }
5833
5834 if (m_testConfig.viewportSwizzle)
5835 {
5836 pViewportSwizzle = ViewportSwizzlePtr(
5837 new vk::VkPipelineViewportSwizzleStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
5838 viewportPnext = pViewportSwizzle.get();
5839
5840 const auto &swizzleVec = m_testConfig.viewportSwizzleConfig.staticValue;
5841 pViewportSwizzle->viewportCount = static_cast<uint32_t>(swizzleVec.size());
5842 pViewportSwizzle->pViewportSwizzles = de::dataOrNull(swizzleVec);
5843 }
5844
5845 const vk::VkShadingRatePaletteEntryNV defaultShadingRatePaletteEntry =
5846 vk::VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV;
5847 const auto defaultShadingRatePalette = vk::makeShadingRatePaletteNV(1u, &defaultShadingRatePaletteEntry);
5848 std::vector<vk::VkShadingRatePaletteNV> shadingRatePaletteVec;
5849
5850 const auto defaultViewportWScalingFactors = vk::makeViewportWScalingNV(-1.0f, -1.0f);
5851 std::vector<vk::VkViewportWScalingNV> viewportWScalingVec;
5852
5853 if (m_testConfig.shadingRateImage)
5854 {
5855 pShadingRateImage = ShadingRateImagePtr(
5856 new vk::VkPipelineViewportShadingRateImageStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
5857 viewportPnext = pShadingRateImage.get();
5858
5859 const auto &viewportVec = m_testConfig.getActiveViewportVec();
5860 pShadingRateImage->shadingRateImageEnable = makeVkBool32(m_testConfig.shadingRateImageEnableConfig.staticValue);
5861 pShadingRateImage->viewportCount = de::sizeU32(viewportVec);
5862
5863 shadingRatePaletteVec.resize(viewportVec.size(), defaultShadingRatePalette);
5864 pShadingRateImage->pShadingRatePalettes = shadingRatePaletteVec.data();
5865 }
5866
5867 if (m_testConfig.viewportWScaling)
5868 {
5869 pViewportWScaling = ViewportWScalingPtr(
5870 new vk::VkPipelineViewportWScalingStateCreateInfoNV(vk::initVulkanStructure(viewportPnext)));
5871 viewportPnext = pViewportWScaling.get();
5872
5873 const auto &viewportVec = m_testConfig.getActiveViewportVec();
5874 pViewportWScaling->viewportWScalingEnable = makeVkBool32(m_testConfig.viewportWScalingEnableConfig.staticValue);
5875 pViewportWScaling->viewportCount = de::sizeU32(viewportVec);
5876
5877 viewportWScalingVec.resize(viewportVec.size(), defaultViewportWScalingFactors);
5878 pViewportWScaling->pViewportWScalings = viewportWScalingVec.data();
5879 }
5880
5881 if (m_testConfig.representativeFragmentTest)
5882 {
5883 pReprFragment =
5884 ReprFragmentPtr(new vk::VkPipelineRepresentativeFragmentTestStateCreateInfoNV(vk::initVulkanStructure()));
5885 pReprFragment->representativeFragmentTestEnable =
5886 makeVkBool32(m_testConfig.reprFragTestEnableConfig.staticValue);
5887 }
5888 #endif // CTS_USES_VULKANSC
5889
5890 // Multisample state.
5891 const vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo{
5892 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
5893 multisamplePnext, // const void* pNext;
5894 0u, // VkPipelineMultisampleStateCreateFlags flags;
5895 m_testConfig.rasterizationSamplesConfig.staticValue, // VkSampleCountFlagBits rasterizationSamples;
5896 makeVkBool32(m_testConfig.sampleShadingEnable), // VkBool32 sampleShadingEnable;
5897 m_testConfig.minSampleShading, // float minSampleShading;
5898 de::dataOrNull(m_testConfig.sampleMaskConfig.staticValue), // const VkSampleMask* pSampleMask;
5899 makeVkBool32(m_testConfig.alphaToCoverageConfig.staticValue), // VkBool32 alphaToCoverageEnable;
5900 makeVkBool32(m_testConfig.alphaToOneConfig.staticValue), // VkBool32 alphaToOneEnable;
5901 };
5902
5903 // Depth/stencil state.
5904 vk::VkStencilOpState staticFrontStencil;
5905 vk::VkStencilOpState staticBackStencil;
5906 bool staticFrontStencilSet = false;
5907 bool staticBackStencilSet = false;
5908
5909 // Common setup for the front and back operations.
5910 staticFrontStencil.compareMask = 0xFFu;
5911 staticFrontStencil.writeMask = 0xFFu;
5912 staticFrontStencil.reference = m_testConfig.referenceStencil;
5913 staticBackStencil = staticFrontStencil;
5914
5915 for (const auto &op : m_testConfig.stencilOpConfig.staticValue)
5916 {
5917 if ((op.faceMask & vk::VK_STENCIL_FACE_FRONT_BIT) != 0u)
5918 {
5919 copy(staticFrontStencil, op);
5920 staticFrontStencilSet = true;
5921 }
5922 if ((op.faceMask & vk::VK_STENCIL_FACE_BACK_BIT) != 0u)
5923 {
5924 copy(staticBackStencil, op);
5925 staticBackStencilSet = true;
5926 }
5927 }
5928
5929 // Default values for the static part.
5930 if (!staticFrontStencilSet)
5931 copy(staticFrontStencil, kDefaultStencilOpParams);
5932 if (!staticBackStencilSet)
5933 copy(staticBackStencil, kDefaultStencilOpParams);
5934
5935 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
5936 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
5937 nullptr, // const void* pNext;
5938 0u, // VkPipelineDepthStencilStateCreateFlags flags;
5939 makeVkBool32(m_testConfig.depthTestEnableConfig.staticValue), // VkBool32 depthTestEnable;
5940 makeVkBool32(m_testConfig.depthWriteEnableConfig.staticValue), // VkBool32 depthWriteEnable;
5941 m_testConfig.depthCompareOpConfig.staticValue, // VkCompareOp depthCompareOp;
5942 makeVkBool32(m_testConfig.depthBoundsTestEnableConfig.staticValue), // VkBool32 depthBoundsTestEnable;
5943 makeVkBool32(m_testConfig.stencilTestEnableConfig.staticValue), // VkBool32 stencilTestEnable;
5944 staticFrontStencil, // VkStencilOpState front;
5945 staticBackStencil, // VkStencilOpState back;
5946 m_testConfig.depthBoundsConfig.staticValue.first, // float minDepthBounds;
5947 m_testConfig.depthBoundsConfig.staticValue.second, // float maxDepthBounds;
5948 };
5949
5950 // Dynamic state. Here we will set all states which have a dynamic value.
5951 const auto dynamicStates = m_testConfig.getDynamicStates();
5952
5953 const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
5954 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
5955 nullptr, // const void* pNext;
5956 0u, // VkPipelineDynamicStateCreateFlags flags;
5957 static_cast<uint32_t>(dynamicStates.size()), // uint32_t dynamicStateCount;
5958 de::dataOrNull(dynamicStates), // const VkDynamicState* pDynamicStates;
5959 };
5960
5961 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
5962 makeVkBool32(m_testConfig.colorBlendEnableConfig.staticValue), // VkBool32 blendEnable
5963 m_testConfig.colorBlendEquationConfig.staticValue
5964 .srcColorBlendFactor, // VkBlendFactor srcColorBlendFactor
5965 m_testConfig.colorBlendEquationConfig.staticValue
5966 .dstColorBlendFactor, // VkBlendFactor dstColorBlendFactor
5967 m_testConfig.colorBlendEquationConfig.staticValue.colorBlendOp, // VkBlendOp colorBlendOp
5968 m_testConfig.colorBlendEquationConfig.staticValue
5969 .srcAlphaBlendFactor, // VkBlendFactor srcAlphaBlendFactor
5970 m_testConfig.colorBlendEquationConfig.staticValue
5971 .dstAlphaBlendFactor, // VkBlendFactor dstAlphaBlendFactor
5972 m_testConfig.colorBlendEquationConfig.staticValue.alphaBlendOp, // VkBlendOp alphaBlendOp
5973 m_testConfig.colorWriteMaskConfig.staticValue, // VkColorComponentFlags colorWriteMask
5974 };
5975 const std::vector<vk::VkPipelineColorBlendAttachmentState> colorBlendAttachmentStateVec(kColorAttCount,
5976 colorBlendAttachmentState);
5977
5978 void *colorBlendPnext = nullptr;
5979
5980 using ColorBlendAdvancedPtr = de::MovePtr<vk::VkPipelineColorBlendAdvancedStateCreateInfoEXT>;
5981 ColorBlendAdvancedPtr pColorBlendAdvanced;
5982
5983 if (m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced())
5984 {
5985 pColorBlendAdvanced = ColorBlendAdvancedPtr(
5986 new vk::VkPipelineColorBlendAdvancedStateCreateInfoEXT(vk::initVulkanStructure(colorBlendPnext)));
5987 pColorBlendAdvanced->srcPremultiplied = VK_TRUE;
5988 pColorBlendAdvanced->dstPremultiplied = VK_TRUE;
5989 pColorBlendAdvanced->blendOverlap = vk::VK_BLEND_OVERLAP_UNCORRELATED_EXT;
5990 colorBlendPnext = pColorBlendAdvanced.get();
5991 }
5992
5993 const std::vector<vk::VkBool32> colorWriteValues(colorBlendAttachmentStateVec.size(),
5994 m_testConfig.colorWriteEnableConfig.staticValue);
5995
5996 using ColorWriteEnablePtr = de::MovePtr<vk::VkPipelineColorWriteCreateInfoEXT>;
5997 ColorWriteEnablePtr pColorWriteEnable;
5998
5999 if (m_testConfig.useColorWriteEnable)
6000 {
6001 pColorWriteEnable =
6002 ColorWriteEnablePtr(new vk::VkPipelineColorWriteCreateInfoEXT(vk::initVulkanStructure(colorBlendPnext)));
6003 pColorWriteEnable->attachmentCount = de::sizeU32(colorWriteValues);
6004 pColorWriteEnable->pColorWriteEnables = de::dataOrNull(colorWriteValues);
6005 colorBlendPnext = pColorWriteEnable.get();
6006 }
6007
6008 if (m_testConfig.nullStaticColorBlendAttPtr || m_testConfig.colorBlendAttCnt0)
6009 {
6010 DE_ASSERT(static_cast<bool>(m_testConfig.colorBlendEnableConfig.dynamicValue));
6011 DE_ASSERT(static_cast<bool>(m_testConfig.colorBlendEquationConfig.dynamicValue));
6012 DE_ASSERT(static_cast<bool>(m_testConfig.colorWriteMaskConfig.dynamicValue));
6013 }
6014
6015 const auto attachmentCount = m_testConfig.colorBlendAttCnt0 ? 0u : de::sizeU32(colorBlendAttachmentStateVec);
6016 const auto attachments =
6017 m_testConfig.nullStaticColorBlendAttPtr ? nullptr : de::dataOrNull(colorBlendAttachmentStateVec);
6018
6019 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
6020 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
6021 colorBlendPnext, // const void* pNext
6022 0u, // VkPipelineColorBlendStateCreateFlags flags
6023 m_testConfig.logicOpEnableConfig.staticValue, // VkBool32 logicOpEnable
6024 m_testConfig.logicOpConfig.staticValue, // VkLogicOp logicOp
6025 attachmentCount, // uint32_t attachmentCount
6026 attachments, // const VkPipelineColorBlendAttachmentState* pAttachments
6027 {
6028 // float blendConstants[4]
6029 m_testConfig.blendConstantsConfig.staticValue[0],
6030 m_testConfig.blendConstantsConfig.staticValue[1],
6031 m_testConfig.blendConstantsConfig.staticValue[2],
6032 m_testConfig.blendConstantsConfig.staticValue[3],
6033 },
6034 };
6035
6036 vk::GraphicsPipelineWrapper staticPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(),
6037 m_testConfig.pipelineConstructionType);
6038
6039 // Create extra dynamic patch control points pipeline if needed.
6040 vk::GraphicsPipelineWrapper extraDynPCPPipeline(
6041 vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(), m_testConfig.pipelineConstructionType);
6042
6043 if (m_testConfig.useExtraDynPCPPipeline)
6044 {
6045 vertDPCPModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vertDPCP"));
6046 fragDPCPModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("fragDPCP"));
6047
6048 const vk::VkPipelineVertexInputStateCreateInfo extraDPCPInputState = vk::initVulkanStructure();
6049 const vk::VkDynamicState extraDynamicState = vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
6050 const vk::VkPipelineDynamicStateCreateInfo extraDynamicStateInfo = {
6051 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
6052 nullptr, // const void* pNext;
6053 0u, // VkPipelineDynamicStateCreateFlags flags;
6054 1u, // uint32_t dynamicStateCount;
6055 &extraDynamicState, // const VkDynamicState* pDynamicStates;
6056 };
6057
6058 const vk::PipelineLayoutWrapper extraPipelineLayout(m_testConfig.pipelineConstructionType, vkd, device);
6059
6060 const auto viewports = m_testConfig.viewportConfig.staticValue;
6061 const auto scissors = m_testConfig.scissorConfig.staticValue;
6062
6063 extraDynPCPPipeline.setDynamicState(&extraDynamicStateInfo)
6064 .setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
6065 .setDefaultColorBlendState()
6066 .setDefaultMultisampleState()
6067 .setupVertexInputState(&extraDPCPInputState)
6068 .setupPreRasterizationShaderState(viewports, scissors, extraPipelineLayout, *renderPassFramebuffers[0], 0u,
6069 vertDPCPModule, &rasterizationStateCreateInfo)
6070 .setupFragmentShaderState(extraPipelineLayout, *renderPassFramebuffers[0], 0u, fragDPCPModule,
6071 &depthStencilStateCreateInfo)
6072 .setupFragmentOutputState(*renderPassFramebuffers[0], 0u)
6073 .setMonolithicPipelineLayout(extraPipelineLayout)
6074 .buildPipeline();
6075 }
6076 else if (m_testConfig.useExtraDynPipeline)
6077 {
6078 vertDPCPModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vertDPCP"));
6079 }
6080
6081 // Create static pipeline when needed.
6082 if (kUseStaticPipeline)
6083 {
6084 auto viewports = m_testConfig.viewportConfig.staticValue;
6085 auto scissors = m_testConfig.scissorConfig.staticValue;
6086
6087 // The viewport and scissor counts must match in the static part, which will be used by the static pipeline.
6088 const auto minStaticCount = static_cast<uint32_t>(
6089 std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
6090 viewports.resize(minStaticCount);
6091 scissors.resize(minStaticCount);
6092
6093 staticPipeline.setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
6094 .setViewportStatePnext(viewportPnext)
6095 .setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue);
6096
6097 // The pAttachments pointer must never be null for the static pipeline.
6098 vk::VkPipelineColorBlendStateCreateInfo staticCBStateInfo = colorBlendStateCreateInfo;
6099 if (m_testConfig.nullStaticColorBlendAttPtr)
6100 staticCBStateInfo.pAttachments = de::dataOrNull(colorBlendAttachmentStateVec);
6101
6102 // The attachment count must never be 0 for the static pipeline.
6103 if (m_testConfig.colorBlendAttCnt0)
6104 staticCBStateInfo.attachmentCount = de::sizeU32(colorBlendAttachmentStateVec);
6105
6106 #ifndef CTS_USES_VULKANSC
6107 if (m_testConfig.useMeshShaders)
6108 {
6109 staticPipeline.setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout,
6110 *renderPassFramebuffers[0], 0u, vk::ShaderWrapper(),
6111 staticMeshModule, &rasterizationStateCreateInfo);
6112 }
6113 else
6114 #endif // CTS_USES_VULKANSC
6115 {
6116 staticPipeline.setupVertexInputState(&vertexInputStateCreateInfo, &inputAssemblyStateCreateInfo)
6117 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPassFramebuffers[0], 0u,
6118 staticVertModule, &rasterizationStateCreateInfo, tescModule,
6119 teseModule, geomModule);
6120 }
6121
6122 vk::ShaderWrapper emptyFrag{};
6123 const vk::ShaderWrapper &fragForStatic =
6124 m_testConfig.rastDiscardEnableConfig.staticValue ? emptyFrag : staticFragModule;
6125
6126 staticPipeline
6127 #ifndef CTS_USES_VULKANSC
6128 .setRepresentativeFragmentTestState(pReprFragment.get())
6129 #endif // CTS_USES_VULKANSC
6130 .setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, fragForStatic,
6131 &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
6132 .setupFragmentOutputState(*renderPassFramebuffers[0], 0u, &staticCBStateInfo, &multisampleStateCreateInfo)
6133 .setMonolithicPipelineLayout(pipelineLayout)
6134 .buildPipeline();
6135 }
6136
6137 // Create dynamic pipeline.
6138 vk::GraphicsPipelineWrapper graphicsPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(),
6139 m_testConfig.pipelineConstructionType);
6140 vk::GraphicsPipelineWrapper extraDynPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(),
6141 m_testConfig.pipelineConstructionType);
6142 {
6143 auto viewports = m_testConfig.viewportConfig.staticValue;
6144 auto scissors = m_testConfig.scissorConfig.staticValue;
6145
6146 const auto finalDynamicViewportCount =
6147 (m_testConfig.viewportConfig.dynamicValue ? m_testConfig.viewportConfig.dynamicValue.get().size() :
6148 m_testConfig.viewportConfig.staticValue.size());
6149
6150 const auto finalDynamicScissorCount =
6151 (m_testConfig.scissorConfig.dynamicValue ? m_testConfig.scissorConfig.dynamicValue.get().size() :
6152 m_testConfig.scissorConfig.staticValue.size());
6153
6154 const auto minDynamicCount =
6155 static_cast<uint32_t>(std::min(finalDynamicScissorCount, finalDynamicViewportCount));
6156
6157 // The viewport and scissor counts must be zero when a dynamic value will be provided, as per the spec.
6158 if (m_testConfig.viewportConfig.dynamicValue)
6159 {
6160 graphicsPipeline.setDefaultViewportsCount();
6161 if (m_testConfig.useExtraDynPipeline)
6162 extraDynPipeline.setDefaultViewportsCount();
6163 viewports = std::vector<vk::VkViewport>();
6164 }
6165 else
6166 viewports.resize(minDynamicCount);
6167
6168 if (m_testConfig.scissorConfig.dynamicValue)
6169 {
6170 graphicsPipeline.setDefaultScissorsCount();
6171 if (m_testConfig.useExtraDynPipeline)
6172 extraDynPipeline.setDefaultScissorsCount();
6173 scissors = std::vector<vk::VkRect2D>();
6174 }
6175 else
6176 scissors.resize(minDynamicCount);
6177
6178 // Setting patch control points to std::numeric_limits<uint32_t>::max() will force null tessellation state pointer.
6179 const auto patchControlPoints =
6180 ((m_testConfig.favorStaticNullPointers && m_testConfig.patchControlPointsConfig.dynamicValue) ?
6181 std::numeric_limits<uint32_t>::max() :
6182 m_testConfig.patchControlPointsConfig.staticValue);
6183
6184 const auto disableViewportState =
6185 (m_testConfig.favorStaticNullPointers && m_testConfig.viewportConfig.dynamicValue &&
6186 m_testConfig.scissorConfig.dynamicValue);
6187
6188 graphicsPipeline.setDynamicState(&dynamicStateCreateInfo)
6189 .setDefaultPatchControlPoints(patchControlPoints)
6190 .setViewportStatePnext(viewportPnext)
6191 .setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue)
6192 .disableViewportState(disableViewportState);
6193 if (m_testConfig.useExtraDynPipeline)
6194 extraDynPipeline.setDynamicState(&dynamicStateCreateInfo)
6195 .setDefaultPatchControlPoints(patchControlPoints)
6196 .setViewportStatePnext(viewportPnext)
6197 .setDefaultTessellationDomainOrigin(m_testConfig.tessDomainOriginConfig.staticValue)
6198 .disableViewportState(disableViewportState);
6199
6200 const auto staticRasterizationStateCreateInfo =
6201 ((m_testConfig.favorStaticNullPointers && m_testConfig.depthClampEnableConfig.dynamicValue &&
6202 m_testConfig.rastDiscardEnableConfig.dynamicValue && m_testConfig.polygonModeConfig.dynamicValue &&
6203 m_testConfig.cullModeConfig.dynamicValue && m_testConfig.frontFaceConfig.dynamicValue &&
6204 m_testConfig.depthBiasEnableConfig.dynamicValue && m_testConfig.depthBiasConfig.dynamicValue &&
6205 m_testConfig.lineWidthConfig.dynamicValue) ?
6206 nullptr :
6207 &rasterizationStateCreateInfo);
6208
6209 DE_ASSERT(!m_testConfig.useExtraDynPipeline || !m_testConfig.useMeshShaders);
6210
6211 const vk::VkPipelineVertexInputStateCreateInfo emptyVertexInputStateCreateInfo = {
6212 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
6213 DE_NULL, // const void* pNext;
6214 0u, // VkPipelineVertexInputStateCreateFlags flags;
6215 0u, // uint32_t vertexBindingDescriptionCount;
6216 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
6217 0u, // uint32_t vertexAttributeDescriptionCount;
6218 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
6219 };
6220
6221 #ifndef CTS_USES_VULKANSC
6222 if (m_testConfig.useMeshShaders)
6223 {
6224 graphicsPipeline.setupPreRasterizationMeshShaderState(
6225 viewports, scissors, pipelineLayout, *renderPassFramebuffers[0], 0u, vk::ShaderWrapper(),
6226 dynamicMeshModule, staticRasterizationStateCreateInfo);
6227 }
6228 else
6229 #endif // CTS_USES_VULKANSC
6230 {
6231 const auto staticVertexInputStateCreateInfo =
6232 ((m_testConfig.favorStaticNullPointers && m_testConfig.testVertexDynamic()) ?
6233 nullptr :
6234 &vertexInputStateCreateInfo);
6235
6236 const auto staticInputAssemblyStateCreateInfo =
6237 ((m_testConfig.favorStaticNullPointers && m_testConfig.primRestartEnableConfig.dynamicValue &&
6238 m_testConfig.topologyConfig.dynamicValue) ?
6239 nullptr :
6240 &inputAssemblyStateCreateInfo);
6241
6242 graphicsPipeline
6243 .setupVertexInputState(staticVertexInputStateCreateInfo, staticInputAssemblyStateCreateInfo,
6244 VK_NULL_HANDLE, vk::PipelineCreationFeedbackCreateInfoWrapper(),
6245 m_testConfig.favorStaticNullPointers)
6246 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPassFramebuffers[0], 0u,
6247 dynamicVertModule, staticRasterizationStateCreateInfo, tescModule,
6248 teseModule, geomModule);
6249
6250 if (m_testConfig.useExtraDynPipeline)
6251 extraDynPipeline
6252 .setupVertexInputState(&emptyVertexInputStateCreateInfo, staticInputAssemblyStateCreateInfo,
6253 VK_NULL_HANDLE, vk::PipelineCreationFeedbackCreateInfoWrapper(),
6254 m_testConfig.favorStaticNullPointers)
6255 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPassFramebuffers[0],
6256 0u, vertDPCPModule, staticRasterizationStateCreateInfo);
6257 }
6258
6259 const auto staticMultisampleStateCreateInfo =
6260 ((m_testConfig.favorStaticNullPointers && m_testConfig.rasterizationSamplesConfig.dynamicValue &&
6261 m_testConfig.sampleMaskConfig.dynamicValue && m_testConfig.alphaToCoverageConfig.dynamicValue &&
6262 (m_testConfig.alphaToOneConfig.dynamicValue || m_testConfig.disableAlphaToOneFeature)) ?
6263 nullptr :
6264 &multisampleStateCreateInfo);
6265
6266 const auto staticDepthStencilStateCreateInfo =
6267 ((m_testConfig.favorStaticNullPointers && m_testConfig.depthTestEnableConfig.dynamicValue &&
6268 m_testConfig.depthWriteEnableConfig.dynamicValue && m_testConfig.depthCompareOpConfig.dynamicValue &&
6269 m_testConfig.depthBoundsTestEnableConfig.dynamicValue &&
6270 m_testConfig.stencilTestEnableConfig.dynamicValue && m_testConfig.stencilOpConfig.dynamicValue &&
6271 m_testConfig.depthBoundsConfig.dynamicValue) ?
6272 nullptr :
6273 &depthStencilStateCreateInfo);
6274
6275 const auto staticColorBlendStateCreateInfo =
6276 ((m_testConfig.favorStaticNullPointers && m_testConfig.logicOpEnableConfig.dynamicValue &&
6277 m_testConfig.logicOpConfig.dynamicValue && m_testConfig.colorBlendEnableConfig.dynamicValue &&
6278 m_testConfig.colorBlendEquationConfig.dynamicValue &&
6279 (m_testConfig.colorBlendBoth || !m_testConfig.colorBlendEquationConfig.staticValue.isAdvanced()) &&
6280 m_testConfig.colorWriteMaskConfig.dynamicValue && m_testConfig.blendConstantsConfig.dynamicValue) ?
6281 nullptr :
6282 &colorBlendStateCreateInfo);
6283 graphicsPipeline
6284 #ifndef CTS_USES_VULKANSC
6285 .setRepresentativeFragmentTestState(pReprFragment.get())
6286 #endif // CTS_USES_VULKANSC
6287 .setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, dynamicFragModule,
6288 staticDepthStencilStateCreateInfo, staticMultisampleStateCreateInfo)
6289 .setupFragmentOutputState(*renderPassFramebuffers[0], 0u, staticColorBlendStateCreateInfo,
6290 staticMultisampleStateCreateInfo)
6291 .setMonolithicPipelineLayout(pipelineLayout)
6292 .buildPipeline();
6293 if (m_testConfig.useExtraDynPipeline)
6294 extraDynPipeline
6295 #ifndef CTS_USES_VULKANSC
6296 .setRepresentativeFragmentTestState(pReprFragment.get())
6297 #endif // CTS_USES_VULKANSC
6298 .setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, dynamicFragModule,
6299 staticDepthStencilStateCreateInfo, staticMultisampleStateCreateInfo)
6300 .setupFragmentOutputState(*renderPassFramebuffers[0], 0u, staticColorBlendStateCreateInfo,
6301 staticMultisampleStateCreateInfo)
6302 .setMonolithicPipelineLayout(pipelineLayout)
6303 .buildPipeline();
6304 }
6305
6306 vk::GraphicsPipelineWrapper meshNoOutPipeline(vki, vkd, physicalDevice, device, deviceHelper.getDeviceExtensions(),
6307 m_testConfig.pipelineConstructionType);
6308
6309 #ifndef CTS_USES_VULKANSC
6310 if (m_testConfig.bindUnusedMeshShadingPipeline)
6311 {
6312 // Remove dynamic states which are not compatible with mesh shading pipelines.
6313 std::vector<vk::VkDynamicState> meshNoOutDynamicStates;
6314 std::copy_if(begin(dynamicStates), end(dynamicStates), std::back_inserter(meshNoOutDynamicStates),
6315 isMeshShadingPipelineCompatible);
6316
6317 const vk::VkPipelineDynamicStateCreateInfo meshNoOutDynamicStateInfo = {
6318 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
6319 nullptr, // const void* pNext;
6320 0u, // VkPipelineDynamicStateCreateFlags flags;
6321 de::sizeU32(meshNoOutDynamicStates), // uint32_t dynamicStateCount;
6322 de::dataOrNull(meshNoOutDynamicStates), // const VkDynamicState* pDynamicStates;
6323 };
6324
6325 // Provide a viewport state similar to the static pipeline.
6326 auto viewports = m_testConfig.viewportConfig.staticValue;
6327 auto scissors = m_testConfig.scissorConfig.staticValue;
6328
6329 const auto minStaticCount = static_cast<uint32_t>(
6330 std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
6331 viewports.resize(minStaticCount);
6332 scissors.resize(minStaticCount);
6333
6334 meshNoOutPipeline.setDynamicState(&meshNoOutDynamicStateInfo)
6335 .setDefaultPatchControlPoints(m_testConfig.patchControlPointsConfig.staticValue)
6336 .setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, *renderPassFramebuffers[0], 0u,
6337 vk::ShaderWrapper(), meshNoOutModule, &rasterizationStateCreateInfo)
6338 .setupFragmentShaderState(pipelineLayout, *renderPassFramebuffers[0], 0u, vk::ShaderWrapper(),
6339 &depthStencilStateCreateInfo, &multisampleStateCreateInfo)
6340 .setupFragmentOutputState(*renderPassFramebuffers[0], 0u, &colorBlendStateCreateInfo,
6341 &multisampleStateCreateInfo)
6342 .setMonolithicPipelineLayout(pipelineLayout)
6343 .buildPipeline();
6344 }
6345 #endif // CTS_USES_VULKANSC
6346
6347 // Command buffer.
6348 const auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
6349 const auto cmdBufferPtr =
6350 vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
6351 const auto cmdBuffer = cmdBufferPtr.get();
6352
6353 // Clear values, clear to green for dynamic logicOp
6354 std::vector<vk::VkClearValue> clearValues(kColorAttCount, m_testConfig.clearColorValue);
6355 clearValues.push_back(vk::makeClearValueDepthStencil(m_testConfig.clearDepthValue, m_testConfig.clearStencilValue));
6356
6357 // Record command buffer.
6358 vk::beginCommandBuffer(vkd, cmdBuffer);
6359
6360 for (uint32_t iteration = 0u; iteration < kNumIterations; ++iteration)
6361 {
6362 // Track in-advance vertex buffer binding.
6363 bool boundInAdvance = false;
6364
6365 // Maybe set extended dynamic state here.
6366 if (kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START)
6367 {
6368 setDynamicStates(m_testConfig, vkd, cmdBuffer);
6369 boundInAdvance =
6370 maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
6371 }
6372
6373 // Begin render pass.
6374 renderPassFramebuffers[iteration].begin(vkd, cmdBuffer, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight),
6375 static_cast<uint32_t>(clearValues.size()), clearValues.data());
6376
6377 // Bind a static pipeline first if needed.
6378 if (kBindStaticFirst && iteration == 0u)
6379 staticPipeline.bind(cmdBuffer);
6380
6381 // Maybe set extended dynamic state here.
6382 if (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES)
6383 {
6384 setDynamicStates(m_testConfig, vkd, cmdBuffer);
6385 boundInAdvance =
6386 maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
6387 }
6388
6389 // Bind dynamic pipeline.
6390 if ((kSequenceOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC &&
6391 kSequenceOrdering != SequenceOrdering::TWO_DRAWS_STATIC) ||
6392 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
6393 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
6394 {
6395 if (m_testConfig.bindUnusedMeshShadingPipeline)
6396 {
6397 DE_ASSERT(kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START);
6398 meshNoOutPipeline.bind(cmdBuffer);
6399 }
6400
6401 if (m_testConfig.useExtraDynPCPPipeline)
6402 {
6403 extraDynPCPPipeline.bind(cmdBuffer);
6404
6405 // In these two sequence orderings, the right dynamic state value will have been set before and we would be
6406 // setting it to a wrong value here, resulting in test failures. We keep the right value instead.
6407 if (kSequenceOrdering != SequenceOrdering::CMD_BUFFER_START &&
6408 kSequenceOrdering != SequenceOrdering::BETWEEN_PIPELINES)
6409 vkd.cmdSetPatchControlPointsEXT(cmdBuffer, m_testConfig.patchControlPointsConfig.staticValue);
6410
6411 vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
6412 }
6413
6414 if (m_testConfig.useExtraDynPipeline)
6415 {
6416 extraDynPipeline.bind(cmdBuffer);
6417
6418 if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW ||
6419 kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES ||
6420 kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC)
6421 setDynamicStates(m_testConfig, vkd, cmdBuffer);
6422
6423 vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
6424 }
6425
6426 graphicsPipeline.bind(cmdBuffer);
6427
6428 // When shader objects are used vkCmdSetVertexInput() will overwrite vkCmdBindBuffers2 so we have to call it again
6429 if (boundInAdvance && vk::isConstructionTypeShaderObject(m_testConfig.pipelineConstructionType))
6430 maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
6431 }
6432
6433 if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
6434 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
6435 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
6436 {
6437 setDynamicStates(m_testConfig, vkd, cmdBuffer);
6438 boundInAdvance =
6439 maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
6440 }
6441
6442 // Bind a static pipeline last if needed.
6443 if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
6444 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration > 0u))
6445 {
6446 staticPipeline.bind(cmdBuffer);
6447 }
6448
6449 const auto &viewportVec = m_testConfig.getActiveViewportVec();
6450 for (size_t viewportIdx = 0u; viewportIdx < viewportVec.size(); ++viewportIdx)
6451 {
6452 for (size_t meshIdx = 0u; meshIdx < m_testConfig.meshParams.size(); ++meshIdx)
6453 {
6454 // Push constants.
6455 PushConstants pushConstants = {
6456 m_testConfig.meshParams[meshIdx].color, // tcu::Vec4 triangleColor;
6457 m_testConfig.meshParams[meshIdx].depth, // float meshDepth;
6458 static_cast<int32_t>(viewportIdx), // int32_t viewPortIndex;
6459 m_testConfig.meshParams[meshIdx].scaleX, // float scaleX;
6460 m_testConfig.meshParams[meshIdx].scaleY, // float scaleY;
6461 m_testConfig.meshParams[meshIdx].offsetX, // float offsetX;
6462 m_testConfig.meshParams[meshIdx].offsetY, // float offsetY;
6463 m_testConfig.meshParams[meshIdx].stripScale, // float stripScale;
6464 };
6465 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantStageFlags, 0u,
6466 static_cast<uint32_t>(sizeof(pushConstants)), &pushConstants);
6467
6468 // Track vertex bounding state for this mesh.
6469 bool boundBeforeDraw = false;
6470
6471 // Maybe set extended dynamic state here.
6472 if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW ||
6473 kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES)
6474 {
6475 setDynamicStates(m_testConfig, vkd, cmdBuffer);
6476 boundBeforeDraw = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, meshIdx, vertBuffers,
6477 rvertBuffers);
6478 }
6479
6480 // Bind vertex buffer with static stride if needed and draw.
6481 if (!(boundInAdvance || boundBeforeDraw) && !m_testConfig.useMeshShaders)
6482 {
6483 bindVertexBuffers(vkd, cmdBuffer,
6484 (m_testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers));
6485 if (m_testConfig.needsIndexBuffer())
6486 {
6487 const auto indexType = vk::VK_INDEX_TYPE_UINT32;
6488 vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer->get(), 0, indexType);
6489 }
6490 }
6491
6492 if (vertDataAsSSBO)
6493 {
6494 if (topologyClass == TopologyClass::LINE)
6495 DE_ASSERT(!m_testConfig.meshParams[meshIdx].reversed);
6496
6497 const auto boundSet = (m_testConfig.meshParams[meshIdx].reversed ? meshDescriptorSetRev.get() :
6498 meshDescriptorSet.get());
6499 vkd.cmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, pipelineLayout.get(), 0u, 1u, &boundSet, 0u,
6500 nullptr);
6501 }
6502
6503 #ifndef CTS_USES_VULKANSC
6504 // Shading rate image if enabled (we'll use a null handle to simplify, which is valid).
6505 if (m_testConfig.shadingRateImage)
6506 vkd.cmdBindShadingRateImageNV(cmdBuffer, VK_NULL_HANDLE, vk::VK_IMAGE_LAYOUT_GENERAL);
6507 #endif // CTS_USES_VULKANSC
6508
6509 if (kFragAtomics)
6510 vkd.cmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, pipelineLayout.get(),
6511 m_testConfig.getFragDescriptorSetIndex(), 1u, &fragDescriptorSet.get(),
6512 0u, nullptr);
6513
6514 // Draw mesh.
6515 if (m_testConfig.needsIndexBuffer())
6516 {
6517 uint32_t numIndices = static_cast<uint32_t>(indices.size());
6518 // For SequenceOrdering::TWO_DRAWS_DYNAMIC and TWO_DRAWS_STATIC cases, the first draw does not have primitive restart enabled
6519 // So, draw without using the invalid index, the second draw with primitive restart enabled will replace the results
6520 // using all indices.
6521 if (iteration == 0u && m_testConfig.testPrimRestartEnable() &&
6522 (m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
6523 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
6524 {
6525 numIndices = 2u;
6526 }
6527 vkd.cmdDrawIndexed(cmdBuffer, numIndices, m_testConfig.instanceCount, 0u, 0u, 0u);
6528 }
6529 #ifndef CTS_USES_VULKANSC
6530 else if (m_testConfig.useMeshShaders)
6531 {
6532 // Make sure drawing this way makes sense.
6533 const auto minVertCount = ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
6534 DE_UNREF(minVertCount); // For release builds.
6535 DE_ASSERT(vertices.size() >= minVertCount);
6536 DE_ASSERT(m_testConfig.instanceCount == 1u);
6537 DE_ASSERT(!m_testConfig.topologyConfig.dynamicValue);
6538
6539 uint32_t numPrimitives = 0u;
6540
6541 if (topologyClass == TopologyClass::TRIANGLE)
6542 {
6543 DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
6544 numPrimitives = de::sizeU32(vertices) - 2u;
6545 }
6546 else if (topologyClass == TopologyClass::LINE)
6547 {
6548 DE_ASSERT(m_testConfig.topologyConfig.staticValue == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP);
6549 const auto vertsPerRow = 4u;
6550 const auto linesPerRow = 3u;
6551 const auto vertexCount = de::sizeU32(vertices);
6552 const auto rowCount = vertexCount / vertsPerRow;
6553 numPrimitives = rowCount * linesPerRow;
6554
6555 if (m_testConfig.obliqueLine)
6556 numPrimitives = 1u;
6557 else
6558 DE_ASSERT(vertexCount % vertsPerRow == 0u);
6559 }
6560 else
6561 DE_ASSERT(false);
6562
6563 vkd.cmdDrawMeshTasksEXT(cmdBuffer, numPrimitives, 1u, 1u);
6564 }
6565 #endif // CTS_USES_VULKANSC
6566 else
6567 {
6568 uint32_t vertexCount = static_cast<uint32_t>(vertices.size());
6569 if (m_testConfig.singleVertex)
6570 vertexCount = m_testConfig.singleVertexDrawCount;
6571 vkd.cmdDraw(cmdBuffer, vertexCount, m_testConfig.instanceCount, 0u, 0u);
6572 }
6573 }
6574 }
6575
6576 renderPassFramebuffers[iteration].end(vkd, cmdBuffer);
6577 }
6578
6579 if (kFragAtomics)
6580 {
6581 const auto bufferBarrier = vk::makeMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT);
6582 vk::cmdPipelineMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
6583 vk::VK_PIPELINE_STAGE_HOST_BIT, &bufferBarrier);
6584 }
6585
6586 vk::endCommandBuffer(vkd, cmdBuffer);
6587
6588 // Submit commands.
6589 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
6590
6591 // Read result image aspects from the last used framebuffer.
6592 using LevelPtr = de::MovePtr<tcu::TextureLevel>;
6593
6594 const tcu::UVec2 renderSize(kFramebufferWidth, kFramebufferHeight);
6595
6596 const auto colorResultImg = (kUseResolveAtt ? resolveImages.back()->get() : colorImages.back()->get());
6597 const auto colorBuffer =
6598 readColorAttachment(vkd, device, queue, queueIndex, allocator, colorResultImg, colorFormat, renderSize);
6599 const auto colorAccess = colorBuffer->getAccess();
6600
6601 LevelPtr depthBuffer;
6602 LevelPtr stencilBuffer;
6603 tcu::PixelBufferAccess depthAccess;
6604 tcu::PixelBufferAccess stencilAccess;
6605
6606 if (!kMultisampleDS)
6607 {
6608 depthBuffer = readDepthAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(),
6609 dsFormatInfo->imageFormat, renderSize);
6610 stencilBuffer =
6611 readStencilAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(),
6612 dsFormatInfo->imageFormat, renderSize, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
6613 depthAccess = depthBuffer->getAccess();
6614 stencilAccess = stencilBuffer->getAccess();
6615 }
6616
6617 const int kWidth = static_cast<int>(kFramebufferWidth);
6618 const int kHeight = static_cast<int>(kFramebufferHeight);
6619
6620 // Generate reference color buffer.
6621 const auto tcuColorFormat = vk::mapVkFormat(colorFormat);
6622 tcu::TextureLevel referenceColorLevel(tcuColorFormat, kWidth, kHeight);
6623 tcu::PixelBufferAccess referenceColorAccess = referenceColorLevel.getAccess();
6624 (*m_testConfig.referenceColor)(referenceColorAccess);
6625
6626 const tcu::TextureFormat errorFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
6627 tcu::TextureLevel colorError(errorFormat, kWidth, kHeight);
6628 tcu::TextureLevel depthError(errorFormat, kWidth, kHeight);
6629 tcu::TextureLevel stencilError(errorFormat, kWidth, kHeight);
6630 const auto colorErrorAccess = colorError.getAccess();
6631 const auto depthErrorAccess = depthError.getAccess();
6632 const auto stencilErrorAccess = stencilError.getAccess();
6633 const tcu::Vec4 kGood(0.0f, 1.0f, 0.0f, 1.0f);
6634 const tcu::Vec4 kBad(1.0f, 0.0f, 0.0f, 1.0f);
6635
6636 // Check expected values.
6637 const bool hasCustomVerif = static_cast<bool>(m_testConfig.colorVerificator);
6638 const auto minDepth = m_testConfig.expectedDepth - dsFormatInfo->depthThreshold - m_testConfig.extraDepthThreshold;
6639 const auto maxDepth = m_testConfig.expectedDepth + dsFormatInfo->depthThreshold + m_testConfig.extraDepthThreshold;
6640 bool colorMatch = true;
6641 bool depthMatch = true;
6642 bool stencilMatch = true;
6643 bool match;
6644
6645 if (hasCustomVerif)
6646 colorMatch = (*m_testConfig.colorVerificator)(colorAccess, referenceColorAccess, colorErrorAccess);
6647
6648 for (int y = 0; y < kHeight; ++y)
6649 for (int x = 0; x < kWidth; ++x)
6650 {
6651 if (!hasCustomVerif)
6652 {
6653 if (vk::isUnormFormat(colorFormat))
6654 {
6655 const auto colorPixel = colorAccess.getPixel(x, y);
6656 const auto expectedPixel = referenceColorAccess.getPixel(x, y);
6657 match = tcu::boolAll(tcu::lessThan(tcu::absDiff(colorPixel, expectedPixel), kUnormColorThreshold));
6658 }
6659 else
6660 {
6661 DE_ASSERT(vk::isUintFormat(colorFormat));
6662 const auto colorPixel = colorAccess.getPixelUint(x, y);
6663 const auto expectedPixel = referenceColorAccess.getPixelUint(x, y);
6664 match = (colorPixel == expectedPixel);
6665 }
6666
6667 colorErrorAccess.setPixel((match ? kGood : kBad), x, y);
6668 if (!match)
6669 colorMatch = false;
6670 }
6671
6672 if (!kMultisampleDS)
6673 {
6674 const auto depthPixel = depthAccess.getPixDepth(x, y);
6675 match = de::inRange(depthPixel, minDepth, maxDepth);
6676 depthErrorAccess.setPixel((match ? kGood : kBad), x, y);
6677 if (!match)
6678 depthMatch = false;
6679
6680 const auto stencilPixel = static_cast<uint32_t>(stencilAccess.getPixStencil(x, y));
6681 match = (stencilPixel == m_testConfig.expectedStencil);
6682 stencilErrorAccess.setPixel((match ? kGood : kBad), x, y);
6683 if (!match)
6684 stencilMatch = false;
6685 }
6686 }
6687
6688 if (!(colorMatch && depthMatch && stencilMatch))
6689 {
6690 if (!colorMatch)
6691 logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
6692
6693 if (!depthMatch)
6694 logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
6695
6696 if (!stencilMatch)
6697 logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
6698
6699 if (!(colorMatch && depthMatch && stencilMatch))
6700 return tcu::TestStatus::fail("Incorrect value found in attachments; please check logged images");
6701 }
6702
6703 // Check storage buffer if used.
6704 uint32_t fragCounter = 0u;
6705
6706 if (kFragAtomics)
6707 {
6708 DE_ASSERT(m_testConfig.oversizedTriangle);
6709 DE_ASSERT(m_testConfig.meshParams.size() == 1u);
6710 DE_ASSERT(!m_testConfig.depthWriteEnableConfig.dynamicValue); // No dynamic value for depth writes.
6711 DE_ASSERT(!m_testConfig.depthWriteEnableConfig.staticValue); // No depth writes.
6712
6713 auto &counterBufferAlloc = counterBuffer->getAllocation();
6714 void *counterBufferData = counterBufferAlloc.getHostPtr();
6715 vk::invalidateAlloc(vkd, device, counterBufferAlloc);
6716
6717 deMemcpy(&fragCounter, counterBufferData, sizeof(fragCounter));
6718 }
6719
6720 if (m_testConfig.representativeFragmentTest)
6721 {
6722 DE_ASSERT(!m_testConfig.rasterizationSamplesConfig.dynamicValue);
6723
6724 // The expected number of invocations depends on how many draws are performed with the test enabled.
6725 // Draws with the test disabled should always result in kFramebufferHeight * kFramebufferWidth invocations.
6726 // Draws with the test enabled should result in at least 1 invocation, maybe more.
6727 uint32_t minValue = 0u;
6728
6729 const uint32_t minInvocations[] = {
6730 (kFramebufferHeight * kFramebufferWidth *
6731 static_cast<uint32_t>(m_testConfig.rasterizationSamplesConfig.staticValue)),
6732 1u,
6733 };
6734
6735 if (kNumIterations == 1u)
6736 {
6737 const auto testEnabled = m_testConfig.getActiveReprFragTestEnable();
6738 minValue += minInvocations[testEnabled];
6739 }
6740 else if (kNumIterations == 2u)
6741 {
6742 for (uint32_t i = 0u; i < kNumIterations; ++i)
6743 {
6744 bool testEnabled = false;
6745
6746 #ifndef CTS_USES_VULKANSC
6747 // Actually varies depending on TWO_DRAWS_STATIC/_DYNAMIC, but does not affect results.
6748 const bool staticDraw = (i == 0u);
6749
6750 if (staticDraw)
6751 testEnabled = m_testConfig.reprFragTestEnableConfig.staticValue;
6752 else
6753 {
6754 testEnabled = (m_testConfig.reprFragTestEnableConfig.dynamicValue ?
6755 m_testConfig.reprFragTestEnableConfig.dynamicValue.get() :
6756 m_testConfig.reprFragTestEnableConfig.staticValue);
6757 }
6758 #endif // CTS_USES_VULKANSC
6759
6760 minValue += minInvocations[testEnabled];
6761 }
6762 }
6763 else
6764 {
6765 DE_ASSERT(false);
6766 }
6767
6768 log << tcu::TestLog::Message << "Fragment counter minimum value: " << minValue << tcu::TestLog::EndMessage;
6769 log << tcu::TestLog::Message << "Fragment counter: " << fragCounter << tcu::TestLog::EndMessage;
6770
6771 if (fragCounter < minValue)
6772 {
6773 std::ostringstream msg;
6774 msg << "Fragment shader invocation counter lower than expected: found " << fragCounter
6775 << " and expected at least " << minValue;
6776 return tcu::TestStatus::fail(msg.str());
6777 }
6778 }
6779 else if (kFragAtomics)
6780 {
6781 // The expected number of invocations depends on how many draws are performed and the sample count of each one.
6782 // Draws with the test disabled should always result in kFramebufferHeight * kFramebufferWidth invocations.
6783 // Draws with the test enabled should result in at least 1 invocation, maybe more.
6784 uint32_t sampleCount = 0u;
6785
6786 if (kNumIterations == 1u)
6787 {
6788 sampleCount += static_cast<uint32_t>(m_testConfig.getActiveSampleCount());
6789 }
6790 else if (kNumIterations == 2u)
6791 {
6792 for (uint32_t i = 0u; i < kNumIterations; ++i)
6793 {
6794 // Actually varies depending on TWO_DRAWS_STATIC/_DYNAMIC, but does not affect results.
6795 const bool staticDraw = (i == 0u);
6796
6797 if (staticDraw)
6798 sampleCount += static_cast<uint32_t>(m_testConfig.rasterizationSamplesConfig.staticValue);
6799 else
6800 {
6801 sampleCount +=
6802 static_cast<uint32_t>(m_testConfig.rasterizationSamplesConfig.dynamicValue ?
6803 m_testConfig.rasterizationSamplesConfig.dynamicValue.get() :
6804 m_testConfig.rasterizationSamplesConfig.staticValue);
6805 }
6806 }
6807 }
6808 else
6809 {
6810 DE_ASSERT(false);
6811 }
6812
6813 const uint32_t expectedValue = sampleCount * kFramebufferWidth * kFramebufferHeight;
6814
6815 if (fragCounter != expectedValue)
6816 {
6817 std::ostringstream msg;
6818 msg << "Fragment shader invocation count does not match expected value: found " << fragCounter
6819 << " and expected " << expectedValue;
6820 return tcu::TestStatus::fail(msg.str());
6821 }
6822 }
6823
6824 return tcu::TestStatus::pass("Pass");
6825 }
6826
stencilPasses(vk::VkCompareOp op,uint8_t storedValue,uint8_t referenceValue)6827 bool stencilPasses(vk::VkCompareOp op, uint8_t storedValue, uint8_t referenceValue)
6828 {
6829 switch (op)
6830 {
6831 case vk::VK_COMPARE_OP_NEVER:
6832 return false;
6833 case vk::VK_COMPARE_OP_LESS:
6834 return (referenceValue < storedValue);
6835 case vk::VK_COMPARE_OP_EQUAL:
6836 return (referenceValue == storedValue);
6837 case vk::VK_COMPARE_OP_LESS_OR_EQUAL:
6838 return (referenceValue <= storedValue);
6839 case vk::VK_COMPARE_OP_GREATER:
6840 return (referenceValue > storedValue);
6841 case vk::VK_COMPARE_OP_GREATER_OR_EQUAL:
6842 return (referenceValue >= storedValue);
6843 case vk::VK_COMPARE_OP_ALWAYS:
6844 return true;
6845 default:
6846 DE_ASSERT(false);
6847 return false;
6848 }
6849
6850 return false; // Unreachable.
6851 }
6852
stencilResult(vk::VkStencilOp op,uint8_t storedValue,uint8_t referenceValue,uint8_t min,uint8_t max)6853 uint8_t stencilResult(vk::VkStencilOp op, uint8_t storedValue, uint8_t referenceValue, uint8_t min, uint8_t max)
6854 {
6855 uint8_t result = storedValue;
6856
6857 switch (op)
6858 {
6859 case vk::VK_STENCIL_OP_KEEP:
6860 break;
6861 case vk::VK_STENCIL_OP_ZERO:
6862 result = 0;
6863 break;
6864 case vk::VK_STENCIL_OP_REPLACE:
6865 result = referenceValue;
6866 break;
6867 case vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP:
6868 result = ((result == max) ? result : static_cast<uint8_t>(result + 1));
6869 break;
6870 case vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP:
6871 result = ((result == min) ? result : static_cast<uint8_t>(result - 1));
6872 break;
6873 case vk::VK_STENCIL_OP_INVERT:
6874 result = static_cast<uint8_t>(~result);
6875 break;
6876 case vk::VK_STENCIL_OP_INCREMENT_AND_WRAP:
6877 result = ((result == max) ? min : static_cast<uint8_t>(result + 1));
6878 break;
6879 case vk::VK_STENCIL_OP_DECREMENT_AND_WRAP:
6880 result = ((result == min) ? max : static_cast<uint8_t>(result - 1));
6881 break;
6882 default:
6883 DE_ASSERT(false);
6884 break;
6885 }
6886
6887 return result;
6888 }
6889
6890 class TestGroupWithClean : public tcu::TestCaseGroup
6891 {
6892 public:
TestGroupWithClean(tcu::TestContext & testCtx,const char * name)6893 TestGroupWithClean(tcu::TestContext &testCtx, const char *name) : tcu::TestCaseGroup(testCtx, name)
6894 {
6895 }
6896
deinit(void)6897 void deinit(void) override
6898 {
6899 cleanupDevices();
6900 }
6901 };
6902
6903 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
6904
6905 } // anonymous namespace
6906
createExtendedDynamicStateTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)6907 tcu::TestCaseGroup *createExtendedDynamicStateTests(tcu::TestContext &testCtx,
6908 vk::PipelineConstructionType pipelineConstructionType)
6909 {
6910 GroupPtr extendedDynamicStateGroup(new TestGroupWithClean(testCtx, "extended_dynamic_state"));
6911 GroupPtr meshShaderGroup(new tcu::TestCaseGroup(testCtx, "mesh_shader"));
6912
6913 // Auxiliar constants.
6914 const uint32_t kHalfWidthU = kFramebufferWidth / 2u;
6915 const int32_t kHalfWidthI = static_cast<int32_t>(kHalfWidthU);
6916 const float kHalfWidthF = static_cast<float>(kHalfWidthU);
6917 const float kWidthF = static_cast<float>(kFramebufferWidth);
6918 const float kHeightF = static_cast<float>(kFramebufferHeight);
6919
6920 static const struct
6921 {
6922 SequenceOrdering ordering;
6923 std::string name;
6924 } kOrderingCases[] = {
6925 // Dynamic state set after command buffer start
6926 {SequenceOrdering::CMD_BUFFER_START, "cmd_buffer_start"},
6927 // Dynamic state set just before drawing
6928 {SequenceOrdering::BEFORE_DRAW, "before_draw"},
6929 // Dynamic after a pipeline with static states has been bound and before a pipeline with dynamic states has been bound
6930 {SequenceOrdering::BETWEEN_PIPELINES, "between_pipelines"},
6931 // Dynamic state set after both a static-state pipeline and a second dynamic-state pipeline have been bound
6932 {SequenceOrdering::AFTER_PIPELINES, "after_pipelines"},
6933 // Dynamic state set after a dynamic pipeline has been bound and before a second static-state pipeline with the right values has been bound
6934 {SequenceOrdering::BEFORE_GOOD_STATIC, "before_good_static"},
6935 // Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again
6936 {SequenceOrdering::TWO_DRAWS_DYNAMIC, "two_draws_dynamic"},
6937 // Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again
6938 {SequenceOrdering::TWO_DRAWS_STATIC, "two_draws_static"},
6939 };
6940
6941 static const struct
6942 {
6943 bool useMeshShaders;
6944 std::string groupName;
6945 } kMeshShadingCases[] = {
6946 {false, ""},
6947 #ifndef CTS_USES_VULKANSC
6948 {true, "mesh_shader"},
6949 #endif // CTS_USES_VULKANSC
6950 };
6951
6952 static const struct
6953 {
6954 bool bindUnusedMeshShadingPipeline;
6955 std::string nameSuffix;
6956 } kBindUnusedCases[] = {
6957 {false, ""},
6958 #ifndef CTS_USES_VULKANSC
6959 {true, "_bind_unused_ms"},
6960 #endif // CTS_USES_VULKANSC
6961 };
6962
6963 static const std::vector<ColorBlendSubCase> cbSubCases{
6964 ColorBlendSubCase::EQ_ONLY,
6965 ColorBlendSubCase::ALL_CB,
6966 ColorBlendSubCase::ALL_BUT_LO,
6967 };
6968
6969 for (const auto &kMeshShadingCase : kMeshShadingCases)
6970 for (const auto &kOrderingCase : kOrderingCases)
6971 {
6972 if (vk::isConstructionTypeShaderObject(pipelineConstructionType) &&
6973 (kOrderingCase.ordering == SequenceOrdering::BETWEEN_PIPELINES ||
6974 kOrderingCase.ordering == SequenceOrdering::AFTER_PIPELINES))
6975 continue;
6976
6977 const auto &kUseMeshShaders = kMeshShadingCase.useMeshShaders;
6978 const auto &kOrdering = kOrderingCase.ordering;
6979
6980 GroupPtr orderingGroup(new tcu::TestCaseGroup(testCtx, kOrderingCase.name.c_str()));
6981
6982 // Cull modes.
6983 {
6984 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6985 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
6986 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE);
6987 // Dynamically set cull mode to none
6988 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_none", config));
6989 }
6990 {
6991 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6992 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_AND_BACK;
6993 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_BACK_BIT);
6994 // Dynamically set cull mode to back
6995 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_back", config));
6996 }
6997 {
6998 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
6999 // Make triangles look back.
7000 config.meshParams[0].reversed = true;
7001 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7002 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_BIT);
7003 // Dynamically set cull mode to front
7004 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front", config));
7005 }
7006 {
7007 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7008 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_NONE;
7009 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_AND_BACK);
7010 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7011 // Dynamically set cull mode to front and back
7012 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front_and_back", config));
7013 }
7014
7015 // Front face.
7016 {
7017 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7018 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7019 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
7020 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
7021 // Dynamically set front face to clockwise
7022 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw", config));
7023 }
7024 {
7025 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7026 // Pass triangles in clockwise order.
7027 config.meshParams[0].reversed = true;
7028 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7029 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
7030 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
7031 // Dynamically set front face to counter-clockwise
7032 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw", config));
7033 }
7034 {
7035 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7036 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7037 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
7038 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
7039 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7040 // Dynamically set front face to clockwise with a counter-clockwise mesh
7041 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw_reversed", config));
7042 }
7043 {
7044 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7045 // Pass triangles in clockwise order.
7046 config.meshParams[0].reversed = true;
7047 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7048 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
7049 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
7050 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7051 // Dynamically set front face to counter-clockwise with a clockwise mesh
7052 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw_reversed", config));
7053 }
7054
7055 // Rasterizer discard
7056 {
7057 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7058 config.rastDiscardEnableConfig.staticValue = false;
7059 config.rastDiscardEnableConfig.dynamicValue = tcu::just(true);
7060 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7061 // Dynamically disable rasterizer
7062 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "disable_raster", config));
7063 }
7064 {
7065 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7066 config.rastDiscardEnableConfig.staticValue = true;
7067 config.rastDiscardEnableConfig.dynamicValue = tcu::just(false);
7068 // Dynamically enable rasterizer
7069 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "enable_raster", config));
7070 }
7071
7072 // Logic op
7073 {
7074 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7075
7076 config.logicOpEnableConfig.staticValue = true;
7077 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_CLEAR;
7078 config.logicOpConfig.dynamicValue = tcu::just<vk::VkLogicOp>(vk::VK_LOGIC_OP_OR);
7079
7080 // Clear to green, paint in blue, expect cyan due to logic op.
7081 config.meshParams[0].color = kLogicOpTriangleColorFl;
7082 config.clearColorValue = vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(),
7083 kGreenClearColor.z(), kGreenClearColor.w());
7084 config.referenceColor.reset(new SingleColorGenerator(kLogicOpFinalColor));
7085
7086 // Dynamically change logic op to VK_LOGIC_OP_OR
7087 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_or", config));
7088 }
7089
7090 // Logic op enable.
7091 {
7092 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7093
7094 config.logicOpEnableConfig.staticValue = false;
7095 config.logicOpEnableConfig.dynamicValue = true;
7096 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_OR;
7097
7098 // Clear to green, paint in blue, expect cyan due to logic op.
7099 config.meshParams[0].color = kLogicOpTriangleColorFl;
7100 config.clearColorValue = vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(),
7101 kGreenClearColor.z(), kGreenClearColor.w());
7102 config.referenceColor.reset(new SingleColorGenerator(kLogicOpFinalColor));
7103
7104 // Dynamically enable logic OP
7105 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_enable", config));
7106 }
7107 {
7108 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7109
7110 config.logicOpEnableConfig.staticValue = true;
7111 config.logicOpEnableConfig.dynamicValue = false;
7112 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_OR;
7113
7114 // Clear to green, paint in blue, expect cyan due to logic op.
7115 config.meshParams[0].color = kLogicOpTriangleColorFl;
7116 config.clearColorValue = vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(),
7117 kGreenClearColor.z(), kGreenClearColor.w());
7118 config.referenceColor.reset(new SingleColorGenerator(kLogicOpTriangleColor));
7119
7120 // Dynamically disable logic OP
7121 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_disable", config));
7122 }
7123
7124 // Color blend enable.
7125 {
7126 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7127
7128 // The equation picks the old color instead of the new one if blending is enabled.
7129 config.colorBlendEquationConfig.staticValue =
7130 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD,
7131 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
7132
7133 config.colorBlendEnableConfig.staticValue = false;
7134 config.colorBlendEnableConfig.dynamicValue = true;
7135 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7136
7137 // Dynamically enable color blending
7138 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_enable", config));
7139 }
7140 {
7141 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7142
7143 // The equation picks the old color instead of the new one if blending is enabled.
7144 config.colorBlendEquationConfig.staticValue =
7145 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD,
7146 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
7147
7148 config.colorBlendEnableConfig.staticValue = true;
7149 config.colorBlendEnableConfig.dynamicValue = false;
7150
7151 // Dynamically disable color blending
7152 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "color_blend_disable", config));
7153 }
7154
7155 // Color blend equation.
7156 {
7157 for (const auto &cbSubCase : cbSubCases)
7158 {
7159 const bool onlyEq = (cbSubCase == ColorBlendSubCase::EQ_ONLY);
7160 const bool allCBDynamic = (cbSubCase == ColorBlendSubCase::ALL_CB);
7161
7162 // Skip two-draws variants as this will use dynamic logic op and force UNORM color attachments, which would result in illegal operations.
7163 if (allCBDynamic && (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC ||
7164 kOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC))
7165 continue;
7166
7167 for (int j = 0; j < 2; ++j)
7168 {
7169 const bool enableStateValue = (j > 0);
7170
7171 // Do not test statically disabling color blend.
7172 if (onlyEq && !enableStateValue)
7173 continue;
7174
7175 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7176
7177 // The equation picks the old color instead of the new one if blending is enabled.
7178 config.colorBlendEquationConfig.staticValue =
7179 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD,
7180 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
7181
7182 // The dynamic value picks the new color.
7183 config.colorBlendEquationConfig.dynamicValue =
7184 ColorBlendEq(vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD,
7185 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD);
7186
7187 if (!onlyEq)
7188 {
7189 config.colorBlendEnableConfig.staticValue = !enableStateValue;
7190 config.colorBlendEnableConfig.dynamicValue = enableStateValue;
7191 config.colorWriteMaskConfig.staticValue = (0 | 0 | 0 | 0);
7192 config.colorWriteMaskConfig.dynamicValue = (CR | CG | CB | CA);
7193 config.blendConstantsConfig.staticValue = BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
7194 config.blendConstantsConfig.dynamicValue = BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
7195 // Note we don't set a dynamic value for alpha to coverage.
7196
7197 config.useColorWriteEnable = true;
7198 config.colorWriteEnableConfig.staticValue = false;
7199 config.colorWriteEnableConfig.dynamicValue = true;
7200
7201 if (allCBDynamic)
7202 {
7203 config.forceUnormColorFormat = true;
7204 config.logicOpEnableConfig.staticValue = true;
7205 config.logicOpEnableConfig.dynamicValue = false;
7206 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_COPY;
7207 config.logicOpConfig.dynamicValue = vk::VK_LOGIC_OP_CLEAR;
7208 }
7209 }
7210 else
7211 {
7212 config.colorBlendEnableConfig.staticValue = enableStateValue;
7213 }
7214
7215 const std::string stateStr = (enableStateValue ? "enable" : "disable");
7216 const std::string nameSuffix =
7217 (onlyEq ?
7218 "" :
7219 (allCBDynamic ? ("_dynamic_" + stateStr) : ("_dynamic_but_logic_op_" + stateStr)));
7220
7221 // Dynamically set a color equation that picks the mesh color
7222 orderingGroup->addChild(new ExtendedDynamicStateTest(
7223 testCtx, "color_blend_equation_new_color" + nameSuffix, config));
7224
7225 config.colorBlendEquationConfig.swapValues();
7226 config.referenceColor.reset(
7227 new SingleColorGenerator(enableStateValue ? kDefaultClearColor : kDefaultTriangleColor));
7228
7229 // Dynamically set a color equation that picks the clear color
7230 orderingGroup->addChild(new ExtendedDynamicStateTest(
7231 testCtx, "color_blend_equation_old_color" + nameSuffix, config));
7232 }
7233 }
7234 }
7235
7236 // Color blend advanced.
7237 {
7238 for (const auto &cbSubCase : cbSubCases)
7239 {
7240 const bool onlyEq = (cbSubCase == ColorBlendSubCase::EQ_ONLY);
7241 const bool allCBDynamic = (cbSubCase == ColorBlendSubCase::ALL_CB);
7242
7243 // Skip two-draws variants as this will use dynamic logic op and force UNORM color attachments, which would result in illegal operations.
7244 if (allCBDynamic && (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC ||
7245 kOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC))
7246 continue;
7247
7248 for (int j = 0; j < 2; ++j)
7249 {
7250 const bool enableStateValue = (j > 0);
7251
7252 // Do not test statically disabling color blend.
7253 if (onlyEq && !enableStateValue)
7254 continue;
7255
7256 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7257
7258 // This static value picks the old color instead of the new one.
7259 config.colorBlendEquationConfig.staticValue =
7260 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_DARKEN_EXT,
7261 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_DARKEN_EXT);
7262
7263 // The dynamic value picks the new color.
7264 config.colorBlendEquationConfig.dynamicValue = ColorBlendEq(
7265 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_LIGHTEN_EXT,
7266 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_LIGHTEN_EXT);
7267
7268 if (!onlyEq)
7269 {
7270 config.colorBlendEnableConfig.staticValue = !enableStateValue;
7271 config.colorBlendEnableConfig.dynamicValue = enableStateValue;
7272 config.colorWriteMaskConfig.staticValue = (0 | 0 | 0 | 0);
7273 config.colorWriteMaskConfig.dynamicValue = (CR | CG | CB | CA);
7274 config.blendConstantsConfig.staticValue = BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
7275 config.blendConstantsConfig.dynamicValue = BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
7276 // Note we don't set a dynamic value for alpha to coverage.
7277
7278 config.useColorWriteEnable = true;
7279 config.colorWriteEnableConfig.staticValue = false;
7280 config.colorWriteEnableConfig.dynamicValue = true;
7281
7282 if (allCBDynamic)
7283 {
7284 config.forceUnormColorFormat = true;
7285 config.logicOpEnableConfig.staticValue = true;
7286 config.logicOpEnableConfig.dynamicValue = false;
7287 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_COPY;
7288 config.logicOpConfig.dynamicValue = vk::VK_LOGIC_OP_CLEAR;
7289 }
7290 }
7291 else
7292 {
7293 config.colorBlendEnableConfig.staticValue = true;
7294 }
7295
7296 const std::string stateStr = (enableStateValue ? "enable" : "disable");
7297 const std::string nameSuffix =
7298 (onlyEq ?
7299 "" :
7300 (allCBDynamic ? ("_dynamic_" + stateStr) : ("_dynamic_but_logic_op_" + stateStr)));
7301
7302 // Dynamically set an advanced color equation that picks the mesh color
7303 orderingGroup->addChild(new ExtendedDynamicStateTest(
7304 testCtx, "color_blend_equation_advanced_new_color" + nameSuffix, config));
7305
7306 config.colorBlendEquationConfig.swapValues();
7307 config.referenceColor.reset(
7308 new SingleColorGenerator(enableStateValue ? kDefaultClearColor : kDefaultTriangleColor));
7309
7310 // Dynamically set an advanced color equation that picks the clear color
7311 orderingGroup->addChild(new ExtendedDynamicStateTest(
7312 testCtx, "color_blend_equation_advanced_old_color" + nameSuffix, config));
7313 }
7314 }
7315 }
7316
7317 // All color blend as dynamic, including both blend equations.
7318 {
7319 for (int i = 0; i < 2; ++i)
7320 {
7321 for (int j = 0; j < 2; ++j)
7322 {
7323 const bool swapEquation = (j > 0);
7324 const bool picksNew = (!swapEquation);
7325 const auto colorBlendResultName = (picksNew ? "new" : "old");
7326
7327 const bool colorBlendEnableDyn = (i > 0);
7328 const bool colorBlendEnableStatic = !colorBlendEnableDyn;
7329 const auto colorBlendStateName = (colorBlendEnableDyn ? "enabled" : "disabled");
7330
7331 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7332
7333 // We need to apply both color blending equation states instead of deciding if it's advanced or not.
7334 config.colorBlendBoth = true;
7335
7336 config.colorBlendEnableConfig.staticValue = colorBlendEnableStatic;
7337 config.colorBlendEnableConfig.dynamicValue = colorBlendEnableDyn;
7338
7339 config.colorWriteMaskConfig.staticValue = (0 | 0 | 0 | 0);
7340 config.colorWriteMaskConfig.dynamicValue = (CR | CG | CB | CA);
7341 config.blendConstantsConfig.staticValue = BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
7342 config.blendConstantsConfig.dynamicValue = BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
7343
7344 config.useColorWriteEnable = true;
7345 config.colorWriteEnableConfig.staticValue = false;
7346 config.colorWriteEnableConfig.dynamicValue = true;
7347
7348 config.forceUnormColorFormat = true;
7349 config.logicOpEnableConfig.staticValue = true;
7350 config.logicOpEnableConfig.dynamicValue = false;
7351 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_COPY;
7352 config.logicOpConfig.dynamicValue = vk::VK_LOGIC_OP_CLEAR;
7353
7354 // This static value picks the new color.
7355 config.colorBlendEquationConfig.staticValue = ColorBlendEq(
7356 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_LIGHTEN_EXT,
7357 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_LIGHTEN_EXT);
7358
7359 // The dynamic value picks the old color instead of the new one.
7360 config.colorBlendEquationConfig.dynamicValue =
7361 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_DARKEN_EXT,
7362 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_DARKEN_EXT);
7363
7364 if (swapEquation)
7365 config.colorBlendEquationConfig.swapValues();
7366
7367 // Expected result.
7368 const auto expectGeomColor = (!colorBlendEnableDyn || swapEquation);
7369 config.referenceColor.reset(
7370 new SingleColorGenerator(expectGeomColor ? kDefaultTriangleColor : kDefaultClearColor));
7371
7372 const auto testName = std::string("color_blend_all_") + colorBlendStateName + "_" +
7373 colorBlendResultName + "_color";
7374 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7375 }
7376 }
7377 }
7378
7379 // Dynamic color blend equation with dual blending.
7380 {
7381 // Two equations: one picks index 0 and the other one picks index 1.
7382 const struct
7383 {
7384 const ColorBlendEq equation;
7385 const tcu::Vec4 expectedColor;
7386 } dualSrcCases[] = {
7387 {
7388 ColorBlendEq(vk::VK_BLEND_FACTOR_SRC_COLOR, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD,
7389 vk::VK_BLEND_FACTOR_SRC_ALPHA, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD),
7390 // This matches our logic in the frag shader for the first color index.
7391 kOpaqueWhite,
7392 },
7393 {
7394 ColorBlendEq(vk::VK_BLEND_FACTOR_SRC1_COLOR, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD,
7395 vk::VK_BLEND_FACTOR_SRC1_ALPHA, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD),
7396 // This matches our logic in the frag shader for color1.
7397 kDefaultTriangleColor,
7398 },
7399 };
7400
7401 for (size_t dynamicPick = 0u; dynamicPick < de::arrayLength(dualSrcCases); ++dynamicPick)
7402 {
7403 DE_ASSERT(de::arrayLength(dualSrcCases) == size_t{2});
7404
7405 const auto &dynamicEq = dualSrcCases[dynamicPick].equation;
7406 const auto &staticEq = dualSrcCases[size_t{1} - dynamicPick].equation;
7407
7408 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7409
7410 config.dualSrcBlend = true;
7411 config.colorBlendEnableConfig.staticValue = true;
7412 config.colorBlendEquationConfig.staticValue = staticEq;
7413 config.colorBlendEquationConfig.dynamicValue = dynamicEq;
7414 config.referenceColor.reset(new SingleColorGenerator(dualSrcCases[dynamicPick].expectedColor));
7415
7416 const auto indexStr = std::to_string(dynamicPick);
7417 // Dynamically change dual source blending equation to pick color index
7418 orderingGroup->addChild(
7419 new ExtendedDynamicStateTest(testCtx, "color_blend_dual_index_" + indexStr, config));
7420 }
7421 }
7422
7423 // Null color blend pipeline pAttachments pointer with all structure contents as dynamic states.
7424 {
7425 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7426
7427 // The equation picks the old color instead of the new one if blending is enabled.
7428 config.colorBlendEquationConfig.staticValue =
7429 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD,
7430 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
7431
7432 // The dynamic value picks the new color.
7433 config.colorBlendEquationConfig.dynamicValue =
7434 ColorBlendEq(vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD,
7435 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD);
7436
7437 config.colorBlendEnableConfig.staticValue = false;
7438 config.colorBlendEnableConfig.dynamicValue = true;
7439
7440 config.colorWriteMaskConfig.staticValue = (0 | 0 | 0 | 0);
7441 config.colorWriteMaskConfig.dynamicValue = (CR | CG | CB | CA);
7442
7443 config.nullStaticColorBlendAttPtr = true; // What this test is about.
7444
7445 const char *testName = "null_color_blend_att_ptr";
7446 // Set all VkPipelineColorBlendAttachmentState substates as dynamic and pass a null pointer in VkPipelineColorBlendStateCreateInfo::pAttachments
7447 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7448 }
7449
7450 // Full dynamic blending with attachment count set to 0 and/or pAttachments set to null
7451 {
7452 TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
7453
7454 // The equation picks the old color instead of the new one if blending is enabled.
7455 baseConfig.colorBlendEquationConfig.staticValue =
7456 ColorBlendEq(vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD,
7457 vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
7458
7459 // The dynamic value picks the new color.
7460 baseConfig.colorBlendEquationConfig.dynamicValue =
7461 ColorBlendEq(vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD,
7462 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ZERO, vk::VK_BLEND_OP_ADD);
7463
7464 baseConfig.colorBlendEnableConfig.staticValue = false;
7465 baseConfig.colorBlendEnableConfig.dynamicValue = true;
7466
7467 baseConfig.colorWriteMaskConfig.staticValue = (0 | 0 | 0 | 0);
7468 baseConfig.colorWriteMaskConfig.dynamicValue = (CR | CG | CB | CA);
7469
7470 baseConfig.colorBlendAttCnt0 = true;
7471
7472 // VkPipelineColorBlendStateCreateInfo::attachmentCount = 0 and VkPipelineColorBlendStateCreateInfo::pAttachments may not be null
7473 // DS3 advanced blending required
7474 {
7475 TestConfig config(baseConfig);
7476 config.disableAdvBlendingCoherentOps = false;
7477 config.colorBlendBoth = true;
7478
7479 const char *testName = "color_blend_att_count_0_adv";
7480 // Set all VkPipelineColorBlendAttachmentState substates as dynamic and set VkPipelineColorBlendStateCreateInfo::attachmentCount to 0 when DS3 advanced blending is supported
7481 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7482 }
7483
7484 // VkPipelineColorBlendStateCreateInfo::attachmentCount = 0 and VkPipelineColorBlendStateCreateInfo::pAttachments may not be null
7485 // DS3 advanced blending not required
7486 // Advanced blending extension disabled if enabled/supported by default
7487 {
7488 TestConfig config(baseConfig);
7489 config.disableAdvBlendingCoherentOps = true;
7490 config.colorBlendBoth = false;
7491
7492 const char *testName = "color_blend_att_count_0";
7493 // Set all VkPipelineColorBlendAttachmentState substates as dynamic and set VkPipelineColorBlendStateCreateInfo::attachmentCount to 0
7494 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7495 }
7496
7497 // VkPipelineColorBlendStateCreateInfo::attachmentCount = 0 and VkPipelineColorBlendStateCreateInfo::pAttachments = nullptr
7498 // DS3 advanced blending required
7499 {
7500 TestConfig config(baseConfig);
7501 config.disableAdvBlendingCoherentOps = false;
7502 config.nullStaticColorBlendAttPtr = true;
7503
7504 const char *testName = "color_blend_no_attachments";
7505 // Set all VkPipelineColorBlendAttachmentState substates as dynamic and set VkPipelineColorBlendStateCreateInfo::attachmentCount to 0 and VkPipelineColorBlendStateCreateInfo::pAttachments to null
7506 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7507 }
7508 }
7509
7510 // Dynamically enable primitive restart
7511 if (!kUseMeshShaders)
7512 {
7513 for (const auto &bindUnusedCase : kBindUnusedCases)
7514 {
7515 if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7516 continue;
7517
7518 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7519 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7520 config.extraLineRestarts = true;
7521 config.primRestartEnableConfig.staticValue = false;
7522 config.primRestartEnableConfig.dynamicValue = tcu::just(true);
7523 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7524 config.referenceColor.reset(new CenterStripGenerator(kDefaultTriangleColor, kDefaultClearColor));
7525 // Dynamically enable primitiveRestart
7526 orderingGroup->addChild(new ExtendedDynamicStateTest(
7527 testCtx, std::string("prim_restart_enable") + bindUnusedCase.nameSuffix, config));
7528 }
7529 }
7530
7531 // Dynamically change the number of primitive control points
7532 if (!kUseMeshShaders)
7533 {
7534 for (const auto &bindUnusedCase : kBindUnusedCases)
7535 {
7536 if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
7537 continue;
7538
7539 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7540 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7541 config.patchControlPointsConfig.staticValue = 1;
7542 config.patchControlPointsConfig.dynamicValue = 3;
7543 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7544 // Dynamically change patch control points
7545 orderingGroup->addChild(new ExtendedDynamicStateTest(
7546 testCtx, "patch_control_points" + bindUnusedCase.nameSuffix, config));
7547 }
7548
7549 {
7550 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7551 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7552 config.patchControlPointsConfig.staticValue = 1;
7553 config.patchControlPointsConfig.dynamicValue = 3;
7554 config.useExtraDynPCPPipeline = true;
7555
7556 const auto testName = "patch_control_points_extra_pipeline";
7557 // Dynamically change patch control points and draw first with a pipeline using the state and no tessellation shaders
7558 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
7559 }
7560 }
7561
7562 // Test tessellation domain origin.
7563 if (!kUseMeshShaders)
7564 {
7565 {
7566 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7567 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7568 config.patchControlPointsConfig.staticValue = 3;
7569 config.tessDomainOriginConfig.staticValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
7570 config.tessDomainOriginConfig.dynamicValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
7571 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
7572
7573 // Dynamically set the right domain origin to lower left
7574 orderingGroup->addChild(
7575 new ExtendedDynamicStateTest(testCtx, "tess_domain_origin_lower_left", config));
7576 }
7577 {
7578 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7579 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
7580 config.patchControlPointsConfig.staticValue = 3;
7581 config.tessDomainOriginConfig.staticValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
7582 config.tessDomainOriginConfig.dynamicValue = vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
7583 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
7584
7585 // Dynamically set the right domain origin to upper left
7586 orderingGroup->addChild(
7587 new ExtendedDynamicStateTest(testCtx, "tess_domain_origin_upper_left", config));
7588 }
7589 }
7590
7591 // Dynamic topology.
7592 if (!kUseMeshShaders)
7593 {
7594 TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
7595
7596 for (int i = 0; i < 2; ++i)
7597 {
7598 const bool forceGeometryShader = (i > 0);
7599
7600 static const struct
7601 {
7602 vk::VkPrimitiveTopology staticVal;
7603 vk::VkPrimitiveTopology dynamicVal;
7604 } kTopologyCases[] = {
7605 {vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP},
7606 {vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP},
7607 {vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST},
7608 };
7609
7610 for (const auto &kTopologyCase : kTopologyCases)
7611 {
7612 const auto topologyClass = getTopologyClass(kTopologyCase.staticVal);
7613
7614 for (const auto &bindUnusedCase : kBindUnusedCases)
7615 {
7616 if (bindUnusedCase.bindUnusedMeshShadingPipeline &&
7617 kOrdering != SequenceOrdering::CMD_BUFFER_START)
7618 continue;
7619
7620 TestConfig config(baseConfig);
7621 config.forceGeometryShader = forceGeometryShader;
7622 config.topologyConfig.staticValue = kTopologyCase.staticVal;
7623 config.topologyConfig.dynamicValue =
7624 tcu::just<vk::VkPrimitiveTopology>(kTopologyCase.dynamicVal);
7625 config.primRestartEnableConfig.staticValue = (topologyClass == TopologyClass::LINE);
7626 config.patchControlPointsConfig.staticValue = (config.needsTessellation() ? 3u : 1u);
7627 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7628
7629 const std::string className = topologyClassName(topologyClass);
7630 const std::string name = "topology_" + className + (forceGeometryShader ? "_geom" : "") +
7631 bindUnusedCase.nameSuffix;
7632 // Dynamically switch primitive topologies
7633 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, name, config));
7634 }
7635 }
7636 }
7637 }
7638
7639 // Line stipple enable.
7640 {
7641 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7642
7643 config.primRestartEnableConfig.staticValue = true;
7644 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7645 config.lineStippleEnableConfig.staticValue = true;
7646 config.lineStippleEnableConfig.dynamicValue = false;
7647 config.lineStippleParamsConfig.staticValue = LineStippleParams{1u, 0x5555u};
7648
7649 // Dynamically disable line stipple
7650 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_disable", config));
7651
7652 config.lineStippleEnableConfig.swapValues();
7653 config.referenceColor.reset(
7654 new VerticalStripesGenerator(kDefaultTriangleColor, kDefaultClearColor, 1u));
7655
7656 // Dynamycally enable line stipple
7657 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_enable", config));
7658 }
7659
7660 // Line stipple params.
7661 {
7662 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7663
7664 config.primRestartEnableConfig.staticValue = true;
7665 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7666 config.lineStippleEnableConfig.staticValue = true;
7667 config.lineStippleParamsConfig.staticValue = LineStippleParams{1u, 0x5555u};
7668 config.lineStippleParamsConfig.dynamicValue = LineStippleParams{2u, 0x3333u};
7669 config.referenceColor.reset(
7670 new VerticalStripesGenerator(kDefaultTriangleColor, kDefaultClearColor, 4u));
7671
7672 // Dynamically change the line stipple parameters
7673 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_stipple_params", config));
7674 }
7675
7676 // Line rasterization mode.
7677 {
7678 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7679
7680 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7681 config.obliqueLine = true;
7682 config.colorVerificator = verifyTopLeftCornerExactly;
7683 config.lineStippleEnableConfig.staticValue = false;
7684 config.lineStippleParamsConfig.staticValue = LineStippleParams{0u, 0u};
7685 config.lineRasterModeConfig.staticValue = LineRasterizationMode::RECTANGULAR;
7686 config.lineRasterModeConfig.dynamicValue = LineRasterizationMode::BRESENHAM;
7687
7688 // Dynamically set line rasterization mode to bresenham
7689 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_bresenham", config));
7690
7691 config.lineRasterModeConfig.swapValues();
7692 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7693 // Dynamically set line rasterization mode to rectangular
7694 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_rectangular", config));
7695 }
7696 {
7697 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7698
7699 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
7700 config.obliqueLine = true;
7701 config.colorVerificator = verifyTopLeftCornerWithPartialAlpha;
7702 config.lineStippleEnableConfig.staticValue = false;
7703 config.lineStippleParamsConfig.staticValue = LineStippleParams{0u, 0u};
7704 config.lineRasterModeConfig.staticValue = LineRasterizationMode::BRESENHAM;
7705 config.lineRasterModeConfig.dynamicValue = LineRasterizationMode::SMOOTH;
7706
7707 // Dynamically set line rasterization mode to smooth
7708 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "line_raster_mode_smooth", config));
7709 }
7710
7711 // Viewport.
7712 {
7713 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7714 // 2 scissors, bad static single viewport.
7715 config.scissorConfig.staticValue =
7716 ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight),
7717 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
7718 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
7719 config.viewportConfig.dynamicValue = ViewportVec{
7720 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7721 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7722 };
7723 // Dynamically set 2 viewports
7724 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports", config));
7725 }
7726 {
7727 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7728 // Bad static reduced viewport.
7729 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
7730 config.viewportConfig.staticValue =
7731 ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight));
7732 // Dynamically set viewport to cover full framebuffer
7733 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_viewport", config));
7734 }
7735 {
7736 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7737 // 2 scissors (left half, right half), 2 reversed static viewports that need fixing (right, left).
7738 config.scissorConfig.staticValue =
7739 ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight),
7740 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
7741 config.viewportConfig.staticValue = ViewportVec{
7742 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
7743 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
7744 };
7745 config.viewportConfig.dynamicValue =
7746 ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
7747 // Dynamically switch the order with 2 viewports
7748 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch", config));
7749 }
7750 {
7751 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7752 // 2 scissors, reversed dynamic viewports that should result in no drawing taking place.
7753 config.scissorConfig.staticValue =
7754 ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight),
7755 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
7756 config.viewportConfig.staticValue = ViewportVec{
7757 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
7758 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
7759 };
7760 config.viewportConfig.dynamicValue =
7761 ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
7762 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7763 // Dynamically switch the order with 2 viewports resulting in clean image
7764 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch_clean", config));
7765 }
7766
7767 // Scissor.
7768 {
7769 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7770 // 2 viewports, bad static single scissor.
7771 config.viewportConfig.staticValue = ViewportVec{
7772 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7773 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7774 };
7775 config.scissorConfig.staticValue =
7776 ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
7777 config.scissorConfig.dynamicValue = ScissorVec{
7778 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
7779 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
7780 };
7781 // Dynamically set 2 scissors
7782 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors", config));
7783 }
7784 {
7785 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7786 // 1 viewport, bad static single scissor.
7787 config.scissorConfig.staticValue =
7788 ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
7789 config.scissorConfig.dynamicValue =
7790 ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight));
7791 // Dynamically set scissor to cover full framebuffer
7792 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_scissor", config));
7793 }
7794 {
7795 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7796 // 2 viewports, 2 reversed scissors that need fixing.
7797 config.viewportConfig.staticValue = ViewportVec{
7798 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7799 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7800 };
7801 config.scissorConfig.staticValue = ScissorVec{
7802 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
7803 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
7804 };
7805 config.scissorConfig.dynamicValue =
7806 ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
7807 // Dynamically switch the order with 2 scissors
7808 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch", config));
7809 }
7810 {
7811 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7812 // 2 viewports, 2 scissors switched to prevent drawing.
7813 config.viewportConfig.staticValue = ViewportVec{
7814 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7815 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
7816 };
7817 config.scissorConfig.staticValue = ScissorVec{
7818 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
7819 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
7820 };
7821 config.scissorConfig.dynamicValue =
7822 ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
7823 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7824 // Dynamically switch the order with 2 scissors to avoid drawing
7825 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch_clean", config));
7826 }
7827
7828 // Stride.
7829 if (!kUseMeshShaders)
7830 {
7831 struct
7832 {
7833 const VertexGenerator *factory;
7834 const std::string prefix;
7835 } strideCases[] = {
7836 {getVertexWithPaddingGenerator(), "stride"},
7837 {getVertexWithExtraAttributesGenerator(), "large_stride"},
7838 };
7839
7840 for (const auto &strideCase : strideCases)
7841 {
7842 const auto factory = strideCase.factory;
7843 const auto &prefix = strideCase.prefix;
7844 const auto vertexStrides = factory->getVertexDataStrides();
7845 StrideVec halfStrides;
7846
7847 halfStrides.reserve(vertexStrides.size());
7848 for (const auto &stride : vertexStrides)
7849 halfStrides.push_back(stride / 2u);
7850
7851 if (factory == getVertexWithExtraAttributesGenerator() &&
7852 kOrdering == SequenceOrdering::TWO_DRAWS_STATIC)
7853 {
7854 // This case is invalid because it breaks VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the dynamic
7855 // stride being less than the extent of the binding for the second attribute.
7856 continue;
7857 }
7858
7859 for (const auto &bindUnusedCase : kBindUnusedCases)
7860 {
7861 if (bindUnusedCase.bindUnusedMeshShadingPipeline &&
7862 kOrdering != SequenceOrdering::CMD_BUFFER_START)
7863 continue;
7864
7865 {
7866 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
7867 config.strideConfig.staticValue = halfStrides;
7868 config.strideConfig.dynamicValue = vertexStrides;
7869 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7870 // Dynamically set stride
7871 orderingGroup->addChild(
7872 new ExtendedDynamicStateTest(testCtx, prefix + bindUnusedCase.nameSuffix, config));
7873 }
7874 {
7875 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
7876 config.strideConfig.staticValue = halfStrides;
7877 config.strideConfig.dynamicValue = vertexStrides;
7878 config.vertexDataOffset = vertexStrides[0];
7879 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7880 // Dynamically set stride using a nonzero vertex data offset
7881 orderingGroup->addChild(new ExtendedDynamicStateTest(
7882 testCtx, prefix + "_with_offset" + bindUnusedCase.nameSuffix, config));
7883 }
7884 {
7885 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, factory);
7886 config.strideConfig.staticValue = halfStrides;
7887 config.strideConfig.dynamicValue = vertexStrides;
7888 config.vertexDataOffset = vertexStrides[0];
7889 config.vertexDataExtraBytes = config.vertexDataOffset;
7890 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
7891
7892 // 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.
7893 config.referenceColor.reset(
7894 new HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor));
7895 config.meshParams[0].scaleY = 0.5f;
7896 config.meshParams[0].offsetY = -0.5f;
7897
7898 // Dynamically set stride using a nonzero vertex data offset and extra bytes
7899 orderingGroup->addChild(new ExtendedDynamicStateTest(
7900 testCtx, prefix + "_with_offset_and_padding" + bindUnusedCase.nameSuffix, config));
7901 }
7902 }
7903 }
7904
7905 // Dynamic stride of 0
7906 //
7907 // The "two_draws" variants are invalid because the non-zero vertex stride will cause out-of-bounds access
7908 // when drawing more than one vertex.
7909 if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC && kOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC)
7910 {
7911 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders,
7912 getVertexWithExtraAttributesGenerator());
7913 config.strideConfig.staticValue = config.getActiveVertexGenerator()->getVertexDataStrides();
7914 config.strideConfig.dynamicValue = {0};
7915 config.vertexDataOffset = 4;
7916 config.singleVertex = true;
7917 config.singleVertexDrawCount = 6;
7918
7919 // Make the mesh cover the top half only. If the implementation reads data outside the vertex data it should read the
7920 // offscreen vertex and draw something in the bottom half.
7921 config.referenceColor.reset(
7922 new HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor));
7923 config.meshParams[0].scaleY = 0.5f;
7924 config.meshParams[0].offsetY = -0.5f;
7925
7926 // Use strip scale to synthesize a strip from a vertex attribute which remains constant over the draw call.
7927 config.meshParams[0].stripScale = 1.0f;
7928
7929 // Dynamically set zero stride using a nonzero vertex data offset
7930 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "zero_stride_with_offset", config));
7931 }
7932 }
7933
7934 // Depth test enable.
7935 {
7936 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7937 config.depthTestEnableConfig.staticValue = false;
7938 config.depthTestEnableConfig.dynamicValue = tcu::just(true);
7939 // By default, the depth test never passes when enabled.
7940 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
7941 // Dynamically enable depth test
7942 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_enable", config));
7943 }
7944 {
7945 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7946 config.depthTestEnableConfig.staticValue = true;
7947 config.depthTestEnableConfig.dynamicValue = tcu::just(false);
7948 // Dynamically disable depth test
7949 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_disable", config));
7950 }
7951
7952 // Depth write enable.
7953 {
7954 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7955
7956 // Enable depth test and set values so it passes.
7957 config.depthTestEnableConfig.staticValue = true;
7958 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
7959 config.clearDepthValue = 0.5f;
7960 config.meshParams[0].depth = 0.25f;
7961
7962 // Enable writes and expect the mesh value.
7963 config.depthWriteEnableConfig.staticValue = false;
7964 config.depthWriteEnableConfig.dynamicValue = tcu::just(true);
7965 config.expectedDepth = 0.25f;
7966
7967 // Dynamically enable writes to the depth buffer
7968 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_enable", config));
7969 }
7970 {
7971 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7972
7973 // Enable depth test and set values so it passes.
7974 config.depthTestEnableConfig.staticValue = true;
7975 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
7976 config.clearDepthValue = 0.5f;
7977 config.meshParams[0].depth = 0.25f;
7978
7979 // But disable writing dynamically and expect the clear value.
7980 config.depthWriteEnableConfig.staticValue = true;
7981 config.depthWriteEnableConfig.dynamicValue = tcu::just(false);
7982 config.expectedDepth = 0.5f;
7983
7984 // Dynamically disable writes to the depth buffer
7985 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_disable", config));
7986 }
7987
7988 // Depth clamp enable.
7989 {
7990 // Without clamping, the mesh depth fails the depth test after applying the viewport transform.
7991 // With clamping, it should pass thanks to the viewport.
7992 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
7993
7994 config.meshParams[0].depth = 1.5f;
7995 config.clearDepthValue = 0.625f;
7996 config.depthTestEnableConfig.staticValue = true;
7997 config.depthWriteEnableConfig.staticValue = true;
7998 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
7999 config.viewportConfig.staticValue =
8000 ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.0f, 0.5f));
8001 config.expectedDepth = 0.5f;
8002
8003 config.depthClampEnableConfig.staticValue = false;
8004 config.depthClampEnableConfig.dynamicValue = true;
8005
8006 // Dynamically enable depth clamp
8007 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable", config));
8008 }
8009 {
8010 // Reverse situation.
8011 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8012
8013 config.meshParams[0].depth = 1.5f;
8014 config.clearDepthValue = 0.625f;
8015 config.depthTestEnableConfig.staticValue = true;
8016 config.depthWriteEnableConfig.staticValue = true;
8017 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
8018 config.viewportConfig.staticValue =
8019 ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.0f, 0.5f));
8020 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
8021 config.expectedDepth = 0.625f;
8022
8023 config.depthClampEnableConfig.staticValue = true;
8024 config.depthClampEnableConfig.dynamicValue = false;
8025
8026 // Dynamically disable depth clamp
8027 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_disable", config));
8028 }
8029
8030 #if 0
8031 // "If the depth clamping state is changed dynamically, and the pipeline was not created with
8032 // VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT enabled, then depth clipping is enabled when depth clamping is disabled and vice
8033 // versa"
8034 //
8035 // Try to verify the implementation ignores the static depth clipping state. We cannot test the following sequence orderings for this:
8036 // - 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.
8037 // - TWO_DRAWS_DYNAMIC because the first draw may modify the framebuffer with undesired side-effects.
8038 if (kOrdering != SequenceOrdering::BEFORE_GOOD_STATIC && kOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC && kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
8039 {
8040 {
8041 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8042
8043 config.meshParams[0].depth = -0.5f;
8044 config.clearDepthValue = 1.0f;
8045 config.depthTestEnableConfig.staticValue = true;
8046 config.depthWriteEnableConfig.staticValue = true;
8047 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8048 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
8049 config.expectedDepth = 0.5f; // Geometry will be clamped to this value.
8050
8051 config.depthClampEnableConfig.staticValue = false;
8052 config.depthClampEnableConfig.dynamicValue = true;
8053
8054 // Dynamically enable depth clamp while making sure depth clip is disabled
8055 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable_no_clip", config));
8056 }
8057 {
8058 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8059
8060 config.meshParams[0].depth = -0.5f;
8061 config.clearDepthValue = 1.0f;
8062 config.depthTestEnableConfig.staticValue = true;
8063 config.depthWriteEnableConfig.staticValue = true;
8064 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8065 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
8066 config.expectedDepth = 1.0f; // Geometry should be clipped in this case.
8067 config.referenceColor.reset (new SingleColorGenerator(kDefaultClearColor));
8068
8069 // Enable clamping dynamically, with clipping enabled statically.
8070 config.depthClampEnableConfig.staticValue = false;
8071 config.depthClampEnableConfig.dynamicValue = true;
8072 config.depthClipEnableConfig.staticValue = OptBoolean(true);
8073
8074 // Dynamically enable depth clamp while keeping depth clip enabled statically
8075 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_enable_with_clip", config));
8076 }
8077 {
8078 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8079
8080 config.meshParams[0].depth = -0.5f;
8081 config.clearDepthValue = 1.0f;
8082 config.depthTestEnableConfig.staticValue = true;
8083 config.depthWriteEnableConfig.staticValue = true;
8084 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8085 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
8086 config.expectedDepth = 1.0f; // Geometry should be clipped in this case.
8087 config.referenceColor.reset (new SingleColorGenerator(kDefaultClearColor));
8088
8089 config.depthClampEnableConfig.staticValue = true;
8090 config.depthClampEnableConfig.dynamicValue = false;
8091 if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
8092 config.depthClipEnableConfig.staticValue = OptBoolean(true);
8093
8094 // Dynamically disable depth clamp making sure depth clipping is enabled
8095 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_clamp_disable_with_clip", config));
8096 }
8097 // Note: the combination of depth clamp disabled and depth clip disabled cannot be tested because if Zf falls outside
8098 // [Zmin,Zmax] from the viewport, then the value of Zf is undefined during the depth test.
8099 }
8100 #endif
8101
8102 // Polygon mode.
8103 {
8104 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8105
8106 config.polygonModeConfig.staticValue = vk::VK_POLYGON_MODE_FILL;
8107 config.polygonModeConfig.dynamicValue = vk::VK_POLYGON_MODE_POINT;
8108 config.oversizedTriangle = true;
8109 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
8110
8111 // Dynamically set polygon draw mode to points
8112 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "polygon_mode_point", config));
8113 }
8114 {
8115 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8116
8117 config.polygonModeConfig.staticValue = vk::VK_POLYGON_MODE_POINT;
8118 config.polygonModeConfig.dynamicValue = vk::VK_POLYGON_MODE_FILL;
8119 config.oversizedTriangle = true;
8120
8121 // Dynamically set polygon draw mode to fill
8122 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "polygon_mode_fill", config));
8123 }
8124
8125 for (int i = 0; i < 2; ++i)
8126 {
8127 const bool multisample = (i > 0);
8128 const auto activeSampleCount = (multisample ? kMultiSampleCount : kSingleSampleCount);
8129 const auto inactiveSampleCount = (multisample ? kSingleSampleCount : kMultiSampleCount);
8130 const std::string namePrefix = (multisample ? "multi_sample_" : "single_sample_");
8131 const std::string descSuffix = (multisample ? " in multisample mode" : " in single sample mode");
8132
8133 // Sample count.
8134 {
8135 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8136
8137 // The static pipeline would be illegal due to VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853.
8138 if (!config.useStaticPipeline())
8139 {
8140 config.rasterizationSamplesConfig.staticValue = inactiveSampleCount;
8141 config.rasterizationSamplesConfig.dynamicValue = activeSampleCount;
8142 // Dynamically set the rasterization sample count
8143 orderingGroup->addChild(
8144 new ExtendedDynamicStateTest(testCtx, namePrefix + "rasterization_samples", config));
8145 }
8146 }
8147
8148 // Sample mask
8149 {
8150 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8151 config.rasterizationSamplesConfig = activeSampleCount;
8152 config.sampleMaskConfig.staticValue = SampleMaskVec(1u, 0u);
8153 config.sampleMaskConfig.dynamicValue = SampleMaskVec(1u, 0xFFu);
8154
8155 // Dynamically set a sample mask that allows drawing
8156 orderingGroup->addChild(
8157 new ExtendedDynamicStateTest(testCtx, namePrefix + "sample_mask_enable", config));
8158 }
8159 {
8160 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8161 config.rasterizationSamplesConfig = activeSampleCount;
8162 config.sampleMaskConfig.staticValue = SampleMaskVec(1u, 0xFFu);
8163 config.sampleMaskConfig.dynamicValue = SampleMaskVec(1u, 0u);
8164 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
8165
8166 // Dynamically set a sample mask that prevents drawing
8167 orderingGroup->addChild(
8168 new ExtendedDynamicStateTest(testCtx, namePrefix + "sample_mask_disable", config));
8169 }
8170
8171 // Alpha to coverage.
8172 {
8173 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8174
8175 config.rasterizationSamplesConfig = activeSampleCount;
8176 config.meshParams[0].color = kTransparentColor;
8177 config.alphaToCoverageConfig.staticValue = false;
8178 config.alphaToCoverageConfig.dynamicValue = true;
8179 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
8180
8181 // Dynamically enable alpha to coverage
8182 orderingGroup->addChild(
8183 new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_coverage_enable", config));
8184 }
8185 {
8186 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8187
8188 config.rasterizationSamplesConfig = activeSampleCount;
8189 config.meshParams[0].color = kTransparentColor;
8190 config.alphaToCoverageConfig.staticValue = true;
8191 config.alphaToCoverageConfig.dynamicValue = false;
8192 config.referenceColor.reset(new SingleColorGenerator(kTransparentColor));
8193
8194 // Dynamically disable alpha to coverage
8195 orderingGroup->addChild(
8196 new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_coverage_disable", config));
8197 }
8198
8199 // Alpha to one.
8200 {
8201 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8202
8203 config.rasterizationSamplesConfig = activeSampleCount;
8204 config.meshParams[0].color = kTransparentColor;
8205 config.alphaToOneConfig.staticValue = false;
8206 config.alphaToOneConfig.dynamicValue = true;
8207 config.referenceColor.reset(new SingleColorGenerator(kDefaultTriangleColor));
8208
8209 // Dynamically enable alpha to one
8210 orderingGroup->addChild(
8211 new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_one_enable", config));
8212 }
8213 {
8214 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8215
8216 config.rasterizationSamplesConfig = activeSampleCount;
8217 config.meshParams[0].color = kTransparentColor;
8218 config.alphaToOneConfig.staticValue = true;
8219 config.alphaToOneConfig.dynamicValue = false;
8220 config.referenceColor.reset(new SingleColorGenerator(kTransparentColor));
8221
8222 // Dynamically disable alpha to one
8223 orderingGroup->addChild(
8224 new ExtendedDynamicStateTest(testCtx, namePrefix + "alpha_to_one_disable", config));
8225 }
8226 }
8227
8228 // Special sample mask case: make sure the dynamic sample mask count does not overwrite the actual sample mask.
8229 {
8230 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8231
8232 // There's guaranteed support for 1 sample and 4 samples. So the official pipeline sample count will be 1 sample, and
8233 // the one we'll use in the dynamic sample mask call will be 4.
8234 //
8235 // 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
8236 // the implementation into having that one covered by using a Y offset of 0.75.
8237 config.dynamicSampleMaskCount = tcu::just(kMultiSampleCount);
8238 config.sampleMaskConfig.staticValue = SampleMaskVec(1u, 0u);
8239 config.sampleMaskConfig.dynamicValue = SampleMaskVec(1u, 0xFFu);
8240 config.offCenterTriangle = true;
8241 config.offCenterProportion = tcu::Vec2(0.0f, 0.75f);
8242 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultTriangleColor,
8243 kDefaultClearColor, kDefaultClearColor));
8244
8245 // Dynamically set sample mask with slightly different sample count
8246 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_mask_count", config));
8247 }
8248
8249 // Special rasterization samples case: make sure rasterization samples is taken from the dynamic value, but provide a larger mask.
8250 {
8251 const auto kLargeRasterizationSampleCount = vk::VK_SAMPLE_COUNT_64_BIT;
8252 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8253
8254 // We cannot create a static pipeline with the configuration below because the render pass attachments will have a
8255 // sample count of kMultiSampleCount and VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853
8256 // applies here.
8257 if (!config.useStaticPipeline())
8258 {
8259 config.rasterizationSamplesConfig.staticValue = kLargeRasterizationSampleCount;
8260 config.rasterizationSamplesConfig.dynamicValue = kMultiSampleCount;
8261 config.sampleMaskConfig.staticValue = SampleMaskVec{0xFFFFFFF0u, 0xFFFFFFFFu}; // Last 4 bits off.
8262 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
8263
8264 // Dynamically set the rasterization samples to a low value while disabling bits corresponding to the dynamic sample count
8265 orderingGroup->addChild(
8266 new ExtendedDynamicStateTest(testCtx, "large_static_rasterization_samples_off", config));
8267
8268 config.sampleMaskConfig.staticValue = SampleMaskVec{0xFu, 0u}; // Last 4 bits on.
8269 config.referenceColor.reset(new SingleColorGenerator(kDefaultTriangleColor));
8270
8271 // Dynamically set the rasterization samples to a low value while enabling bits corresponding to the dynamic sample count
8272 orderingGroup->addChild(
8273 new ExtendedDynamicStateTest(testCtx, "large_static_rasterization_samples_on", config));
8274 }
8275 }
8276
8277 // Color write mask.
8278 {
8279 const struct
8280 {
8281 vk::VkColorComponentFlags staticVal;
8282 vk::VkColorComponentFlags dynamicVal;
8283 } colorComponentCases[] = {
8284 {(CR | CG | CB | CA), (CR | 0 | 0 | 0)}, {(CR | CG | CB | CA), (0 | CG | 0 | 0)},
8285 {(CR | CG | CB | CA), (0 | 0 | CB | 0)}, {(CR | CG | CB | CA), (0 | 0 | 0 | CA)},
8286 {(CR | CG | CB | CA), (0 | 0 | 0 | 0)}, {(0 | 0 | 0 | 0), (CR | 0 | 0 | 0)},
8287 {(0 | 0 | 0 | 0), (0 | CG | 0 | 0)}, {(0 | 0 | 0 | 0), (0 | 0 | CB | 0)},
8288 {(0 | 0 | 0 | 0), (0 | 0 | 0 | CA)}, {(0 | 0 | 0 | 0), (CR | CG | CB | CA)},
8289 };
8290
8291 for (const auto &colorCompCase : colorComponentCases)
8292 {
8293 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8294
8295 config.clearColorValue = vk::makeClearValueColor(kTransparentClearColor);
8296 config.meshParams[0].color = kOpaqueWhite;
8297 config.colorWriteMaskConfig.staticValue = colorCompCase.staticVal;
8298 config.colorWriteMaskConfig.dynamicValue = colorCompCase.dynamicVal;
8299 config.referenceColor.reset(new SingleColorGenerator(
8300 filterColor(kTransparentClearColor, kOpaqueWhite, colorCompCase.dynamicVal)));
8301
8302 const auto staticCode = componentCodes(colorCompCase.staticVal);
8303 const auto dynamicCode = componentCodes(colorCompCase.dynamicVal);
8304 const auto testName = "color_write_mask_" + staticCode + "_to_" + dynamicCode;
8305 // Dynamically set color write mask
8306 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8307 }
8308 }
8309
8310 // Rasterization stream selection.
8311 if (!kUseMeshShaders)
8312 {
8313 const struct
8314 {
8315 OptRastStream shaderStream; // Stream in the geometry shader.
8316 OptRastStream staticVal; // Static value for the extension struct.
8317 OptRastStream dynamicVal; // Dynamic value for the setter.
8318 const bool expectDraw; // Match between actual stream and active selected value?
8319 const char *name;
8320 } rastStreamCases[] = {
8321 {tcu::just(1u), tcu::Nothing, tcu::just(1u), true, "none_to_one"},
8322 {tcu::just(1u), tcu::just(0u), tcu::just(1u), true, "zero_to_one"},
8323 {tcu::Nothing, tcu::just(1u), tcu::just(0u), true, "one_to_zero"},
8324 {tcu::just(0u), tcu::just(1u), tcu::just(0u), true, "one_to_zero_explicit"},
8325 {tcu::just(0u), tcu::Nothing, tcu::just(1u), false, "none_to_one_mismatch"},
8326 {tcu::just(0u), tcu::just(0u), tcu::just(1u), false, "zero_to_one_mismatch"},
8327 {tcu::Nothing, tcu::Nothing, tcu::just(1u), false, "none_to_one_mismatch_implicit"},
8328 {tcu::Nothing, tcu::just(0u), tcu::just(1u), false, "zero_to_one_mismatch_implicit"},
8329 };
8330
8331 for (const auto &rastStreamCase : rastStreamCases)
8332 {
8333 // In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
8334 // calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
8335 // must be set if the used pipeline contains the dynamic state.
8336 if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC && !static_cast<bool>(rastStreamCase.staticVal))
8337 continue;
8338
8339 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8340
8341 config.rasterizationStreamConfig.staticValue = rastStreamCase.staticVal;
8342 config.rasterizationStreamConfig.dynamicValue = rastStreamCase.dynamicVal;
8343 config.shaderRasterizationStream = rastStreamCase.shaderStream;
8344 config.referenceColor.reset(new SingleColorGenerator(
8345 rastStreamCase.expectDraw ? kDefaultTriangleColor : kDefaultClearColor));
8346
8347 const auto testName = std::string("rasterization_stream_") + rastStreamCase.name;
8348
8349 // Dynamically switch rasterization streams
8350 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8351 }
8352 }
8353
8354 // Provoking vertex mode.
8355 {
8356 const struct
8357 {
8358 OptBoolean staticVal;
8359 OptBoolean dynamicVal;
8360 const char *name;
8361 } provokingVtxCases[] = {
8362 // Dynamically switch provoking vertex mode from none (first) to last
8363 {tcu::Nothing, tcu::just(true), "provoking_vertex_first_to_last_implicit"},
8364 // Dynamically switch provoking vertex mode from first to last
8365 {tcu::just(false), tcu::just(true), "provoking_vertex_first_to_last_explicit"},
8366 // Dynamically switch provoking vertex mode from last to first
8367 {tcu::just(true), tcu::just(false), "provoking_vertex_last_to_first"},
8368 };
8369
8370 for (const auto &provokingVtxCase : provokingVtxCases)
8371 {
8372 // In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
8373 // calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
8374 // must be set if the used pipeline contains the dynamic state.
8375 if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC &&
8376 !static_cast<bool>(provokingVtxCase.staticVal))
8377 continue;
8378
8379 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders,
8380 getProvokingVertexWithPaddingGenerator(provokingVtxCase.dynamicVal.get()));
8381 config.provokingVertexConfig.staticValue = provokingVtxCase.staticVal;
8382 config.provokingVertexConfig.dynamicValue = provokingVtxCase.dynamicVal;
8383 config.oversizedTriangle = true;
8384
8385 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, provokingVtxCase.name, config));
8386 }
8387 }
8388
8389 // Depth clip negative one to one.
8390 {
8391 const struct
8392 {
8393 OptBoolean staticVal;
8394 OptBoolean dynamicVal;
8395 const char *name;
8396 } negativeOneToOneCases[] = {
8397 // Dynamically switch negative one to one mode from none (false) to true
8398 {tcu::Nothing, tcu::just(true), "negative_one_to_one_false_to_true_implicit"},
8399 // Dynamically switch negative one to one mode from false to true
8400 {tcu::just(false), tcu::just(true), "negative_one_to_one_false_to_true_explicit"},
8401 // Dynamically switch negative one to one mode from true to false
8402 {tcu::just(true), tcu::just(false), "negative_one_to_one_true_to_false"},
8403 };
8404
8405 for (const auto &negOneToOneCase : negativeOneToOneCases)
8406 {
8407 // In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
8408 // calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
8409 // must be set if the used pipeline contains the dynamic state.
8410 if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC &&
8411 !static_cast<bool>(negOneToOneCase.staticVal))
8412 continue;
8413
8414 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8415 config.negativeOneToOneConfig.staticValue = negOneToOneCase.staticVal;
8416 config.negativeOneToOneConfig.dynamicValue = negOneToOneCase.dynamicVal;
8417
8418 // Enable depth test and set values so it passes.
8419 config.depthTestEnableConfig.staticValue = true;
8420 config.depthWriteEnableConfig.staticValue = true;
8421 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
8422 config.meshParams[0].depth = 0.5f;
8423 config.expectedDepth = (config.getActiveNegativeOneToOneValue() ? 0.75f : 0.5f);
8424
8425 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, negOneToOneCase.name, config));
8426 }
8427 }
8428
8429 // Depth clip enable.
8430 {
8431 const struct
8432 {
8433 OptBoolean staticVal;
8434 OptBoolean dynamicVal;
8435 const char *name;
8436 } depthClipEnableCases[] = {
8437 // Dynamically switch negative one to one mode from none (true) to false
8438 {tcu::Nothing, tcu::just(false), "depth_clip_enable_true_to_false_implicit"},
8439 // Dynamically switch negative one to one mode from true to false
8440 {tcu::just(true), tcu::just(false), "depth_clip_enable_true_to_false_explicit"},
8441 // Dynamically switch negative one to one mode from false to true
8442 {tcu::just(false), tcu::just(true), "depth_clip_enable_true_to_false"},
8443 };
8444
8445 for (const auto &depthClipEnableCase : depthClipEnableCases)
8446 {
8447 // In TWO_DRAWS_STATIC sequence ordering, the bad dynamic value may be tcu::Nothing, which is equivalent to not
8448 // calling the state-setting function, but the pipeline will be used to draw. This is illegal. The dynamic value
8449 // must be set if the used pipeline contains the dynamic state.
8450 if (kOrdering == SequenceOrdering::TWO_DRAWS_STATIC &&
8451 !static_cast<bool>(depthClipEnableCase.staticVal))
8452 continue;
8453
8454 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8455 config.depthClipEnableConfig.staticValue = depthClipEnableCase.staticVal;
8456 config.depthClipEnableConfig.dynamicValue = depthClipEnableCase.dynamicVal;
8457
8458 const bool depthClipActive = config.getActiveDepthClipEnable();
8459
8460 // Enable depth test and set values so it passes.
8461 config.depthTestEnableConfig.staticValue = true;
8462 config.depthWriteEnableConfig.staticValue = true;
8463 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
8464 config.meshParams[0].depth = -0.5f;
8465 config.viewportConfig.staticValue =
8466 ViewportVec(1u, vk::makeViewport(0.0f, 0.0f, kWidthF, kHeightF, 0.5f, 1.0f));
8467 config.expectedDepth = (depthClipActive ? 1.0f : 0.25f);
8468 config.referenceColor.reset(
8469 new SingleColorGenerator(depthClipActive ? kDefaultClearColor : kDefaultTriangleColor));
8470
8471 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, depthClipEnableCase.name, config));
8472 }
8473 }
8474
8475 // Sample locations enablement.
8476 {
8477 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8478 config.rasterizationSamplesConfig = kMultiSampleCount;
8479 config.offCenterTriangle = true;
8480 config.offCenterProportion = tcu::Vec2(0.90625f, 0.90625f);
8481
8482 // Push sample locations towards the bottom right corner so they're able to sample the off-center triangle.
8483 config.sampleLocations = tcu::Vec2(1.0f, 1.0f);
8484
8485 config.sampleLocationsEnableConfig.staticValue = false;
8486 config.sampleLocationsEnableConfig.dynamicValue = true;
8487
8488 // Dynamically enable sample locations
8489 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_locations_enable", config));
8490
8491 config.sampleLocationsEnableConfig.swapValues();
8492 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor,
8493 kDefaultClearColor, kDefaultClearColor));
8494
8495 // Dynamically disable sample locations
8496 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_locations_disable", config));
8497 }
8498
8499 // Coverage to color enable.
8500 {
8501 for (int i = 0; i < 2; ++i)
8502 {
8503 const bool multisample = (i > 0);
8504
8505 for (int j = 0; j < 2; ++j)
8506 {
8507 const bool covToColor = (j > 0);
8508 const uint32_t referenceRed =
8509 ((covToColor ? (multisample ? 15u : 1u) : 48u /*matches meshParams[0].color*/));
8510
8511 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8512
8513 config.oversizedTriangle = true; // This avoids partial coverages in fragments.
8514 config.rasterizationSamplesConfig = (multisample ? kMultiSampleCount : kSingleSampleCount);
8515 config.coverageToColorEnableConfig.staticValue = !covToColor;
8516 config.coverageToColorEnableConfig.dynamicValue = covToColor;
8517 config.meshParams[0].color =
8518 tcu::Vec4(48.0f, 0.0f, 0.0f, 1.0f); // Distinct value, does not match any coverage mask.
8519 config.referenceColor.reset(new SingleColorGenerator(tcu::UVec4(referenceRed, 0u, 0u, 1u)));
8520
8521 const std::string finalState = (covToColor ? "enable" : "disable");
8522 const auto testName =
8523 "coverage_to_color_" + finalState + "_" + (multisample ? "multisample" : "single_sample");
8524
8525 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8526 }
8527 }
8528 }
8529
8530 // Coverage to color location.
8531 {
8532 for (int i = 0; i < 2; ++i)
8533 {
8534 const bool multisample = (i > 0);
8535
8536 for (int j = 0; j < 2; ++j)
8537 {
8538 const bool locationLast = (j > 0);
8539 const uint32_t colorAttCount = 4u;
8540 const uint32_t covToColorLoc = (locationLast ? colorAttCount - 1u : 0u);
8541 const uint32_t referenceRed =
8542 ((locationLast ? (multisample ? 15u : 1u) : 48u /*matches meshParams[0].color*/));
8543
8544 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8545
8546 config.oversizedTriangle = true; // This avoids partial coverages in fragments.
8547 config.rasterizationSamplesConfig = (multisample ? kMultiSampleCount : kSingleSampleCount);
8548 config.colorAttachmentCount = colorAttCount;
8549 config.coverageToColorEnableConfig.staticValue = true;
8550 config.coverageToColorLocationConfig.staticValue = (locationLast ? 0u : colorAttCount - 1u);
8551 config.coverageToColorLocationConfig.dynamicValue = covToColorLoc;
8552 config.meshParams[0].color =
8553 tcu::Vec4(48.0f, 0.0f, 0.0f, 1.0f); // Distinct value, does not match any coverage mask.
8554 config.referenceColor.reset(new SingleColorGenerator(tcu::UVec4(referenceRed, 0u, 0u, 1u)));
8555
8556 const auto locName = std::to_string(covToColorLoc);
8557 const auto testName = "coverage_to_color_location_" + locName + "_" +
8558 (multisample ? "multisample" : "single_sample");
8559 // Dynamically enable coverage to color in location
8560 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8561 }
8562 }
8563 }
8564
8565 #ifndef CTS_USES_VULKANSC
8566 // Coverage modulation mode.
8567 {
8568 const struct
8569 {
8570 vk::VkCoverageModulationModeNV staticVal;
8571 vk::VkCoverageModulationModeNV dynamicVal;
8572 tcu::Vec4 partialCovFactor; // This will match the expected coverage proportion. See below.
8573 const char *name;
8574 } modulationModeCases[] = {
8575 {vk::VK_COVERAGE_MODULATION_MODE_NONE_NV, vk::VK_COVERAGE_MODULATION_MODE_RGB_NV,
8576 tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f), "rgb"},
8577 {vk::VK_COVERAGE_MODULATION_MODE_NONE_NV, vk::VK_COVERAGE_MODULATION_MODE_ALPHA_NV,
8578 tcu::Vec4(1.0f, 1.0f, 1.0f, 0.25f), "alpha"},
8579 {vk::VK_COVERAGE_MODULATION_MODE_NONE_NV, vk::VK_COVERAGE_MODULATION_MODE_RGBA_NV,
8580 tcu::Vec4(0.25f, 0.25f, 0.25f, 0.25f), "rgba"},
8581 {vk::VK_COVERAGE_MODULATION_MODE_RGBA_NV, vk::VK_COVERAGE_MODULATION_MODE_NONE_NV,
8582 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), "none"},
8583 };
8584
8585 for (const auto &modulationModeCase : modulationModeCases)
8586 {
8587 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8588
8589 config.coverageModulation = true;
8590 config.rasterizationSamplesConfig = kMultiSampleCount;
8591 config.colorSampleCount = kSingleSampleCount;
8592
8593 // With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8594 // * Leave the corner pixel uncovered.
8595 // * Cover the top border with sample 3 (1/4 the samples = 0.25).
8596 // * Cover the left border with sample 1 (1/4 the samples = 0.25).
8597 config.offCenterProportion = tcu::Vec2(0.6875f, 0.6875f);
8598 config.offCenterTriangle = true;
8599
8600 config.coverageModulationModeConfig.staticValue = modulationModeCase.staticVal;
8601 config.coverageModulationModeConfig.dynamicValue = modulationModeCase.dynamicVal;
8602
8603 const auto &partialCoverageColor = kDefaultTriangleColor * modulationModeCase.partialCovFactor;
8604 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, partialCoverageColor,
8605 kDefaultClearColor, partialCoverageColor));
8606
8607 const auto testName = std::string("coverage_modulation_mode_") + modulationModeCase.name;
8608 // Dynamically set coverage modulation mode
8609 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, config));
8610 }
8611 }
8612
8613 // Coverage modulation table enable.
8614 {
8615 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8616
8617 config.coverageModulation = true;
8618 config.rasterizationSamplesConfig = kMultiSampleCount;
8619 config.colorSampleCount = kSingleSampleCount;
8620
8621 // With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8622 // * Leave the corner pixel uncovered.
8623 // * Cover the top border with sample 3 (1/4 the samples = 0.25).
8624 // * Cover the left border with sample 1 (1/4 the samples = 0.25).
8625 config.offCenterProportion = tcu::Vec2(0.6875f, 0.6875f);
8626 config.offCenterTriangle = true;
8627
8628 const CovModTableVec table{0.75f, 1.0f, 1.0f, 1.0f};
8629 config.coverageModulationModeConfig.staticValue = vk::VK_COVERAGE_MODULATION_MODE_RGB_NV;
8630 config.coverageModTableConfig.staticValue = table;
8631
8632 config.coverageModTableEnableConfig.staticValue = false;
8633 config.coverageModTableEnableConfig.dynamicValue = true;
8634
8635 const auto tableCoverFactor = tcu::Vec4(0.75f, 0.75f, 0.75f, 1.0f);
8636 const auto &tablePartialCoverageColor = kDefaultTriangleColor * tableCoverFactor;
8637
8638 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, tablePartialCoverageColor,
8639 kDefaultClearColor, tablePartialCoverageColor));
8640
8641 // Dynamically enable coverage modulation table
8642 orderingGroup->addChild(
8643 new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_enable", config));
8644
8645 // Reverse situation, fall back to the default modulation factor.
8646 config.coverageModTableEnableConfig.swapValues();
8647 const auto noTableCoverFactor = tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f);
8648 const auto &noTablePartialCoverageColor = kDefaultTriangleColor * noTableCoverFactor;
8649 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor,
8650 noTablePartialCoverageColor, kDefaultClearColor,
8651 noTablePartialCoverageColor));
8652
8653 // Dynamically disable coverage modulation table
8654 orderingGroup->addChild(
8655 new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_disable", config));
8656 }
8657
8658 // Coverage modulation table.
8659 {
8660 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8661
8662 config.coverageModulation = true;
8663 config.rasterizationSamplesConfig = kMultiSampleCount;
8664 config.colorSampleCount = kSingleSampleCount;
8665
8666 // With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8667 // * Cover the corner pixel with 1 sample (0.25).
8668 // * Cover the top border with 2 samples (0.5).
8669 // * Cover the left border with 2 samples (0.5).
8670 config.offCenterProportion = tcu::Vec2(0.5f, 0.5f);
8671 config.offCenterTriangle = true;
8672
8673 config.coverageModulationModeConfig.staticValue = vk::VK_COVERAGE_MODULATION_MODE_RGB_NV;
8674 config.coverageModTableEnableConfig.staticValue = true;
8675
8676 // corner border unused main
8677 const CovModTableVec goodTable{0.75f, 0.25f, 0.0f, 0.5f};
8678 const CovModTableVec badTable{0.5f, 0.75f, 1.0f, 0.25f};
8679
8680 config.coverageModTableConfig.staticValue = badTable;
8681 config.coverageModTableConfig.dynamicValue = goodTable;
8682
8683 // VK_COVERAGE_MODULATION_MODE_RGB_NV, factors for RGB according to goodTable, alpha untouched.
8684 const auto cornerFactor = tcu::Vec4(0.75f, 0.75f, 0.75f, 1.0f);
8685 const auto borderFactor = tcu::Vec4(0.25f, 0.25f, 0.25f, 1.0f);
8686 const auto mainFactor = tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f);
8687
8688 const auto &cornerColor = kDefaultTriangleColor * cornerFactor;
8689 const auto &borderColor = kDefaultTriangleColor * borderFactor;
8690 const auto &mainColor = kDefaultTriangleColor * mainFactor;
8691
8692 config.referenceColor.reset(
8693 new TopLeftBorderGenerator(mainColor, borderColor, cornerColor, borderColor));
8694
8695 // Dynamically change coverage modulation table
8696 orderingGroup->addChild(
8697 new ExtendedDynamicStateTest(testCtx, "coverage_modulation_table_change", config));
8698 }
8699
8700 // Coverage reduction mode.
8701 {
8702 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8703
8704 config.coverageReduction = true;
8705 config.rasterizationSamplesConfig = kMultiSampleCount;
8706 config.colorSampleCount = kSingleSampleCount;
8707
8708 // With VK_SAMPLE_COUNT_4_BIT and the standard sample locations, this pixel offset will:
8709 // * Leave the corner pixel uncovered.
8710 // * Cover the top border with sample 3 (1/4 the samples = 0.25).
8711 // * Cover the left border with sample 1 (1/4 the samples = 0.25).
8712 config.offCenterProportion = tcu::Vec2(0.6875f, 0.6875f);
8713 config.offCenterTriangle = true;
8714
8715 config.coverageReductionModeConfig.staticValue = vk::VK_COVERAGE_REDUCTION_MODE_MERGE_NV;
8716 config.coverageReductionModeConfig.dynamicValue = vk::VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV;
8717
8718 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor,
8719 kDefaultClearColor, kDefaultClearColor));
8720 // Dynamically set coverage reduction truncate mode
8721 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_reduction_truncate", config));
8722
8723 // In merge mode, the only pixel without coverage should be the corner. However, the spec is a bit ambiguous in this
8724 // case:
8725 //
8726 // VK_COVERAGE_REDUCTION_MODE_MERGE_NV specifies that each color sample will be associated with an
8727 // implementation-dependent subset of samples in the pixel coverage. If any of those associated samples are covered,
8728 // the color sample is covered.
8729 //
8730 // We cannot be 100% sure the single color sample will be associated with the whole set of 4 rasterization samples, but
8731 // the test appears to pass in existing HW.
8732 config.coverageReductionModeConfig.swapValues();
8733 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultTriangleColor,
8734 kDefaultClearColor, kDefaultTriangleColor));
8735 // Dynamically set coverage reduction merge mode
8736 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "coverage_reduction_merge", config));
8737 }
8738
8739 // Viewport swizzle.
8740 {
8741 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8742
8743 config.viewportSwizzle = true;
8744 config.oversizedTriangle = true;
8745 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
8746
8747 const vk::VkViewportSwizzleNV idSwizzle{
8748 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
8749 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
8750 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
8751 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
8752 };
8753
8754 const vk::VkViewportSwizzleNV
8755 yxSwizzle // Switches Y and X coordinates, makes the oversized triangle clockwise.
8756 {
8757 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, // <--
8758 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, // <--
8759 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
8760 vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
8761 };
8762
8763 config.viewportSwizzleConfig.staticValue = ViewportSwzVec(1u, idSwizzle);
8764 config.viewportSwizzleConfig.dynamicValue = ViewportSwzVec(1u, yxSwizzle);
8765 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
8766
8767 // Dynamically set a viewport swizzle with X and Y switched around
8768 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_swizzle_yx", config));
8769
8770 config.viewportSwizzleConfig.swapValues();
8771 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
8772 // Dynamically set the viewport identity swizzle
8773 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "viewport_swizzle_xy", config));
8774 }
8775
8776 // Shading rate image enable.
8777 // VK_NV_shading_rate_image is disabled when using shader objects due to interaction with VK_KHR_fragment_shading_rate
8778 if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
8779 {
8780 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8781
8782 for (int i = 0; i < 2; ++i)
8783 {
8784 const bool sriEnable = (i > 0);
8785 const std::string enableStr = (sriEnable ? "enable" : "disable");
8786
8787 config.shadingRateImage = true;
8788 config.shadingRateImageEnableConfig.staticValue = !sriEnable;
8789 config.shadingRateImageEnableConfig.dynamicValue = sriEnable;
8790 config.referenceColor.reset(
8791 new SingleColorGenerator(sriEnable ? kDefaultClearColor : kDefaultTriangleColor));
8792
8793 orderingGroup->addChild(
8794 new ExtendedDynamicStateTest(testCtx, "shading_rate_image_" + enableStr, config));
8795 }
8796 }
8797
8798 // Viewport W Scaling enable.
8799 {
8800 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8801
8802 for (int i = 0; i < 2; ++i)
8803 {
8804 const bool wScalingEnable = (i > 0);
8805 const std::string enableStr = (wScalingEnable ? "enable" : "disable");
8806
8807 config.colorVerificator = verifyTopLeftCornerExactly;
8808 config.viewportWScaling = true;
8809 config.viewportWScalingEnableConfig.staticValue = !wScalingEnable;
8810 config.viewportWScalingEnableConfig.dynamicValue = wScalingEnable;
8811 config.referenceColor.reset(
8812 new SingleColorGenerator(wScalingEnable ? kDefaultClearColor : kDefaultTriangleColor));
8813
8814 orderingGroup->addChild(
8815 new ExtendedDynamicStateTest(testCtx, "viewport_w_scaling_" + enableStr, config));
8816 }
8817 }
8818
8819 // Representative fragment test state.
8820 {
8821 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8822
8823 for (int i = 0; i < 2; ++i)
8824 {
8825 const bool reprFragTestEnable = (i > 0);
8826 const std::string enableStr = (reprFragTestEnable ? "enable" : "disable");
8827
8828 config.depthTestEnableConfig.staticValue = true;
8829 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
8830 config.colorWriteMaskConfig.staticValue = 0u; // Disable color writes.
8831 config.oversizedTriangle = true;
8832 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
8833
8834 config.representativeFragmentTest = true;
8835 config.reprFragTestEnableConfig.staticValue = !reprFragTestEnable;
8836 config.reprFragTestEnableConfig.dynamicValue = reprFragTestEnable;
8837
8838 orderingGroup->addChild(
8839 new ExtendedDynamicStateTest(testCtx, "repr_frag_test_" + enableStr, config));
8840 }
8841 }
8842 #endif // CTS_USES_VULKANSC
8843
8844 // Conservative rasterization mode.
8845 {
8846 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8847 config.offCenterTriangle = true;
8848
8849 // Single-sampling at the pixel center should not cover this, but overestimation should result in coverage.
8850 config.offCenterProportion = tcu::Vec2(0.75f, 0.75f);
8851 config.extraPrimitiveOverEstConfig.staticValue = 0.0f;
8852 config.conservativeRasterModeConfig.staticValue = vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
8853 config.conservativeRasterModeConfig.dynamicValue =
8854 vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
8855
8856 // Dynamically set conservative rasterization mode to overestimation
8857 orderingGroup->addChild(
8858 new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_overestimate", config));
8859
8860 config.conservativeRasterModeConfig.swapValues();
8861 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor,
8862 kDefaultClearColor, kDefaultClearColor));
8863 // Dynamically set conservative rasterization mode to disabled
8864 orderingGroup->addChild(
8865 new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_disabled", config));
8866 }
8867 {
8868 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8869 config.offCenterTriangle = true;
8870
8871 // Single-sampling at the pixel center should cover this, but underestimation should result in lack of coverage.
8872 config.offCenterProportion = tcu::Vec2(0.25f, 0.25f);
8873 config.extraPrimitiveOverEstConfig.staticValue = 0.0f;
8874 config.conservativeRasterModeConfig.staticValue = vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
8875 config.conservativeRasterModeConfig.dynamicValue =
8876 vk::VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT;
8877 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor,
8878 kDefaultClearColor, kDefaultClearColor));
8879
8880 // Dynamically set conservative rasterization mode to underestimation
8881 orderingGroup->addChild(
8882 new ExtendedDynamicStateTest(testCtx, "conservative_rasterization_mode_underestimate", config));
8883 }
8884
8885 // Extra primitive overestimation size.
8886 // Notes as of 2022-08-12 and gpuinfo.org:
8887 // * primitiveOverestimationSize is typically 0.0, 0.001953125 or 0.00195313 (i.e. very small).
8888 // * maxExtraPrimitiveOverestimationSize is typically 0.0 or 0.75 (no other values).
8889 // * extraPrimitiveOverestimationSizeGranularity is typically 0.0 or 0.25 (no other values).
8890 {
8891 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8892 config.offCenterTriangle = true;
8893
8894 // Move the triangle by more than one pixel, then use an extra overestimation of 0.75 to cover the border pixels too.
8895 config.offCenterProportion = tcu::Vec2(1.125f, 1.125f);
8896 config.maxPrimitiveOverestimationSize =
8897 0.5f; // Otherwise the base overestimation size will be enough. This should never trigger.
8898 config.conservativeRasterModeConfig.staticValue =
8899 vk::VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
8900 config.extraPrimitiveOverEstConfig.staticValue = 0.0f;
8901 config.extraPrimitiveOverEstConfig.dynamicValue =
8902 0.75f; // Large enough to reach the center of the border pixel.
8903
8904 // Dynamically set the extra overestimation size to a large value
8905 orderingGroup->addChild(
8906 new ExtendedDynamicStateTest(testCtx, "extra_overestimation_size_large", config));
8907
8908 config.extraPrimitiveOverEstConfig.swapValues();
8909 config.referenceColor.reset(new TopLeftBorderGenerator(kDefaultTriangleColor, kDefaultClearColor,
8910 kDefaultClearColor, kDefaultClearColor));
8911
8912 // Dynamically set the extra overestimation size to zero
8913 orderingGroup->addChild(
8914 new ExtendedDynamicStateTest(testCtx, "extra_overestimation_size_none", config));
8915 }
8916
8917 // Depth bias enable with static or dynamic depth bias parameters.
8918 {
8919 const DepthBiasParams kAlternativeDepthBiasParams = {2e7f, 0.25f};
8920
8921 for (int dynamicBiasIter = 0; dynamicBiasIter < 2; ++dynamicBiasIter)
8922 {
8923 const bool useDynamicBias = (dynamicBiasIter > 0);
8924
8925 {
8926 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8927
8928 // Enable depth test and write 1.0f
8929 config.depthTestEnableConfig.staticValue = true;
8930 config.depthWriteEnableConfig.staticValue = true;
8931 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8932 // Clear depth buffer to 0.25f
8933 config.clearDepthValue = 0.25f;
8934 // Write depth to 0.5f
8935 config.meshParams[0].depth = 0.5f;
8936
8937 // Enable dynamic depth bias and expect the depth value to be clamped to 0.75f based on depthBiasConstantFactor and depthBiasClamp
8938 if (useDynamicBias)
8939 {
8940 config.depthBiasConfig.staticValue = kNoDepthBiasParams;
8941 config.depthBiasConfig.dynamicValue = kAlternativeDepthBiasParams;
8942 }
8943 else
8944 {
8945 config.depthBiasConfig.staticValue = kAlternativeDepthBiasParams;
8946 }
8947
8948 config.depthBiasEnableConfig.staticValue = false;
8949 config.depthBiasEnableConfig.dynamicValue = tcu::just(true);
8950 config.expectedDepth = 0.75f;
8951
8952 std::string caseName = "depth_bias_enable";
8953
8954 if (useDynamicBias)
8955 {
8956 caseName += "_dynamic_bias_params";
8957 }
8958
8959 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
8960 }
8961 {
8962 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
8963
8964 // Enable depth test and write 1.0f
8965 config.depthTestEnableConfig.staticValue = true;
8966 config.depthWriteEnableConfig.staticValue = true;
8967 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
8968 // Clear depth buffer to 0.25f
8969 config.clearDepthValue = 0.25f;
8970 // Write depth to 0.5f
8971 config.meshParams[0].depth = 0.5f;
8972
8973 // Disable dynamic depth bias and expect the depth value to remain at 0.5f based on written value
8974 if (useDynamicBias)
8975 {
8976 config.depthBiasConfig.staticValue = kNoDepthBiasParams;
8977 config.depthBiasConfig.dynamicValue = kAlternativeDepthBiasParams;
8978 }
8979 else
8980 {
8981 config.depthBiasConfig.staticValue = kAlternativeDepthBiasParams;
8982 }
8983
8984 config.depthBiasEnableConfig.staticValue = true;
8985 config.depthBiasEnableConfig.dynamicValue = tcu::just(false);
8986 config.expectedDepth = 0.5f;
8987
8988 std::string caseName = "depth_bias_disable";
8989
8990 if (useDynamicBias)
8991 {
8992 caseName += "_dynamic_bias_params";
8993 }
8994
8995 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
8996 }
8997 }
8998 }
8999
9000 #ifndef CTS_USES_VULKANSC
9001 // Depth bias representation info.
9002 {
9003 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9004
9005 // Enable depth test and writes.
9006 config.depthTestEnableConfig.staticValue = true;
9007 config.depthWriteEnableConfig.staticValue = true;
9008 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
9009 config.clearDepthValue = 0.0f;
9010 config.meshParams[0].depth = 0.125f;
9011 const double targetBias = 0.5f;
9012 config.expectedDepth = 0.625f; // mesh depth + target bias
9013
9014 vk::VkDepthBiasRepresentationInfoEXT depthBiasReprInfo = vk::initVulkanStructure();
9015 depthBiasReprInfo.depthBiasRepresentation =
9016 vk::VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT;
9017 depthBiasReprInfo.depthBiasExact = VK_TRUE;
9018 config.depthBiasReprInfo = depthBiasReprInfo;
9019 config.neededDepthChannelClass = tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
9020
9021 // We will choose a format with floating point representation, but force a UNORM exact depth bias representation.
9022 // 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).
9023 // To reach our target bias, the constant factor must be calculated based on it and the value of R.
9024 //
9025 // If the VkDepthBiasRepresentationInfoEXT is not taken into account, the value of R would be 2^(E-N), such that:
9026 // E is the maximum exponent in the range of Z values that the primitive uses (-3 for our mesh depth of 0.125).
9027 // N is the number of mantissa bits in the floating point format (23 in our case)
9028 // R would be wrongly calculated as 2^(-26) (1/4th of the intended value).
9029 const double minR = 1.0 / static_cast<double>(1u << 24u);
9030 const double constantFactor = targetBias / minR;
9031
9032 const DepthBiasParams kPositiveBias{static_cast<float>(constantFactor), 0.0f};
9033 config.depthBiasEnableConfig.staticValue = true;
9034 config.depthBiasConfig.staticValue = kNoDepthBiasParams;
9035 config.depthBiasConfig.dynamicValue = kPositiveBias;
9036 config.extraDepthThreshold = static_cast<float>(minR);
9037
9038 const char *caseName = "depth_bias_repr_info";
9039 // Dynamically set the depth bias representation information
9040 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
9041 }
9042 {
9043 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9044
9045 // Enable depth test and writes.
9046 config.depthTestEnableConfig.staticValue = true;
9047 config.depthWriteEnableConfig.staticValue = true;
9048 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
9049 config.clearDepthValue = 0.25f; // Clear depth buffer to 0.25.
9050 config.meshParams[0].depth = 0.5f; // Set mesh depth to 0.5 as a base.
9051
9052 // Enable dynamic depth bias to add a 0.25 bias to the mesh depth (using float representation), expecting the final
9053 // depth to be 0.75.
9054 vk::VkDepthBiasRepresentationInfoEXT depthBiasReprInfo = vk::initVulkanStructure();
9055 depthBiasReprInfo.depthBiasRepresentation = vk::VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT;
9056 depthBiasReprInfo.depthBiasExact = VK_FALSE;
9057 config.depthBiasReprInfo = depthBiasReprInfo;
9058
9059 const DepthBiasParams kPositiveBias{0.25f, 0.0f};
9060 config.depthBiasEnableConfig.staticValue = true;
9061 config.depthBiasConfig.staticValue = kNoDepthBiasParams;
9062 config.depthBiasConfig.dynamicValue = kPositiveBias;
9063 config.expectedDepth = 0.75f;
9064
9065 const char *caseName = "depth_bias_repr_info_float";
9066 // Dynamically set the depth bias representation information to float representation
9067 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, config));
9068 }
9069 #endif // CTS_USES_VULKANSC
9070
9071 // Depth compare op.
9072 {
9073 TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
9074 const tcu::Vec4 kAlternativeColor(0.0f, 0.0f, 0.5f, 1.0f);
9075 baseConfig.depthTestEnableConfig.staticValue = true;
9076 baseConfig.depthWriteEnableConfig.staticValue = true;
9077 baseConfig.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_NEVER;
9078 baseConfig.clearDepthValue = 0.5f;
9079
9080 {
9081 TestConfig config = baseConfig;
9082 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
9083 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NEVER;
9084 config.meshParams[0].depth = 0.25f;
9085 config.expectedDepth = 0.5f;
9086 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
9087 // Dynamically set the depth compare operator to NEVER
9088 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_never", config));
9089 }
9090 {
9091 TestConfig config = baseConfig;
9092 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS;
9093 config.meshParams[0].depth = 0.25f;
9094 config.expectedDepth = 0.25f;
9095 // Dynamically set the depth compare operator to LESS
9096 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less", config));
9097 }
9098 {
9099 TestConfig config = baseConfig;
9100 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER;
9101 config.meshParams[0].depth = 0.75f;
9102 config.expectedDepth = 0.75f;
9103 // Dynamically set the depth compare operator to GREATER
9104 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater", config));
9105 }
9106 {
9107 TestConfig config = baseConfig;
9108 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_EQUAL;
9109 config.meshParams[0].depth = 0.5f;
9110 config.meshParams[0].color = kAlternativeColor;
9111 // Draw another mesh in front to verify it does not pass the equality test.
9112 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.25f));
9113 config.expectedDepth = 0.5f;
9114 config.referenceColor.reset(new SingleColorGenerator(kAlternativeColor));
9115 // Dynamically set the depth compare operator to EQUAL
9116 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_equal", config));
9117 }
9118 {
9119 TestConfig config = baseConfig;
9120 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
9121 config.meshParams[0].depth = 0.25f;
9122 config.expectedDepth = 0.25f;
9123 // Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with smaller depth
9124 orderingGroup->addChild(
9125 new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less", config));
9126 }
9127 {
9128 TestConfig config = baseConfig;
9129 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
9130 config.meshParams[0].depth = 0.5f;
9131 config.expectedDepth = 0.5f;
9132 // Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with equal depth
9133 orderingGroup->addChild(
9134 new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_equal", config));
9135 }
9136 {
9137 TestConfig config = baseConfig;
9138 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
9139 config.meshParams[0].depth = 0.25f;
9140 // Draw another mesh with the same depth in front of it.
9141 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.25f));
9142 config.expectedDepth = 0.25f;
9143 config.referenceColor.reset(new SingleColorGenerator(kAlternativeColor));
9144 // Dynamically set the depth compare operator to LESS_OR_EQUAL and draw two meshes with less and equal depth
9145 orderingGroup->addChild(
9146 new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less_then_equal", config));
9147 }
9148 {
9149 TestConfig config = baseConfig;
9150 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
9151 config.meshParams[0].depth = 0.75f;
9152 config.expectedDepth = 0.75f;
9153 // Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with greater depth
9154 orderingGroup->addChild(
9155 new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater", config));
9156 }
9157 {
9158 TestConfig config = baseConfig;
9159 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
9160 config.meshParams[0].depth = 0.5f;
9161 config.expectedDepth = 0.5f;
9162 // Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with equal depth
9163 orderingGroup->addChild(
9164 new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_equal", config));
9165 }
9166 {
9167 TestConfig config = baseConfig;
9168 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
9169 config.meshParams[0].depth = 0.75f;
9170 // Draw another mesh with the same depth in front of it.
9171 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.75f));
9172 config.expectedDepth = 0.75f;
9173 config.referenceColor.reset(new SingleColorGenerator(kAlternativeColor));
9174 // Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw two meshes with greater and equal depth
9175 orderingGroup->addChild(new ExtendedDynamicStateTest(
9176 testCtx, "depth_compare_greater_equal_greater_then_equal", config));
9177 }
9178 {
9179 TestConfig config = baseConfig;
9180 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NOT_EQUAL;
9181
9182 // Draw first mesh in front.
9183 config.meshParams[0].depth = 0.25f;
9184 // Draw another mesh in the back, this should pass too.
9185 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.5f));
9186 // Finally a new mesh with the same depth. This should not pass.
9187 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.5f));
9188
9189 config.referenceColor.reset(new SingleColorGenerator(kAlternativeColor));
9190 config.expectedDepth = 0.5f;
9191 // Dynamically set the depth compare operator to NOT_EQUAL
9192 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_not_equal", config));
9193 }
9194 {
9195 TestConfig config = baseConfig;
9196 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_ALWAYS;
9197
9198 config.meshParams[0].depth = 0.5f;
9199 config.expectedDepth = 0.5f;
9200 // Dynamically set the depth compare operator to ALWAYS and draw with equal depth
9201 orderingGroup->addChild(
9202 new ExtendedDynamicStateTest(testCtx, "depth_compare_always_equal", config));
9203
9204 config.meshParams[0].depth = 0.25f;
9205 config.expectedDepth = 0.25f;
9206 // Dynamically set the depth compare operator to ALWAYS and draw with less depth
9207 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_less", config));
9208
9209 config.meshParams[0].depth = 0.75f;
9210 config.expectedDepth = 0.75f;
9211 // Dynamically set the depth compare operator to ALWAYS and draw with greater depth
9212 orderingGroup->addChild(
9213 new ExtendedDynamicStateTest(testCtx, "depth_compare_always_greater", config));
9214 }
9215 }
9216
9217 // Depth bounds test.
9218 {
9219 TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
9220 baseConfig.depthBoundsConfig.staticValue = std::make_pair(0.25f, 0.75f);
9221 baseConfig.meshParams[0].depth = 0.0f;
9222
9223 {
9224 TestConfig config = baseConfig;
9225 config.depthBoundsTestEnableConfig.staticValue = false;
9226 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(true);
9227 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
9228 // Dynamically enable the depth bounds test
9229 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_enable", config));
9230 }
9231 {
9232 TestConfig config = baseConfig;
9233 config.depthBoundsTestEnableConfig.staticValue = true;
9234 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(false);
9235 // Dynamically disable the depth bounds test
9236 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_disable", config));
9237 }
9238 }
9239
9240 // Stencil test enable.
9241 {
9242 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9243 config.stencilTestEnableConfig.staticValue = false;
9244 config.stencilTestEnableConfig.dynamicValue = tcu::just(true);
9245 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
9246 config.referenceColor.reset(new SingleColorGenerator(kDefaultClearColor));
9247 // Dynamically enable the stencil test
9248 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_enable", config));
9249 }
9250 {
9251 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9252 config.stencilTestEnableConfig.staticValue = true;
9253 config.stencilTestEnableConfig.dynamicValue = tcu::just(false);
9254 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
9255 // Dynamically disable the stencil test
9256 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_disable", config));
9257 }
9258
9259 // Stencil operation. Many combinations are possible.
9260 {
9261 static const struct
9262 {
9263 vk::VkStencilFaceFlags face;
9264 std::string name;
9265 } kFaces[] = {
9266 {vk::VK_STENCIL_FACE_FRONT_BIT, "face_front"},
9267 {vk::VK_STENCIL_FACE_FRONT_AND_BACK, "face_both_single"},
9268 {vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM, "face_both_dual"}, // MAX_ENUM is a placeholder.
9269 };
9270
9271 static const struct
9272 {
9273 vk::VkCompareOp compareOp;
9274 std::string name;
9275 } kCompare[] = {
9276 {vk::VK_COMPARE_OP_LESS, "lt"},
9277 {vk::VK_COMPARE_OP_GREATER, "gt"},
9278 };
9279
9280 using u8vec = std::vector<uint8_t>;
9281
9282 static const auto kMinVal = std::numeric_limits<uint8_t>::min();
9283 static const auto kMaxVal = std::numeric_limits<uint8_t>::max();
9284 static const auto kMinValI = static_cast<int>(kMinVal);
9285 static const auto kMaxValI = static_cast<int>(kMaxVal);
9286
9287 static const struct
9288 {
9289 vk::VkStencilOp stencilOp;
9290 std::string name;
9291 u8vec clearValues; // One test per clear value interesting for this operation.
9292 vk::VkStencilOp
9293 incompatibleOp; // Alternative operation giving incompatible results for the given values.
9294 } kStencilOps[] = {
9295 {vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP, "inc_clamp", u8vec{kMaxVal - 1, kMaxVal},
9296 vk::VK_STENCIL_OP_ZERO},
9297 {vk::VK_STENCIL_OP_DECREMENT_AND_WRAP, "dec_wrap", u8vec{kMinVal + 1, kMinVal},
9298 vk::VK_STENCIL_OP_KEEP},
9299 };
9300
9301 for (const auto &face : kFaces)
9302 for (const auto &compare : kCompare)
9303 for (const auto &op : kStencilOps)
9304 {
9305 // Try clearing the stencil value with different values.
9306 for (const auto clearVal : op.clearValues)
9307 {
9308 // Use interesting values as the reference stencil value.
9309 for (const auto delta : {-1, 1})
9310 {
9311 const int refVal = clearVal + delta;
9312 if (refVal < kMinValI || refVal > kMaxValI)
9313 continue;
9314
9315 const auto refValU8 = static_cast<uint8_t>(refVal);
9316 const auto refValU32 = static_cast<uint32_t>(refVal);
9317
9318 // Calculate outcome of the stencil test itself.
9319 const bool wouldPass = stencilPasses(compare.compareOp, clearVal, refValU8);
9320
9321 // If the test passes, use an additional variant for the depthFail operation.
9322 const int subCases = (wouldPass ? 2 : 1);
9323
9324 for (int subCaseIdx = 0; subCaseIdx < subCases; ++subCaseIdx)
9325 {
9326 for (int extraPipelineIter = 0; extraPipelineIter < 2; ++extraPipelineIter)
9327 {
9328 const bool useExtraPipeline =
9329 (extraPipelineIter >
9330 0); // Bind and draw with another pipeline using the same dynamic states.
9331
9332 if (useExtraPipeline && (kOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
9333 kOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
9334 continue;
9335
9336 if (useExtraPipeline && kUseMeshShaders)
9337 continue;
9338
9339 const bool depthFail =
9340 (subCaseIdx > 0); // depthFail would be the second variant.
9341 const bool globalPass =
9342 (wouldPass && !depthFail); // Global result of the stencil+depth test.
9343
9344 // Start tuning test parameters.
9345 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9346
9347 // No face culling is applied by default, so both the front and back operations could apply depending on the mesh.
9348 if (face.face == vk::VK_STENCIL_FACE_FRONT_BIT)
9349 {
9350 // Default parameters are OK.
9351 }
9352 else if (face.face == vk::VK_STENCIL_FACE_BACK_BIT)
9353 {
9354 // Reverse the mesh so it applies the back operation.
9355 config.meshParams[0].reversed = true;
9356 }
9357 else // Front and back.
9358 {
9359 // Draw both a front and a back-facing mesh so both are applied.
9360 // The first mesh will be drawn in the top half and the second mesh in the bottom half.
9361
9362 // Make the second mesh a reversed copy of the first mesh.
9363 config.meshParams.push_back(config.meshParams.front());
9364 config.meshParams.back().reversed = true;
9365
9366 // Apply scale and offset to the top mesh.
9367 config.meshParams.front().scaleY = 0.5f;
9368 config.meshParams.front().offsetY = -0.5f;
9369
9370 // Apply scale and offset to the bottom mesh.
9371 config.meshParams.back().scaleY = 0.5f;
9372 config.meshParams.back().offsetY = 0.5f;
9373 }
9374
9375 // Enable the stencil test.
9376 config.stencilTestEnableConfig.staticValue = true;
9377
9378 // Set dynamic configuration.
9379 StencilOpParams dynamicStencilConfig;
9380 dynamicStencilConfig.faceMask = face.face;
9381 dynamicStencilConfig.compareOp = compare.compareOp;
9382 dynamicStencilConfig.failOp = vk::VK_STENCIL_OP_MAX_ENUM;
9383 dynamicStencilConfig.passOp = vk::VK_STENCIL_OP_MAX_ENUM;
9384 dynamicStencilConfig.depthFailOp = vk::VK_STENCIL_OP_MAX_ENUM;
9385
9386 // Set operations so only the appropriate operation for this case gives the right result.
9387 vk::VkStencilOp *activeOp = nullptr;
9388 vk::VkStencilOp *inactiveOps[2] = {nullptr, nullptr};
9389 if (wouldPass)
9390 {
9391 if (depthFail)
9392 {
9393 activeOp = &dynamicStencilConfig.depthFailOp;
9394 inactiveOps[0] = &dynamicStencilConfig.passOp;
9395 inactiveOps[1] = &dynamicStencilConfig.failOp;
9396 }
9397 else
9398 {
9399 activeOp = &dynamicStencilConfig.passOp;
9400 inactiveOps[0] = &dynamicStencilConfig.depthFailOp;
9401 inactiveOps[1] = &dynamicStencilConfig.failOp;
9402 }
9403 }
9404 else
9405 {
9406 activeOp = &dynamicStencilConfig.failOp;
9407 inactiveOps[0] = &dynamicStencilConfig.passOp;
9408 inactiveOps[1] = &dynamicStencilConfig.depthFailOp;
9409 }
9410
9411 *activeOp = op.stencilOp;
9412 *inactiveOps[0] = op.incompatibleOp;
9413 *inactiveOps[1] = op.incompatibleOp;
9414
9415 // Make sure all ops have been configured properly.
9416 DE_ASSERT(dynamicStencilConfig.failOp != vk::VK_STENCIL_OP_MAX_ENUM);
9417 DE_ASSERT(dynamicStencilConfig.passOp != vk::VK_STENCIL_OP_MAX_ENUM);
9418 DE_ASSERT(dynamicStencilConfig.depthFailOp != vk::VK_STENCIL_OP_MAX_ENUM);
9419
9420 // Set an incompatible static operation too.
9421 auto &staticStencilConfig = config.stencilOpConfig.staticValue.front();
9422 staticStencilConfig.faceMask = face.face;
9423 staticStencilConfig.compareOp =
9424 (globalPass ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
9425 staticStencilConfig.passOp = op.incompatibleOp;
9426 staticStencilConfig.failOp = op.incompatibleOp;
9427 staticStencilConfig.depthFailOp = op.incompatibleOp;
9428
9429 // Set dynamic configuration.
9430 StencilOpVec stencilOps;
9431 stencilOps.push_back(dynamicStencilConfig);
9432
9433 if (stencilOps.front().faceMask == vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM)
9434 {
9435 // This is the dual case. We will set the front and back face values with two separate calls.
9436 stencilOps.push_back(stencilOps.front());
9437 stencilOps.front().faceMask = vk::VK_STENCIL_FACE_FRONT_BIT;
9438 stencilOps.back().faceMask = vk::VK_STENCIL_FACE_BACK_BIT;
9439 staticStencilConfig.faceMask = vk::VK_STENCIL_FACE_FRONT_AND_BACK;
9440 }
9441
9442 config.stencilOpConfig.dynamicValue = tcu::just(stencilOps);
9443 config.clearStencilValue = clearVal;
9444 config.referenceStencil = refValU32;
9445
9446 if (depthFail)
9447 {
9448 // Enable depth test and make it fail.
9449 config.depthTestEnableConfig.staticValue = true;
9450 config.clearDepthValue = 0.5f;
9451 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
9452
9453 for (auto &meshPar : config.meshParams)
9454 meshPar.depth = 0.75f;
9455 }
9456
9457 // Set expected outcome.
9458 config.referenceColor.reset(new SingleColorGenerator(
9459 globalPass ? kDefaultTriangleColor : kDefaultClearColor));
9460 config.expectedDepth =
9461 config.clearDepthValue; // No depth writing by default.
9462 config.expectedStencil =
9463 stencilResult(op.stencilOp, clearVal, refValU8, kMinVal, kMaxVal);
9464
9465 config.useExtraDynPipeline = useExtraPipeline;
9466
9467 const std::string testName =
9468 std::string("stencil_state") +
9469 ((useExtraPipeline) ? "_extra_pipeline" : "") + "_" + face.name + "_" +
9470 compare.name + "_" + op.name + "_clear_" +
9471 de::toString(static_cast<int>(clearVal)) + "_ref_" +
9472 de::toString(refVal) + "_" +
9473 (wouldPass ? (depthFail ? "depthfail" : "pass") : "fail");
9474
9475 // Dynamically configure stencil test
9476 orderingGroup->addChild(
9477 new ExtendedDynamicStateTest(testCtx, testName, config));
9478 }
9479 }
9480 }
9481 }
9482 }
9483 }
9484
9485 // Vertex input.
9486 if (!kUseMeshShaders)
9487 {
9488 for (const auto &bindUnusedCase : kBindUnusedCases)
9489 {
9490 if (bindUnusedCase.bindUnusedMeshShadingPipeline && kOrdering != SequenceOrdering::CMD_BUFFER_START)
9491 continue;
9492
9493 // TWO_DRAWS_STATIC would be invalid because it violates VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the
9494 // dynamic stride being less than the extent of the binding for the second attribute.
9495 if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
9496 {
9497 {
9498 const auto staticGen = getVertexWithPaddingGenerator();
9499 const auto dynamicGen = getVertexWithExtraAttributesGenerator();
9500 const auto goodStrides = dynamicGen->getVertexDataStrides();
9501 StrideVec badStrides;
9502
9503 badStrides.reserve(goodStrides.size());
9504 for (const auto &stride : goodStrides)
9505 badStrides.push_back(stride / 2u);
9506
9507 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, staticGen,
9508 dynamicGen);
9509 config.strideConfig.staticValue = badStrides;
9510 config.strideConfig.dynamicValue = goodStrides;
9511 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
9512 orderingGroup->addChild(new ExtendedDynamicStateTest(
9513 testCtx, "vertex_input" + bindUnusedCase.nameSuffix, config));
9514 }
9515 {
9516 const auto staticGen = getVertexWithInstanceDataGenerator();
9517 const auto goodStrides = staticGen->getVertexDataStrides();
9518 StrideVec badStrides;
9519
9520 DE_ASSERT(goodStrides.size() == 2u);
9521 badStrides.reserve(2u);
9522 badStrides.push_back(goodStrides.at(0u));
9523 badStrides.push_back(goodStrides.at(1u) / 2u); // Halve instance rate stride.
9524
9525 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders, staticGen);
9526 config.strideConfig.staticValue = badStrides;
9527 config.strideConfig.dynamicValue = goodStrides;
9528 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
9529 config.instanceCount = 2u;
9530 // Dynamically set instance rate stride
9531 orderingGroup->addChild(new ExtendedDynamicStateTest(
9532 testCtx, "instance_rate_stride" + bindUnusedCase.nameSuffix, config));
9533 }
9534 }
9535
9536 {
9537 // Variant without mixing in the stride config.
9538 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders,
9539 getVertexWithPaddingGenerator(), getVertexWithExtraAttributesGenerator());
9540 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
9541 // Dynamically set vertex input without using dynamic strides
9542 orderingGroup->addChild(new ExtendedDynamicStateTest(
9543 testCtx, "vertex_input_no_dyn_stride" + bindUnusedCase.nameSuffix, config));
9544 }
9545
9546 {
9547 // Variant using multiple bindings.
9548 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders,
9549 getVertexWithExtraAttributesGenerator(),
9550 getVertexWithMultipleBindingsGenerator());
9551 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
9552 // Dynamically set vertex input with multiple bindings
9553 orderingGroup->addChild(new ExtendedDynamicStateTest(
9554 testCtx, "vertex_input_multiple_bindings" + bindUnusedCase.nameSuffix, config));
9555 }
9556
9557 {
9558 // Variant checking dynamic vertex inputs with 16-bit floats.
9559 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders,
9560 getVertexWithPaddingGenerator(), getVertexWithPadding16Generator());
9561 config.bindUnusedMeshShadingPipeline = bindUnusedCase.bindUnusedMeshShadingPipeline;
9562 // Dynamically set vertex input with float16 inputs
9563 orderingGroup->addChild(new ExtendedDynamicStateTest(
9564 testCtx, "vertex_input_float16" + bindUnusedCase.nameSuffix, config));
9565 }
9566 }
9567 }
9568
9569 // Null state pointers. These do not make sense for shader objects.
9570 if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
9571 {
9572 TestConfig baseConfig(pipelineConstructionType, kOrdering, kUseMeshShaders);
9573 baseConfig.favorStaticNullPointers = true;
9574
9575 if (!kUseMeshShaders)
9576 {
9577 TestConfig config(pipelineConstructionType, kOrdering, false, getVertexWithPaddingGenerator(),
9578 getVertexWithExtraAttributesGenerator());
9579 config.favorStaticNullPointers = true;
9580 // Use null pVertexInputState
9581 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_vertex_input_state", config));
9582 }
9583
9584 if (!kUseMeshShaders)
9585 {
9586 TestConfig config(baseConfig);
9587 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
9588 config.topologyConfig.dynamicValue = vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
9589 config.extraLineRestarts = true;
9590 config.primRestartEnableConfig.staticValue = false;
9591 config.primRestartEnableConfig.dynamicValue = tcu::just(true);
9592 config.referenceColor.reset(new CenterStripGenerator(kDefaultTriangleColor, kDefaultClearColor));
9593 // Use null pVertexInputState
9594 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_input_assembly_state", config));
9595 }
9596
9597 if (!kUseMeshShaders)
9598 {
9599 TestConfig config(baseConfig);
9600 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
9601 config.patchControlPointsConfig.staticValue = 1;
9602 config.patchControlPointsConfig.dynamicValue = 3;
9603 // Use null pTessellationState
9604 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_tessellation_state", config));
9605 }
9606
9607 {
9608 TestConfig config(baseConfig);
9609
9610 config.viewportConfig.staticValue = ViewportVec{
9611 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
9612 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
9613 };
9614
9615 config.scissorConfig.staticValue = ScissorVec{
9616 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
9617 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
9618 };
9619
9620 config.scissorConfig.dynamicValue =
9621 ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
9622 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(),
9623 config.viewportConfig.staticValue.front()};
9624
9625 // Use null pViewportState
9626 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_viewport_state", config));
9627 }
9628
9629 {
9630 TestConfig config(baseConfig);
9631 config.depthClampEnableConfig.staticValue = true;
9632 config.depthClampEnableConfig.dynamicValue = false;
9633 config.rastDiscardEnableConfig.staticValue = true;
9634 config.rastDiscardEnableConfig.dynamicValue = false;
9635 config.polygonModeConfig.staticValue = vk::VK_POLYGON_MODE_POINT;
9636 config.polygonModeConfig.dynamicValue = vk::VK_POLYGON_MODE_FILL;
9637 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_AND_BACK;
9638 config.cullModeConfig.dynamicValue = vk::VK_CULL_MODE_NONE;
9639 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
9640 config.frontFaceConfig.dynamicValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
9641 config.depthBiasEnableConfig.staticValue = true;
9642 config.depthBiasEnableConfig.dynamicValue = false;
9643 config.depthBiasConfig.staticValue = DepthBiasParams{1.0f, 1.0f};
9644 config.depthBiasConfig.dynamicValue = kNoDepthBiasParams;
9645 config.lineWidthConfig.staticValue = 0.0f;
9646 config.lineWidthConfig.dynamicValue = 1.0f;
9647 // Use null pRasterizationState
9648 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_rasterization_state", config));
9649 }
9650
9651 {
9652 TestConfig config(baseConfig);
9653 config.rasterizationSamplesConfig.staticValue = kMultiSampleCount;
9654 config.rasterizationSamplesConfig.dynamicValue = kSingleSampleCount;
9655 config.sampleMaskConfig.staticValue = SampleMaskVec(1u, 0u);
9656 config.sampleMaskConfig.dynamicValue = SampleMaskVec(1u, 0xFFu);
9657 config.alphaToCoverageConfig.staticValue = true;
9658 config.alphaToCoverageConfig.dynamicValue = false;
9659 config.alphaToOneConfig.staticValue = true;
9660 config.alphaToOneConfig.dynamicValue = false;
9661 // Use null pMultisampleState
9662 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_multisample_state", config));
9663 }
9664
9665 {
9666 TestConfig config(baseConfig);
9667 config.rasterizationSamplesConfig.staticValue = kMultiSampleCount;
9668 config.rasterizationSamplesConfig.dynamicValue = kSingleSampleCount;
9669 config.sampleMaskConfig.staticValue = SampleMaskVec(1u, 0u);
9670 config.sampleMaskConfig.dynamicValue = SampleMaskVec(1u, 0xFFu);
9671 config.alphaToCoverageConfig.staticValue = true;
9672 config.alphaToCoverageConfig.dynamicValue = false;
9673 config.disableAlphaToOneFeature = true;
9674 // Use null pMultisampleState
9675 orderingGroup->addChild(
9676 new ExtendedDynamicStateTest(testCtx, "null_multisample_state_no_alpha_to_one", config));
9677 }
9678
9679 {
9680 TestConfig config(baseConfig);
9681 config.depthTestEnableConfig.staticValue = true;
9682 config.depthTestEnableConfig.dynamicValue = false;
9683 config.depthWriteEnableConfig.staticValue = true;
9684 config.depthWriteEnableConfig.dynamicValue = false;
9685 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_NEVER;
9686 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_ALWAYS;
9687 config.depthBoundsTestEnableConfig.staticValue = true;
9688 config.depthBoundsTestEnableConfig.dynamicValue = false;
9689 config.stencilTestEnableConfig.staticValue = true;
9690 config.stencilTestEnableConfig.dynamicValue = false;
9691 config.stencilOpConfig.staticValue =
9692 StencilOpVec(1u, StencilOpParams{vk::VK_STENCIL_FACE_FRONT_AND_BACK, vk::VK_STENCIL_OP_INVERT,
9693 vk::VK_STENCIL_OP_INVERT, vk::VK_STENCIL_OP_INVERT,
9694 vk::VK_COMPARE_OP_NEVER});
9695 config.stencilOpConfig.dynamicValue = StencilOpVec(
9696 1u, StencilOpParams{vk::VK_STENCIL_FACE_FRONT_AND_BACK, vk::VK_STENCIL_OP_KEEP,
9697 vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS});
9698 config.depthBoundsConfig.staticValue = std::make_pair(1.0f, 1.0f);
9699 config.depthBoundsConfig.dynamicValue = std::make_pair(0.0f, 0.0f);
9700 // Use null pDepthStencilState
9701 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_depth_stencil_state", config));
9702 }
9703
9704 {
9705 TestConfig config(baseConfig);
9706 config.forceUnormColorFormat = true;
9707 config.logicOpEnableConfig.staticValue = true;
9708 config.logicOpEnableConfig.dynamicValue = false;
9709 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_CLEAR;
9710 config.logicOpConfig.dynamicValue = vk::VK_LOGIC_OP_COPY;
9711 config.colorBlendEnableConfig.staticValue = true;
9712 config.colorBlendEnableConfig.dynamicValue = false;
9713 config.colorBlendEquationConfig.staticValue = ColorBlendEq();
9714 config.colorBlendEquationConfig.dynamicValue =
9715 ColorBlendEq(vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD,
9716 vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_FACTOR_ONE, vk::VK_BLEND_OP_ADD);
9717 config.colorWriteMaskConfig.staticValue = 0u;
9718 config.colorWriteMaskConfig.dynamicValue = (CR | CG | CB | CA);
9719 config.blendConstantsConfig.staticValue = BlendConstArray{1.0f, 1.0f, 1.0f, 1.0f};
9720 config.blendConstantsConfig.dynamicValue = BlendConstArray{0.0f, 0.0f, 0.0f, 0.0f};
9721 // Use null pColorBlendState
9722 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "null_color_blend_state", config));
9723 }
9724 }
9725
9726 {
9727 TestConfig config(pipelineConstructionType, kOrdering, kUseMeshShaders);
9728 config.sampleShadingEnable = true;
9729 config.minSampleShading = 1.0f;
9730 config.forceAtomicCounters = true;
9731 config.oversizedTriangle = true;
9732 config.rasterizationSamplesConfig.staticValue = kSingleSampleCount;
9733 config.rasterizationSamplesConfig.dynamicValue = kMultiSampleCount;
9734 // Test number of frag shader invocations with sample shading enabled and dynamic sample counts
9735 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "sample_shading_sample_count", config));
9736 }
9737
9738 tcu::TestCaseGroup *group = (kUseMeshShaders ? meshShaderGroup.get() : extendedDynamicStateGroup.get());
9739 group->addChild(orderingGroup.release());
9740 }
9741
9742 extendedDynamicStateGroup->addChild(meshShaderGroup.release());
9743 extendedDynamicStateGroup->addChild(createExtendedDynamicStateMiscTests(testCtx, pipelineConstructionType));
9744 return extendedDynamicStateGroup.release();
9745 }
9746
9747 } // namespace pipeline
9748 } // namespace vkt
9749