1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2020 The Khronos Group Inc.
6 * Copyright (c) 2020 Valve Corporation.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 * \brief Extended dynamic state tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktPipelineExtendedDynamicStateTests.hpp"
26 #include "vktPipelineImageUtil.hpp"
27 #include "vktTestCase.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkImageUtil.hpp"
39 #include "tcuVector.hpp"
40 #include "tcuMaybe.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuVectorUtil.hpp"
43 #include "tcuStringTemplate.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deStringUtil.hpp"
68 inline vk::VkBool32 makeVkBool32(bool value)
70 return (value ? VK_TRUE : VK_FALSE);
74 constexpr deUint32 kFramebufferWidth = 64u;
75 constexpr deUint32 kFramebufferHeight = 64u;
78 constexpr vk::VkFormat kUnormColorFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
79 constexpr vk::VkFormat kIntColorFormat = vk::VK_FORMAT_R8G8B8A8_UINT;
80 const tcu::Vec4 kUnormColorThreshold (0.005f); // 1/255 < 0.005 < 2/255.
82 struct DepthStencilFormat
84 vk::VkFormat imageFormat;
88 const DepthStencilFormat kDepthStencilFormats[] =
90 { vk::VK_FORMAT_D32_SFLOAT_S8_UINT, 0.0f },
91 { vk::VK_FORMAT_D24_UNORM_S8_UINT, 1.0e-07f }, // 1/(2**24-1) < 1.0e-07f < 2/(2**24-1)
94 using StrideVec = std::vector<vk::VkDeviceSize>;
96 // We will use several data types in vertex bindings. Each type will need to define a few things.
102 // Vertex input attribute declarations in GLSL form. One sentence per element.
103 virtual std::vector<std::string> getAttributeDeclarations() const = 0;
105 // Get statements to calculate a vec2 called "vertexCoords" using the vertex input attributes.
106 virtual std::vector<std::string> getVertexCoordCalc() const = 0;
111 // Vertex attributes for VkPipelineVertexInputStateCreateInfo.
112 virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const = 0;
114 // Vertex attributes for VK_EXT_vertex_input_dynamic_state.
115 virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const = 0;
117 // Vertex bindings for VkPipelineVertexInputStateCreateInfo.
118 virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions (const StrideVec& strides) const = 0;
120 // Vertex bindings for VK_EXT_vertex_input_dynamic_state.
121 virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2 (const StrideVec& strides) const = 0;
123 // Create buffer data given an array of coordinates and an initial padding.
124 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;
126 // Stride of vertex data in each binding.
127 virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const = 0;
130 // Auxiliar function to create these structs more easily.
131 vk::VkVertexInputAttributeDescription2EXT makeVertexInputAttributeDescription2EXT (deUint32 location, deUint32 binding, vk::VkFormat format, deUint32 offset)
133 vk::VkVertexInputAttributeDescription2EXT desc = vk::initVulkanStructure();
134 desc.location = location;
135 desc.binding = binding;
136 desc.format = format;
137 desc.offset = offset;
141 vk::VkVertexInputBindingDescription2EXT makeVertexInputBindingDescription2EXT (deUint32 binding, deUint32 stride, vk::VkVertexInputRate inputRate)
143 vk::VkVertexInputBindingDescription2EXT desc = vk::initVulkanStructure();
144 desc.binding = binding;
145 desc.stride = stride;
146 desc.inputRate = inputRate;
151 // Fill a section of the given buffer (from offset to offset+count) with repeating copies of the given data.
152 void fillWithPattern(void* ptr_, size_t offset, size_t count, const void* src, size_t srcSize)
154 auto ptr = reinterpret_cast<char*>(ptr_);
156 size_t pending = count;
160 const size_t stepSize = de::min(srcSize, pending);
161 deMemcpy(ptr + offset + done, src, stepSize);
167 // Create a single binding vertex data vector given a type T for vertex data.
169 std::vector<deUint8> createSingleBindingVertexData (const std::vector<tcu::Vec2>& coords, vk::VkDeviceSize dataOffset, vk::VkDeviceSize trailingPadding, const void* paddingPattern, size_t patternSize)
171 DE_ASSERT(!coords.empty());
173 const auto dataOffsetSz = static_cast<size_t>(dataOffset);
174 const auto trailingPaddingSz = static_cast<size_t>(trailingPadding);
176 std::vector<deUint8> buffer;
177 buffer.resize(dataOffsetSz + coords.size() * sizeof(T) + trailingPaddingSz);
179 fillWithPattern(buffer.data(), 0u, dataOffsetSz, paddingPattern, patternSize);
181 auto pos = dataOffsetSz;
182 for (const auto& coord : coords)
184 new (&buffer[pos]) T(coord);
188 fillWithPattern(buffer.data(), pos, trailingPaddingSz, paddingPattern, patternSize);
193 // Vertices in buffers will have 2 components and a padding to properly test the stride.
194 // This is the vertex type that will be used normally.
195 class VertexWithPadding : public VertexGenerator
200 VertexData(const tcu::Vec2& coords_)
202 , padding (0.0f, 0.0f)
210 virtual std::vector<std::string> getAttributeDeclarations() const override
212 std::vector<std::string> declarations;
213 declarations.push_back("layout(location=0) in vec2 position;");
217 virtual std::vector<std::string> getVertexCoordCalc() const override
219 std::vector<std::string> statements;
220 statements.push_back("vec2 vertexCoords = position;");
224 virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
226 std::vector<vk::VkVertexInputAttributeDescription> descriptions;
227 descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
231 // Vertex attributes for VK_EXT_vertex_input_dynamic_state.
232 virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
234 std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
235 descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
239 // Vertex bindings for VkPipelineVertexInputStateCreateInfo.
240 virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
242 std::vector<vk::VkVertexInputBindingDescription> descriptions;
243 descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
247 // Vertex bindings for VK_EXT_vertex_input_dynamic_state.
248 virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
250 std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
251 descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
255 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
257 return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
260 virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
262 return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
266 // Vertices with coordinates, padding and an extra constant field.
267 class VertexWithExtraAttributes : public VertexGenerator
272 VertexData (const tcu::Vec2& coords_)
276 deMemset(padding, 0, sizeof(padding));
280 tcu::Vec2 padding[10];
285 virtual std::vector<std::string> getAttributeDeclarations() const override
287 std::vector<std::string> declarations;
288 declarations.push_back("layout(location=0) in vec2 position;");
289 declarations.push_back("layout(location=1) in vec2 ones;");
293 virtual std::vector<std::string> getVertexCoordCalc() const override
295 std::vector<std::string> statements;
296 statements.push_back("vec2 vertexCoords = position;");
297 statements.push_back("vertexCoords = vertexCoords * ones;");
301 virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
303 std::vector<vk::VkVertexInputAttributeDescription> descriptions;
304 descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
305 descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(VertexData, ones))));
309 virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
311 std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
312 descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u));
313 descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(VertexData, ones))));
317 virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
319 std::vector<vk::VkVertexInputBindingDescription> descriptions;
320 descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
324 virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
326 std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
327 descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
331 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
333 return std::vector<std::vector<deUint8>>(1u, createSingleBindingVertexData<VertexData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize));
336 virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
338 return std::vector<vk::VkDeviceSize>(1u, static_cast<vk::VkDeviceSize>(sizeof(VertexData)));
342 // Vertices using multiple bindings and constant fields.
343 // Binding 0: no data actually used.
344 // Binding 1: contains location 0, array of PaddingOnes.
345 // Binding 2: no data actually used.
346 // Binding 3: contains location 1, array of CoordsData.
347 // Binding 4: no data actually used.
348 // Binding 5: contains location 2, array of OneZeroPadding.
349 // See getAttributeDeclarations().
350 class MultipleBindingsVertex : public VertexGenerator
359 CoordsData (const tcu::Vec2& coords_)
360 : padding0 (0.0f, 3.0f)
362 , padding1 (3.0f, 0.0f)
368 tcu::Vec2 padding[4];
371 PaddingOnes (const tcu::Vec2&)
374 deMemset(&padding, 0, sizeof(padding));
378 struct OneZeroPadding
381 tcu::Vec2 padding[3];
383 OneZeroPadding (const tcu::Vec2&)
384 : oneZero (1.0f, 1.0f, 0.0f, 0.0f)
386 deMemset(&padding, 0, sizeof(padding));
394 Zeros (const tcu::Vec2&)
400 virtual std::vector<std::string> getAttributeDeclarations() const override
402 std::vector<std::string> declarations;
403 declarations.reserve(3u);
405 declarations.push_back("layout(location=0) in vec2 ones;");
406 declarations.push_back("layout(location=1) in vec2 position;");
407 declarations.push_back("layout(location=2) in vec4 oneZero;");
412 virtual std::vector<std::string> getVertexCoordCalc() const override
414 std::vector<std::string> statements;
415 statements.reserve(2u);
417 statements.push_back("vec2 vertexCoords = position;");
418 statements.push_back("vertexCoords = ((vertexCoords * ones) + oneZero.zw) * oneZero.xy;");
423 virtual std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions() const override
425 // We create the descriptions vector out of order to make it more interesting. See the attribute declarations.
426 std::vector<vk::VkVertexInputAttributeDescription> descriptions;
427 descriptions.reserve(3u);
429 descriptions.push_back(vk::makeVertexInputAttributeDescription(1u, 3u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(CoordsData, coords))));
430 descriptions.push_back(vk::makeVertexInputAttributeDescription(2u, 5u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(offsetof(OneZeroPadding, oneZero))));
431 descriptions.push_back(vk::makeVertexInputAttributeDescription(0u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(PaddingOnes, ones))));
436 virtual std::vector<vk::VkVertexInputAttributeDescription2EXT> getAttributeDescriptions2() const override
438 // We create the descriptions vector out of order to make it more interesting. See the attribute declarations.
439 std::vector<vk::VkVertexInputAttributeDescription2EXT> descriptions;
440 descriptions.reserve(3u);
442 descriptions.push_back(makeVertexInputAttributeDescription2EXT(2u, 5u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(offsetof(OneZeroPadding, oneZero))));
443 descriptions.push_back(makeVertexInputAttributeDescription2EXT(1u, 3u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(CoordsData, coords))));
444 descriptions.push_back(makeVertexInputAttributeDescription2EXT(0u, 1u, vk::VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(PaddingOnes, ones))));
449 virtual std::vector<vk::VkVertexInputBindingDescription> getBindingDescriptions(const StrideVec& strides) const override
451 // Provide descriptions out of order to make it more interesting.
452 std::vector<vk::VkVertexInputBindingDescription> descriptions;
453 descriptions.reserve(6u);
455 descriptions.push_back(vk::makeVertexInputBindingDescription(2u, static_cast<deUint32>(strides.at(2)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
456 descriptions.push_back(vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
457 descriptions.push_back(vk::makeVertexInputBindingDescription(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
458 descriptions.push_back(vk::makeVertexInputBindingDescription(4u, static_cast<deUint32>(strides.at(4)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
459 descriptions.push_back(vk::makeVertexInputBindingDescription(3u, static_cast<deUint32>(strides.at(3)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
460 descriptions.push_back(vk::makeVertexInputBindingDescription(5u, static_cast<deUint32>(strides.at(5)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
465 virtual std::vector<vk::VkVertexInputBindingDescription2EXT> getBindingDescriptions2(const StrideVec& strides) const override
467 // Provide descriptions out of order to make it more interesting.
468 std::vector<vk::VkVertexInputBindingDescription2EXT> descriptions;
469 descriptions.reserve(6u);
471 descriptions.push_back(makeVertexInputBindingDescription2EXT(2u, static_cast<deUint32>(strides.at(2)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
472 descriptions.push_back(makeVertexInputBindingDescription2EXT(0u, static_cast<deUint32>(strides.at(0)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
473 descriptions.push_back(makeVertexInputBindingDescription2EXT(1u, static_cast<deUint32>(strides.at(1)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
474 descriptions.push_back(makeVertexInputBindingDescription2EXT(5u, static_cast<deUint32>(strides.at(5)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
475 descriptions.push_back(makeVertexInputBindingDescription2EXT(4u, static_cast<deUint32>(strides.at(4)), vk::VK_VERTEX_INPUT_RATE_INSTANCE));
476 descriptions.push_back(makeVertexInputBindingDescription2EXT(3u, static_cast<deUint32>(strides.at(3)), vk::VK_VERTEX_INPUT_RATE_VERTEX));
481 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
483 std::vector<std::vector<deUint8>> result;
486 result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize)); // Not actually used.
487 result.push_back(createSingleBindingVertexData<PaddingOnes>(coords, dataOffset, trailingPadding, paddingPattern, patternSize)); // Binding 1 contains location=0 as PaddingOnes.
488 result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize)); // Not actually used.
489 result.push_back(createSingleBindingVertexData<CoordsData>(coords, dataOffset, trailingPadding, paddingPattern, patternSize)); // Binding 3 contains location=1 as CoordsData.
490 result.push_back(createSingleBindingVertexData<Zeros>(coords, dataOffset, trailingPadding, paddingPattern, patternSize)); // Not actually used.
491 result.push_back(createSingleBindingVertexData<OneZeroPadding>(coords, dataOffset, trailingPadding, paddingPattern, patternSize)); // Binding 5 contains location=2 as OneZeroPadding.
496 virtual std::vector<vk::VkDeviceSize> getVertexDataStrides() const override
498 std::vector<vk::VkDeviceSize> strides;
501 strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
502 strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(PaddingOnes)));
503 strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
504 strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(CoordsData)));
505 strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(Zeros)));
506 strides.push_back(static_cast<vk::VkDeviceSize>(sizeof(OneZeroPadding)));
512 // Stencil Operation parameters, as used in vkCmdSetStencilOpEXT().
513 struct StencilOpParams
515 vk::VkStencilFaceFlags faceMask;
516 vk::VkStencilOp failOp;
517 vk::VkStencilOp passOp;
518 vk::VkStencilOp depthFailOp;
519 vk::VkCompareOp compareOp;
522 const StencilOpParams kDefaultStencilOpParams =
524 vk::VK_STENCIL_FACE_FRONT_AND_BACK,
525 vk::VK_STENCIL_OP_KEEP,
526 vk::VK_STENCIL_OP_KEEP,
527 vk::VK_STENCIL_OP_KEEP,
528 vk::VK_COMPARE_OP_ALWAYS
531 using ViewportVec = std::vector<vk::VkViewport>;
532 using ScissorVec = std::vector<vk::VkRect2D>;
533 using StencilOpVec = std::vector<StencilOpParams>;
535 // Generic, to be used with any state than can be set statically and, as an option, dynamically.
537 struct StaticAndDynamicPair
540 tcu::Maybe<T> dynamicValue;
542 // Helper constructor to set a static value and no dynamic value.
543 StaticAndDynamicPair (const T& value)
544 : staticValue (value)
545 , dynamicValue (tcu::nothing<T>())
549 // Helper constructor to set both.
550 StaticAndDynamicPair (const T& sVal, const T& dVal)
552 , dynamicValue (tcu::just<T>(dVal))
556 // If the dynamic value is present, swap static and dynamic values.
557 void swapValues (void)
561 std::swap(staticValue, dynamicValue.get());
565 // For anything boolean, see below.
566 using BooleanFlagConfig = StaticAndDynamicPair<bool>;
568 // Configuration for every aspect of the extended dynamic state.
569 using CullModeConfig = StaticAndDynamicPair<vk::VkCullModeFlags>;
570 using FrontFaceConfig = StaticAndDynamicPair<vk::VkFrontFace>;
571 using TopologyConfig = StaticAndDynamicPair<vk::VkPrimitiveTopology>;
572 using ViewportConfig = StaticAndDynamicPair<ViewportVec>; // At least one element.
573 using ScissorConfig = StaticAndDynamicPair<ScissorVec>; // At least one element.
574 using StrideConfig = StaticAndDynamicPair<StrideVec>; // At least one element.
575 using DepthTestEnableConfig = BooleanFlagConfig;
576 using DepthWriteEnableConfig = BooleanFlagConfig;
577 using DepthCompareOpConfig = StaticAndDynamicPair<vk::VkCompareOp>;
578 using DepthBoundsTestEnableConfig = BooleanFlagConfig;
579 using StencilTestEnableConfig = BooleanFlagConfig;
580 using StencilOpConfig = StaticAndDynamicPair<StencilOpVec>; // At least one element.
581 using VertexGeneratorConfig = StaticAndDynamicPair<const VertexGenerator*>;
582 using DepthBiasEnableConfig = BooleanFlagConfig;
583 using RastDiscardEnableConfig = BooleanFlagConfig;
584 using PrimRestartEnableConfig = BooleanFlagConfig;
585 using LogicOpConfig = StaticAndDynamicPair<vk::VkLogicOp>;
586 using PatchControlPointsConfig = StaticAndDynamicPair<deUint8>;
588 const tcu::Vec4 kDefaultTriangleColor (0.0f, 0.0f, 1.0f, 1.0f); // Opaque blue.
589 const tcu::Vec4 kDefaultClearColor (0.0f, 0.0f, 0.0f, 1.0f); // Opaque black.
591 const tcu::Vec4 kLogicOpTriangleColor (0.0f, 0.0f,255.f,255.f); // Opaque blue. Note: tcu::Vec4 and will be cast to the appropriate type in the shader.
592 const tcu::UVec4 kGreenClearColor ( 0u, 255u, 0u, 255u); // Opaque green, UINT.
593 const tcu::UVec4 kLogicOpFinalColor ( 0u, 255u, 255u, 255u); // Opaque cyan, UINT.
605 MeshParams (const tcu::Vec4& color_ = kDefaultTriangleColor,
607 bool reversed_ = false,
608 float scaleX_ = 1.0f,
609 float scaleY_ = 1.0f,
610 float offsetX_ = 0.0f,
611 float offsetY_ = 0.0f)
614 , reversed (reversed_)
622 enum class SequenceOrdering
624 CMD_BUFFER_START = 0, // Set state at the start of the command buffer.
625 BEFORE_DRAW = 1, // After binding dynamic pipeline and just before drawing.
626 BETWEEN_PIPELINES = 2, // After a static state pipeline has been bound but before the dynamic state pipeline has been bound.
627 AFTER_PIPELINES = 3, // After a static state pipeline and a second dynamic state pipeline have been bound.
628 BEFORE_GOOD_STATIC = 4, // Before a static state pipeline with the correct values has been bound.
629 TWO_DRAWS_DYNAMIC = 5, // Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again.
630 TWO_DRAWS_STATIC = 6, // Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again.
633 using ReferenceColorGenerator = std::function<void(tcu::PixelBufferAccess&)>;
635 // Most tests expect a single output color in the whole image.
636 class SingleColorGenerator
639 SingleColorGenerator (const tcu::Vec4& color)
640 : m_colorFloat (color)
645 SingleColorGenerator (const tcu::UVec4& color)
646 : m_colorFloat (0.0f)
647 , m_colorUint (color)
651 void operator()(tcu::PixelBufferAccess& access)
653 constexpr auto kWidth = static_cast<int>(kFramebufferWidth);
654 constexpr auto kHeight = static_cast<int>(kFramebufferHeight);
656 for (int y = 0; y < kHeight; ++y)
657 for (int x = 0; x < kWidth; ++x)
660 access.setPixel(m_colorUint, x, y);
662 access.setPixel(m_colorFloat, x, y);
667 const tcu::Vec4 m_colorFloat;
668 const tcu::UVec4 m_colorUint;
672 // Some tests expect the upper half and the lower half having different color values.
673 class HorizontalSplitGenerator
676 HorizontalSplitGenerator (const tcu::Vec4& top, const tcu::Vec4& bottom)
677 : m_top(top), m_bottom(bottom)
680 void operator()(tcu::PixelBufferAccess& access)
682 constexpr auto kWidth = static_cast<int>(kFramebufferWidth);
683 constexpr auto kHeight = static_cast<int>(kFramebufferHeight);
684 constexpr auto kHalfHeight = kHeight / 2;
686 for (int y = 0; y < kHeight; ++y)
687 for (int x = 0; x < kWidth; ++x)
689 const auto& color = (y < kHalfHeight ? m_top : m_bottom);
690 access.setPixel(color, x, y);
695 const tcu::Vec4 m_top;
696 const tcu::Vec4 m_bottom;
699 const VertexGenerator* getVertexWithPaddingGenerator ()
701 static const VertexWithPadding vertexWithPadding;
702 return &vertexWithPadding;
705 const VertexGenerator* getVertexWithExtraAttributesGenerator ()
707 static const VertexWithExtraAttributes vertexWithExtraAttributes;
708 return &vertexWithExtraAttributes;
711 const VertexGenerator* getVertexWithMultipleBindingsGenerator ()
713 static const MultipleBindingsVertex multipleBindingsVertex;
714 return &multipleBindingsVertex;
717 // Create VertexGeneratorConfig varying constructor depending on having none, only the static or both.
718 VertexGeneratorConfig makeVertexGeneratorConfig (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
720 DE_ASSERT(!(dynamicGen && !staticGen));
722 return VertexGeneratorConfig(staticGen, dynamicGen);
724 return VertexGeneratorConfig(staticGen);
725 return VertexGeneratorConfig(getVertexWithPaddingGenerator()); // Only static part with a default option.c
728 // Similar to makeVertexGeneratorConfig, choosing the final value.
729 const VertexGenerator* chooseVertexGenerator (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
731 DE_ASSERT(!(dynamicGen && !staticGen));
736 return getVertexWithPaddingGenerator();
739 enum class TopologyClass
748 std::string topologyClassName (TopologyClass tclass)
752 case TopologyClass::POINT: return "point";
753 case TopologyClass::LINE: return "line";
754 case TopologyClass::TRIANGLE: return "triangle";
755 case TopologyClass::PATCH: return "patch";
764 TopologyClass getTopologyClass (vk::VkPrimitiveTopology topology)
768 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
769 return TopologyClass::POINT;
770 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
771 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
772 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
773 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
774 return TopologyClass::LINE;
775 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
776 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
777 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
778 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
779 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
780 return TopologyClass::TRIANGLE;
781 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
782 return TopologyClass::PATCH;
788 return TopologyClass::INVALID;
793 // Main sequence ordering.
794 SequenceOrdering sequenceOrdering;
796 // Drawing parameters: tests will draw one or more flat meshes of triangles covering the whole "screen".
797 std::vector<MeshParams> meshParams; // Mesh parameters for each full-screen layer of geometry.
798 deUint32 referenceStencil; // Reference stencil value.
800 // Clearing parameters for the framebuffer.
801 vk::VkClearValue clearColorValue;
802 float clearDepthValue;
803 deUint32 clearStencilValue;
805 // Expected output in the attachments.
806 ReferenceColorGenerator referenceColor;
808 deUint32 expectedStencil;
810 // Depth bounds parameters for the pipeline.
811 float minDepthBounds;
812 float maxDepthBounds;
814 // Force inclusion of passthrough geometry shader or not.
815 bool forceGeometryShader;
817 // Offset and extra room after the vertex buffer data.
818 vk::VkDeviceSize vertexDataOffset;
819 vk::VkDeviceSize vertexDataExtraBytes;
821 // Static and dynamic pipeline configuration.
822 VertexGeneratorConfig vertexGenerator;
823 CullModeConfig cullModeConfig;
824 FrontFaceConfig frontFaceConfig;
825 TopologyConfig topologyConfig;
826 ViewportConfig viewportConfig;
827 ScissorConfig scissorConfig;
828 StrideConfig strideConfig;
829 DepthTestEnableConfig depthTestEnableConfig;
830 DepthWriteEnableConfig depthWriteEnableConfig;
831 DepthCompareOpConfig depthCompareOpConfig;
832 DepthBoundsTestEnableConfig depthBoundsTestEnableConfig;
833 StencilTestEnableConfig stencilTestEnableConfig;
834 StencilOpConfig stencilOpConfig;
835 DepthBiasEnableConfig depthBiasEnableConfig;
836 RastDiscardEnableConfig rastDiscardEnableConfig;
837 PrimRestartEnableConfig primRestartEnableConfig;
838 LogicOpConfig logicOpConfig;
839 PatchControlPointsConfig patchControlPointsConfig;
842 TestConfig (SequenceOrdering ordering, const VertexGenerator* staticVertexGenerator = nullptr, const VertexGenerator* dynamicVertexGenerator = nullptr)
843 : sequenceOrdering (ordering)
844 , meshParams (1u, MeshParams())
845 , referenceStencil (0u)
846 , clearColorValue (vk::makeClearValueColor(kDefaultClearColor))
847 , clearDepthValue (1.0f)
848 , clearStencilValue (0u)
849 , referenceColor (SingleColorGenerator(kDefaultTriangleColor))
850 , expectedDepth (1.0f)
851 , expectedStencil (0u)
852 , minDepthBounds (0.0f)
853 , maxDepthBounds (1.0f)
854 , forceGeometryShader (false)
855 , vertexDataOffset (0ull)
856 , vertexDataExtraBytes (0ull)
857 , vertexGenerator (makeVertexGeneratorConfig(staticVertexGenerator, dynamicVertexGenerator))
858 , cullModeConfig (static_cast<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE))
859 , frontFaceConfig (vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
860 // By default we will use a triangle fan with 6 vertices that could be wrongly interpreted as a triangle list with 2 triangles.
861 , topologyConfig (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN)
862 , viewportConfig (ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight)))
863 , scissorConfig (ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight)))
864 // By default, the vertex stride is the size of a vertex according to the chosen vertex type.
865 , strideConfig (chooseVertexGenerator(staticVertexGenerator, dynamicVertexGenerator)->getVertexDataStrides())
866 , depthTestEnableConfig (false)
867 , depthWriteEnableConfig (false)
868 , depthCompareOpConfig (vk::VK_COMPARE_OP_NEVER)
869 , depthBoundsTestEnableConfig (false)
870 , stencilTestEnableConfig (false)
871 , stencilOpConfig (StencilOpVec(1u, kDefaultStencilOpParams))
872 , depthBiasEnableConfig (false)
873 , rastDiscardEnableConfig (false)
874 , primRestartEnableConfig (false)
875 , logicOpConfig (vk::VK_LOGIC_OP_CLEAR)
876 , patchControlPointsConfig (1u)
877 , m_swappedValues (false)
881 // Get the proper viewport vector according to the test config.
882 const ViewportVec& getActiveViewportVec () const
884 return ((viewportConfig.dynamicValue && !m_swappedValues) ? viewportConfig.dynamicValue.get() : viewportConfig.staticValue);
887 // Gets the proper vertex generator according to the test config.
888 const VertexGenerator* getActiveVertexGenerator () const
890 return ((vertexGenerator.dynamicValue && !m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
893 // Gets the inactive vertex generator according to the test config. If there's only one, return that.
894 const VertexGenerator* getInactiveVertexGenerator () const
896 return ((vertexGenerator.dynamicValue && m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
899 // Get the active number of patch control points according to the test config.
900 deUint32 getActivePatchControlPoints () const
902 return ((patchControlPointsConfig.dynamicValue && !m_swappedValues) ? patchControlPointsConfig.dynamicValue.get() : patchControlPointsConfig.staticValue);
905 // Returns true if there is more than one viewport.
906 bool isMultiViewport () const
908 return (getActiveViewportVec().size() > 1);
911 // Returns true if the case needs a geometry shader.
912 bool needsGeometryShader () const
914 // Writing to gl_ViewportIndex from vertex or tesselation shaders needs the shaderOutputViewportIndex feature, which is less
915 // commonly supported than geometry shaders, so we will use a geometry shader if we need to write to it.
916 return (isMultiViewport() || forceGeometryShader);
919 // Returns true if we should use the static and dynamic values exchanged.
920 // This makes the static part of the pipeline have the actual expected values.
921 bool isReversed () const
923 return (sequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
924 sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC);
927 // Swaps static and dynamic configuration values.
930 vertexGenerator.swapValues();
931 cullModeConfig.swapValues();
932 frontFaceConfig.swapValues();
933 topologyConfig.swapValues();
934 viewportConfig.swapValues();
935 scissorConfig.swapValues();
936 strideConfig.swapValues();
937 depthTestEnableConfig.swapValues();
938 depthWriteEnableConfig.swapValues();
939 depthCompareOpConfig.swapValues();
940 depthBoundsTestEnableConfig.swapValues();
941 stencilTestEnableConfig.swapValues();
942 stencilOpConfig.swapValues();
943 depthBiasEnableConfig.swapValues();
944 rastDiscardEnableConfig.swapValues();
945 primRestartEnableConfig.swapValues();
946 logicOpConfig.swapValues();
947 patchControlPointsConfig.swapValues();
949 m_swappedValues = !m_swappedValues;
952 // Returns the number of iterations when recording commands.
953 deUint32 numIterations () const
955 deUint32 iterations = 0u;
957 switch (sequenceOrdering)
959 case SequenceOrdering::TWO_DRAWS_DYNAMIC:
960 case SequenceOrdering::TWO_DRAWS_STATIC:
971 // Returns true if we're testing the logic op.
972 bool testLogicOp () const
974 return static_cast<bool>(logicOpConfig.dynamicValue);
977 // Returns true if we're testing the patch control points.
978 bool testPatchControlPoints () const
980 return static_cast<bool>(patchControlPointsConfig.dynamicValue);
983 // Returns true if the topology class is patches for tessellation.
984 bool patchesTopology () const
986 return (getTopologyClass(topologyConfig.staticValue) == TopologyClass::PATCH);
989 // Returns true if the test needs tessellation shaders.
990 bool needsTessellation () const
992 return (testPatchControlPoints() || patchesTopology());
995 // Returns true if the test needs an index buffer.
996 bool needsIndexBuffer () const
998 return static_cast<bool>(primRestartEnableConfig.dynamicValue);
1001 // Returns the appropriate color image format for the test.
1002 vk::VkFormat colorFormat () const
1004 // Pick int color format when testing logic op.
1005 return (testLogicOp() ? kIntColorFormat : kUnormColorFormat);
1008 // Returns the list of dynamic states affected by this config.
1009 std::vector<vk::VkDynamicState> getDynamicStates () const
1011 std::vector<vk::VkDynamicState> dynamicStates;
1013 if (cullModeConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
1014 if (frontFaceConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
1015 if (topologyConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
1016 if (viewportConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT);
1017 if (scissorConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT);
1018 if (strideConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
1019 if (depthTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
1020 if (depthWriteEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
1021 if (depthCompareOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
1022 if (depthBoundsTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
1023 if (stencilTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
1024 if (stencilOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
1025 if (vertexGenerator.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
1026 if (patchControlPointsConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
1027 if (rastDiscardEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT);
1028 if (depthBiasEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT);
1029 if (logicOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
1030 if (primRestartEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT);
1032 return dynamicStates;
1035 // Returns the list of extensions needed by this config.
1036 std::vector<std::string> getRequiredExtensions () const
1038 std::vector<std::string> extensions;
1040 if (cullModeConfig.dynamicValue
1041 || frontFaceConfig.dynamicValue
1042 || topologyConfig.dynamicValue
1043 || viewportConfig.dynamicValue
1044 || scissorConfig.dynamicValue
1045 || strideConfig.dynamicValue
1046 || depthTestEnableConfig.dynamicValue
1047 || depthWriteEnableConfig.dynamicValue
1048 || depthCompareOpConfig.dynamicValue
1049 || depthBoundsTestEnableConfig.dynamicValue
1050 || stencilTestEnableConfig.dynamicValue
1051 || stencilOpConfig.dynamicValue)
1053 extensions.push_back("VK_EXT_extended_dynamic_state");
1056 if (vertexGenerator.dynamicValue)
1058 extensions.push_back("VK_EXT_vertex_input_dynamic_state");
1061 if (patchControlPointsConfig.dynamicValue
1062 || rastDiscardEnableConfig.dynamicValue
1063 || depthBiasEnableConfig.dynamicValue
1064 || logicOpConfig.dynamicValue
1065 || primRestartEnableConfig.dynamicValue)
1067 extensions.push_back("VK_EXT_extended_dynamic_state2");
1074 // Extended dynamic state cases as created by createExtendedDynamicStateTests() are based on the assumption that, when a state
1075 // has a static and a dynamic value configured at the same time, the static value is wrong and the dynamic value will give
1076 // expected results. That's appropriate for most test variants, but in some others we want to reverse the situation: a dynamic
1077 // pipeline with wrong values and a static one with good values.
1079 // Instead of modifying how tests are created, we use isReversed() and swapValues() above, allowing us to swap static and
1080 // 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
1081 // given point in time in order to correctly answer some questions while running the test. m_swappedValues tracks that state.
1082 bool m_swappedValues;
1085 struct PushConstants
1087 tcu::Vec4 triangleColor;
1089 deInt32 viewPortIndex;
1096 void copy(vk::VkStencilOpState& dst, const StencilOpParams& src)
1098 dst.failOp = src.failOp;
1099 dst.passOp = src.passOp;
1100 dst.depthFailOp = src.depthFailOp;
1101 dst.compareOp = src.compareOp;
1104 class ExtendedDynamicStateTest : public vkt::TestCase
1107 ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig);
1108 virtual ~ExtendedDynamicStateTest (void) {}
1110 virtual void checkSupport (Context& context) const;
1111 virtual void initPrograms (vk::SourceCollections& programCollection) const;
1112 virtual TestInstance* createInstance (Context& context) const;
1115 TestConfig m_testConfig;
1118 class ExtendedDynamicStateInstance : public vkt::TestInstance
1121 ExtendedDynamicStateInstance (Context& context, const TestConfig& testConfig);
1122 virtual ~ExtendedDynamicStateInstance (void) {}
1124 virtual tcu::TestStatus iterate (void);
1127 TestConfig m_testConfig;
1130 ExtendedDynamicStateTest::ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig)
1131 : vkt::TestCase (testCtx, name, description)
1132 , m_testConfig (testConfig)
1134 const auto staticTopologyClass = getTopologyClass(testConfig.topologyConfig.staticValue);
1135 DE_UNREF(staticTopologyClass); // For release builds.
1137 // Matching topology classes.
1138 DE_ASSERT(!testConfig.topologyConfig.dynamicValue ||
1139 staticTopologyClass == getTopologyClass(testConfig.topologyConfig.dynamicValue.get()));
1141 // Supported topology classes for these tests.
1142 DE_ASSERT(staticTopologyClass == TopologyClass::LINE || staticTopologyClass == TopologyClass::TRIANGLE
1143 || staticTopologyClass == TopologyClass::PATCH);
1145 // Make sure these are consistent.
1146 DE_ASSERT(!(m_testConfig.testPatchControlPoints() && !m_testConfig.patchesTopology()));
1147 DE_ASSERT(!(m_testConfig.patchesTopology() && m_testConfig.getActivePatchControlPoints() <= 1u));
1150 void ExtendedDynamicStateTest::checkSupport (Context& context) const
1152 const auto& vki = context.getInstanceInterface();
1153 const auto physicalDevice = context.getPhysicalDevice();
1155 // Check extension support.
1156 const auto requiredExtensions = m_testConfig.getRequiredExtensions();
1157 for (const auto& extension : requiredExtensions)
1158 context.requireDeviceFunctionality(extension);
1160 // Needed for extended state included as part of VK_EXT_extended_dynamic_state2.
1161 if (de::contains(begin(requiredExtensions), end(requiredExtensions), "VK_EXT_extended_dynamic_state2"))
1163 const auto& eds2Features = context.getExtendedDynamicState2FeaturesEXT();
1165 if (m_testConfig.testLogicOp() && !eds2Features.extendedDynamicState2LogicOp)
1166 TCU_THROW(NotSupportedError, "VK_EXT_extended_dynamic_state2 : changing LogicOp dynamically is not supported");
1168 if (m_testConfig.testPatchControlPoints() && !eds2Features.extendedDynamicState2PatchControlPoints)
1169 TCU_THROW(NotSupportedError, "VK_EXT_extended_dynamic_state2 : changing patch control points dynamically is not supported");
1172 // Check the number of viewports needed and the corresponding limits.
1173 const auto& viewportConfig = m_testConfig.viewportConfig;
1174 auto numViewports = viewportConfig.staticValue.size();
1176 if (viewportConfig.dynamicValue)
1177 numViewports = std::max(numViewports, viewportConfig.dynamicValue.get().size());
1179 if (numViewports > 1)
1181 const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
1182 if (numViewports > static_cast<decltype(numViewports)>(properties.limits.maxViewports))
1183 TCU_THROW(NotSupportedError, "Number of viewports not supported (" + de::toString(numViewports) + ")");
1186 const auto& dbTestEnable = m_testConfig.depthBoundsTestEnableConfig;
1187 const bool useDepthBounds = (dbTestEnable.staticValue || (dbTestEnable.dynamicValue && dbTestEnable.dynamicValue.get()));
1189 if (useDepthBounds || m_testConfig.needsGeometryShader() || m_testConfig.needsTessellation())
1191 const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
1193 // Check depth bounds test support.
1194 if (useDepthBounds && !features.depthBounds)
1195 TCU_THROW(NotSupportedError, "Depth bounds feature not supported");
1197 // Check geometry shader support.
1198 if (m_testConfig.needsGeometryShader() && !features.geometryShader)
1199 TCU_THROW(NotSupportedError, "Geometry shader not supported");
1201 // Check tessellation support
1202 if (m_testConfig.needsTessellation() && !features.tessellationShader)
1203 TCU_THROW(NotSupportedError, "Tessellation feature not supported");
1206 // Check color image format support (depth/stencil will be chosen at runtime).
1207 const vk::VkFormatFeatureFlags kColorFeatures = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
1209 // Pick int color format for logic op
1210 vk::VkFormat colorFormat = m_testConfig.colorFormat();
1211 const auto colorProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, colorFormat);
1213 if ((colorProperties.optimalTilingFeatures & kColorFeatures) != kColorFeatures)
1214 TCU_THROW(NotSupportedError, "Required color image features not supported");
1217 void ExtendedDynamicStateTest::initPrograms (vk::SourceCollections& programCollection) const
1219 std::ostringstream pushSource;
1220 std::ostringstream vertSourceTemplateStream;
1221 std::ostringstream fragSource;
1222 std::ostringstream geomSource;
1223 std::ostringstream tescSource;
1224 std::ostringstream teseSource;
1227 << "layout(push_constant, std430) uniform PushConstantsBlock {\n"
1228 << " vec4 triangleColor;\n"
1229 << " float depthValue;\n"
1230 << " int viewPortIndex;\n"
1231 << " float scaleX;\n"
1232 << " float scaleY;\n"
1233 << " float offsetX;\n"
1234 << " float offsetY;\n"
1235 << "} pushConstants;\n"
1237 const auto pushConstants = pushSource.str();
1239 // The actual generator, attributes and calculations.
1240 const auto activeGen = m_testConfig.getActiveVertexGenerator();
1241 const auto attribDecls = activeGen->getAttributeDeclarations();
1242 const auto coordCalcs = activeGen->getVertexCoordCalc();
1244 // The static generator, attributes and calculations, for the static pipeline, if needed.
1245 const auto inactiveGen = m_testConfig.getInactiveVertexGenerator();
1246 const auto staticAttribDec = inactiveGen->getAttributeDeclarations();
1247 const auto staticCoordCalc = inactiveGen->getVertexCoordCalc();
1249 std::ostringstream activeAttribs;
1250 std::ostringstream activeCalcs;
1251 std::ostringstream inactiveAttribs;
1252 std::ostringstream inactiveCalcs;
1254 for (const auto& decl : attribDecls)
1255 activeAttribs << decl << "\n";
1257 for (const auto& statement : coordCalcs)
1258 activeCalcs << " " << statement << "\n";
1260 for (const auto& decl : staticAttribDec)
1261 inactiveAttribs << decl << "\n";
1263 for (const auto& statement : staticCoordCalc)
1264 inactiveCalcs << " " << statement << "\n";
1266 vertSourceTemplateStream
1270 << "out gl_PerVertex\n"
1272 << " vec4 gl_Position;\n"
1274 << "void main() {\n"
1275 << "${CALCULATIONS}"
1276 << " gl_Position = vec4(vertexCoords.x * pushConstants.scaleX + pushConstants.offsetX, vertexCoords.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
1280 tcu::StringTemplate vertSourceTemplate (vertSourceTemplateStream.str());
1282 std::map<std::string, std::string> activeMap;
1283 std::map<std::string, std::string> inactiveMap;
1285 activeMap["ATTRIBUTES"] = activeAttribs.str();
1286 activeMap["CALCULATIONS"] = activeCalcs.str();
1288 inactiveMap["ATTRIBUTES"] = inactiveAttribs.str();
1289 inactiveMap["CALCULATIONS"] = inactiveCalcs.str();
1291 const auto activeVertSource = vertSourceTemplate.specialize(activeMap);
1292 const auto inactiveVertSource = vertSourceTemplate.specialize(inactiveMap);
1294 const auto colorFormat = m_testConfig.colorFormat();
1295 const auto vecType = (vk::isUnormFormat(colorFormat) ? "vec4" : "uvec4");
1300 << "layout(location=0) out " << vecType << " color;\n"
1301 << "void main() {\n"
1302 << " color = " << vecType << "(pushConstants.triangleColor);\n"
1306 if (m_testConfig.needsGeometryShader())
1308 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
1309 const std::string inputPrimitive = ((topologyClass == TopologyClass::LINE) ? "lines" : "triangles");
1310 const deUint32 vertexCount = ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
1311 const std::string outputPrimitive = ((topologyClass == TopologyClass::LINE) ? "line_strip" : "triangle_strip");
1315 << "layout (" << inputPrimitive << ") in;\n"
1316 << "layout (" << outputPrimitive << ", max_vertices=" << vertexCount << ") out;\n"
1317 << (m_testConfig.isMultiViewport() ? pushConstants : "")
1318 << "in gl_PerVertex\n"
1320 << " vec4 gl_Position;\n"
1321 << "} gl_in[" << vertexCount << "];\n"
1322 << "out gl_PerVertex\n"
1324 << " vec4 gl_Position;\n"
1326 << "void main() {\n"
1327 << (m_testConfig.isMultiViewport() ? " gl_ViewportIndex = pushConstants.viewPortIndex;\n" : "")
1330 for (deUint32 i = 0; i < vertexCount; ++i)
1333 << " gl_Position = gl_in[" << i << "].gl_Position;\n"
1334 << " EmitVertex();\n"
1343 if (m_testConfig.needsTessellation())
1347 << "#extension GL_EXT_tessellation_shader : require\n"
1348 << "layout(vertices=3) out;\n"
1349 << "in gl_PerVertex\n"
1351 << " vec4 gl_Position;\n"
1352 << "} gl_in[gl_MaxPatchVertices];\n"
1353 << "out gl_PerVertex\n"
1355 << " vec4 gl_Position;\n"
1357 << "void main() {\n"
1358 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1359 << " gl_TessLevelOuter[0] = 3.0;\n"
1360 << " gl_TessLevelOuter[1] = 3.0;\n"
1361 << " gl_TessLevelOuter[2] = 3.0;\n"
1362 << " gl_TessLevelInner[0] = 3.0;\n"
1367 << "#extension GL_EXT_tessellation_shader : require\n"
1368 << "layout(triangles) in;\n"
1369 << "in gl_PerVertex\n"
1371 << " vec4 gl_Position;\n"
1372 << "} gl_in[gl_MaxPatchVertices];\n"
1373 << "out gl_PerVertex\n"
1375 << " vec4 gl_Position;\n"
1377 << "void main() {\n"
1378 << " gl_Position = (gl_in[0].gl_Position * gl_TessCoord.x + \n"
1379 << " gl_in[1].gl_Position * gl_TessCoord.y + \n"
1380 << " gl_in[2].gl_Position * gl_TessCoord.z);\n"
1386 programCollection.glslSources.add("vert") << glu::VertexSource(activeVertSource);
1387 programCollection.glslSources.add("vert2") << glu::VertexSource(inactiveVertSource);
1388 programCollection.glslSources.add("frag") << glu::FragmentSource(fragSource.str());
1389 if (m_testConfig.needsGeometryShader())
1390 programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource.str());
1391 if (m_testConfig.needsTessellation())
1393 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSource.str());
1394 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSource.str());
1398 TestInstance* ExtendedDynamicStateTest::createInstance (Context& context) const
1400 return new ExtendedDynamicStateInstance(context, m_testConfig);
1403 ExtendedDynamicStateInstance::ExtendedDynamicStateInstance(Context& context, const TestConfig& testConfig)
1404 : vkt::TestInstance (context)
1405 , m_testConfig (testConfig)
1409 struct VertexBufferInfo
1417 VertexBufferInfo (VertexBufferInfo&& other)
1418 : buffer (other.buffer.release())
1419 , offset (other.offset)
1420 , dataSize (other.dataSize)
1423 de::MovePtr<vk::BufferWithMemory> buffer;
1424 vk::VkDeviceSize offset;
1425 vk::VkDeviceSize dataSize;
1428 void logErrors(tcu::TestLog& log, const std::string& setName, const std::string& setDesc, const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& errorMask)
1430 log << tcu::TestLog::ImageSet(setName, setDesc)
1431 << tcu::TestLog::Image(setName + "Result", "Result image", result)
1432 << tcu::TestLog::Image(setName + "ErrorMask", "Error mask with errors marked in red", errorMask)
1433 << tcu::TestLog::EndImageSet;
1436 void copyAndFlush(const vk::DeviceInterface& vkd, vk::VkDevice device, vk::BufferWithMemory& buffer, size_t offset, const void* src, size_t size)
1438 auto& alloc = buffer.getAllocation();
1439 auto dst = reinterpret_cast<char*>(alloc.getHostPtr());
1441 deMemcpy(dst + offset, src, size);
1442 vk::flushAlloc(vkd, device, alloc);
1445 // Sets values for dynamic states if needed according to the test configuration.
1446 void setDynamicStates(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer)
1448 if (testConfig.cullModeConfig.dynamicValue)
1449 vkd.cmdSetCullModeEXT(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
1451 if (testConfig.frontFaceConfig.dynamicValue)
1452 vkd.cmdSetFrontFaceEXT(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
1454 if (testConfig.topologyConfig.dynamicValue)
1455 vkd.cmdSetPrimitiveTopologyEXT(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
1457 if (testConfig.viewportConfig.dynamicValue)
1459 const auto& viewports = testConfig.viewportConfig.dynamicValue.get();
1460 vkd.cmdSetViewportWithCountEXT(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
1463 if (testConfig.scissorConfig.dynamicValue)
1465 const auto& scissors = testConfig.scissorConfig.dynamicValue.get();
1466 vkd.cmdSetScissorWithCountEXT(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
1469 if (testConfig.depthTestEnableConfig.dynamicValue)
1470 vkd.cmdSetDepthTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
1472 if (testConfig.depthWriteEnableConfig.dynamicValue)
1473 vkd.cmdSetDepthWriteEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
1475 if (testConfig.depthCompareOpConfig.dynamicValue)
1476 vkd.cmdSetDepthCompareOpEXT(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
1478 if (testConfig.depthBoundsTestEnableConfig.dynamicValue)
1479 vkd.cmdSetDepthBoundsTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
1481 if (testConfig.stencilTestEnableConfig.dynamicValue)
1482 vkd.cmdSetStencilTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
1484 if (testConfig.depthBiasEnableConfig.dynamicValue)
1485 vkd.cmdSetDepthBiasEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBiasEnableConfig.dynamicValue.get()));
1487 if (testConfig.rastDiscardEnableConfig.dynamicValue)
1488 vkd.cmdSetRasterizerDiscardEnableEXT(cmdBuffer, makeVkBool32(testConfig.rastDiscardEnableConfig.dynamicValue.get()));
1490 if (testConfig.primRestartEnableConfig.dynamicValue)
1491 vkd.cmdSetPrimitiveRestartEnableEXT(cmdBuffer, makeVkBool32(testConfig.primRestartEnableConfig.dynamicValue.get()));
1493 if (testConfig.logicOpConfig.dynamicValue)
1494 vkd.cmdSetLogicOpEXT(cmdBuffer, testConfig.logicOpConfig.dynamicValue.get());
1496 if (testConfig.patchControlPointsConfig.dynamicValue)
1497 vkd.cmdSetPatchControlPointsEXT(cmdBuffer, testConfig.patchControlPointsConfig.dynamicValue.get());
1499 if (testConfig.stencilOpConfig.dynamicValue)
1501 for (const auto& params : testConfig.stencilOpConfig.dynamicValue.get())
1502 vkd.cmdSetStencilOpEXT(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
1505 if (testConfig.vertexGenerator.dynamicValue)
1507 const auto generator = testConfig.vertexGenerator.dynamicValue.get();
1508 const auto bindings = generator->getBindingDescriptions2(testConfig.strideConfig.staticValue);
1509 const auto attributes = generator->getAttributeDescriptions2();
1511 vkd.cmdSetVertexInputEXT(cmdBuffer,
1512 static_cast<deUint32>(bindings.size()), de::dataOrNull(bindings),
1513 static_cast<deUint32>(attributes.size()), de::dataOrNull(attributes));
1517 // Bind the appropriate vertex buffers using dynamic strides if the test configuration needs a dynamic stride.
1518 // Return true if the vertex buffer was bound.
1519 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)
1521 if (!testConfig.strideConfig.dynamicValue)
1524 const auto& viewportVec = testConfig.getActiveViewportVec();
1525 DE_UNREF(viewportVec); // For release builds.
1527 // When dynamically setting the vertex buffer stride, we cannot bind the vertex buffer in advance for some sequence
1528 // orderings if we have several viewports or meshes.
1529 DE_ASSERT((viewportVec.size() == 1u && testConfig.meshParams.size() == 1u)
1530 || testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW
1531 || testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
1533 // Split buffers, offsets, sizes and strides into their own vectors for the call.
1534 std::vector<vk::VkBuffer> buffers;
1535 std::vector<vk::VkDeviceSize> offsets;
1536 std::vector<vk::VkDeviceSize> sizes;
1537 const auto strides = testConfig.strideConfig.dynamicValue.get();
1539 const auto& chosenBuffers = (testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers);
1541 buffers.reserve (chosenBuffers.size());
1542 offsets.reserve (chosenBuffers.size());
1543 sizes.reserve (chosenBuffers.size());
1544 DE_ASSERT(chosenBuffers.size() == strides.size());
1546 for (const auto& vertBuffer : chosenBuffers)
1548 buffers.push_back (vertBuffer.buffer->get());
1549 offsets.push_back (vertBuffer.offset);
1550 sizes.push_back (vertBuffer.dataSize);
1553 vkd.cmdBindVertexBuffers2EXT(cmdBuffer, 0u, static_cast<deUint32>(chosenBuffers.size()), buffers.data(), offsets.data(), sizes.data(), strides.data());
1558 // Bind the given vertex buffers with the non-dynamic call. Similar to maybeBindVertexBufferDynStride but simpler.
1559 void bindVertexBuffers (const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer, const std::vector<VertexBufferInfo>& vertexBuffers)
1561 std::vector<vk::VkBuffer> buffers;
1562 std::vector<vk::VkDeviceSize> offsets;
1564 buffers.reserve (vertexBuffers.size());
1565 offsets.reserve (vertexBuffers.size());
1567 for (const auto& vertBuffer : vertexBuffers)
1569 buffers.push_back (vertBuffer.buffer->get());
1570 offsets.push_back (vertBuffer.offset);
1573 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, static_cast<deUint32>(vertexBuffers.size()), buffers.data(), offsets.data());
1577 // Create a vector of VertexBufferInfo elements using the given vertex generator and set of vertices.
1578 void prepareVertexBuffers ( std::vector<VertexBufferInfo>& buffers,
1579 const vk::DeviceInterface& vkd,
1580 vk::VkDevice device,
1581 vk::Allocator& allocator,
1582 const VertexGenerator* generator,
1583 const std::vector<tcu::Vec2>& vertices,
1584 deUint32 dataOffset,
1585 deUint32 trailingSize)
1587 const deUint32 paddingBytes = 0xDEADBEEFu;
1588 const auto vertexData = generator->createVertexData(vertices, dataOffset, trailingSize, &paddingBytes, sizeof(paddingBytes));
1590 for (const auto& bufferBytes : vertexData)
1592 const auto bufferSize = static_cast<vk::VkDeviceSize>(de::dataSize(bufferBytes));
1593 const auto extraSize = static_cast<vk::VkDeviceSize>(dataOffset + trailingSize);
1594 DE_ASSERT(bufferSize > extraSize);
1595 const auto dataSize = bufferSize - extraSize;
1597 // Create a full-size buffer but remember the data size and offset for it.
1598 const auto createInfo = vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1600 VertexBufferInfo bufferInfo;
1601 bufferInfo.buffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(vkd, device, allocator, createInfo, vk::MemoryRequirement::HostVisible));
1602 bufferInfo.offset = static_cast<vk::VkDeviceSize>(dataOffset);
1603 bufferInfo.dataSize = dataSize;
1604 buffers.emplace_back(std::move(bufferInfo));
1606 // Copy the whole contents to the full buffer.
1607 copyAndFlush(vkd, device, *buffers.back().buffer, 0, bufferBytes.data(), de::dataSize(bufferBytes));
1611 tcu::TestStatus ExtendedDynamicStateInstance::iterate (void)
1613 using ImageWithMemoryVec = std::vector<std::unique_ptr<vk::ImageWithMemory>>;
1614 using ImageViewVec = std::vector<vk::Move<vk::VkImageView>>;
1615 using FramebufferVec = std::vector<vk::Move<vk::VkFramebuffer>>;
1617 const auto& vki = m_context.getInstanceInterface();
1618 const auto& vkd = m_context.getDeviceInterface();
1619 const auto physicalDevice = m_context.getPhysicalDevice();
1620 const auto device = m_context.getDevice();
1621 auto& allocator = m_context.getDefaultAllocator();
1622 const auto queue = m_context.getUniversalQueue();
1623 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1624 auto& log = m_context.getTestContext().getLog();
1626 const auto kReversed = m_testConfig.isReversed();
1627 const auto kNumIterations = m_testConfig.numIterations();
1628 const auto kSequenceOrdering = m_testConfig.sequenceOrdering;
1630 const auto kFramebufferExtent = vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u);
1631 const vk::VkImageUsageFlags kColorUsage = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1632 const vk::VkImageUsageFlags kDSUsage = (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1633 const vk::VkFormatFeatureFlags kDSFeatures = (vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
1634 const auto colorFormat = m_testConfig.colorFormat();
1636 // Choose depth/stencil format.
1637 const DepthStencilFormat* dsFormatInfo = nullptr;
1639 for (const auto& kDepthStencilFormat : kDepthStencilFormats)
1641 const auto dsProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kDepthStencilFormat.imageFormat);
1642 if ((dsProperties.optimalTilingFeatures & kDSFeatures) == kDSFeatures)
1644 dsFormatInfo = &kDepthStencilFormat;
1649 // Note: Not Supported insted of Fail because the transfer feature is not mandatory.
1651 TCU_THROW(NotSupportedError, "Required depth/stencil image features not supported");
1652 log << tcu::TestLog::Message << "Chosen depth/stencil format: " << dsFormatInfo->imageFormat << tcu::TestLog::EndMessage;
1654 // Swap static and dynamic values in the test configuration so the static pipeline ends up with the expected values for cases
1655 // where we will bind the static pipeline last before drawing.
1657 m_testConfig.swapValues();
1659 // Create color and depth/stencil images.
1660 ImageWithMemoryVec colorImages;
1661 ImageWithMemoryVec dsImages;
1663 const vk::VkImageCreateInfo colorImageInfo =
1665 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1666 nullptr, // const void* pNext;
1667 0u, // VkImageCreateFlags flags;
1668 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1669 colorFormat, // VkFormat format;
1670 kFramebufferExtent, // VkExtent3D extent;
1671 1u, // deUint32 mipLevels;
1672 1u, // deUint32 arrayLayers;
1673 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1674 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1675 kColorUsage, // VkImageUsageFlags usage;
1676 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1677 1u, // deUint32 queueFamilyIndexCount;
1678 &queueIndex, // const deUint32* pQueueFamilyIndices;
1679 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1681 for (deUint32 i = 0u; i < kNumIterations; ++i)
1682 colorImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, colorImageInfo, vk::MemoryRequirement::Any));
1684 const vk::VkImageCreateInfo dsImageInfo =
1686 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1687 nullptr, // const void* pNext;
1688 0u, // VkImageCreateFlags flags;
1689 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1690 dsFormatInfo->imageFormat, // VkFormat format;
1691 kFramebufferExtent, // VkExtent3D extent;
1692 1u, // deUint32 mipLevels;
1693 1u, // deUint32 arrayLayers;
1694 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1695 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1696 kDSUsage, // VkImageUsageFlags usage;
1697 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1698 1u, // deUint32 queueFamilyIndexCount;
1699 &queueIndex, // const deUint32* pQueueFamilyIndices;
1700 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1702 for (deUint32 i = 0u; i < kNumIterations; ++i)
1703 dsImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, dsImageInfo, vk::MemoryRequirement::Any));
1705 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1706 const auto dsSubresourceRange = vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
1708 ImageViewVec colorImageViews;
1709 ImageViewVec dsImageViews;
1711 for (const auto& img : colorImages)
1712 colorImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1714 for (const auto& img : dsImages)
1715 dsImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, dsFormatInfo->imageFormat, dsSubresourceRange));
1718 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
1719 const std::vector<deUint32> indices { 0, 1, 2, 3, 0xFFFFFFFF, 4, 5, 0, 3 };
1720 std::vector<tcu::Vec2> vertices;
1722 if (topologyClass == TopologyClass::TRIANGLE)
1724 // Full-screen triangle fan with 6 vertices.
1727 // +-------+-------+
1735 // +-------+-------+
1737 vertices.reserve(6u);
1738 vertices.push_back(tcu::Vec2( 0.0f, 1.0f));
1739 vertices.push_back(tcu::Vec2( 1.0f, 1.0f));
1740 vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
1741 vertices.push_back(tcu::Vec2( 0.0f, -1.0f));
1742 vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
1743 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
1745 else if (topologyClass == TopologyClass::PATCH)
1747 DE_ASSERT(m_testConfig.getActivePatchControlPoints() > 1u);
1749 // 2 triangles making a quad
1750 vertices.reserve(6u);
1751 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
1752 vertices.push_back(tcu::Vec2( 1.0f, 1.0f));
1753 vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
1754 vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
1755 vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
1756 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
1758 else // TopologyClass::LINE
1760 // 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.
1761 vertices.reserve(kFramebufferHeight * 4u);
1762 const float lineHeight = 2.0f / static_cast<float>(kFramebufferHeight);
1763 for (deUint32 rowIdx = 0; rowIdx < kFramebufferHeight; ++rowIdx)
1765 // Offset of 0.5 pixels + one line per row from -1 to 1.
1766 const float yCoord = (lineHeight / 2.0f) + lineHeight * static_cast<float>(rowIdx) - 1.0f;
1767 vertices.push_back(tcu::Vec2(-1.0f, yCoord));
1768 vertices.push_back(tcu::Vec2(-0.5f, yCoord));
1769 vertices.push_back(tcu::Vec2( 0.5f, yCoord));
1770 vertices.push_back(tcu::Vec2( 1.0f, yCoord));
1774 // Reversed vertices, except for the first one (0, 5, 4, 3, 2, 1): clockwise mesh for triangles. Not to be used with lines.
1775 std::vector<tcu::Vec2> rvertices;
1776 if (topologyClass == TopologyClass::TRIANGLE)
1778 DE_ASSERT(!vertices.empty());
1779 rvertices.reserve(vertices.size());
1780 rvertices.push_back(vertices[0]);
1781 std::copy_n(vertices.rbegin(), vertices.size() - 1u, std::back_inserter(rvertices));
1784 if (topologyClass != TopologyClass::TRIANGLE)
1786 for (const auto& mesh : m_testConfig.meshParams)
1788 DE_UNREF(mesh); // For release builds.
1789 DE_ASSERT(!mesh.reversed);
1793 // Buffers with vertex data for the different bindings.
1794 std::vector<VertexBufferInfo> vertBuffers;
1795 std::vector<VertexBufferInfo> rvertBuffers;
1798 const auto dataOffset = static_cast<deUint32>(m_testConfig.vertexDataOffset);
1799 const auto trailingSize = static_cast<deUint32>(m_testConfig.vertexDataExtraBytes);
1800 const auto generator = m_testConfig.getActiveVertexGenerator();
1801 prepareVertexBuffers(vertBuffers, vkd, device, allocator, generator, vertices, dataOffset, trailingSize);
1802 if (topologyClass == TopologyClass::TRIANGLE)
1803 prepareVertexBuffers(rvertBuffers, vkd, device, allocator, generator, rvertices, dataOffset, trailingSize);
1807 const auto indexDataSize = static_cast<vk::VkDeviceSize>(de::dataSize(indices));
1808 const auto indexBufferInfo = vk::makeBufferCreateInfo(indexDataSize, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
1809 vk::BufferWithMemory indexBuffer (vkd, device, allocator, indexBufferInfo, vk::MemoryRequirement::HostVisible);
1810 copyAndFlush(vkd, device, indexBuffer, 0, indices.data(), static_cast<size_t>(indexDataSize));
1812 // Descriptor set layout.
1813 vk::DescriptorSetLayoutBuilder layoutBuilder;
1814 const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1817 vk::VkShaderStageFlags pushConstantStageFlags = (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1818 if (m_testConfig.isMultiViewport())
1819 pushConstantStageFlags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1821 const vk::VkPushConstantRange pushConstantRange =
1823 pushConstantStageFlags, // VkShaderStageFlags stageFlags;
1824 0u, // deUint32 offset;
1825 static_cast<deUint32>(sizeof(PushConstants)), // deUint32 size;
1828 const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1830 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1831 nullptr, // const void* pNext;
1832 0u, // VkPipelineLayoutCreateFlags flags;
1833 1u, // deUint32 setLayoutCount;
1834 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
1835 1u, // deUint32 pushConstantRangeCount;
1836 &pushConstantRange, // const VkPushConstantRange* pPushConstantRanges;
1838 const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo);
1840 // Render pass with single subpass.
1841 const vk::VkAttachmentReference colorAttachmentReference =
1843 0u, // deUint32 attachment;
1844 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1847 const vk::VkAttachmentReference dsAttachmentReference =
1849 1u, // deUint32 attachment;
1850 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1853 const vk::VkSubpassDescription subpassDescription =
1855 0u, // VkSubpassDescriptionFlags flags;
1856 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1857 0u, // deUint32 inputAttachmentCount;
1858 nullptr, // const VkAttachmentReference* pInputAttachments;
1859 1u, // deUint32 colorAttachmentCount;
1860 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
1861 nullptr, // const VkAttachmentReference* pResolveAttachments;
1862 &dsAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
1863 0u, // deUint32 preserveAttachmentCount;
1864 nullptr, // const deUint32* pPreserveAttachments;
1867 std::vector<vk::VkAttachmentDescription> attachmentDescriptions;
1869 attachmentDescriptions.push_back(vk::VkAttachmentDescription
1871 0u, // VkAttachmentDescriptionFlags flags;
1872 colorFormat, // VkFormat format;
1873 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1874 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1875 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1876 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1877 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1878 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1879 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1882 attachmentDescriptions.push_back(vk::VkAttachmentDescription
1884 0u, // VkAttachmentDescriptionFlags flags;
1885 dsFormatInfo->imageFormat, // VkFormat format;
1886 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1887 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1888 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1889 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
1890 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
1891 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1892 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1895 const vk::VkRenderPassCreateInfo renderPassCreateInfo =
1897 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1898 nullptr, // const void* pNext;
1899 0u, // VkRenderPassCreateFlags flags;
1900 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
1901 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
1902 1u, // deUint32 subpassCount;
1903 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1904 0u, // deUint32 dependencyCount;
1905 nullptr, // const VkSubpassDependency* pDependencies;
1907 const auto renderPass = vk::createRenderPass(vkd, device, &renderPassCreateInfo);
1910 FramebufferVec framebuffers;
1912 DE_ASSERT(colorImageViews.size() == dsImageViews.size());
1913 for (size_t imgIdx = 0; imgIdx < colorImageViews.size(); ++imgIdx)
1915 std::vector<vk::VkImageView> attachments;
1916 attachments.push_back(colorImageViews[imgIdx].get());
1917 attachments.push_back(dsImageViews[imgIdx].get());
1919 const vk::VkFramebufferCreateInfo framebufferCreateInfo =
1921 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1922 nullptr, // const void* pNext;
1923 0u, // VkFramebufferCreateFlags flags;
1924 renderPass.get(), // VkRenderPass renderPass;
1925 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount;
1926 attachments.data(), // const VkImageView* pAttachments;
1927 kFramebufferWidth, // deUint32 width;
1928 kFramebufferHeight, // deUint32 height;
1929 1u, // deUint32 layers;
1932 framebuffers.emplace_back(vk::createFramebuffer(vkd, device, &framebufferCreateInfo));
1936 const auto vertModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1937 const auto vertModule2 = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert2"), 0u);
1938 const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1939 vk::Move<vk::VkShaderModule> geomModule;
1940 vk::Move<vk::VkShaderModule> tescModule;
1941 vk::Move<vk::VkShaderModule> teseModule;
1943 if (m_testConfig.needsGeometryShader())
1944 geomModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("geom"), 0u);
1946 if (m_testConfig.needsTessellation())
1948 tescModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("tesc"), 0u);
1949 teseModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("tese"), 0u);
1953 std::vector<vk::VkPipelineShaderStageCreateInfo> shaderStages;
1954 std::vector<vk::VkPipelineShaderStageCreateInfo> shaderStaticStages;
1956 vk::VkPipelineShaderStageCreateInfo shaderStageCreateInfo =
1958 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1959 nullptr, // const void* pNext;
1960 0u, // VkPipelineShaderStageCreateFlags flags;
1961 vk::VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
1962 fragModule.get(), // VkShaderModule module;
1963 "main", // const char* pName;
1964 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
1967 shaderStages.push_back(shaderStageCreateInfo);
1969 if (m_testConfig.needsGeometryShader())
1971 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1972 shaderStageCreateInfo.module = geomModule.get();
1973 shaderStages.push_back(shaderStageCreateInfo);
1976 if (m_testConfig.needsTessellation())
1978 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1979 shaderStageCreateInfo.module = tescModule.get();
1980 shaderStages.push_back(shaderStageCreateInfo);
1982 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1983 shaderStageCreateInfo.module = teseModule.get();
1984 shaderStages.push_back(shaderStageCreateInfo);
1987 // Both vectors are the same up to here. Then, they differ in the vertex stage.
1988 shaderStaticStages = shaderStages;
1989 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_VERTEX_BIT;
1991 shaderStageCreateInfo.module = vertModule.get();
1992 shaderStages.push_back(shaderStageCreateInfo);
1994 shaderStageCreateInfo.module = vertModule2.get();
1995 shaderStaticStages.push_back(shaderStageCreateInfo);
1998 const auto vertexBindings = m_testConfig.vertexGenerator.staticValue->getBindingDescriptions(m_testConfig.strideConfig.staticValue);
1999 const auto vertexAttributes = m_testConfig.vertexGenerator.staticValue->getAttributeDescriptions();
2001 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
2003 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2004 nullptr, // const void* pNext;
2005 0u, // VkPipelineVertexInputStateCreateFlags flags;
2006 static_cast<deUint32>(vertexBindings.size()), // deUint32 vertexBindingDescriptionCount;
2007 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2008 static_cast<deUint32>(vertexAttributes.size()), // deUint32 vertexAttributeDescriptionCount;
2009 vertexAttributes.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2013 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
2015 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
2016 nullptr, // const void* pNext;
2017 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
2018 m_testConfig.topologyConfig.staticValue, // VkPrimitiveTopology topology;
2019 makeVkBool32(m_testConfig.primRestartEnableConfig.staticValue), // VkBool32 primitiveRestartEnable;
2023 if (m_testConfig.viewportConfig.dynamicValue)
2024 DE_ASSERT(m_testConfig.viewportConfig.dynamicValue.get().size() > 0u);
2026 DE_ASSERT(m_testConfig.viewportConfig.staticValue.size() > 0u);
2028 if (m_testConfig.scissorConfig.dynamicValue)
2029 DE_ASSERT(m_testConfig.scissorConfig.dynamicValue.get().size() > 0u);
2031 DE_ASSERT(m_testConfig.scissorConfig.staticValue.size() > 0u);
2033 // The viewport and scissor counts must match in the static part, which will be used by the static pipeline.
2034 const auto minStaticCount = static_cast<deUint32>(std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
2036 // For the static pipeline.
2037 const vk::VkPipelineViewportStateCreateInfo staticViewportStateCreateInfo =
2039 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2040 nullptr, // const void* pNext;
2041 0u, // VkPipelineViewportStateCreateFlags flags;
2042 minStaticCount, // deUint32 viewportCount;
2043 m_testConfig.viewportConfig.staticValue.data(), // const VkViewport* pViewports;
2044 minStaticCount, // deUint32 scissorCount;
2045 m_testConfig.scissorConfig.staticValue.data(), // const VkRect2D* pScissors;
2048 // For the dynamic pipeline.
2049 const auto finalDynamicViewportCount = (m_testConfig.viewportConfig.dynamicValue
2050 ? m_testConfig.viewportConfig.dynamicValue.get().size()
2051 : m_testConfig.viewportConfig.staticValue.size());
2053 const auto finalDynamicScissorCount = (m_testConfig.scissorConfig.dynamicValue
2054 ? m_testConfig.scissorConfig.dynamicValue.get().size()
2055 : m_testConfig.scissorConfig.staticValue.size());
2057 const auto minDynamicCount = static_cast<deUint32>(std::min(finalDynamicScissorCount, finalDynamicViewportCount));
2059 // The viewport and scissor counts must be zero when a dynamic value will be provided, as per the spec.
2060 const vk::VkPipelineViewportStateCreateInfo dynamicViewportStateCreateInfo =
2062 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2063 nullptr, // const void* pNext;
2064 0u, // VkPipelineViewportStateCreateFlags flags;
2065 (m_testConfig.viewportConfig.dynamicValue ? 0u : minDynamicCount), // deUint32 viewportCount;
2066 m_testConfig.viewportConfig.staticValue.data(), // const VkViewport* pViewports;
2067 (m_testConfig.scissorConfig.dynamicValue ? 0u : minDynamicCount), // deUint32 scissorCount;
2068 m_testConfig.scissorConfig.staticValue.data(), // const VkRect2D* pScissors;
2071 // Rasterization state.
2072 vk::VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
2074 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2075 nullptr, // const void* pNext;
2076 0u, // VkPipelineRasterizationStateCreateFlags flags;
2077 VK_FALSE, // VkBool32 depthClampEnable;
2078 makeVkBool32(m_testConfig.rastDiscardEnableConfig.staticValue), // VkBool32 rasterizerDiscardEnable;
2079 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
2080 m_testConfig.cullModeConfig.staticValue, // VkCullModeFlags cullMode;
2081 m_testConfig.frontFaceConfig.staticValue, // VkFrontFace frontFace;
2082 makeVkBool32(m_testConfig.depthBiasEnableConfig.staticValue), // VkBool32 depthBiasEnable;
2083 // Change the depth bias parameters if depth bias is dynamic
2084 m_testConfig.depthBiasEnableConfig.dynamicValue ? 2e7f : 0.0f, // float depthBiasConstantFactor;
2085 m_testConfig.depthBiasEnableConfig.dynamicValue ? 0.25f : 0.0f, // float depthBiasClamp;
2086 0.0f, // float depthBiasSlopeFactor;
2087 1.0f, // float lineWidth;
2090 // Multisample state.
2091 const vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
2093 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2094 nullptr, // const void* pNext;
2095 0u, // VkPipelineMultisampleStateCreateFlags flags;
2096 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
2097 VK_FALSE, // VkBool32 sampleShadingEnable;
2098 0.0f, // float minSampleShading;
2099 nullptr, // const VkSampleMask* pSampleMask;
2100 VK_FALSE, // VkBool32 alphaToCoverageEnable;
2101 VK_FALSE, // VkBool32 alphaToOneEnable;
2104 // Depth/stencil state.
2105 vk::VkStencilOpState staticFrontStencil;
2106 vk::VkStencilOpState staticBackStencil;
2107 bool staticFrontStencilSet = false;
2108 bool staticBackStencilSet = false;
2110 // Common setup for the front and back operations.
2111 staticFrontStencil.compareMask = 0xFFu;
2112 staticFrontStencil.writeMask = 0xFFu;
2113 staticFrontStencil.reference = m_testConfig.referenceStencil;
2114 staticBackStencil = staticFrontStencil;
2116 for (const auto& op : m_testConfig.stencilOpConfig.staticValue)
2118 if ((op.faceMask & vk::VK_STENCIL_FACE_FRONT_BIT) != 0u)
2120 copy(staticFrontStencil, op);
2121 staticFrontStencilSet = true;
2123 if ((op.faceMask & vk::VK_STENCIL_FACE_BACK_BIT) != 0u)
2125 copy(staticBackStencil, op);
2126 staticBackStencilSet = true;
2130 // Default values for the static part.
2131 if (!staticFrontStencilSet)
2132 copy(staticFrontStencil, kDefaultStencilOpParams);
2133 if (!staticBackStencilSet)
2134 copy(staticBackStencil, kDefaultStencilOpParams);
2136 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
2138 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
2139 nullptr, // const void* pNext;
2140 0u, // VkPipelineDepthStencilStateCreateFlags flags;
2141 makeVkBool32(m_testConfig.depthTestEnableConfig.staticValue), // VkBool32 depthTestEnable;
2142 makeVkBool32(m_testConfig.depthWriteEnableConfig.staticValue), // VkBool32 depthWriteEnable;
2143 m_testConfig.depthCompareOpConfig.staticValue, // VkCompareOp depthCompareOp;
2144 makeVkBool32(m_testConfig.depthBoundsTestEnableConfig.staticValue), // VkBool32 depthBoundsTestEnable;
2145 makeVkBool32(m_testConfig.stencilTestEnableConfig.staticValue), // VkBool32 stencilTestEnable;
2146 staticFrontStencil, // VkStencilOpState front;
2147 staticBackStencil, // VkStencilOpState back;
2148 m_testConfig.minDepthBounds, // float minDepthBounds;
2149 m_testConfig.maxDepthBounds, // float maxDepthBounds;
2152 // Dynamic state. Here we will set all states which have a dynamic value.
2153 const auto dynamicStates = m_testConfig.getDynamicStates();
2155 const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
2157 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
2158 nullptr, // const void* pNext;
2159 0u, // VkPipelineDynamicStateCreateFlags flags;
2160 static_cast<deUint32>(dynamicStates.size()), // deUint32 dynamicStateCount;
2161 de::dataOrNull(dynamicStates), // const VkDynamicState* pDynamicStates;
2164 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
2166 VK_FALSE, // VkBool32 blendEnable
2167 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
2168 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
2169 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
2170 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
2171 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
2172 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
2173 vk::VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
2174 | vk::VK_COLOR_COMPONENT_G_BIT
2175 | vk::VK_COLOR_COMPONENT_B_BIT
2176 | vk::VK_COLOR_COMPONENT_A_BIT
2179 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
2181 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
2182 nullptr, // const void* pNext
2183 0u, // VkPipelineColorBlendStateCreateFlags flags
2184 makeVkBool32(m_testConfig.testLogicOp()), // VkBool32 logicOpEnable
2185 m_testConfig.logicOpConfig.staticValue, // VkLogicOp logicOp
2186 1u, // deUint32 attachmentCount
2187 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
2188 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
2191 const vk::VkPipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo =
2193 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType
2194 nullptr, // const void* pNext
2195 0u, // VkPipelineTessellationStateCreateFlags flags
2196 m_testConfig.patchControlPointsConfig.staticValue, // uint32_t patchControlPoints
2199 const auto pTessellationState = (m_testConfig.needsTessellation() ? &pipelineTessellationStateCreateInfo : nullptr);
2201 const vk::VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfoTemplate =
2203 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
2204 nullptr, // const void* pNext;
2205 0u, // VkPipelineCreateFlags flags;
2206 static_cast<deUint32>(shaderStages.size()), // deUint32 stageCount;
2207 shaderStages.data(), // const VkPipelineShaderStageCreateInfo* pStages;
2208 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
2209 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
2210 pTessellationState, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
2211 nullptr, // const VkPipelineViewportStateCreateInfo * pViewportState;
2212 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
2213 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
2214 &depthStencilStateCreateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
2215 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
2216 nullptr, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2217 pipelineLayout.get(), // VkPipelineLayout layout;
2218 renderPass.get(), // VkRenderPass renderPass;
2219 0u, // deUint32 subpass;
2220 DE_NULL, // VkPipeline basePipelineHandle;
2221 0, // deInt32 basePipelineIndex;
2224 vk::Move<vk::VkPipeline> staticPipeline;
2225 const bool bindStaticFirst = (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES ||
2226 kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES ||
2227 kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC);
2228 const bool useStaticPipeline = (bindStaticFirst || kReversed);
2230 // Create static pipeline when needed.
2231 if (useStaticPipeline)
2233 auto staticPipelineCreateInfo = graphicsPipelineCreateInfoTemplate;
2234 staticPipelineCreateInfo.pViewportState = &staticViewportStateCreateInfo;
2235 staticPipelineCreateInfo.pStages = shaderStaticStages.data();
2236 staticPipeline = vk::createGraphicsPipeline(vkd, device, DE_NULL, &staticPipelineCreateInfo);
2239 // Create dynamic pipeline.
2240 vk::Move<vk::VkPipeline> graphicsPipeline;
2242 auto dynamicPipelineCreateInfo = graphicsPipelineCreateInfoTemplate;
2243 dynamicPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
2244 dynamicPipelineCreateInfo.pViewportState = &dynamicViewportStateCreateInfo;
2245 graphicsPipeline = vk::createGraphicsPipeline(vkd, device, DE_NULL, &dynamicPipelineCreateInfo);
2249 const auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
2250 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd , device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2251 const auto cmdBuffer = cmdBufferPtr.get();
2253 // Clear values, clear to green for dynamic logicOp
2254 std::vector<vk::VkClearValue> clearValues;
2255 clearValues.push_back(m_testConfig.clearColorValue);
2256 clearValues.push_back(vk::makeClearValueDepthStencil(m_testConfig.clearDepthValue, m_testConfig.clearStencilValue));
2258 // Record command buffer.
2259 vk::beginCommandBuffer(vkd, cmdBuffer);
2261 for (deUint32 iteration = 0u; iteration < kNumIterations; ++iteration)
2263 // Track in-advance vertex buffer binding.
2264 bool boundInAdvance = false;
2266 // Maybe set extended dynamic state here.
2267 if (kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START)
2269 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2270 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
2273 // Begin render pass.
2274 vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffers[iteration].get(), vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
2276 // Bind a static pipeline first if needed.
2277 if (bindStaticFirst && iteration == 0u)
2278 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, staticPipeline.get());
2280 // Maybe set extended dynamic state here.
2281 if (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES)
2283 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2284 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
2287 // Bind dynamic pipeline.
2288 if ((kSequenceOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC &&
2289 kSequenceOrdering != SequenceOrdering::TWO_DRAWS_STATIC) ||
2290 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
2291 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
2293 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
2296 if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
2297 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
2298 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
2300 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2301 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
2304 // Bind a static pipeline last if needed.
2305 if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
2306 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration > 0u))
2308 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, staticPipeline.get());
2311 const auto& viewportVec = m_testConfig.getActiveViewportVec();
2312 for (size_t viewportIdx = 0u; viewportIdx < viewportVec.size(); ++viewportIdx)
2314 for (size_t meshIdx = 0u; meshIdx < m_testConfig.meshParams.size(); ++meshIdx)
2317 PushConstants pushConstants =
2319 m_testConfig.meshParams[meshIdx].color, // tcu::Vec4 triangleColor;
2320 m_testConfig.meshParams[meshIdx].depth, // float meshDepth;
2321 static_cast<deInt32>(viewportIdx), // deInt32 viewPortIndex;
2322 m_testConfig.meshParams[meshIdx].scaleX, // float scaleX;
2323 m_testConfig.meshParams[meshIdx].scaleY, // float scaleY;
2324 m_testConfig.meshParams[meshIdx].offsetX, // float offsetX;
2325 m_testConfig.meshParams[meshIdx].offsetY, // float offsetY;
2327 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantStageFlags, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
2329 // Track vertex bounding state for this mesh.
2330 bool boundBeforeDraw = false;
2332 // Maybe set extended dynamic state here.
2333 if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW || kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES)
2335 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2336 boundBeforeDraw = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, meshIdx, vertBuffers, rvertBuffers);
2339 // Bind vertex buffer with static stride if needed and draw.
2340 if (!(boundInAdvance || boundBeforeDraw))
2342 bindVertexBuffers(vkd, cmdBuffer, (m_testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers));
2343 if (m_testConfig.needsIndexBuffer())
2345 vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), 0, vk::VK_INDEX_TYPE_UINT32);
2350 if (m_testConfig.needsIndexBuffer())
2352 deUint32 numIndices = static_cast<deUint32>(indices.size());
2353 // For SequenceOrdering::TWO_DRAWS_DYNAMIC and TWO_DRAWS_STATIC cases, the first draw does not have primitive restart enabled
2354 // So, draw without using the invalid (0xFFFFFFFF) index, the second draw with primitive restart enabled will replace the results
2355 // using all indices.
2356 if (iteration == 0u &&
2357 (m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
2358 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
2360 vkd.cmdDrawIndexed(cmdBuffer, numIndices, 1u, 0u, 0u, 0u);
2363 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
2367 vk::endRenderPass(vkd, cmdBuffer);
2370 vk::endCommandBuffer(vkd, cmdBuffer);
2373 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2375 // Read result image aspects from the last used framebuffer.
2376 const tcu::UVec2 renderSize (kFramebufferWidth, kFramebufferHeight);
2377 const auto colorBuffer = readColorAttachment(vkd, device, queue, queueIndex, allocator, colorImages.back()->get(), colorFormat, renderSize);
2378 const auto depthBuffer = readDepthAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize);
2379 const auto stencilBuffer = readStencilAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
2380 const auto colorAccess = colorBuffer->getAccess();
2381 const auto depthAccess = depthBuffer->getAccess();
2382 const auto stencilAccess = stencilBuffer->getAccess();
2384 const int kWidth = static_cast<int>(kFramebufferWidth);
2385 const int kHeight = static_cast<int>(kFramebufferHeight);
2387 // Generate reference color buffer.
2388 const auto tcuColorFormat = vk::mapVkFormat(colorFormat);
2389 tcu::TextureLevel referenceColorLevel (tcuColorFormat, kWidth, kHeight);
2390 tcu::PixelBufferAccess referenceColorAccess = referenceColorLevel.getAccess();
2391 m_testConfig.referenceColor(referenceColorAccess);
2393 const tcu::TextureFormat errorFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
2394 tcu::TextureLevel colorError (errorFormat, kWidth, kHeight);
2395 tcu::TextureLevel depthError (errorFormat, kWidth, kHeight);
2396 tcu::TextureLevel stencilError (errorFormat, kWidth, kHeight);
2397 const auto colorErrorAccess = colorError.getAccess();
2398 const auto depthErrorAccess = depthError.getAccess();
2399 const auto stencilErrorAccess = stencilError.getAccess();
2400 const tcu::Vec4 kGood (0.0f, 1.0f, 0.0f, 1.0f);
2401 const tcu::Vec4 kBad (1.0f, 0.0f, 0.0f, 1.0f);
2403 // Check expected values.
2404 const auto minDepth = m_testConfig.expectedDepth - dsFormatInfo->depthThreshold;
2405 const auto maxDepth = m_testConfig.expectedDepth + dsFormatInfo->depthThreshold;
2406 bool colorMatch = true;
2407 bool depthMatch = true;
2408 bool stencilMatch = true;
2411 for (int y = 0; y < kHeight; ++y)
2412 for (int x = 0; x < kWidth; ++x)
2414 if (vk::isUnormFormat(colorFormat))
2416 auto colorPixel = colorAccess.getPixel(x, y);
2417 auto expectedPixel = referenceColorAccess.getPixel(x, y);
2418 match = tcu::boolAll(tcu::lessThan(tcu::absDiff(colorPixel, expectedPixel), kUnormColorThreshold));
2422 DE_ASSERT(vk::isUintFormat(colorFormat));
2423 auto colorPixel = colorAccess.getPixelUint(x, y);
2424 auto expectedPixel = referenceColorAccess.getPixelUint(x, y);
2425 match = (colorPixel == expectedPixel);
2428 colorErrorAccess.setPixel((match ? kGood : kBad), x, y);
2432 const auto depthPixel = depthAccess.getPixDepth(x, y);
2433 match = de::inRange(depthPixel, minDepth, maxDepth);
2434 depthErrorAccess.setPixel((match ? kGood : kBad), x, y);
2438 const auto stencilPixel = static_cast<deUint32>(stencilAccess.getPixStencil(x, y));
2439 match = (stencilPixel == m_testConfig.expectedStencil);
2440 stencilErrorAccess.setPixel((match ? kGood : kBad), x, y);
2442 stencilMatch = false;
2445 if (!(colorMatch && depthMatch && stencilMatch))
2448 logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
2451 logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
2454 logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
2456 return tcu::TestStatus::fail("Incorrect value found in attachments; please check logged images");
2459 return tcu::TestStatus::pass("Pass");
2462 bool stencilPasses(vk::VkCompareOp op, deUint8 storedValue, deUint8 referenceValue)
2466 case vk::VK_COMPARE_OP_NEVER: return false;
2467 case vk::VK_COMPARE_OP_LESS: return (referenceValue < storedValue);
2468 case vk::VK_COMPARE_OP_EQUAL: return (referenceValue == storedValue);
2469 case vk::VK_COMPARE_OP_LESS_OR_EQUAL: return (referenceValue <= storedValue);
2470 case vk::VK_COMPARE_OP_GREATER: return (referenceValue > storedValue);
2471 case vk::VK_COMPARE_OP_GREATER_OR_EQUAL: return (referenceValue >= storedValue);
2472 case vk::VK_COMPARE_OP_ALWAYS: return true;
2473 default: DE_ASSERT(false); return false;
2476 return false; // Unreachable.
2479 deUint8 stencilResult(vk::VkStencilOp op, deUint8 storedValue, deUint8 referenceValue, deUint8 min, deUint8 max)
2481 deUint8 result = storedValue;
2485 case vk::VK_STENCIL_OP_KEEP: break;
2486 case vk::VK_STENCIL_OP_ZERO: result = 0; break;
2487 case vk::VK_STENCIL_OP_REPLACE: result = referenceValue; break;
2488 case vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP: result = ((result == max) ? result : static_cast<deUint8>(result + 1)); break;
2489 case vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP: result = ((result == min) ? result : static_cast<deUint8>(result - 1)); break;
2490 case vk::VK_STENCIL_OP_INVERT: result = static_cast<deUint8>(~result); break;
2491 case vk::VK_STENCIL_OP_INCREMENT_AND_WRAP: result = ((result == max) ? min : static_cast<deUint8>(result + 1)); break;
2492 case vk::VK_STENCIL_OP_DECREMENT_AND_WRAP: result = ((result == min) ? max : static_cast<deUint8>(result - 1)); break;
2493 default: DE_ASSERT(false); break;
2499 } // anonymous namespace
2501 tcu::TestCaseGroup* createExtendedDynamicStateTests (tcu::TestContext& testCtx)
2503 de::MovePtr<tcu::TestCaseGroup> extendedDynamicStateGroup(new tcu::TestCaseGroup(testCtx, "extended_dynamic_state", "Tests for VK_EXT_extended_dynamic_state"));
2505 // Auxiliar constants.
2506 const deUint32 kHalfWidthU = kFramebufferWidth/2u;
2507 const deInt32 kHalfWidthI = static_cast<deInt32>(kHalfWidthU);
2508 const float kHalfWidthF = static_cast<float>(kHalfWidthU);
2509 const float kHeightF = static_cast<float>(kFramebufferHeight);
2513 SequenceOrdering ordering;
2516 } kOrderingCases[] =
2518 { SequenceOrdering::CMD_BUFFER_START, "cmd_buffer_start", "Dynamic state set after command buffer start" },
2519 { SequenceOrdering::BEFORE_DRAW, "before_draw", "Dynamic state set just before drawing" },
2520 { SequenceOrdering::BETWEEN_PIPELINES, "between_pipelines", "Dynamic after a pipeline with static states has been bound and before a pipeline with dynamic states has been bound" },
2521 { SequenceOrdering::AFTER_PIPELINES, "after_pipelines", "Dynamic state set after both a static-state pipeline and a second dynamic-state pipeline have been bound" },
2522 { SequenceOrdering::BEFORE_GOOD_STATIC, "before_good_static", "Dynamic state set after a dynamic pipeline has been bound and before a second static-state pipeline with the right values has been bound" },
2523 { SequenceOrdering::TWO_DRAWS_DYNAMIC, "two_draws_dynamic", "Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again" },
2524 { SequenceOrdering::TWO_DRAWS_STATIC, "two_draws_static", "Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again" },
2527 for (const auto& kOrderingCase : kOrderingCases)
2529 const auto& kOrdering = kOrderingCase.ordering;
2531 de::MovePtr<tcu::TestCaseGroup> orderingGroup(new tcu::TestCaseGroup(testCtx, kOrderingCase.name.c_str(), kOrderingCase.desc.c_str()));
2535 TestConfig config(kOrdering);
2536 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
2537 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE);
2538 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_none", "Dynamically set cull mode to none", config));
2541 TestConfig config(kOrdering);
2542 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_AND_BACK;
2543 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_BACK_BIT);
2544 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_back", "Dynamically set cull mode to back", config));
2547 TestConfig config(kOrdering);
2548 // Make triangles look back.
2549 config.meshParams[0].reversed = true;
2550 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2551 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_BIT);
2552 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front", "Dynamically set cull mode to front", config));
2555 TestConfig config(kOrdering);
2556 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_NONE;
2557 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_AND_BACK);
2558 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2559 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front_and_back", "Dynamically set cull mode to front and back", config));
2564 TestConfig config(kOrdering);
2565 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2566 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
2567 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
2568 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw", "Dynamically set front face to clockwise", config));
2571 TestConfig config(kOrdering);
2572 // Pass triangles in clockwise order.
2573 config.meshParams[0].reversed = true;
2574 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2575 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
2576 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
2577 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw", "Dynamically set front face to counter-clockwise", config));
2580 TestConfig config(kOrdering);
2581 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2582 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
2583 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
2584 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2585 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw_reversed", "Dynamically set front face to clockwise with a counter-clockwise mesh", config));
2588 TestConfig config(kOrdering);
2589 // Pass triangles in clockwise order.
2590 config.meshParams[0].reversed = true;
2591 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2592 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
2593 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
2594 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2595 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw_reversed", "Dynamically set front face to counter-clockwise with a clockwise mesh", config));
2598 // Rasterizer discard
2600 TestConfig config(kOrdering);
2601 config.rastDiscardEnableConfig.staticValue = false;
2602 config.rastDiscardEnableConfig.dynamicValue = tcu::just(true);
2603 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2604 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "disable_raster", "Dynamically disable rasterizer", config));
2607 TestConfig config(kOrdering);
2608 config.rastDiscardEnableConfig.staticValue = true;
2609 config.rastDiscardEnableConfig.dynamicValue = tcu::just(false);
2610 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "enable_raster", "Dynamically enable rasterizer", config));
2615 TestConfig config(kOrdering);
2616 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_CLEAR;
2617 config.logicOpConfig.dynamicValue = tcu::just<vk::VkLogicOp>(vk::VK_LOGIC_OP_OR);
2618 // Clear to green, paint in blue, expect cyan due to logic op.
2619 config.meshParams[0].color = kLogicOpTriangleColor;
2620 config.clearColorValue = vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
2621 config.referenceColor = SingleColorGenerator(kLogicOpFinalColor);
2622 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_or", "Dynamically change logic op to VK_LOGIC_OP_OR", config));
2625 // Dynamically enable primitive restart
2627 TestConfig config(kOrdering);
2628 config.primRestartEnableConfig.staticValue = false;
2629 config.primRestartEnableConfig.dynamicValue = tcu::just(true);
2630 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "prim_restart_enable", "Dynamically enable primitiveRestart", config));
2633 // Dynamically change the number of primitive control points
2635 TestConfig config(kOrdering);
2636 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
2637 config.patchControlPointsConfig.staticValue = 1;
2638 config.patchControlPointsConfig.dynamicValue = 3;
2639 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "patch_control_points", "Dynamically change patch control points", config));
2642 // Dynamic topology.
2644 TestConfig baseConfig(kOrdering);
2646 for (int i = 0; i < 2; ++i)
2648 const bool forceGeometryShader = (i > 0);
2652 vk::VkPrimitiveTopology staticVal;
2653 vk::VkPrimitiveTopology dynamicVal;
2654 } kTopologyCases[] =
2656 { vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN },
2657 { vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP },
2658 { vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST },
2661 for (const auto& kTopologyCase : kTopologyCases)
2663 TestConfig config(baseConfig);
2664 config.forceGeometryShader = forceGeometryShader;
2665 config.topologyConfig.staticValue = kTopologyCase.staticVal;
2666 config.topologyConfig.dynamicValue = tcu::just<vk::VkPrimitiveTopology>(kTopologyCase.dynamicVal);
2667 config.patchControlPointsConfig.staticValue = (config.needsTessellation() ? 3u : 1u);
2669 const std::string className = topologyClassName(getTopologyClass(config.topologyConfig.staticValue));
2670 const std::string name = "topology_" + className + (forceGeometryShader ? "_geom" : "");
2671 const std::string desc = "Dynamically switch primitive topologies from the " + className + " class" + (forceGeometryShader ? " and use a geometry shader" : "");
2672 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, name, desc, config));
2679 TestConfig config(kOrdering);
2680 // 2 scissors, bad static single viewport.
2681 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
2682 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
2683 config.viewportConfig.dynamicValue = ViewportVec{
2684 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2685 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2687 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports", "Dynamically set 2 viewports", config));
2690 TestConfig config(kOrdering);
2691 // Bad static reduced viewport.
2692 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
2693 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight));
2694 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_viewport", "Dynamically set viewport to cover full framebuffer", config));
2697 TestConfig config(kOrdering);
2698 // 2 scissors (left half, right half), 2 reversed static viewports that need fixing (right, left).
2699 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
2700 config.viewportConfig.staticValue = ViewportVec{
2701 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
2702 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
2704 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
2705 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch", "Dynamically switch the order with 2 viewports", config));
2708 TestConfig config(kOrdering);
2709 // 2 scissors, reversed dynamic viewports that should result in no drawing taking place.
2710 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
2711 config.viewportConfig.staticValue = ViewportVec{
2712 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
2713 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
2715 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
2716 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2717 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch_clean", "Dynamically switch the order with 2 viewports resulting in clean image", config));
2722 TestConfig config(kOrdering);
2723 // 2 viewports, bad static single scissor.
2724 config.viewportConfig.staticValue = ViewportVec{
2725 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2726 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2728 config.scissorConfig.staticValue = ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
2729 config.scissorConfig.dynamicValue = ScissorVec{
2730 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
2731 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
2733 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors", "Dynamically set 2 scissors", config));
2736 TestConfig config(kOrdering);
2737 // 1 viewport, bad static single scissor.
2738 config.scissorConfig.staticValue = ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
2739 config.scissorConfig.dynamicValue = ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight));
2740 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_scissor", "Dynamically set scissor to cover full framebuffer", config));
2743 TestConfig config(kOrdering);
2744 // 2 viewports, 2 reversed scissors that need fixing.
2745 config.viewportConfig.staticValue = ViewportVec{
2746 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2747 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2749 config.scissorConfig.staticValue = ScissorVec{
2750 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
2751 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
2753 config.scissorConfig.dynamicValue = ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
2754 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch", "Dynamically switch the order with 2 scissors", config));
2757 TestConfig config(kOrdering);
2758 // 2 viewports, 2 scissors switched to prevent drawing.
2759 config.viewportConfig.staticValue = ViewportVec{
2760 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2761 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2763 config.scissorConfig.staticValue = ScissorVec{
2764 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
2765 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
2767 config.scissorConfig.dynamicValue = ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
2768 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2769 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch_clean", "Dynamically switch the order with 2 scissors to avoid drawing", config));
2776 const VertexGenerator* factory;
2777 const std::string prefix;
2780 { getVertexWithPaddingGenerator(), "stride" },
2781 { getVertexWithExtraAttributesGenerator(), "large_stride" },
2784 for (const auto& strideCase : strideCases)
2786 const auto factory = strideCase.factory;
2787 const auto& prefix = strideCase.prefix;
2788 const auto vertexStrides = factory->getVertexDataStrides();
2789 StrideVec halfStrides;
2791 halfStrides.reserve(vertexStrides.size());
2792 for (const auto& stride : vertexStrides)
2793 halfStrides.push_back(stride / 2u);
2795 if (factory == getVertexWithExtraAttributesGenerator() && kOrdering == SequenceOrdering::TWO_DRAWS_STATIC)
2797 // This case is invalid because it breaks VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the dynamic
2798 // stride being less than the extent of the binding for the second attribute.
2803 TestConfig config(kOrdering, factory);
2804 config.strideConfig.staticValue = halfStrides;
2805 config.strideConfig.dynamicValue = vertexStrides;
2806 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix, "Dynamically set stride", config));
2809 TestConfig config(kOrdering, factory);
2810 config.strideConfig.staticValue = halfStrides;
2811 config.strideConfig.dynamicValue = vertexStrides;
2812 config.vertexDataOffset = vertexStrides[0];
2813 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset", "Dynamically set stride using a nonzero vertex data offset", config));
2816 TestConfig config(kOrdering, factory);
2817 config.strideConfig.staticValue = halfStrides;
2818 config.strideConfig.dynamicValue = vertexStrides;
2819 config.vertexDataOffset = vertexStrides[0];
2820 config.vertexDataExtraBytes = config.vertexDataOffset;
2822 // 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.
2823 config.referenceColor = HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor);
2824 config.meshParams[0].scaleY = 0.5f;
2825 config.meshParams[0].offsetY = -0.5f;
2827 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset_and_padding", "Dynamically set stride using a nonzero vertex data offset and extra bytes", config));
2832 // Depth test enable.
2834 TestConfig config(kOrdering);
2835 config.depthTestEnableConfig.staticValue = false;
2836 config.depthTestEnableConfig.dynamicValue = tcu::just(true);
2837 // By default, the depth test never passes when enabled.
2838 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2839 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_enable", "Dynamically enable depth test", config));
2842 TestConfig config(kOrdering);
2843 config.depthTestEnableConfig.staticValue = true;
2844 config.depthTestEnableConfig.dynamicValue = tcu::just(false);
2845 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_disable", "Dynamically disable depth test", config));
2848 // Depth write enable.
2850 TestConfig config(kOrdering);
2852 // Enable depth test and set values so it passes.
2853 config.depthTestEnableConfig.staticValue = true;
2854 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
2855 config.clearDepthValue = 0.5f;
2856 config.meshParams[0].depth = 0.25f;
2858 // Enable writes and expect the mesh value.
2859 config.depthWriteEnableConfig.staticValue = false;
2860 config.depthWriteEnableConfig.dynamicValue = tcu::just(true);
2861 config.expectedDepth = 0.25f;
2863 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_enable", "Dynamically enable writes to the depth buffer", config));
2866 TestConfig config(kOrdering);
2868 // Enable depth test and set values so it passes.
2869 config.depthTestEnableConfig.staticValue = true;
2870 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
2871 config.clearDepthValue = 0.5f;
2872 config.meshParams[0].depth = 0.25f;
2874 // But disable writing dynamically and expect the clear value.
2875 config.depthWriteEnableConfig.staticValue = true;
2876 config.depthWriteEnableConfig.dynamicValue = tcu::just(false);
2877 config.expectedDepth = 0.5f;
2879 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_disable", "Dynamically disable writes to the depth buffer", config));
2882 // Depth bias enable.
2885 TestConfig config(kOrdering);
2887 // Enable depth test and write 1.0f
2888 config.depthTestEnableConfig.staticValue = true;
2889 config.depthWriteEnableConfig.staticValue = true;
2890 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
2891 // Clear depth buffer to 0.25f
2892 config.clearDepthValue = 0.25f;
2893 // Write depth to 0.5f
2894 config.meshParams[0].depth = 0.5f;
2896 // Enable dynamic depth bias and expect the depth value to be clamped to 0.75f based on depthBiasConstantFactor and depthBiasClamp
2897 config.depthBiasEnableConfig.staticValue = false;
2898 config.depthBiasEnableConfig.dynamicValue = tcu::just(true);
2899 config.expectedDepth = 0.75f;
2901 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bias_enable", "Dynamically enable the depth bias", config));
2904 TestConfig config(kOrdering);
2906 // Enable depth test and write 1.0f
2907 config.depthTestEnableConfig.staticValue = true;
2908 config.depthWriteEnableConfig.staticValue = true;
2909 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
2910 // Clear depth buffer to 0.25f
2911 config.clearDepthValue = 0.25f;
2912 // Write depth to 0.5f
2913 config.meshParams[0].depth = 0.5f;
2915 // Disable dynamic depth bias and expect the depth value to remain at 0.5f based on written value
2916 config.depthBiasEnableConfig.staticValue = true;
2917 config.depthBiasEnableConfig.dynamicValue = tcu::just(false);
2918 config.expectedDepth = 0.5f;
2920 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bias_disable", "Dynamically disable the depth bias", config));
2924 // Depth compare op.
2926 TestConfig baseConfig(kOrdering);
2927 const tcu::Vec4 kAlternativeColor (0.0f, 0.0f, 0.5f, 1.0f);
2928 baseConfig.depthTestEnableConfig.staticValue = true;
2929 baseConfig.depthWriteEnableConfig.staticValue = true;
2930 baseConfig.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_NEVER;
2931 baseConfig.clearDepthValue = 0.5f;
2934 TestConfig config = baseConfig;
2935 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
2936 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NEVER;
2937 config.meshParams[0].depth = 0.25f;
2938 config.expectedDepth = 0.5f;
2939 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2940 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_never", "Dynamically set the depth compare operator to NEVER", config));
2943 TestConfig config = baseConfig;
2944 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS;
2945 config.meshParams[0].depth = 0.25f;
2946 config.expectedDepth = 0.25f;
2947 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less", "Dynamically set the depth compare operator to LESS", config));
2950 TestConfig config = baseConfig;
2951 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER;
2952 config.meshParams[0].depth = 0.75f;
2953 config.expectedDepth = 0.75f;
2954 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater", "Dynamically set the depth compare operator to GREATER", config));
2957 TestConfig config = baseConfig;
2958 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_EQUAL;
2959 config.meshParams[0].depth = 0.5f;
2960 config.meshParams[0].color = kAlternativeColor;
2961 // Draw another mesh in front to verify it does not pass the equality test.
2962 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.25f));
2963 config.expectedDepth = 0.5f;
2964 config.referenceColor = SingleColorGenerator(kAlternativeColor);
2965 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_equal", "Dynamically set the depth compare operator to EQUAL", config));
2968 TestConfig config = baseConfig;
2969 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
2970 config.meshParams[0].depth = 0.25f;
2971 config.expectedDepth = 0.25f;
2972 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less", "Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with smaller depth", config));
2975 TestConfig config = baseConfig;
2976 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
2977 config.meshParams[0].depth = 0.5f;
2978 config.expectedDepth = 0.5f;
2979 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_equal", "Dynamically set the depth compare operator to LESS_OR_EQUAL and draw with equal depth", config));
2982 TestConfig config = baseConfig;
2983 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
2984 config.meshParams[0].depth = 0.25f;
2985 // Draw another mesh with the same depth in front of it.
2986 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.25f));
2987 config.expectedDepth = 0.25f;
2988 config.referenceColor = SingleColorGenerator(kAlternativeColor);
2989 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less_equal_less_then_equal", "Dynamically set the depth compare operator to LESS_OR_EQUAL and draw two meshes with less and equal depth", config));
2992 TestConfig config = baseConfig;
2993 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
2994 config.meshParams[0].depth = 0.75f;
2995 config.expectedDepth = 0.75f;
2996 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater", "Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with greater depth", config));
2999 TestConfig config = baseConfig;
3000 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
3001 config.meshParams[0].depth = 0.5f;
3002 config.expectedDepth = 0.5f;
3003 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_equal", "Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw with equal depth", config));
3006 TestConfig config = baseConfig;
3007 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
3008 config.meshParams[0].depth = 0.75f;
3009 // Draw another mesh with the same depth in front of it.
3010 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.75f));
3011 config.expectedDepth = 0.75f;
3012 config.referenceColor = SingleColorGenerator(kAlternativeColor);
3013 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater_equal_greater_then_equal", "Dynamically set the depth compare operator to GREATER_OR_EQUAL and draw two meshes with greater and equal depth", config));
3016 TestConfig config = baseConfig;
3017 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NOT_EQUAL;
3019 // Draw first mesh in front.
3020 config.meshParams[0].depth = 0.25f;
3021 // Draw another mesh in the back, this should pass too.
3022 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.5f));
3023 // Finally a new mesh with the same depth. This should not pass.
3024 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.5f));
3026 config.referenceColor = SingleColorGenerator(kAlternativeColor);
3027 config.expectedDepth = 0.5f;
3028 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_not_equal", "Dynamically set the depth compare operator to NOT_EQUAL", config));
3031 TestConfig config = baseConfig;
3032 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_ALWAYS;
3034 config.meshParams[0].depth = 0.5f;
3035 config.expectedDepth = 0.5f;
3036 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_equal", "Dynamically set the depth compare operator to ALWAYS and draw with equal depth", config));
3038 config.meshParams[0].depth = 0.25f;
3039 config.expectedDepth = 0.25f;
3040 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_less", "Dynamically set the depth compare operator to ALWAYS and draw with less depth", config));
3042 config.meshParams[0].depth = 0.75f;
3043 config.expectedDepth = 0.75f;
3044 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_greater", "Dynamically set the depth compare operator to ALWAYS and draw with greater depth", config));
3048 // Depth bounds test.
3050 TestConfig baseConfig(kOrdering);
3051 baseConfig.minDepthBounds = 0.25f;
3052 baseConfig.maxDepthBounds = 0.75f;
3053 baseConfig.meshParams[0].depth = 0.0f;
3056 TestConfig config = baseConfig;
3057 config.depthBoundsTestEnableConfig.staticValue = false;
3058 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(true);
3059 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
3060 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_enable", "Dynamically enable the depth bounds test", config));
3063 TestConfig config = baseConfig;
3064 config.depthBoundsTestEnableConfig.staticValue = true;
3065 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(false);
3066 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_disable", "Dynamically disable the depth bounds test", config));
3070 // Stencil test enable.
3072 TestConfig config(kOrdering);
3073 config.stencilTestEnableConfig.staticValue = false;
3074 config.stencilTestEnableConfig.dynamicValue = tcu::just(true);
3075 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
3076 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
3077 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_enable", "Dynamically enable the stencil test", config));
3080 TestConfig config(kOrdering);
3081 config.stencilTestEnableConfig.staticValue = true;
3082 config.stencilTestEnableConfig.dynamicValue = tcu::just(false);
3083 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
3084 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_disable", "Dynamically disable the stencil test", config));
3087 // Stencil operation. Many combinations are possible.
3091 vk::VkStencilFaceFlags face;
3095 { vk::VK_STENCIL_FACE_FRONT_BIT, "face_front" },
3096 { vk::VK_STENCIL_FACE_BACK_BIT, "face_back" },
3097 { vk::VK_STENCIL_FRONT_AND_BACK, "face_both_single" },
3098 { vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM, "face_both_dual" }, // MAX_ENUM is a placeholder.
3103 vk::VkCompareOp compareOp;
3107 { vk::VK_COMPARE_OP_NEVER, "xf" },
3108 { vk::VK_COMPARE_OP_LESS, "lt" },
3109 { vk::VK_COMPARE_OP_EQUAL, "eq" },
3110 { vk::VK_COMPARE_OP_LESS_OR_EQUAL, "le" },
3111 { vk::VK_COMPARE_OP_GREATER, "gt" },
3112 { vk::VK_COMPARE_OP_GREATER_OR_EQUAL, "ge" },
3113 { vk::VK_COMPARE_OP_ALWAYS, "xt" },
3116 using u8vec = std::vector<deUint8>;
3118 static const auto kMinVal = std::numeric_limits<deUint8>::min();
3119 static const auto kMaxVal = std::numeric_limits<deUint8>::max();
3120 static const auto kMidVal = static_cast<deUint8>(kMaxVal * 2u / 5u);
3121 static const auto kMinValI = static_cast<int>(kMinVal);
3122 static const auto kMaxValI = static_cast<int>(kMaxVal);
3126 vk::VkStencilOp stencilOp;
3128 u8vec clearValues; // One test per clear value interesting for this operation.
3129 vk::VkStencilOp incompatibleOp; // Alternative operation giving incompatible results for the given values.
3132 { vk::VK_STENCIL_OP_KEEP, "keep", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
3133 { vk::VK_STENCIL_OP_ZERO, "zero", u8vec{kMidVal}, vk::VK_STENCIL_OP_KEEP },
3134 { vk::VK_STENCIL_OP_REPLACE, "replace", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
3135 { vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP, "inc_clamp", u8vec{kMaxVal - 1, kMaxVal}, vk::VK_STENCIL_OP_ZERO },
3136 { vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP, "dec_clamp", u8vec{kMinVal + 1, kMinVal}, vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP },
3137 { vk::VK_STENCIL_OP_INVERT, "invert", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
3138 { vk::VK_STENCIL_OP_INCREMENT_AND_WRAP, "inc_wrap", u8vec{kMaxVal - 1, kMaxVal}, vk::VK_STENCIL_OP_KEEP },
3139 { vk::VK_STENCIL_OP_DECREMENT_AND_WRAP, "dec_wrap", u8vec{kMinVal + 1, kMinVal}, vk::VK_STENCIL_OP_KEEP },
3142 for (const auto& face : kFaces)
3143 for (const auto& compare : kCompare)
3144 for (const auto& op : kStencilOps)
3146 // Try clearing the stencil value with different values.
3147 for (const auto clearVal : op.clearValues)
3149 // Use interesting values as the reference stencil value.
3150 for (int delta = -1; delta <= 1; ++delta)
3152 const int refVal = clearVal + delta;
3153 if (refVal < kMinValI || refVal > kMaxValI)
3156 const auto refValU8 = static_cast<deUint8>(refVal);
3157 const auto refValU32 = static_cast<deUint32>(refVal);
3159 // Calculate outcome of the stencil test itself.
3160 const bool wouldPass = stencilPasses(compare.compareOp, clearVal, refValU8);
3162 // If the test passes, use an additional variant for the depthFail operation.
3163 const int subCases = (wouldPass ? 2 : 1);
3165 for (int subCaseIdx = 0; subCaseIdx < subCases; ++subCaseIdx)
3167 const bool depthFail = (subCaseIdx > 0); // depthFail would be the second variant.
3168 const bool globalPass = (wouldPass && !depthFail); // Global result of the stencil+depth test.
3170 // Start tuning test parameters.
3171 TestConfig config(kOrdering);
3173 // No face culling is applied by default, so both the front and back operations could apply depending on the mesh.
3174 if (face.face == vk::VK_STENCIL_FACE_FRONT_BIT)
3176 // Default parameters are OK.
3178 else if (face.face == vk::VK_STENCIL_FACE_BACK_BIT)
3180 // Reverse the mesh so it applies the back operation.
3181 config.meshParams[0].reversed = true;
3183 else // Front and back.
3185 // Draw both a front and a back-facing mesh so both are applied.
3186 // The first mesh will be drawn in the top half and the second mesh in the bottom half.
3188 // Make the second mesh a reversed copy of the first mesh.
3189 config.meshParams.push_back(config.meshParams.front());
3190 config.meshParams.back().reversed = true;
3192 // Apply scale and offset to the top mesh.
3193 config.meshParams.front().scaleY = 0.5f;
3194 config.meshParams.front().offsetY = -0.5f;
3196 // Apply scale and offset to the bottom mesh.
3197 config.meshParams.back().scaleY = 0.5f;
3198 config.meshParams.back().offsetY = 0.5f;
3201 // Enable the stencil test.
3202 config.stencilTestEnableConfig.staticValue = true;
3204 // Set dynamic configuration.
3205 StencilOpParams dynamicStencilConfig;
3206 dynamicStencilConfig.faceMask = face.face;
3207 dynamicStencilConfig.compareOp = compare.compareOp;
3208 dynamicStencilConfig.failOp = vk::VK_STENCIL_OP_MAX_ENUM;
3209 dynamicStencilConfig.passOp = vk::VK_STENCIL_OP_MAX_ENUM;
3210 dynamicStencilConfig.depthFailOp = vk::VK_STENCIL_OP_MAX_ENUM;
3212 // Set operations so only the appropriate operation for this case gives the right result.
3213 vk::VkStencilOp* activeOp = nullptr;
3214 vk::VkStencilOp* inactiveOps[2] = { nullptr, nullptr };
3219 activeOp = &dynamicStencilConfig.depthFailOp;
3220 inactiveOps[0] = &dynamicStencilConfig.passOp;
3221 inactiveOps[1] = &dynamicStencilConfig.failOp;
3225 activeOp = &dynamicStencilConfig.passOp;
3226 inactiveOps[0] = &dynamicStencilConfig.depthFailOp;
3227 inactiveOps[1] = &dynamicStencilConfig.failOp;
3232 activeOp = &dynamicStencilConfig.failOp;
3233 inactiveOps[0] = &dynamicStencilConfig.passOp;
3234 inactiveOps[1] = &dynamicStencilConfig.depthFailOp;
3237 *activeOp = op.stencilOp;
3238 *inactiveOps[0] = op.incompatibleOp;
3239 *inactiveOps[1] = op.incompatibleOp;
3241 // Make sure all ops have been configured properly.
3242 DE_ASSERT(dynamicStencilConfig.failOp != vk::VK_STENCIL_OP_MAX_ENUM);
3243 DE_ASSERT(dynamicStencilConfig.passOp != vk::VK_STENCIL_OP_MAX_ENUM);
3244 DE_ASSERT(dynamicStencilConfig.depthFailOp != vk::VK_STENCIL_OP_MAX_ENUM);
3246 // Set an incompatible static operation too.
3247 auto& staticStencilConfig = config.stencilOpConfig.staticValue.front();
3248 staticStencilConfig.faceMask = face.face;
3249 staticStencilConfig.compareOp = (globalPass ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
3250 staticStencilConfig.passOp = op.incompatibleOp;
3251 staticStencilConfig.failOp = op.incompatibleOp;
3252 staticStencilConfig.depthFailOp = op.incompatibleOp;
3254 // Set dynamic configuration.
3255 StencilOpVec stencilOps;
3256 stencilOps.push_back(dynamicStencilConfig);
3258 if (stencilOps.front().faceMask == vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM)
3260 // This is the dual case. We will set the front and back face values with two separate calls.
3261 stencilOps.push_back(stencilOps.front());
3262 stencilOps.front().faceMask = vk::VK_STENCIL_FACE_FRONT_BIT;
3263 stencilOps.back().faceMask = vk::VK_STENCIL_FACE_BACK_BIT;
3264 staticStencilConfig.faceMask = vk::VK_STENCIL_FACE_FRONT_AND_BACK;
3267 config.stencilOpConfig.dynamicValue = tcu::just(stencilOps);
3268 config.clearStencilValue = clearVal;
3269 config.referenceStencil = refValU32;
3273 // Enable depth test and make it fail.
3274 config.depthTestEnableConfig.staticValue = true;
3275 config.clearDepthValue = 0.5f;
3276 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
3278 for (auto& meshPar : config.meshParams)
3279 meshPar.depth = 0.75f;
3282 // Set expected outcome.
3283 config.referenceColor = SingleColorGenerator(globalPass ? kDefaultTriangleColor : kDefaultClearColor);
3284 config.expectedDepth = config.clearDepthValue; // No depth writing by default.
3285 config.expectedStencil = stencilResult(op.stencilOp, clearVal, refValU8, kMinVal, kMaxVal);
3287 const std::string testName = std::string("stencil_state")
3289 + "_" + compare.name
3291 + "_clear_" + de::toString(static_cast<int>(clearVal))
3292 + "_ref_" + de::toString(refVal)
3293 + "_" + (wouldPass ? (depthFail ? "depthfail" : "pass") : "fail");
3295 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, "Dynamically configure stencil test, variant " + testName, config));
3304 // TWO_DRAWS_STATIC would be invalid because it violates VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the
3305 // dynamic stride being less than the extent of the binding for the second attribute.
3306 if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
3308 const auto staticGen = getVertexWithPaddingGenerator();
3309 const auto dynamicGen = getVertexWithExtraAttributesGenerator();
3310 const auto goodStrides = dynamicGen->getVertexDataStrides();
3311 StrideVec badStrides;
3313 badStrides.reserve(goodStrides.size());
3314 for (const auto& stride : goodStrides)
3315 badStrides.push_back(stride / 2u);
3317 TestConfig config(kOrdering, staticGen, dynamicGen);
3318 config.strideConfig.staticValue = badStrides;
3319 config.strideConfig.dynamicValue = goodStrides;
3320 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input", "Dynamically set vertex input", config));
3324 // Variant without mixing in the stride config.
3325 TestConfig config(kOrdering, getVertexWithPaddingGenerator(), getVertexWithExtraAttributesGenerator());
3326 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_no_dyn_stride", "Dynamically set vertex input without using dynamic strides", config));
3330 // Variant using multiple bindings.
3331 TestConfig config(kOrdering, getVertexWithExtraAttributesGenerator(), getVertexWithMultipleBindingsGenerator());
3332 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_multiple_bindings", "Dynamically set vertex input with multiple bindings", config));
3336 extendedDynamicStateGroup->addChild(orderingGroup.release());
3339 return extendedDynamicStateGroup.release();