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