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 struct DepthBiasParams
533 float constantFactor;
537 const DepthBiasParams kNoDepthBiasParams = { 0.0f, 0.0f };
539 using ViewportVec = std::vector<vk::VkViewport>;
540 using ScissorVec = std::vector<vk::VkRect2D>;
541 using StencilOpVec = std::vector<StencilOpParams>;
543 // Generic, to be used with any state than can be set statically and, as an option, dynamically.
545 struct StaticAndDynamicPair
548 tcu::Maybe<T> dynamicValue;
550 // Helper constructor to set a static value and no dynamic value.
551 StaticAndDynamicPair (const T& value)
552 : staticValue (value)
553 , dynamicValue (tcu::nothing<T>())
557 // Helper constructor to set both.
558 StaticAndDynamicPair (const T& sVal, const T& dVal)
560 , dynamicValue (tcu::just<T>(dVal))
564 // If the dynamic value is present, swap static and dynamic values.
565 void swapValues (void)
569 std::swap(staticValue, dynamicValue.get());
573 // For anything boolean, see below.
574 using BooleanFlagConfig = StaticAndDynamicPair<bool>;
576 // Configuration for every aspect of the extended dynamic state.
577 using CullModeConfig = StaticAndDynamicPair<vk::VkCullModeFlags>;
578 using FrontFaceConfig = StaticAndDynamicPair<vk::VkFrontFace>;
579 using TopologyConfig = StaticAndDynamicPair<vk::VkPrimitiveTopology>;
580 using ViewportConfig = StaticAndDynamicPair<ViewportVec>; // At least one element.
581 using ScissorConfig = StaticAndDynamicPair<ScissorVec>; // At least one element.
582 using StrideConfig = StaticAndDynamicPair<StrideVec>; // At least one element.
583 using DepthTestEnableConfig = BooleanFlagConfig;
584 using DepthWriteEnableConfig = BooleanFlagConfig;
585 using DepthCompareOpConfig = StaticAndDynamicPair<vk::VkCompareOp>;
586 using DepthBoundsTestEnableConfig = BooleanFlagConfig;
587 using StencilTestEnableConfig = BooleanFlagConfig;
588 using StencilOpConfig = StaticAndDynamicPair<StencilOpVec>; // At least one element.
589 using VertexGeneratorConfig = StaticAndDynamicPair<const VertexGenerator*>;
590 using DepthBiasEnableConfig = BooleanFlagConfig;
591 using RastDiscardEnableConfig = BooleanFlagConfig;
592 using PrimRestartEnableConfig = BooleanFlagConfig;
593 using LogicOpConfig = StaticAndDynamicPair<vk::VkLogicOp>;
594 using PatchControlPointsConfig = StaticAndDynamicPair<deUint8>;
595 using DepthBiasConfig = StaticAndDynamicPair<DepthBiasParams>;
597 const tcu::Vec4 kDefaultTriangleColor (0.0f, 0.0f, 1.0f, 1.0f); // Opaque blue.
598 const tcu::Vec4 kDefaultClearColor (0.0f, 0.0f, 0.0f, 1.0f); // Opaque black.
600 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.
601 const tcu::UVec4 kGreenClearColor ( 0u, 255u, 0u, 255u); // Opaque green, UINT.
602 const tcu::UVec4 kLogicOpFinalColor ( 0u, 255u, 255u, 255u); // Opaque cyan, UINT.
615 MeshParams (const tcu::Vec4& color_ = kDefaultTriangleColor,
617 bool reversed_ = false,
618 float scaleX_ = 1.0f,
619 float scaleY_ = 1.0f,
620 float offsetX_ = 0.0f,
621 float offsetY_ = 0.0f,
622 float fanScale_ = 0.0f)
625 , reversed (reversed_)
630 , fanScale (fanScale_)
634 enum class SequenceOrdering
636 CMD_BUFFER_START = 0, // Set state at the start of the command buffer.
637 BEFORE_DRAW = 1, // After binding dynamic pipeline and just before drawing.
638 BETWEEN_PIPELINES = 2, // After a static state pipeline has been bound but before the dynamic state pipeline has been bound.
639 AFTER_PIPELINES = 3, // After a static state pipeline and a second dynamic state pipeline have been bound.
640 BEFORE_GOOD_STATIC = 4, // Before a static state pipeline with the correct values has been bound.
641 TWO_DRAWS_DYNAMIC = 5, // Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again.
642 TWO_DRAWS_STATIC = 6, // Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again.
645 using ReferenceColorGenerator = std::function<void(tcu::PixelBufferAccess&)>;
647 // Most tests expect a single output color in the whole image.
648 class SingleColorGenerator
651 SingleColorGenerator (const tcu::Vec4& color)
652 : m_colorFloat (color)
657 SingleColorGenerator (const tcu::UVec4& color)
658 : m_colorFloat (0.0f)
659 , m_colorUint (color)
663 void operator()(tcu::PixelBufferAccess& access)
665 constexpr auto kWidth = static_cast<int>(kFramebufferWidth);
666 constexpr auto kHeight = static_cast<int>(kFramebufferHeight);
668 for (int y = 0; y < kHeight; ++y)
669 for (int x = 0; x < kWidth; ++x)
672 access.setPixel(m_colorUint, x, y);
674 access.setPixel(m_colorFloat, x, y);
679 const tcu::Vec4 m_colorFloat;
680 const tcu::UVec4 m_colorUint;
684 // Some tests expect the upper half and the lower half having different color values.
685 class HorizontalSplitGenerator
688 HorizontalSplitGenerator (const tcu::Vec4& top, const tcu::Vec4& bottom)
689 : m_top(top), m_bottom(bottom)
692 void operator()(tcu::PixelBufferAccess& access)
694 constexpr auto kWidth = static_cast<int>(kFramebufferWidth);
695 constexpr auto kHeight = static_cast<int>(kFramebufferHeight);
696 constexpr auto kHalfHeight = kHeight / 2;
698 for (int y = 0; y < kHeight; ++y)
699 for (int x = 0; x < kWidth; ++x)
701 const auto& color = (y < kHalfHeight ? m_top : m_bottom);
702 access.setPixel(color, x, y);
707 const tcu::Vec4 m_top;
708 const tcu::Vec4 m_bottom;
711 const VertexGenerator* getVertexWithPaddingGenerator ()
713 static const VertexWithPadding vertexWithPadding;
714 return &vertexWithPadding;
717 const VertexGenerator* getVertexWithExtraAttributesGenerator ()
719 static const VertexWithExtraAttributes vertexWithExtraAttributes;
720 return &vertexWithExtraAttributes;
723 const VertexGenerator* getVertexWithMultipleBindingsGenerator ()
725 static const MultipleBindingsVertex multipleBindingsVertex;
726 return &multipleBindingsVertex;
729 // Create VertexGeneratorConfig varying constructor depending on having none, only the static or both.
730 VertexGeneratorConfig makeVertexGeneratorConfig (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
732 DE_ASSERT(!(dynamicGen && !staticGen));
734 return VertexGeneratorConfig(staticGen, dynamicGen);
736 return VertexGeneratorConfig(staticGen);
737 return VertexGeneratorConfig(getVertexWithPaddingGenerator()); // Only static part with a default option.c
740 // Similar to makeVertexGeneratorConfig, choosing the final value.
741 const VertexGenerator* chooseVertexGenerator (const VertexGenerator* staticGen, const VertexGenerator* dynamicGen)
743 DE_ASSERT(!(dynamicGen && !staticGen));
748 return getVertexWithPaddingGenerator();
751 enum class TopologyClass
760 std::string topologyClassName (TopologyClass tclass)
764 case TopologyClass::POINT: return "point";
765 case TopologyClass::LINE: return "line";
766 case TopologyClass::TRIANGLE: return "triangle";
767 case TopologyClass::PATCH: return "patch";
776 TopologyClass getTopologyClass (vk::VkPrimitiveTopology topology)
780 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
781 return TopologyClass::POINT;
782 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
783 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
784 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
785 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
786 return TopologyClass::LINE;
787 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
788 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
789 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
790 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
791 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
792 return TopologyClass::TRIANGLE;
793 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
794 return TopologyClass::PATCH;
800 return TopologyClass::INVALID;
805 // Main sequence ordering.
806 SequenceOrdering sequenceOrdering;
808 // Drawing parameters: tests will draw one or more flat meshes of triangles covering the whole "screen".
809 std::vector<MeshParams> meshParams; // Mesh parameters for each full-screen layer of geometry.
810 deUint32 referenceStencil; // Reference stencil value.
812 // Clearing parameters for the framebuffer.
813 vk::VkClearValue clearColorValue;
814 float clearDepthValue;
815 deUint32 clearStencilValue;
817 // Expected output in the attachments.
818 ReferenceColorGenerator referenceColor;
820 deUint32 expectedStencil;
822 // Depth bounds parameters for the pipeline.
823 float minDepthBounds;
824 float maxDepthBounds;
826 // Force inclusion of passthrough geometry shader or not.
827 bool forceGeometryShader;
829 // Force single vertex in the VBO.
831 deUint32 singleVertexDrawCount;
833 // Offset and extra room after the vertex buffer data.
834 vk::VkDeviceSize vertexDataOffset;
835 vk::VkDeviceSize vertexDataExtraBytes;
837 // Static and dynamic pipeline configuration.
838 VertexGeneratorConfig vertexGenerator;
839 CullModeConfig cullModeConfig;
840 FrontFaceConfig frontFaceConfig;
841 TopologyConfig topologyConfig;
842 ViewportConfig viewportConfig;
843 ScissorConfig scissorConfig;
844 StrideConfig strideConfig;
845 DepthTestEnableConfig depthTestEnableConfig;
846 DepthWriteEnableConfig depthWriteEnableConfig;
847 DepthCompareOpConfig depthCompareOpConfig;
848 DepthBoundsTestEnableConfig depthBoundsTestEnableConfig;
849 StencilTestEnableConfig stencilTestEnableConfig;
850 StencilOpConfig stencilOpConfig;
851 DepthBiasEnableConfig depthBiasEnableConfig;
852 RastDiscardEnableConfig rastDiscardEnableConfig;
853 PrimRestartEnableConfig primRestartEnableConfig;
854 LogicOpConfig logicOpConfig;
855 PatchControlPointsConfig patchControlPointsConfig;
856 DepthBiasConfig depthBiasConfig;
859 TestConfig (SequenceOrdering ordering, const VertexGenerator* staticVertexGenerator = nullptr, const VertexGenerator* dynamicVertexGenerator = nullptr)
860 : sequenceOrdering (ordering)
861 , meshParams (1u, MeshParams())
862 , referenceStencil (0u)
863 , clearColorValue (vk::makeClearValueColor(kDefaultClearColor))
864 , clearDepthValue (1.0f)
865 , clearStencilValue (0u)
866 , referenceColor (SingleColorGenerator(kDefaultTriangleColor))
867 , expectedDepth (1.0f)
868 , expectedStencil (0u)
869 , minDepthBounds (0.0f)
870 , maxDepthBounds (1.0f)
871 , forceGeometryShader (false)
872 , singleVertex (false)
873 , singleVertexDrawCount (0)
874 , vertexDataOffset (0ull)
875 , vertexDataExtraBytes (0ull)
876 , vertexGenerator (makeVertexGeneratorConfig(staticVertexGenerator, dynamicVertexGenerator))
877 , cullModeConfig (static_cast<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE))
878 , frontFaceConfig (vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
879 // By default we will use a triangle fan with 6 vertices that could be wrongly interpreted as a triangle list with 2 triangles.
880 , topologyConfig (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN)
881 , viewportConfig (ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight)))
882 , scissorConfig (ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight)))
883 // By default, the vertex stride is the size of a vertex according to the chosen vertex type.
884 , strideConfig (chooseVertexGenerator(staticVertexGenerator, dynamicVertexGenerator)->getVertexDataStrides())
885 , depthTestEnableConfig (false)
886 , depthWriteEnableConfig (false)
887 , depthCompareOpConfig (vk::VK_COMPARE_OP_NEVER)
888 , depthBoundsTestEnableConfig (false)
889 , stencilTestEnableConfig (false)
890 , stencilOpConfig (StencilOpVec(1u, kDefaultStencilOpParams))
891 , depthBiasEnableConfig (false)
892 , rastDiscardEnableConfig (false)
893 , primRestartEnableConfig (false)
894 , logicOpConfig (vk::VK_LOGIC_OP_CLEAR)
895 , patchControlPointsConfig (1u)
896 , depthBiasConfig (kNoDepthBiasParams)
897 , m_swappedValues (false)
901 // Get the proper viewport vector according to the test config.
902 const ViewportVec& getActiveViewportVec () const
904 return ((viewportConfig.dynamicValue && !m_swappedValues) ? viewportConfig.dynamicValue.get() : viewportConfig.staticValue);
907 // Gets the proper vertex generator according to the test config.
908 const VertexGenerator* getActiveVertexGenerator () const
910 return ((vertexGenerator.dynamicValue && !m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
913 // Gets the inactive vertex generator according to the test config. If there's only one, return that.
914 const VertexGenerator* getInactiveVertexGenerator () const
916 return ((vertexGenerator.dynamicValue && m_swappedValues) ? vertexGenerator.dynamicValue.get() : vertexGenerator.staticValue);
919 // Get the active number of patch control points according to the test config.
920 deUint32 getActivePatchControlPoints () const
922 return ((patchControlPointsConfig.dynamicValue && !m_swappedValues) ? patchControlPointsConfig.dynamicValue.get() : patchControlPointsConfig.staticValue);
925 // Get the active depth bias parameters.
926 DepthBiasParams getActiveDepthBiasParams () const
928 return ((depthBiasConfig.dynamicValue && !m_swappedValues) ? depthBiasConfig.dynamicValue.get() : depthBiasConfig.staticValue);
931 // Returns true if there is more than one viewport.
932 bool isMultiViewport () const
934 return (getActiveViewportVec().size() > 1);
937 // Returns true if the case needs a geometry shader.
938 bool needsGeometryShader () const
940 // Writing to gl_ViewportIndex from vertex or tesselation shaders needs the shaderOutputViewportIndex feature, which is less
941 // commonly supported than geometry shaders, so we will use a geometry shader if we need to write to it.
942 return (isMultiViewport() || forceGeometryShader);
945 // Returns true if we should use the static and dynamic values exchanged.
946 // This makes the static part of the pipeline have the actual expected values.
947 bool isReversed () const
949 return (sequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
950 sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC);
953 // Swaps static and dynamic configuration values.
956 vertexGenerator.swapValues();
957 cullModeConfig.swapValues();
958 frontFaceConfig.swapValues();
959 topologyConfig.swapValues();
960 viewportConfig.swapValues();
961 scissorConfig.swapValues();
962 strideConfig.swapValues();
963 depthTestEnableConfig.swapValues();
964 depthWriteEnableConfig.swapValues();
965 depthCompareOpConfig.swapValues();
966 depthBoundsTestEnableConfig.swapValues();
967 stencilTestEnableConfig.swapValues();
968 stencilOpConfig.swapValues();
969 depthBiasEnableConfig.swapValues();
970 rastDiscardEnableConfig.swapValues();
971 primRestartEnableConfig.swapValues();
972 logicOpConfig.swapValues();
973 patchControlPointsConfig.swapValues();
974 depthBiasConfig.swapValues();
976 m_swappedValues = !m_swappedValues;
979 // Returns the number of iterations when recording commands.
980 deUint32 numIterations () const
982 deUint32 iterations = 0u;
984 switch (sequenceOrdering)
986 case SequenceOrdering::TWO_DRAWS_DYNAMIC:
987 case SequenceOrdering::TWO_DRAWS_STATIC:
998 // Returns true if we're testing the logic op.
999 bool testLogicOp () const
1001 return static_cast<bool>(logicOpConfig.dynamicValue);
1004 // Returns true if we're testing the patch control points.
1005 bool testPatchControlPoints () const
1007 return static_cast<bool>(patchControlPointsConfig.dynamicValue);
1010 // Returns true if the topology class is patches for tessellation.
1011 bool patchesTopology () const
1013 return (getTopologyClass(topologyConfig.staticValue) == TopologyClass::PATCH);
1016 // Returns true if the test needs tessellation shaders.
1017 bool needsTessellation () const
1019 return (testPatchControlPoints() || patchesTopology());
1022 // Returns true if the test needs an index buffer.
1023 bool needsIndexBuffer () const
1025 return static_cast<bool>(primRestartEnableConfig.dynamicValue);
1028 // Returns true if the test needs the depth bias clamp feature.
1029 bool needsDepthBiasClampFeature () const
1031 return (getActiveDepthBiasParams().clamp != 0.0f);
1034 // Returns the appropriate color image format for the test.
1035 vk::VkFormat colorFormat () const
1037 // Pick int color format when testing logic op.
1038 return (testLogicOp() ? kIntColorFormat : kUnormColorFormat);
1041 // Returns the list of dynamic states affected by this config.
1042 std::vector<vk::VkDynamicState> getDynamicStates () const
1044 std::vector<vk::VkDynamicState> dynamicStates;
1046 if (depthBiasConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS);
1047 if (cullModeConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
1048 if (frontFaceConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
1049 if (topologyConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
1050 if (viewportConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT);
1051 if (scissorConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT);
1052 if (strideConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
1053 if (depthTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
1054 if (depthWriteEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
1055 if (depthCompareOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
1056 if (depthBoundsTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
1057 if (stencilTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
1058 if (stencilOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
1059 if (vertexGenerator.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
1060 if (patchControlPointsConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
1061 if (rastDiscardEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT);
1062 if (depthBiasEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT);
1063 if (logicOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT);
1064 if (primRestartEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT);
1066 return dynamicStates;
1069 // Returns the list of extensions needed by this config.
1070 std::vector<std::string> getRequiredExtensions () const
1072 std::vector<std::string> extensions;
1074 if (cullModeConfig.dynamicValue
1075 || frontFaceConfig.dynamicValue
1076 || topologyConfig.dynamicValue
1077 || viewportConfig.dynamicValue
1078 || scissorConfig.dynamicValue
1079 || strideConfig.dynamicValue
1080 || depthTestEnableConfig.dynamicValue
1081 || depthWriteEnableConfig.dynamicValue
1082 || depthCompareOpConfig.dynamicValue
1083 || depthBoundsTestEnableConfig.dynamicValue
1084 || stencilTestEnableConfig.dynamicValue
1085 || stencilOpConfig.dynamicValue)
1087 extensions.push_back("VK_EXT_extended_dynamic_state");
1090 if (vertexGenerator.dynamicValue)
1092 extensions.push_back("VK_EXT_vertex_input_dynamic_state");
1095 if (patchControlPointsConfig.dynamicValue
1096 || rastDiscardEnableConfig.dynamicValue
1097 || depthBiasEnableConfig.dynamicValue
1098 || logicOpConfig.dynamicValue
1099 || primRestartEnableConfig.dynamicValue)
1101 extensions.push_back("VK_EXT_extended_dynamic_state2");
1108 // Extended dynamic state cases as created by createExtendedDynamicStateTests() are based on the assumption that, when a state
1109 // has a static and a dynamic value configured at the same time, the static value is wrong and the dynamic value will give
1110 // expected results. That's appropriate for most test variants, but in some others we want to reverse the situation: a dynamic
1111 // pipeline with wrong values and a static one with good values.
1113 // Instead of modifying how tests are created, we use isReversed() and swapValues() above, allowing us to swap static and
1114 // 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
1115 // given point in time in order to correctly answer some questions while running the test. m_swappedValues tracks that state.
1116 bool m_swappedValues;
1119 struct PushConstants
1121 tcu::Vec4 triangleColor;
1123 deInt32 viewPortIndex;
1131 void copy(vk::VkStencilOpState& dst, const StencilOpParams& src)
1133 dst.failOp = src.failOp;
1134 dst.passOp = src.passOp;
1135 dst.depthFailOp = src.depthFailOp;
1136 dst.compareOp = src.compareOp;
1139 class ExtendedDynamicStateTest : public vkt::TestCase
1142 ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig);
1143 virtual ~ExtendedDynamicStateTest (void) {}
1145 virtual void checkSupport (Context& context) const;
1146 virtual void initPrograms (vk::SourceCollections& programCollection) const;
1147 virtual TestInstance* createInstance (Context& context) const;
1150 TestConfig m_testConfig;
1153 class ExtendedDynamicStateInstance : public vkt::TestInstance
1156 ExtendedDynamicStateInstance (Context& context, const TestConfig& testConfig);
1157 virtual ~ExtendedDynamicStateInstance (void) {}
1159 virtual tcu::TestStatus iterate (void);
1162 TestConfig m_testConfig;
1165 ExtendedDynamicStateTest::ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig)
1166 : vkt::TestCase (testCtx, name, description)
1167 , m_testConfig (testConfig)
1169 const auto staticTopologyClass = getTopologyClass(testConfig.topologyConfig.staticValue);
1170 DE_UNREF(staticTopologyClass); // For release builds.
1172 // Matching topology classes.
1173 DE_ASSERT(!testConfig.topologyConfig.dynamicValue ||
1174 staticTopologyClass == getTopologyClass(testConfig.topologyConfig.dynamicValue.get()));
1176 // Supported topology classes for these tests.
1177 DE_ASSERT(staticTopologyClass == TopologyClass::LINE || staticTopologyClass == TopologyClass::TRIANGLE
1178 || staticTopologyClass == TopologyClass::PATCH);
1180 // Make sure these are consistent.
1181 DE_ASSERT(!(m_testConfig.testPatchControlPoints() && !m_testConfig.patchesTopology()));
1182 DE_ASSERT(!(m_testConfig.patchesTopology() && m_testConfig.getActivePatchControlPoints() <= 1u));
1185 void ExtendedDynamicStateTest::checkSupport (Context& context) const
1187 const auto& vki = context.getInstanceInterface();
1188 const auto physicalDevice = context.getPhysicalDevice();
1190 // Check extension support.
1191 const auto requiredExtensions = m_testConfig.getRequiredExtensions();
1192 for (const auto& extension : requiredExtensions)
1193 context.requireDeviceFunctionality(extension);
1195 // Needed for extended state included as part of VK_EXT_extended_dynamic_state2.
1196 if (de::contains(begin(requiredExtensions), end(requiredExtensions), "VK_EXT_extended_dynamic_state2"))
1198 const auto& eds2Features = context.getExtendedDynamicState2FeaturesEXT();
1200 if (m_testConfig.testLogicOp() && !eds2Features.extendedDynamicState2LogicOp)
1201 TCU_THROW(NotSupportedError, "VK_EXT_extended_dynamic_state2 : changing LogicOp dynamically is not supported");
1203 if (m_testConfig.testPatchControlPoints() && !eds2Features.extendedDynamicState2PatchControlPoints)
1204 TCU_THROW(NotSupportedError, "VK_EXT_extended_dynamic_state2 : changing patch control points dynamically is not supported");
1207 // Check the number of viewports needed and the corresponding limits.
1208 const auto& viewportConfig = m_testConfig.viewportConfig;
1209 auto numViewports = viewportConfig.staticValue.size();
1211 if (viewportConfig.dynamicValue)
1212 numViewports = std::max(numViewports, viewportConfig.dynamicValue.get().size());
1214 if (numViewports > 1)
1216 const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
1217 if (numViewports > static_cast<decltype(numViewports)>(properties.limits.maxViewports))
1218 TCU_THROW(NotSupportedError, "Number of viewports not supported (" + de::toString(numViewports) + ")");
1221 const auto& dbTestEnable = m_testConfig.depthBoundsTestEnableConfig;
1222 const bool useDepthBounds = (dbTestEnable.staticValue || (dbTestEnable.dynamicValue && dbTestEnable.dynamicValue.get()));
1224 if (useDepthBounds || m_testConfig.needsGeometryShader() || m_testConfig.needsTessellation() || m_testConfig.needsDepthBiasClampFeature())
1226 const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
1228 // Check depth bounds test support.
1229 if (useDepthBounds && !features.depthBounds)
1230 TCU_THROW(NotSupportedError, "Depth bounds feature not supported");
1232 // Check geometry shader support.
1233 if (m_testConfig.needsGeometryShader() && !features.geometryShader)
1234 TCU_THROW(NotSupportedError, "Geometry shader not supported");
1236 // Check tessellation support
1237 if (m_testConfig.needsTessellation() && !features.tessellationShader)
1238 TCU_THROW(NotSupportedError, "Tessellation feature not supported");
1240 // Check depth bias clamp feature.
1241 if (m_testConfig.needsDepthBiasClampFeature() && !features.depthBiasClamp)
1242 TCU_THROW(NotSupportedError, "Depth bias clamp not supported");
1245 // Check color image format support (depth/stencil will be chosen at runtime).
1246 const vk::VkFormatFeatureFlags kColorFeatures = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
1248 // Pick int color format for logic op
1249 vk::VkFormat colorFormat = m_testConfig.colorFormat();
1250 const auto colorProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, colorFormat);
1252 if ((colorProperties.optimalTilingFeatures & kColorFeatures) != kColorFeatures)
1253 TCU_THROW(NotSupportedError, "Required color image features not supported");
1256 void ExtendedDynamicStateTest::initPrograms (vk::SourceCollections& programCollection) const
1258 std::ostringstream pushSource;
1259 std::ostringstream vertSourceTemplateStream;
1260 std::ostringstream fragSource;
1261 std::ostringstream geomSource;
1262 std::ostringstream tescSource;
1263 std::ostringstream teseSource;
1266 << "layout(push_constant, std430) uniform PushConstantsBlock {\n"
1267 << " vec4 triangleColor;\n"
1268 << " float depthValue;\n"
1269 << " int viewPortIndex;\n"
1270 << " float scaleX;\n"
1271 << " float scaleY;\n"
1272 << " float offsetX;\n"
1273 << " float offsetY;\n"
1274 << " float fanScale;\n"
1275 << "} pushConstants;\n"
1277 const auto pushConstants = pushSource.str();
1279 // The actual generator, attributes and calculations.
1280 const auto activeGen = m_testConfig.getActiveVertexGenerator();
1281 const auto attribDecls = activeGen->getAttributeDeclarations();
1282 const auto coordCalcs = activeGen->getVertexCoordCalc();
1284 // The static generator, attributes and calculations, for the static pipeline, if needed.
1285 const auto inactiveGen = m_testConfig.getInactiveVertexGenerator();
1286 const auto staticAttribDec = inactiveGen->getAttributeDeclarations();
1287 const auto staticCoordCalc = inactiveGen->getVertexCoordCalc();
1289 std::ostringstream activeAttribs;
1290 std::ostringstream activeCalcs;
1291 std::ostringstream inactiveAttribs;
1292 std::ostringstream inactiveCalcs;
1294 for (const auto& decl : attribDecls)
1295 activeAttribs << decl << "\n";
1297 for (const auto& statement : coordCalcs)
1298 activeCalcs << " " << statement << "\n";
1300 for (const auto& decl : staticAttribDec)
1301 inactiveAttribs << decl << "\n";
1303 for (const auto& statement : staticCoordCalc)
1304 inactiveCalcs << " " << statement << "\n";
1306 vertSourceTemplateStream
1310 << "out gl_PerVertex\n"
1312 << " vec4 gl_Position;\n"
1314 << "void main() {\n"
1315 << "${CALCULATIONS}"
1316 << " gl_Position = vec4(vertexCoords.x * pushConstants.scaleX + pushConstants.offsetX, vertexCoords.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
1317 << " vec2 fanOffset;\n"
1318 << " switch (gl_VertexIndex) {\n"
1319 << " case 0: fanOffset = vec2(0.0, 0.0); break;\n"
1320 << " case 1: fanOffset = vec2(1.0, 0.0); break;\n"
1321 << " case 2: fanOffset = vec2(1.0, -1.0); break;\n"
1322 << " case 3: fanOffset = vec2(0.0, -1.0); break;\n"
1323 << " case 4: fanOffset = vec2(-1.0, -1.0); break;\n"
1324 << " case 5: fanOffset = vec2(-1.0, 0.0); break;\n"
1325 << " default: fanOffset = vec2(-1000.0); break;\n"
1327 << " gl_Position.xy += pushConstants.fanScale * fanOffset;\n"
1331 tcu::StringTemplate vertSourceTemplate (vertSourceTemplateStream.str());
1333 std::map<std::string, std::string> activeMap;
1334 std::map<std::string, std::string> inactiveMap;
1336 activeMap["ATTRIBUTES"] = activeAttribs.str();
1337 activeMap["CALCULATIONS"] = activeCalcs.str();
1339 inactiveMap["ATTRIBUTES"] = inactiveAttribs.str();
1340 inactiveMap["CALCULATIONS"] = inactiveCalcs.str();
1342 const auto activeVertSource = vertSourceTemplate.specialize(activeMap);
1343 const auto inactiveVertSource = vertSourceTemplate.specialize(inactiveMap);
1345 const auto colorFormat = m_testConfig.colorFormat();
1346 const auto vecType = (vk::isUnormFormat(colorFormat) ? "vec4" : "uvec4");
1351 << "layout(location=0) out " << vecType << " color;\n"
1352 << "void main() {\n"
1353 << " color = " << vecType << "(pushConstants.triangleColor);\n"
1357 if (m_testConfig.needsGeometryShader())
1359 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
1360 const std::string inputPrimitive = ((topologyClass == TopologyClass::LINE) ? "lines" : "triangles");
1361 const deUint32 vertexCount = ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
1362 const std::string outputPrimitive = ((topologyClass == TopologyClass::LINE) ? "line_strip" : "triangle_strip");
1366 << "layout (" << inputPrimitive << ") in;\n"
1367 << "layout (" << outputPrimitive << ", max_vertices=" << vertexCount << ") out;\n"
1368 << (m_testConfig.isMultiViewport() ? pushConstants : "")
1369 << "in gl_PerVertex\n"
1371 << " vec4 gl_Position;\n"
1372 << "} gl_in[" << vertexCount << "];\n"
1373 << "out gl_PerVertex\n"
1375 << " vec4 gl_Position;\n"
1377 << "void main() {\n"
1378 << (m_testConfig.isMultiViewport() ? " gl_ViewportIndex = pushConstants.viewPortIndex;\n" : "")
1381 for (deUint32 i = 0; i < vertexCount; ++i)
1384 << " gl_Position = gl_in[" << i << "].gl_Position;\n"
1385 << " EmitVertex();\n"
1394 if (m_testConfig.needsTessellation())
1398 << "#extension GL_EXT_tessellation_shader : require\n"
1399 << "layout(vertices=3) out;\n"
1400 << "in gl_PerVertex\n"
1402 << " vec4 gl_Position;\n"
1403 << "} gl_in[gl_MaxPatchVertices];\n"
1404 << "out gl_PerVertex\n"
1406 << " vec4 gl_Position;\n"
1408 << "void main() {\n"
1409 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1410 << " gl_TessLevelOuter[0] = 3.0;\n"
1411 << " gl_TessLevelOuter[1] = 3.0;\n"
1412 << " gl_TessLevelOuter[2] = 3.0;\n"
1413 << " gl_TessLevelInner[0] = 3.0;\n"
1418 << "#extension GL_EXT_tessellation_shader : require\n"
1419 << "layout(triangles) in;\n"
1420 << "in gl_PerVertex\n"
1422 << " vec4 gl_Position;\n"
1423 << "} gl_in[gl_MaxPatchVertices];\n"
1424 << "out gl_PerVertex\n"
1426 << " vec4 gl_Position;\n"
1428 << "void main() {\n"
1429 << " gl_Position = (gl_in[0].gl_Position * gl_TessCoord.x + \n"
1430 << " gl_in[1].gl_Position * gl_TessCoord.y + \n"
1431 << " gl_in[2].gl_Position * gl_TessCoord.z);\n"
1437 programCollection.glslSources.add("vert") << glu::VertexSource(activeVertSource);
1438 programCollection.glslSources.add("vert2") << glu::VertexSource(inactiveVertSource);
1439 programCollection.glslSources.add("frag") << glu::FragmentSource(fragSource.str());
1440 if (m_testConfig.needsGeometryShader())
1441 programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource.str());
1442 if (m_testConfig.needsTessellation())
1444 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSource.str());
1445 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSource.str());
1449 TestInstance* ExtendedDynamicStateTest::createInstance (Context& context) const
1451 return new ExtendedDynamicStateInstance(context, m_testConfig);
1454 ExtendedDynamicStateInstance::ExtendedDynamicStateInstance(Context& context, const TestConfig& testConfig)
1455 : vkt::TestInstance (context)
1456 , m_testConfig (testConfig)
1460 struct VertexBufferInfo
1468 VertexBufferInfo (VertexBufferInfo&& other)
1469 : buffer (other.buffer.release())
1470 , offset (other.offset)
1471 , dataSize (other.dataSize)
1474 de::MovePtr<vk::BufferWithMemory> buffer;
1475 vk::VkDeviceSize offset;
1476 vk::VkDeviceSize dataSize;
1479 void logErrors(tcu::TestLog& log, const std::string& setName, const std::string& setDesc, const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& errorMask)
1481 log << tcu::TestLog::ImageSet(setName, setDesc)
1482 << tcu::TestLog::Image(setName + "Result", "Result image", result)
1483 << tcu::TestLog::Image(setName + "ErrorMask", "Error mask with errors marked in red", errorMask)
1484 << tcu::TestLog::EndImageSet;
1487 void copyAndFlush(const vk::DeviceInterface& vkd, vk::VkDevice device, vk::BufferWithMemory& buffer, size_t offset, const void* src, size_t size)
1489 auto& alloc = buffer.getAllocation();
1490 auto dst = reinterpret_cast<char*>(alloc.getHostPtr());
1492 deMemcpy(dst + offset, src, size);
1493 vk::flushAlloc(vkd, device, alloc);
1496 // Sets values for dynamic states if needed according to the test configuration.
1497 void setDynamicStates(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer)
1499 if (testConfig.cullModeConfig.dynamicValue)
1500 vkd.cmdSetCullModeEXT(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
1502 if (testConfig.frontFaceConfig.dynamicValue)
1503 vkd.cmdSetFrontFaceEXT(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
1505 if (testConfig.topologyConfig.dynamicValue)
1506 vkd.cmdSetPrimitiveTopologyEXT(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
1508 if (testConfig.viewportConfig.dynamicValue)
1510 const auto& viewports = testConfig.viewportConfig.dynamicValue.get();
1511 vkd.cmdSetViewportWithCountEXT(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
1514 if (testConfig.scissorConfig.dynamicValue)
1516 const auto& scissors = testConfig.scissorConfig.dynamicValue.get();
1517 vkd.cmdSetScissorWithCountEXT(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
1520 if (testConfig.depthTestEnableConfig.dynamicValue)
1521 vkd.cmdSetDepthTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
1523 if (testConfig.depthWriteEnableConfig.dynamicValue)
1524 vkd.cmdSetDepthWriteEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
1526 if (testConfig.depthCompareOpConfig.dynamicValue)
1527 vkd.cmdSetDepthCompareOpEXT(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
1529 if (testConfig.depthBoundsTestEnableConfig.dynamicValue)
1530 vkd.cmdSetDepthBoundsTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
1532 if (testConfig.stencilTestEnableConfig.dynamicValue)
1533 vkd.cmdSetStencilTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
1535 if (testConfig.depthBiasEnableConfig.dynamicValue)
1536 vkd.cmdSetDepthBiasEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBiasEnableConfig.dynamicValue.get()));
1538 if (testConfig.depthBiasConfig.dynamicValue)
1540 const auto& bias = testConfig.depthBiasConfig.dynamicValue.get();
1541 vkd.cmdSetDepthBias(cmdBuffer, bias.constantFactor, bias.clamp, 0.0f);
1544 if (testConfig.rastDiscardEnableConfig.dynamicValue)
1545 vkd.cmdSetRasterizerDiscardEnableEXT(cmdBuffer, makeVkBool32(testConfig.rastDiscardEnableConfig.dynamicValue.get()));
1547 if (testConfig.primRestartEnableConfig.dynamicValue)
1548 vkd.cmdSetPrimitiveRestartEnableEXT(cmdBuffer, makeVkBool32(testConfig.primRestartEnableConfig.dynamicValue.get()));
1550 if (testConfig.logicOpConfig.dynamicValue)
1551 vkd.cmdSetLogicOpEXT(cmdBuffer, testConfig.logicOpConfig.dynamicValue.get());
1553 if (testConfig.patchControlPointsConfig.dynamicValue)
1554 vkd.cmdSetPatchControlPointsEXT(cmdBuffer, testConfig.patchControlPointsConfig.dynamicValue.get());
1556 if (testConfig.stencilOpConfig.dynamicValue)
1558 for (const auto& params : testConfig.stencilOpConfig.dynamicValue.get())
1559 vkd.cmdSetStencilOpEXT(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
1562 if (testConfig.vertexGenerator.dynamicValue)
1564 const auto generator = testConfig.vertexGenerator.dynamicValue.get();
1565 const auto bindings = generator->getBindingDescriptions2(testConfig.strideConfig.staticValue);
1566 const auto attributes = generator->getAttributeDescriptions2();
1568 vkd.cmdSetVertexInputEXT(cmdBuffer,
1569 static_cast<deUint32>(bindings.size()), de::dataOrNull(bindings),
1570 static_cast<deUint32>(attributes.size()), de::dataOrNull(attributes));
1574 // Bind the appropriate vertex buffers using dynamic strides if the test configuration needs a dynamic stride.
1575 // Return true if the vertex buffer was bound.
1576 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)
1578 if (!testConfig.strideConfig.dynamicValue)
1581 const auto& viewportVec = testConfig.getActiveViewportVec();
1582 DE_UNREF(viewportVec); // For release builds.
1584 // When dynamically setting the vertex buffer stride, we cannot bind the vertex buffer in advance for some sequence
1585 // orderings if we have several viewports or meshes.
1586 DE_ASSERT((viewportVec.size() == 1u && testConfig.meshParams.size() == 1u)
1587 || testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW
1588 || testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
1590 // Split buffers, offsets, sizes and strides into their own vectors for the call.
1591 std::vector<vk::VkBuffer> buffers;
1592 std::vector<vk::VkDeviceSize> offsets;
1593 std::vector<vk::VkDeviceSize> sizes;
1594 const auto strides = testConfig.strideConfig.dynamicValue.get();
1596 const auto& chosenBuffers = (testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers);
1598 buffers.reserve (chosenBuffers.size());
1599 offsets.reserve (chosenBuffers.size());
1600 sizes.reserve (chosenBuffers.size());
1601 DE_ASSERT(chosenBuffers.size() == strides.size());
1603 for (const auto& vertBuffer : chosenBuffers)
1605 buffers.push_back (vertBuffer.buffer->get());
1606 offsets.push_back (vertBuffer.offset);
1607 sizes.push_back (vertBuffer.dataSize);
1610 vkd.cmdBindVertexBuffers2EXT(cmdBuffer, 0u, static_cast<deUint32>(chosenBuffers.size()), buffers.data(), offsets.data(), sizes.data(), strides.data());
1615 // Bind the given vertex buffers with the non-dynamic call. Similar to maybeBindVertexBufferDynStride but simpler.
1616 void bindVertexBuffers (const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer, const std::vector<VertexBufferInfo>& vertexBuffers)
1618 std::vector<vk::VkBuffer> buffers;
1619 std::vector<vk::VkDeviceSize> offsets;
1621 buffers.reserve (vertexBuffers.size());
1622 offsets.reserve (vertexBuffers.size());
1624 for (const auto& vertBuffer : vertexBuffers)
1626 buffers.push_back (vertBuffer.buffer->get());
1627 offsets.push_back (vertBuffer.offset);
1630 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, static_cast<deUint32>(vertexBuffers.size()), buffers.data(), offsets.data());
1634 // Create a vector of VertexBufferInfo elements using the given vertex generator and set of vertices.
1635 void prepareVertexBuffers ( std::vector<VertexBufferInfo>& buffers,
1636 const vk::DeviceInterface& vkd,
1637 vk::VkDevice device,
1638 vk::Allocator& allocator,
1639 const VertexGenerator* generator,
1640 const std::vector<tcu::Vec2>& vertices,
1641 deUint32 dataOffset,
1642 deUint32 trailingSize)
1644 const deUint32 paddingBytes = 0xDEADBEEFu;
1645 const auto vertexData = generator->createVertexData(vertices, dataOffset, trailingSize, &paddingBytes, sizeof(paddingBytes));
1647 for (const auto& bufferBytes : vertexData)
1649 const auto bufferSize = static_cast<vk::VkDeviceSize>(de::dataSize(bufferBytes));
1650 const auto extraSize = static_cast<vk::VkDeviceSize>(dataOffset + trailingSize);
1651 DE_ASSERT(bufferSize > extraSize);
1652 const auto dataSize = bufferSize - extraSize;
1654 // Create a full-size buffer but remember the data size and offset for it.
1655 const auto createInfo = vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1657 VertexBufferInfo bufferInfo;
1658 bufferInfo.buffer = de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(vkd, device, allocator, createInfo, vk::MemoryRequirement::HostVisible));
1659 bufferInfo.offset = static_cast<vk::VkDeviceSize>(dataOffset);
1660 bufferInfo.dataSize = dataSize;
1661 buffers.emplace_back(std::move(bufferInfo));
1663 // Copy the whole contents to the full buffer.
1664 copyAndFlush(vkd, device, *buffers.back().buffer, 0, bufferBytes.data(), de::dataSize(bufferBytes));
1668 tcu::TestStatus ExtendedDynamicStateInstance::iterate (void)
1670 using ImageWithMemoryVec = std::vector<std::unique_ptr<vk::ImageWithMemory>>;
1671 using ImageViewVec = std::vector<vk::Move<vk::VkImageView>>;
1672 using FramebufferVec = std::vector<vk::Move<vk::VkFramebuffer>>;
1674 const auto& vki = m_context.getInstanceInterface();
1675 const auto& vkd = m_context.getDeviceInterface();
1676 const auto physicalDevice = m_context.getPhysicalDevice();
1677 const auto device = m_context.getDevice();
1678 auto& allocator = m_context.getDefaultAllocator();
1679 const auto queue = m_context.getUniversalQueue();
1680 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1681 auto& log = m_context.getTestContext().getLog();
1683 const auto kReversed = m_testConfig.isReversed();
1684 const auto kNumIterations = m_testConfig.numIterations();
1685 const auto kSequenceOrdering = m_testConfig.sequenceOrdering;
1687 const auto kFramebufferExtent = vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u);
1688 const vk::VkImageUsageFlags kColorUsage = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1689 const vk::VkImageUsageFlags kDSUsage = (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1690 const vk::VkFormatFeatureFlags kDSFeatures = (vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
1691 const auto colorFormat = m_testConfig.colorFormat();
1693 // Choose depth/stencil format.
1694 const DepthStencilFormat* dsFormatInfo = nullptr;
1696 for (const auto& kDepthStencilFormat : kDepthStencilFormats)
1698 const auto dsProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kDepthStencilFormat.imageFormat);
1699 if ((dsProperties.optimalTilingFeatures & kDSFeatures) == kDSFeatures)
1701 dsFormatInfo = &kDepthStencilFormat;
1706 // Note: Not Supported insted of Fail because the transfer feature is not mandatory.
1708 TCU_THROW(NotSupportedError, "Required depth/stencil image features not supported");
1709 log << tcu::TestLog::Message << "Chosen depth/stencil format: " << dsFormatInfo->imageFormat << tcu::TestLog::EndMessage;
1711 // Swap static and dynamic values in the test configuration so the static pipeline ends up with the expected values for cases
1712 // where we will bind the static pipeline last before drawing.
1714 m_testConfig.swapValues();
1716 // Create color and depth/stencil images.
1717 ImageWithMemoryVec colorImages;
1718 ImageWithMemoryVec dsImages;
1720 const vk::VkImageCreateInfo colorImageInfo =
1722 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1723 nullptr, // const void* pNext;
1724 0u, // VkImageCreateFlags flags;
1725 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1726 colorFormat, // VkFormat format;
1727 kFramebufferExtent, // VkExtent3D extent;
1728 1u, // deUint32 mipLevels;
1729 1u, // deUint32 arrayLayers;
1730 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1731 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1732 kColorUsage, // VkImageUsageFlags usage;
1733 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1734 1u, // deUint32 queueFamilyIndexCount;
1735 &queueIndex, // const deUint32* pQueueFamilyIndices;
1736 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1738 for (deUint32 i = 0u; i < kNumIterations; ++i)
1739 colorImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, colorImageInfo, vk::MemoryRequirement::Any));
1741 const vk::VkImageCreateInfo dsImageInfo =
1743 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1744 nullptr, // const void* pNext;
1745 0u, // VkImageCreateFlags flags;
1746 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1747 dsFormatInfo->imageFormat, // VkFormat format;
1748 kFramebufferExtent, // VkExtent3D extent;
1749 1u, // deUint32 mipLevels;
1750 1u, // deUint32 arrayLayers;
1751 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1752 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1753 kDSUsage, // VkImageUsageFlags usage;
1754 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1755 1u, // deUint32 queueFamilyIndexCount;
1756 &queueIndex, // const deUint32* pQueueFamilyIndices;
1757 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1759 for (deUint32 i = 0u; i < kNumIterations; ++i)
1760 dsImages.emplace_back(new vk::ImageWithMemory(vkd, device, allocator, dsImageInfo, vk::MemoryRequirement::Any));
1762 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1763 const auto dsSubresourceRange = vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
1765 ImageViewVec colorImageViews;
1766 ImageViewVec dsImageViews;
1768 for (const auto& img : colorImages)
1769 colorImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1771 for (const auto& img : dsImages)
1772 dsImageViews.emplace_back(vk::makeImageView(vkd, device, img->get(), vk::VK_IMAGE_VIEW_TYPE_2D, dsFormatInfo->imageFormat, dsSubresourceRange));
1775 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
1776 const std::vector<deUint32> indices { 0, 1, 2, 3, 0xFFFFFFFF, 4, 5, 0, 3 };
1777 std::vector<tcu::Vec2> vertices;
1779 if (topologyClass == TopologyClass::TRIANGLE)
1781 // Full-screen triangle fan with 6 vertices.
1784 // +-------+-------+
1792 // +-------+-------+
1794 vertices.reserve(6u);
1795 vertices.push_back(tcu::Vec2( 0.0f, 1.0f));
1796 vertices.push_back(tcu::Vec2( 1.0f, 1.0f));
1797 vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
1798 vertices.push_back(tcu::Vec2( 0.0f, -1.0f));
1799 vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
1800 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
1802 else if (topologyClass == TopologyClass::PATCH)
1804 DE_ASSERT(m_testConfig.getActivePatchControlPoints() > 1u);
1806 // 2 triangles making a quad
1807 vertices.reserve(6u);
1808 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
1809 vertices.push_back(tcu::Vec2( 1.0f, 1.0f));
1810 vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
1811 vertices.push_back(tcu::Vec2( 1.0f, -1.0f));
1812 vertices.push_back(tcu::Vec2(-1.0f, -1.0f));
1813 vertices.push_back(tcu::Vec2(-1.0f, 1.0f));
1815 else // TopologyClass::LINE
1817 // 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.
1818 vertices.reserve(kFramebufferHeight * 4u);
1819 const float lineHeight = 2.0f / static_cast<float>(kFramebufferHeight);
1820 for (deUint32 rowIdx = 0; rowIdx < kFramebufferHeight; ++rowIdx)
1822 // Offset of 0.5 pixels + one line per row from -1 to 1.
1823 const float yCoord = (lineHeight / 2.0f) + lineHeight * static_cast<float>(rowIdx) - 1.0f;
1824 vertices.push_back(tcu::Vec2(-1.0f, yCoord));
1825 vertices.push_back(tcu::Vec2(-0.5f, yCoord));
1826 vertices.push_back(tcu::Vec2( 0.5f, yCoord));
1827 vertices.push_back(tcu::Vec2( 1.0f, yCoord));
1831 if (m_testConfig.singleVertex)
1834 // Reversed vertices, except for the first one (0, 5, 4, 3, 2, 1): clockwise mesh for triangles. Not to be used with lines.
1835 std::vector<tcu::Vec2> rvertices;
1836 if (topologyClass == TopologyClass::TRIANGLE)
1838 DE_ASSERT(!vertices.empty());
1839 rvertices.reserve(vertices.size());
1840 rvertices.push_back(vertices[0]);
1841 std::copy_n(vertices.rbegin(), vertices.size() - 1u, std::back_inserter(rvertices));
1844 if (topologyClass != TopologyClass::TRIANGLE)
1846 for (const auto& mesh : m_testConfig.meshParams)
1848 DE_UNREF(mesh); // For release builds.
1849 DE_ASSERT(!mesh.reversed);
1853 // Buffers with vertex data for the different bindings.
1854 std::vector<VertexBufferInfo> vertBuffers;
1855 std::vector<VertexBufferInfo> rvertBuffers;
1858 const auto dataOffset = static_cast<deUint32>(m_testConfig.vertexDataOffset);
1859 const auto trailingSize = static_cast<deUint32>(m_testConfig.vertexDataExtraBytes);
1860 const auto generator = m_testConfig.getActiveVertexGenerator();
1861 prepareVertexBuffers(vertBuffers, vkd, device, allocator, generator, vertices, dataOffset, trailingSize);
1862 if (topologyClass == TopologyClass::TRIANGLE)
1863 prepareVertexBuffers(rvertBuffers, vkd, device, allocator, generator, rvertices, dataOffset, trailingSize);
1867 const auto indexDataSize = static_cast<vk::VkDeviceSize>(de::dataSize(indices));
1868 const auto indexBufferInfo = vk::makeBufferCreateInfo(indexDataSize, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
1869 vk::BufferWithMemory indexBuffer (vkd, device, allocator, indexBufferInfo, vk::MemoryRequirement::HostVisible);
1870 copyAndFlush(vkd, device, indexBuffer, 0, indices.data(), static_cast<size_t>(indexDataSize));
1872 // Descriptor set layout.
1873 vk::DescriptorSetLayoutBuilder layoutBuilder;
1874 const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1877 vk::VkShaderStageFlags pushConstantStageFlags = (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1878 if (m_testConfig.isMultiViewport())
1879 pushConstantStageFlags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
1881 const vk::VkPushConstantRange pushConstantRange =
1883 pushConstantStageFlags, // VkShaderStageFlags stageFlags;
1884 0u, // deUint32 offset;
1885 static_cast<deUint32>(sizeof(PushConstants)), // deUint32 size;
1888 const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1890 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1891 nullptr, // const void* pNext;
1892 0u, // VkPipelineLayoutCreateFlags flags;
1893 1u, // deUint32 setLayoutCount;
1894 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
1895 1u, // deUint32 pushConstantRangeCount;
1896 &pushConstantRange, // const VkPushConstantRange* pPushConstantRanges;
1898 const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo);
1900 // Render pass with single subpass.
1901 const vk::VkAttachmentReference colorAttachmentReference =
1903 0u, // deUint32 attachment;
1904 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1907 const vk::VkAttachmentReference dsAttachmentReference =
1909 1u, // deUint32 attachment;
1910 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1913 const vk::VkSubpassDescription subpassDescription =
1915 0u, // VkSubpassDescriptionFlags flags;
1916 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1917 0u, // deUint32 inputAttachmentCount;
1918 nullptr, // const VkAttachmentReference* pInputAttachments;
1919 1u, // deUint32 colorAttachmentCount;
1920 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
1921 nullptr, // const VkAttachmentReference* pResolveAttachments;
1922 &dsAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
1923 0u, // deUint32 preserveAttachmentCount;
1924 nullptr, // const deUint32* pPreserveAttachments;
1927 std::vector<vk::VkAttachmentDescription> attachmentDescriptions;
1929 attachmentDescriptions.push_back(vk::VkAttachmentDescription
1931 0u, // VkAttachmentDescriptionFlags flags;
1932 colorFormat, // VkFormat format;
1933 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1934 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1935 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1936 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1937 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1938 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1939 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1942 attachmentDescriptions.push_back(vk::VkAttachmentDescription
1944 0u, // VkAttachmentDescriptionFlags flags;
1945 dsFormatInfo->imageFormat, // VkFormat format;
1946 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1947 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1948 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1949 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
1950 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
1951 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1952 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1955 const vk::VkRenderPassCreateInfo renderPassCreateInfo =
1957 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1958 nullptr, // const void* pNext;
1959 0u, // VkRenderPassCreateFlags flags;
1960 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
1961 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
1962 1u, // deUint32 subpassCount;
1963 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1964 0u, // deUint32 dependencyCount;
1965 nullptr, // const VkSubpassDependency* pDependencies;
1967 const auto renderPass = vk::createRenderPass(vkd, device, &renderPassCreateInfo);
1970 FramebufferVec framebuffers;
1972 DE_ASSERT(colorImageViews.size() == dsImageViews.size());
1973 for (size_t imgIdx = 0; imgIdx < colorImageViews.size(); ++imgIdx)
1975 std::vector<vk::VkImageView> attachments;
1976 attachments.push_back(colorImageViews[imgIdx].get());
1977 attachments.push_back(dsImageViews[imgIdx].get());
1979 const vk::VkFramebufferCreateInfo framebufferCreateInfo =
1981 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1982 nullptr, // const void* pNext;
1983 0u, // VkFramebufferCreateFlags flags;
1984 renderPass.get(), // VkRenderPass renderPass;
1985 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount;
1986 attachments.data(), // const VkImageView* pAttachments;
1987 kFramebufferWidth, // deUint32 width;
1988 kFramebufferHeight, // deUint32 height;
1989 1u, // deUint32 layers;
1992 framebuffers.emplace_back(vk::createFramebuffer(vkd, device, &framebufferCreateInfo));
1996 const auto vertModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1997 const auto vertModule2 = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert2"), 0u);
1998 const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1999 vk::Move<vk::VkShaderModule> geomModule;
2000 vk::Move<vk::VkShaderModule> tescModule;
2001 vk::Move<vk::VkShaderModule> teseModule;
2003 if (m_testConfig.needsGeometryShader())
2004 geomModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("geom"), 0u);
2006 if (m_testConfig.needsTessellation())
2008 tescModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("tesc"), 0u);
2009 teseModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("tese"), 0u);
2013 std::vector<vk::VkPipelineShaderStageCreateInfo> shaderStages;
2014 std::vector<vk::VkPipelineShaderStageCreateInfo> shaderStaticStages;
2016 vk::VkPipelineShaderStageCreateInfo shaderStageCreateInfo =
2018 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2019 nullptr, // const void* pNext;
2020 0u, // VkPipelineShaderStageCreateFlags flags;
2021 vk::VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
2022 fragModule.get(), // VkShaderModule module;
2023 "main", // const char* pName;
2024 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
2027 shaderStages.push_back(shaderStageCreateInfo);
2029 if (m_testConfig.needsGeometryShader())
2031 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
2032 shaderStageCreateInfo.module = geomModule.get();
2033 shaderStages.push_back(shaderStageCreateInfo);
2036 if (m_testConfig.needsTessellation())
2038 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
2039 shaderStageCreateInfo.module = tescModule.get();
2040 shaderStages.push_back(shaderStageCreateInfo);
2042 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2043 shaderStageCreateInfo.module = teseModule.get();
2044 shaderStages.push_back(shaderStageCreateInfo);
2047 // Both vectors are the same up to here. Then, they differ in the vertex stage.
2048 shaderStaticStages = shaderStages;
2049 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_VERTEX_BIT;
2051 shaderStageCreateInfo.module = vertModule.get();
2052 shaderStages.push_back(shaderStageCreateInfo);
2054 shaderStageCreateInfo.module = vertModule2.get();
2055 shaderStaticStages.push_back(shaderStageCreateInfo);
2058 const auto vertexBindings = m_testConfig.vertexGenerator.staticValue->getBindingDescriptions(m_testConfig.strideConfig.staticValue);
2059 const auto vertexAttributes = m_testConfig.vertexGenerator.staticValue->getAttributeDescriptions();
2061 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
2063 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2064 nullptr, // const void* pNext;
2065 0u, // VkPipelineVertexInputStateCreateFlags flags;
2066 static_cast<deUint32>(vertexBindings.size()), // deUint32 vertexBindingDescriptionCount;
2067 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2068 static_cast<deUint32>(vertexAttributes.size()), // deUint32 vertexAttributeDescriptionCount;
2069 vertexAttributes.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2073 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
2075 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
2076 nullptr, // const void* pNext;
2077 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
2078 m_testConfig.topologyConfig.staticValue, // VkPrimitiveTopology topology;
2079 makeVkBool32(m_testConfig.primRestartEnableConfig.staticValue), // VkBool32 primitiveRestartEnable;
2083 if (m_testConfig.viewportConfig.dynamicValue)
2084 DE_ASSERT(m_testConfig.viewportConfig.dynamicValue.get().size() > 0u);
2086 DE_ASSERT(m_testConfig.viewportConfig.staticValue.size() > 0u);
2088 if (m_testConfig.scissorConfig.dynamicValue)
2089 DE_ASSERT(m_testConfig.scissorConfig.dynamicValue.get().size() > 0u);
2091 DE_ASSERT(m_testConfig.scissorConfig.staticValue.size() > 0u);
2093 // The viewport and scissor counts must match in the static part, which will be used by the static pipeline.
2094 const auto minStaticCount = static_cast<deUint32>(std::min(m_testConfig.viewportConfig.staticValue.size(), m_testConfig.scissorConfig.staticValue.size()));
2096 // For the static pipeline.
2097 const vk::VkPipelineViewportStateCreateInfo staticViewportStateCreateInfo =
2099 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2100 nullptr, // const void* pNext;
2101 0u, // VkPipelineViewportStateCreateFlags flags;
2102 minStaticCount, // deUint32 viewportCount;
2103 m_testConfig.viewportConfig.staticValue.data(), // const VkViewport* pViewports;
2104 minStaticCount, // deUint32 scissorCount;
2105 m_testConfig.scissorConfig.staticValue.data(), // const VkRect2D* pScissors;
2108 // For the dynamic pipeline.
2109 const auto finalDynamicViewportCount = (m_testConfig.viewportConfig.dynamicValue
2110 ? m_testConfig.viewportConfig.dynamicValue.get().size()
2111 : m_testConfig.viewportConfig.staticValue.size());
2113 const auto finalDynamicScissorCount = (m_testConfig.scissorConfig.dynamicValue
2114 ? m_testConfig.scissorConfig.dynamicValue.get().size()
2115 : m_testConfig.scissorConfig.staticValue.size());
2117 const auto minDynamicCount = static_cast<deUint32>(std::min(finalDynamicScissorCount, finalDynamicViewportCount));
2119 // The viewport and scissor counts must be zero when a dynamic value will be provided, as per the spec.
2120 const vk::VkPipelineViewportStateCreateInfo dynamicViewportStateCreateInfo =
2122 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2123 nullptr, // const void* pNext;
2124 0u, // VkPipelineViewportStateCreateFlags flags;
2125 (m_testConfig.viewportConfig.dynamicValue ? 0u : minDynamicCount), // deUint32 viewportCount;
2126 m_testConfig.viewportConfig.staticValue.data(), // const VkViewport* pViewports;
2127 (m_testConfig.scissorConfig.dynamicValue ? 0u : minDynamicCount), // deUint32 scissorCount;
2128 m_testConfig.scissorConfig.staticValue.data(), // const VkRect2D* pScissors;
2131 // Rasterization state.
2132 vk::VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
2134 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2135 nullptr, // const void* pNext;
2136 0u, // VkPipelineRasterizationStateCreateFlags flags;
2137 VK_FALSE, // VkBool32 depthClampEnable;
2138 makeVkBool32(m_testConfig.rastDiscardEnableConfig.staticValue), // VkBool32 rasterizerDiscardEnable;
2139 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
2140 m_testConfig.cullModeConfig.staticValue, // VkCullModeFlags cullMode;
2141 m_testConfig.frontFaceConfig.staticValue, // VkFrontFace frontFace;
2142 makeVkBool32(m_testConfig.depthBiasEnableConfig.staticValue), // VkBool32 depthBiasEnable;
2143 m_testConfig.depthBiasConfig.staticValue.constantFactor, // float depthBiasConstantFactor;
2144 m_testConfig.depthBiasConfig.staticValue.clamp, // float depthBiasClamp;
2145 0.0f, // float depthBiasSlopeFactor;
2146 1.0f, // float lineWidth;
2149 // Multisample state.
2150 const vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
2152 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2153 nullptr, // const void* pNext;
2154 0u, // VkPipelineMultisampleStateCreateFlags flags;
2155 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
2156 VK_FALSE, // VkBool32 sampleShadingEnable;
2157 0.0f, // float minSampleShading;
2158 nullptr, // const VkSampleMask* pSampleMask;
2159 VK_FALSE, // VkBool32 alphaToCoverageEnable;
2160 VK_FALSE, // VkBool32 alphaToOneEnable;
2163 // Depth/stencil state.
2164 vk::VkStencilOpState staticFrontStencil;
2165 vk::VkStencilOpState staticBackStencil;
2166 bool staticFrontStencilSet = false;
2167 bool staticBackStencilSet = false;
2169 // Common setup for the front and back operations.
2170 staticFrontStencil.compareMask = 0xFFu;
2171 staticFrontStencil.writeMask = 0xFFu;
2172 staticFrontStencil.reference = m_testConfig.referenceStencil;
2173 staticBackStencil = staticFrontStencil;
2175 for (const auto& op : m_testConfig.stencilOpConfig.staticValue)
2177 if ((op.faceMask & vk::VK_STENCIL_FACE_FRONT_BIT) != 0u)
2179 copy(staticFrontStencil, op);
2180 staticFrontStencilSet = true;
2182 if ((op.faceMask & vk::VK_STENCIL_FACE_BACK_BIT) != 0u)
2184 copy(staticBackStencil, op);
2185 staticBackStencilSet = true;
2189 // Default values for the static part.
2190 if (!staticFrontStencilSet)
2191 copy(staticFrontStencil, kDefaultStencilOpParams);
2192 if (!staticBackStencilSet)
2193 copy(staticBackStencil, kDefaultStencilOpParams);
2195 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
2197 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
2198 nullptr, // const void* pNext;
2199 0u, // VkPipelineDepthStencilStateCreateFlags flags;
2200 makeVkBool32(m_testConfig.depthTestEnableConfig.staticValue), // VkBool32 depthTestEnable;
2201 makeVkBool32(m_testConfig.depthWriteEnableConfig.staticValue), // VkBool32 depthWriteEnable;
2202 m_testConfig.depthCompareOpConfig.staticValue, // VkCompareOp depthCompareOp;
2203 makeVkBool32(m_testConfig.depthBoundsTestEnableConfig.staticValue), // VkBool32 depthBoundsTestEnable;
2204 makeVkBool32(m_testConfig.stencilTestEnableConfig.staticValue), // VkBool32 stencilTestEnable;
2205 staticFrontStencil, // VkStencilOpState front;
2206 staticBackStencil, // VkStencilOpState back;
2207 m_testConfig.minDepthBounds, // float minDepthBounds;
2208 m_testConfig.maxDepthBounds, // float maxDepthBounds;
2211 // Dynamic state. Here we will set all states which have a dynamic value.
2212 const auto dynamicStates = m_testConfig.getDynamicStates();
2214 const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
2216 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
2217 nullptr, // const void* pNext;
2218 0u, // VkPipelineDynamicStateCreateFlags flags;
2219 static_cast<deUint32>(dynamicStates.size()), // deUint32 dynamicStateCount;
2220 de::dataOrNull(dynamicStates), // const VkDynamicState* pDynamicStates;
2223 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
2225 VK_FALSE, // VkBool32 blendEnable
2226 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
2227 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
2228 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
2229 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
2230 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
2231 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
2232 vk::VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
2233 | vk::VK_COLOR_COMPONENT_G_BIT
2234 | vk::VK_COLOR_COMPONENT_B_BIT
2235 | vk::VK_COLOR_COMPONENT_A_BIT
2238 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
2240 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
2241 nullptr, // const void* pNext
2242 0u, // VkPipelineColorBlendStateCreateFlags flags
2243 makeVkBool32(m_testConfig.testLogicOp()), // VkBool32 logicOpEnable
2244 m_testConfig.logicOpConfig.staticValue, // VkLogicOp logicOp
2245 1u, // deUint32 attachmentCount
2246 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
2247 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
2250 const vk::VkPipelineTessellationStateCreateInfo pipelineTessellationStateCreateInfo =
2252 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType
2253 nullptr, // const void* pNext
2254 0u, // VkPipelineTessellationStateCreateFlags flags
2255 m_testConfig.patchControlPointsConfig.staticValue, // uint32_t patchControlPoints
2258 const auto pTessellationState = (m_testConfig.needsTessellation() ? &pipelineTessellationStateCreateInfo : nullptr);
2260 const vk::VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfoTemplate =
2262 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
2263 nullptr, // const void* pNext;
2264 0u, // VkPipelineCreateFlags flags;
2265 static_cast<deUint32>(shaderStages.size()), // deUint32 stageCount;
2266 shaderStages.data(), // const VkPipelineShaderStageCreateInfo* pStages;
2267 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
2268 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
2269 pTessellationState, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
2270 nullptr, // const VkPipelineViewportStateCreateInfo * pViewportState;
2271 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
2272 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
2273 &depthStencilStateCreateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
2274 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
2275 nullptr, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2276 pipelineLayout.get(), // VkPipelineLayout layout;
2277 renderPass.get(), // VkRenderPass renderPass;
2278 0u, // deUint32 subpass;
2279 DE_NULL, // VkPipeline basePipelineHandle;
2280 0, // deInt32 basePipelineIndex;
2283 vk::Move<vk::VkPipeline> staticPipeline;
2284 const bool bindStaticFirst = (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES ||
2285 kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES ||
2286 kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC);
2287 const bool useStaticPipeline = (bindStaticFirst || kReversed);
2289 // Create static pipeline when needed.
2290 if (useStaticPipeline)
2292 auto staticPipelineCreateInfo = graphicsPipelineCreateInfoTemplate;
2293 staticPipelineCreateInfo.pViewportState = &staticViewportStateCreateInfo;
2294 staticPipelineCreateInfo.pStages = shaderStaticStages.data();
2295 staticPipeline = vk::createGraphicsPipeline(vkd, device, DE_NULL, &staticPipelineCreateInfo);
2298 // Create dynamic pipeline.
2299 vk::Move<vk::VkPipeline> graphicsPipeline;
2301 auto dynamicPipelineCreateInfo = graphicsPipelineCreateInfoTemplate;
2302 dynamicPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
2303 dynamicPipelineCreateInfo.pViewportState = &dynamicViewportStateCreateInfo;
2304 graphicsPipeline = vk::createGraphicsPipeline(vkd, device, DE_NULL, &dynamicPipelineCreateInfo);
2308 const auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
2309 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd , device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2310 const auto cmdBuffer = cmdBufferPtr.get();
2312 // Clear values, clear to green for dynamic logicOp
2313 std::vector<vk::VkClearValue> clearValues;
2314 clearValues.push_back(m_testConfig.clearColorValue);
2315 clearValues.push_back(vk::makeClearValueDepthStencil(m_testConfig.clearDepthValue, m_testConfig.clearStencilValue));
2317 // Record command buffer.
2318 vk::beginCommandBuffer(vkd, cmdBuffer);
2320 for (deUint32 iteration = 0u; iteration < kNumIterations; ++iteration)
2322 // Track in-advance vertex buffer binding.
2323 bool boundInAdvance = false;
2325 // Maybe set extended dynamic state here.
2326 if (kSequenceOrdering == SequenceOrdering::CMD_BUFFER_START)
2328 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2329 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
2332 // Begin render pass.
2333 vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffers[iteration].get(), vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
2335 // Bind a static pipeline first if needed.
2336 if (bindStaticFirst && iteration == 0u)
2337 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, staticPipeline.get());
2339 // Maybe set extended dynamic state here.
2340 if (kSequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES)
2342 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2343 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
2346 // Bind dynamic pipeline.
2347 if ((kSequenceOrdering != SequenceOrdering::TWO_DRAWS_DYNAMIC &&
2348 kSequenceOrdering != SequenceOrdering::TWO_DRAWS_STATIC) ||
2349 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
2350 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
2352 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
2355 if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
2356 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC && iteration > 0u) ||
2357 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration == 0u))
2359 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2360 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffers, rvertBuffers);
2363 // Bind a static pipeline last if needed.
2364 if (kSequenceOrdering == SequenceOrdering::BEFORE_GOOD_STATIC ||
2365 (kSequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC && iteration > 0u))
2367 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, staticPipeline.get());
2370 const auto& viewportVec = m_testConfig.getActiveViewportVec();
2371 for (size_t viewportIdx = 0u; viewportIdx < viewportVec.size(); ++viewportIdx)
2373 for (size_t meshIdx = 0u; meshIdx < m_testConfig.meshParams.size(); ++meshIdx)
2376 PushConstants pushConstants =
2378 m_testConfig.meshParams[meshIdx].color, // tcu::Vec4 triangleColor;
2379 m_testConfig.meshParams[meshIdx].depth, // float meshDepth;
2380 static_cast<deInt32>(viewportIdx), // deInt32 viewPortIndex;
2381 m_testConfig.meshParams[meshIdx].scaleX, // float scaleX;
2382 m_testConfig.meshParams[meshIdx].scaleY, // float scaleY;
2383 m_testConfig.meshParams[meshIdx].offsetX, // float offsetX;
2384 m_testConfig.meshParams[meshIdx].offsetY, // float offsetY;
2385 m_testConfig.meshParams[meshIdx].fanScale, // float fanScale;
2387 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantStageFlags, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
2389 // Track vertex bounding state for this mesh.
2390 bool boundBeforeDraw = false;
2392 // Maybe set extended dynamic state here.
2393 if (kSequenceOrdering == SequenceOrdering::BEFORE_DRAW || kSequenceOrdering == SequenceOrdering::AFTER_PIPELINES)
2395 setDynamicStates(m_testConfig, vkd, cmdBuffer);
2396 boundBeforeDraw = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, meshIdx, vertBuffers, rvertBuffers);
2399 // Bind vertex buffer with static stride if needed and draw.
2400 if (!(boundInAdvance || boundBeforeDraw))
2402 bindVertexBuffers(vkd, cmdBuffer, (m_testConfig.meshParams[meshIdx].reversed ? rvertBuffers : vertBuffers));
2403 if (m_testConfig.needsIndexBuffer())
2405 vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), 0, vk::VK_INDEX_TYPE_UINT32);
2410 if (m_testConfig.needsIndexBuffer())
2412 deUint32 numIndices = static_cast<deUint32>(indices.size());
2413 // For SequenceOrdering::TWO_DRAWS_DYNAMIC and TWO_DRAWS_STATIC cases, the first draw does not have primitive restart enabled
2414 // So, draw without using the invalid (0xFFFFFFFF) index, the second draw with primitive restart enabled will replace the results
2415 // using all indices.
2416 if (iteration == 0u &&
2417 (m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_DYNAMIC ||
2418 m_testConfig.sequenceOrdering == SequenceOrdering::TWO_DRAWS_STATIC))
2420 vkd.cmdDrawIndexed(cmdBuffer, numIndices, 1u, 0u, 0u, 0u);
2424 deUint32 vertex_count = static_cast<deUint32>(vertices.size());
2425 if (m_testConfig.singleVertex)
2426 vertex_count = m_testConfig.singleVertexDrawCount;
2427 vkd.cmdDraw(cmdBuffer, vertex_count, 1u, 0u, 0u);
2432 vk::endRenderPass(vkd, cmdBuffer);
2435 vk::endCommandBuffer(vkd, cmdBuffer);
2438 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2440 // Read result image aspects from the last used framebuffer.
2441 const tcu::UVec2 renderSize (kFramebufferWidth, kFramebufferHeight);
2442 const auto colorBuffer = readColorAttachment(vkd, device, queue, queueIndex, allocator, colorImages.back()->get(), colorFormat, renderSize);
2443 const auto depthBuffer = readDepthAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize);
2444 const auto stencilBuffer = readStencilAttachment(vkd, device, queue, queueIndex, allocator, dsImages.back()->get(), dsFormatInfo->imageFormat, renderSize, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
2445 const auto colorAccess = colorBuffer->getAccess();
2446 const auto depthAccess = depthBuffer->getAccess();
2447 const auto stencilAccess = stencilBuffer->getAccess();
2449 const int kWidth = static_cast<int>(kFramebufferWidth);
2450 const int kHeight = static_cast<int>(kFramebufferHeight);
2452 // Generate reference color buffer.
2453 const auto tcuColorFormat = vk::mapVkFormat(colorFormat);
2454 tcu::TextureLevel referenceColorLevel (tcuColorFormat, kWidth, kHeight);
2455 tcu::PixelBufferAccess referenceColorAccess = referenceColorLevel.getAccess();
2456 m_testConfig.referenceColor(referenceColorAccess);
2458 const tcu::TextureFormat errorFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
2459 tcu::TextureLevel colorError (errorFormat, kWidth, kHeight);
2460 tcu::TextureLevel depthError (errorFormat, kWidth, kHeight);
2461 tcu::TextureLevel stencilError (errorFormat, kWidth, kHeight);
2462 const auto colorErrorAccess = colorError.getAccess();
2463 const auto depthErrorAccess = depthError.getAccess();
2464 const auto stencilErrorAccess = stencilError.getAccess();
2465 const tcu::Vec4 kGood (0.0f, 1.0f, 0.0f, 1.0f);
2466 const tcu::Vec4 kBad (1.0f, 0.0f, 0.0f, 1.0f);
2468 // Check expected values.
2469 const auto minDepth = m_testConfig.expectedDepth - dsFormatInfo->depthThreshold;
2470 const auto maxDepth = m_testConfig.expectedDepth + dsFormatInfo->depthThreshold;
2471 bool colorMatch = true;
2472 bool depthMatch = true;
2473 bool stencilMatch = true;
2476 for (int y = 0; y < kHeight; ++y)
2477 for (int x = 0; x < kWidth; ++x)
2479 if (vk::isUnormFormat(colorFormat))
2481 auto colorPixel = colorAccess.getPixel(x, y);
2482 auto expectedPixel = referenceColorAccess.getPixel(x, y);
2483 match = tcu::boolAll(tcu::lessThan(tcu::absDiff(colorPixel, expectedPixel), kUnormColorThreshold));
2487 DE_ASSERT(vk::isUintFormat(colorFormat));
2488 auto colorPixel = colorAccess.getPixelUint(x, y);
2489 auto expectedPixel = referenceColorAccess.getPixelUint(x, y);
2490 match = (colorPixel == expectedPixel);
2493 colorErrorAccess.setPixel((match ? kGood : kBad), x, y);
2497 const auto depthPixel = depthAccess.getPixDepth(x, y);
2498 match = de::inRange(depthPixel, minDepth, maxDepth);
2499 depthErrorAccess.setPixel((match ? kGood : kBad), x, y);
2503 const auto stencilPixel = static_cast<deUint32>(stencilAccess.getPixStencil(x, y));
2504 match = (stencilPixel == m_testConfig.expectedStencil);
2505 stencilErrorAccess.setPixel((match ? kGood : kBad), x, y);
2507 stencilMatch = false;
2510 if (!(colorMatch && depthMatch && stencilMatch))
2513 logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
2516 logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
2519 logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
2521 return tcu::TestStatus::fail("Incorrect value found in attachments; please check logged images");
2524 return tcu::TestStatus::pass("Pass");
2527 bool stencilPasses(vk::VkCompareOp op, deUint8 storedValue, deUint8 referenceValue)
2531 case vk::VK_COMPARE_OP_NEVER: return false;
2532 case vk::VK_COMPARE_OP_LESS: return (referenceValue < storedValue);
2533 case vk::VK_COMPARE_OP_EQUAL: return (referenceValue == storedValue);
2534 case vk::VK_COMPARE_OP_LESS_OR_EQUAL: return (referenceValue <= storedValue);
2535 case vk::VK_COMPARE_OP_GREATER: return (referenceValue > storedValue);
2536 case vk::VK_COMPARE_OP_GREATER_OR_EQUAL: return (referenceValue >= storedValue);
2537 case vk::VK_COMPARE_OP_ALWAYS: return true;
2538 default: DE_ASSERT(false); return false;
2541 return false; // Unreachable.
2544 deUint8 stencilResult(vk::VkStencilOp op, deUint8 storedValue, deUint8 referenceValue, deUint8 min, deUint8 max)
2546 deUint8 result = storedValue;
2550 case vk::VK_STENCIL_OP_KEEP: break;
2551 case vk::VK_STENCIL_OP_ZERO: result = 0; break;
2552 case vk::VK_STENCIL_OP_REPLACE: result = referenceValue; break;
2553 case vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP: result = ((result == max) ? result : static_cast<deUint8>(result + 1)); break;
2554 case vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP: result = ((result == min) ? result : static_cast<deUint8>(result - 1)); break;
2555 case vk::VK_STENCIL_OP_INVERT: result = static_cast<deUint8>(~result); break;
2556 case vk::VK_STENCIL_OP_INCREMENT_AND_WRAP: result = ((result == max) ? min : static_cast<deUint8>(result + 1)); break;
2557 case vk::VK_STENCIL_OP_DECREMENT_AND_WRAP: result = ((result == min) ? max : static_cast<deUint8>(result - 1)); break;
2558 default: DE_ASSERT(false); break;
2564 } // anonymous namespace
2566 tcu::TestCaseGroup* createExtendedDynamicStateTests (tcu::TestContext& testCtx)
2568 de::MovePtr<tcu::TestCaseGroup> extendedDynamicStateGroup(new tcu::TestCaseGroup(testCtx, "extended_dynamic_state", "Tests for VK_EXT_extended_dynamic_state"));
2570 // Auxiliar constants.
2571 const deUint32 kHalfWidthU = kFramebufferWidth/2u;
2572 const deInt32 kHalfWidthI = static_cast<deInt32>(kHalfWidthU);
2573 const float kHalfWidthF = static_cast<float>(kHalfWidthU);
2574 const float kHeightF = static_cast<float>(kFramebufferHeight);
2578 SequenceOrdering ordering;
2581 } kOrderingCases[] =
2583 { SequenceOrdering::CMD_BUFFER_START, "cmd_buffer_start", "Dynamic state set after command buffer start" },
2584 { SequenceOrdering::BEFORE_DRAW, "before_draw", "Dynamic state set just before drawing" },
2585 { 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" },
2586 { SequenceOrdering::AFTER_PIPELINES, "after_pipelines", "Dynamic state set after both a static-state pipeline and a second dynamic-state pipeline have been bound" },
2587 { 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" },
2588 { SequenceOrdering::TWO_DRAWS_DYNAMIC, "two_draws_dynamic", "Bind bad static pipeline and draw, followed by binding correct dynamic pipeline and drawing again" },
2589 { SequenceOrdering::TWO_DRAWS_STATIC, "two_draws_static", "Bind bad dynamic pipeline and draw, followed by binding correct static pipeline and drawing again" },
2592 for (const auto& kOrderingCase : kOrderingCases)
2594 const auto& kOrdering = kOrderingCase.ordering;
2596 de::MovePtr<tcu::TestCaseGroup> orderingGroup(new tcu::TestCaseGroup(testCtx, kOrderingCase.name.c_str(), kOrderingCase.desc.c_str()));
2600 TestConfig config(kOrdering);
2601 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
2602 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE);
2603 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_none", "Dynamically set cull mode to none", config));
2606 TestConfig config(kOrdering);
2607 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_AND_BACK;
2608 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_BACK_BIT);
2609 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_back", "Dynamically set cull mode to back", config));
2612 TestConfig config(kOrdering);
2613 // Make triangles look back.
2614 config.meshParams[0].reversed = true;
2615 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2616 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_BIT);
2617 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front", "Dynamically set cull mode to front", config));
2620 TestConfig config(kOrdering);
2621 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_NONE;
2622 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_AND_BACK);
2623 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2624 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front_and_back", "Dynamically set cull mode to front and back", config));
2629 TestConfig config(kOrdering);
2630 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2631 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
2632 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
2633 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw", "Dynamically set front face to clockwise", config));
2636 TestConfig config(kOrdering);
2637 // Pass triangles in clockwise order.
2638 config.meshParams[0].reversed = true;
2639 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2640 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
2641 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
2642 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw", "Dynamically set front face to counter-clockwise", config));
2645 TestConfig config(kOrdering);
2646 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2647 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
2648 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
2649 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2650 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw_reversed", "Dynamically set front face to clockwise with a counter-clockwise mesh", config));
2653 TestConfig config(kOrdering);
2654 // Pass triangles in clockwise order.
2655 config.meshParams[0].reversed = true;
2656 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
2657 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
2658 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
2659 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2660 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw_reversed", "Dynamically set front face to counter-clockwise with a clockwise mesh", config));
2663 // Rasterizer discard
2665 TestConfig config(kOrdering);
2666 config.rastDiscardEnableConfig.staticValue = false;
2667 config.rastDiscardEnableConfig.dynamicValue = tcu::just(true);
2668 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2669 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "disable_raster", "Dynamically disable rasterizer", config));
2672 TestConfig config(kOrdering);
2673 config.rastDiscardEnableConfig.staticValue = true;
2674 config.rastDiscardEnableConfig.dynamicValue = tcu::just(false);
2675 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "enable_raster", "Dynamically enable rasterizer", config));
2680 TestConfig config(kOrdering);
2681 config.logicOpConfig.staticValue = vk::VK_LOGIC_OP_CLEAR;
2682 config.logicOpConfig.dynamicValue = tcu::just<vk::VkLogicOp>(vk::VK_LOGIC_OP_OR);
2683 // Clear to green, paint in blue, expect cyan due to logic op.
2684 config.meshParams[0].color = kLogicOpTriangleColor;
2685 config.clearColorValue = vk::makeClearValueColorU32(kGreenClearColor.x(), kGreenClearColor.y(), kGreenClearColor.z(), kGreenClearColor.w());
2686 config.referenceColor = SingleColorGenerator(kLogicOpFinalColor);
2687 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "logic_op_or", "Dynamically change logic op to VK_LOGIC_OP_OR", config));
2690 // Dynamically enable primitive restart
2692 TestConfig config(kOrdering);
2693 config.primRestartEnableConfig.staticValue = false;
2694 config.primRestartEnableConfig.dynamicValue = tcu::just(true);
2695 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "prim_restart_enable", "Dynamically enable primitiveRestart", config));
2698 // Dynamically change the number of primitive control points
2700 TestConfig config(kOrdering);
2701 config.topologyConfig.staticValue = vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
2702 config.patchControlPointsConfig.staticValue = 1;
2703 config.patchControlPointsConfig.dynamicValue = 3;
2704 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "patch_control_points", "Dynamically change patch control points", config));
2707 // Dynamic topology.
2709 TestConfig baseConfig(kOrdering);
2711 for (int i = 0; i < 2; ++i)
2713 const bool forceGeometryShader = (i > 0);
2717 vk::VkPrimitiveTopology staticVal;
2718 vk::VkPrimitiveTopology dynamicVal;
2719 } kTopologyCases[] =
2721 { vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN },
2722 { vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP },
2723 { vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST },
2726 for (const auto& kTopologyCase : kTopologyCases)
2728 TestConfig config(baseConfig);
2729 config.forceGeometryShader = forceGeometryShader;
2730 config.topologyConfig.staticValue = kTopologyCase.staticVal;
2731 config.topologyConfig.dynamicValue = tcu::just<vk::VkPrimitiveTopology>(kTopologyCase.dynamicVal);
2732 config.patchControlPointsConfig.staticValue = (config.needsTessellation() ? 3u : 1u);
2734 const std::string className = topologyClassName(getTopologyClass(config.topologyConfig.staticValue));
2735 const std::string name = "topology_" + className + (forceGeometryShader ? "_geom" : "");
2736 const std::string desc = "Dynamically switch primitive topologies from the " + className + " class" + (forceGeometryShader ? " and use a geometry shader" : "");
2737 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, name, desc, config));
2744 TestConfig config(kOrdering);
2745 // 2 scissors, bad static single viewport.
2746 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
2747 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
2748 config.viewportConfig.dynamicValue = ViewportVec{
2749 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2750 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2752 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports", "Dynamically set 2 viewports", config));
2755 TestConfig config(kOrdering);
2756 // Bad static reduced viewport.
2757 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
2758 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight));
2759 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_viewport", "Dynamically set viewport to cover full framebuffer", config));
2762 TestConfig config(kOrdering);
2763 // 2 scissors (left half, right half), 2 reversed static viewports that need fixing (right, left).
2764 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
2765 config.viewportConfig.staticValue = ViewportVec{
2766 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
2767 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
2769 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
2770 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch", "Dynamically switch the order with 2 viewports", config));
2773 TestConfig config(kOrdering);
2774 // 2 scissors, reversed dynamic viewports that should result in no drawing taking place.
2775 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
2776 config.viewportConfig.staticValue = ViewportVec{
2777 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
2778 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
2780 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
2781 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2782 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch_clean", "Dynamically switch the order with 2 viewports resulting in clean image", config));
2787 TestConfig config(kOrdering);
2788 // 2 viewports, bad static single scissor.
2789 config.viewportConfig.staticValue = ViewportVec{
2790 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2791 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2793 config.scissorConfig.staticValue = ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
2794 config.scissorConfig.dynamicValue = ScissorVec{
2795 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
2796 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
2798 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors", "Dynamically set 2 scissors", config));
2801 TestConfig config(kOrdering);
2802 // 1 viewport, bad static single scissor.
2803 config.scissorConfig.staticValue = ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
2804 config.scissorConfig.dynamicValue = ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight));
2805 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_scissor", "Dynamically set scissor to cover full framebuffer", config));
2808 TestConfig config(kOrdering);
2809 // 2 viewports, 2 reversed scissors that need fixing.
2810 config.viewportConfig.staticValue = ViewportVec{
2811 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2812 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2814 config.scissorConfig.staticValue = ScissorVec{
2815 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
2816 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
2818 config.scissorConfig.dynamicValue = ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
2819 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch", "Dynamically switch the order with 2 scissors", config));
2822 TestConfig config(kOrdering);
2823 // 2 viewports, 2 scissors switched to prevent drawing.
2824 config.viewportConfig.staticValue = ViewportVec{
2825 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2826 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
2828 config.scissorConfig.staticValue = ScissorVec{
2829 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
2830 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
2832 config.scissorConfig.dynamicValue = ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
2833 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2834 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch_clean", "Dynamically switch the order with 2 scissors to avoid drawing", config));
2841 const VertexGenerator* factory;
2842 const std::string prefix;
2845 { getVertexWithPaddingGenerator(), "stride" },
2846 { getVertexWithExtraAttributesGenerator(), "large_stride" },
2849 for (const auto& strideCase : strideCases)
2851 const auto factory = strideCase.factory;
2852 const auto& prefix = strideCase.prefix;
2853 const auto vertexStrides = factory->getVertexDataStrides();
2854 StrideVec halfStrides;
2856 halfStrides.reserve(vertexStrides.size());
2857 for (const auto& stride : vertexStrides)
2858 halfStrides.push_back(stride / 2u);
2860 if (factory == getVertexWithExtraAttributesGenerator() && kOrdering == SequenceOrdering::TWO_DRAWS_STATIC)
2862 // This case is invalid because it breaks VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the dynamic
2863 // stride being less than the extent of the binding for the second attribute.
2868 TestConfig config(kOrdering, factory);
2869 config.strideConfig.staticValue = halfStrides;
2870 config.strideConfig.dynamicValue = vertexStrides;
2871 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix, "Dynamically set stride", config));
2874 TestConfig config(kOrdering, factory);
2875 config.strideConfig.staticValue = halfStrides;
2876 config.strideConfig.dynamicValue = vertexStrides;
2877 config.vertexDataOffset = vertexStrides[0];
2878 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset", "Dynamically set stride using a nonzero vertex data offset", config));
2881 TestConfig config(kOrdering, factory);
2882 config.strideConfig.staticValue = halfStrides;
2883 config.strideConfig.dynamicValue = vertexStrides;
2884 config.vertexDataOffset = vertexStrides[0];
2885 config.vertexDataExtraBytes = config.vertexDataOffset;
2887 // 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.
2888 config.referenceColor = HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor);
2889 config.meshParams[0].scaleY = 0.5f;
2890 config.meshParams[0].offsetY = -0.5f;
2892 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, prefix + "_with_offset_and_padding", "Dynamically set stride using a nonzero vertex data offset and extra bytes", config));
2896 // Dynamic stride of 0
2898 TestConfig config(kOrdering, getVertexWithExtraAttributesGenerator());
2899 config.strideConfig.staticValue = config.getActiveVertexGenerator()->getVertexDataStrides();
2900 config.strideConfig.dynamicValue = { 0 };
2901 config.vertexDataOffset = 4;
2902 config.singleVertex = true;
2903 config.singleVertexDrawCount = 6;
2905 // Make the mesh cover the top half only. If the implementation reads data outside the vertex data it should read the
2906 // offscreen vertex and draw something in the bottom half.
2907 config.referenceColor = HorizontalSplitGenerator(kDefaultTriangleColor, kDefaultClearColor);
2908 config.meshParams[0].scaleY = 0.5f;
2909 config.meshParams[0].offsetY = -0.5f;
2911 // Use fan scale to synthesize a fan from a vertex attribute which remains constant over the draw call.
2912 config.meshParams[0].fanScale = 1.0f;
2914 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "zero_stride_with_offset", "Dynamically set zero stride using a nonzero vertex data offset", config));
2918 // Depth test enable.
2920 TestConfig config(kOrdering);
2921 config.depthTestEnableConfig.staticValue = false;
2922 config.depthTestEnableConfig.dynamicValue = tcu::just(true);
2923 // By default, the depth test never passes when enabled.
2924 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
2925 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_enable", "Dynamically enable depth test", config));
2928 TestConfig config(kOrdering);
2929 config.depthTestEnableConfig.staticValue = true;
2930 config.depthTestEnableConfig.dynamicValue = tcu::just(false);
2931 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_disable", "Dynamically disable depth test", config));
2934 // Depth write enable.
2936 TestConfig config(kOrdering);
2938 // Enable depth test and set values so it passes.
2939 config.depthTestEnableConfig.staticValue = true;
2940 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
2941 config.clearDepthValue = 0.5f;
2942 config.meshParams[0].depth = 0.25f;
2944 // Enable writes and expect the mesh value.
2945 config.depthWriteEnableConfig.staticValue = false;
2946 config.depthWriteEnableConfig.dynamicValue = tcu::just(true);
2947 config.expectedDepth = 0.25f;
2949 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_enable", "Dynamically enable writes to the depth buffer", config));
2952 TestConfig config(kOrdering);
2954 // Enable depth test and set values so it passes.
2955 config.depthTestEnableConfig.staticValue = true;
2956 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
2957 config.clearDepthValue = 0.5f;
2958 config.meshParams[0].depth = 0.25f;
2960 // But disable writing dynamically and expect the clear value.
2961 config.depthWriteEnableConfig.staticValue = true;
2962 config.depthWriteEnableConfig.dynamicValue = tcu::just(false);
2963 config.expectedDepth = 0.5f;
2965 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_disable", "Dynamically disable writes to the depth buffer", config));
2968 // Depth bias enable with static or dynamic depth bias parameters.
2970 const DepthBiasParams kAlternativeDepthBiasParams = { 2e7f, 0.25f };
2972 for (int dynamicBiasIter = 0; dynamicBiasIter < 2; ++dynamicBiasIter)
2974 const bool useDynamicBias = (dynamicBiasIter > 0);
2977 TestConfig config(kOrdering);
2979 // Enable depth test and write 1.0f
2980 config.depthTestEnableConfig.staticValue = true;
2981 config.depthWriteEnableConfig.staticValue = true;
2982 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
2983 // Clear depth buffer to 0.25f
2984 config.clearDepthValue = 0.25f;
2985 // Write depth to 0.5f
2986 config.meshParams[0].depth = 0.5f;
2988 // Enable dynamic depth bias and expect the depth value to be clamped to 0.75f based on depthBiasConstantFactor and depthBiasClamp
2991 config.depthBiasConfig.staticValue = kNoDepthBiasParams;
2992 config.depthBiasConfig.dynamicValue = kAlternativeDepthBiasParams;
2996 config.depthBiasConfig.staticValue = kAlternativeDepthBiasParams;
2999 config.depthBiasEnableConfig.staticValue = false;
3000 config.depthBiasEnableConfig.dynamicValue = tcu::just(true);
3001 config.expectedDepth = 0.75f;
3003 std::string caseName = "depth_bias_enable";
3004 std::string caseDesc = "Dynamically enable the depth bias";
3008 caseName += "_dynamic_bias_params";
3009 caseDesc += " and set the bias params dynamically";
3012 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, caseDesc, config));
3015 TestConfig config(kOrdering);
3017 // Enable depth test and write 1.0f
3018 config.depthTestEnableConfig.staticValue = true;
3019 config.depthWriteEnableConfig.staticValue = true;
3020 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
3021 // Clear depth buffer to 0.25f
3022 config.clearDepthValue = 0.25f;
3023 // Write depth to 0.5f
3024 config.meshParams[0].depth = 0.5f;
3026 // Disable dynamic depth bias and expect the depth value to remain at 0.5f based on written value
3029 config.depthBiasConfig.staticValue = kNoDepthBiasParams;
3030 config.depthBiasConfig.dynamicValue = kAlternativeDepthBiasParams;
3034 config.depthBiasConfig.staticValue = kAlternativeDepthBiasParams;
3037 config.depthBiasEnableConfig.staticValue = true;
3038 config.depthBiasEnableConfig.dynamicValue = tcu::just(false);
3039 config.expectedDepth = 0.5f;
3041 std::string caseName = "depth_bias_disable";
3042 std::string caseDesc = "Dynamically disable the depth bias";
3046 caseName += "_dynamic_bias_params";
3047 caseDesc += " and set the bias params dynamically";
3050 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, caseName, caseDesc, config));
3055 // Depth compare op.
3057 TestConfig baseConfig(kOrdering);
3058 const tcu::Vec4 kAlternativeColor (0.0f, 0.0f, 0.5f, 1.0f);
3059 baseConfig.depthTestEnableConfig.staticValue = true;
3060 baseConfig.depthWriteEnableConfig.staticValue = true;
3061 baseConfig.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_NEVER;
3062 baseConfig.clearDepthValue = 0.5f;
3065 TestConfig config = baseConfig;
3066 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
3067 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NEVER;
3068 config.meshParams[0].depth = 0.25f;
3069 config.expectedDepth = 0.5f;
3070 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
3071 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_never", "Dynamically set the depth compare operator to NEVER", config));
3074 TestConfig config = baseConfig;
3075 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS;
3076 config.meshParams[0].depth = 0.25f;
3077 config.expectedDepth = 0.25f;
3078 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less", "Dynamically set the depth compare operator to LESS", config));
3081 TestConfig config = baseConfig;
3082 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER;
3083 config.meshParams[0].depth = 0.75f;
3084 config.expectedDepth = 0.75f;
3085 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater", "Dynamically set the depth compare operator to GREATER", config));
3088 TestConfig config = baseConfig;
3089 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_EQUAL;
3090 config.meshParams[0].depth = 0.5f;
3091 config.meshParams[0].color = kAlternativeColor;
3092 // Draw another mesh in front to verify it does not pass the equality test.
3093 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.25f));
3094 config.expectedDepth = 0.5f;
3095 config.referenceColor = SingleColorGenerator(kAlternativeColor);
3096 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_equal", "Dynamically set the depth compare operator to EQUAL", config));
3099 TestConfig config = baseConfig;
3100 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
3101 config.meshParams[0].depth = 0.25f;
3102 config.expectedDepth = 0.25f;
3103 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));
3106 TestConfig config = baseConfig;
3107 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
3108 config.meshParams[0].depth = 0.5f;
3109 config.expectedDepth = 0.5f;
3110 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));
3113 TestConfig config = baseConfig;
3114 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
3115 config.meshParams[0].depth = 0.25f;
3116 // Draw another mesh with the same depth in front of it.
3117 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.25f));
3118 config.expectedDepth = 0.25f;
3119 config.referenceColor = SingleColorGenerator(kAlternativeColor);
3120 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));
3123 TestConfig config = baseConfig;
3124 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
3125 config.meshParams[0].depth = 0.75f;
3126 config.expectedDepth = 0.75f;
3127 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));
3130 TestConfig config = baseConfig;
3131 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
3132 config.meshParams[0].depth = 0.5f;
3133 config.expectedDepth = 0.5f;
3134 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));
3137 TestConfig config = baseConfig;
3138 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
3139 config.meshParams[0].depth = 0.75f;
3140 // Draw another mesh with the same depth in front of it.
3141 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.75f));
3142 config.expectedDepth = 0.75f;
3143 config.referenceColor = SingleColorGenerator(kAlternativeColor);
3144 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));
3147 TestConfig config = baseConfig;
3148 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NOT_EQUAL;
3150 // Draw first mesh in front.
3151 config.meshParams[0].depth = 0.25f;
3152 // Draw another mesh in the back, this should pass too.
3153 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.5f));
3154 // Finally a new mesh with the same depth. This should not pass.
3155 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.5f));
3157 config.referenceColor = SingleColorGenerator(kAlternativeColor);
3158 config.expectedDepth = 0.5f;
3159 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_not_equal", "Dynamically set the depth compare operator to NOT_EQUAL", config));
3162 TestConfig config = baseConfig;
3163 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_ALWAYS;
3165 config.meshParams[0].depth = 0.5f;
3166 config.expectedDepth = 0.5f;
3167 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_equal", "Dynamically set the depth compare operator to ALWAYS and draw with equal depth", config));
3169 config.meshParams[0].depth = 0.25f;
3170 config.expectedDepth = 0.25f;
3171 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_less", "Dynamically set the depth compare operator to ALWAYS and draw with less depth", config));
3173 config.meshParams[0].depth = 0.75f;
3174 config.expectedDepth = 0.75f;
3175 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_greater", "Dynamically set the depth compare operator to ALWAYS and draw with greater depth", config));
3179 // Depth bounds test.
3181 TestConfig baseConfig(kOrdering);
3182 baseConfig.minDepthBounds = 0.25f;
3183 baseConfig.maxDepthBounds = 0.75f;
3184 baseConfig.meshParams[0].depth = 0.0f;
3187 TestConfig config = baseConfig;
3188 config.depthBoundsTestEnableConfig.staticValue = false;
3189 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(true);
3190 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
3191 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_enable", "Dynamically enable the depth bounds test", config));
3194 TestConfig config = baseConfig;
3195 config.depthBoundsTestEnableConfig.staticValue = true;
3196 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(false);
3197 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_disable", "Dynamically disable the depth bounds test", config));
3201 // Stencil test enable.
3203 TestConfig config(kOrdering);
3204 config.stencilTestEnableConfig.staticValue = false;
3205 config.stencilTestEnableConfig.dynamicValue = tcu::just(true);
3206 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
3207 config.referenceColor = SingleColorGenerator(kDefaultClearColor);
3208 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_enable", "Dynamically enable the stencil test", config));
3211 TestConfig config(kOrdering);
3212 config.stencilTestEnableConfig.staticValue = true;
3213 config.stencilTestEnableConfig.dynamicValue = tcu::just(false);
3214 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
3215 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_disable", "Dynamically disable the stencil test", config));
3218 // Stencil operation. Many combinations are possible.
3222 vk::VkStencilFaceFlags face;
3226 { vk::VK_STENCIL_FACE_FRONT_BIT, "face_front" },
3227 { vk::VK_STENCIL_FACE_BACK_BIT, "face_back" },
3228 { vk::VK_STENCIL_FRONT_AND_BACK, "face_both_single" },
3229 { vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM, "face_both_dual" }, // MAX_ENUM is a placeholder.
3234 vk::VkCompareOp compareOp;
3238 { vk::VK_COMPARE_OP_NEVER, "xf" },
3239 { vk::VK_COMPARE_OP_LESS, "lt" },
3240 { vk::VK_COMPARE_OP_EQUAL, "eq" },
3241 { vk::VK_COMPARE_OP_LESS_OR_EQUAL, "le" },
3242 { vk::VK_COMPARE_OP_GREATER, "gt" },
3243 { vk::VK_COMPARE_OP_GREATER_OR_EQUAL, "ge" },
3244 { vk::VK_COMPARE_OP_ALWAYS, "xt" },
3247 using u8vec = std::vector<deUint8>;
3249 static const auto kMinVal = std::numeric_limits<deUint8>::min();
3250 static const auto kMaxVal = std::numeric_limits<deUint8>::max();
3251 static const auto kMidVal = static_cast<deUint8>(kMaxVal * 2u / 5u);
3252 static const auto kMinValI = static_cast<int>(kMinVal);
3253 static const auto kMaxValI = static_cast<int>(kMaxVal);
3257 vk::VkStencilOp stencilOp;
3259 u8vec clearValues; // One test per clear value interesting for this operation.
3260 vk::VkStencilOp incompatibleOp; // Alternative operation giving incompatible results for the given values.
3263 { vk::VK_STENCIL_OP_KEEP, "keep", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
3264 { vk::VK_STENCIL_OP_ZERO, "zero", u8vec{kMidVal}, vk::VK_STENCIL_OP_KEEP },
3265 { vk::VK_STENCIL_OP_REPLACE, "replace", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
3266 { vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP, "inc_clamp", u8vec{kMaxVal - 1, kMaxVal}, vk::VK_STENCIL_OP_ZERO },
3267 { vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP, "dec_clamp", u8vec{kMinVal + 1, kMinVal}, vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP },
3268 { vk::VK_STENCIL_OP_INVERT, "invert", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
3269 { vk::VK_STENCIL_OP_INCREMENT_AND_WRAP, "inc_wrap", u8vec{kMaxVal - 1, kMaxVal}, vk::VK_STENCIL_OP_KEEP },
3270 { vk::VK_STENCIL_OP_DECREMENT_AND_WRAP, "dec_wrap", u8vec{kMinVal + 1, kMinVal}, vk::VK_STENCIL_OP_KEEP },
3273 for (const auto& face : kFaces)
3274 for (const auto& compare : kCompare)
3275 for (const auto& op : kStencilOps)
3277 // Try clearing the stencil value with different values.
3278 for (const auto clearVal : op.clearValues)
3280 // Use interesting values as the reference stencil value.
3281 for (int delta = -1; delta <= 1; ++delta)
3283 const int refVal = clearVal + delta;
3284 if (refVal < kMinValI || refVal > kMaxValI)
3287 const auto refValU8 = static_cast<deUint8>(refVal);
3288 const auto refValU32 = static_cast<deUint32>(refVal);
3290 // Calculate outcome of the stencil test itself.
3291 const bool wouldPass = stencilPasses(compare.compareOp, clearVal, refValU8);
3293 // If the test passes, use an additional variant for the depthFail operation.
3294 const int subCases = (wouldPass ? 2 : 1);
3296 for (int subCaseIdx = 0; subCaseIdx < subCases; ++subCaseIdx)
3298 const bool depthFail = (subCaseIdx > 0); // depthFail would be the second variant.
3299 const bool globalPass = (wouldPass && !depthFail); // Global result of the stencil+depth test.
3301 // Start tuning test parameters.
3302 TestConfig config(kOrdering);
3304 // No face culling is applied by default, so both the front and back operations could apply depending on the mesh.
3305 if (face.face == vk::VK_STENCIL_FACE_FRONT_BIT)
3307 // Default parameters are OK.
3309 else if (face.face == vk::VK_STENCIL_FACE_BACK_BIT)
3311 // Reverse the mesh so it applies the back operation.
3312 config.meshParams[0].reversed = true;
3314 else // Front and back.
3316 // Draw both a front and a back-facing mesh so both are applied.
3317 // The first mesh will be drawn in the top half and the second mesh in the bottom half.
3319 // Make the second mesh a reversed copy of the first mesh.
3320 config.meshParams.push_back(config.meshParams.front());
3321 config.meshParams.back().reversed = true;
3323 // Apply scale and offset to the top mesh.
3324 config.meshParams.front().scaleY = 0.5f;
3325 config.meshParams.front().offsetY = -0.5f;
3327 // Apply scale and offset to the bottom mesh.
3328 config.meshParams.back().scaleY = 0.5f;
3329 config.meshParams.back().offsetY = 0.5f;
3332 // Enable the stencil test.
3333 config.stencilTestEnableConfig.staticValue = true;
3335 // Set dynamic configuration.
3336 StencilOpParams dynamicStencilConfig;
3337 dynamicStencilConfig.faceMask = face.face;
3338 dynamicStencilConfig.compareOp = compare.compareOp;
3339 dynamicStencilConfig.failOp = vk::VK_STENCIL_OP_MAX_ENUM;
3340 dynamicStencilConfig.passOp = vk::VK_STENCIL_OP_MAX_ENUM;
3341 dynamicStencilConfig.depthFailOp = vk::VK_STENCIL_OP_MAX_ENUM;
3343 // Set operations so only the appropriate operation for this case gives the right result.
3344 vk::VkStencilOp* activeOp = nullptr;
3345 vk::VkStencilOp* inactiveOps[2] = { nullptr, nullptr };
3350 activeOp = &dynamicStencilConfig.depthFailOp;
3351 inactiveOps[0] = &dynamicStencilConfig.passOp;
3352 inactiveOps[1] = &dynamicStencilConfig.failOp;
3356 activeOp = &dynamicStencilConfig.passOp;
3357 inactiveOps[0] = &dynamicStencilConfig.depthFailOp;
3358 inactiveOps[1] = &dynamicStencilConfig.failOp;
3363 activeOp = &dynamicStencilConfig.failOp;
3364 inactiveOps[0] = &dynamicStencilConfig.passOp;
3365 inactiveOps[1] = &dynamicStencilConfig.depthFailOp;
3368 *activeOp = op.stencilOp;
3369 *inactiveOps[0] = op.incompatibleOp;
3370 *inactiveOps[1] = op.incompatibleOp;
3372 // Make sure all ops have been configured properly.
3373 DE_ASSERT(dynamicStencilConfig.failOp != vk::VK_STENCIL_OP_MAX_ENUM);
3374 DE_ASSERT(dynamicStencilConfig.passOp != vk::VK_STENCIL_OP_MAX_ENUM);
3375 DE_ASSERT(dynamicStencilConfig.depthFailOp != vk::VK_STENCIL_OP_MAX_ENUM);
3377 // Set an incompatible static operation too.
3378 auto& staticStencilConfig = config.stencilOpConfig.staticValue.front();
3379 staticStencilConfig.faceMask = face.face;
3380 staticStencilConfig.compareOp = (globalPass ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
3381 staticStencilConfig.passOp = op.incompatibleOp;
3382 staticStencilConfig.failOp = op.incompatibleOp;
3383 staticStencilConfig.depthFailOp = op.incompatibleOp;
3385 // Set dynamic configuration.
3386 StencilOpVec stencilOps;
3387 stencilOps.push_back(dynamicStencilConfig);
3389 if (stencilOps.front().faceMask == vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM)
3391 // This is the dual case. We will set the front and back face values with two separate calls.
3392 stencilOps.push_back(stencilOps.front());
3393 stencilOps.front().faceMask = vk::VK_STENCIL_FACE_FRONT_BIT;
3394 stencilOps.back().faceMask = vk::VK_STENCIL_FACE_BACK_BIT;
3395 staticStencilConfig.faceMask = vk::VK_STENCIL_FACE_FRONT_AND_BACK;
3398 config.stencilOpConfig.dynamicValue = tcu::just(stencilOps);
3399 config.clearStencilValue = clearVal;
3400 config.referenceStencil = refValU32;
3404 // Enable depth test and make it fail.
3405 config.depthTestEnableConfig.staticValue = true;
3406 config.clearDepthValue = 0.5f;
3407 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
3409 for (auto& meshPar : config.meshParams)
3410 meshPar.depth = 0.75f;
3413 // Set expected outcome.
3414 config.referenceColor = SingleColorGenerator(globalPass ? kDefaultTriangleColor : kDefaultClearColor);
3415 config.expectedDepth = config.clearDepthValue; // No depth writing by default.
3416 config.expectedStencil = stencilResult(op.stencilOp, clearVal, refValU8, kMinVal, kMaxVal);
3418 const std::string testName = std::string("stencil_state")
3420 + "_" + compare.name
3422 + "_clear_" + de::toString(static_cast<int>(clearVal))
3423 + "_ref_" + de::toString(refVal)
3424 + "_" + (wouldPass ? (depthFail ? "depthfail" : "pass") : "fail");
3426 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, "Dynamically configure stencil test, variant " + testName, config));
3435 // TWO_DRAWS_STATIC would be invalid because it violates VUID-vkCmdBindVertexBuffers2EXT-pStrides-03363 due to the
3436 // dynamic stride being less than the extent of the binding for the second attribute.
3437 if (kOrdering != SequenceOrdering::TWO_DRAWS_STATIC)
3439 const auto staticGen = getVertexWithPaddingGenerator();
3440 const auto dynamicGen = getVertexWithExtraAttributesGenerator();
3441 const auto goodStrides = dynamicGen->getVertexDataStrides();
3442 StrideVec badStrides;
3444 badStrides.reserve(goodStrides.size());
3445 for (const auto& stride : goodStrides)
3446 badStrides.push_back(stride / 2u);
3448 TestConfig config(kOrdering, staticGen, dynamicGen);
3449 config.strideConfig.staticValue = badStrides;
3450 config.strideConfig.dynamicValue = goodStrides;
3451 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input", "Dynamically set vertex input", config));
3455 // Variant without mixing in the stride config.
3456 TestConfig config(kOrdering, getVertexWithPaddingGenerator(), getVertexWithExtraAttributesGenerator());
3457 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_no_dyn_stride", "Dynamically set vertex input without using dynamic strides", config));
3461 // Variant using multiple bindings.
3462 TestConfig config(kOrdering, getVertexWithExtraAttributesGenerator(), getVertexWithMultipleBindingsGenerator());
3463 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "vertex_input_multiple_bindings", "Dynamically set vertex input with multiple bindings", config));
3467 extendedDynamicStateGroup->addChild(orderingGroup.release());
3470 return extendedDynamicStateGroup.release();