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